/*  Prototype JavaScript framework, version 1.6.1_rc2
 *  (c) 2005-2009 Sam Stephenson
 *
 *  Prototype is freely distributable under the terms of an MIT-style license.
 *  For details, see the Prototype web site: http://www.prototypejs.org/
 *
 *--------------------------------------------------------------------------*/

var Prototype = {
  Version: '1.6.1_rc2',
  Browser: {
    IE:     !!(window.attachEvent &&
    navigator.userAgent.indexOf('Opera') === -1),
    Opera:  navigator.userAgent.indexOf('Opera') > -1,
    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 &&
    navigator.userAgent.indexOf('KHTML') === -1,
    MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
  },
  BrowserFeatures: {
    XPath: !!document.evaluate,
    SelectorsAPI: !!document.querySelector,
    ElementExtensions: (function() {
      if (window.HTMLElement && window.HTMLElement.prototype)
        return true;
      if (window.Element && window.Element.prototype)
        return true;
    })(),
    SpecificElementExtensions: (function() {
      if (typeof window.HTMLDivElement !== 'undefined')
        return true;

      var div = document.createElement('div');
      if (div['__proto__'] && div['__proto__'] !==
       document.createElement('form')['__proto__']) {
        return true;
      }

      return false;
    })()
  },

  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
  JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,

  emptyFunction: function() { },
  K: function(x) { return x }
};

if (Prototype.Browser.MobileSafari)
  Prototype.BrowserFeatures.SpecificElementExtensions = false;


var Abstract = { };


var Try = {
  these: function() {
    var returnValue;

    for (var i = 0, length = arguments.length; i < length; i++) {
      var lambda = arguments[i];
      try {
        returnValue = lambda();
        break;
      } catch (e) { }
    }

    return returnValue;
  }
};

/* Based on Alex Arnell's inheritance implementation. */

var Class = (function() {
  function create() {
    var parent = null, properties = $A(arguments);
    if (Object.isFunction(properties[0]))
      parent = properties.shift();

    function klass() {
      this.initialize.apply(this, arguments);
    }

    Object.extend(klass, Class.Methods);
    klass.superclass = parent;
    klass.subclasses = [];

    if (parent) {
      var subclass = function() {};
      subclass.prototype = parent.prototype;
      klass.prototype = new subclass;
      parent.subclasses.push(klass);
    }

    for (var i = 0; i < properties.length; i++)
      klass.addMethods(properties[i]);

    if (!klass.prototype.initialize)
      klass.prototype.initialize = Prototype.emptyFunction;

    klass.prototype.constructor = klass;
    return klass;
  }

  function addMethods(source) {
    var ancestor   = this.superclass && this.superclass.prototype;
    var properties = Object.keys(source);

    if (!Object.keys({ toString: true }).length) {
      if (source.toString != Object.prototype.toString)
        properties.push("toString");
      if (source.valueOf != Object.prototype.valueOf)
        properties.push("valueOf");
    }

    for (var i = 0, length = properties.length; i < length; i++) {
      var property = properties[i], value = source[property];
      if (ancestor && Object.isFunction(value) &&
          value.argumentNames().first() == "$super") {
        var method = value;
        value = (function(m) {
          return function() { return ancestor[m].apply(this, arguments); };
        })(property).wrap(method);

        value.valueOf = method.valueOf.bind(method);
        value.toString = method.toString.bind(method);
      }
      this.prototype[property] = value;
    }

    return this;
  }

  return {
    create: create,
    Methods: {
      addMethods: addMethods
    }
  };
})();
(function() {

  function getClass(object) {
    return Object.prototype.toString.call(object)
     .match(/^\[object\s(.*)\]$/)[1];
  }

  function extend(destination, source) {
    for (var property in source)
      destination[property] = source[property];
    return destination;
  }

  function inspect(object) {
    try {
      if (isUndefined(object)) return 'undefined';
      if (object === null) return 'null';
      return object.inspect ? object.inspect() : String(object);
    } catch (e) {
      if (e instanceof RangeError) return '...';
      throw e;
    }
  }

  function toJSON(object) {
    var type = typeof object;
    switch (type) {
      case 'undefined':
      case 'function':
      case 'unknown': return;
      case 'boolean': return object.toString();
    }

    if (object === null) return 'null';
    if (object.toJSON) return object.toJSON();
    if (isElement(object)) return;

    var results = [];
    for (var property in object) {
      var value = toJSON(object[property]);
      if (!isUndefined(value))
        results.push(property.toJSON() + ': ' + value);
    }

    return '{' + results.join(', ') + '}';
  }

  function toQueryString(object) {
    return $H(object).toQueryString();
  }

  function toHTML(object) {
    return object && object.toHTML ? object.toHTML() : String.interpret(object);
  }

  function keys(object) {
    var results = [];
    for (var property in object)
      results.push(property);
    return results;
  }

  function values(object) {
    var results = [];
    for (var property in object)
      results.push(object[property]);
    return results;
  }

  function clone(object) {
    return extend({ }, object);
  }

  function isElement(object) {
    return !!(object && object.nodeType == 1);
  }

  function isArray(object) {
    return getClass(object) === "Array";
  }


  function isHash(object) {
    return object instanceof Hash;
  }

  function isFunction(object) {
    return typeof object === "function";
  }

  function isString(object) {
    return getClass(object) === "String";
  }

  function isNumber(object) {
    return getClass(object) === "Number";
  }

  function isUndefined(object) {
    return typeof object === "undefined";
  }

  extend(Object, {
    extend:        extend,
    inspect:       inspect,
    toJSON:        toJSON,
    toQueryString: toQueryString,
    toHTML:        toHTML,
    keys:          keys,
    values:        values,
    clone:         clone,
    isElement:     isElement,
    isArray:       isArray,
    isHash:        isHash,
    isFunction:    isFunction,
    isString:      isString,
    isNumber:      isNumber,
    isUndefined:   isUndefined
  });
})();
Object.extend(Function.prototype, (function() {
  var slice = Array.prototype.slice;

  function update(array, args) {
    var arrayLength = array.length, length = args.length;
    while (length--) array[arrayLength + length] = args[length];
    return array;
  }

  function merge(array, args) {
    array = slice.call(array, 0);
    return update(array, args);
  }

  function argumentNames() {
    var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
      .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
      .replace(/\s+/g, '').split(',');
    return names.length == 1 && !names[0] ? [] : names;
  }

  function bind(context) {
    if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
    var __method = this, args = slice.call(arguments, 1);
    return function() {
      var a = merge(args, arguments);
      return __method.apply(context, a);
    }
  }

  function bindAsEventListener(context) {
    var __method = this, args = slice.call(arguments, 1);
    return function(event) {
      var a = update([event || window.event], args);
      return __method.apply(context, a);
    }
  }

  function curry() {
    if (!arguments.length) return this;
    var __method = this, args = slice.call(arguments, 0);
    return function() {
      var a = merge(args, arguments);
      return __method.apply(this, a);
    }
  }

  function delay(timeout) {
    var __method = this, args = slice.call(arguments, 1);
    timeout = timeout * 1000
    return window.setTimeout(function() {
      return __method.apply(__method, args);
    }, timeout);
  }

  function defer() {
    var args = update([0.01], arguments);
    return this.delay.apply(this, args);
  }

  function wrap(wrapper) {
    var __method = this;
    return function() {
      var a = update([__method.bind(this)], arguments);
      return wrapper.apply(this, a);
    }
  }

  function methodize() {
    if (this._methodized) return this._methodized;
    var __method = this;
    return this._methodized = function() {
      var a = update([this], arguments);
      return __method.apply(null, a);
    };
  }

  return {
    argumentNames:       argumentNames,
    bind:                bind,
    bindAsEventListener: bindAsEventListener,
    curry:               curry,
    delay:               delay,
    defer:               defer,
    wrap:                wrap,
    methodize:           methodize
  }
})());


Date.prototype.toJSON = function() {
  return '"' + this.getUTCFullYear() + '-' +
    (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
    this.getUTCDate().toPaddedString(2) + 'T' +
    this.getUTCHours().toPaddedString(2) + ':' +
    this.getUTCMinutes().toPaddedString(2) + ':' +
    this.getUTCSeconds().toPaddedString(2) + 'Z"';
};


RegExp.prototype.match = RegExp.prototype.test;

RegExp.escape = function(str) {
  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};
var PeriodicalExecuter = Class.create({
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;

    this.registerCallback();
  },

  registerCallback: function() {
    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  execute: function() {
    this.callback(this);
  },

  stop: function() {
    if (!this.timer) return;
    clearInterval(this.timer);
    this.timer = null;
  },

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
        this.execute();
      } catch(e) {
        /* empty catch for clients that don't support try/finally */
      }
      finally {
        this.currentlyExecuting = false;
      }
    }
  }
});
Object.extend(String, {
  interpret: function(value) {
    return value == null ? '' : String(value);
  },
  specialChar: {
    '\b': '\\b',
    '\t': '\\t',
    '\n': '\\n',
    '\f': '\\f',
    '\r': '\\r',
    '\\': '\\\\'
  }
});

Object.extend(String.prototype, (function() {

  function prepareReplacement(replacement) {
    if (Object.isFunction(replacement)) return replacement;
    var template = new Template(replacement);
    return function(match) { return template.evaluate(match) };
  }

  function gsub(pattern, replacement) {
    var result = '', source = this, match;
    replacement = prepareReplacement(replacement);

    if (Object.isString(pattern))
      pattern = RegExp.escape(pattern);

    if (!(pattern.length || pattern.source)) {
      replacement = replacement('');
      return replacement + source.split('').join(replacement) + replacement;
    }

    while (source.length > 0) {
      if (match = source.match(pattern)) {
        result += source.slice(0, match.index);
        result += String.interpret(replacement(match));
        source  = source.slice(match.index + match[0].length);
      } else {
        result += source, source = '';
      }
    }
    return result;
  }

  function sub(pattern, replacement, count) {
    replacement = prepareReplacement(replacement);
    count = Object.isUndefined(count) ? 1 : count;

    return this.gsub(pattern, function(match) {
      if (--count < 0) return match[0];
      return replacement(match);
    });
  }

  function scan(pattern, iterator) {
    this.gsub(pattern, iterator);
    return String(this);
  }

  function truncate(length, truncation) {
    length = length || 30;
    truncation = Object.isUndefined(truncation) ? '...' : truncation;
    return this.length > length ?
      this.slice(0, length - truncation.length) + truncation : String(this);
  }

  function strip() {
    return this.replace(/^\s+/, '').replace(/\s+$/, '');
  }

  function stripTags() {
    return this.replace(/<\/?[^>]+>/gi, '');
  }

  function stripScripts() {
    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
  }

  function extractScripts() {
    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
    return (this.match(matchAll) || []).map(function(scriptTag) {
      return (scriptTag.match(matchOne) || ['', ''])[1];
    });
  }

  function evalScripts() {
    return this.extractScripts().map(function(script) { return eval(script) });
  }

  function escapeHTML() {
    escapeHTML.text.data = this;
    return escapeHTML.div.innerHTML;
  }

  function unescapeHTML() {
    var div = document.createElement('div');
    div.innerHTML = this.stripTags();
    return div.childNodes[0] ? (div.childNodes.length > 1 ?
      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
      div.childNodes[0].nodeValue) : '';
  }

  function toQueryParams(separator) {
    var match = this.strip().match(/([^?#]*)(#.*)?$/);
    if (!match) return { };

    return match[1].split(separator || '&').inject({ }, function(hash, pair) {
      if ((pair = pair.split('='))[0]) {
        var key = decodeURIComponent(pair.shift());
        var value = pair.length > 1 ? pair.join('=') : pair[0];
        if (value != undefined) value = decodeURIComponent(value);

        if (key in hash) {
          if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
          hash[key].push(value);
        }
        else hash[key] = value;
      }
      return hash;
    });
  }

  function toArray() {
    return this.split('');
  }

  function succ() {
    return this.slice(0, this.length - 1) +
      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
  }

  function times(count) {
    return count < 1 ? '' : new Array(count + 1).join(this);
  }

  function camelize() {
    var parts = this.split('-'), len = parts.length;
    if (len == 1) return parts[0];

    var camelized = this.charAt(0) == '-'
      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
      : parts[0];

    for (var i = 1; i < len; i++)
      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);

    return camelized;
  }

  function capitalize() {
    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
  }

  function underscore() {
    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
  }

  function dasherize() {
    return this.gsub(/_/,'-');
  }

  function inspect(useDoubleQuotes) {
    var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
      var character = String.specialChar[match[0]];
      return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
    });
    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
  }

  function toJSON() {
    return this.inspect(true);
  }

  function unfilterJSON(filter) {
    return this.sub(filter || Prototype.JSONFilter, '#{1}');
  }

  function isJSON() {
    var str = this;
    if (str.blank()) return false;
    str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
    return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
  }

  function evalJSON(sanitize) {
    var json = this.unfilterJSON();
    try {
      if (!sanitize || json.isJSON()) return eval('(' + json + ')');
    } catch (e) { }
    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
  }

  function include(pattern) {
    return this.indexOf(pattern) > -1;
  }

  function startsWith(pattern) {
    return this.indexOf(pattern) === 0;
  }

  function endsWith(pattern) {
    var d = this.length - pattern.length;
    return d >= 0 && this.lastIndexOf(pattern) === d;
  }

  function empty() {
    return this == '';
  }

  function blank() {
    return /^\s*$/.test(this);
  }

  function interpolate(object, pattern) {
    return new Template(this, pattern).evaluate(object);
  }

  return {
    gsub:           gsub,
    sub:            sub,
    scan:           scan,
    truncate:       truncate,
    strip:          strip,
    stripTags:      stripTags,
    stripScripts:   stripScripts,
    extractScripts: extractScripts,
    evalScripts:    evalScripts,
    escapeHTML:     escapeHTML,
    unescapeHTML:   unescapeHTML,
    toQueryParams:  toQueryParams,
    parseQuery:     toQueryParams,
    toArray:        toArray,
    succ:           succ,
    times:          times,
    camelize:       camelize,
    capitalize:     capitalize,
    underscore:     underscore,
    dasherize:      dasherize,
    inspect:        inspect,
    toJSON:         toJSON,
    unfilterJSON:   unfilterJSON,
    isJSON:         isJSON,
    evalJSON:       evalJSON,
    include:        include,
    startsWith:     startsWith,
    endsWith:       endsWith,
    empty:          empty,
    blank:          blank,
    interpolate:    interpolate
  };
})());

Object.extend(String.prototype.escapeHTML, {
  div:  document.createElement('div'),
  text: document.createTextNode('')
});

String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text);

if ('<\n>'.escapeHTML() !== '&lt;\n&gt;') {
  String.prototype.escapeHTML = function() {
    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
  }
}

if ('&lt;\n&gt;'.unescapeHTML() !== '<\n>') {
  String.prototype.unescapeHTML = function() {
    return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
  }
}
var Template = Class.create({
  initialize: function(template, pattern) {
    this.template = template.toString();
    this.pattern = pattern || Template.Pattern;
  },

  evaluate: function(object) {
    if (Object.isFunction(object.toTemplateReplacements))
      object = object.toTemplateReplacements();

    return this.template.gsub(this.pattern, function(match) {
      if (object == null) return '';

      var before = match[1] || '';
      if (before == '\\') return match[2];

      var ctx = object, expr = match[3];
      var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
      match = pattern.exec(expr);
      if (match == null) return before;

      while (match != null) {
        var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
        ctx = ctx[comp];
        if (null == ctx || '' == match[3]) break;
        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
        match = pattern.exec(expr);
      }

      return before + String.interpret(ctx);
    });
  }
});
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;

var $break = { };

var Enumerable = (function() {
  function each(iterator, context) {
    var index = 0;
    try {
      this._each(function(value) {
        iterator.call(context, value, index++);
      });
    } catch (e) {
      if (e != $break) throw e;
    }
    return this;
  }

  function eachSlice(number, iterator, context) {
    var index = -number, slices = [], array = this.toArray();
    if (number < 1) return array;
    while ((index += number) < array.length)
      slices.push(array.slice(index, index+number));
    return slices.collect(iterator, context);
  }

  function all(iterator, context) {
    iterator = iterator || Prototype.K;
    var result = true;
    this.each(function(value, index) {
      result = result && !!iterator.call(context, value, index);
      if (!result) throw $break;
    });
    return result;
  }

  function any(iterator, context) {
    iterator = iterator || Prototype.K;
    var result = false;
    this.each(function(value, index) {
      if (result = !!iterator.call(context, value, index))
        throw $break;
    });
    return result;
  }

  function collect(iterator, context) {
    iterator = iterator || Prototype.K;
    var results = [];
    this.each(function(value, index) {
      results.push(iterator.call(context, value, index));
    });
    return results;
  }

  function detect(iterator, context) {
    var result;
    this.each(function(value, index) {
      if (iterator.call(context, value, index)) {
        result = value;
        throw $break;
      }
    });
    return result;
  }

  function findAll(iterator, context) {
    var results = [];
    this.each(function(value, index) {
      if (iterator.call(context, value, index))
        results.push(value);
    });
    return results;
  }

  function grep(filter, iterator, context) {
    iterator = iterator || Prototype.K;
    var results = [];

    if (Object.isString(filter))
      filter = new RegExp(RegExp.escape(filter));

    this.each(function(value, index) {
      if (filter.match(value))
        results.push(iterator.call(context, value, index));
    });
    return results;
  }

  function include(object) {
    if (Object.isFunction(this.indexOf))
      if (this.indexOf(object) != -1) return true;

    var found = false;
    this.each(function(value) {
      if (value == object) {
        found = true;
        throw $break;
      }
    });
    return found;
  }

  function inGroupsOf(number, fillWith) {
    fillWith = Object.isUndefined(fillWith) ? null : fillWith;
    return this.eachSlice(number, function(slice) {
      while(slice.length < number) slice.push(fillWith);
      return slice;
    });
  }

  function inject(memo, iterator, context) {
    this.each(function(value, index) {
      memo = iterator.call(context, memo, value, index);
    });
    return memo;
  }

  function invoke(method) {
    var args = $A(arguments).slice(1);
    return this.map(function(value) {
      return value[method].apply(value, args);
    });
  }

  function max(iterator, context) {
    iterator = iterator || Prototype.K;
    var result;
    this.each(function(value, index) {
      value = iterator.call(context, value, index);
      if (result == null || value >= result)
        result = value;
    });
    return result;
  }

  function min(iterator, context) {
    iterator = iterator || Prototype.K;
    var result;
    this.each(function(value, index) {
      value = iterator.call(context, value, index);
      if (result == null || value < result)
        result = value;
    });
    return result;
  }

  function partition(iterator, context) {
    iterator = iterator || Prototype.K;
    var trues = [], falses = [];
    this.each(function(value, index) {
      (iterator.call(context, value, index) ?
        trues : falses).push(value);
    });
    return [trues, falses];
  }

  function pluck(property) {
    var results = [];
    this.each(function(value) {
      results.push(value[property]);
    });
    return results;
  }

  function reject(iterator, context) {
    var results = [];
    this.each(function(value, index) {
      if (!iterator.call(context, value, index))
        results.push(value);
    });
    return results;
  }

  function sortBy(iterator, context) {
    return this.map(function(value, index) {
      return {
        value: value,
        criteria: iterator.call(context, value, index)
      };
    }).sort(function(left, right) {
      var a = left.criteria, b = right.criteria;
      return a < b ? -1 : a > b ? 1 : 0;
    }).pluck('value');
  }

  function toArray() {
    return this.map();
  }

  function zip() {
    var iterator = Prototype.K, args = $A(arguments);
    if (Object.isFunction(args.last()))
      iterator = args.pop();

    var collections = [this].concat(args).map($A);
    return this.map(function(value, index) {
      return iterator(collections.pluck(index));
    });
  }

  function size() {
    return this.toArray().length;
  }

  function inspect() {
    return '#<Enumerable:' + this.toArray().inspect() + '>';
  }









  return {
    each:       each,
    eachSlice:  eachSlice,
    all:        all,
    every:      all,
    any:        any,
    some:       any,
    collect:    collect,
    map:        collect,
    detect:     detect,
    findAll:    findAll,
    select:     findAll,
    filter:     findAll,
    grep:       grep,
    include:    include,
    member:     include,
    inGroupsOf: inGroupsOf,
    inject:     inject,
    invoke:     invoke,
    max:        max,
    min:        min,
    partition:  partition,
    pluck:      pluck,
    reject:     reject,
    sortBy:     sortBy,
    toArray:    toArray,
    entries:    toArray,
    zip:        zip,
    size:       size,
    inspect:    inspect,
    find:       detect
  };
})();
function $A(iterable) {
  if (!iterable) return [];
  if ('toArray' in iterable) return iterable.toArray();
  var length = iterable.length || 0, results = new Array(length);
  while (length--) results[length] = iterable[length];
  return results;
}

function $w(string) {
  if (!Object.isString(string)) return [];
  string = string.strip();
  return string ? string.split(/\s+/) : [];
}

Array.from = $A;


(function() {
  var arrayProto = Array.prototype,
      slice = arrayProto.slice,
      _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available

  function each(iterator) {
    for (var i = 0, length = this.length; i < length; i++)
      iterator(this[i]);
  }
  if (!_each) _each = each;

  function clear() {
    this.length = 0;
    return this;
  }

  function first() {
    return this[0];
  }

  function last() {
    return this[this.length - 1];
  }

  function compact() {
    return this.select(function(value) {
      return value != null;
    });
  }

  function flatten() {
    return this.inject([], function(array, value) {
      if (Object.isArray(value))
        return array.concat(value.flatten());
      array.push(value);
      return array;
    });
  }

  function without() {
    var values = slice.call(arguments, 0);
    return this.select(function(value) {
      return !values.include(value);
    });
  }

  function reverse(inline) {
    return (inline !== false ? this : this.toArray())._reverse();
  }

  function uniq(sorted) {
    return this.inject([], function(array, value, index) {
      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
        array.push(value);
      return array;
    });
  }

  function intersect(array) {
    return this.uniq().findAll(function(item) {
      return array.detect(function(value) { return item === value });
    });
  }


  function clone() {
    return slice.call(this, 0);
  }

  function size() {
    return this.length;
  }

  function inspect() {
    return '[' + this.map(Object.inspect).join(', ') + ']';
  }

  function toJSON() {
    var results = [];
    this.each(function(object) {
      var value = Object.toJSON(object);
      if (!Object.isUndefined(value)) results.push(value);
    });
    return '[' + results.join(', ') + ']';
  }

  function indexOf(item, i) {
    i || (i = 0);
    var length = this.length;
    if (i < 0) i = length + i;
    for (; i < length; i++)
      if (this[i] === item) return i;
    return -1;
  }

  function lastIndexOf(item, i) {
    i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
    var n = this.slice(0, i).reverse().indexOf(item);
    return (n < 0) ? n : i - n - 1;
  }

  function concat() {
    var array = slice.call(this, 0), item;
    for (var i = 0, length = arguments.length; i < length; i++) {
      item = arguments[i];
      if (Object.isArray(item) && !('callee' in item)) {
        for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
          array.push(item[j]);
      } else {
        array.push(item);
      }
    }
    return array;
  }

  Object.extend(arrayProto, Enumerable);

  if (!arrayProto._reverse)
    arrayProto._reverse = arrayProto.reverse;

  Object.extend(arrayProto, {
    _each:     _each,
    clear:     clear,
    first:     first,
    last:      last,
    compact:   compact,
    flatten:   flatten,
    without:   without,
    reverse:   reverse,
    uniq:      uniq,
    intersect: intersect,
    clone:     clone,
    toArray:   clone,
    size:      size,
    inspect:   inspect,
    toJSON:    toJSON
  });

  var CONCAT_ARGUMENTS_BUGGY = (function() {
    return [].concat(arguments)[0][0] !== 1;
  })(1,2)

  if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;

  if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
  if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
})();
function $H(object) {
  return new Hash(object);
};

var Hash = Class.create(Enumerable, (function() {
  function initialize(object) {
    this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
  }

  function _each(iterator) {
    for (var key in this._object) {
      var value = this._object[key], pair = [key, value];
      pair.key = key;
      pair.value = value;
      iterator(pair);
    }
  }

  function set(key, value) {
    return this._object[key] = value;
  }

  function get(key) {
    if (this._object[key] !== Object.prototype[key])
      return this._object[key];
  }

  function unset(key) {
    var value = this._object[key];
    delete this._object[key];
    return value;
  }

  function toObject() {
    return Object.clone(this._object);
  }

  function keys() {
    return this.pluck('key');
  }

  function values() {
    return this.pluck('value');
  }

  function index(value) {
    var match = this.detect(function(pair) {
      return pair.value === value;
    });
    return match && match.key;
  }

  function merge(object) {
    return this.clone().update(object);
  }

  function update(object) {
    return new Hash(object).inject(this, function(result, pair) {
      result.set(pair.key, pair.value);
      return result;
    });
  }

  function toQueryPair(key, value) {
    if (Object.isUndefined(value)) return key;
    return key + '=' + encodeURIComponent(String.interpret(value));
  }

  function toQueryString() {
    return this.inject([], function(results, pair) {
      var key = encodeURIComponent(pair.key), values = pair.value;

      if (values && typeof values == 'object') {
        if (Object.isArray(values))
          return results.concat(values.map(toQueryPair.curry(key)));
      } else results.push(toQueryPair(key, values));
      return results;
    }).join('&');
  }

  function inspect() {
    return '#<Hash:{' + this.map(function(pair) {
      return pair.map(Object.inspect).join(': ');
    }).join(', ') + '}>';
  }

  function toJSON() {
    return Object.toJSON(this.toObject());
  }

  function clone() {
    return new Hash(this);
  }

  return {
    initialize:             initialize,
    _each:                  _each,
    set:                    set,
    get:                    get,
    unset:                  unset,
    toObject:               toObject,
    toTemplateReplacements: toObject,
    keys:                   keys,
    values:                 values,
    index:                  index,
    merge:                  merge,
    update:                 update,
    toQueryString:          toQueryString,
    inspect:                inspect,
    toJSON:                 toJSON,
    clone:                  clone
  };
})());

Hash.from = $H;
Object.extend(Number.prototype, (function() {
  function toColorPart() {
    return this.toPaddedString(2, 16);
  }

  function succ() {
    return this + 1;
  }

  function times(iterator, context) {
    $R(0, this, true).each(iterator, context);
    return this;
  }

  function toPaddedString(length, radix) {
    var string = this.toString(radix || 10);
    return '0'.times(length - string.length) + string;
  }

  function toJSON() {
    return isFinite(this) ? this.toString() : 'null';
  }

  function abs() {
    return Math.abs(this);
  }

  function round() {
    return Math.round(this);
  }

  function ceil() {
    return Math.ceil(this);
  }

  function floor() {
    return Math.floor(this);
  }

  return {
    toColorPart:    toColorPart,
    succ:           succ,
    times:          times,
    toPaddedString: toPaddedString,
    toJSON:         toJSON,
    abs:            abs,
    round:          round,
    ceil:           ceil,
    floor:          floor
  };
})());

function $R(start, end, exclusive) {
  return new ObjectRange(start, end, exclusive);
}

var ObjectRange = Class.create(Enumerable, (function() {
  function initialize(start, end, exclusive) {
    this.start = start;
    this.end = end;
    this.exclusive = exclusive;
  }

  function _each(iterator) {
    var value = this.start;
    while (this.include(value)) {
      iterator(value);
      value = value.succ();
    }
  }

  function include(value) {
    if (value < this.start)
      return false;
    if (this.exclusive)
      return value < this.end;
    return value <= this.end;
  }

  return {
    initialize: initialize,
    _each:      _each,
    include:    include
  };
})());



var Ajax = {
  getTransport: function() {
    return Try.these(
      function() {return new XMLHttpRequest()},
      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
    ) || false;
  },

  activeRequestCount: 0
};

Ajax.Responders = {
  responders: [],

  _each: function(iterator) {
    this.responders._each(iterator);
  },

  register: function(responder) {
    if (!this.include(responder))
      this.responders.push(responder);
  },

  unregister: function(responder) {
    this.responders = this.responders.without(responder);
  },

  dispatch: function(callback, request, transport, json) {
    this.each(function(responder) {
      if (Object.isFunction(responder[callback])) {
        try {
          responder[callback].apply(responder, [request, transport, json]);
        } catch (e) { }
      }
    });
  }
};

Object.extend(Ajax.Responders, Enumerable);

Ajax.Responders.register({
  onCreate:   function() { Ajax.activeRequestCount++ },
  onComplete: function() { Ajax.activeRequestCount-- }
});
Ajax.Base = Class.create({
  initialize: function(options) {
    this.options = {
      method:       'post',
      asynchronous: true,
      contentType:  'application/x-www-form-urlencoded',
      encoding:     'UTF-8',
      parameters:   '',
      evalJSON:     true,
      evalJS:       true
    };
    Object.extend(this.options, options || { });

    this.options.method = this.options.method.toLowerCase();

    if (Object.isString(this.options.parameters))
      this.options.parameters = this.options.parameters.toQueryParams();
    else if (Object.isHash(this.options.parameters))
      this.options.parameters = this.options.parameters.toObject();
  }
});
Ajax.Request = Class.create(Ajax.Base, {
  _complete: false,

  initialize: function($super, url, options) {
    $super(options);
    this.transport = Ajax.getTransport();
    this.request(url);
  },

  request: function(url) {
    this.url = url;
    this.method = this.options.method;
    var params = Object.clone(this.options.parameters);

    if (!['get', 'post'].include(this.method)) {
      params['_method'] = this.method;
      this.method = 'post';
    }

    this.parameters = params;

    if (params = Object.toQueryString(params)) {
      if (this.method == 'get')
        this.url += (this.url.include('?') ? '&' : '?') + params;
      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
        params += '&_=';
    }

    try {
      var response = new Ajax.Response(this);
      if (this.options.onCreate) this.options.onCreate(response);
      Ajax.Responders.dispatch('onCreate', this, response);

      this.transport.open(this.method.toUpperCase(), this.url,
        this.options.asynchronous);

      if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);

      this.transport.onreadystatechange = this.onStateChange.bind(this);
      this.setRequestHeaders();

      this.body = this.method == 'post' ? (this.options.postBody || params) : null;
      this.transport.send(this.body);

      /* Force Firefox to handle ready state 4 for synchronous requests */
      if (!this.options.asynchronous && this.transport.overrideMimeType)
        this.onStateChange();

    }
    catch (e) {
      this.dispatchException(e);
    }
  },

  onStateChange: function() {
    var readyState = this.transport.readyState;
    if (readyState > 1 && !((readyState == 4) && this._complete))
      this.respondToReadyState(this.transport.readyState);
  },

  setRequestHeaders: function() {
    var headers = {
      'X-Requested-With': 'XMLHttpRequest',
      'X-Prototype-Version': Prototype.Version,
      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
    };

    if (this.method == 'post') {
      headers['Content-type'] = this.options.contentType +
        (this.options.encoding ? '; charset=' + this.options.encoding : '');

      /* Force "Connection: close" for older Mozilla browsers to work
       * around a bug where XMLHttpRequest sends an incorrect
       * Content-length header. See Mozilla Bugzilla #246651.
       */
      if (this.transport.overrideMimeType &&
          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
            headers['Connection'] = 'close';
    }

    if (typeof this.options.requestHeaders == 'object') {
      var extras = this.options.requestHeaders;

      if (Object.isFunction(extras.push))
        for (var i = 0, length = extras.length; i < length; i += 2)
          headers[extras[i]] = extras[i+1];
      else
        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
    }

    for (var name in headers)
      this.transport.setRequestHeader(name, headers[name]);
  },

  success: function() {
    var status = this.getStatus();
    return !status || (status >= 200 && status < 300);
  },

  getStatus: function() {
    try {
      return this.transport.status || 0;
    } catch (e) { return 0 }
  },

  respondToReadyState: function(readyState) {
    var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);

    if (state == 'Complete') {
      try {
        this._complete = true;
        (this.options['on' + response.status]
         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
         || Prototype.emptyFunction)(response, response.headerJSON);
      } catch (e) {
        this.dispatchException(e);
      }

      var contentType = response.getHeader('Content-type');
      if (this.options.evalJS == 'force'
          || (this.options.evalJS && this.isSameOrigin() && contentType
          && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
        this.evalResponse();
    }

    try {
      (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
      Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
    } catch (e) {
      this.dispatchException(e);
    }

    if (state == 'Complete') {
      this.transport.onreadystatechange = Prototype.emptyFunction;
    }
  },

  isSameOrigin: function() {
    var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
    return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
      protocol: location.protocol,
      domain: document.domain,
      port: location.port ? ':' + location.port : ''
    }));
  },

  getHeader: function(name) {
    try {
      return this.transport.getResponseHeader(name) || null;
    } catch (e) { return null; }
  },

  evalResponse: function() {
    try {
      return eval((this.transport.responseText || '').unfilterJSON());
    } catch (e) {
      this.dispatchException(e);
    }
  },

  dispatchException: function(exception) {
    (this.options.onException || Prototype.emptyFunction)(this, exception);
    Ajax.Responders.dispatch('onException', this, exception);
  }
});

