/*  Prototype JavaScript framework, version 1.3.1
 *  (c) 2005 Sam Stephenson <sam@conio.net>
 *
 *  THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
 *  against the source tree, available from the Prototype darcs repository. 
 *
 *  Prototype is freely distributable under the terms of an MIT-style license.
 *
 *  For details, see the Prototype web site: http://prototype.conio.net/
 *
/*--------------------------------------------------------------------------*/

var Prototype = {
  Version: '1.3.1',
  emptyFunction: function() {}
}

var Class = {
  create: function() {
    return function() { 
      this.initialize.apply(this, arguments);
    }
  }
}

var Abstract = new Object();

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

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

Function.prototype.bind = function(object) {
  var __method = this;
  return function() {
    __method.apply(object, arguments);
  }
}

Function.prototype.bindAsEventListener = function(object) {
  var __method = this;
  return function(event) {
    __method.call(object, event || window.event);
  }
}

Number.prototype.toColorPart = function() {
  var digits = this.toString(16);
  if (this < 16) return '0' + digits;
  return digits;
}

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

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

    return returnValue;
  }
}

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

var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype = {
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;

    this.registerCallback();
  },

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

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try { 
        this.currentlyExecuting = true;
        this.callback(); 
      } finally { 
        this.currentlyExecuting = false;
      }
    }
  }
}

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

function $() {
  var elements = new Array();

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

    if (arguments.length == 1) 
      return element;

    elements.push(element);
  }

  return elements;
}

if (!Array.prototype.push) {
  Array.prototype.push = function() {
		var startLength = this.length;
		for (var i = 0; i < arguments.length; i++)
      this[startLength + i] = arguments[i];
	  return this.length;
  }
}

if (!Function.prototype.apply) {
  // Based on code from http://www.youngpup.net/
  Function.prototype.apply = function(object, parameters) {
    var parameterStrings = new Array();
    if (!object)     object = window;
    if (!parameters) parameters = new Array();
    
    for (var i = 0; i < parameters.length; i++)
      parameterStrings[i] = 'parameters[' + i + ']';
    
    object.__apply__ = this;
    var result = eval('object.__apply__(' + 
      parameterStrings.join(', ') + ')');
    object.__apply__ = null;
    
    return result;
  }
}

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

  escapeHTML: function() {
    var div = document.createElement('div');
    var text = document.createTextNode(this);
    div.appendChild(text);
    return div.innerHTML;
  },

  unescapeHTML: function() {
    var div = document.createElement('div');
    div.innerHTML = this.stripTags();
    return div.childNodes[0].nodeValue;
  }
});

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

Ajax.Base = function() {};
Ajax.Base.prototype = {
  setOptions: function(options) {
    this.options = {
      method:       'post',
      asynchronous: true,
      parameters:   ''
    }.extend(options || {});
  },

  responseIsSuccess: function() {
    return this.transport.status == 'undefined'
        || this.transport.status == 0 
        || (this.transport.status >= 200 && this.transport.status < 300);
  },

  responseIsFailure: function() {
    return !this.responseIsSuccess();
  }
}

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

Ajax.Request.prototype = (new Ajax.Base()).extend({
  initialize: function(url, options) {
    this.transport = Ajax.getTransport();
    this.setOptions(options);
    this.request(url);
  },

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

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

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

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

      this.setRequestHeaders();

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

    } catch (e) {
    }
  },

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

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

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

    if (this.options.requestHeaders)
      requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);

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

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

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

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

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

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

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

Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
  initialize: function(container, url, options) {
    this.containers = {
      success: container.success ? $(container.success) : $(container),
      failure: container.failure ? $(container.failure) :
        (container.success ? null : $(container))
    }

    this.transport = Ajax.getTransport();
    this.setOptions(options);

    var onComplete = this.options.onComplete || Prototype.emptyFunction;
    this.options.onComplete = (function() {
      this.updateContent();
      onComplete(this.transport);
    }).bind(this);

    this.request(url);
  },

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

    var match    = new RegExp(Ajax.Updater.ScriptFragment, 'img');
    var response = this.transport.responseText.replace(match, '');
    var scripts  = this.transport.responseText.match(match);

    if (receiver) {
      if (this.options.insertion) {
        new this.options.insertion(receiver, response);
      } else {
        receiver.innerHTML = response;
      }
    }

    if (this.responseIsSuccess()) {
      if (this.onComplete)
        setTimeout((function() {this.onComplete(
          this.transport)}).bind(this), 10);
    }

    if (this.options.evalScripts && scripts) {
      match = new RegExp(Ajax.Updater.ScriptFragment, 'im');
      setTimeout((function() {
        for (var i = 0; i < scripts.length; i++)
          eval(scripts[i].match(match)[1]);
      }).bind(this), 10);
    }
  }
});

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

    this.frequency = (this.options.frequency || 2);
    this.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.onComplete = undefined;
    clearTimeout(this.timer);
    (this.onComplete || Ajax.emptyFunction).apply(this, arguments);
  },

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

      this.lastText = request.responseText;
    }
    this.timer = setTimeout(this.onTimerEvent.bind(this), 
      this.decay * this.frequency * 1000);
  },

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

document.getElementsByClassName = function(className) {
  var children = document.getElementsByTagName('*') || document.all;
  var elements = new Array();
  
  for (var i = 0; i < children.length; i++) {
    var child = children[i];
    var classNames = child.className.split(' ');
    for (var j = 0; j < classNames.length; j++) {
      if (classNames[j] == className) {
        elements.push(child);
        break;
      }
    }
  }
  
  return elements;
}

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

if (!window.Element) {
  var Element = new Object();
}

Object.extend(Element, {
  toggle: function() {
    for (var i = 0; i < arguments.length; i++) {
      var element = $(arguments[i]);
      element.style.display = 
        (element.style.display == 'none' ? '' : 'none');
    }
  },

  hide: function() {
    for (var i = 0; i < arguments.length; i++) {
      var element = $(arguments[i]);
      element.style.display = 'none';
    }
  },

  show: function() {
    for (var i = 0; i < arguments.length; i++) {
      var element = $(arguments[i]);
      element.style.display = '';
    }
  },

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

  hasClassName: function(element, className) {
    element = $(element);
    if (!element)
      return;
    var a = element.className.split(' ');
    for (var i = 0; i < a.length; i++) {
      if (a[i] == className)
        return true;
    }
    return false;
  },

  addClassName: function(element, className) {
    element = $(element);
    Element.removeClassName(element, className);
    element.className += ' ' + className;
  },

  removeClassName: function(element, className) {
    element = $(element);
    if (!element)
      return;
    var newClassName = '';
    var a = element.className.split(' ');
    for (var i = 0; i < a.length; i++) {
      if (a[i] != className) {
        if (i > 0)
          newClassName += ' ';
        newClassName += a[i];
      }
    }
    element.className = newClassName;
  },
  
  // removes whitespace-only text node children
  cleanWhitespace: function(element) {
    var element = $(element);
    for (var i = 0; i < element.childNodes.length; i++) {
      var node = element.childNodes[i];
      if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) 
        Element.remove(node);
    }
  }
});

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

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