Ajax.Request.Events =
  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];








Ajax.Response = Class.create({
  initialize: function(request){
    this.request = request;
    var transport  = this.transport  = request.transport,
        readyState = this.readyState = transport.readyState;

    if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
      this.status       = this.getStatus();
      this.statusText   = this.getStatusText();
      this.responseText = String.interpret(transport.responseText);
      this.headerJSON   = this._getHeaderJSON();
    }

    if(readyState == 4) {
      var xml = transport.responseXML;
      this.responseXML  = Object.isUndefined(xml) ? null : xml;
      this.responseJSON = this._getResponseJSON();
    }
  },

  status:      0,

  statusText: '',

  getStatus: Ajax.Request.prototype.getStatus,

  getStatusText: function() {
    try {
      return this.transport.statusText || '';
    } catch (e) { return '' }
  },

  getHeader: Ajax.Request.prototype.getHeader,

  getAllHeaders: function() {
    try {
      return this.getAllResponseHeaders();
    } catch (e) { return null }
  },

  getResponseHeader: function(name) {
    return this.transport.getResponseHeader(name);
  },

  getAllResponseHeaders: function() {
    return this.transport.getAllResponseHeaders();
  },

  _getHeaderJSON: function() {
    var json = this.getHeader('X-JSON');
    if (!json) return null;
    json = decodeURIComponent(escape(json));
    try {
      return json.evalJSON(this.request.options.sanitizeJSON ||
        !this.request.isSameOrigin());
    } catch (e) {
      this.request.dispatchException(e);
    }
  },

  _getResponseJSON: function() {
    var options = this.request.options;
    if (!options.evalJSON || (options.evalJSON != 'force' &&
      !(this.getHeader('Content-type') || '').include('application/json')) ||
        this.responseText.blank())
          return null;
    try {
      return this.responseText.evalJSON(options.sanitizeJSON ||
        !this.request.isSameOrigin());
    } catch (e) {
      this.request.dispatchException(e);
    }
  }
});

Ajax.Updater = Class.create(Ajax.Request, {
  initialize: function($super, container, url, options) {
    this.container = {
      success: (container.success || container),
      failure: (container.failure || (container.success ? null : container))
    };

    options = Object.clone(options);
    var onComplete = options.onComplete;
    options.onComplete = (function(response, json) {
      this.updateContent(response.responseText);
      if (Object.isFunction(onComplete)) onComplete(response, json);
    }).bind(this);

    $super(url, options);
  },

  updateContent: function(responseText) {
    var receiver = this.container[this.success() ? 'success' : 'failure'],
        options = this.options;

    if (!options.evalScripts) responseText = responseText.stripScripts();

    if (receiver = $(receiver)) {
      if (options.insertion) {
        if (Object.isString(options.insertion)) {
          var insertion = { }; insertion[options.insertion] = responseText;
          receiver.insert(insertion);
        }
        else options.insertion(receiver, responseText);
      }
      else receiver.update(responseText);
    }
  }
});

Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
  initialize: function($super, container, url, options) {
    $super(options);
    this.onComplete = this.options.onComplete;

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

    this.updater = { };
    this.container = container;
    this.url = url;

    this.start();
  },

  start: function() {
    this.options.onComplete = this.updateComplete.bind(this);
    this.onTimerEvent();
  },

  stop: function() {
    this.updater.options.onComplete = undefined;
    clearTimeout(this.timer);
    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
  },

  updateComplete: function(response) {
    if (this.options.decay) {
      this.decay = (response.responseText == this.lastText ?
        this.decay * this.options.decay : 1);

      this.lastText = response.responseText;
    }
    this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
  },

  onTimerEvent: function() {
    this.updater = new Ajax.Updater(this.container, this.url, this.options);
  }
});



function $(element) {
  if (arguments.length > 1) {
    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
      elements.push($(arguments[i]));
    return elements;
  }
  if (Object.isString(element))
    element = document.getElementById(element);
  return Element.extend(element);
}

if (Prototype.BrowserFeatures.XPath) {
  document._getElementsByXPath = function(expression, parentElement) {
    var results = [];
    var query = document.evaluate(expression, $(parentElement) || document,
      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    for (var i = 0, length = query.snapshotLength; i < length; i++)
      results.push(Element.extend(query.snapshotItem(i)));
    return results;
  };
}

/*--------------------------------------------------------------------------*/

if (!window.Node) var Node = { };

if (!Node.ELEMENT_NODE) {
  Object.extend(Node, {
    ELEMENT_NODE: 1,
    ATTRIBUTE_NODE: 2,
    TEXT_NODE: 3,
    CDATA_SECTION_NODE: 4,
    ENTITY_REFERENCE_NODE: 5,
    ENTITY_NODE: 6,
    PROCESSING_INSTRUCTION_NODE: 7,
    COMMENT_NODE: 8,
    DOCUMENT_NODE: 9,
    DOCUMENT_TYPE_NODE: 10,
    DOCUMENT_FRAGMENT_NODE: 11,
    NOTATION_NODE: 12
  });
}


(function(global) {

  var SETATTRIBUTE_IGNORES_NAME = (function(){
    var elForm = document.createElement("form");
    var elInput = document.createElement("input");
    var root = document.documentElement;
    elInput.setAttribute("name", "test");
    elForm.appendChild(elInput);
    root.appendChild(elForm);
    var isBuggy = elForm.elements
      ? (typeof elForm.elements.test == "undefined")
      : null;
    root.removeChild(elForm);
    elForm = elInput = null;
    return isBuggy;
  })();

  var element = global.Element;
  global.Element = function(tagName, attributes) {
    attributes = attributes || { };
    tagName = tagName.toLowerCase();
    var cache = Element.cache;
    if (SETATTRIBUTE_IGNORES_NAME && attributes.name) {
      tagName = '<' + tagName + ' name="' + attributes.name + '">';
      delete attributes.name;
      return Element.writeAttribute(document.createElement(tagName), attributes);
    }
    if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
    return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
  };
  Object.extend(global.Element, element || { });
  if (element) global.Element.prototype = element.prototype;
})(this);

Element.cache = { };
Element.idCounter = 1;

Element.Methods = {
  visible: function(element) {
    return $(element).style.display != 'none';
  },

  toggle: function(element) {
    element = $(element);
    Element[Element.visible(element) ? 'hide' : 'show'](element);
    return element;
  },


  hide: function(element) {
    element = $(element);
    element.style.display = 'none';
    return element;
  },

  show: function(element) {
    element = $(element);
    element.style.display = '';
    return element;
  },

  remove: function(element) {
    element = $(element);
    element.parentNode.removeChild(element);
    return element;
  },

  update: (function(){

    var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
      var el = document.createElement("select"),
          isBuggy = true;
      el.innerHTML = "<option value=\"test\">test</option>";
      if (el.options && el.options[0]) {
        isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
      }
      el = null;
      return isBuggy;
    })();

    var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
      try {
        var el = document.createElement("table");
        if (el && el.tBodies) {
          el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
          var isBuggy = typeof el.tBodies[0] == "undefined";
          el = null;
          return isBuggy;
        }
      } catch (e) {
        return true;
      }
    })();

    var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
      var s = document.createElement("script"),
          isBuggy = false;
      try {
        s.appendChild(document.createTextNode(""));
        isBuggy = !s.firstChild ||
          s.firstChild && s.firstChild.nodeType !== 3;
      } catch (e) {
        isBuggy = true;
      }
      s = null;
      return isBuggy;
    })();

    function update(element, content) {
      element = $(element);

      if (content && content.toElement)
        content = content.toElement();

      if (Object.isElement(content))
        return element.update().insert(content);

      content = Object.toHTML(content);

      var tagName = element.tagName.toUpperCase();

      if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
        element.text = content;
        return element;
      }

      if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) {
        if (tagName in Element._insertionTranslations.tags) {
          $A(element.childNodes).each(function(node) {
            element.removeChild(node);
          });
          Element._getContentFromAnonymousElement(tagName, content.stripScripts())
            .each(function(node) {
              element.appendChild(node)
            });
        }
        else {
          element.innerHTML = content.stripScripts();
        }
      }
      else {
        element.innerHTML = content.stripScripts();
      }

      content.evalScripts.bind(content).defer();
      return element;
    }

    return update;
  })(),

  replace: function(element, content) {
    element = $(element);
    if (content && content.toElement) content = content.toElement();
    else if (!Object.isElement(content)) {
      content = Object.toHTML(content);
      var range = element.ownerDocument.createRange();
      range.selectNode(element);
      content.evalScripts.bind(content).defer();
      content = range.createContextualFragment(content.stripScripts());
    }
    element.parentNode.replaceChild(content, element);
    return element;
  },

  insert: function(element, insertions) {
    element = $(element);

    if (Object.isString(insertions) || Object.isNumber(insertions) ||
        Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
          insertions = {bottom:insertions};

    var content, insert, tagName, childNodes;

    for (var position in insertions) {
      content  = insertions[position];
      position = position.toLowerCase();
      insert = Element._insertionTranslations[position];

      if (content && content.toElement) content = content.toElement();
      if (Object.isElement(content)) {
        insert(element, content);
        continue;
      }

      content = Object.toHTML(content);

      tagName = ((position == 'before' || position == 'after')
        ? element.parentNode : element).tagName.toUpperCase();

      childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());

      if (position == 'top' || position == 'after') childNodes.reverse();
      childNodes.each(insert.curry(element));

      content.evalScripts.bind(content).defer();
    }

    return element;
  },

  wrap: function(element, wrapper, attributes) {
    element = $(element);
    if (Object.isElement(wrapper))
      $(wrapper).writeAttribute(attributes || { });
    else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
    else wrapper = new Element('div', wrapper);
    if (element.parentNode)
      element.parentNode.replaceChild(wrapper, element);
    wrapper.appendChild(element);
    return wrapper;
  },

  inspect: function(element) {
    element = $(element);
    var result = '<' + element.tagName.toLowerCase();
    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
      var property = pair.first(), attribute = pair.last();
      var value = (element[property] || '').toString();
      if (value) result += ' ' + attribute + '=' + value.inspect(true);
    });
    return result + '>';
  },

  recursivelyCollect: function(element, property) {
    element = $(element);
    var elements = [];
    while (element = element[property])
      if (element.nodeType == 1)
        elements.push(Element.extend(element));
    return elements;
  },

  ancestors: function(element) {
    return $(element).recursivelyCollect('parentNode');
  },

  descendants: function(element) {
    return Element.select(element, "*");
  },

  firstDescendant: function(element) {
    element = $(element).firstChild;
    while (element && element.nodeType != 1) element = element.nextSibling;
    return $(element);
  },

  immediateDescendants: function(element) {
    if (!(element = $(element).firstChild)) return [];
    while (element && element.nodeType != 1) element = element.nextSibling;
    if (element) return [element].concat($(element).nextSiblings());
    return [];
  },

  previousSiblings: function(element) {
    return $(element).recursivelyCollect('previousSibling');
  },

  nextSiblings: function(element) {
    return $(element).recursivelyCollect('nextSibling');
  },

  siblings: function(element) {
    element = $(element);
    return element.previousSiblings().reverse().concat(element.nextSiblings());
  },

  match: function(element, selector) {
    if (Object.isString(selector))
      selector = new Selector(selector);
    return selector.match($(element));
  },

  up: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return $(element.parentNode);
    var ancestors = element.ancestors();
    return Object.isNumber(expression) ? ancestors[expression] :
      Selector.findElement(ancestors, expression, index);
  },

  down: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return element.firstDescendant();
    return Object.isNumber(expression) ? element.descendants()[expression] :
      Element.select(element, expression)[index || 0];
  },

  previous: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
    var previousSiblings = element.previousSiblings();
    return Object.isNumber(expression) ? previousSiblings[expression] :
      Selector.findElement(previousSiblings, expression, index);
  },

  next: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
    var nextSiblings = element.nextSiblings();
    return Object.isNumber(expression) ? nextSiblings[expression] :
      Selector.findElement(nextSiblings, expression, index);
  },


  select: function() {
    var args = $A(arguments), element = $(args.shift());
    return Selector.findChildElements(element, args);
  },

  adjacent: function() {
    var args = $A(arguments), element = $(args.shift());
    return Selector.findChildElements(element.parentNode, args).without(element);
  },

  identify: function(element) {
    element = $(element);
    var id = element.readAttribute('id');
    if (id) return id;
    do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id));
    element.writeAttribute('id', id);
    return id;
  },

  readAttribute: (function(){

    var iframeGetAttributeThrowsError = (function(){
      var el = document.createElement('iframe'),
          isBuggy = false;

      document.documentElement.appendChild(el);
      try {
        el.getAttribute('type', 2);
      } catch(e) {
        isBuggy = true;
      }
      document.documentElement.removeChild(el);
      el = null;
      return isBuggy;
    })();

    return function(element, name) {
      element = $(element);
      if (iframeGetAttributeThrowsError &&
          name === 'type' &&
          element.tagName.toUpperCase() == 'IFRAME') {
        return element.getAttribute('type');
      }
      if (Prototype.Browser.IE) {
        var t = Element._attributeTranslations.read;
        if (t.values[name]) return t.values[name](element, name);
        if (t.names[name]) name = t.names[name];
        if (name.include(':')) {
          return (!element.attributes || !element.attributes[name]) ? null :
           element.attributes[name].value;
        }
      }
      return element.getAttribute(name);
    }
  })(),

  writeAttribute: function(element, name, value) {
    element = $(element);
    var attributes = { }, t = Element._attributeTranslations.write;

    if (typeof name == 'object') attributes = name;
    else attributes[name] = Object.isUndefined(value) ? true : value;

    for (var attr in attributes) {
      name = t.names[attr] || attr;
      value = attributes[attr];
      if (t.values[attr]) name = t.values[attr](element, value);
      if (value === false || value === null)
        element.removeAttribute(name);
      else if (value === true)
        element.setAttribute(name, name);
      else element.setAttribute(name, value);
    }
    return element;
  },

  getHeight: function(element) {
    return $(element).getDimensions().height;
  },

  getWidth: function(element) {
    return $(element).getDimensions().width;
  },

  classNames: function(element) {
    return new Element.ClassNames(element);
  },

  hasClassName: function(element, className) {
    if (!(element = $(element))) return;
    var elementClassName = element.className;
    return (elementClassName.length > 0 && (elementClassName == className ||
      new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
  },

  addClassName: function(element, className) {
    if (!(element = $(element))) return;
    if (!element.hasClassName(className))
      element.className += (element.className ? ' ' : '') + className;
    return element;
  },

  removeClassName: function(element, className) {
    if (!(element = $(element))) return;
    element.className = element.className.replace(
      new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
    return element;
  },

  toggleClassName: function(element, className) {
    if (!(element = $(element))) return;
    return element[element.hasClassName(className) ?
      'removeClassName' : 'addClassName'](className);
  },

  cleanWhitespace: function(element) {
    element = $(element);
    var node = element.firstChild;
    while (node) {
      var nextNode = node.nextSibling;
      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
        element.removeChild(node);
      node = nextNode;
    }
    return element;
  },

  empty: function(element) {
    return $(element).innerHTML.blank();
  },

  descendantOf: function(element, ancestor) {
    element = $(element), ancestor = $(ancestor);

    if (element.compareDocumentPosition)
      return (element.compareDocumentPosition(ancestor) & 8) === 8;

    if (ancestor.contains)
      return ancestor.contains(element) && ancestor !== element;

    while (element = element.parentNode)
      if (element == ancestor) return true;

    return false;
  },

  scrollTo: function(element) {
    element = $(element);
    var pos = element.cumulativeOffset();
    window.scrollTo(pos[0], pos[1]);
    return element;
  },

  getStyle: function(element, style) {
    element = $(element);
    style = style == 'float' ? 'cssFloat' : style.camelize();
    var value = element.style[style];
    if (!value || value == 'auto') {
      var css = document.defaultView.getComputedStyle(element, null);
      value = css ? css[style] : null;
    }
    if (style == 'opacity') return value ? parseFloat(value) : 1.0;
    return value == 'auto' ? null : value;
  },

  getOpacity: function(element) {
    return $(element).getStyle('opacity');
  },

  setStyle: function(element, styles) {
    element = $(element);
    var elementStyle = element.style, match;
    if (Object.isString(styles)) {
      element.style.cssText += ';' + styles;
      return styles.include('opacity') ?
        element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
    }
    for (var property in styles)
      if (property == 'opacity') element.setOpacity(styles[property]);
      else
        elementStyle[(property == 'float' || property == 'cssFloat') ?
          (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
            property] = styles[property];

    return element;
  },

  setOpacity: function(element, value) {
    element = $(element);
    element.style.opacity = (value == 1 || value === '') ? '' :
      (value < 0.00001) ? 0 : value;
    return element;
  },

  getDimensions: function(element) {
    element = $(element);
    var display = element.getStyle('display');
    if (display != 'none' && display != null) // Safari bug
      return {width: element.offsetWidth, height: element.offsetHeight};

    var els = element.style;
    var originalVisibility = els.visibility;
    var originalPosition = els.position;
    var originalDisplay = els.display;
    els.visibility = 'hidden';
    if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari
      els.position = 'absolute';
    els.display = 'block';
    var originalWidth = element.clientWidth;
    var originalHeight = element.clientHeight;
    els.display = originalDisplay;
    els.position = originalPosition;
    els.visibility = originalVisibility;
    return {width: originalWidth, height: originalHeight};
  },

  makePositioned: function(element) {
    element = $(element);
    var pos = Element.getStyle(element, 'position');
    if (pos == 'static' || !pos) {
      element._madePositioned = true;
      element.style.position = 'relative';
      if (Prototype.Browser.Opera) {
        element.style.top = 0;
        element.style.left = 0;
      }
    }
    return element;
  },

  undoPositioned: function(element) {
    element = $(element);
    if (element._madePositioned) {
      element._madePositioned = undefined;
      element.style.position =
        element.style.top =
        element.style.left =
        element.style.bottom =
        element.style.right = '';
    }
    return element;
  },

  makeClipping: function(element) {
    element = $(element);
    if (element._overflow) return element;
    element._overflow = Element.getStyle(element, 'overflow') || 'auto';
    if (element._overflow !== 'hidden')
      element.style.overflow = 'hidden';
    return element;
  },

  undoClipping: function(element) {
    element = $(element);
    if (!element._overflow) return element;
    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
    element._overflow = null;
    return element;
  },

  cumulativeOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
    } while (element);
    return Element._returnOffset(valueL, valueT);
  },

  positionedOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
      if (element) {
        if (element.tagName.toUpperCase() == 'BODY') break;
        var p = Element.getStyle(element, 'position');
        if (p !== 'static') break;
      }
    } while (element);
    return Element._returnOffset(valueL, valueT);
  },

  absolutize: function(element) {
    element = $(element);
    if (element.getStyle('position') == 'absolute') return element;

    var offsets = element.positionedOffset();
    var top     = offsets[1];
    var left    = offsets[0];
    var width   = element.clientWidth;
    var height  = element.clientHeight;

    element._originalLeft   = left - parseFloat(element.style.left  || 0);
    element._originalTop    = top  - parseFloat(element.style.top || 0);
    element._originalWidth  = element.style.width;
    element._originalHeight = element.style.height;

    element.style.position = 'absolute';
    element.style.top    = top + 'px';
    element.style.left   = left + 'px';
    element.style.width  = width + 'px';
    element.style.height = height + 'px';
    return element;
  },

  relativize: function(element) {
    element = $(element);
    if (element.getStyle('position') == 'relative') return element;

    element.style.position = 'relative';
    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);

    element.style.top    = top + 'px';
    element.style.left   = left + 'px';
    element.style.height = element._originalHeight;
    element.style.width  = element._originalWidth;
    return element;
  },

  cumulativeScrollOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.scrollTop  || 0;
      valueL += element.scrollLeft || 0;
      element = element.parentNode;
    } while (element);
    return Element._returnOffset(valueL, valueT);
  },

  getOffsetParent: function(element) {
    if (element.offsetParent) return $(element.offsetParent);
    if (element == document.body) return $(element);

    while ((element = element.parentNode) && element != document.body)
      if (Element.getStyle(element, 'position') != 'static')
        return $(element);

    return $(document.body);
  },

  viewportOffset: function(forElement) {
    var valueT = 0, valueL = 0;

    var element = forElement;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;

      if (element.offsetParent == document.body &&
        Element.getStyle(element, 'position') == 'absolute') break;

    } while (element = element.offsetParent);

    element = forElement;
    do {
      if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {
        valueT -= element.scrollTop  || 0;
        valueL -= element.scrollLeft || 0;
      }
    } while (element = element.parentNode);

    return Element._returnOffset(valueL, valueT);
  },

  clonePosition: function(element, source) {
    var options = Object.extend({
      setLeft:    true,
      setTop:     true,
      setWidth:   true,
      setHeight:  true,
      offsetTop:  0,
      offsetLeft: 0
    }, arguments[2] || { });

    source = $(source);
    var p = source.viewportOffset();

    element = $(element);
    var delta = [0, 0];
    var parent = null;
    if (Element.getStyle(element, 'position') == 'absolute') {
      parent = element.getOffsetParent();
      delta = parent.viewportOffset();
    }

    if (parent == document.body) {
      delta[0] -= document.body.offsetLeft;
      delta[1] -= document.body.offsetTop;
    }

    if (options.setLeft)   element.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
    if (options.setTop)    element.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
    if (options.setWidth)  element.style.width = source.offsetWidth + 'px';
    if (options.setHeight) element.style.height = source.offsetHeight + 'px';
    return element;
  }
};

Object.extend(Element.Methods, {
  getElementsBySelector: Element.Methods.select,

  childElements: Element.Methods.immediateDescendants
});

Element._attributeTranslations = {
  write: {
    names: {
      className: 'class',
      htmlFor:   'for'
    },
    values: { }
  }
};

if (Prototype.Browser.Opera) {
  Element.Methods.getStyle = Element.Methods.getStyle.wrap(
    function(proceed, element, style) {
      switch (style) {
        case 'left': case 'top': case 'right': case 'bottom':
          if (proceed(element, 'position') === 'static') return null;
        case 'height': case 'width':
          if (!Element.visible(element)) return null;

          var dim = parseInt(proceed(element, style), 10);

          if (dim !== element['offset' + style.capitalize()])
            return dim + 'px';

          var properties;
          if (style === 'height') {
            properties = ['border-top-width', 'padding-top',
             'padding-bottom', 'border-bottom-width'];
          }
          else {
            properties = ['border-left-width', 'padding-left',
             'padding-right', 'border-right-width'];
          }
          return properties.inject(dim, function(memo, property) {
            var val = proceed(element, property);
            return val === null ? memo : memo - parseInt(val, 10);
          }) + 'px';
        default: return proceed(element, style);
      }
    }
  );

  Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
    function(proceed, element, attribute) {
      if (attribute === 'title') return element.title;
      return proceed(element, attribute);
    }
  );
}

else if (Prototype.Browser.IE) {
  Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
    function(proceed, element) {
      element = $(element);
      try { element.offsetParent }
      catch(e) { return $(document.body) }
      var position = element.getStyle('position');
      if (position !== 'static') return proceed(element);
      element.setStyle({ position: 'relative' });
      var value = proceed(element);
      element.setStyle({ position: position });
      return value;
    }
  );

  $w('positionedOffset viewportOffset').each(function(method) {
    Element.Methods[method] = Element.Methods[method].wrap(
      function(proceed, element) {
        element = $(element);
        try { element.offsetParent }
        catch(e) { return Element._returnOffset(0,0) }
        var position = element.getStyle('position');
        if (position !== 'static') return proceed(element);
        var offsetParent = element.getOffsetParent();
        if (offsetParent && offsetParent.getStyle('position') === 'fixed')
          offsetParent.setStyle({ zoom: 1 });
        element.setStyle({ position: 'relative' });
        var value = proceed(element);
        element.setStyle({ position: position });
        return value;
      }
    );
  });

  Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
    function(proceed, element) {
      try { element.offsetParent }
      catch(e) { return Element._returnOffset(0,0) }
      return proceed(element);
    }
  );

  Element.Methods.getStyle = function(element, style) {
    element = $(element);
    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
    var value = element.style[style];
    if (!value && element.currentStyle) value = element.currentStyle[style];

    if (style == 'opacity') {
      if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
        if (value[1]) return parseFloat(value[1]) / 100;
      return 1.0;
    }

    if (value == 'auto') {
      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
        return element['offset' + style.capitalize()] + 'px';
      return null;
    }
    return value;
  };

  Element.Methods.setOpacity = function(element, value) {
    function stripAlpha(filter){
      return filter.replace(/alpha\([^\)]*\)/gi,'');
    }
    element = $(element);
    var currentStyle = element.currentStyle;
    if ((currentStyle && !currentStyle.hasLayout) ||
      (!currentStyle && element.style.zoom == 'normal'))
        element.style.zoom = 1;

    var filter = element.getStyle('filter'), style = element.style;
    if (value == 1 || value === '') {
      (filter = stripAlpha(filter)) ?
        style.filter = filter : style.removeAttribute('filter');
      return element;
    } else if (value < 0.00001) value = 0;
    style.filter = stripAlpha(filter) +
      'alpha(opacity=' + (value * 100) + ')';
    return element;
  };

  Element._attributeTranslations = (function(){

    var classProp = 'className';
    var forProp = 'for';

    var el = document.createElement('div');

    el.setAttribute(classProp, 'x');

    if (el.className !== 'x') {
      el.setAttribute('class', 'x');
      if (el.className === 'x') {
        classProp = 'class';
      }
    }
    el = null;

    el = document.createElement('label');
    el.setAttribute(forProp, 'x');
    if (el.htmlFor !== 'x') {
      el.setAttribute('htmlFor', 'x');
      if (el.htmlFor === 'x') {
        forProp = 'htmlFor';
      }
    }
    el = null;

    return {
      read: {
        names: {
          'class':      classProp,
          'className':  classProp,
          'for':        forProp,
          'htmlFor':    forProp
        },
        values: {
          _getAttr: function(element, attribute) {
            return element.getAttribute(attribute, 2);
          },
          _getAttrNode: function(element, attribute) {
            var node = element.getAttributeNode(attribute);
            return node ? node.value : "";
          },
          _getEv: (function(){

            var el = document.createElement('div');
            el.onclick = Prototype.emptyFunction;
            var value = el.getAttribute('onclick');
            var f;

            if (String(value).indexOf('{') > -1) {
              f = function(element, attribute) {
                attribute = element.getAttribute(attribute);
                if (!attribute) return null;
                attribute = attribute.toString();
                attribute = attribute.split('{')[1];
                attribute = attribute.split('}')[0];
                return attribute.strip();
              }
            }
            else if (value === '') {
              f = function(element, attribute) {
                attribute = element.getAttribute(attribute);
                if (!attribute) return null;
                return attribute.strip();
              }
            }
            el = null;
            return f;
          })(),
          _flag: function(element, attribute) {
            return $(element).hasAttribute(attribute) ? attribute : null;
          },
          style: function(element) {
            return element.style.cssText.toLowerCase();
          },
          title: function(element) {
            return element.title;
          }
        }
      }
    }
  })();

  Element._attributeTranslations.write = {
    names: Object.extend({
      cellpadding: 'cellPadding',
      cellspacing: 'cellSpacing'
    }, Element._attributeTranslations.read.names),
    values: {
      checked: function(element, value) {
        element.checked = !!value;
      },

      style: function(element, value) {
        element.style.cssText = value ? value : '';
      }
    }
  };

  Element._attributeTranslations.has = {};

  $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
      'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
    Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
    Element._attributeTranslations.has[attr.toLowerCase()] = attr;
  });

  (function(v) {
    Object.extend(v, {
      href:        v._getAttr,
      src:         v._getAttr,
      type:        v._getAttr,
      action:      v._getAttrNode,
      disabled:    v._flag,
      checked:     v._flag,
      readonly:    v._flag,
      multiple:    v._flag,
      onload:      v._getEv,
      onunload:    v._getEv,
      onclick:     v._getEv,
      ondblclick:  v._getEv,
      onmousedown: v._getEv,
      onmouseup:   v._getEv,
      onmouseover: v._getEv,
      onmousemove: v._getEv,
      onmouseout:  v._getEv,
      onfocus:     v._getEv,
      onblur:      v._getEv,
      onkeypress:  v._getEv,
      onkeydown:   v._getEv,
      onkeyup:     v._getEv,
      onsubmit:    v._getEv,
      onreset:     v._getEv,
      onselect:    v._getEv,
      onchange:    v._getEv
    });
  })(Element._attributeTranslations.read.values);

  if (Prototype.BrowserFeatures.ElementExtensions) {
    (function() {
      function _descendants(element) {
        var nodes = element.getElementsByTagName('*'), results = [];
        for (var i = 0, node; node = nodes[i]; i++)
          if (node.tagName !== "!") // Filter out comment nodes.
            results.push(node);
        return results;
      }

      Element.Methods.down = function(element, expression, index) {
        element = $(element);
        if (arguments.length == 1) return element.firstDescendant();
        return Object.isNumber(expression) ? _descendants(element)[expression] :
          Element.select(element, expression)[index || 0];
      }
    })();
  }

}

else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
  Element.Methods.setOpacity = function(element, value) {
    element = $(element);
    element.style.opacity = (value == 1) ? 0.999999 :
      (value === '') ? '' : (value < 0.00001) ? 0 : value;
    return element;
  };
}