Abstract.Insertion = function(adjacency) {
  this.adjacency = adjacency;
}

Abstract.Insertion.prototype = {
  initialize: function(element, content) {
    this.element = $(element);
    this.content = content;
    
    if (this.adjacency && this.element.insertAdjacentHTML) {
      this.element.insertAdjacentHTML(this.adjacency, this.content);
    } else {
      this.range = this.element.ownerDocument.createRange();
      if (this.initializeRange) this.initializeRange();
      this.fragment = this.range.createContextualFragment(this.content);
      this.insertContent();
    }
  }
}

var Insertion = new Object();

Insertion.Before = Class.create();
Insertion.Before.prototype = (new Abstract.Insertion('beforeBegin')).extend({
  initializeRange: function() {
    this.range.setStartBefore(this.element);
  },
  
  insertContent: function() {
    this.element.parentNode.insertBefore(this.fragment, this.element);
  }
});

Insertion.Top = Class.create();
Insertion.Top.prototype = (new Abstract.Insertion('afterBegin')).extend({
  initializeRange: function() {
    this.range.selectNodeContents(this.element);
    this.range.collapse(true);
  },
  
  insertContent: function() {  
    this.element.insertBefore(this.fragment, this.element.firstChild);
  }
});

Insertion.Bottom = Class.create();
Insertion.Bottom.prototype = (new Abstract.Insertion('beforeEnd')).extend({
  initializeRange: function() {
    this.range.selectNodeContents(this.element);
    this.range.collapse(this.element);
  },
  
  insertContent: function() {
    this.element.appendChild(this.fragment);
  }
});

Insertion.After = Class.create();
Insertion.After.prototype = (new Abstract.Insertion('afterEnd')).extend({
  initializeRange: function() {
    this.range.setStartAfter(this.element);
  },
  
  insertContent: function() {
    this.element.parentNode.insertBefore(this.fragment, 
      this.element.nextSibling);
  }
});

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

  focus: function(element) {
    $(element).focus();
  },
  
  present: function() {
    for (var i = 0; i < arguments.length; i++)
      if ($(arguments[i]).value == '') return false;
    return true;
  },
  
  select: function(element) {
    $(element).select();
  },
   
  activate: function(element) {
    $(element).focus();
    $(element).select();
  }
}

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

var Form = {
  serialize: function(form) {
    var elements = Form.getElements($(form));
    var queryComponents = new Array();
    
    for (var i = 0; i < elements.length; i++) {
      var queryComponent = Form.Element.serialize(elements[i]);
      if (queryComponent)
        queryComponents.push(queryComponent);
    }
    
    return queryComponents.join('&');
  },
  
  getElements: function(form) {
    var form = $(form);
    var elements = new Array();

    for (tagName in Form.Element.Serializers) {
      var tagElements = form.getElementsByTagName(tagName);
      for (var j = 0; j < tagElements.length; j++)
        elements.push(tagElements[j]);
    }
    return elements;
  },
  
  getInputs: function(form, typeName, name) {
    var form = $(form);
    var inputs = form.getElementsByTagName('input');
    
    if (!typeName && !name)
      return inputs;
      
    var matchingInputs = new Array();
    for (var i = 0; i < inputs.length; i++) {
      var input = inputs[i];
      if ((typeName && input.type != typeName) ||
          (name && input.name != name)) 
        continue;
      matchingInputs.push(input);
    }

    return matchingInputs;
  },

  disable: function(form) {
    var elements = Form.getElements(form);
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      element.blur();
      element.disabled = 'true';
    }
  },

  enable: function(form) {
    var elements = Form.getElements(form);
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      element.disabled = '';
    }
  },

  focusFirstElement: function(form) {
    var form = $(form);
    var elements = Form.getElements(form);
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      if (element.type != 'hidden' && !element.disabled) {
        Field.activate(element);
        break;
      }
    }
  },

  reset: function(form) {
    $(form).reset();
  }
}

Form.Element = {
  serialize: function(element) {
    var element = $(element);
    var method = element.tagName.toLowerCase();
    var parameter = Form.Element.Serializers[method](element);
    
    if (parameter)
      return encodeURIComponent(parameter[0]) + '=' + 
        encodeURIComponent(parameter[1]);                   
  },
  
  getValue: function(element) {
    var element = $(element);
    var method = element.tagName.toLowerCase();
    var parameter = Form.Element.Serializers[method](element);
    
    if (parameter) 
      return parameter[1];
  }
}

Form.Element.Serializers = {
  input: function(element) {
    switch (element.type.toLowerCase()) {
      case 'submit':
      case 'hidden':
      case 'password':
      case 'text':
        return Form.Element.Serializers.textarea(element);
      case 'checkbox':  
      case 'radio':
        return Form.Element.Serializers.inputSelector(element);
    }
    return false;
  },

  inputSelector: function(element) {
    if (element.checked)
      return [element.name, element.value];
  },

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

  select: function(element) {
    var value = '';
    if (element.type == 'select-one') {
      var index = element.selectedIndex;
      if (index >= 0)
        value = element.options[index].value || element.options[index].text;
    } else {
      value = new Array();
      for (var i = 0; i < element.length; i++) {
        var opt = element.options[i];
        if (opt.selected)
          value.push(opt.value || opt.text);
      }
    }
    return [element.name, value];
  }
}

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

var $F = Form.Element.getValue;

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

Abstract.TimedObserver = function() {}
Abstract.TimedObserver.prototype = {
  initialize: function(element, frequency, callback) {
    this.frequency = frequency;
    this.element   = $(element);
    this.callback  = callback;
    
    this.lastValue = this.getValue();
    this.registerCallback();
  },
  
  registerCallback: function() {
    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },
  
  onTimerEvent: function() {
    var value = this.getValue();
    if (this.lastValue != value) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  }
}

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

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

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

Abstract.EventObserver = function() {}
Abstract.EventObserver.prototype = {
  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() {
    var elements = Form.getElements(this.element);
    for (var i = 0; i < elements.length; i++)
      this.registerCallback(elements[i]);
  },
  
  registerCallback: function(element) {
    if (element.type) {
      switch (element.type.toLowerCase()) {
        case 'checkbox':  
        case 'radio':
          element.target = this;
          element.prev_onclick = element.onclick || Prototype.emptyFunction;
          element.onclick = function() {
            this.prev_onclick(); 
            this.target.onElementEvent();
          }
          break;
        case 'password':
        case 'text':
        case 'textarea':
        case 'select-one':
        case 'select-multiple':
          element.target = this;
          element.prev_onchange = element.onchange || Prototype.emptyFunction;
          element.onchange = function() {
            this.prev_onchange(); 
            this.target.onElementEvent();
          }
          break;
      }
    }    
  }
}

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

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


if (!window.Event) {
  var Event = new Object();
}

Object.extend(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,

  element: function(event) {
    return event.target || event.srcElement;
  },

  isLeftClick: function(event) {
    return (((event.which) && (event.which == 1)) ||
            ((event.button) && (event.button == 1)));
  },

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

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

  stop: function(event) {
    if (event.preventDefault) { 
      event.preventDefault(); 
      event.stopPropagation(); 
    } else {
      event.returnValue = false;
    }
  },

  // find the first node with the given tagName, starting from the
  // node the event was triggered on; traverses the DOM upwards
  findElement: function(event, tagName) {
    var element = Event.element(event);
    while (element.parentNode && (!element.tagName ||
        (element.tagName.toUpperCase() != tagName.toUpperCase())))
      element = element.parentNode;
    return element;
  },

  observers: false,
  
  _observeAndCache: function(element, name, observer, useCapture) {
    if (!this.observers) this.observers = [];
    if (element.addEventListener) {
      this.observers.push([element, name, observer, useCapture]);
      element.addEventListener(name, observer, useCapture);
    } else if (element.attachEvent) {
      this.observers.push([element, name, observer, useCapture]);
      element.attachEvent('on' + name, observer);
    }
  },
  
  unloadCache: function() {
    if (!Event.observers) return;
    for (var i = 0; i < Event.observers.length; i++) {
      Event.stopObserving.apply(this, Event.observers[i]);
      Event.observers[i][0] = null;
    }
    Event.observers = false;
  },

  observe: function(element, name, observer, useCapture) {
    var element = $(element);
    useCapture = useCapture || false;
    
    if (name == 'keypress' &&
        ((navigator.appVersion.indexOf('AppleWebKit') > 0) 
        || element.attachEvent))
      name = 'keydown';
    
    this._observeAndCache(element, name, observer, useCapture);
  },

  stopObserving: function(element, name, observer, useCapture) {
    var element = $(element);
    useCapture = useCapture || false;
    
    if (name == 'keypress' &&
        ((navigator.appVersion.indexOf('AppleWebKit') > 0) 
        || element.detachEvent))
      name = 'keydown';
    
    if (element.removeEventListener) {
      element.removeEventListener(name, observer, useCapture);
    } else if (element.detachEvent) {
      element.detachEvent('on' + name, observer);
    }
  }
});

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

var Position = {

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

  // must be called before calling withinIncludingScrolloffset, every time the
  // page is scrolled
  prepare: function() {
    this.deltaX =  window.pageXOffset 
                || document.documentElement.scrollLeft 
                || document.body.scrollLeft 
                || 0;
    this.deltaY =  window.pageYOffset 
                || document.documentElement.scrollTop 
                || document.body.scrollTop 
                || 0;
  },

  realOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.scrollTop  || 0;
      valueL += element.scrollLeft || 0; 
      element = element.parentNode;
    } while (element);
    return [valueL, valueT];
  },

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

  // caches x/y coordinate pair to use with overlap
  within: function(element, x, y) {
    if (this.includeScrollOffsets)
      return this.withinIncludingScrolloffsets(element, x, y);
    this.xcomp = x;
    this.ycomp = y;
    this.offset = this.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 = this.realOffset(element);

    this.xcomp = x + offsetcache[0] - this.deltaX;
    this.ycomp = y + offsetcache[1] - this.deltaY;
    this.offset = this.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);
  },

  // within must be called directly before
  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;
  },

  clone: function(source, target) {
    source = $(source);
    target = $(target);
    target.style.position = 'absolute';
    var offsets = this.cumulativeOffset(source);
    target.style.top    = offsets[1] + 'px';
    target.style.left   = offsets[0] + 'px';
    target.style.width  = source.offsetWidth + 'px';
    target.style.height = source.offsetHeight + 'px';
  }
}


var jsvMaxcharLengthArray = Array();

var jsvIsIE501 = navigator.userAgent.indexOf("MSIE 5.01") > 0 ? true : false;
var jsvIsNN6 = navigator.userAgent.indexOf("Netscape6") > 0 ? true : false;
var jsvIsIE=document.all&&navigator.userAgent.indexOf("Opera")==-1;

Event.observe(window, 'load', jsfInit, false);

function getElementsByName_iefix(tag, name)
{
     var elem = document.getElementsByTagName(tag);
     var arr = new Array();
     for(i = 0,iarr = 0; i < elem.length; i++) {
          att = elem[i].getAttribute("name");
          if(att == name) {
               arr[iarr] = elem[i];
               iarr++;
          }
     }
     return arr;
}

function contractAll()
{
	var togs, contents, hide;
	
	if (jsvIsIE)
	{
		togs = getElementsByName_iefix("div", "reduceToggle");
		contents = getElementsByName_iefix("div", "content");
	}
	else
	{
		togs = document.getElementsByName("reduceToggle");
		contents = document.getElementsByName("content");
	}
	
	for (i=0; i<togs.length; i++)
	{
		var baseURL = self.location.href;
		var anc = baseURL.split("#")[1];

		if (jsvIsIE)
		{
			if (togs[i].parentElement.parentElement.children[0].name != anc)
			{
				togs[i].style.display = "none";
				contents[i].style.display = "none";
			}
		}
		else
		{
			if (togs[i].parentNode.parentNode.childNodes[1].name != anc)
			{
				togs[i].style.display = "none";
				contents[i].style.display = "none";
			}
		}
	}
}

function jsfToggleMenu(self)
{
	if (jsvIsIE) 
	{
		if (self.parentElement.parentElement.children[0].style.display == "none")
		{
			self.parentElement.parentElement.children[0].style.display = "";
			self.parentElement.parentElement.children[1].style.display = "none";
			self.parentElement.parentElement.parentElement.children[2].children[1].style.display = "none";
		} else {
			self.parentElement.parentElement.children[0].style.display = "none";
			self.parentElement.parentElement.children[1].style.display = "";
			self.parentElement.parentElement.parentElement.children[2].children[1].style.display = "";
		}
	} else {
		if (self.parentNode.parentNode.childNodes[1].style.display == "none")
		{
			self.parentNode.parentNode.childNodes[1].style.display = "";
			self.parentNode.parentNode.childNodes[3].style.display = "none";
			self.parentNode.parentNode.parentNode.childNodes[5].childNodes[3].style.display = "none";
		} else {
			self.parentNode.parentNode.childNodes[1].style.display = "none";
			self.parentNode.parentNode.childNodes[3].style.display = "";
			self.parentNode.parentNode.parentNode.childNodes[5].childNodes[3].style.display = "";
		}
	}
}