else if (Prototype.Browser.WebKit) {
  Element.Methods.setOpacity = function(element, value) {
    element = $(element);
    element.style.opacity = (value == 1 || value === '') ? '' :
      (value < 0.00001) ? 0 : value;

    if (value == 1)
      if(element.tagName.toUpperCase() == 'IMG' && element.width) {
        element.width++; element.width--;
      } else try {
        var n = document.createTextNode(' ');
        element.appendChild(n);
        element.removeChild(n);
      } catch (e) { }

    return element;
  };

  Element.Methods.cumulativeOffset = function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      if (element.offsetParent == document.body)
        if (Element.getStyle(element, 'position') == 'absolute') break;

      element = element.offsetParent;
    } while (element);

    return Element._returnOffset(valueL, valueT);
  };
}

if ('outerHTML' in document.documentElement) {
  Element.Methods.replace = function(element, content) {
    element = $(element);

    if (content && content.toElement) content = content.toElement();
    if (Object.isElement(content)) {
      element.parentNode.replaceChild(content, element);
      return element;
    }

    content = Object.toHTML(content);
    var parent = element.parentNode, tagName = parent.tagName.toUpperCase();

    if (Element._insertionTranslations.tags[tagName]) {
      var nextSibling = element.next();
      var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
      parent.removeChild(element);
      if (nextSibling)
        fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
      else
        fragments.each(function(node) { parent.appendChild(node) });
    }
    else element.outerHTML = content.stripScripts();

    content.evalScripts.bind(content).defer();
    return element;
  };
}

Element._returnOffset = function(l, t) {
  var result = [l, t];
  result.left = l;
  result.top = t;
  return result;
};

Element._getContentFromAnonymousElement = function(tagName, html) {
  var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
  if (t) {
    div.innerHTML = t[0] + html + t[1];
    t[2].times(function() { div = div.firstChild });
  } else div.innerHTML = html;
  return $A(div.childNodes);
};

Element._insertionTranslations = {
  before: function(element, node) {
    element.parentNode.insertBefore(node, element);
  },
  top: function(element, node) {
    element.insertBefore(node, element.firstChild);
  },
  bottom: function(element, node) {
    element.appendChild(node);
  },
  after: function(element, node) {
    element.parentNode.insertBefore(node, element.nextSibling);
  },
  tags: {
    TABLE:  ['<table>',                '</table>',                   1],
    TBODY:  ['<table><tbody>',         '</tbody></table>',           2],
    TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3],
    TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
    SELECT: ['<select>',               '</select>',                  1]
  }
};

(function() {
  Object.extend(this.tags, {
    THEAD: this.tags.TBODY,
    TFOOT: this.tags.TBODY,
    TH:    this.tags.TD
  });
}).call(Element._insertionTranslations);

Element.Methods.Simulated = {
  hasAttribute: function(element, attribute) {
    attribute = Element._attributeTranslations.has[attribute] || attribute;
    var node = $(element).getAttributeNode(attribute);
    return !!(node && node.specified);
  }
};

Element.Methods.ByTag = { };

Object.extend(Element, Element.Methods);

(function(div) {

  if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) {
    window.HTMLElement = { };
    window.HTMLElement.prototype = div['__proto__'];
    Prototype.BrowserFeatures.ElementExtensions = true;
  }

  div = null;

})(document.createElement('div'))

Element.extend = (function() {

  function checkDeficiency(tagName) {
    if (typeof window.Element != 'undefined') {
      var proto = window.Element.prototype;
      if (proto) {
        var id = '_' + (Math.random()+'').slice(2);
        var el = document.createElement(tagName);
        proto[id] = 'x';
        var isBuggy = (el[id] !== 'x');
        delete proto[id];
        el = null;
        return isBuggy;
      }
    }
    return false;
  }

  function extendElementWith(element, methods) {
    for (var property in methods) {
      var value = methods[property];
      if (Object.isFunction(value) && !(property in element))
        element[property] = value.methodize();
    }
  }

  var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object');
  var HTMLAPPLETELEMENT_PROTOTYPE_BUGGY = checkDeficiency('applet');

  if (Prototype.BrowserFeatures.SpecificElementExtensions) {
    if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY &&
        HTMLAPPLETELEMENT_PROTOTYPE_BUGGY) {
      return function(element) {
        if (element && element.tagName) {
          var tagName = element.tagName.toUpperCase();
          if (tagName === 'OBJECT' || tagName === 'APPLET') {
            extendElementWith(element, Element.Methods);
            if (tagName === 'OBJECT') {
              extendElementWith(element, Element.Methods.ByTag.OBJECT)
            }
            else if (tagName === 'APPLET') {
              extendElementWith(element, Element.Methods.ByTag.APPLET)
            }
          }
        }
        return element;
      }
    }
    return Prototype.K;
  }

  var Methods = { }, ByTag = Element.Methods.ByTag;

  var extend = Object.extend(function(element) {
    if (!element || typeof element._extendedByPrototype != 'undefined' ||
        element.nodeType != 1 || element == window) return element;

    var methods = Object.clone(Methods),
        tagName = element.tagName.toUpperCase();

    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);

    extendElementWith(element, methods);

    element._extendedByPrototype = Prototype.emptyFunction;
    return element;

  }, {
    refresh: function() {
      if (!Prototype.BrowserFeatures.ElementExtensions) {
        Object.extend(Methods, Element.Methods);
        Object.extend(Methods, Element.Methods.Simulated);
      }
    }
  });

  extend.refresh();
  return extend;
})();

Element.hasAttribute = function(element, attribute) {
  if (element.hasAttribute) return element.hasAttribute(attribute);
  return Element.Methods.Simulated.hasAttribute(element, attribute);
};

Element.addMethods = function(methods) {
  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;

  if (!methods) {
    Object.extend(Form, Form.Methods);
    Object.extend(Form.Element, Form.Element.Methods);
    Object.extend(Element.Methods.ByTag, {
      "FORM":     Object.clone(Form.Methods),
      "INPUT":    Object.clone(Form.Element.Methods),
      "SELECT":   Object.clone(Form.Element.Methods),
      "TEXTAREA": Object.clone(Form.Element.Methods)
    });
  }

  if (arguments.length == 2) {
    var tagName = methods;
    methods = arguments[1];
  }

  if (!tagName) Object.extend(Element.Methods, methods || { });
  else {
    if (Object.isArray(tagName)) tagName.each(extend);
    else extend(tagName);
  }

  function extend(tagName) {
    tagName = tagName.toUpperCase();
    if (!Element.Methods.ByTag[tagName])
      Element.Methods.ByTag[tagName] = { };
    Object.extend(Element.Methods.ByTag[tagName], methods);
  }

  function copy(methods, destination, onlyIfAbsent) {
    onlyIfAbsent = onlyIfAbsent || false;
    for (var property in methods) {
      var value = methods[property];
      if (!Object.isFunction(value)) continue;
      if (!onlyIfAbsent || !(property in destination))
        destination[property] = value.methodize();
    }
  }

  function findDOMClass(tagName) {
    var klass;
    var trans = {
      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
      "FrameSet", "IFRAME": "IFrame"
    };
    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
    if (window[klass]) return window[klass];
    klass = 'HTML' + tagName + 'Element';
    if (window[klass]) return window[klass];
    klass = 'HTML' + tagName.capitalize() + 'Element';
    if (window[klass]) return window[klass];

    var element = document.createElement(tagName);
    var proto = element['__proto__'] || element.constructor.prototype;
    element = null;
    return proto;
  }

  var elementPrototype = window.HTMLElement ? HTMLElement.prototype :
   Element.prototype;

  if (F.ElementExtensions) {
    copy(Element.Methods, elementPrototype);
    copy(Element.Methods.Simulated, elementPrototype, true);
  }

  if (F.SpecificElementExtensions) {
    for (var tag in Element.Methods.ByTag) {
      var klass = findDOMClass(tag);
      if (Object.isUndefined(klass)) continue;
      copy(T[tag], klass.prototype);
    }
  }

  Object.extend(Element, Element.Methods);
  delete Element.ByTag;

  if (Element.extend.refresh) Element.extend.refresh();
  Element.cache = { };
};


document.viewport = {

  getDimensions: function() {
    return { width: this.getWidth(), height: this.getHeight() };
  },

  getScrollOffsets: function() {
    return Element._returnOffset(
      window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
      window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop);
  }
};

(function(viewport) {
  var B = Prototype.Browser, doc = document, element, property = {};

  function getRootElement() {
    if (B.WebKit && !doc.evaluate)
      return document;

    if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)
      return document.body;

    return document.documentElement;
  }

  function define(D) {
    if (!element) element = getRootElement();

    property[D] = 'client' + D;

    viewport['get' + D] = function() { return element[property[D]] };
    return viewport['get' + D]();
  }

  viewport.getWidth  = define.curry('Width');

  viewport.getHeight = define.curry('Height');
})(document.viewport);


Element.Storage = {
  UID: 1
};

Element.addMethods({
  getStorage: function(element) {
    if (!(element = $(element))) return;

    var uid;
    if (element === window) {
      uid = 0;
    } else {
      if (typeof element._prototypeUID === "undefined")
        element._prototypeUID = [Element.Storage.UID++];
      uid = element._prototypeUID[0];
    }

    if (!Element.Storage[uid])
      Element.Storage[uid] = $H();

    return Element.Storage[uid];
  },

  store: function(element, key, value) {
    if (!(element = $(element))) return;

    if (arguments.length === 2) {
      element.getStorage().update(key);
    } else {
      element.getStorage().set(key, value);
    }

    return element;
  },

  retrieve: function(element, key, defaultValue) {
    if (!(element = $(element))) return;
    var hash = Element.getStorage(element), value = hash.get(key);

    if (Object.isUndefined(value)) {
      hash.set(key, defaultValue);
      value = defaultValue;
    }

    return value;
  },

  clone: function(element, deep) {
    if (!(element = $(element))) return;
    var clone = element.cloneNode(deep);
    clone._prototypeUID = void 0;
    if (deep) {
      var descendants = Element.select(clone, '*'),
          i = descendants.length;
      while (i--) {
        descendants[i]._prototypeUID = void 0;
      }
    }
    return Element.extend(clone);
  }
});
/* Portions of the Selector class are derived from Jack Slocum's DomQuery,
 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
 * license.  Please see http://www.yui-ext.com/ for more information. */

var Selector = Class.create({
  initialize: function(expression) {
    this.expression = expression.strip();

    if (this.shouldUseSelectorsAPI()) {
      this.mode = 'selectorsAPI';
    } else if (this.shouldUseXPath()) {
      this.mode = 'xpath';
      this.compileXPathMatcher();
    } else {
      this.mode = "normal";
      this.compileMatcher();
    }

  },

  shouldUseXPath: (function() {

    var IS_DESCENDANT_SELECTOR_BUGGY = (function(){
      var isBuggy = false;
      if (document.evaluate && window.XPathResult) {
        var el = document.createElement('div');
        el.innerHTML = '<ul><li></li></ul><div><ul><li></li></ul></div>';

        var xpath = ".//*[local-name()='ul' or local-name()='UL']" +
          "//*[local-name()='li' or local-name()='LI']";

        var result = document.evaluate(xpath, el, null,
          XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

        isBuggy = (result.snapshotLength !== 2);
        el = null;
      }
      return isBuggy;
    })();

    return function() {
      if (!Prototype.BrowserFeatures.XPath) return false;

      var e = this.expression;

      if (Prototype.Browser.WebKit &&
       (e.include("-of-type") || e.include(":empty")))
        return false;

      if ((/(\[[\w-]*?:|:checked)/).test(e))
        return false;

      if (IS_DESCENDANT_SELECTOR_BUGGY) return false;

      return true;
    }

  })(),

  shouldUseSelectorsAPI: function() {
    if (!Prototype.BrowserFeatures.SelectorsAPI) return false;

    if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false;

    if (!Selector._div) Selector._div = new Element('div');

    try {
      Selector._div.querySelector(this.expression);
    } catch(e) {
      return false;
    }

    return true;
  },

  compileMatcher: function() {
    var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
        c = Selector.criteria, le, p, m, len = ps.length, name;

    if (Selector._cache[e]) {
      this.matcher = Selector._cache[e];
      return;
    }

    this.matcher = ["this.matcher = function(root) {",
                    "var r = root, h = Selector.handlers, c = false, n;"];

    while (e && le != e && (/\S/).test(e)) {
      le = e;
      for (var i = 0; i<len; i++) {
        p = ps[i].re;
        name = ps[i].name;
        if (m = e.match(p)) {
          this.matcher.push(Object.isFunction(c[name]) ? c[name](m) :
            new Template(c[name]).evaluate(m));
          e = e.replace(m[0], '');
          break;
        }
      }
    }

    this.matcher.push("return h.unique(n);\n}");
    eval(this.matcher.join('\n'));
    Selector._cache[this.expression] = this.matcher;
  },

  compileXPathMatcher: function() {
    var e = this.expression, ps = Selector.patterns,
        x = Selector.xpath, le, m, len = ps.length, name;

    if (Selector._cache[e]) {
      this.xpath = Selector._cache[e]; return;
    }

    this.matcher = ['.//*'];
    while (e && le != e && (/\S/).test(e)) {
      le = e;
      for (var i = 0; i<len; i++) {
        name = ps[i].name;
        if (m = e.match(ps[i].re)) {
          this.matcher.push(Object.isFunction(x[name]) ? x[name](m) :
            new Template(x[name]).evaluate(m));
          e = e.replace(m[0], '');
          break;
        }
      }
    }

    this.xpath = this.matcher.join('');
    Selector._cache[this.expression] = this.xpath;
  },

  findElements: function(root) {
    root = root || document;
    var e = this.expression, results;

    switch (this.mode) {
      case 'selectorsAPI':
        if (root !== document) {
          var oldId = root.id, id = $(root).identify();
          id = id.replace(/[\.:]/g, "\\$0");
          e = "#" + id + " " + e;
        }

        results = $A(root.querySelectorAll(e)).map(Element.extend);
        root.id = oldId;

        return results;
      case 'xpath':
        return document._getElementsByXPath(this.xpath, root);
      default:
       return this.matcher(root);
    }
  },

  match: function(element) {
    this.tokens = [];

    var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
    var le, p, m, len = ps.length, name;

    while (e && le !== e && (/\S/).test(e)) {
      le = e;
      for (var i = 0; i<len; i++) {
        p = ps[i].re;
        name = ps[i].name;
        if (m = e.match(p)) {
          if (as[name]) {
            this.tokens.push([name, Object.clone(m)]);
            e = e.replace(m[0], '');
          } else {
            return this.findElements(document).include(element);
          }
        }
      }
    }

    var match = true, name, matches;
    for (var i = 0, token; token = this.tokens[i]; i++) {
      name = token[0], matches = token[1];
      if (!Selector.assertions[name](element, matches)) {
        match = false; break;
      }
    }

    return match;
  },

  toString: function() {
    return this.expression;
  },

  inspect: function() {
    return "#<Selector:" + this.expression.inspect() + ">";
  }
});

if (Prototype.BrowserFeatures.SelectorsAPI &&
 document.compatMode === 'BackCompat') {
  Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){
    var div = document.createElement('div'),
     span = document.createElement('span');

    div.id = "prototype_test_id";
    span.className = 'Test';
    div.appendChild(span);
    var isIgnored = (div.querySelector('#prototype_test_id .test') !== null);
    div = span = null;
    return isIgnored;
  })();
}

Object.extend(Selector, {
  _cache: { },

  xpath: {
    descendant:   "//*",
    child:        "/*",
    adjacent:     "/following-sibling::*[1]",
    laterSibling: '/following-sibling::*',
    tagName:      function(m) {
      if (m[1] == '*') return '';
      return "[local-name()='" + m[1].toLowerCase() +
             "' or local-name()='" + m[1].toUpperCase() + "']";
    },
    className:    "[contains(concat(' ', @class, ' '), ' #{1} ')]",
    id:           "[@id='#{1}']",
    attrPresence: function(m) {
      m[1] = m[1].toLowerCase();
      return new Template("[@#{1}]").evaluate(m);
    },
    attr: function(m) {
      m[1] = m[1].toLowerCase();
      m[3] = m[5] || m[6];
      return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
    },
    pseudo: function(m) {
      var h = Selector.xpath.pseudos[m[1]];
      if (!h) return '';
      if (Object.isFunction(h)) return h(m);
      return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
    },
    operators: {
      '=':  "[@#{1}='#{3}']",
      '!=': "[@#{1}!='#{3}']",
      '^=': "[starts-with(@#{1}, '#{3}')]",
      '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
      '*=': "[contains(@#{1}, '#{3}')]",
      '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
      '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
    },
    pseudos: {
      'first-child': '[not(preceding-sibling::*)]',
      'last-child':  '[not(following-sibling::*)]',
      'only-child':  '[not(preceding-sibling::* or following-sibling::*)]',
      'empty':       "[count(*) = 0 and (count(text()) = 0)]",
      'checked':     "[@checked]",
      'disabled':    "[(@disabled) and (@type!='hidden')]",
      'enabled':     "[not(@disabled) and (@type!='hidden')]",
      'not': function(m) {
        var e = m[6], p = Selector.patterns,
            x = Selector.xpath, le, v, len = p.length, name;

        var exclusion = [];
        while (e && le != e && (/\S/).test(e)) {
          le = e;
          for (var i = 0; i<len; i++) {
            name = p[i].name
            if (m = e.match(p[i].re)) {
              v = Object.isFunction(x[name]) ? x[name](m) : new Template(x[name]).evaluate(m);
              exclusion.push("(" + v.substring(1, v.length - 1) + ")");
              e = e.replace(m[0], '');
              break;
            }
          }
        }
        return "[not(" + exclusion.join(" and ") + ")]";
      },
      'nth-child':      function(m) {
        return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
      },
      'nth-last-child': function(m) {
        return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
      },
      'nth-of-type':    function(m) {
        return Selector.xpath.pseudos.nth("position() ", m);
      },
      'nth-last-of-type': function(m) {
        return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
      },
      'first-of-type':  function(m) {
        m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
      },
      'last-of-type':   function(m) {
        m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
      },
      'only-of-type':   function(m) {
        var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
      },
      nth: function(fragment, m) {
        var mm, formula = m[6], predicate;
        if (formula == 'even') formula = '2n+0';
        if (formula == 'odd')  formula = '2n+1';
        if (mm = formula.match(/^(\d+)$/)) // digit only
          return '[' + fragment + "= " + mm[1] + ']';
        if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
          if (mm[1] == "-") mm[1] = -1;
          var a = mm[1] ? Number(mm[1]) : 1;
          var b = mm[2] ? Number(mm[2]) : 0;
          predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
          "((#{fragment} - #{b}) div #{a} >= 0)]";
          return new Template(predicate).evaluate({
            fragment: fragment, a: a, b: b });
        }
      }
    }
  },

  criteria: {
    tagName:      'n = h.tagName(n, r, "#{1}", c);      c = false;',
    className:    'n = h.className(n, r, "#{1}", c);    c = false;',
    id:           'n = h.id(n, r, "#{1}", c);           c = false;',
    attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
    attr: function(m) {
      m[3] = (m[5] || m[6]);
      return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
    },
    pseudo: function(m) {
      if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
      return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
    },
    descendant:   'c = "descendant";',
    child:        'c = "child";',
    adjacent:     'c = "adjacent";',
    laterSibling: 'c = "laterSibling";'
  },

  patterns: [
    { name: 'laterSibling', re: /^\s*~\s*/ },
    { name: 'child',        re: /^\s*>\s*/ },
    { name: 'adjacent',     re: /^\s*\+\s*/ },
    { name: 'descendant',   re: /^\s/ },

    { name: 'tagName',      re: /^\s*(\*|[\w\-]+)(\b|$)?/ },
    { name: 'id',           re: /^#([\w\-\*]+)(\b|$)/ },
    { name: 'className',    re: /^\.([\w\-\*]+)(\b|$)/ },
    { name: 'pseudo',       re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ },
    { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ },
    { name: 'attr',         re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ }
  ],

  assertions: {
    tagName: function(element, matches) {
      return matches[1].toUpperCase() == element.tagName.toUpperCase();
    },

    className: function(element, matches) {
      return Element.hasClassName(element, matches[1]);
    },

    id: function(element, matches) {
      return element.id === matches[1];
    },

    attrPresence: function(element, matches) {
      return Element.hasAttribute(element, matches[1]);
    },

    attr: function(element, matches) {
      var nodeValue = Element.readAttribute(element, matches[1]);
      return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
    }
  },

  handlers: {
    concat: function(a, b) {
      for (var i = 0, node; node = b[i]; i++)
        a.push(node);
      return a;
    },

    mark: function(nodes) {
      var _true = Prototype.emptyFunction;
      for (var i = 0, node; node = nodes[i]; i++)
        node._countedByPrototype = _true;
      return nodes;
    },

    unmark: function(nodes) {
      for (var i = 0, node; node = nodes[i]; i++)
        node._countedByPrototype = undefined;
      return nodes;
    },

    index: function(parentNode, reverse, ofType) {
      parentNode._countedByPrototype = Prototype.emptyFunction;
      if (reverse) {
        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
          var node = nodes[i];
          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
        }
      } else {
        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
      }
    },

    unique: function(nodes) {
      if (nodes.length == 0) return nodes;
      var results = [], n;
      for (var i = 0, l = nodes.length; i < l; i++)
        if (typeof (n = nodes[i])._countedByPrototype == 'undefined') {
          n._countedByPrototype = Prototype.emptyFunction;
          results.push(Element.extend(n));
        }
      return Selector.handlers.unmark(results);
    },

    descendant: function(nodes) {
      var h = Selector.handlers;
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        h.concat(results, node.getElementsByTagName('*'));
      return results;
    },

    child: function(nodes) {
      var h = Selector.handlers;
      for (var i = 0, results = [], node; node = nodes[i]; i++) {
        for (var j = 0, child; child = node.childNodes[j]; j++)
          if (child.nodeType == 1 && child.tagName != '!') results.push(child);
      }
      return results;
    },

    adjacent: function(nodes) {
      for (var i = 0, results = [], node; node = nodes[i]; i++) {
        var next = this.nextElementSibling(node);
        if (next) results.push(next);
      }
      return results;
    },

    laterSibling: function(nodes) {
      var h = Selector.handlers;
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        h.concat(results, Element.nextSiblings(node));
      return results;
    },

    nextElementSibling: function(node) {
      while (node = node.nextSibling)
        if (node.nodeType == 1) return node;
      return null;
    },

    previousElementSibling: function(node) {
      while (node = node.previousSibling)
        if (node.nodeType == 1) return node;
      return null;
    },

    tagName: function(nodes, root, tagName, combinator) {
      var uTagName = tagName.toUpperCase();
      var results = [], h = Selector.handlers;
      if (nodes) {
        if (combinator) {
          if (combinator == "descendant") {
            for (var i = 0, node; node = nodes[i]; i++)
              h.concat(results, node.getElementsByTagName(tagName));
            return results;
          } else nodes = this[combinator](nodes);
          if (tagName == "*") return nodes;
        }
        for (var i = 0, node; node = nodes[i]; i++)
          if (node.tagName.toUpperCase() === uTagName) results.push(node);
        return results;
      } else return root.getElementsByTagName(tagName);
    },

    id: function(nodes, root, id, combinator) {
      var targetNode = $(id), h = Selector.handlers;

      if (root == document) {
        if (!targetNode) return [];
        if (!nodes) return [targetNode];
      } else {
        if (!root.sourceIndex || root.sourceIndex < 1) {
          var nodes = root.getElementsByTagName('*');
          for (var j = 0, node; node = nodes[j]; j++) {
            if (node.id === id) return [node];
          }
        }
      }

      if (nodes) {
        if (combinator) {
          if (combinator == 'child') {
            for (var i = 0, node; node = nodes[i]; i++)
              if (targetNode.parentNode == node) return [targetNode];
          } else if (combinator == 'descendant') {
            for (var i = 0, node; node = nodes[i]; i++)
              if (Element.descendantOf(targetNode, node)) return [targetNode];
          } else if (combinator == 'adjacent') {
            for (var i = 0, node; node = nodes[i]; i++)
              if (Selector.handlers.previousElementSibling(targetNode) == node)
                return [targetNode];
          } else nodes = h[combinator](nodes);
        }
        for (var i = 0, node; node = nodes[i]; i++)
          if (node == targetNode) return [targetNode];
        return [];
      }
      return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
    },

    className: function(nodes, root, className, combinator) {
      if (nodes && combinator) nodes = this[combinator](nodes);
      return Selector.handlers.byClassName(nodes, root, className);
    },

    byClassName: function(nodes, root, className) {
      if (!nodes) nodes = Selector.handlers.descendant([root]);
      var needle = ' ' + className + ' ';
      for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
        nodeClassName = node.className;
        if (nodeClassName.length == 0) continue;
        if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
          results.push(node);
      }
      return results;
    },

    attrPresence: function(nodes, root, attr, combinator) {
      if (!nodes) nodes = root.getElementsByTagName("*");
      if (nodes && combinator) nodes = this[combinator](nodes);
      var results = [];
      for (var i = 0, node; node = nodes[i]; i++)
        if (Element.hasAttribute(node, attr)) results.push(node);
      return results;
    },

    attr: function(nodes, root, attr, value, operator, combinator) {
      if (!nodes) nodes = root.getElementsByTagName("*");
      if (nodes && combinator) nodes = this[combinator](nodes);
      var handler = Selector.operators[operator], results = [];
      for (var i = 0, node; node = nodes[i]; i++) {
        var nodeValue = Element.readAttribute(node, attr);
        if (nodeValue === null) continue;
        if (handler(nodeValue, value)) results.push(node);
      }
      return results;
    },

    pseudo: function(nodes, name, value, root, combinator) {
      if (nodes && combinator) nodes = this[combinator](nodes);
      if (!nodes) nodes = root.getElementsByTagName("*");
      return Selector.pseudos[name](nodes, value, root);
    }
  },

  pseudos: {
    'first-child': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++) {
        if (Selector.handlers.previousElementSibling(node)) continue;
          results.push(node);
      }
      return results;
    },
    'last-child': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++) {
        if (Selector.handlers.nextElementSibling(node)) continue;
          results.push(node);
      }
      return results;
    },
    'only-child': function(nodes, value, root) {
      var h = Selector.handlers;
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
          results.push(node);
      return results;
    },
    'nth-child':        function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, formula, root);
    },
    'nth-last-child':   function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, formula, root, true);
    },
    'nth-of-type':      function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, formula, root, false, true);
    },
    'nth-last-of-type': function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, formula, root, true, true);
    },
    'first-of-type':    function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, "1", root, false, true);
    },
    'last-of-type':     function(nodes, formula, root) {
      return Selector.pseudos.nth(nodes, "1", root, true, true);
    },
    'only-of-type':     function(nodes, formula, root) {
      var p = Selector.pseudos;
      return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
    },

    getIndices: function(a, b, total) {
      if (a == 0) return b > 0 ? [b] : [];
      return $R(1, total).inject([], function(memo, i) {
        if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
        return memo;
      });
    },

    nth: function(nodes, formula, root, reverse, ofType) {
      if (nodes.length == 0) return [];
      if (formula == 'even') formula = '2n+0';
      if (formula == 'odd')  formula = '2n+1';
      var h = Selector.handlers, results = [], indexed = [], m;
      h.mark(nodes);
      for (var i = 0, node; node = nodes[i]; i++) {
        if (!node.parentNode._countedByPrototype) {
          h.index(node.parentNode, reverse, ofType);
          indexed.push(node.parentNode);
        }
      }
      if (formula.match(/^\d+$/)) { // just a number
        formula = Number(formula);
        for (var i = 0, node; node = nodes[i]; i++)
          if (node.nodeIndex == formula) results.push(node);
      } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
        if (m[1] == "-") m[1] = -1;
        var a = m[1] ? Number(m[1]) : 1;
        var b = m[2] ? Number(m[2]) : 0;
        var indices = Selector.pseudos.getIndices(a, b, nodes.length);
        for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
          for (var j = 0; j < l; j++)
            if (node.nodeIndex == indices[j]) results.push(node);
        }
      }
      h.unmark(nodes);
      h.unmark(indexed);
      return results;
    },

    'empty': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++) {
        if (node.tagName == '!' || node.firstChild) continue;
        results.push(node);
      }
      return results;
    },

    'not': function(nodes, selector, root) {
      var h = Selector.handlers, selectorType, m;
      var exclusions = new Selector(selector).findElements(root);
      h.mark(exclusions);
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        if (!node._countedByPrototype) results.push(node);
      h.unmark(exclusions);
      return results;
    },

    'enabled': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        if (!node.disabled && (!node.type || node.type !== 'hidden'))
          results.push(node);
      return results;
    },

    'disabled': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        if (node.disabled) results.push(node);
      return results;
    },

    'checked': function(nodes, value, root) {
      for (var i = 0, results = [], node; node = nodes[i]; i++)
        if (node.checked) results.push(node);
      return results;
    }
  },

  operators: {
    '=':  function(nv, v) { return nv == v; },
    '!=': function(nv, v) { return nv != v; },
    '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); },
    '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
    '*=': function(nv, v) { return nv == v || nv && nv.include(v); },
    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
    '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() +
     '-').include('-' + (v || "").toUpperCase() + '-'); }
  },

  split: function(expression) {
    var expressions = [];
    expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
      expressions.push(m[1].strip());
    });
    return expressions;
  },

  matchElements: function(elements, expression) {
    var matches = $$(expression), h = Selector.handlers;
    h.mark(matches);
    for (var i = 0, results = [], element; element = elements[i]; i++)
      if (element._countedByPrototype) results.push(element);
    h.unmark(matches);
    return results;
  },

  findElement: function(elements, expression, index) {
    if (Object.isNumber(expression)) {
      index = expression; expression = false;
    }
    return Selector.matchElements(elements, expression || '*')[index || 0];
  },

  findChildElements: function(element, expressions) {
    expressions = Selector.split(expressions.join(','));
    var results = [], h = Selector.handlers;
    for (var i = 0, l = expressions.length, selector; i < l; i++) {
      selector = new Selector(expressions[i].strip());
      h.concat(results, selector.findElements(element));
    }
    return (l > 1) ? h.unique(results) : results;
  }
});

if (Prototype.Browser.IE) {
  Object.extend(Selector.handlers, {
    concat: function(a, b) {
      for (var i = 0, node; node = b[i]; i++)
        if (node.tagName !== "!") a.push(node);
      return a;
    },

    unmark: function(nodes) {
      for (var i = 0, node; node = nodes[i]; i++)
        node.removeAttribute('_countedByPrototype');
      return nodes;
    }
  });
}

function $$() {
  return Selector.findChildElements(document, $A(arguments));
}

var Form = {
  reset: function(form) {
    form = $(form);
    form.reset();
    return form;
  },

  serializeElements: function(elements, options) {
    if (typeof options != 'object') options = { hash: !!options };
    else if (Object.isUndefined(options.hash)) options.hash = true;
    var key, value, submitted = false, submit = options.submit;

    var data = elements.inject({ }, function(result, element) {
      if (!element.disabled && element.name) {
        key = element.name; value = $(element).getValue();
        if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
            submit !== false && (!submit || key == submit) && (submitted = true)))) {
          if (key in result) {
            if (!Object.isArray(result[key])) result[key] = [result[key]];
            result[key].push(value);
          }
          else result[key] = value;
        }
      }
      return result;
    });

    return options.hash ? data : Object.toQueryString(data);
  }
};

Form.Methods = {
  serialize: function(form, options) {
    return Form.serializeElements(Form.getElements(form), options);
  },

  getElements: function(form) {
    var elements = $(form).getElementsByTagName('*'),
        element,
        arr = [ ],
        serializers = Form.Element.Serializers;
    for (var i = 0; element = elements[i]; i++) {
      arr.push(element);
    }
    return arr.inject([], function(elements, child) {
      if (serializers[child.tagName.toLowerCase()])
        elements.push(Element.extend(child));
      return elements;
    })
  },

  getInputs: function(form, typeName, name) {
    form = $(form);
    var inputs = form.getElementsByTagName('input');

    if (!typeName && !name) return $A(inputs).map(Element.extend);

    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
      var input = inputs[i];
      if ((typeName && input.type != typeName) || (name && input.name != name))
        continue;
      matchingInputs.push(Element.extend(input));
    }

    return matchingInputs;
  },

  disable: function(form) {
    form = $(form);
    Form.getElements(form).invoke('disable');
    return form;
  },

  enable: function(form) {
    form = $(form);
    Form.getElements(form).invoke('enable');
    return form;
  },

  findFirstElement: function(form) {
    var elements = $(form).getElements().findAll(function(element) {
      return 'hidden' != element.type && !element.disabled;
    });
    var firstByIndex = elements.findAll(function(element) {
      return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
    }).sortBy(function(element) { return element.tabIndex }).first();

    return firstByIndex ? firstByIndex : elements.find(function(element) {
      return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
    });
  },

  focusFirstElement: function(form) {
    form = $(form);
    form.findFirstElement().activate();
    return form;
  },

  request: function(form, options) {
    form = $(form), options = Object.clone(options || { });

    var params = options.parameters, action = form.readAttribute('action') || '';
    if (action.blank()) action = window.location.href;
    options.parameters = form.serialize(true);

    if (params) {
      if (Object.isString(params)) params = params.toQueryParams();
      Object.extend(options.parameters, params);
    }

    if (form.hasAttribute('method') && !options.method)
      options.method = form.method;

    return new Ajax.Request(action, options);
  }
};

/*--------------------------------------------------------------------------*/


Form.Element = {
  focus: function(element) {
    $(element).focus();
    return element;
  },

  select: function(element) {
    $(element).select();
    return element;
  }
};

Form.Element.Methods = {

  serialize: function(element) {
    element = $(element);
    if (!element.disabled && element.name) {
      var value = element.getValue();
      if (value != undefined) {
        var pair = { };
        pair[element.name] = value;
        return Object.toQueryString(pair);
      }
    }
    return '';
  },

  getValue: function(element) {
    element = $(element);
    var method = element.tagName.toLowerCase();
    return Form.Element.Serializers[method](element);
  },

  setValue: function(element, value) {
    element = $(element);
    var method = element.tagName.toLowerCase();
    Form.Element.Serializers[method](element, value);
    return element;
  },

  clear: function(element) {
    $(element).value = '';
    return element;
  },

  present: function(element) {
    return $(element).value != '';
  },

  activate: function(element) {
    element = $(element);
    try {
      element.focus();
      if (element.select && (element.tagName.toLowerCase() != 'input' ||
          !['button', 'reset', 'submit'].include(element.type)))
        element.select();
    } catch (e) { }
    return element;
  },

  disable: function(element) {
    element = $(element);
    element.disabled = true;
    return element;
  },

  enable: function(element) {
    element = $(element);
    element.disabled = false;
    return element;
  }
};

/*--------------------------------------------------------------------------*/

var Field = Form.Element;

var $F = Form.Element.Methods.getValue;

/*--------------------------------------------------------------------------*/

Form.Element.Serializers = {
  input: function(element, value) {
    switch (element.type.toLowerCase()) {
      case 'checkbox':
      case 'radio':
        return Form.Element.Serializers.inputSelector(element, value);
      default:
        return Form.Element.Serializers.textarea(element, value);
    }
  },

  inputSelector: function(element, value) {
    if (Object.isUndefined(value)) return element.checked ? element.value : null;
    else element.checked = !!value;
  },

  textarea: function(element, value) {
    if (Object.isUndefined(value)) return element.value;
    else element.value = value;
  },

  select: function(element, value) {
    if (Object.isUndefined(value))
      return this[element.type == 'select-one' ?
        'selectOne' : 'selectMany'](element);
    else {
      var opt, currentValue, single = !Object.isArray(value);
      for (var i = 0, length = element.length; i < length; i++) {
        opt = element.options[i];
        currentValue = this.optionValue(opt);
        if (single) {
          if (currentValue == value) {
            opt.selected = true;
            return;
          }
        }
        else opt.selected = value.include(currentValue);
      }
    }
  },

  selectOne: function(element) {
    var index = element.selectedIndex;
    return index >= 0 ? this.optionValue(element.options[index]) : null;
  },

  selectMany: function(element) {
    var values, length = element.length;
    if (!length) return null;

    for (var i = 0, values = []; i < length; i++) {
      var opt = element.options[i];
      if (opt.selected) values.push(this.optionValue(opt));
    }
    return values;
  },

  optionValue: function(opt) {
    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
  }
};

/*--------------------------------------------------------------------------*/


Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
  initialize: function($super, element, frequency, callback) {
    $super(callback, frequency);
    this.element   = $(element);
    this.lastValue = this.getValue();
  },

  execute: function() {
    var value = this.getValue();
    if (Object.isString(this.lastValue) && Object.isString(value) ?
        this.lastValue != value : String(this.lastValue) != String(value)) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  }
});

Form.Element.Observer = Class.create(Abstract.TimedObserver, {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

Form.Observer = Class.create(Abstract.TimedObserver, {
  getValue: function() {
    return Form.serialize(this.element);
  }
});

/*--------------------------------------------------------------------------*/

Abstract.EventObserver = Class.create({
  initialize: function(element, callback) {
    this.element  = $(element);
    this.callback = callback;

    this.lastValue = this.getValue();
    if (this.element.tagName.toLowerCase() == 'form')
      this.registerFormCallbacks();
    else
      this.registerCallback(this.element);
  },

  onElementEvent: function() {
    var value = this.getValue();
    if (this.lastValue != value) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  },

  registerFormCallbacks: function() {
    Form.getElements(this.element).each(this.registerCallback, this);
  },

  registerCallback: function(element) {
    if (element.type) {
      switch (element.type.toLowerCase()) {
        case 'checkbox':
        case 'radio':
          Event.observe(element, 'click', this.onElementEvent.bind(this));
          break;
        default:
          Event.observe(element, 'change', this.onElementEvent.bind(this));
          break;
      }
    }
  }
});

Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

Form.EventObserver = Class.create(Abstract.EventObserver, {
  getValue: function() {
    return Form.serialize(this.element);
  }
});
(function() {

  var Event = {
    KEY_BACKSPACE: 8,
    KEY_TAB:       9,
    KEY_RETURN:   13,
    KEY_ESC:      27,
    KEY_LEFT:     37,
    KEY_UP:       38,
    KEY_RIGHT:    39,
    KEY_DOWN:     40,
    KEY_DELETE:   46,
    KEY_HOME:     36,
    KEY_END:      35,
    KEY_PAGEUP:   33,
    KEY_PAGEDOWN: 34,
    KEY_INSERT:   45,

    cache: {}
  };

  var _isButton;
  if (Prototype.Browser.IE) {
    var buttonMap = { 0: 1, 1: 4, 2: 2 };
    _isButton = function(event, code) {
      return event.button === buttonMap[code];
    };
  } else if (Prototype.Browser.WebKit) {
    _isButton = function(event, code) {
      switch (code) {
        case 0: return event.which == 1 && !event.metaKey;
        case 1: return event.which == 1 && event.metaKey;
        default: return false;
      }
    };
  } else {
    _isButton = function(event, code) {
      return event.which ? (event.which === code + 1) : (event.button === code);
    };
  }

  function isLeftClick(event)   { return _isButton(event, 0) }

  function isMiddleClick(event) { return _isButton(event, 1) }

  function isRightClick(event)  { return _isButton(event, 2) }

  function element(event) {
    event = Event.extend(event);

    var node = event.target, type = event.type,
     currentTarget = event.currentTarget;

    if (currentTarget && currentTarget.tagName) {
      if (type === 'load' || type === 'error' ||
        (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
          && currentTarget.type === 'radio'))
            node = currentTarget;
    }

    if (node.nodeType == Node.TEXT_NODE)
      node = node.parentNode;

    return Element.extend(node);
  }

  function findElement(event, expression) {
    var element = Event.element(event);
    if (!expression) return element;
    var elements = [element].concat(element.ancestors());
    return Selector.findElement(elements, expression, 0);
  }

  function pointer(event) {
    return { x: pointerX(event), y: pointerY(event) };
  }

  function pointerX(event) {
    var docElement = document.documentElement,
     body = document.body || { scrollLeft: 0 };

    return event.pageX || (event.clientX +
      (docElement.scrollLeft || body.scrollLeft) -
      (docElement.clientLeft || 0));
  }

  function pointerY(event) {
    var docElement = document.documentElement,
     body = document.body || { scrollTop: 0 };

    return  event.pageY || (event.clientY +
       (docElement.scrollTop || body.scrollTop) -
       (docElement.clientTop || 0));
  }


  function stop(event) {
    Event.extend(event);
    event.preventDefault();
    event.stopPropagation();

    event.stopped = true;
  }

  Event.Methods = {
    isLeftClick: isLeftClick,
    isMiddleClick: isMiddleClick,
    isRightClick: isRightClick,

    element: element,
    findElement: findElement,

    pointer: pointer,
    pointerX: pointerX,
    pointerY: pointerY,

    stop: stop
  };


  var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
    m[name] = Event.Methods[name].methodize();
    return m;
  });

  if (Prototype.Browser.IE) {
    function _relatedTarget(event) {
      var element;
      switch (event.type) {
        case 'mouseover': element = event.fromElement; break;
        case 'mouseout':  element = event.toElement;   break;
        default: return null;
      }
      return Element.extend(element);
    }

    Object.extend(methods, {
      stopPropagation: function() { this.cancelBubble = true },
      preventDefault:  function() { this.returnValue = false },
      inspect: function() { return '[object Event]' }
    });

    Event.extend = function(event, element) {
      if (!event) return false;
      if (event._extendedByPrototype) return event;

      event._extendedByPrototype = Prototype.emptyFunction;
      var pointer = Event.pointer(event);

      Object.extend(event, {
        target: event.srcElement || element,
        relatedTarget: _relatedTarget(event),
        pageX:  pointer.x,
        pageY:  pointer.y
      });

      return Object.extend(event, methods);
    };
  } else {
    Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
    Object.extend(Event.prototype, methods);
    Event.extend = Prototype.K;
  }

  function _createResponder(element, eventName, handler) {
    var registry = Element.retrieve(element, 'prototype_event_registry');

    if (Object.isUndefined(registry)) {
      CACHE.push(element);
      registry = Element.retrieve(element, 'prototype_event_registry', $H());
    }

    var respondersForEvent = registry.get(eventName);
    if (Object.isUndefined()) {
      respondersForEvent = [];
      registry.set(eventName, respondersForEvent);
    }

    if (respondersForEvent.pluck('handler').include(handler)) return false;

    var responder;
    if (eventName.include(":")) {
      responder = function(event) {
        if (Object.isUndefined(event.eventName))
          return false;

        if (event.eventName !== eventName)
          return false;

        Event.extend(event, element);
        handler.call(element, event);
      };
    } else {
      if (!Prototype.Browser.IE &&
       (eventName === "mouseenter" || eventName === "mouseleave")) {
        if (eventName === "mouseenter" || eventName === "mouseleave") {
          responder = function(event) {
            Event.extend(event, element);

            var parent = event.relatedTarget;
            while (parent && parent !== element) {
              try { parent = parent.parentNode; }
              catch(e) { parent = element; }
            }

            if (parent === element) return;

            handler.call(element, event);
          };
        }
      } else {
        responder = function(event) {
          Event.extend(event, element);
          handler.call(element, event);
        };
      }
    }

    responder.handler = handler;
    respondersForEvent.push(responder);
    return responder;
  }

  function _destroyCache() {
    for (var i = 0, length = CACHE.length; i < length; i++) {
      Event.stopObserving(CACHE[i]);
      CACHE[i] = null;
    }
  }

  var CACHE = [];

  if (Prototype.Browser.IE)
    window.attachEvent('onunload', _destroyCache);

  if (Prototype.Browser.WebKit)
    window.addEventListener('unload', Prototype.emptyFunction, false);


  var _getDOMEventName = Prototype.K;

  if (!Prototype.Browser.IE) {
    _getDOMEventName = function(eventName) {
      var translations = { mouseenter: "mouseover", mouseleave: "mouseout" };
      return eventName in translations ? translations[eventName] : eventName;
    };
  }

  function observe(element, eventName, handler) {
    element = $(element);

    var responder = _createResponder(element, eventName, handler);

    if (!responder) return element;

    if (eventName.include(':')) {
      if (element.addEventListener)
        element.addEventListener("dataavailable", responder, false);
      else {
        element.attachEvent("ondataavailable", responder);
        element.attachEvent("onfilterchange", responder);
      }
    } else {
      var actualEventName = _getDOMEventName(eventName);

      if (element.addEventListener)
        element.addEventListener(actualEventName, responder, false);
      else
        element.attachEvent("on" + actualEventName, responder);
    }

    return element;
  }

  function stopObserving(element, eventName, handler) {
    element = $(element);

    var registry = Element.retrieve(element, 'prototype_event_registry');

    if (Object.isUndefined(registry)) return element;

    if (eventName && !handler) {
      var responders = registry.get(eventName);

      if (Object.isUndefined(responders)) return element;

      responders.each( function(r) {
        Element.stopObserving(element, eventName, r.handler);
      });
      return element;
    } else if (!eventName) {
      registry.each( function(pair) {
        var eventName = pair.key, responders = pair.value;

        responders.each( function(r) {
          Element.stopObserving(element, eventName, r.handler);
        });
      });
      return element;
    }

    var responders = registry.get(eventName);

    if (!responders) return;

    var responder = responders.find( function(r) { return r.handler === handler; });
    if (!responder) return element;

    var actualEventName = _getDOMEventName(eventName);

    if (eventName.include(':')) {
      if (element.removeEventListener)
        element.removeEventListener("dataavailable", responder, false);
      else {
        element.detachEvent("ondataavailable", responder);
        element.detachEvent("onfilterchange",  responder);
      }
    } else {
      if (element.removeEventListener)
        element.removeEventListener(actualEventName, responder, false);
      else
        element.detachEvent('on' + actualEventName, responder);
    }

    registry.set(eventName, responders.without(responder));

    return element;
  }

  function fire(element, eventName, memo, bubble) {
    element = $(element);

    if (Object.isUndefined(bubble))
      bubble = true;

    if (element == document && document.createEvent && !element.dispatchEvent)
      element = document.documentElement;

    var event;
    if (document.createEvent) {
      event = document.createEvent('HTMLEvents');
      event.initEvent('dataavailable', true, true);
    } else {
      event = document.createEventObject();
      event.eventType = bubble ? 'ondataavailable' : 'onfilterchange';
    }

    event.eventName = eventName;
    event.memo = memo || { };

    if (document.createEvent)
      element.dispatchEvent(event);
    else
      element.fireEvent(event.eventType, event);

    return Event.extend(event);
  }


  Object.extend(Event, Event.Methods);

  Object.extend(Event, {
    fire:          fire,
    observe:       observe,
    stopObserving: stopObserving
  });

  Element.addMethods({
    fire:          fire,

    observe:       observe,

    stopObserving: stopObserving
  });

  Object.extend(document, {
    fire:          fire.methodize(),

    observe:       observe.methodize(),

    stopObserving: stopObserving.methodize(),

    loaded:        false
  });

  if (window.Event) Object.extend(window.Event, Event);
  else window.Event = Event;
})();

(function() {
  /* Support for the DOMContentLoaded event is based on work by Dan Webb,
     Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */

  var timer;

  function fireContentLoadedEvent() {
    if (document.loaded) return;
    if (timer) window.clearTimeout(timer);
    document.loaded = true;
    document.fire('dom:loaded');
  }

  function checkReadyState() {
    if (document.readyState === 'complete') {
      document.stopObserving('readystatechange', checkReadyState);
      fireContentLoadedEvent();
    }
  }

  function pollDoScroll() {
    try { document.documentElement.doScroll('left'); }
    catch(e) {
      timer = pollDoScroll.defer();
      return;
    }
    fireContentLoadedEvent();
  }

  if (document.addEventListener) {
    document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
  } else {
    document.observe('readystatechange', checkReadyState);
    if (window == top)
      timer = pollDoScroll.defer();
  }

  Event.observe(window, 'load', fireContentLoadedEvent);
})();

Element.addMethods();

/*------------------------------- DEPRECATED -------------------------------*/

Hash.toQueryString = Object.toQueryString;

var Toggle = { display: Element.toggle };

Element.Methods.childOf = Element.Methods.descendantOf;

var Insertion = {
  Before: function(element, content) {
    return Element.insert(element, {before:content});
  },

  Top: function(element, content) {
    return Element.insert(element, {top:content});
  },

  Bottom: function(element, content) {
    return Element.insert(element, {bottom:content});
  },

  After: function(element, content) {
    return Element.insert(element, {after:content});
  }
};

var $continue = new Error('"throw $continue" is deprecated, use "return" instead');

var Position = {
  includeScrollOffsets: false,

  prepare: function() {
    this.deltaX =  window.pageXOffset
                || document.documentElement.scrollLeft
                || document.body.scrollLeft
                || 0;
    this.deltaY =  window.pageYOffset
                || document.documentElement.scrollTop
                || document.body.scrollTop
                || 0;
  },

  within: function(element, x, y) {
    if (this.includeScrollOffsets)
      return this.withinIncludingScrolloffsets(element, x, y);
    this.xcomp = x;
    this.ycomp = y;
    this.offset = Element.cumulativeOffset(element);

    return (y >= this.offset[1] &&
            y <  this.offset[1] + element.offsetHeight &&
            x >= this.offset[0] &&
            x <  this.offset[0] + element.offsetWidth);
  },

  withinIncludingScrolloffsets: function(element, x, y) {
    var offsetcache = Element.cumulativeScrollOffset(element);

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

    return (this.ycomp >= this.offset[1] &&
            this.ycomp <  this.offset[1] + element.offsetHeight &&
            this.xcomp >= this.offset[0] &&
            this.xcomp <  this.offset[0] + element.offsetWidth);
  },

  overlap: function(mode, element) {
    if (!mode) return 0;
    if (mode == 'vertical')
      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
        element.offsetHeight;
    if (mode == 'horizontal')
      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
        element.offsetWidth;
  },


  cumulativeOffset: Element.Methods.cumulativeOffset,

  positionedOffset: Element.Methods.positionedOffset,

  absolutize: function(element) {
    Position.prepare();
    return Element.absolutize(element);
  },

  relativize: function(element) {
    Position.prepare();
    return Element.relativize(element);
  },

  realOffset: Element.Methods.cumulativeScrollOffset,

  offsetParent: Element.Methods.getOffsetParent,

  page: Element.Methods.viewportOffset,

  clone: function(source, target, options) {
    options = options || { };
    return Element.clonePosition(target, source, options);
  }
};

/*--------------------------------------------------------------------------*/

if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
  function iter(name) {
    return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
  }

  instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
  function(element, className) {
    className = className.toString().strip();
    var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
    return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
  } : function(element, className) {
    className = className.toString().strip();
    var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
    if (!classNames && !className) return elements;

    var nodes = $(element).getElementsByTagName('*');
    className = ' ' + className + ' ';

    for (var i = 0, child, cn; child = nodes[i]; i++) {
      if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
          (classNames && classNames.all(function(name) {
            return !name.toString().blank() && cn.include(' ' + name + ' ');
          }))))
        elements.push(Element.extend(child));
    }
    return elements;
  };

  return function(className, parentElement) {
    return $(parentElement || document.body).getElementsByClassName(className);
  };
}(Element.Methods);

/*--------------------------------------------------------------------------*/

Element.ClassNames = Class.create();
Element.ClassNames.prototype = {
  initialize: function(element) {
    this.element = $(element);
  },

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

  set: function(className) {
    this.element.className = className;
  },

  add: function(classNameToAdd) {
    if (this.include(classNameToAdd)) return;
    this.set($A(this).concat(classNameToAdd).join(' '));
  },

  remove: function(classNameToRemove) {
    if (!this.include(classNameToRemove)) return;
    this.set($A(this).without(classNameToRemove).join(' '));
  },

  toString: function() {
    return $A(this).join(' ');
  }
};

Object.extend(Element.ClassNames.prototype, Enumerable);