function jsfInit()
{
	jsfBalanceTables();
}

function jsfBalanceTables()
{
	tables = document.getElementsByClassName("jsBalanceColumns");
	//exit if there is only one table
	if(tables.length<2)
	{
		return;
	}
	var firstTRFound;
	//count all letters in cells get maxium for each column
	for(a=0;a<tables.length;a++)
	{
		firstTRFound = false;
		//find TBODY
		for(b=0;b<tables[a].childNodes.length;b++)
		{
			if(tables[a].childNodes[b].nodeName=="TBODY")
			{
				//get first TR
				for(c=0;c<tables[a].childNodes[b].childNodes.length;c++)
				{
					if(tables[a].childNodes[b].childNodes[c].nodeName=="TR"&&!firstTRFound)
					{
						firstTRFound = true;
						jsfCollectCellTextLength(tables[a].childNodes[b].childNodes[c]);
					}
				}
			}
		}
	}
	//convert values into percentages
	columnWidthArray = jsfConvertValuesToPercentage(jsvMaxcharLengthArray);
	
	for(a=0;a<tables.length;a++)
	{
		firstTRFound = false;
		//find TBODY
		for(b=0;b<tables[a].childNodes.length;b++)
		{
			if(tables[a].childNodes[b].nodeName=="TBODY")
			{
				//get first TR
				for(c=0;c<tables[a].childNodes[b].childNodes.length;c++)
				{
					if(tables[a].childNodes[b].childNodes[c].nodeName=="TR"&&!firstTRFound)
					{
						//set column widths
						firstTRFound = true;
						setColumnWidths(columnWidthArray,tables[a].childNodes[b].childNodes[c]);
						
					}
				}
			}
		}
	}
}

function jsfConvertValuesToPercentage(theArray)
{
	totalValue = 0;
	for(f=0;f<theArray.length;f++)
	{
		totalValue+=theArray[f];
	}
	percArray = Array();
	for(f=0;f<theArray.length;f++)
	{
		percArray.push(Math.round(theArray[f]/totalValue*100));
	}
	return percArray;
}

function setColumnWidths(widthArray,row)
{
	cell = 0;
	for(g=0;g<row.childNodes.length;g++)
	{
		if(row.childNodes[g].nodeName=="TD"||row.childNodes[g].nodeName=="TH")
		{
			if (row.childNodes[g].colSpan != null && row.childNodes[g].colSpan > 1)
			{
				var tempLength = 0;
				for (i=0; i<row.childNodes[g].colSpan; i++)
				{
					tempLength += widthArray[cell+i];
				}
				row.childNodes[g].style.width=tempLength+"%";
//				row.childNodes[g].style.width=(widthArray[cell]*row.childNodes[g].colSpan)+"%";
				cell+=row.childNodes[g].colSpan;
			}
			else
			{
				row.childNodes[g].style.width=widthArray[cell]+"%";
				cell++;
			}
		}
	}
}

function jsfCollectCellTextLength(row)
{
	if(row==null)
	{
		return;	
	}
	firstPass = jsvMaxcharLengthArray.length==0?true:false;
	
	cell = 0;
	//go through each td/th
	for(d=0;d<row.childNodes.length;d++)
	{
		//find TD or TH
		if((row.childNodes[d].nodeName=="TD"||row.childNodes[d].nodeName=="TH"))
		{
			for(e=0;e<row.childNodes[d].childNodes.length;e++)
			{
				//find text node
				if(row.childNodes[d].childNodes[e].nodeType==3)
				{
					//alert(row.childNodes[d].childNodes[e].nodeValue);
					if(firstPass)
					{
						if (row.childNodes[d].colSpan != null && row.childNodes[d].colSpan > 1)
						{
							for (x=0; x<row.childNodes[d].colSpan; x++)
							{
								jsvMaxcharLengthArray.push((getStringDisplayLength(row.childNodes[d].childNodes[e].nodeValue)/row.childNodes[d].colSpan));
							}
						}
						else
						{
							jsvMaxcharLengthArray.push(getStringDisplayLength(row.childNodes[d].childNodes[e].nodeValue));
						}
					}
					else
					{
						
						if (row.childNodes[d].colSpan != null)
						{
							for (x=0; x<row.childNodes[d].colSpan; x++)
							{
								jsvMaxcharLengthArray[cell+x] = jsvMaxcharLengthArray[cell+x]<(getStringDisplayLength(row.childNodes[d].childNodes[e].nodeValue) / row.childNodes[d].colSpan)?(getStringDisplayLength(row.childNodes[d].childNodes[e].nodeValue) / row.childNodes[d].colSpan):jsvMaxcharLengthArray[cell+x];
							}
							cell+=row.childNodes[d].colSpan;
						} 
						else
						{
							jsvMaxcharLengthArray[cell] = jsvMaxcharLengthArray[cell]<getStringDisplayLength(row.childNodes[d].childNodes[e].nodeValue)?getStringDisplayLength(row.childNodes[d].childNodes[e].nodeValue):jsvMaxcharLengthArray[cell];
							cell++;
						}
					}
				}
			}
		}
	}
	//find the next row in the table and recurse
	jsfCollectCellTextLength(getNextSibling(row,"TR"));
}


function getStringDisplayLength(theString)
{
	theLength = 0;
	for(i=0;i<theString.length;i++)		
	{
		theLength+=(getCharDisplayLength(theString.charAt(i)));
	}
	return theLength;
}

function getCharDisplayLength(theChar)
{
	switch(theChar)
	{
		case 'i':
		case 'j':
		case 'i':
		case 'j':
		case '.':
		case ',':
			return 1;
		case 'f':
		case 'r':
		case 't':
			return 3;
		case 'k':
		case 's':
		case 'J':
			return 4;
		case 'i':
		case 'j':
		case 'l':
		case 'I':
		case '.':
		case ',':
		case 'f':
		case 'r':
		case 't':
		case 'k':
		case 's':
		case 'J':
		case 'a':
		case 'b':
		case 'c':
		case 'd':
		case 'e':
		case 'g':
		case 'h':
		case 'n':
		case 'o':
		case 'p':
		case 'q':
		case 'u':
		case 'v':
		case 'x':
		case 'Y':
		case 'z':
		case 'E':
		case 'F':
		case 'L':
		case 'P':
		case 'T':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
		case '(':
		case ')':
		case '/':
			return 5;
		case 'B':
		case 'C':
		case 'D':
		case 'H':
		case 'K':
		case 'N':
		case 'R':
		case 'S':
		case 'U':
		case 'V':
		case 'X':
		case 'Z':
		case '0':
		case '%':
			return 6;
		case 'm':
		case 'A':
		case 'G':
		case 'M':
		case 'O':
		case 'Q':
		case 'Y':
			return 8;
		case 'w':
		case 'W':
			return 11;
		default:
			//check if the character is double byte
			if (theChar.charCodeAt(0) > 255)
				return 11;
			return 0;
	}
}

function getNextSibling(object,siblingNodeName)
{
	if(object.nextSibling!=null)
	{
		if(object.nextSibling.nodeName==siblingNodeName)
		{
			return object.nextSibling;
		}
		else
		{
			return getNextSibling(object.nextSibling,siblingNodeName);
		}
	}
}

/***************************************************************************************************************
* The following functions are copied from http://www.hsbc.com.hk/regional/js/hsbc.js in 1G website. This is
* to provide the same functions as the 1G sites.
***************************************************************************************************************/

//
// Platform and browser detect variables
//

var isUnix = false;
var isLinux = false;
var isMacintoshPPC = false;
var isMacintosh68K = false;
var isWindows95 = false;
var isWindows98 = false;
var isWindowsNT= false;
var isWindows3x = false;

var isNew = false;
var isIE = false;
var isIE4 = false;
var isIE5 = false;
var isNetscape = false;
var isNetscape4 = false;
var isNetscape6 = false;

var userAgent = navigator.userAgent.toLowerCase();
var appName = navigator.appName;
var appVersion = parseInt(navigator.appVersion);
var platform = (navigator.platform).substring (0, 5);

// Browser detection
if (appVersion > 5) isNew = true;
else if (appName == "Netscape") {
  isNetscape = true;
  if (appVersion == 4) isNetscape4 = true;
  else if (appVersion == 5) isNetscape6 = true;
}
else if (appName == "Microsoft Internet Explorer") {
  isIE = true;
  if (appVersion == 4) {
    isIE4 = true;
    if (msieversion() == 5) isIE5 = true;
  }
}

function msieversion() {
  var ua = window.navigator.userAgent
  var msie = ua.indexOf ( "MSIE " )
  if ( msie > 0 ) return parseInt (ua.substring (msie+5, ua.indexOf (".", msie )))
  else return 0;
}

// Platform detection
if ( ( userAgent.indexOf("win95") !=-1) || ( userAgent.indexOf("windows 95") !=-1) ) isWindows95 = true;
if ( ( userAgent.indexOf("win98") !=-1) || ( userAgent.indexOf("windows 98") !=-1) ) isWIndows98 = true;
if ( ( userAgent.indexOf("winnt") !=-1) || ( userAgent.indexOf("windows nt") !=-1) ) isWindowsNT= true;
if ( ( userAgent.indexOf("win16") !=-1) || ( userAgent.indexOf("windows 3.1") !=-1) ) isWindows3x = true;
if ( navigator.appVersion.indexOf("Mac") != -1 ) {
  if ( userAgent.indexOf("pc)") !=-1 ) isMacintoshPPC = true;
  else isMacintosh68K = true;
}
if ( platform == "SunOS" ) isUnix = true;
else if ( platform == "HP-UX" ) isUnix = true;
else if ( platform == "IRIX " ) isUnix = true;
else if ( ( ( navigator.platform ).substring (0, 3) ) == "AIX" ) isUnix = true;
else if ( userAgent.indexOf("linux") != -1 ) isLinux = true;

// Added by Chris to support existing hsbc functions

if(isIE || isIE4 || isIE5) ie=true;
else ie=false;
if(isMacintoshPPC || isMacintosh68K) mac=true;
else mac=false;
if(isWindowsNT) nt=true;
else nt=false;
if(isUnix || isLinux) unix=true;
else unix=false;
if(navigator.appVersion.indexOf("MSIE") != -1 && navigator.appVersion.indexOf("5.5") != -1) ie5_5=true;
else ie5_5=false;

//
// Generic functions
//

//This preloads the images. See the body tag for the syntax to do this for an image
function imageLoad() {
        if (document.images) {
                var imgFileArg = imageLoad.arguments;
                imgFileStr = imgFileArg[0];
                var imgFiles = imageLoad.arguments;
                if (imgFileStr != null && imgFileStr.indexOf("'") > -1 ) {
                        imgFileStr = imgFileStr.substring(1,imgFileStr.length-1);
                        imgFiles = imgFileStr.split("','");
                }
                if (document.preloadArray==null) document.preloadArray = new Array();
                var i = document.preloadArray.length;
                with (document) for (var j=0; j<imgFiles.length; j++){
                        preloadArray[i] = new Image;
                        preloadArray[i++].src = imgFiles[j];
                } 
        }
}

function swapImage(layerStem,imageSpace,imageName) {
  var ns4 = (document.layers)? true:false;
  var ie4 = (document.all)? true:false;
	if(!ie){	if(layerStem == ""){imageObj = document.images[imageSpace];}
				else
			{imageObj = eval(layerStem+".document.images[imageSpace]");}
		}
	if(ie){imageObj = document.all[imageSpace]}

        imageObj.src = imageName;

}

// Used for selecting window size
function openWindow(winUrl, winName, properties) {

switch (properties) {

    case "win_a":
        newWindow = window.open(winUrl,winName,"scrollbars,menubar,toolbar,resizable,HEIGHT=460,WIDTH=790");
        newWindow.focus();
	break

    case "win_b":
	  	var enhancePopup = true;	
		var checkPath1 = winUrl.indexOf("www.login.hsbc.com");		// hard coded path 1
		var checkPath2 = winUrl.indexOf("www.register.hsbc.com");	// hard coded path 2

		if(checkPath1 > -1 || checkPath2 > -1) // special handling for the URLs
		{
			var appName = navigator.appName.toLowerCase();
			var appVersion = parseFloat(navigator.appVersion);

			if(appName.indexOf("netscape") > -1 && !isNaN(appVersion) && appVersion >= 5 ) // netscape 6.0+
			{
				var appProduct = navigator.product.toLowerCase();
				if(appProduct.indexOf("gecko") > -1) // Gecko is being used
				{
					if(navigator.vendorSub != "6.2") // skip Netscape 6.2
					{
						if(!isNaN(parseFloat(navigator.vendorSub)) && parseFloat(navigator.vendorSub) >= 6.2) // Should be Netscape 6.21+
						{
							enhancePopup = false;
						}				
					}
				}
				else // Gecko is not being used
				{
					var ua = navigator.userAgent.toLowerCase();
					var ns6_index = ua.lastIndexOf("netscape6");
					var versionNum = 0;
				
					if(ns6_index > -1)  // Netscape 6
					{
						if(ua.substring(ns6_index+10, ua.length) != "6.2")
						{
							versionNum = parseFloat(ua.substring(ns6_index+10, ua.length));
						}
					}	
					else
					{
						var ns_index = ua.lastIndexOf("netscape");
						if(ns_index > -1)  // Netscape 7 or +
						{
							versionNum = parseFloat(ua.substring(ns_index+9, ua.length));
						}
					}
					if(!isNaN(versionNum) && versionNum >= 6.2)
					{
						enhancePopup = false;
					}
				}		
			}
		}
		if(enhancePopup) // usual case
		{
			newWindow = window.open(winUrl,winName,"scrollbars,HEIGHT=470,WIDTH=525");
			newWindow.focus();
		}
		else
		{
			self.location.href=winUrl;
		}
	break

    case "win_b_no_scroll":
        newWindow = window.open(winUrl,winName,"HEIGHT=470,WIDTH=525");
        newWindow.focus();
        break

    default:
        newWindow = window.open(winUrl,winName,properties);
        newWindow.focus();
    }
}  