/*--------------------------------------------------------------------------*/
/*
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 2.5.1
*/
if(typeof YAHOO=="undefined"||!YAHOO){var YAHOO={};}YAHOO.namespace=function(){var A=arguments,E=null,C,B,D;for(C=0;C<A.length;C=C+1){D=A[C].split(".");E=YAHOO;for(B=(D[0]=="YAHOO")?1:0;B<D.length;B=B+1){E[D[B]]=E[D[B]]||{};E=E[D[B]];}}return E;};YAHOO.log=function(D,A,C){var B=YAHOO.widget.Logger;if(B&&B.log){return B.log(D,A,C);}else{return false;}};YAHOO.register=function(A,E,D){var I=YAHOO.env.modules;if(!I[A]){I[A]={versions:[],builds:[]};}var B=I[A],H=D.version,G=D.build,F=YAHOO.env.listeners;B.name=A;B.version=H;B.build=G;B.versions.push(H);B.builds.push(G);B.mainClass=E;for(var C=0;C<F.length;C=C+1){F[C](B);}if(E){E.VERSION=H;E.BUILD=G;}else{YAHOO.log("mainClass is undefined for module "+A,"warn");}};YAHOO.env=YAHOO.env||{modules:[],listeners:[]};YAHOO.env.getVersion=function(A){return YAHOO.env.modules[A]||null;};YAHOO.env.ua=function(){var C={ie:0,opera:0,gecko:0,webkit:0,mobile:null,air:0};var B=navigator.userAgent,A;if((/KHTML/).test(B)){C.webkit=1;}A=B.match(/AppleWebKit\/([^\s]*)/);if(A&&A[1]){C.webkit=parseFloat(A[1]);if(/ Mobile\//.test(B)){C.mobile="Apple";}else{A=B.match(/NokiaN[^\/]*/);if(A){C.mobile=A[0];}}A=B.match(/AdobeAIR\/([^\s]*)/);if(A){C.air=A[0];}}if(!C.webkit){A=B.match(/Opera[\s\/]([^\s]*)/);if(A&&A[1]){C.opera=parseFloat(A[1]);A=B.match(/Opera Mini[^;]*/);if(A){C.mobile=A[0];}}else{A=B.match(/MSIE\s([^;]*)/);if(A&&A[1]){C.ie=parseFloat(A[1]);}else{A=B.match(/Gecko\/([^\s]*)/);if(A){C.gecko=1;A=B.match(/rv:([^\s\)]*)/);if(A&&A[1]){C.gecko=parseFloat(A[1]);}}}}}return C;}();(function(){YAHOO.namespace("util","widget","example");if("undefined"!==typeof YAHOO_config){var B=YAHOO_config.listener,A=YAHOO.env.listeners,D=true,C;if(B){for(C=0;C<A.length;C=C+1){if(A[C]==B){D=false;break;}}if(D){A.push(B);}}}})();YAHOO.lang=YAHOO.lang||{isArray:function(B){if(B){var A=YAHOO.lang;return A.isNumber(B.length)&&A.isFunction(B.splice);}return false;},isBoolean:function(A){return typeof A==="boolean";},isFunction:function(A){return typeof A==="function";},isNull:function(A){return A===null;},isNumber:function(A){return typeof A==="number"&&isFinite(A);},isObject:function(A){return(A&&(typeof A==="object"||YAHOO.lang.isFunction(A)))||false;},isString:function(A){return typeof A==="string";},isUndefined:function(A){return typeof A==="undefined";},hasOwnProperty:function(A,B){if(Object.prototype.hasOwnProperty){return A.hasOwnProperty(B);}return !YAHOO.lang.isUndefined(A[B])&&A.constructor.prototype[B]!==A[B];},_IEEnumFix:function(C,B){if(YAHOO.env.ua.ie){var E=["toString","valueOf"],A;for(A=0;A<E.length;A=A+1){var F=E[A],D=B[F];if(YAHOO.lang.isFunction(D)&&D!=Object.prototype[F]){C[F]=D;}}}},extend:function(D,E,C){if(!E||!D){throw new Error("YAHOO.lang.extend failed, please check that "+"all dependencies are included.");}var B=function(){};B.prototype=E.prototype;D.prototype=new B();D.prototype.constructor=D;D.superclass=E.prototype;if(E.prototype.constructor==Object.prototype.constructor){E.prototype.constructor=E;}if(C){for(var A in C){D.prototype[A]=C[A];}YAHOO.lang._IEEnumFix(D.prototype,C);}},augmentObject:function(E,D){if(!D||!E){throw new Error("Absorb failed, verify dependencies.");}var A=arguments,C,F,B=A[2];if(B&&B!==true){for(C=2;C<A.length;C=C+1){E[A[C]]=D[A[C]];}}else{for(F in D){if(B||!E[F]){E[F]=D[F];}}YAHOO.lang._IEEnumFix(E,D);}},augmentProto:function(D,C){if(!C||!D){throw new Error("Augment failed, verify dependencies.");}var A=[D.prototype,C.prototype];for(var B=2;B<arguments.length;B=B+1){A.push(arguments[B]);}YAHOO.lang.augmentObject.apply(this,A);},dump:function(A,G){var C=YAHOO.lang,D,F,I=[],J="{...}",B="f(){...}",H=", ",E=" => ";if(!C.isObject(A)){return A+"";}else{if(A instanceof Date||("nodeType" in A&&"tagName" in A)){return A;}else{if(C.isFunction(A)){return B;}}}G=(C.isNumber(G))?G:3;if(C.isArray(A)){I.push("[");for(D=0,F=A.length;D<F;D=D+1){if(C.isObject(A[D])){I.push((G>0)?C.dump(A[D],G-1):J);}else{I.push(A[D]);}I.push(H);}if(I.length>1){I.pop();}I.push("]");}else{I.push("{");for(D in A){if(C.hasOwnProperty(A,D)){I.push(D+E);if(C.isObject(A[D])){I.push((G>0)?C.dump(A[D],G-1):J);}else{I.push(A[D]);}I.push(H);}}if(I.length>1){I.pop();}I.push("}");}return I.join("");},substitute:function(Q,B,J){var G,F,E,M,N,P,D=YAHOO.lang,L=[],C,H="dump",K=" ",A="{",O="}";for(;;){G=Q.lastIndexOf(A);if(G<0){break;}F=Q.indexOf(O,G);if(G+1>=F){break;}C=Q.substring(G+1,F);M=C;P=null;E=M.indexOf(K);if(E>-1){P=M.substring(E+1);M=M.substring(0,E);}N=B[M];if(J){N=J(M,N,P);}if(D.isObject(N)){if(D.isArray(N)){N=D.dump(N,parseInt(P,10));}else{P=P||"";var I=P.indexOf(H);if(I>-1){P=P.substring(4);}if(N.toString===Object.prototype.toString||I>-1){N=D.dump(N,parseInt(P,10));}else{N=N.toString();}}}else{if(!D.isString(N)&&!D.isNumber(N)){N="~-"+L.length+"-~";L[L.length]=C;}}Q=Q.substring(0,G)+N+Q.substring(F+1);}for(G=L.length-1;G>=0;G=G-1){Q=Q.replace(new RegExp("~-"+G+"-~"),"{"+L[G]+"}","g");}return Q;},trim:function(A){try{return A.replace(/^\s+|\s+$/g,"");}catch(B){return A;}},merge:function(){var D={},B=arguments;for(var C=0,A=B.length;C<A;C=C+1){YAHOO.lang.augmentObject(D,B[C],true);}return D;},later:function(H,B,I,D,E){H=H||0;B=B||{};var C=I,G=D,F,A;if(YAHOO.lang.isString(I)){C=B[I];}if(!C){throw new TypeError("method undefined");}if(!YAHOO.lang.isArray(G)){G=[D];}F=function(){C.apply(B,G);};A=(E)?setInterval(F,H):setTimeout(F,H);return{interval:E,cancel:function(){if(this.interval){clearInterval(A);}else{clearTimeout(A);}}};},isValue:function(B){var A=YAHOO.lang;return(A.isObject(B)||A.isString(B)||A.isNumber(B)||A.isBoolean(B));}};YAHOO.util.Lang=YAHOO.lang;YAHOO.lang.augment=YAHOO.lang.augmentProto;YAHOO.augment=YAHOO.lang.augmentProto;YAHOO.extend=YAHOO.lang.extend;YAHOO.register("yahoo",YAHOO,{version:"2.5.1",build:"984"});/*
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 2.5.1
*/
YAHOO.util.CustomEvent=function(D,B,C,A){this.type=D;this.scope=B||window;this.silent=C;this.signature=A||YAHOO.util.CustomEvent.LIST;this.subscribers=[];if(!this.silent){}var E="_YUICEOnSubscribe";if(D!==E){this.subscribeEvent=new YAHOO.util.CustomEvent(E,this,true);}this.lastError=null;};YAHOO.util.CustomEvent.LIST=0;YAHOO.util.CustomEvent.FLAT=1;YAHOO.util.CustomEvent.prototype={subscribe:function(B,C,A){if(!B){throw new Error("Invalid callback for subscriber to '"+this.type+"'");}if(this.subscribeEvent){this.subscribeEvent.fire(B,C,A);}this.subscribers.push(new YAHOO.util.Subscriber(B,C,A));},unsubscribe:function(D,F){if(!D){return this.unsubscribeAll();}var E=false;for(var B=0,A=this.subscribers.length;B<A;++B){var C=this.subscribers[B];if(C&&C.contains(D,F)){this._delete(B);E=true;}}return E;},fire:function(){var D=this.subscribers.length;if(!D&&this.silent){return true;}var H=[].slice.call(arguments,0),F=true,C,I=false;if(!this.silent){}var B=this.subscribers.slice();for(C=0;C<D;++C){var K=B[C];if(!K){I=true;}else{if(!this.silent){}var J=K.getScope(this.scope);if(this.signature==YAHOO.util.CustomEvent.FLAT){var A=null;if(H.length>0){A=H[0];}try{F=K.fn.call(J,A,K.obj);}catch(E){this.lastError=E;}}else{try{F=K.fn.call(J,this.type,H,K.obj);}catch(G){this.lastError=G;}}if(false===F){if(!this.silent){}return false;}}}return true;},unsubscribeAll:function(){for(var A=this.subscribers.length-1;A>-1;A--){this._delete(A);}this.subscribers=[];return A;},_delete:function(A){var B=this.subscribers[A];if(B){delete B.fn;delete B.obj;}this.subscribers.splice(A,1);},toString:function(){return"CustomEvent: "+"'"+this.type+"', "+"scope: "+this.scope;}};YAHOO.util.Subscriber=function(B,C,A){this.fn=B;this.obj=YAHOO.lang.isUndefined(C)?null:C;this.override=A;};YAHOO.util.Subscriber.prototype.getScope=function(A){if(this.override){if(this.override===true){return this.obj;}else{return this.override;}}return A;};YAHOO.util.Subscriber.prototype.contains=function(A,B){if(B){return(this.fn==A&&this.obj==B);}else{return(this.fn==A);}};YAHOO.util.Subscriber.prototype.toString=function(){return"Subscriber { obj: "+this.obj+", override: "+(this.override||"no")+" }";};if(!YAHOO.util.Event){YAHOO.util.Event=function(){var H=false;var I=[];var J=[];var G=[];var E=[];var C=0;var F=[];var B=[];var A=0;var D={63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9};return{POLL_RETRYS:2000,POLL_INTERVAL:20,EL:0,TYPE:1,FN:2,WFN:3,UNLOAD_OBJ:3,ADJ_SCOPE:4,OBJ:5,OVERRIDE:6,lastError:null,isSafari:YAHOO.env.ua.webkit,webkit:YAHOO.env.ua.webkit,isIE:YAHOO.env.ua.ie,_interval:null,_dri:null,DOMReady:false,startInterval:function(){if(!this._interval){var K=this;var L=function(){K._tryPreloadAttach();};this._interval=setInterval(L,this.POLL_INTERVAL);}},onAvailable:function(P,M,Q,O,N){var K=(YAHOO.lang.isString(P))?[P]:P;for(var L=0;L<K.length;L=L+1){F.push({id:K[L],fn:M,obj:Q,override:O,checkReady:N});}C=this.POLL_RETRYS;this.startInterval();},onContentReady:function(M,K,N,L){this.onAvailable(M,K,N,L,true);},onDOMReady:function(K,M,L){if(this.DOMReady){setTimeout(function(){var N=window;if(L){if(L===true){N=M;}else{N=L;}}K.call(N,"DOMReady",[],M);},0);}else{this.DOMReadyEvent.subscribe(K,M,L);}},addListener:function(M,K,V,Q,L){if(!V||!V.call){return false;}if(this._isValidCollection(M)){var W=true;for(var R=0,T=M.length;R<T;++R){W=this.on(M[R],K,V,Q,L)&&W;}return W;}else{if(YAHOO.lang.isString(M)){var P=this.getEl(M);if(P){M=P;}else{this.onAvailable(M,function(){YAHOO.util.Event.on(M,K,V,Q,L);});return true;}}}if(!M){return false;}if("unload"==K&&Q!==this){J[J.length]=[M,K,V,Q,L];return true;}var Y=M;if(L){if(L===true){Y=Q;}else{Y=L;}}var N=function(Z){return V.call(Y,YAHOO.util.Event.getEvent(Z,M),Q);};var X=[M,K,V,N,Y,Q,L];var S=I.length;I[S]=X;if(this.useLegacyEvent(M,K)){var O=this.getLegacyIndex(M,K);if(O==-1||M!=G[O][0]){O=G.length;B[M.id+K]=O;G[O]=[M,K,M["on"+K]];E[O]=[];M["on"+K]=function(Z){YAHOO.util.Event.fireLegacyEvent(YAHOO.util.Event.getEvent(Z),O);};}E[O].push(X);}else{try{this._simpleAdd(M,K,N,false);}catch(U){this.lastError=U;this.removeListener(M,K,V);return false;}}return true;},fireLegacyEvent:function(O,M){var Q=true,K,S,R,T,P;S=E[M].slice();for(var L=0,N=S.length;L<N;++L){R=S[L];if(R&&R[this.WFN]){T=R[this.ADJ_SCOPE];P=R[this.WFN].call(T,O);Q=(Q&&P);}}K=G[M];if(K&&K[2]){K[2](O);}return Q;},getLegacyIndex:function(L,M){var K=this.generateId(L)+M;if(typeof B[K]=="undefined"){return -1;}else{return B[K];}},useLegacyEvent:function(L,M){if(this.webkit&&("click"==M||"dblclick"==M)){var K=parseInt(this.webkit,10);if(!isNaN(K)&&K<418){return true;}}return false;},removeListener:function(L,K,T){var O,R,V;if(typeof L=="string"){L=this.getEl(L);}else{if(this._isValidCollection(L)){var U=true;for(O=L.length-1;O>-1;O--){U=(this.removeListener(L[O],K,T)&&U);}return U;}}if(!T||!T.call){return this.purgeElement(L,false,K);}if("unload"==K){for(O=J.length-1;O>-1;O--){V=J[O];if(V&&V[0]==L&&V[1]==K&&V[2]==T){J.splice(O,1);return true;}}return false;}var P=null;var Q=arguments[3];if("undefined"===typeof Q){Q=this._getCacheIndex(L,K,T);}if(Q>=0){P=I[Q];}if(!L||!P){return false;}if(this.useLegacyEvent(L,K)){var N=this.getLegacyIndex(L,K);var M=E[N];if(M){for(O=0,R=M.length;O<R;++O){V=M[O];if(V&&V[this.EL]==L&&V[this.TYPE]==K&&V[this.FN]==T){M.splice(O,1);break;}}}}else{try{this._simpleRemove(L,K,P[this.WFN],false);}catch(S){this.lastError=S;return false;}}delete I[Q][this.WFN];delete I[Q][this.FN];I.splice(Q,1);return true;},getTarget:function(M,L){var K=M.target||M.srcElement;return this.resolveTextNode(K);},resolveTextNode:function(L){try{if(L&&3==L.nodeType){return L.parentNode;}}catch(K){}return L;},getPageX:function(L){var K=L.pageX;if(!K&&0!==K){K=L.clientX||0;if(this.isIE){K+=this._getScrollLeft();}}return K;},getPageY:function(K){var L=K.pageY;if(!L&&0!==L){L=K.clientY||0;if(this.isIE){L+=this._getScrollTop();}}return L;},getXY:function(K){return[this.getPageX(K),this.getPageY(K)];},getRelatedTarget:function(L){var K=L.relatedTarget;
if(!K){if(L.type=="mouseout"){K=L.toElement;}else{if(L.type=="mouseover"){K=L.fromElement;}}}return this.resolveTextNode(K);},getTime:function(M){if(!M.time){var L=new Date().getTime();try{M.time=L;}catch(K){this.lastError=K;return L;}}return M.time;},stopEvent:function(K){this.stopPropagation(K);this.preventDefault(K);},stopPropagation:function(K){if(K.stopPropagation){K.stopPropagation();}else{K.cancelBubble=true;}},preventDefault:function(K){if(K.preventDefault){K.preventDefault();}else{K.returnValue=false;}},getEvent:function(M,K){var L=M||window.event;if(!L){var N=this.getEvent.caller;while(N){L=N.arguments[0];if(L&&Event==L.constructor){break;}N=N.caller;}}return L;},getCharCode:function(L){var K=L.keyCode||L.charCode||0;if(YAHOO.env.ua.webkit&&(K in D)){K=D[K];}return K;},_getCacheIndex:function(O,P,N){for(var M=0,L=I.length;M<L;M=M+1){var K=I[M];if(K&&K[this.FN]==N&&K[this.EL]==O&&K[this.TYPE]==P){return M;}}return -1;},generateId:function(K){var L=K.id;if(!L){L="yuievtautoid-"+A;++A;K.id=L;}return L;},_isValidCollection:function(L){try{return(L&&typeof L!=="string"&&L.length&&!L.tagName&&!L.alert&&typeof L[0]!=="undefined");}catch(K){return false;}},elCache:{},getEl:function(K){return(typeof K==="string")?document.getElementById(K):K;},clearCache:function(){},DOMReadyEvent:new YAHOO.util.CustomEvent("DOMReady",this),_load:function(L){if(!H){H=true;var K=YAHOO.util.Event;K._ready();K._tryPreloadAttach();}},_ready:function(L){var K=YAHOO.util.Event;if(!K.DOMReady){K.DOMReady=true;K.DOMReadyEvent.fire();K._simpleRemove(document,"DOMContentLoaded",K._ready);}},_tryPreloadAttach:function(){if(F.length===0){C=0;clearInterval(this._interval);this._interval=null;return ;}if(this.locked){return ;}if(this.isIE){if(!this.DOMReady){this.startInterval();return ;}}this.locked=true;var Q=!H;if(!Q){Q=(C>0&&F.length>0);}var P=[];var R=function(T,U){var S=T;if(U.override){if(U.override===true){S=U.obj;}else{S=U.override;}}U.fn.call(S,U.obj);};var L,K,O,N,M=[];for(L=0,K=F.length;L<K;L=L+1){O=F[L];if(O){N=this.getEl(O.id);if(N){if(O.checkReady){if(H||N.nextSibling||!Q){M.push(O);F[L]=null;}}else{R(N,O);F[L]=null;}}else{P.push(O);}}}for(L=0,K=M.length;L<K;L=L+1){O=M[L];R(this.getEl(O.id),O);}C--;if(Q){for(L=F.length-1;L>-1;L--){O=F[L];if(!O||!O.id){F.splice(L,1);}}this.startInterval();}else{clearInterval(this._interval);this._interval=null;}this.locked=false;},purgeElement:function(O,P,R){var M=(YAHOO.lang.isString(O))?this.getEl(O):O;var Q=this.getListeners(M,R),N,K;if(Q){for(N=Q.length-1;N>-1;N--){var L=Q[N];this.removeListener(M,L.type,L.fn);}}if(P&&M&&M.childNodes){for(N=0,K=M.childNodes.length;N<K;++N){this.purgeElement(M.childNodes[N],P,R);}}},getListeners:function(M,K){var P=[],L;if(!K){L=[I,J];}else{if(K==="unload"){L=[J];}else{L=[I];}}var R=(YAHOO.lang.isString(M))?this.getEl(M):M;for(var O=0;O<L.length;O=O+1){var T=L[O];if(T){for(var Q=0,S=T.length;Q<S;++Q){var N=T[Q];if(N&&N[this.EL]===R&&(!K||K===N[this.TYPE])){P.push({type:N[this.TYPE],fn:N[this.FN],obj:N[this.OBJ],adjust:N[this.OVERRIDE],scope:N[this.ADJ_SCOPE],index:Q});}}}}return(P.length)?P:null;},_unload:function(Q){var K=YAHOO.util.Event,N,M,L,P,O,R=J.slice();for(N=0,P=J.length;N<P;++N){L=R[N];if(L){var S=window;if(L[K.ADJ_SCOPE]){if(L[K.ADJ_SCOPE]===true){S=L[K.UNLOAD_OBJ];}else{S=L[K.ADJ_SCOPE];}}L[K.FN].call(S,K.getEvent(Q,L[K.EL]),L[K.UNLOAD_OBJ]);R[N]=null;L=null;S=null;}}J=null;if(I){for(M=I.length-1;M>-1;M--){L=I[M];if(L){K.removeListener(L[K.EL],L[K.TYPE],L[K.FN],M);}}L=null;}G=null;K._simpleRemove(window,"unload",K._unload);},_getScrollLeft:function(){return this._getScroll()[1];},_getScrollTop:function(){return this._getScroll()[0];},_getScroll:function(){var K=document.documentElement,L=document.body;if(K&&(K.scrollTop||K.scrollLeft)){return[K.scrollTop,K.scrollLeft];}else{if(L){return[L.scrollTop,L.scrollLeft];}else{return[0,0];}}},regCE:function(){},_simpleAdd:function(){if(window.addEventListener){return function(M,N,L,K){M.addEventListener(N,L,(K));};}else{if(window.attachEvent){return function(M,N,L,K){M.attachEvent("on"+N,L);};}else{return function(){};}}}(),_simpleRemove:function(){if(window.removeEventListener){return function(M,N,L,K){M.removeEventListener(N,L,(K));};}else{if(window.detachEvent){return function(L,M,K){L.detachEvent("on"+M,K);};}else{return function(){};}}}()};}();(function(){var EU=YAHOO.util.Event;EU.on=EU.addListener;
/* DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller */
if(EU.isIE){YAHOO.util.Event.onDOMReady(YAHOO.util.Event._tryPreloadAttach,YAHOO.util.Event,true);var n=document.createElement("p");EU._dri=setInterval(function(){try{n.doScroll("left");clearInterval(EU._dri);EU._dri=null;EU._ready();n=null;}catch(ex){}},EU.POLL_INTERVAL);}else{if(EU.webkit&&EU.webkit<525){EU._dri=setInterval(function(){var rs=document.readyState;if("loaded"==rs||"complete"==rs){clearInterval(EU._dri);EU._dri=null;EU._ready();}},EU.POLL_INTERVAL);}else{EU._simpleAdd(document,"DOMContentLoaded",EU._ready);}}EU._simpleAdd(window,"load",EU._load);EU._simpleAdd(window,"unload",EU._unload);EU._tryPreloadAttach();})();}YAHOO.util.EventProvider=function(){};YAHOO.util.EventProvider.prototype={__yui_events:null,__yui_subscribers:null,subscribe:function(A,C,F,E){this.__yui_events=this.__yui_events||{};var D=this.__yui_events[A];if(D){D.subscribe(C,F,E);}else{this.__yui_subscribers=this.__yui_subscribers||{};var B=this.__yui_subscribers;if(!B[A]){B[A]=[];}B[A].push({fn:C,obj:F,override:E});}},unsubscribe:function(C,E,G){this.__yui_events=this.__yui_events||{};var A=this.__yui_events;if(C){var F=A[C];if(F){return F.unsubscribe(E,G);}}else{var B=true;for(var D in A){if(YAHOO.lang.hasOwnProperty(A,D)){B=B&&A[D].unsubscribe(E,G);}}return B;}return false;},unsubscribeAll:function(A){return this.unsubscribe(A);},createEvent:function(G,D){this.__yui_events=this.__yui_events||{};var A=D||{};var I=this.__yui_events;if(I[G]){}else{var H=A.scope||this;var E=(A.silent);var B=new YAHOO.util.CustomEvent(G,H,E,YAHOO.util.CustomEvent.FLAT);
I[G]=B;if(A.onSubscribeCallback){B.subscribeEvent.subscribe(A.onSubscribeCallback);}this.__yui_subscribers=this.__yui_subscribers||{};var F=this.__yui_subscribers[G];if(F){for(var C=0;C<F.length;++C){B.subscribe(F[C].fn,F[C].obj,F[C].override);}}}return I[G];},fireEvent:function(E,D,A,C){this.__yui_events=this.__yui_events||{};var G=this.__yui_events[E];if(!G){return null;}var B=[];for(var F=1;F<arguments.length;++F){B.push(arguments[F]);}return G.fire.apply(G,B);},hasEvent:function(A){if(this.__yui_events){if(this.__yui_events[A]){return true;}}return false;}};YAHOO.util.KeyListener=function(A,F,B,C){if(!A){}else{if(!F){}else{if(!B){}}}if(!C){C=YAHOO.util.KeyListener.KEYDOWN;}var D=new YAHOO.util.CustomEvent("keyPressed");this.enabledEvent=new YAHOO.util.CustomEvent("enabled");this.disabledEvent=new YAHOO.util.CustomEvent("disabled");if(typeof A=="string"){A=document.getElementById(A);}if(typeof B=="function"){D.subscribe(B);}else{D.subscribe(B.fn,B.scope,B.correctScope);}function E(J,I){if(!F.shift){F.shift=false;}if(!F.alt){F.alt=false;}if(!F.ctrl){F.ctrl=false;}if(J.shiftKey==F.shift&&J.altKey==F.alt&&J.ctrlKey==F.ctrl){var G;if(F.keys instanceof Array){for(var H=0;H<F.keys.length;H++){G=F.keys[H];if(G==J.charCode){D.fire(J.charCode,J);break;}else{if(G==J.keyCode){D.fire(J.keyCode,J);break;}}}}else{G=F.keys;if(G==J.charCode){D.fire(J.charCode,J);}else{if(G==J.keyCode){D.fire(J.keyCode,J);}}}}}this.enable=function(){if(!this.enabled){YAHOO.util.Event.addListener(A,C,E);this.enabledEvent.fire(F);}this.enabled=true;};this.disable=function(){if(this.enabled){YAHOO.util.Event.removeListener(A,C,E);this.disabledEvent.fire(F);}this.enabled=false;};this.toString=function(){return"KeyListener ["+F.keys+"] "+A.tagName+(A.id?"["+A.id+"]":"");};};YAHOO.util.KeyListener.KEYDOWN="keydown";YAHOO.util.KeyListener.KEYUP="keyup";YAHOO.util.KeyListener.KEY={ALT:18,BACK_SPACE:8,CAPS_LOCK:20,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,META:224,NUM_LOCK:144,PAGE_DOWN:34,PAGE_UP:33,PAUSE:19,PRINTSCREEN:44,RIGHT:39,SCROLL_LOCK:145,SHIFT:16,SPACE:32,TAB:9,UP:38};YAHOO.register("event",YAHOO.util.Event,{version:"2.5.1",build:"984"});/*
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 2.5.1
*/
YAHOO.util.History=(function(){var C=null;var K=null;var F=false;var D=[];var B=[];function I(){var M,L;L=top.location.href;M=L.indexOf("#");return M>=0?L.substr(M+1):null;}function A(){var M,N,O=[],L=[];for(M in D){if(YAHOO.lang.hasOwnProperty(D,M)){N=D[M];O.push(M+"="+N.initialState);L.push(M+"="+N.currentState);}}K.value=O.join("&")+"|"+L.join("&");if(YAHOO.env.ua.webkit){K.value+="|"+B.join(",");}}function H(L){var Q,R,M,O,P,T,S,N;if(!L){for(M in D){if(YAHOO.lang.hasOwnProperty(D,M)){O=D[M];O.currentState=O.initialState;O.onStateChange(unescape(O.currentState));}}return ;}P=[];T=L.split("&");for(Q=0,R=T.length;Q<R;Q++){S=T[Q].split("=");if(S.length===2){M=S[0];N=S[1];P[M]=N;}}for(M in D){if(YAHOO.lang.hasOwnProperty(D,M)){O=D[M];N=P[M];if(!N||O.currentState!==N){O.currentState=N||O.initialState;O.onStateChange(unescape(O.currentState));}}}}function J(O){var L,N;L='<html><body><div id="state">'+O+"</div></body></html>";try{N=C.contentWindow.document;N.open();N.write(L);N.close();return true;}catch(M){return false;}}function G(){var O,L,N,M;if(!C.contentWindow||!C.contentWindow.document){setTimeout(G,10);return ;}O=C.contentWindow.document;L=O.getElementById("state");N=L?L.innerText:null;M=I();setInterval(function(){var U,Q,R,S,T,P;O=C.contentWindow.document;L=O.getElementById("state");U=L?L.innerText:null;T=I();if(U!==N){N=U;H(N);if(!N){Q=[];for(R in D){if(YAHOO.lang.hasOwnProperty(D,R)){S=D[R];Q.push(R+"="+S.initialState);}}T=Q.join("&");}else{T=N;}top.location.hash=T;M=T;A();}else{if(T!==M){M=T;J(T);}}},50);F=true;YAHOO.util.History.onLoadEvent.fire();}function E(){var S,U,Q,W,M,O,V,P,T,N,L,R;Q=K.value.split("|");if(Q.length>1){V=Q[0].split("&");for(S=0,U=V.length;S<U;S++){W=V[S].split("=");if(W.length===2){M=W[0];P=W[1];O=D[M];if(O){O.initialState=P;}}}T=Q[1].split("&");for(S=0,U=T.length;S<U;S++){W=T[S].split("=");if(W.length>=2){M=W[0];N=W[1];O=D[M];if(O){O.currentState=N;}}}}if(Q.length>2){B=Q[2].split(",");}if(YAHOO.env.ua.ie){G();}else{L=history.length;R=I();setInterval(function(){var Z,X,Y;X=I();Y=history.length;if(X!==R){R=X;L=Y;H(R);A();}else{if(Y!==L&&YAHOO.env.ua.webkit){R=X;L=Y;Z=B[L-1];H(Z);A();}}},50);F=true;YAHOO.util.History.onLoadEvent.fire();}}return{onLoadEvent:new YAHOO.util.CustomEvent("onLoad"),onReady:function(M,N,L){if(F){setTimeout(function(){var O=window;if(L){if(L===true){O=N;}else{O=L;}}M.call(O,"onLoad",[],N);},0);}else{YAHOO.util.History.onLoadEvent.subscribe(M,N,L);}},register:function(O,L,Q,R,N){var P,M;if(typeof O!=="string"||YAHOO.lang.trim(O)===""||typeof L!=="string"||typeof Q!=="function"){throw new Error("Missing or invalid argument");}if(D[O]){return ;}if(F){throw new Error("All modules must be registered before calling YAHOO.util.History.initialize");}O=escape(O);L=escape(L);P=null;if(N===true){P=R;}else{P=N;}M=function(S){return Q.call(P,S,R);};D[O]={name:O,initialState:L,currentState:L,onStateChange:M};},initialize:function(L,M){if(F){return ;}if(YAHOO.env.ua.opera){}if(typeof L==="string"){L=document.getElementById(L);}if(!L||L.tagName.toUpperCase()!=="TEXTAREA"&&(L.tagName.toUpperCase()!=="INPUT"||L.type!=="hidden"&&L.type!=="text")){throw new Error("Missing or invalid argument");}K=L;if(YAHOO.env.ua.ie){if(typeof M==="string"){M=document.getElementById(M);}if(!M||M.tagName.toUpperCase()!=="IFRAME"){throw new Error("Missing or invalid argument");}C=M;}YAHOO.util.Event.onDOMReady(E);},navigate:function(M,N){var L;if(typeof M!=="string"||typeof N!=="string"){throw new Error("Missing or invalid argument");}L={};L[M]=N;return YAHOO.util.History.multiNavigate(L);},multiNavigate:function(M){var L,N,P,O,Q;if(typeof M!=="object"){throw new Error("Missing or invalid argument");}if(!F){throw new Error("The Browser History Manager is not initialized");}for(N in M){if(!D[N]){throw new Error("The following module has not been registered: "+N);}}L=[];for(N in D){if(YAHOO.lang.hasOwnProperty(D,N)){P=D[N];if(YAHOO.lang.hasOwnProperty(M,N)){O=M[unescape(N)];}else{O=unescape(P.currentState);}N=escape(N);O=escape(O);L.push(N+"="+O);}}Q=L.join("&");if(YAHOO.env.ua.ie){return J(Q);}else{top.location.hash=Q;if(YAHOO.env.ua.webkit){B[history.length]=Q;A();}return true;}},getCurrentState:function(L){var M;if(typeof L!=="string"){throw new Error("Missing or invalid argument");}if(!F){throw new Error("The Browser History Manager is not initialized");}M=D[L];if(!M){throw new Error("No such registered module: "+L);}return unescape(M.currentState);},getBookmarkedState:function(Q){var P,M,L,S,N,R,O;if(typeof Q!=="string"){throw new Error("Missing or invalid argument");}L=top.location.href.indexOf("#");S=L>=0?top.location.href.substr(L+1):top.location.href;N=S.split("&");for(P=0,M=N.length;P<M;P++){R=N[P].split("=");if(R.length===2){O=R[0];if(O===Q){return unescape(R[1]);}}}return null;},getQueryStringParameter:function(Q,N){var O,M,L,S,R,P;N=N||top.location.href;L=N.indexOf("?");S=L>=0?N.substr(L+1):N;L=S.lastIndexOf("#");S=L>=0?S.substr(0,L):S;R=S.split("&");for(O=0,M=R.length;O<M;O++){P=R[O].split("=");if(P.length>=2){if(P[0]===Q){return unescape(P[1]);}}}return null;}};})();YAHOO.register("history",YAHOO.util.History,{version:"2.5.1",build:"984"});/**
 * reflection.js v1.9
 *
 * Contributors: Cow http://cow.neondragon.net
 *               Gfx http://www.jroller.com/page/gfx/
 *               Sitharus http://www.sitharus.com
 *               Andreas Linde http://www.andreaslinde.de
 *               Tralala, coder @ http://www.vbulletin.org
 *
 * Freely distributable under MIT-style license.
 */
 


var Reflection = {
	defaultHeight : 0.5,
	defaultOpacity: 0.5,
	
	add: function(image, options) {
		Reflection.remove(image);
		
		doptions = { "height" : Reflection.defaultHeight, "opacity" : Reflection.defaultOpacity }
		if (options) {
			for (var i in doptions) {
				if (!options[i]) {
					options[i] = doptions[i];
				}
			}
		} else {
			options = doptions;
		}
	
		try {
			var d = document.createElement('div');
			var p = image;
			
			var classes = p.className.split(' ');
			var newClasses = '';
			for (j=0;j<classes.length;j++) {
				if (classes[j] != "reflect") {
					if (newClasses) {
						newClasses += ' '
					}
					
					newClasses += classes[j];
				}
			}

			var reflectionHeight = Math.floor(p.height*options['height']);
			var divHeight = Math.floor(p.height*(1+options['height']));
			
			var reflectionWidth = p.width;
			
			if (document.all && !window.opera) {
				/* Fix hyperlinks */
                if(p.parentElement.tagName == 'A') {
	                var d = document.createElement('a');
	                d.href = p.parentElement.href;
                }  
                    
				/* Copy original image's classes & styles to div */
				d.className = newClasses;
				p.className = 'reflected';
				
				d.style.cssText = p.style.cssText;
				p.style.cssText = 'vertical-align: bottom';
			
				var reflection = document.createElement('img');
				reflection.src = p.src;
				reflection.style.width = reflectionWidth+'px';
				reflection.style.display = 'block';
				reflection.style.height = p.height+"px";
				
				reflection.style.marginBottom = "-"+(p.height-reflectionHeight)+'px';
				reflection.style.filter = 'flipv progid:DXImageTransform.Microsoft.Alpha(opacity='+(options['opacity']*100)+', style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy='+(options['height']*100)+')';
				
				d.style.width = reflectionWidth+'px';
				d.style.height = divHeight+'px';
				p.parentNode.replaceChild(d, p);
				
				d.appendChild(p);
				d.appendChild(reflection);
			} else {
				var canvas = document.createElement('canvas');
				if (canvas.getContext) {
					/* Copy original image's classes & styles to div */
					d.className = newClasses;
					p.className = 'reflected';
					
					d.style.cssText = p.style.cssText;
					p.style.cssText = 'vertical-align: bottom';
			
					var context = canvas.getContext("2d");
				
					canvas.style.height = reflectionHeight+'px';
					canvas.style.width = reflectionWidth+'px';
					canvas.height = reflectionHeight;
					canvas.width = reflectionWidth;
					
					d.style.width = reflectionWidth+'px';
					d.style.height = divHeight+'px';
					p.parentNode.replaceChild(d, p);
					
					d.appendChild(p);
					d.appendChild(canvas);
					
					context.save();
					
					context.translate(0,image.height-1);
					context.scale(1,-1);
					
					context.drawImage(image, 0, 0, reflectionWidth, image.height);
	
					context.restore();
					
					context.globalCompositeOperation = "destination-out";
					var gradient = context.createLinearGradient(0, 0, 0, reflectionHeight);
					
					gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)");
					gradient.addColorStop(0, "rgba(255, 255, 255, "+(1-options['opacity'])+")");
		
					context.fillStyle = gradient;
					if (navigator.appVersion.indexOf('WebKit') != -1) {
						context.fill();
					} else {
						context.fillRect(0, 0, reflectionWidth, reflectionHeight*2);
					}
				}
			}
		} catch (e) {
	    }
	},
	
	remove : function(image) {
		if (image.className == "reflected") {
			image.className = image.parentNode.className;
			image.parentNode.parentNode.replaceChild(image, image.parentNode);
		}
	}
}


function addReflections() {
	var rimages = document.getElementsByClassName('reflect');
	for (i=0;i<rimages.length;i++) {
		var rheight = null;
		var ropacity = null;
		
		var classes = rimages[i].className.split(' ');
		for (j=0;j<classes.length;j++) {
			if (classes[j].indexOf("rheight") == 0) {
				var rheight = classes[j].substring(7)/100;
			} else if (classes[j].indexOf("ropacity") == 0) {
				var ropacity = classes[j].substring(8)/100;
			}
		}
		
		Reflection.add(rimages[i], { height: rheight, opacity : ropacity});
	}
}

//var previousOnload = window.onload;
//window.onload = function () { if(previousOnload) previousOnload(); addReflections(); }
/** 
 * @fileoverview Contient des classes permettant de gÃ©rer les chargement (loading, curseur wait).
 * @author cutibipoulet@gmail.com pour rs2i / Pmu.fr
 * @version 0.1
 */
 
 /**
 * Permet de retourner un tableau avec la taille du document : [height,width]
 */
function getDocumentSize  (){return [document.viewport.getHeight(),document.viewport.getWidth() ];}
 
 
 
 
/**
 * Permet de gerer les differents loader ajax.
*/

function LoaderAjax(){} ;var LoaderAjax = Class.create();
/**
 * @constructor
 * @param divAMask la div a masquer par le loader
 */
LoaderAjax.prototype.initialize = function(divAMask,couleur) {
	
	if(couleur==undefined||couleur==null)couleur='';
	this.couleur=couleur;
	
	this.divAMask = divAMask;
	this.divAMaskElem = $(divAMask);
	//construction de la div de maskage : 
	var offset = Position.cumulativeOffset(this.divAMaskElem);
	var elementMask = new Element("div");
	$$('body')[0].insert(elementMask);
	elementMask.id="theMashfor_"+divAMask;
	this.mask = $("theMashfor_"+divAMask);
	this.mask.setStyle({position:"absolute",
					  	top:offset[1]+"px",left:offset[0]+"px",
					  	width:(this.divAMaskElem.getWidth()+2)+"px",height:(this.divAMaskElem.getHeight()+2)+"px",
					  	'z-index':"100",background:"#EAEAEA",
					  	opacity: ".8",filter: "alpha(opacity=80)"});
	this.mask.id="theMashfor_"+divAMask;
	var demilargeur = this.divAMaskElem.getWidth() / 2;
	var demihauteur = this.divAMaskElem.getHeight() / 2;
	this.mask.innerHTML = '<div style="margin-left:'+demilargeur+'px;margin-top:'+demihauteur+'px;" ><img src="/pmu/img/backgrounds/all/loaderAjax.gif" alt="chargement"  /></div>';
	this.mask.hide();
	
	document.body.insert(this.mask);
}

/**
 * Permet de rafraichir les proprietes du loader
 */
LoaderAjax.prototype.refresh = function (){
	this.divAMaskElem = $(this.divAMask);
	if(this.divAMaskElem!=null){
	var offset = Position.cumulativeOffset(this.divAMaskElem);
	this.mask.setStyle({position:"absolute",
					  	top:offset[1]+"px",left:offset[0]+"px",
					  	width:(this.divAMaskElem.getWidth()+2)+"px",height:(this.divAMaskElem.getHeight()+2)+"px"
					  	});
	var demilargeur = this.divAMaskElem.getWidth() / 2;
	var demihauteur = this.divAMaskElem.getHeight() / 2;
	this.mask.innerHTML = '<div style="margin-left:'+demilargeur+'px;margin-top:'+demihauteur+'px;" ><img src="/pmu/img/backgrounds/all/loaderAjax'+this.couleur+'.gif" alt="chargement"  /></div>';
	}
	return this;
}

/**
 * Permet d'afficher le loader uniquement si l'element a maskquer est visible 
 */
LoaderAjax.prototype.show = function (){
	if(this.divAMaskElem != null && this.divAMaskElem.visible() ==  true ) {
	this.mask.show();
	getWaitManager().wait();
	}
	return this;
}
/**
 * Permet de cacher le loader
 */
LoaderAjax.prototype.hide = function (){
	this.mask.hide();
	getWaitManager().unWait();
	return this;
}	




/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////     WAIT MANAGER                           ////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
/**
 * Classe qui permet de gÃ©rer les chargements : 
 */
var WaitManager = Class.create();
/**
 * crÃ©er l'overlay qui permettra d'afficher le curseur wait
 * @constructor 
 */
WaitManager.prototype.initialize = function() {
this.overlayWait=new Element("div");
this.overlayWait.setStyle({backgroundColor:'#EEEEEE',opacity:'0.00',cursor:'wait',position:'absolute',top:'0px',left:'0px','z-index':'100000'});
new Insertion.Bottom(document.getElementsByTagName('body')[0], this.overlayWait);
this.waiting=0;
//pooler pour gerer les attentes infinies.
this.errorPool =null;
//les ecouteurs : 
this.listenersOnLock=[];
}
/**
 * Rafraichit la zone d'overlay
 * @private
 */
WaitManager.prototype.refresh = function (){var dim=getDocumentSize();this.overlayWait.setStyle({width:dim[1]-20+'px',height:dim[0]+'px'});};
/**
 * Affiche le curseur wait
 */
WaitManager.prototype.wait = function(){
	
	//permet de delocker si la lock est trop grande.. (pour eviter les blocages en cas d'erreur) 4 secondes
	if(this.errorPool!=null)this.errorPool.stop();
	this.errorPool = new PeriodicalExecuter(this.unWaitBecauseError,4);
	
	this.waiting++;//un element de plus attend
	if(this.waiting>1){//on reaffiche que si cela n'est pas deja affiche
		this.refresh();this.overlayWait.style.display='block';
		//on dispatch
		for(var i=0;i<this.listenersOnLock.length;i++){
		this.listenersOnLock[i][0][this.listenersOnLock[i][1]]=true;//lockage de la propriete
		}
	}
}
/**
 * fait disparaitre le curseur wait
 */
WaitManager.prototype.unWait= function(){
	this.waiting--;
	if(this.waiting==0){//si plus d'elements en attente, on cache l'attente.
		this.overlayWait.style.display='none';
		//on dispatch
		for(var i=0;i<this.listenersOnLock.length;i++){
		this.listenersOnLock[i][0][this.listenersOnLock[i][1]]=false;//delockage de la propriete
		}
	}
}

/**
 * Permet de supprimer l'attente si celle ci a durÃ©e trop longtemps
 */
WaitManager.prototype.unWaitBecauseError = function (pE){
if(waitManager.errorPool!=null)
waitManager.errorPool.stop();
waitManager.waiting=1;
waitManager.unWait();
}

/***
 * Permet d'ajouter un ecouteur de l'etat de l'attente.
 * @param typeEvent : un string qui est : 'onlock' pour recevoir les evenements de lockage / delockage
 * @param o l'objet a mettre a jour
 * @param varName le nom de la variable a mettre a jour sur l'objet (boolean).
 * */
WaitManager.prototype.addEventListener = function(typeEvent,o,varName) {
	if(typeEvent=='onlock'){
		this.listenersOnLock.push([o,varName]);
	}

}


/**
 * singleton de gestionnaire de wait
 */
waitManager=null;
/**
 * singleton du manager de wait 
 * a instancier apres le chargement du HTML
 * @return WaitManager le gestionnaire d'attente
 */
function getWaitManager(){
	return (waitManager==null)?waitManager=new WaitManager():waitManager;
}/** 
 * @fileoverview Fichier contenant les classes ElementsSlider et ListeCliquable. Ces classes sont spï¿½cialisï¿½s dans
 * la gestion des listes.
 *
 * @author cutibipoulet@gmail.com
 * @version 0.1
 */



/**
 *  @class Classe qui permet de gerer le slider des elements dans un conteneur.<br />  
 *  Le slider permet d'afficher un nombre d'elements parmis une liste, et de faire defiler  les elements de cette liste.
 */
function ElementsSlider(){};
var ElementsSlider = Class.create();

/**
 * Permet d'initialiser le slider.
 * @param  theSlider le nom de la div contenant les elements du slider
 * @param  nbrElem le nombre d'elements a afficher
 * @param  lElement id de l'element permettant de faire defiler le slider vers la gauche
 * @param  rElement id de l'element permettant de faire defiler le slider vers la droite
 * @param ignoredClassNames, facultatif est la liste des Ã©lÃ©ment Ã  ne pas prendre en compte. Ceci est une classe CSS.
 * @constructor
 */
ElementsSlider.prototype.initialize = function(theSlider,nbrElem,lElement,rElement,ignoredClassNames) {

//TODO retirer la margin litÃ©ral de toute la classe 
this.hiddenMargin='-20000px';
this.leftElement = lElement;
this.rightElement = rElement;
this.slider = theSlider;
this.indice = 0;//pos actuelle du slider
this.nbrElements = nbrElem;
this.step=nbrElem;//nombre d'elements dÃ©placÃ©s quand on slide
this.elementsSlider = new Array();

//suppression des Ã©lÃ©ments non voulus : 
var elemsTmp = $(this.slider).childElements();
for (var i=0,max=elemsTmp.length;i<max;i++){
	if(!elemsTmp[i].hasClassName(ignoredClassNames) ){
	elemsTmp[i].oldMarginLeft = "0px";//TODO remove le 0Px et prendre l'original
	this.elementsSlider.push(elemsTmp[i]);
	}
}
//on init le tout : 
var i = 0 ; 
this.elementsSlider.each(function (e){i++<nbrElem?e.style.marginLeft=e.oldMarginLeft:e.style.marginLeft='-20000px';});

$(rElement).style.display="block";
$(lElement).style.display="block";

//gestion des clicks
Event.observe($(rElement), 'click',this.slideRightCB=this.slideRight.bindAsEventListener(this));
Event.observe($(lElement), 'click',this.slideLeftCB=this.slideLeft.bindAsEventListener(this));

//gestion des styles
$(lElement).style.cursor = "pointer";
$(rElement).style.cursor = "pointer";


//gestion des elements de defilement
if(this.nbrElements >= this.elementsSlider.length ) $(this.rightElement).hide();
$(this.leftElement).hide();
}

/**
 * Permet de detruire la liste 'proprement'
 */
ElementsSlider.prototype.destroy= function(){
Event.stopObserving($(this.rightElement),'click',this.slideRightCB);
Event.stopObserving($(this.leftElement),'click',this.slideLeftCB);
}


/**
 * Permet de faire defiler les elements vers la droite.
 * @param  e l'evenement a la source de l'appel
 */
ElementsSlider.prototype.slideRight= function(ea) {
var elementsSlider = this.elementsSlider;
//fait defiler les elements du menu vers la droite
if((this.indice + this.nbrElements) >= elementsSlider.length  )return;//overflow
elementsSlider.each( function (e){e.style.marginLeft='-20000px';});
this.indice += this.step;
for(var i=this.indice,max=this.indice+this.nbrElements;i<max;i++){
		try{
			elementsSlider[i].style.marginLeft=elementsSlider[i].oldMarginLeft;
			}catch(ee){break;}
	}

//gestion des boutons de defilement
(this.indice + this.nbrElements >= elementsSlider.length) ? $(this.rightElement).style.display='none':$(this.rightElement).style.display="block";
$(this.leftElement).style.display="block";
return false;
}
	
	
/**
 * Permet de faire defiler les elements vers la gauche
 * @param  e l'evenement a la source de l'appel
 */
ElementsSlider.prototype.slideLeft = function(ae) {	
	var elementsSlider = this.elementsSlider;
	if((this.indice-this.step)<0)return ; //overflow
	elementsSlider.each( function (e){e.style.marginLeft='-20000px';});
	this.indice -= this.step;
	for(var i=this.indice,max=this.indice+this.nbrElements;i<max;i++){
		try{elementsSlider[i].style.marginLeft=elementsSlider[i].oldMarginLeft;}catch(ee){break;}
		}
	//gestion des defilements :
	(this.indice - this.step < 0) ? $(this.leftElement).hide():$(this.leftElement).style.display="block";
	$(this.rightElement).style.display="block";
	return false;
	}
	
	
/**
 * Permet de voir un element apartenant a la liste ( slide jusqu'a voir l'element ).
 * On defile a gauche puis vers la droite jusqqu'a ce que l'element apparaisse 
 * @param l'element que l'on veut voir apparaitre.
 */
ElementsSlider.prototype.viewElement = function(element) {	
	while (this.indice > 0)
		this.slideLeft();
	var oldIndice = -1;
	while (this.indice != oldIndice ){
		oldIndice = this.indice;
		if(element.style.marginLeft!='-20000px')break;
		this.slideRight();
		}
		return false;
	}

/**
 * @class ListeCliquable Classe permetant de generer des listes cliquables. 
 * Les elements de la liste reagierons au rollOver, rollOut et au click.
 */
function ListeCliquable(){};var ListeCliquable = Class.create();

/**
 * Creer la liste cliquable.
 * @param conteneur est l'id du conteneur des elements de la liste cliquable.
 * @param classRollOver est le nom de la classe de style en rollOver sur un Item
 * @param ne sert plus a rien // DEPRECATED
 * @param classClick est le nom de la classe de style pour l'item selectionne
 * @param onclick callback sous forme de string appele sur le click des elements. Cette chaine est evalue grave a 'eval'.
 * @param ignoredClassNames, facultatif est la liste des Ã©lÃ©ment Ã  ne pas prendre en compte. Ceci est une classe CSS.
 * @constructor 
 */
ListeCliquable.prototype.initialize= function(conteneur,classRollOver,classRollOut,classClick,onclick,ignoredClassNames) {

//verif des parametres , sinon on quitte : 
try{$(conteneur).innerHTML}catch(e){return ;}
this.selectedElement=null;
this.rollOverClass = classRollOver;
//this.rollOutClass = classRollOut;
this.clickClass = classClick;
this.onclick=onclick;
this.elements = new Array();

//suppression des Ã©lÃ©ments non voulus : 
var elemsTmp = $(conteneur).childElements();
for (var i=0,max=elemsTmp.length;i<max;i++){
	if(!elemsTmp[i].hasClassName(ignoredClassNames) ){
	this.elements.push(elemsTmp[i]);
	}
}

//selection de l'element clickÃ© si dÃ©ja clickÃ© :
for (var i=0,max=this.elements.length;i<max;i++)
	if(this.elements[i].hasClassName(classClick))
		this.selectedElement = this.elements[i];

//ajout des events :
for (var i=0,max=this.elements.length;i<max;i++){
	Event.observe(this.elements[i], 'mouseover',this.overCB=this.over.bindAsEventListener(this,this.elements[i]));
	Event.observe(this.elements[i], 'mouseout',this.outCB=this.out.bindAsEventListener(this,this.elements[i]));
	Event.observe(this.elements[i], 'click',this.clickCB=this.click.bindAsEventListener(this,this.elements[i]));
}

}

/**
 * Permet de detruire la liste 'proprement'
 */
ListeCliquable.prototype.destroy= function(){
for (var i=0,max=this.elements.length;i<max;i++){
	Event.stopObserving(this.elements[i],'mouseover',this.overCB);
	Event.stopObserving(this.elements[i],'mouseout',this.outCB);
	Event.stopObserving(this.elements[i],'click',this.clickCB);
	}
}

/**
 * @private
 * Gestion du rollOver sur un Item
 * @param event est l'evenement contenant l'element qui a lance l'evenement
 * @param l'item qui pour lequel l'event est lancÃ©
 */
ListeCliquable.prototype.over= function(event,elem){
	elem.addClassName (this.rollOverClass);
	if(this.selectedElement!=null)
		this.selectedElement.removeClassName(this.clickClass);
	}

/**
 * @private
 * Gestion du rollOut sur un Item
 * @param event est l'evenement contenant l'element qui a lance l'evenement
 * @param l'item qui pour lequel l'event est lancÃ©
 */
ListeCliquable.prototype.out = function(event,elem){
	elem.removeClassName(this.rollOverClass);
	if(this.selectedElement!=null)
	   this.selectedElement.addClassName(this.clickClass); 
	}
/**
 * @private
 * Gestion du Click sur un Item
 * @param event est l'evenement contenant l'element qui a ete presse
 * @param l'item qui pour lequel l'event est lancÃ©
 */
ListeCliquable.prototype.click= function(event,elem){
	var element = elem;
	for (var i = 0,max=this.elements.length;i<max;i++)
		this.elements[i].removeClassName(this.clickClass);
	this.selectedElement = element;
	this.selectedElement.addClassName(this.clickClass);
	//puis on effectu le click :
	eval(this.onclick);
	//on arrete l'evenement
	event.stop();
	return false;
	}
	

/**
 * Permet de cliquer un element de la liste. 
 * @param l'element a clicquer
 */
ListeCliquable.prototype.clickAnElement= function(element){
	try{element.onmouseover();}catch(e){}
	var i=0;
	for (var max=this.elements.length;i<max;i++)if(element==this.elements[i])break;
	this.pressItem(i);
	try{element.onmouseout();}catch(e){}
	return false;
	}	



/**
 * Permet de presser un Item de la liste cliquable. 
 * Ceci est notament utilise pour externiser la selection. 
 * @param indexItem est l'index a selectionner dans la liste
 */
ListeCliquable.prototype.pressItem=function (indexItem){
	if(this.selectedElement!=null)
		this.selectedElement.removeClassName(this.clickClass);
	this.selectedElement=this.elements[indexItem];
	this.selectedElement.addClassName(this.clickClass);
	try{this.selectedElement.onmouseover();}catch(e){}
	try{this.selectedElement.onclick();}catch(e){}
	try{this.selectedElement.onmouseout();}catch(e){}
	return false;
	}
/**
 * Permet de faire un rollover sur un Item de la liste cliquable. 
 * Ceci est notament utilise pour externiser le rollover. 
 * @param indexItem est l'index sur lequel faire le rollOver dans la liste.
 */
ListeCliquable.prototype.rollOverItem=function (indexItem){	
	this.over(null,this.elements[indexItem]);
	try{this.elements[indexItem].onmouseover();}catch(e){}
	return false;
	}
/**
 * Permet de faire un rollout sur un Item de la liste cliquable. 
 * Ceci est notament utilise pour externiser le rollOut. 
 * @param indexItem est l'index sur lequel faire le rollOut dans la liste.
 */
ListeCliquable.prototype.rollOutItem=function (indexItem){
	this.out(null,this.elements[indexItem]);
	try{this.elements[indexItem].onmouseout();}catch(e){}
	return false;
	}
	
/**
 * Permet de deselctionner tous les items
 */
ListeCliquable.prototype.releaseAllItems=function(){
if(this.selectedElement!=null&&this.selectedElement.className!=null)
	this.selectedElement.removeClassName(this.clickClass);
this.selectedElement=null;
return false;
}

/**
 * Permet de gerer de 'lock' sur des actions
*/

function Locker(){} ;var Locker = Class.create();
/**
 * @constructor
 * @param divAMask la div a masquer par le loader
 */
Locker.prototype.initialize = function() {
	this.OK = "OK";
	this.NOK = "NOK";
	
	this.tasks = new Array(); 
}
Locker.prototype.lockTask = function(taskName) {
	if(this.tasks[taskName] != this.NOK){
		this.tasks[taskName]=this.NOK;
		return true;
	}else{
	//	alert('impossible de lock');
		return false;
	}
}
Locker.prototype.unLockTask = function(taskName) {
	if(this.tasks[taskName] == this.NOK){
		this.tasks[taskName]=this.OK;
		return true;
	}else{
		alert('impossible de delocker');
		return false;
	}
}
/**
 * Permet de retourner un tableau avec la taille du document : [height,width]
 */
function getDocumentSize  (){return [document.viewport.getHeight(),document.viewport.getWidth() ];}




/**
 * @class PopIn 
 * Classe permettant de generer des popIn.
 * Les popIn auront au choix un contenu Ajax ou une Iframe.
 */
var PopIn = Class.create();
/**
 * La popIn actuellement selectionnee
 */
var popUpSelected=null;
var overlay2=null;

/**
 * Ouvre obligatoirement les popin en popUp
 */
var allwaysPopUp = false;


/**
 * @constructor
 * Permet de creer la popIn. 
 * @param X la position verticale de la popIn
 * @param Y la position horizontale de la popIn
 * @param w la largeur de la popIn
 * @param h la hauteur de la popIn
 * @param url l'url a partir de laquel charger le contenu de la popIn
 * @param titre Le titre de la popIn
 * @param resizable permet de redimentionner la fenetre si true
 * @param isIframe un boolean a true si on affiche le contenu dans une Iframe.
 * @param hideOverflow, indique si le contenu de la popIn est affichÃ© avec des barres de dÃ©filement si il est trop grand ( un boolean qui par defaut est a false).
 *        ceci ne vaut que pour les non-iframes car pour les iframes, le contenu ne scroll jamais  (c'est dans l'interieur de la iframe que cela doit etre gÃ©rÃ©).
 * @param externizable un boolean par dÃ©faut Ã  true qui di si la fenetre peut etre exernalisÃ©e ( sortie en popUp )
 *  */
PopIn.prototype.initialize = function(X,Y,w,h,url,titre,resizable,isIframe,hideOverflow,externizable) {
//on signale a l'utilisateur l'opÃ©ration en cour : 	
getWaitManager().wait();

this.resizable=resizable;
this.posX=X;
this.posY=Y;
this.width = w;
this.height= h;
this.url=url;
this.titre=titre;
this.isReduced=false;
this.isIframe=isIframe;
this.hideOverflow=hideOverflow;
this.bouge=this.bougeResizer=this.overlayActif=false;
if (typeof externizable == "undefined") {
    externizable = true;
}
this.externizable = externizable;



// OVERLAY Il existe 2 type d'overlay .. pour IE => Iframe sinan div///
if(overlay2==null){	
if(Prototype.Browser.IE){
	var iframeOverlay='<iframe style="display:none;width:2000;height:2000;background-color:transparent;z-index:20000;position:absolute;top:0;left:0;" scrolling="auto" frameborder="0" allowtransparency="true" id="overlayV2" name="overlayV2" width="2000" height="2000" src="/pmu/html/fr/popinNeed.html"></iframe>';
	}else{
	var iframeOverlay='<div style="display:none;width:2000px;height:2000px;background-color:transparent;z-index:22300;position:absolute;top:0;left:0;" id="overlayV2" name="overlayV2" width="2000" height="2000" ></div>';
	}
new Insertion.Bottom(document.getElementsByTagName('body')[0], iframeOverlay);
overlay2 = $('overlayV2');
}

// APPELS /////////////////////////////////
if(isIframe){//ouvre la popin avec une iframe dedant
var content=new Array();
content.responseText='<iframe frameborder="0" scrolling="no"  marginwidth="0" marginheight="0" src="'+url+'" width=100% height=100% ></iframe>';
this.open(content);
}
else new Ajax.Request(this.url,{onComplete:this.open.bindAsEventListener(this),method:'get'});
}

/**
 * Permet d'ouvrir la popIn.
 * Creer le code html et insert le retour ajax dans la popin.
 * Ajoute egualement les ecouteurs d'evenements pour la gestion des cliques et deplacements.
 * @param resultEvent est le resultat a afficher dans la popIn ( resultEvent.responseText )
*/
PopIn.prototype.open = function(resultEvent) {	
//on ne permet pas le scroll en cas de iframe ou de hideOverflow dÃ©finni :
var noscroll = this.hideOverflow || this.isIframe;
this.createElements(noscroll);
this.content.innerHTML = resultEvent.responseText;
if(noscroll)this.content.style.overflow="hidden";
Event.observe(this.header, 'mousedown', this.callBackBarPressed = this.barPressed.bindAsEventListener(this));
Event.observe(this.closeButton, 'mousedown', this.callBackClose = this.close.bindAsEventListener(this));
Event.observe(this.popUpButton, 'mousedown', this.callBackViewPopUp = this.viewPopUp.bindAsEventListener(this));
var doc=(Prototype.Browser.IE)?overlay2.contentWindow.document:document;
Event.observe(doc, 'mouseup',this.callBackReleased = this.released.bindAsEventListener(this));
Event.observe(doc, 'mousemove',this.callBackMoved = this.moved.bindAsEventListener(this) );

this.content.style.height=(this.elem.getHeight()-this.header.getHeight()-4 )+'px';
this.selectPopIn();

//si on est sur opera, on ouvre une popup car la librairie ne suporte pas opera 
// on ouvre Ã©gualement si l'utilisateur prÃ©fere des popup : 
if(allwaysPopUp){
	this.viewPopUp();
}
//fin de l'attente
getWaitManager().unWait();
}
/**
 * Permet de fermer la popIn. Cette methode supprime la popIn du DOM ainsi que les event lies a cette popIn
 */
PopIn.prototype.close = function() {
Event.stopObserving(this.closeButton,'mousedown',this.callBackClose);
Event.stopObserving(this.popUpButton,'mousedown',this.callBackViewPopUp);
Event.stopObserving(this.header,'mousedown',this.callBackBarPressed);
var doc=(Prototype.Browser.IE)?overlay2.contentWindow.document:document;
Event.observe(doc, 'mouseup',this.callBackReleased);
Event.observe(doc, 'mousemove',this.callBackMoved);
this.elem.remove();
}
/**
 * Appeler lorque la bar est appuye, cela initialise le drag de la popIn.
 * @private
 */
PopIn.prototype.barPressed = function(mouseEvent) {
	this.displayOverlay();
	this.baseX=Event.pointerX(mouseEvent);
	this.baseY=Event.pointerY(mouseEvent);
	this.initalPosX = this.posX;
	this.initalPosY = this.posY;
	this.offsetX=0;
	this.offsetY=0;
	this.bouge=true;
	this.selectPopIn();
}
/**
 * Appele lorsque la bar est relachee, cela stop le drag de la popIn.
 * @private
 */
PopIn.prototype.released = function() {
	this.bouge=false;
	this.bougeResizer=false;
	this.hideOverlay();
}



/**
 * Appeler afin de bouger la fenetre ou de la redimentionner selon l'element actuellement actif.
 * @param mouseEvent l'evenement de deplacement
 * @param killoffset optionnel, si positionne a true, indique qu'il faut effectuer le calcule sans l'offser. typyquement, c'est tulise lorsque le deplacement viens de la methode move2 
 * @private
 * */
PopIn.prototype.moved = function(mouseEvent, killoffset) {
	if(document.all)
		if(mouseEvent.button==0)this.released();
		
	mouseEvent.stop();
	document.onselectstart = function (){return null;}//eviter les pb de selection de texte

	if(this.bouge==true){

	this.posX=mouseEvent.pointerX()-this.baseX + this.initalPosX + this.offsetX;
	this.posY=mouseEvent.pointerY()-this.baseY + this.initalPosY + this.offsetY;

	var docSize=getDocumentSize();
	var tailleFenetreHauteur = docSize[0];
	var tailleFenetreLargeur = docSize[1];

	//le nouveau style a appliquer a la fenetre
	var styleToApply = "";

	//repositionnement avec gestion des contraintes
	if(this.initalPosY>this.posY){
		if( this.posY > 0 )
			styleToApply += "top:"+this.posY+'px;';
		else{
			this.offsetY -= this.posY;
			styleToApply += "top:0px";
		}
	}else{
		var elemHeight = this.elem.getHeight();
			styleToApply += "top:"+this.posY+"px;";
	}
	
	if(this.initalPosX >this.posX){
		if( this.posX > 0 )
			styleToApply += "left:"+this.posX+"px;";
		else{
			this.offsetX -= this.posX;
			styleToApply += "left:0px;";
		}
	}
	else{
		var elemWidth = this.elem.getWidth();
		styleToApply += "left:"+this.posX+"px";
	}
	
	//on applique le style :
	this.elem.setStyle(styleToApply);

	//on corrige une erreur potentielle : 
	//contrainte sur le haut : 
	if( this.posY <= 0 ){
			this.elem.setStyle("top:0px");}
	}
	
	document.onselectstart = null;//rend la main sur la selection de texte 
}



/**
 * Permet de creer les elements de la popIn. <br /> 
 * les Styles sont orginises de la maniere : <br />
 * <li>
 * <ul>contenu de la popIn : popInContent</ul>
 * <ul>header : popInHead</ul>
 * <ul>global : popIn</ul>
 * <ul>bouton de fermeture : popInCloseButton</ul>
 * <ul>bouton d'ouverture en popUp : popInPopUpButton</ul>
 * </li>
 *  
 * @private
 */
PopIn.prototype.createElements= function() {
this.elem=new Element("div");
this.header=new Element("div");
this.closeButton=new Element("div");
this.popUpButton=new Element("div");
this.content=new Element("div");

this.header.innerHTML='<span>'+this.titre+'</span>';
this.closeButton.innerHTML="X";
this.popUpButton.innerHTML="&nbsp;";

this.header.insert(this.popUpButton);
this.header.insert(this.closeButton);


this.elem.insert(this.header);
this.elem.insert(this.content);
document.body.appendChild(this.elem);

this.elem.setStyle({position:'absolute',zIndex:'10',left:this.posX+'px',top:this.posY+'px',width:this.width+'px',height:this.height+'px'});
this.closeButton.setStyle({position:'absolute',zIndex:'4',top:'2px',right:'5px'});
this.popUpButton.setStyle({position:'absolute',zIndex:'4',top:'2px',right:'38px'});
this.header.setStyle({position:'absolute',zIndex:'3',top:'0px',left:'0px'});
this.content.setStyle({position:'absolute',zIndex:'4',top:'25px',left:'0px'});

this.header.className="popInHead";
this.content.className="popInContent";
this.elem.className="popIn";
this.closeButton.className="popInCloseButton";
this.popUpButton.className="popInPopUpButton";

//les texte tooltips : 
this.closeButton.title = "Fermer";
this.popUpButton.title = "Ouvrir dans une fen\u00EAtre exterieure";

//pour que le titre ne soit pas selectionnable : 
this.header.onmousedown = this.header.onselectstart = function(){return false;};

//si la fenetre n'est pas externalizable, on cache le bouton de popUp :
if(!this.externizable)
	this.popUpButton.setStyle({visibility:'hidden'});
}

/***
 * permer d'afficher un masque qui permet de ne pas selectionner le texte lors du deplacement des fenetres.
 * @private
 */
PopIn.prototype.displayOverlay = function (){
if(this.overlayActif == true){return;}//deja affiche
overlay2.style.display='block';
var dim=getDocumentSize();
overlay2.style.height=dim[0]+'px';
overlay2.style.width=dim[1]+'px';
this.overlayActif=true;
}
/**
 * enleve le mask precedement affiche.
 * @private
 */
PopIn.prototype.hideOverlay = function (){
if(this.overlayActif==false)return;
overlay2.style.display='none';
this.overlayActif = false;
}
/**
 * Permet de transformer la popIn en popUp.
 * La popUp doit  garder le meme css et la meme position sur la fenetre.
 * on copie donc le premier element style du header de la page actuel dans la futu popup
 */
PopIn.prototype.viewPopUp=function () {
var mesChaines=[];
if( !this.isIframe ){
this.popUp=window.open("",'','width='+this.elem.style.width+',height='+(this.elem.getHeight()-25)+'px,toolbar=no,scrollbars=yes,resizable=no,status=no,location=no,directories=no,menubar=no');
mesChaines.push("<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>");
mesChaines.push("<html><head><title>");
mesChaines.push(this.titre.stripTags());

//ajout des css dans le head :
mesChaines.push("</title><style>");
var lesStyles = $$('style');
for (var i=0;i<lesStyles.length;i++)
	mesChaines.push(lesStyles[i].innerHTML);
mesChaines.push("</style>");
var lesStyles = $$('link');
for (var i=0;i<lesStyles.length;i++)
	mesChaines.push('<LINK REL=StyleSheet HREF="'+lesStyles[i].href+'" TYPE="text/css" />');

mesChaines.push("</head>");
mesChaines.push("<body  "+(this.hideOverflow?'style="overflow:hidden"':'')+">");
mesChaines.push(this.content.innerHTML);
mesChaines.push("</body></html>");
this.popUp.document.write(mesChaines.join(''));
}else{
this.popUp=window.open(this.url,'','width='+this.elem.style.width+',height='+(this.elem.getHeight()-25)+'px,toolbar=no,scrollbars=no,resizable=no,status=no,location=no,directories=no,menubar=no');	
}


//positionnement dans la fenetre : 
var left = self.screenX;if(left==undefined)left = self.screenLeft;
var top = self.screenY;if(top==undefined)top = self.screenTop;else top+=60;
var off = Position.cumulativeOffset( this.elem );
this.popUp.moveTo(left+off[0],top+off[1]);
this.popUp.focus();
this.popUp.document.close();
this.close();
}

/**
 * Permet de donner le focus a la popIn
 */
PopIn.prototype.selectPopIn=function(){
//suppression des events : 
try{Event.stopObserving(this.elem,'click',this.fenetreSelectionneCB);}catch(e){}

this.blurPopIn();
this.elem.style.zIndex=11;
popUpSelected=this;
}

/**
 * Permet de retirer le focus a la popIn
 **/
PopIn.prototype.blurPopIn=function(){
if(popUpSelected == null)return;
popUpSelected.elem.style.zIndex=10;
//ajout de l'evenement pour recup le focus si l'utilisateur click
Event.observe(popUpSelected.elem, 'click', popUpSelected.fenetreSelectionneCB = popUpSelected.selectPopIn.bindAsEventListener(popUpSelected));
}


/**
 * Fichier contenant des fonctions utiles pout tout le site
 */

/**
 * Permet de valider le formuaire de login pour la pdp
 */
var nombreDeClicks = 0;
function validformvisiteur(){
	
	if(nombreDeClicks<1){
		  var login=$('numero');
	      var password=$('code_client'); 

	      var rxLongueur10 = new RegExp(/([0-9]{10})/);
	      var rxLongueur4  = new RegExp(/([0-9]{4})/);

		  if( !rxLongueur10.test(login.value) ){
		  alert ("Le champ numéro client doit contenir 10 chiffres.");
		  login.focus();
		  }else if( !rxLongueur4.test(password.value) ){
		  alert ("Le champ code doit contenir 4 chiffres.");
		  password.focus();
		  }else {
		  	//clické pour empecher le double click
		  	nombreDeClicks++;
		  	return true;
		  }
		  return false;
	}else{
		return false;
	}
}


/**
 * Permet d'afficher l'image d'autopromotion
 */
function affichePub(autopromo){
try{
		var texte=autopromo[Math.floor(Math.random()*autopromo.length)];
		if(texte.endsWith('.swf')){//pour les flashs
			var swf = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,28,0" width="219" height="62">'
	  		+'<param name="movie" value="'+texte+'" />'
			+'<param name="quality" value="high" />'
			+'<param name="wmode" value="transparent" />'
			+'<param name="allowScriptAccess" value="sameDomain" />'
			+'<embed src="'+texte+'" wmode="transparent" allowScriptAccess="sameDomain" quality="high" pluginspage="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash" type="application/x-shockwave-flash" width="219" height="62"></embed>'
			+'</object>';
			$('paris_oval').innerHTML=swf;
		}else{//pour les images
			$('paris_oval').innerHTML = texte;
		}
	}catch(e){
		//une erreur dans l'autopromo
	}
}

/**
 * Transforme un texte bbcode en texte html
 * [u][/u]
 * [b][/b]
 * [i][/i]
 * [a href="" target="_blank" ][/a]
 * [ac][/ac]//met le texte a display:none dans une span avec pour class .arriveCamera
 * [br] permet un retour a la ligne
 * [lb] permet délimiter l'intro du reste du texte
 */
function transformBBCode(text){
text = text.replace(/\[b\]/gi, '<strong>').replace(/\[\/b\]/gi, '</strong>')
		   .replace(/\[i\]/gi, '<em>').replace(/\[\/i\]/gi, '</em>')
		   .replace(/\[u\]/gi, '<span style="text-decoration: underline;">').replace(/\[\/u\]/gi, '</span>')
		   .replace(/\[ac\](.+)\[\/ac\]/gi, '<span style="display:none;" class="arriveCamera">$1</span>')
		   .replace(/\[a([^\]\[<>]+)\]/gi, '<a $1 >')
		   .replace(/\[img([^\]\[<>]+)\]/gi, '<img $1 />')
		   .replace(/\[\/a\]/gi, '</a>')
		   .replace(/\[br\]/gi,'<br />')
		   .replace(/\[lb\]/gi,'');
return text;
}


/**
* Permet d'afficher un flash en popUp
*/
function ouvreFlash(urlDuSWF,largeur,hauteur){
var win = window.open('','', 'resizable=no, location=no, width='+largeur+', height='+hauteur+', menubar=no, status=no, scrollbars=no, menubar=no');	
var inner=[];
inner.push('<html><body style="margin-left: 0px; margin-top: 0px;" ><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab" width="');
inner.push(largeur);
inner.push('" height="'); 
inner.push(hauteur);
inner.push('" align="left">');
inner.push('<param name="quality" value="high" />');
inner.push('<param name="movie" value="'+urlDuSWF+'" />');
inner.push('<embed src="');
inner.push(urlDuSWF);
inner.push('" width="');
inner.push(largeur);
inner.push('" height="');
inner.push(hauteur);
inner.push('" align="left" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash"></embed>');
inner.push('</object></body></html>');
win.document.write(inner.join(''));
win.document.close();
}


/**
 * Permet de récupérer des paramètres de l'url
 */
function getParameter( name )
{
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if( results == null )
    return "";
  else
    return results[1];
}

/**
 * Permet de tagger une partie
 */
function tag(rubrique,section,ns_l){
mediametrieTag(rubrique, section);
if(ns_l!=undefined){
	if(document.domain == 'www.pmu.fr' || document.domain == 'www2.pmu.fr') 
	sitestat("http://fr.sitestat.com/pmu/pmu-fr/s?"+ns_l);
	else sitestat("http://fr.sitestat.com/pmu/test/s?"+ns_l);
}
return false;
}

/**
 * Fonction de taggage mediaMetrie
 */
 function mediametrieTag(rubrique, section){
CM_RUBRIQUE = rubrique;
CM_CLIENT = "pmufr";
CM_SECTION1 = section;
cm_arg="http://stat3.cybermonitor.com/"+CM_CLIENT+"_v?R="+CM_RUBRIQUE+"&S=";
if(CM_SECTION1) cm_arg+=CM_SECTION1;
cm_arg+="&RF="+escape(document.referrer)+"&A="+escape(Math.random());
if(typeof(screen)=="object"){cm_arg+="&scw="+screen.width;
cm_arg+="&sch="+screen.height;cm_arg+="&scp="+screen.colorDepth};
cm_i=new Image(1,1);
cm_i.src=cm_arg;
}

/**
 * Permet de vider les cookies de positionnement
 */
function clearCookies(){
eraseCookie("state");
eraseCookie("redirection");
}

function createCookie(name,value,days) {
if (days) {
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			var expires = "; expires="+date.toGMTString();
}
else var expires = "";
document.cookie = name+"="+value+expires+"; path=/";
}
function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
	if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
function eraseCookie(name) {
createCookie(name,"",-1);
}

 
 
 
 /**
  * Permet de couvrir le login si l'url contient 2.pmu.fr (utilisateurs provenant de la prise de paris )
  */
 function couvreLogin(){
if(window.location.host.split('2.pmu.fr').length>1){
 var swfCouvre = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab" height="196" width="219"> <param name="movie" value="/pmu/img/pdp/divers/couvreloginpdp.swf"> <param name="quality" value="high"> <param name="bgcolor" value="null"> <param name="allowScriptAccess" value="sameDomain"> <embed src="/pmu/img/pdp/divers/couvreloginpdp.swf" bgcolor="null" play="true" loop="true" quality="high" allowscriptaccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer" height="196" width="219"></object>';	
 $('mon_pmu_connexion').innerHTML=swfCouvre;
}
}

/**
 * Fonction de taggage netstat
 */
function sitestat(ns_l){
	// FromUrl v1.5 Copyright (c) 2001-2008 Nedstat B.V. All
var ns_type='' // leave empty for normal/ppc measurement, fill in for clickin,clickout or pdf
var r='' // yes=only parse url when there is a real document.referrer,
// no=only parse url when there is no real document.referrer, empty=always parse url
var t='?' // tag in url where parameters follow; default '?' could be replaced by "#"
var p=new Array();var w='';var l='';var d=document;var n=navigator;var ns_0=''
;if(top!=self){if('\u0041'=='A'){var u=n.userAgent;if(u.indexOf('Safari')==-1)
{var b=u.indexOf('Opera');if(b==-1||(u.charAt(b+6)+0)>5){b=u.indexOf('Mozilla'
);var xb=b!=-1?u.charAt(b+8)>4:1;if(u.indexOf('compatible')!=-1||xb){var c=
'try{ns_0=top.document.referrer}catch(e){}';eval(c);c=
'try{l=top.document.location.href}catch(e){}';eval(c);}}}}}else{ns_0=
d.referrer;l=d.location.href;}if(ns_0.lastIndexOf('/')==ns_0.length-1){ns_0=
ns_0.substring(ns_0.lastIndexOf('/'),0);}var f=ns_l.indexOf('?');if(f!=-1){
var q=ns_l.substring(f+1);ns_l=ns_l.substring(0,f);if(q){var m=q.indexOf('&');
w=q.substring(0,m==-1?q.length:m);if(w.indexOf('=')!=-1){w='';}if(w){q=
q.substring(m==-1?q.length:m+1);q+=(q?'&':'')+'ns_name='+w;}if(ns_0.length>0){
q+=(q?'&':'')+'ns_referrer='+escape(ns_0);}var s=0;var e=0;while(q.length){e=
q.indexOf('&');if(e==-1){e=q.length;}var o=q.substring(s,e);if(o.substring(0,4
)=='amp;'){o=o.substring(4);}if(o)p[p.length]=o;q=q.substring(e+1);}}}var a=
l.indexOf(t);a=a==-1?0:l.substring(a+1);var j;if(r=='yes')j=ns_0.length;else
if(r=='no')j=!ns_0.length;else if(r=='')j=1;if(a&&j){while(a.length){var e=
a.indexOf('&');if(e==-1){e=a.length;}var k=a.substring(0,a.substring(0,e)
.indexOf('='));var v=a.substring(a.substring(0,e).indexOf('=')+1,e);if(
k.substring(0,4)=='amp;'){k=k.substring(4);}while(v.substring(0,1)=='='){v=
v.substring(1);}if(k=='ns_name'){w=v;}else if(k=='ns_or'){var g='ns_referrer='
;for(var z=0;z<p.length;z++){if(p[z].substring(0,g.length)==g){p[z]=
'ns_referrer='+v;}}}else{if(k.substring(0,3)=='ns_'&&v&&k){var h=0;for(var x=0
;x<p.length;x++){if(p[x].substring(0,p[x].indexOf('='))==k){p[x]=k+"="+v;h=1}}
if(!h){p[p.length]=k+"="+v;}}}a=a.substring(e+1);}}if(!w){return;}var s='';
var y='';for(var i=0;i<p.length;i++)if(p[i].substring(0,8)!='ns_name='){if(p[i
].substring(0,12)!='ns_referrer='){s+='&'+p[i];}else{y='&'+p[i];}}s+=ns_type?
'&ns_type='+ns_type+'&ns_action=view':'';ns_pixelUrl=ns_l+'?'+w+"&ns__t="+(
new Date()).getTime();ns_l=ns_pixelUrl+s+y;if(d.images){ns_1=new Image();
ns_1.src=ns_l;}else{d.write('<img src='+ns_l+' width="1" height="1">');}}

function ns_onclick (a, url, name, type, winopt) {
	var ns_l="http://fr.sitestat.com/pmu/pmu-fr/s?";
	ns_l+=name;ns_l+='&ns_type='+type+'&ns_action=view';
	ns_l+='&ns__t='+(new Date()).getTime();
	if(!url)
		url=a.href;
	var ns_0=document.referrer;
	if(ns_0.lastIndexOf('/')==ns_0.length-1)
		ns_0=ns_0.substring(ns_0.lastIndexOf('/'),0);
	if (ns_0.length>0)
		ns_l+='&amp;ns_referrer='+escape(ns_0);
	winopt=winopt||"";
	var target=(a && a.target && a.target!="")?(a.target.substring(0,1)=="_")?a.target.substring(1):a.target:"self";
	var ns_i=new Image();
	

//	  if(target && url){
//		if(window[target]){
//			window.ns_softclick_timer=function(target,url)
//			{
//				return function(){
//					ns_i.onload=ns_i.onerror=function(){
//						return;
//					};
//					window[((window[target])?target:"self")].location.href=url;
//				}
//			}
//			(target,url);
//			window.setTimeout('ns_softclick_timer()',5000);
//			ns_i.onload=ns_i.onerror=window.ns_softclick_timer;
//		} else {
//			window.open(url,target,winopt);
//		}
//	}
	
	ns_i.src=ns_l;
	return false;
}/** 
* @fileoverview Permet de grer le positionnement de l'utilisateur dans la partie course et resultats 
* en fonction de la reunion voulu, de la course voulu, du partant voulu et les onglets selectionnes voulu.   
* @author Pouleriguen Guillaume
* @version 0.1
*/

/////////////////////////////////////////////////////////////////////////////////////////////////
// CONSTANTES ///////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////

/**
* le template a afficher si erreur :
*/
var templateDErreur = "<h2>L'information est momentan&eacute;ment indisponible</h2><p><a onclick=\"#{lien}\" style=\"cursor:pointer;\">Cliquez ici pour rafra&icirc;chir cette zone.</a></p><br /><br /><h2><a style=\"cursor:pointer\" onclick=\"window.location='/pmu/servlet/courseresultats'\">Ou cliquez ici pour retourner sur la page de pr&eacute;sentation des courses du jour</a></h2>";

///
///Les selecteurs css pour les elements graphiques : 
///
var selecteurListeDesPartants = '#left_partant #partantListe a';
var boutonsMenuCourses = "#courseListe itemDeListe";

///
///Les divs utilisés :
///
var boutonsMenuCoursesContainer = "courseListe";
var conteneurDetailPartant = "contenu_rightPartant";
var partieDroiteDesPartants = 'right_partant';
var menuDesCoursesAppercu = "prix_heure";
var menuDesCourses = "#coursesjj > .itemDeListe > .zoneDetailCourse";
var contenuDuCentre = "cr_contenu";
var flecheDetailPartant = 'fleche_select';
var imageCasaqueReflet = 'detCasaque2';
var partantListe = "partantListe";
//le message par defaut de la partie a la place de la preview d'une course quand aucune course n'est selectionné (imprimer le programme)
var messageParDefault='<div onclick="window.open(\'/pmu/servlet/pmu.web.servlet.www.infos.ListeToutesReunions?dd=\'+dateActuelle,\'Impression\',\'width=700px,height=\'+screen.height*0.8+\'px,toolbar=no,resizable=no,scrollbars=yes,status=no,location=no,directories=no,menubar=no\');" title="Imprimer le programme complet des courses du jour." style="cursor: pointer;" id="prix"><p><strong><span style="color: rgb(112, 112, 112);" class="gris">IMPRIMER</span></strong></p><p>le programme du jour</p><p/></div><div onclick="window.open(\'/pmu/servlet/pmu.web.servlet.www.infos.ListeToutesReunions?dd=\'+dateActuelle,\'Impression\',\'width=700px,height=\'+screen.height*0.8+\'px,toolbar=no,resizable=no,scrollbars=yes,status=no,location=no,directories=no,menubar=no\');" style="padding-top: 18px; cursor: pointer;" title="IMPRIMER le programme du jour" id="heure"> <img title="Imprimer le programme complet des courses du jour." style="padding-left:10px;" src="/pmu/img/backgrounds/all/picto_imprimer-tout.gif"/> </div>';





/////////////////////////////////////////////////////////////////////////////////////////////////
// POSITION MANAGER /////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////

 /**
 *  @class permet la navigation dans la page course et resultats.
 */
function PositionManager(){};
var PositionManager= Class.create(); 

/**
 * @constructor initialise le manager.
 */
PositionManager.prototype.initialize = function() {

	this.oldNavigation=new Object();
	//creation des loaders Ajax :
	this.loaderMain = new LoaderAjax(contenuDuCentre);

	//le locker :
	getWaitManager().addEventListener('onlock',this,"lock");

	//les urls :
	this.urlListeCourses="/programmes/#{dd}/liste-des-courses/#{idr}.html";
	this.urlMenuListeCourses="/programmes/#{dd}/menu-liste-des-courses/#{idr}/#{tc}.html";
	this.urlDetailCourse="/programmes/#{dd}/detail-course/#{idr}/#{idc}.html"
	this.urlListeCoursesBig="/programmes/#{dd}/grande-liste-des-courses/#{idr}.html";
	this.urlRapport="/programmes/#{dd}/rapports/#{idr}/#{idc}.html";
	this.urlDetailPartant="/programmes/#{dd}/fiche-partant/#{idr}/#{idc}/#{np}.html";
	this.urlCalendrier="/programmes/calendrier/#{args}.html";
 

	//les paramettres de la requette : 
	this.requestHeadersOptions = {};

	//gestion de l'historique : initialisation
	var myModuleBookmarkedState = YAHOO.util.History.getBookmarkedState("cr");
	var myModuleInitialState = myModuleBookmarkedState || "";
	var elementsDeLocalisation = myModuleInitialState.split('-');

	YAHOO.util.History.register("cr", myModuleInitialState, this.historiqueChange);
	YAHOO.util.History.initialize("yui-history-field", "yui-history-iframe");
}


/**
 * Fonction appelèe lorsque l'historique de navigation change (l'url qui change).
 * Dans cette fonction, on recupère le nouvel état et on navigue
 */
PositionManager.prototype.historiqueChange = function (state) {
	var elementsDeLocalisation = state.split('-');
	if(elementsDeLocalisation.length<5)return;
		positionManager.goTo(elementsDeLocalisation[0],elementsDeLocalisation[1],elementsDeLocalisation[2],elementsDeLocalisation[3],elementsDeLocalisation[4],elementsDeLocalisation[5],elementsDeLocalisation[6]);	
}



/**
 * Permet de positionner le positionmanager sans pour autant charger les pages.
 * @param => les memes que pour goto
 */
 PositionManager.prototype.positionWithNoMoves = function(idReunion,idCourse,idPartant,rapport,selectedTabCourse,selectedTabPartant,calendrier) {
 positionManager.navigation={reunion:idReunion,course:idCourse,partant:idPartant,rapport:rapport,tabCourse:selectedTabCourse,tabPartant:selectedTabPartant,calendrier:calendrier};
 positionManager.oldNavigation={reunion:positionManager.navigation.reunion,
							   course:positionManager.navigation.course,
							   partant:positionManager.navigation.partant,
							   rapport:positionManager.navigation.rapport,
							   tabCourse:positionManager.navigation.tabCourse,
							   tabPartant:positionManager.navigation.tabPartant,
							   calendrier:positionManager.navigation.calendrier};

//gestion des elements dynamiques (onglets, effets ... ) :
//init du slider de reunions
listeReunionsManager = new ElementsSlider('listeReunions',3,'leftSliderListeReunions','rightSliderListeReunions','notInList');
//listeCliquableReunions = new ListeCliquable ('coursesjj','itemDeListeOver','itemDeListe','itemDeListeClick',null,'notInList'); 
//if(listeCliquableReunions.selectedElement)
	//listeReunionsManager.viewElement(listeCliquableReunions.selectedElement);

//init du slider des courses
//listeCliquableCourses = new ListeCliquable (boutonsMenuCoursesContainer,'itemDeListeOver','itemDeListe','itemDeListeClick',null,'notInList');

//init des onglets de la liste des courses si présent :

if( (idCourse == "" || idCourse == "0") && (calendrier == "" || calendrier == "0") ){
tabbedPaneCourse = createOngletCourses();

//init du detail de la course : 
}else if( (calendrier == "" || calendrier == "0")  &&  (rapport == "" || rapport == "0") ){
tabbedPanePartant = createOngletPartants();
selectOngletPartantWithPos(positionManager.navigation.tabPartant);
}else {//init du rapport 
creerAncresPourRapport();
}

return false;
}

/**
 * Permet de se diriger vers une page en fonction d'informations.<br />
 * Attention tous les parametres sont des ID sauf le numero du partant
 * @param idReunion l'id de la reunion a selectionner
 * @param idCourse l'id de la course a selectionner
 * @param idPartant l'id du partant a selectionner
 * @param rapport un boolean (0/1) a 1 si on affiche le rapport de la course (idcourse et idreunion necessaires).
 * @param selectedTabCourse l'onglet a selectionner dans la liste des courses (entier demarant a 0)
 * @param selectedTabPartant l'onglet a selectionner dans de detail du partant (entier demarant a 0)
 * @param calendrier, le calendrier sous la forme "Q_20070708"
 **/
PositionManager.prototype.goTo = function(idReunion,idCourse,idPartant,rapport,selectedTabCourse,selectedTabPartant,calendrier) {
//gestion des locks
if(this.lock==true)return;

//sauvegarde de la navigation courante et verification des parametres
if(!idReunion || idReunion == undefined)idReunion=0;
if(!rapport || rapport == undefined)rapport=0;
if(!idCourse || idCourse == undefined)idCourse=0;
if(!idPartant || idPartant == undefined)idPartant=0;
if(!calendrier || calendrier ==undefined)calendrier = 0 ; 
if(!selectedTabCourse || selectedTabCourse == undefined)selectedTabCourse=0;
if(!selectedTabPartant || selectedTabPartant == undefined)selectedTabPartant=0;
positionManager.navigation={reunion:idReunion,course:idCourse,partant:idPartant,rapport:rapport,tabCourse:selectedTabCourse,tabPartant:selectedTabPartant,calendrier:calendrier};

//si la navigation est la même on ne fait rien : 
if(							   positionManager.navigation.reunion==positionManager.oldNavigation.reunion &&
							   positionManager.navigation.course ==positionManager.oldNavigation.course  &&
							   positionManager.navigation.partant ==positionManager.oldNavigation.partant  &&
							   positionManager.navigation.rapport ==positionManager.oldNavigation.rapport  &&
							   positionManager.navigation.tabCourse ==positionManager.oldNavigation.tabCourse  &&
							   positionManager.navigation.tabPartant ==positionManager.oldNavigation.tabPartant  &&
							   positionManager.navigation.calendrier ==positionManager.oldNavigation.calendrier
							   )return;

///////////////////////////////////////////////////////////////////////////////////////////////
//// LOGIQUE DE CHOIX DE L'AFFICHAGE
///////////////////////////////////////////////////////////////////////////////////////////////
//recuperation de la liste des courses du menu si changement de reunion
if(positionManager.navigation.reunion != positionManager.oldNavigation.reunion && positionManager.navigation.reunion!=0)
	this.displayReunion();
else  //deselection de la course si il n'y en a pas de selectionnee 
	if(positionManager.navigation.course==0){
				try{
				listeCliquableCourses.releaseAllItems();
				$(menuDesCoursesAppercu).innerHTML=messageParDefault;//suppression de l'appercu de la course courante.
				}catch(e){
				}
	}
//on affiche le calendrier si celui ci n'est pas a 0 :
if( positionManager.navigation.calendrier != 0  ){
	this.displayCalendrier();
}
//si il n'y a pas d'id de course et pas rapport  on affiche la grosse liste de courses et que l'etat est different du precedent :
else if( positionManager.navigation.rapport!=1 && positionManager.navigation.course == 0 
	&& ( positionManager.navigation.course!=positionManager.oldNavigation.course || 
		positionManager.navigation.reunion != positionManager.oldNavigation.reunion )
	){
	this.displayListeCourses();
	}
//sinon, si il n'y a pas le rapport, on insere le detail de la course
else if(rapport!=1 && positionManager.navigation.course!=positionManager.oldNavigation.course  ){
	this.displayCourse();
	}
//gestion de la selection des partants : 
else if( positionManager.navigation.partant != positionManager.oldNavigation.partant && rapport != 1 ){
	this.displayPartant();
}
//sinon on affiche le rapport
else  if(rapport==1){
	this.displayRapport();
}
//gestion des onglets : 
else if( positionManager.navigation.tabCourse != positionManager.oldNavigation.tabCourse ){
	this.lock=true;
	selectOngletCourseWithPos(positionManager.navigation.tabCourse);
	this.lock=false;
}
else if( positionManager.navigation.tabPartant != positionManager.oldNavigation.tabPartant ){
	this.lock=true;
	selectOngletPartantWithPos(positionManager.navigation.tabPartant);
	this.lock=false;
}else {
	//rien
}

//deselection de la reunion si celle ci est a 0 : 
if(positionManager.navigation.reunion==0){
	listeCliquableReunions.releaseAllItems();
	$$(menuDesCourses).each(function(e){e.innerHTML='';});//netoyage
	$('conteneurMenuListeDesCourses').innerHTML = "";
}



//sauvegarde de l'etat avant le dernier rafraichissement
positionManager.oldNavigation={reunion:positionManager.navigation.reunion,
							   course:positionManager.navigation.course,
							   partant:positionManager.navigation.partant,
							   rapport:positionManager.navigation.rapport,
							   tabCourse:positionManager.navigation.tabCourse,
							   tabPartant:positionManager.navigation.tabPartant,
							   calendrier:positionManager.navigation.calendrier};

//gestion de l'historique :
if( !(navigator.userAgent.toLowerCase().indexOf('chrome') > -1)){
	if( positionManager.navigation.reunion!=0||positionManager.navigation.course!=0||positionManager.navigation.partant||positionManager.navigation.rapport||positionManager.navigation.tabCourse||positionManager.navigation.tabPartant||positionManager.navigation.calendrier){
		var historyString = positionManager.navigation.reunion+"-"+positionManager.navigation.course+"-"+positionManager.navigation.partant+"-"+positionManager.navigation.rapport+"-"+positionManager.navigation.tabCourse+"-"+positionManager.navigation.tabPartant+"-"+positionManager.navigation.calendrier;
		if(YAHOO.util.History.getCurrentState("cr")!=historyString)
			YAHOO.util.History.navigate("cr",historyString);
	}
}

//gestion du cookie pour les F5 :
createCookie("state",dateActuelle+"n"+positionManager.navigation.reunion+"n"+positionManager.navigation.course+"n"+ getNumPartant(positionManager.navigation.partant)+"n"+positionManager.navigation.rapport+"n"+positionManager.navigation.tabCourse+"n"+positionManager.navigation.tabPartant+"n"+positionManager.navigation.calendrier,1);
return false;
}





///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////// SETTERS                 ////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
PositionManager.prototype.setReunion = function(o) {
if(this.lock==true)return false;
this.goTo(this.navigation.reunion=o,0,0,0,this.navigation.tabCourse,3,0);
return false;
}
PositionManager.prototype.setCourse = function(o) {
if(this.lock==true)return false;
this.goTo(this.navigation.reunion,this.navigation.course=o,0,positionManager.navigation.rapport,this.navigation.tabCourse,this.navigation.tabPartant,0);
}
PositionManager.prototype.setPartant = function(o) {
if(this.lock==true)return false;
this.goTo(this.navigation.reunion,this.navigation.course,this.navigation.partant=o,positionManager.navigation.rapport,0,this.navigation.tabPartant,0);
return false;
}
/**
 * setter pour le rapport 
 * @param o si a 1, affiche le rapport.
 * @param idCourse si diffrent de la course actuelle (rien sinon)
 */
PositionManager.prototype.setRapport = function(o,idCourse) {
if(this.lock==true)return false;
if(idCourse)this.navigation.course=idCourse;
this.goTo(this.navigation.reunion,this.navigation.course,this.navigation.partant,this.navigation.rapport=o,0,3,0);
return false;
}
PositionManager.prototype.setTabCourse = function(o) {
if(this.lock==true)return false;
this.goTo(this.navigation.reunion,this.navigation.course,this.navigation.partant,this.navigation.rapport,this.navigation.tabCourse=o,3,0);
return false;
}
PositionManager.prototype.setTabPartant = function(o) {
if(this.lock==true)return false;
this.goTo(this.navigation.reunion,this.navigation.course,this.navigation.partant,this.navigation.rapport,this.navigation.tabCourse,this.navigation.tabPartant=o,0);
return false;
}
/**
 * positionner sur le calendrier.
 * @param une chaine de caractere sur le calendrier a afficher ( ex : 'Q_20070301' pour afficher le quinte de mars 2007 ) 
 */
PositionManager.prototype.setCalendrier = function (o ){
if(this.lock==true )return false;
this.goTo(0,0,0,0,0,3,this.navigation.calendrier=o);
return false;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////// METHODE DES APPELS AJAX ////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
 * Permet d'afficher une reunion. Cette methode effectu l'appel ajax.
 * @private
 */
PositionManager.prototype.displayReunion = function (){
var url = this.urlListeCourses.interpolate({ idr: positionManager.navigation.reunion , dd: dateActuelle });
new Ajax.Request(url,{encoding:'ISO-8859-1',onSuccess: this.displayReunionCB,onFailure:this.displayReunionCBError,on404:this.displayReunionCBError,requestHeaders:this.requestHeadersOptions ,method:'get'});
url = this.urlMenuListeCourses.interpolate({ idr: positionManager.navigation.reunion , dd: dateActuelle, tc:positionManager.navigation.tabCourse });
new Ajax.Request(url,{encoding:'ISO-8859-1',onSuccess: this.displayMenuReunionCB,onFailure:this.displayMenuReunionCBError,on404:this.displayMenuReunionCBError,requestHeaders:this.requestHeadersOptions ,method:'get'});
}
/**
 * Permet d'afficher une course. Cette methode realise l'appel ajax
 * @private
 */
PositionManager.prototype.displayCourse = function (){
this.loaderMain.refresh().show();
this.lock=true;
listeCliquableCourses.clickAnElement($('itemDeListeCourse_'+positionManager.navigation.course));
this.lock=false;
var url = this.urlDetailCourse.interpolate({idr: positionManager.navigation.reunion , idc: positionManager.navigation.course , dd: dateActuelle});
new Ajax.Request(url, {encoding:'ISO-8859-1',onSuccess: this.displayCourseCB,onFailure:this.displayCourseCBError,on404:this.displayCourseCBError,requestHeaders:this.requestHeadersOptions,method:'get' });
}

/**
 * Permet d'afficher la liste des courses. Cette methode effectu l'appel ajax.
 * @private
 */
PositionManager.prototype.displayListeCourses = function (){
this.loaderMain.refresh().show();
var url = this.urlListeCoursesBig.interpolate({ idr: positionManager.navigation.reunion , dd: dateActuelle });
new Ajax.Request(url, {encoding:'ISO-8859-1',onSuccess: this.displayListeCoursesCB,onFailure:this.displayListeCoursesCBError,on404:this.displayListeCoursesCBError,requestHeaders:this.requestHeadersOptions,method:'get' });
}

/**
 * Permet d'afficher le rapport
 * @private
 */
PositionManager.prototype.displayRapport = function (){
this.loaderMain.refresh().show();
this.lock=true;
listeCliquableCourses.clickAnElement($('itemDeListeCourse_'+positionManager.navigation.course));
this.lock=false;
var url = this.urlRapport.interpolate({ idc: positionManager.navigation.course , idr: positionManager.navigation.reunion , dd: dateActuelle });
new Ajax.Request(url, {encoding:'ISO-8859-1',onSuccess: this.displayRapportCB,onFailure:this.displayRapportCBError,on404:this.displayRapportCBError,requestHeaders:this.requestHeadersOptions,method:'get' });
}

/**
 * Permet d'afficher le partant
 * @private
 */
PositionManager.prototype.displayPartant = function (){
if (loaderDetailPartant==null)loaderDetailPartant = new LoaderAjax(partieDroiteDesPartants);
loaderDetailPartant.refresh().show();
var url = this.urlDetailPartant.interpolate({idr:positionManager.navigation.reunion ,idc: positionManager.navigation.course , np: getNumPartant() , dd: dateActuelle});
new Ajax.Request(url, {encoding:'ISO-8859-1',onSuccess: this.displayPartantCB, onFailure:this.displayPartantCBError,on404:this.displayPartantCBError,parameters: {nonPartant:getIsNonPartant()},requestHeaders:this.requestHeadersOptions ,method:'get'});
}


/**
 * Permet d'afficher le calendrier des courses 
 * @private
 */
PositionManager.prototype.displayCalendrier = function (){
this.loaderMain.refresh().show();
var url = this.urlCalendrier.interpolate({args:positionManager.navigation.calendrier});
new Ajax.Request(url,{encoding:'ISO-8859-1',onSuccess:this.displayCalendrierCB,onFailure:this.displayCalendrierCBError,on404:this.displayCalendrierCBError,method:'get' });
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////// METHODE D'INSERTION AU RETOUR DES APPELS AJAX //////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
 * Permet d'inserer la liste des courses.
 * @private
 */
PositionManager.prototype.displayReunionCB = function ( transport ){
//puis on creer les nouvelles : 
$$(menuDesCourses).each(function(e){e.innerHTML='';});//nétoyage
$$(menuDesCourses+'_'+positionManager.navigation.reunion)[0].innerHTML = transport.responseText;

listeCliquableCourses = new ListeCliquable(boutonsMenuCoursesContainer,'itemDeListeOver','itemDeListe','itemDeListeClick',null,'notInList');

//gereTag : 
processTag(transport.responseText);
}


/**
* Permet d'inserer le menu de la liste des courses
* @private
*/
PositionManager.prototype.displayMenuReunionCB = function ( transport ){
$('conteneurMenuListeDesCourses').innerHTML = transport.responseText;
}



/**
 * Permet d'inserer la grosse liste des courses.
 * @private
 */
PositionManager.prototype.displayListeCoursesCB = function  ( transport ){
	
//on insert
$(contenuDuCentre).innerHTML  = transport.responseText;

//on creer les onglets :
tabbedPaneCourse = createOngletCourses();
//puis on positionne sur le bon onglet :
selectOngletCourseWithPos(positionManager.navigation.tabCourse);

positionManager.loaderMain.hide();

//initialisation des détails des courses :
initInfoCourses();

//gereTag : 
processTag(transport.responseText);

//ouverture d'un détail de la course si cela est demandé
if(infoCourseToOpen!=0){
	maskPlus(infoCourseToOpen);
	infoCourseToOpen=0;//pour ne pas réouvrir l'info sur une autre réunion
	}

}




/**
 * Permet d'inserer une course.
 * @private
 */
PositionManager.prototype.displayCourseCB = function ( transport ){
$(contenuDuCentre).innerHTML  =  transport.responseText;
//generation des onglets, on met a jourla position a chaque changement de tab :
tabbedPanePartant = createOngletPartants();
//selectionne le tab voulu
selectOngletPartantWithPos(positionManager.navigation.tabPartant);

positionManager.loaderMain.hide();

//gereTag : 
processTag(transport.responseText);
}

/***
 * Permet d'inserere le rapport dans la partie centrale
 */
PositionManager.prototype.displayRapportCB = function (transport){ 
	
$(contenuDuCentre).innerHTML=transport.responseText;
//selection de la bonne course dans la liste des courses si il faut en selectionner une :
//TODO attention bug ici ? : selectCourseWithId(positionManager.navigation.course);
//enfin on creer la navigation avec les ancres :
creerAncresPourRapport();
positionManager.loaderMain.hide();

//gereTag : 
processTag(transport.responseText);
}

/***
 * Permet d'inserere le detail du partant a droite de la partie centrale
 */
PositionManager.prototype.displayPartantCB = function (transport){ 
//selectionne le partant voulu
//positionManager.navigation.partant=selectPartantWithId(positionManager.navigation.partant);

$(partieDroiteDesPartants).innerHTML=transport.responseText;
//gestion de la petite fleche verte
if($(flecheDetailPartant)!=null  ){
		var vraiHauteur = numeroLigneSelectionnePartant - Position.cumulativeOffset($(conteneurDetailPartant))[1];
		$(flecheDetailPartant).setStyle({top:vraiHauteur+"px"});
	}
//on grandi aussi la div du detail a la taille de la liste : 
var valueHaute = $(partantListe).getHeight()-35;
if(valueHaute < 500 ) valueHaute = 500;
$(conteneurDetailPartant).setStyle({height: valueHaute+"px"});

//gestion du reflet de l'image
try{
creerReflet(imageCasaqueReflet);
}catch(e){}
loaderDetailPartant.hide();

//gereTag : 
processTag(transport.responseText);
}


/***
 * Permet d'inserere le calendrier des courses dans la partie centrale
 */
PositionManager.prototype.displayCalendrierCB = function (transport){ 
$(contenuDuCentre).innerHTML =transport.responseText;
positionManager.loaderMain.hide();
//gereTag :
processTag(transport.responseText);
}


/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////// LA GESTION DES ERREURS /////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////

/**
 * Permet d'afficher un message d'erreur lorsque le chargement du detail du partant echou
 */
PositionManager.prototype.displayPartantCBError = function (transport){
if(!$(partieDroiteDesPartants)){loaderDetailPartant.hide();return;}
$(partieDroiteDesPartants).innerHTML=templateDErreur.interpolate({lien:"positionManager.displayPartant();"});
loaderDetailPartant.hide();
}

/**
 * Permet d'afficher un message d'erreur lorsque le chargement du calendrier echou
 */
PositionManager.prototype.displayCalendrierCBError = function (transport){
$(contenuDuCentre).innerHTML=templateDErreur.interpolate({lien:"positionManager.displayCalendrier();"});
positionManager.loaderMain.hide();
}

/**
 * Permet d'afficher un message d'erreur lorsque le chargement de la liste des courses (grosse) echou
 */
PositionManager.prototype.displayListeCoursesCBError = function (transport){
$(contenuDuCentre).innerHTML=templateDErreur.interpolate({lien:"positionManager.displayListeCourses();"});
positionManager.loaderMain.hide();
}

/**
 * Permet d'afficher un message d'erreur lorsque le chargement de la liste des courses
 */
PositionManager.prototype.displayReunionCBError = function (transport){
$(menuDesCourses+'_'+positionManager.navigation.reunion)[0].innerHTML=templateDErreur.interpolate({lien:"positionManager.displayReunion();"});
}
 /**
  * Permet d'afficher un message d'erreur lorsque le chargement du menu de la liste des courses
  */
 PositionManager.prototype.displayMenuReunionCBError = function (transport){
 }
 
 
 
/**
 * Permet d'afficher un message d'erreur lorsque le chargement rapport echou
 */
PositionManager.prototype.displayRapportCBError = function (transport){
$(contenuDuCentre).innerHTML=templateDErreur.interpolate({lien:"positionManager.displayRapport();"});
positionManager.loaderMain.hide();
}

/**
 * Permet d'afficher un message d'erreur lorsque le chargement du detail d'une course echou
 */
PositionManager.prototype.displayCourseCBError = function (transport){
$(contenuDuCentre).innerHTML=templateDErreur.interpolate({lien:"positionManager.displayCourse();"});
positionManager.loaderMain.hide();
}




///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////  SINGLETON              ////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var positionManager = null;
/**
 * singleton du manager de position 
 * a instancier apres le chargement du HTML
 */
function getPositionManager(){
	return positionManager==null ? positionManager= new PositionManager() : positionManager;
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////  FUNCTIONS UTILITAIRES  ////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//ces methodes permettent d'effectuer des actions necessaires a la navigation


/**
 * Permet de selectionner une reunion d'un point de vue juste visuel. (pas de navigation).
 * @param id id de la reunion a selectionner
 */
function selectReunionWithId(id){
listeReunionsManager.viewElement($('reunion_'+id));
listeCliquableReunions.clickAnElement($('reunion_'+id));
}

/**
 * Permet de selectionner un partant avec sont id.
 * @param id id du partant a selectionner
 * @return l'id du partant que la fonction a selectionne
 *//*
function selectPartantWithId(id){
var trPartant=null;
//selection de la premiere ligne :
if(id==0){
	trPartant=$$(selecteurListeDesPartants)[0];
	id=trPartant.id.replace('row_','');
}
//ou d'une ligne precise
else {
	 trPartant=$('row_'+id);
	 if(!trPartant)trPartant=$('row_np_'+id);// ici on gere Ã©gualement les non-partants
}
//on click pour de 'faux' sur la ligne du partant :
positionManager.lock=true;
//trPartant.onmouseover(); //TODO Remettre les rollover
trPartant.onclick();
//trPartant.onmouseout();
positionManager.lock=false;

return id;
}*/

/**
 * Permet de naviguer sur les onglets des partants
 * @param pos index de l'onglet a cliquer (commence a 0)
 */
function selectOngletPartantWithPos(pos){
if(tabbedPanePartant)
tabbedPanePartant.goTo(tabbedPanePartant,pos);
}

/**
 * Permet de naviguer sur les onglets des partants
 * @param pos index de l'onglet a cliquer (commence a 0)
 */
function selectOngletCourseWithPos(pos){try{
	//var tousBoutons = ["onglet_etat","onglet_joue_simple","onglet_joue_couple","onglet_joue_couple_ordre","onglet_non_partant","onglet_pronostics","onglet_joue_simple_pari"];
	var tousBoutons = ["onglet_etat","onglet_pronostics","onglet_joue_simple","onglet_non_partant"];
	//var titreOnglet = ["Avancement","Les + jou&eacute;s","Les + jou&eacute;s","Les + jou&eacute;s","Les non-partants","Le pronostic Quint&eacute;+ <img style='margin-bottom: -3px; margin-top: -2px; vertical-align: top;' src='/pmu/img/design/calendrier/logo_GENY.gif'/>","Les + jou&eacute;s"];
	tabbedPaneCourse.goTo(pos);
	for (var i=0,max=tousBoutons.length;i<max;i++) {
		$(tousBoutons[i]).removeClassName("ChoixReuTabCurrent");
		//$$('#'+tousBoutons[i]+' .crayonSelected').each(function (e){e.removeClassName('crayon');});
	}
	$(tousBoutons[pos]).addClassName("ChoixReuTabCurrent");
	
	//if ($('titre-onglet')) {
	//	$('titre-onglet').innerHTML=titreOnglet[pos];
	//}
	//if(pos >0 && pos < 4  ){
		//$('reunion_resultat').show();
	//	$('onglet_joue_simple').addClassName("selected");
	//	if (pos==1) {
	//		$('onglet_joue_simple_pari').addClassName("selected");
	//		$$('#onglet_joue_simple_pari .crayonSelected').each(function (e){e.addClassName('crayon');});
	//	}
	//	$$('#'+tousBoutons[pos]+' .crayonSelected').each(function (e){e.addClassName('crayon');});
	//}
	//else{
		//$('reunion_resultat').hide();
	//}
	}catch(e){
		alert(e);
	}
}

/**
 * Permet recuperer le numero du partant a partir de sont ID
 * @return le numero du partant ou 1 si pas de partants trouvs 
 */
function getNumPartant(){
	if(positionManager.navigation.partant==0)return 1;
	var laListeDesPartants=$$(selecteurListeDesPartants);
	if(!laListeDesPartants)return;
	for(var i=0,max=laListeDesPartants.length;i<max;i++){
		if((laListeDesPartants[i].id).indexOf(positionManager.navigation.partant)>0)
			return i+1;
	}
	return 1;
}

/**
 * Permet de savoir si le partant est non partant ou non.
 * @return une chaine vide si le partant n'est pas un non partant. 'nonPartant' sinon
 */
function getIsNonPartant(){
	if(positionManager.navigation.partant==0)return '';
	var laListeDesPartants=$$(selecteurListeDesPartants);
	if(!laListeDesPartants)return '';
	for(var i=0,max=laListeDesPartants.length;i<max;i++){
		if((laListeDesPartants[i].id).indexOf(positionManager.navigation.partant)>0){
			if((laListeDesPartants[i].id).indexOf('row_np_')>=0)
				return 'nonPartant';
			else 
				return '';
		}
	}
	return '';
}


/**
* Permet de gerer le taggage de la page.
* Cette fonction permet d'evaluer le script contenu dans la string passÃ© en paramÃ¨tres.
* @param le contenu de la page tagge (string).
**/
function processTag(html){
html.evalScripts();
}



/**
Permet de créer les onglet de la liste des courses 
*/
function createOngletCourses(){
return new Calques(['etatDeCourse','lesPronostics','lesPlusJoueSimple','etatNonPartants']);//['etatDeCourse','lesPlusJoueSimple','lesPlusJoueCouple','lesPlusJoueCoupleOrdre','etatNonPartants','lesPronostics']);
}
/*
function ongletCoursesOnClick(e){	
	positionManager.setTabCourse(tabbedPaneCourse.current);
	if(positionManager.navigation.tabCourse!=1 && positionManager.navigation.tabCourse!=2 && positionManager.navigation.tabCourse!=4){
		$('reunion_resultat').hide();
	}else{
		$('reunion_resultat').show();
	}
}*/

function createOngletPartants(){
	return new Onglets (['ongletPartant','ongletPlusInfo1','ongletPlusInfo2','ongletPartantCotes'],['basePartant','plusInfo1','plusInfo2','ongletPartantCotes'],'selected',function (e){gestionOngletsSupplementaire(e);positionManager.setTabPartant(tabbedPanePartant.current);});		  
}/** 
 * @fileoverview Serie de fonctions utilitaires permettant de gerer les elements de la HomeClient.   
 * @author Pouleriguen Guillaume cutibipoulet@gmail.com pour Pmu.fr
 * @version 0.1
 */

//le contexte de l'appli
var contexte = '/pmu/';

var listeCourseManager = null;
var listeCliquableCourses = null;

//les loader 
var loaderDetailPartant = null;

//les onglets
var tabbedPaneCourse=null;
var tabbedPanePartant=null;

//Pour la gestion de la fleche conectant le detail d'un partant avec le tableau de la  liste des partants.
var numeroLigneSelectionnePartant = null;

///LES POP-IN Afin de ne pas ouvrir plusieur fois la meme;
var popInNonPartants=null;
var popInPlusJoue=null;
var popInCotesDeRef=null;
var popInCotesDeRefSimple=null;
var popInCotesDeRefCouple=null;
var popInPerfDet=null;
var popInPhotoArrivee=null;
var popInPronos=null;
//l'url de la radio
var urlRadio = 'http://players.tv-radio.com/equidia/audio/EquidiaFlexPlayer.php';



/**
 * permet l'affichage d'une course
 * @param (int) idCourse l'id de la course a charger
 */
function courseSelectionnee(idCourse){
return getPositionManager().setReunion(idCourse);
}


/**
 * permet de gerer les onglets ( modifications de div... ), une methode appele a chaque changement d'onglets de la liste de partants 
 * 
 */
function gestionOngletsSupplementaire(idOngletClicke){
	 //clique sur l'onglet partant
	//$$('#fakeFichePartant > a')[0].removeClassName("selected");
	 $('fakeFichePartant').firstDescendant().removeClassName("selected");
	if (idOngletClicke==0) {
		$('divPourStyleOnglets').className = "ongletPartantListe";
		$('fakeFichePartant').firstDescendant().addClassName("selected");
		//$$('#fakeFichePartant > a')[0].addClassName("selected");
		//gestion du reflet de l'image 
		// si on revien sur l'onglet 1 il faut recreer la casaque
		creerReflet('detCasaque2');
	} else if (idOngletClicke==1) {
		$('divPourStyleOnglets').className = "ongletPlusInfo1";
	} else if (idOngletClicke==2) {
		$('divPourStyleOnglets').className = "ongletPlusInfo2";
	} else if (idOngletClicke==3) {
		$('divPourStyleOnglets').className = "ongletPlusInfo1";
	}
	 
	
	
	return false;
}

/**
 * Permet de creer un reflet sur une image. Avant de creer le reflet, on s'assure que l'image est bien chargee.
 * On appel la fonction tant que l'image n'est pas chargee avec un delay de quelques secondes. 
 * Pour eviter la recurtion infini, on positionne un indice (on repete 5 fois).
 * 
 * @param l'id de l'image sur laquelle creer le reflet.
 */
function creerReflet(idImage,profondeur){
if(!profondeur)profondeur=5;if(profondeur<=0)return;
var img=$(idImage);

if(img.complete != true){window.setTimeout("creerReflet('"+idImage+"','"+(profondeur--)+"')",1000);return;}
var rheight = null;
var ropacity = null;

var classes=img.className.split(' ');
for (j=0;j<classes.length;j++) {
	if (classes[j].indexOf("rheight") == 0) {
		var rheight = classes[j].substring(7)/100;
	} else if (classes[j].indexOf("ropacity") == 0) {
		var ropacity = classes[j].substring(8)/100;
	}
}
Reflection.add(img,{height:rheight,opacity:ropacity});
return false;
}


/**
 * Permet d'ouvrir une popup qui affiche l'image du parcourt
 * @param imageUrl l'url de l'image a afficher
 */
function ouvreImageParcourt(imageUrl){
var mesChaines=[];
var imageParcourt=open("",'','width=340,height=280,toolbar=no,scrollbars=no,resizable=no');
mesChaines.push("<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>");
mesChaines.push("<html><head><title>Parcours de la R&eacute;union ");
mesChaines.push($('reunion_'+getPositionManager().navigation.reunion).innerHTML);
mesChaines.push("</title></head>");
mesChaines.push("<body><img src='");
mesChaines.push(imageUrl);
mesChaines.push("' alt='vue du parcourt' /></body></html>");
imageParcourt.document.write(mesChaines.join(''));
imageParcourt.document.close();
tag("Coursesetresultats","ParcoursQP");
}



/**
 * Fonction qui permet d'afficher les rapports
 */
function afficheRapports(idCourse){
return getPositionManager().setRapport(1,idCourse);
}
/**
 * Permet d'ouvrir le detail d'un partant dans un popin.
 * @param idCourse qui est l'id de la course
 * @param numPartant qui est le numero du partant dans la course 
 * @param casaque qui est le nom du gif de la casaque
 */
function ouvrePerf(idCourse,numPartant,casaque){
try{popInPerfDet.close()}catch(r){}
var url=contexte+'servlet/pmu.web.servlet.www.infos.PerformancesDetaillesServlet?idc='+idCourse+'&np='+numPartant+'&ppd=0&dd='+dateActuelle+'';
var titre='Performances detaill&eacute;es';
popInPerfDet=new PopIn(10,10,618,646,url,titre,false,true);
return false;
}


/**
 * fonction qui permet d'ouvrir une popUp avec les cotes de reference
 */
function ouvreCotesDeReference(idReunion,idCourse){
try{popInCotesDeRef.close();}catch(r){};
if(idReunion==null){
		idReunion=getPositionManager().navigation.reunion;
		if(idCourse==null)idCourse=getPositionManager().navigation.course;
	}
var url=contexte+'servlet/pmu.web.servlet.www.infos.cotes.CotesDeReference?idr='+idReunion+'&idc='+idCourse+'&dd='+dateActuelle;
var titre='Cotes de R&eacute;f&eacute;rences';
popInCotesDeRef=new PopIn(10,10,680,700,url,titre,false,true);
return false;
}
 
 /**
  * fonction qui permet d'ouvrir une popUp avec les cotes de reference en simple
  */
 function ouvreCotesDeReferenceSimple(idReunion,idCourse){
 try{popInCotesDeRefSimple.close();popInCotesDeRefCouple.close();}catch(r){};
 if(idReunion==null){
 		idReunion=getPositionManager().navigation.reunion;
 		if(idCourse==null)idCourse=getPositionManager().navigation.course;
 	}
 var url=contexte+'servlet/pmu.web.servlet.www.infos.cotes.CotesDeReferenceSimple?idr='+idReunion+'&idc='+idCourse+'&dd='+dateActuelle;
 var titre='Cotes en Simple';
 popInCotesDeRefSimple=new PopIn(10,10,680,268,url,titre,false,true);
 return false;
 }
 
 /**
 * fonction qui permet d'ouvrir une popUp avec les cotes de reference en couple
 */
function ouvreCotesDeReferenceCouple(idReunion,idCourse){
try{popInCotesDeRefSimple.close();popInCotesDeRefCouple.close();}catch(r){};
if(idReunion==null){
		idReunion=getPositionManager().navigation.reunion;
		if(idCourse==null)idCourse=getPositionManager().navigation.course;
	}
var url=contexte+'servlet/pmu.web.servlet.www.infos.cotes.CotesDeReferenceCouple?idr='+idReunion+'&idc='+idCourse+'&dd='+dateActuelle;
var titre='Cotes en Coupl&eacute;';
popInCotesDeRefCouple=new PopIn(10,10,680,700,url,titre,false,true);
return false;
}

 /**
  * fonction qui permet d'ouvrir une popup avec les prono
  */
 function ouvrePronos(nReunion,nCourse){
	 try{popInPronos.close();}catch(r){};
	 var url=contexte+'jsp/fr/infos/pronos.jsp?nr='+nReunion+'&nc='+nCourse+'&dd='+dateActuelleInverse;
	 var titre='Pronostics';
	 popInPronos=new PopIn(10,10,492,310,url,titre,false,false);
	 return false; 
 }

/***
 * Fonction qui permet de creer la gestion des ancres 'virtuels' pour l'affichage des rapports.
 * Cette fonction corrige égualement les images des paris. En effet, cette fonction remplace les images des pictos paris par les images de la liste des paris (les ancres).
 * Attention : pour que cela marche, il faut que la liste des paris soit dans le meme ordre que la liste des 
 * tables de resultats.
 */
function creerAncresPourRapport(){
var tablesRapport = $$('.tableRapport');
var lesLogos = $$('.logoParis');
var boutonsRapport= $$('#listeParis span span');


//corectif pour les logos que si tous les rapports sont prÃ©sents. sinon on ne corrige pas : 
if(boutonsRapport.length == lesLogos.length)
	for(var i=0,max=boutonsRapport.length;i<max;i++){
		lesLogos[i].className = boutonsRapport[i].className;
	}

//création des ancres
if(boutonsRapport.length==tablesRapport.length){
	//le curseur est la main sur les boutons des ancres
	boutonsRapport.each(function(r){r.setStyle("cursor:pointer;")});
}else {
	return;//ne pas creer les ancres si il n'y a pas les tables.
}
for(var i=0,max=boutonsRapport.length;i<max;i++){
	boutonsRapport[i].pos=Position.cumulativeOffset(tablesRapport[i]);
	boutonsRapport[i].onclick=function (){
										 scrollTo(0,this.pos[1]);
										 };
	}

return false;
}

/**
 * permet d'afficher le calendrier des courses. 
 * @param type Q pour quinte, N pour nationale, et R pour reginale.
 * @param date, la date du moi a afficher. 20070101 pour janvier, 20070201 pour fevrier...
 */
function afficheCalendrierDesCourses (type,date){
return getPositionManager().setCalendrier(type+"_"+date);	
}



/**
* Initialisation de l'application.
* Permet notament de postitioner la navigation
*/
function initPMU(){
//instanciation du position manager et on l'initialise :
if(positionManager==null)
	getPositionManager().positionWithNoMoves(idReunionSelectionnee,idCourseSelectionnee,idPartantSelectionne,rapport,ongletCourseSelectionne,ongletPartantSelectionne,0);
//init les repères :
//initReperes();
//initLes info courses :
//initInfoCourses();
//cache le login pour les gens venant de la prise de paris
//couvreLogin();
//init du fil hippique :
//setTimeout("initFilHippique()",120000);
clearCookies();
return false;
}




/**
 * Fonction appelé lorque l'initialisation du système d'historique est faite.
 * Cette fonction est par exemple appelé lors du chargement de la page ou sur un F5.
 */
YAHOO.util.History.onReady(function () {
	if(positionManager==null)
		getPositionManager().positionWithNoMoves(idReunionSelectionnee,idCourseSelectionnee,idPartantSelectionne,rapport,ongletCourseSelectionne,ongletPartantSelectionne,0);
	if(positionManager.navigation.reunion!=0||positionManager.navigation.course!=0||positionManager.navigation.partant||positionManager.navigation.rapport||positionManager.navigation.tabCourse||positionManager.navigation.tabPartant||positionManager.navigation.calendrier){
	var historyString = positionManager.navigation.reunion+"-"+positionManager.navigation.course+"-"+positionManager.navigation.partant+"-"+positionManager.navigation.rapport+"-"+positionManager.navigation.tabCourse+"-"+positionManager.navigation.tabPartant+"-"+positionManager.navigation.calendrier;
	if(YAHOO.util.History.getCurrentState("cr")!=historyString)
	YAHOO.util.History.navigate("cr",historyString);
	}
	
/*	var pm=getPositionManager();
    var myModuleCurrentState = YAHOO.util.History.getCurrentState("cr");

	var elementsDeLocalisation = myModuleCurrentState.split('-');
	if(elementsDeLocalisation.length>5){
		if(verifDateOk(elementsDeLocalisation[0])){
		pm.goTo(elementsDeLocalisation[0],elementsDeLocalisation[1],elementsDeLocalisation[2],elementsDeLocalisation[3],elementsDeLocalisation[4],elementsDeLocalisation[5],elementsDeLocalisation[6]);	
		}else{//erreur dans le bookmark
		pm.goTo(idReunionSelectionnee);
		}
	}
	else{
		pm.goTo(idReunionSelectionnee,idCourseSelectionnee,idPartantSelectionne,rapport,ongletCourseSelectionne,ongletPartantSelectionne);
	}*/
});



/**
 * Permet de voir si la réunion est bien disponible dans le code HTML.
 * C'est utile pour la gestion des bookmarks, à un utilisateur ayant bookmarqué une vielle date, partira en erreur sans cette vérification
 * @param idAverifier un identifiant de réunion à  vérifier. si l'id est présent dans la page, on retourne true. sinon on retourne false.
 **/
function verifDateOk(idAverifier){
return $('contenueListeReunions').innerHTML.include(idAverifier);
}

/**
 * Permet d'afficher le lecteur radio.
 */
function viewRadio(){
window.open(urlRadio,'', 'resizable=no, location=no, width=550, height=100, menubar=no, status=no, scrollbars=no, menubar=no');
}

/*
 * Permet d'afficher la popupVideo.
 * @param nr le numéro de réunion
 * @param idc l'id de la course
 * @param title le titre de la fenetre
 */      
function viewVideoPopUp(nr,nc,title){
var dateCH = dateActuelle.substring(0,2)+'-'+dateActuelle.substring(2,4)+'-'+dateActuelle.substring(4,8);
var urlVideo="http://www.equidiavideo.fr/rarchive.aspx?dtr="+dateCH+"&ext="+nr+"&pmu="+nc+"&dur=L&ref=PMU";
var win = window.open(urlVideo, "");
if(win==null)alert("Vous devez autoriser les popup pour voir la vidéo.")
tag("Coursesetresultats","PopUpCHVideo","fr.videos");
}

/**
* Permet d'afficher la popupVideo du quinté+.
*/
function viewVideoPopUpQP(){
var urlVideo='http://players.tv-radio.com/equidia/player.php';
var fenetreVideo=window.open('','', 'resizable=no, location=no, width=478, height=320, menubar=no, status=no, scrollbars=no, menubar=no');
fenetreVideo.document.write('<html><head><TITLE>La course Quint&eacute;+ du jour.</TITLE></head><body style="margin:0;"><iframe src="'+urlVideo+'" frameborder="0" marginwidth="0" marginheight="0" width="478" height="320" style="overflow:hidden;"  /></body></html>');
fenetreVideo.document.close();
tag("Coursesetresultats","PopUpVideo");
}


/**
 * Permet de masquer les 'plus' d'une certaine ligne
 * @param l'id de la course dont on masque les plus 
 */
function maskPlus(idCourse){
	$('infoContex_'+idCourse).show();
	$$('.infoContexPlus_'+idCourse).each(function (e){
					e.hide();
					}
				);
	tag("Coursesetresultats","PlusInfoOpen");
return false;
}

/***
 * Permet de voir les 'plus' d'une certaine ligne
 * @param l'id de la course dont on masque les plus 
 */
function viewPlus(idCourse){
	$('infoContex_'+idCourse).hide();
	$$('.infoContexPlus_'+idCourse).each(function (e){
		e.show();
	});
return false;
}

/**
 * Permet d'afficher la page pour l'impression. HAck pour etre corss browser et garder le "vrai"
 * habillage.
 */
function viewPrint(){
var mesChaines=[];
var popUp=window.open("",'','width=520px,height='+screen.height*0.8+'px,toolbar=no,scrollbars=no,resizable=yes,status=no,location=no,directories=no,menubar=no');
mesChaines.push("<html><head><title>COURSES ET RESULTATS : ");
try{mesChaines.push('PRIX '+$$('#prix .gris')[0].innerHTML);}catch(e){
	//probablement le calendrier
	try{mesChaines.push('CALENDRIER DES COURSES');}catch(s){}
}
mesChaines.push("</title><style>");
var lesStyles = $$('style');
for (var i=0;i<lesStyles.length;i++)
	mesChaines.push(lesStyles[i].innerHTML);
mesChaines.push("#cr_contenu *{font-size:11px;} </style>");
var lesStyles = $$('link');
for (var i=0;i<lesStyles.length;i++)
	mesChaines.push('<LINK REL=StyleSheet HREF="'+lesStyles[i].href+'" TYPE="text/css" />');
mesChaines.push('<script  type="text/javascript" src="/pmu/js/prototype.js"  ></script><script  type="text/javascript" src="/pmu/js/homeclient/print/print.js"  ></script>');
mesChaines.push("</head>");
mesChaines.push("<body onload='preparePrint()' >");
mesChaines.push("<div id='container' style='width:100%;height:100%;overflow:auto;'>");
//la partie CR :
mesChaines.push("<div id='cr_contenu'>");
mesChaines.push($('cr_contenu').innerHTML);
mesChaines.push("</div>");
mesChaines.push("</body></html>");
popUp.document.write(mesChaines.join(''));
popUp.document.close();
return false;
}


/**
 * Permet d'initialiser les info course (parse et rend le BBCODE)
 */
function initInfoCourses(){
//pour les infos course
$$('#toutes_lesCourses p').each(function (e){e.update(transformBBCode(e.innerHTML));});
return false;
}

/**
 * Permet d'initialiser les repères (parse et rend le BBCODE)
 */
function initReperes(){
//pour les repères :
$$("#fil_info div").each(function (e){e.update(transformBBCode(e.innerHTML));});
return false;
}

/**
 * Permet d'initialiser la mise a jour automatique du fil hippique
 */
function initFilHippique(){
new Ajax.PeriodicalUpdater('filh', contexte+'jsp/fr/infos/FilHippique.jsp', {method: 'get', frequency: 120, decay: 1});
}



/**
 * Affiche une popin avec un détail de partant (le même que l'on voi dans la liste des partants d'une course)
 * La popin est non externalizable à  cause du lien vers plus de dÃ©tails 
 * @param dd la date de partant dans la course sous forme JJMMYYYY
 * @param idc l'id de la course du partant
 * @param num partant, le numéro du partant ds la course
 * @param nomPartant le nom du partant ( sera affiché dans le titre de la popIn )
 **/
function popInDetailPartant(dd,idc,numPartant,nomPartant){
new PopIn(57,82,233,552,'/pmu/servlet/pmu.web.servlet.www.homeclient.DetailPartantBig?idc='+idc+'&np='+numPartant+'&dd='+dd+'&nonPartant=',nomPartant,false,false,true,false);
}
 
/**
 * Permet de recharger le calendrier de la gauche en ajax.
 * @param dd la date du jour au format 25042008
 * @param mc le mois du calendrier cherché au format 01022009  (le jour est toujour 01)
 */
function loadCalendar(mc){
var url = '/pmu/jsp/fr/homeclient/calendrier/calendrierNavigation.jsp?dd='+dateActuelle+'&mc='+mc;
new Ajax.Updater('calendrier',url);
return false;
}

/**
 * Permet de creer des onglets
 */
var Onglets = Class.create();
Onglets.prototype = {
initialize: function(tableauDeDivDesOnglets,tableauDesClassesAAfficherParOnglet,classSelected,theCbFunction) {

this.tabOnglets = tableauDeDivDesOnglets;
this.tabContenu = tableauDesClassesAAfficherParOnglet;
this.classSelected = classSelected;
this.cbFunction = theCbFunction;
this.current = 0;
//les div des contenus (en tableau selon leurs onglet)
this.lesContenus=new Array();
for (var i = 0 ; i < this.tabContenu.length;i++) this.lesContenus.push($$("."+this.tabContenu[i]));

//event sur les onglets : 
for (var i = 0 ; i < this.tabOnglets.length;i++)Event.observe($(this.tabOnglets[i]), 'click', this.goTo.bindAsEventListener(this,i));
},
//change d'onglet
goTo: function(e,f) {
this.current=f;
//contenu des onglets
for (var i = 0 ; i < this.tabContenu.length;i++) this.lesContenus[i].invoke("hide");
this.lesContenus[f].invoke("show");
//gestion du visuel de l'onglet :
for (var i = 0 ; i < this.tabOnglets.length;i++)$(this.tabOnglets[i]).removeClassName(this.classSelected);
$(this.tabOnglets[f]).addClassName(this.classSelected);
try{this.cbFunction(f);}catch(ex){}
return false;},
next:function (){if(this.current<this.tabContenu.length-1)this.goTo(this,this.current+1);return false;},
prev:function (){if(this.current>0)this.goTo(this,this.current-1);return false;}
};



var Calques = Class.create();
Calques.prototype = {
initialize: function(tableauDesClassesAAfficherParOnglet) {
this.tabContenu = tableauDesClassesAAfficherParOnglet;
this.current = 0;
this.lesContenus=new Array();
for (var i = 0 ; i < this.tabContenu.length;i++) this.lesContenus.push($$("."+this.tabContenu[i]));
},
goTo: function(numCalque) {
this.current=numCalque;
for (var i = 0 ; i < this.tabContenu.length;i++) this.lesContenus[i].invoke("hide");
this.lesContenus[numCalque].invoke("show");
return false}};


/**
 * ouvre une popUp. 
 * @param purl l'url a charger ds la popUp
 * @param pwidth la largeur de la popUp
 * @param pheight la hauteur de la popUp a charger 
 * 
 */
function openPopup(purl, pwidth, pheight) {
var win=window.open(purl, self.Ouverte, "resizable=no,scrollbars=yes,status=no,menubar=no,directories=no,location=no,width=" + pwidth + ",height=" + pheight + ",closed=no,opener=no");
if( !win )alert ('Veuillez desactiver le bloquer de popUp de votre navigateur.');
return false;
}