//Closes the current window
function windowClose(){
  window.close();
}

/***************************************************************************************************************
* The following functions are copied from http://www.hsbc.com.hk/regional/js/bbcomm.js in 1G website. This is
* to provide the same functions as the 1G sites.
***************************************************************************************************************/

// Provide some an interface to predefined functions for TeamSite user to user Javascript
function HSBCPredefinedFunction(functionString)
{

	var functionPara = functionString.split(";");
	
	switch(functionPara[0])
	{
		// add the current page to favourites
		// name - Name to be displayed in the favourites
		// url - URL of the page to be bookmarked
		case "addToFavourites":
				addToFavourites(functionPara[1], functionPara[2]);
			break;
		
		// pull in the corresponding style sheet - requires hsbc.js
		// pciefile - style sheet for PC's IE
		// maciefile - style sheet for MAC's IE
		// pcnsfile - style sheet for PC's Netscape 7 (if not specified, it will use pciefile)
		// macnsfile - style sheet for MAC's Netscape 7 (if not specified, it will use maciefile)
		case "addCss":
				addCss(functionPara[1], functionPara[2], functionPara[3], functionPara[4]);
			break;
		
		// Show or Hide a layer by setting the visibility property.
		// layerarraystr is in format of "layer1,property1,layer2,property2 ..."
		// 	where layer1, layer2 ... = id of the layer
		// 			property1, property2 ... = show or hide
		case "ShowHideLayer":
				ShowHideLayer(functionPara[1]);
			break;
		
		case "SwapImage":
				SwapImage(functionPara[1]);
			break;
		
		case "preloadImages":
				preloadImages(functionPara[1]);
			break;
		
		case "MouseOver":
				MouseOver(functionPara[1], functionPara[2], functionPara[3], functionPara[4]);
			break;
		
		case "sendToFriend":
				sendToFriend(functionPara[1]);
			break;
		
		//Popup a new window with the size of PIB Logon.
		case "PIBLogonWindow":
				PIBLogonWindow(functionPara[1]);
			break;
			
		case "B2GLogonWindow":
				B2GLogonWindow(functionPara[1]);
			break;
			
		// spawn a fixed windows (440x680 with no control bars) - requires hsbc.js
		// url - URL
		case "fixedWindow":
				fixedWindow(functionPara[1]);
			break;
		
		case "pulldownRedirect":
				pulldownRedirect(functionPara[1], functionPara[2], functionPara[3], functionPara[4], functionPara[5], functionPara[6]);
			break;
		
		/***************************************************************************************************************
		* Function		: newBrowser(url)
		* Description		: Open a new browser (popup)
		* Parameter Usage	: url -- target URL			  
		* Location		: /regional/js/bbcomm.js
		* Author		: Herman, HUI Wai Man
		* Creation Date		: 28 FEB 2004
		* Side effect		: N/A
		* Amendment History	:
		* Date		By		Description
		* ---------	------------	--------------------------------------------------------------------------------
		*
		***************************************************************************************************************/
		case "newBrowser":
				newBrowser(functionPara[1]);
			break;

		//Location:	/regional/js/tools.js
		case "setFontSize":
				setFontSize();
			break;

		//Location:	/regional/js/tools.js
		case "incrementFontSize":
				incrementFontSize();
			break;

		//Location:	/regional/js/tools.js
		case "decrementFontSize":
				decrementFontSize();
			break;
		
		// Location	: /regional/js/writeflash.js
		case 'writeFlash':
				writeflash(functionPara[1],functionPara[2],functionPara[3],functionPara[4],functionPara[5],
						functionPara[6],functionPara[7],functionPara[8],functionPara[9],functionPara[10],
						functionPara[11],functionPara[12],functionPara[13],functionPara[14]);
			break;
		
		// Print function
		case "print":
				window.print();
			break;

		// Added by Vincent Yip 20060801
		// Open form win function
		case "openFormWin":
				openFormWin(functionPara[1]);
			break;

		default:
			alert("The function : '" + functionPara[0] + "' is not valid");
		break;	
				
	}
}

// pull in the corresponding style sheet - requires hsbc.js
// pciefile - style sheet for PC's IE
// maciefile - style sheet for MAC's IE
// pcnsfile - style sheet for PC's Netscape 7 (if not specified, it will use pciefile)
// macnsfile - style sheet for MAC's Netscape 7 (if not specified, it will use maciefile)
// Supported browsers	: IE6, Netscape 7 for PC; IE, Netscape 6 for mac
function addCss(pciefile, maciefile, pcnsfile, macnsfile)
{
	if (!mac) {
		if (pcnsfile) {
			if (isNetscape6)  {
				document.write('<link rel=\"stylesheet\" href=\"'+pcnsfile+'\" type=\"text/css\">');
			} else {
				document.write('<link rel=\"stylesheet\" href=\"'+pciefile+'\" type=\"text/css\">');
			}
		} else {
			document.write('<link rel=\"stylesheet\" href=\"'+pciefile+'\" type=\"text/css\">');
		}
	} else {
		if (macnsfile) {
			if (isNetscape6)  {
				document.write('<link rel=\"stylesheet\" href=\"'+macnsfile+'\" type=\"text/css\">');
			} else {
				document.write('<link rel=\"stylesheet\" href=\"'+maciefile+'\" type=\"text/css\">');
			}
		} else {
			document.write('<link rel=\"stylesheet\" href=\"'+maciefile+'\" type=\"text/css\">');
		}
	}
}

// Bookmark a certain url for IE users
// name - Name to be displayed in the favourites
// url - URL of the page to be bookmarked
function addToFavourites(name, url) {
	if ((navigator.appVersion.indexOf('MSIE') > 0) && (parseInt(navigator.appVersion) >= 4)) {
		if (url == null || url == "") {
			window.external.AddFavorite(parent.location.href, name);
		} else {
			window.external.AddFavorite(url, name);
		}
	} else if (navigator.appName == "Netscape") {
		alert ("Sorry, your browser does not support this function.");
	}
}

// spawn a new browser (500x700 with all control bars) - requires hsbc.js
// url - URL
function newBrowser(url) {
	nb=window.open(url, "nb", "location,scrollbars,menubar,toolbar,resizable,HEIGHT=500,WIDTH=700");
    nb.focus();
}

// spawn a fixed windows (440x680 with no control bars) - requires hsbc.js
// url - URL
function fixedWindow(url) {
	
	var enhancePopup = true;
	
	var checkPath1 = url.indexOf("www.login.hsbc.com");		// hard coded path 1
	var checkPath2 = url.indexOf("www.register.hsbc.com");	// hard coded path 2

	if(checkPath1 > -1 || checkPath2 > -1) // special handling for the URLs
	{
		var appName = navigator.appName.toLowerCase();
		var appVersion = parseFloat(navigator.appVersion);

		if(appName.indexOf("netscape") > -1 && !isNaN(appVersion) && appVersion >= 5 ) // netscape 6.0+
		{
			var appProduct = navigator.product.toLowerCase();
			if(appProduct.indexOf("gecko") > -1) // Gecko is being used
			{
				if(navigator.vendorSub != "6.2") // skip Netscape 6.2
				{
					if(!isNaN(parseFloat(navigator.vendorSub)) && parseFloat(navigator.vendorSub) >= 6.2) // Should be Netscape 6.21+
					{
						enhancePopup = false;
					}				
				}
			}
			else // Gecko is not being used
			{
				var ua = navigator.userAgent.toLowerCase();
				var ns6_index = ua.lastIndexOf("netscape6");
				var versionNum = 0;
				
				if(ns6_index > -1)  // Netscape 6
				{
					if(ua.substring(ns6_index+10, ua.length) != "6.2")
					{
						versionNum = parseFloat(ua.substring(ns6_index+10, ua.length));
					}
				}	
				else
				{
					var ns_index = ua.lastIndexOf("netscape");
					if(ns_index > -1)  // Netscape 7 or +
					{
						versionNum = parseFloat(ua.substring(ns_index+9, ua.length));
					}
				}
				if(!isNaN(versionNum) && versionNum >= 6.2)
				{
					enhancePopup = false;
				}
			}		
		}
	}
	if(enhancePopup) // usual case
	{
		fw=window.open(url, "fw", "scrollbars,resizable,HEIGHT=440,WIDTH=680");
		fw.focus();
	}
	else
	{
		self.location.href=url;
	}
}


function sendToFriend(url) {
	openerLocation = window.location;
	neww = window.open(url+"&fromURL="+openerLocation,'sendtof',"resizable=yes,scrollbars,status,height=440,width=550");
	neww.focus();
}

function PIBLogonWindow(url) {
	var plw = window.open(url,"plw","width="+screen.width+",height="+screen.height*0.88+",location=no,directories=no,menubar=no,toolbar=no,scrollbars=yes,status=yes,resizable=yes,left='0',top='0'");
	plw.focus();
}

/***************************************************************************************************************
* Function		   : ShowHideLayer(layerarraystr)
* Description		: Show or Hide a layer by setting the visibility property.
* Parameter Usage	: layerarraystr is in format of "layer1,property1,layer2,property2 ..."
*                   where layer1, layer2 ... = id of the layer
*                         property1, property2 ... = show or hide
* Amendment History	:
* Date		By		Description
* ---------	------------	--------------------------------------------------------------------------------
*
***************************************************************************************************************/
function ShowHideLayer(layerarraystr) {
	var a = layerarraystr.split(",");
	if((a.length / 2) != Math.ceil(a.length/2)) {
		alert("Invalid parameters for ShowHideLayer!\nIt must be in format layer1,property1,layer2,property2 ...");
	} else {
		var i,v,obj;
		for (i=0; i<a.length; i+=2) {
			if ((obj=BB_MouseOver_findObj(a[i]))!=null) {
				v=a[i+1];
				if (obj.style) {
					obj=obj.style;
					v=(v=='show')?'visible':(v='hide')?'hidden':v;
				}
				obj.visibility=v;
			}
		}
	}
	a = null;
}

/***************************************************************************************************************
* Function		: SwapImage(imgArrayStr)
* Description		: Change the src property of specified images
* Parameter Usage	: imgArrayStr - in the format of "imgName1,imgPath1,imgName2,imgPath2..."
*                   where imgName1, imgName2 ... = name of image to be changed
*                         imgFullpath1, imgFullpath2 ... = path of the image
* Side effect		: N/A
* Amendment History	:
* Date      By             Description
* ---------	------------   --------------------------------------------------------------------------------
*
***************************************************************************************************************/
function SwapImage(imgArrayStr)
{
	var a = imgArrayStr.split(",");

	if((a.length / 2) != Math.ceil(a.length/2)) {
		alert("Invalid parameters for BB_SwapImage!\nIt must be in format of imgName1,imgPath1,imgName2,imgPath2...");
	} else {
		var i,imgObj;
		for(i=0;i<a.length;i+=2) {
			if ((imgObj=BB_MouseOver_findObj(a[i]))!=null){
				imgObj.src=a[i+1];
			}
		}
	}
	a = null;
}
/***************************************************************************************************************
* Function		: preloadImages(imgarraystr)
* Description		: Preload the images in imgarray
* Parameter Usage	: imgarray - array of image files
* Side effect		: N/A
* Amendment History	:
* Date		By		Description
* ---------	------------	--------------------------------------------------------------------------------
*
***************************************************************************************************************/
function preloadImages(imgarraystr) {
	var d=document;
	var imgarray = imgarraystr.split(",");

	if(d.images) {
		if(!d.p) d.p=new Array();
		var i=0,j=d.p.length,a=imgarray;

		for(i=0; i<a.length; i++)
			if (a[i].indexOf("#")!=0) {
				d.p[j]=new Image; d.p[j++].src=a[i];
			}
	}
}

/***************************************************************************************************************
* Function		: MouseOver(imgName, imgOther, imgPath, imgControl)
* Description		: Display another image when mouse over
*						  When user only wants to change one image when mouseover, set imgControl to 1
*						  When uesr needs to change two images to the same image when mouseover, set imgControl to 2
*						  If user wants to change the image only when it's currently displaying a specific image, use imgControl = "e"
*						  If user wants to change the image only when it's currently not displaying a specific image, use imgControl = "ne"
* Parameter Usage	: imgName		: The name of image
*                   imgPath		: Path of the image for display when mouse over
*                   imgOther		: This usage depends on the value of imgControl
*                   imgControl	: If this is 1, then only change the src of the image with name = imgName to imgPath
*													imgOther will have no use in this case.
*											  If this is 2, imgOther should another image name.
*													Both the imgName and imgOther will change to imgPath
*											  If this is "e", imgOther should be an image src.
*													If imgName's src = imgOther, then change imgName's src to imgPath. Otherwise no change.
*											  If this is "ne", imgOther should be an image src.
*													If imgName's src != imgOther, then change imgName's src to imgPath. Otherwise no change.
*											  Other values will be treated as case 1
* Supported browsers : IE 6, Netscape 7
* Side effect		: N/A
* Amendment History	:
* Date      By             Description
* ---------	------------   --------------------------------------------------------------------------------
*
***************************************************************************************************************/
function MouseOver(imgName, imgOther, imgPath, imgControl)
{
	switch(imgControl)
	{
		case "1":
			var i,j=0,x;
			document.MM_sr=new Array;
			if ((x=BB_MouseOver_findObj(imgName))!=null){
				document.MM_sr[j++]=x;
				if(!x.oSrc) x.oSrc=x.src;
				x.src=imgPath;
			}
			break;

		case "2":
			var i,j=0,x;
			document.MM_sr=new Array;
			if ((x=BB_MouseOver_findObj(imgName))!=null){
				document.MM_sr[j++]=x;
				if(!x.oSrc) x.oSrc=x.src;
				x.src=imgPath;
			}

			if ((x=BB_MouseOver_findObj(imgOther))!=null){
				document.MM_sr[j++]=x;
				if(!x.oSrc) x.oSrc=x.src;
				x.src=imgPath;
			}
			break;

		case "e":
			var imgSrc = location.protocol + "//" + location.hostname;

			if (!(!location.port || location.port==80)) {
				imgSrc+=":"+location.port;
			}

			if (imgOther.indexOf('/') == 0) {
				imgSrc += imgOther
			} else {
				imgSrc += location.pathname.substr(0,location.pathname.lastIndexOf('/')+1) + imgOther;
			}

			imgObj = BB_MouseOver_findObj(imgName);
			if (imgObj != null ) {
				if (imgObj.src == imgSrc) {
					imgObj.src = imgPath;
				}
			}
			break;

		case "ne":
			var imgSrc = location.protocol + "//" + location.hostname;

			if (!(!location.port || location.port==80)) {
				imgSrc+=":"+location.port;
			}

			if (imgOther.indexOf('/') == 0) {
				imgSrc += imgOther
			} else {
				imgSrc += location.pathname.substr(0,location.pathname.lastIndexOf('/')+1) + imgOther;
			}

			imgObj = BB_MouseOver_findObj(imgName);
			if (imgObj != null ) {
				if (imgObj.src != imgSrc) {
					imgObj.src = imgPath;
				}
			}
			break;

		default:
			var i,j=0,x;
			document.MM_sr=new Array;
			if ((x=BB_MouseOver_findObj(imgName))!=null){
				document.MM_sr[j++]=x;
				if(!x.oSrc) x.oSrc=x.src;
				x.src=imgPath;
			}
			break;
	}
}

/***************************************************************************************************************
* Function		: pulldownRedirect(popup, formfield01, formfield02, formfield03, formfield04, formfield05)
* Description	: Load another page in a popup window or in the current window, where the URL of the target page
*					  is determined by concatenating the values of at most 5 pull down menus' selected options
* Parameter Usage : popup : determine either load the new URL in a popup window or in the current window,
*						if equals to "PIBLogonWindow", load in a popup window using the "PIBLogonWindow" function
*						if equals to "fixedWindow", load in a popup window using the "fixedWindow" function
*						if equals to "newBrowser", load in a popup window using the "newBrowser" function
*						if equals to "nopopup" or anything else, load in the current window
*                   formfield01 to formfield05: pull down menu field name and their corresponding form names linked with a dot "."
*																the values of the selection options of the pull down
*																menus are concatenated to form the target URL
* Side effect			: N/A
* Amendment History	:
* Date      By             Description
* ---------	------------   --------------------------------------------------------------------------------
*
***************************************************************************************************************/
function pulldownRedirect(popup, formfield01, formfield02, formfield03, formfield04, formfield05) {
	var currentFormFieldPair, formName, fieldName;
	var fieldValue01 = "", fieldValue02 = "", fieldValue03 = "", fieldValue04 = "", fieldValue05 = "", finalURL = "";
	
	var formfields = new Array(5);
	var fieldValues = new Array(5);
	
	formfields[0] = formfield01;
	formfields[1] = formfield02;
	formfields[2] = formfield03;
	formfields[3] = formfield04;
	formfields[4] = formfield05;
	
	for (lpcnt = 0; lpcnt < formfields.length; lpcnt++) {
		if (typeof formfields[lpcnt] != "undefined" && formfields[lpcnt] != "") {
			currentFormFieldPair = formfields[lpcnt].split(".");
			formName = currentFormFieldPair[0];
			fieldName = currentFormFieldPair[1];
			if (document.forms[formName][fieldName].options[document.forms[formName][fieldName].selectedIndex].value != "")
				fieldValues[lpcnt] = document.forms[formName][fieldName].options[document.forms[formName][fieldName].selectedIndex].value;
		}
	}
	
	for (lpcnt = 0; lpcnt < formfields.length; lpcnt++) {
		if (typeof fieldValues[lpcnt] != "undefined")
			finalURL = finalURL + fieldValues[lpcnt];
	}
	popup = popup.toLowerCase();
	switch(popup)
	{
		case "piblogonwindow":
				PIBLogonWindow(finalURL);
			break;
			
		case "fixedwindow":
				fixedWindow(finalURL);
			break;
			
		case "newbrowser":
				newBrowser(finalURL);
			break;
				
		default:
			location = finalURL;
	}
}

// Added by Vincent Yip 20060801
// This function is made specifically for open new window for PDF documents, as it is found that in IE, you can't call normal windows
// methods if the new window is opening a PDF document. (Probably because IE treats the window as plugin window other than normal browser window).
// Calling methods like focus(), close() will lead to javascript error. As a result, this method won't call window.focus() after popping up the
// new window as in other similar methods in this js.
function openFormWin(url) {
    formwin=window.open(url, "formwin", "scrollbars,resizable,HEIGHT=440,WIDTH=680");
}

function B2GLogonWindow(url) {
	var plw = window.open(url,"Logon","width="+screen.availWidth+",height="+screen.availHeight+",location=no,directories=no,menubar=yes,toolbar=no,scrollbars=yes,status=yes,resizable=yes,left='0',top='0'");
	plw.focus();
}

