/*base64*/
/**
*
*  Base64 encode / decode
*  http://www.webtoolkit.info/
*
**/

var Base64 = {

    // private property
    _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

    // public method for encoding
    encode : function (input) {
        var output = "";
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;

        input = Base64._utf8_encode(input);

        while (i < input.length) {

            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);

            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;

            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }

            output = output +
            this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
            this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);

        }

        return output;
    },

    // public method for decoding
    decode : function (input) {
        var output = "";
        var chr1, chr2, chr3;
        var enc1, enc2, enc3, enc4;
        var i = 0;

        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

        while (i < input.length) {

            enc1 = this._keyStr.indexOf(input.charAt(i++));
            enc2 = this._keyStr.indexOf(input.charAt(i++));
            enc3 = this._keyStr.indexOf(input.charAt(i++));
            enc4 = this._keyStr.indexOf(input.charAt(i++));

            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;

            output = output + String.fromCharCode(chr1);

            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }

        }

        output = Base64._utf8_decode(output);

        return output;

    },

    // private method for UTF-8 encoding
    _utf8_encode : function (string) {
        string = string.replace(/\r\n/g,"\n");
        var utftext = "";

        for (var n = 0; n < string.length; n++) {

            var c = string.charCodeAt(n);

            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }

        }

        return utftext;
    },

    // private method for UTF-8 decoding
    _utf8_decode : function (utftext) {
        var string = "";
        var i = 0;
        var c = c1 = c2 = 0;

        while ( i < utftext.length ) {

            c = utftext.charCodeAt(i);

            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            }
            else if((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i+1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            }
            else {
                c2 = utftext.charCodeAt(i+1);
                c3 = utftext.charCodeAt(i+2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }

        }

        return string;
    }

}

var Cookie = {
  set: function(name, value, daysToExpire) {
    var expire = '';
    if (daysToExpire != undefined) {
      var d = new Date();
      d.setTime(d.getTime() + (86400000 * parseFloat(daysToExpire)));
      expire = '; expires=' + d.toGMTString();
    }
    return (document.cookie = escape(name) + '=' + escape(value || '') + expire);
  },
  get: function(name) {
    var cookie = document.cookie.match(new RegExp('(^|;)\s*' + escape(name) + '=([^;\s]*)'));
    return (cookie ? unescape(cookie[2]) : null);
  },
  erase: function(name) {
    var cookie = Cookie.get(name) || true;
    Cookie.set(name, '', -1);
    return cookie;
  },
  accept: function() {
    if (typeof navigator.cookieEnabled == 'boolean') {
      return navigator.cookieEnabled;
    }
    Cookie.set('_test', '1');
    return (Cookie.erase('_test') === '1');
  }
};

/*controls*/
// script.aculo.us controls.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008

// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//           (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
//           (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
// Contributors:
//  Richard Livsey
//  Rahul Bhargava
//  Rob Wills
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/

// Autocompleter.Base handles all the autocompletion functionality
// that's independent of the data source for autocompletion. This
// includes drawing the autocompletion menu, observing keyboard
// and mouse events, and similar.
//
// Specific autocompleters need to provide, at the very least,
// a getUpdatedChoices function that will be invoked every time
// the text inside the monitored textbox changes. This method
// should get the text for which to provide autocompletion by
// invoking this.getToken(), NOT by directly accessing
// this.element.value. This is to allow incremental tokenized
// autocompletion. Specific auto-completion logic (AJAX, etc)
// belongs in getUpdatedChoices.
//
// Tokenized incremental autocompletion is enabled automatically
// when an autocompleter is instantiated with the 'tokens' option
// in the options parameter, e.g.:
// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
// will incrementally autocomplete with a comma as the token.
// Additionally, ',' in the above example can be replaced with
// a token array, e.g. { tokens: [',', '\n'] } which
// enables autocompletion on multiple tokens. This is most
// useful when one of the tokens is \n (a newline), as it
// allows smart autocompletion after linebreaks.

if(typeof Effect == 'undefined')
  throw("controls.js requires including script.aculo.us' effects.js library");

var Autocompleter = { };
Autocompleter.Base = Class.create({
  baseInitialize: function(element, update, options) {
    element          = $(element);
    this.element     = element;
    this.update      = $(update);
    this.hasFocus    = false;
    this.changed     = false;
    this.active      = false;
    this.index       = 0;
    this.entryCount  = 0;
    this.oldElementValue = this.element.value;

    if(this.setOptions)
      this.setOptions(options);
    else
      this.options = options || { };

    this.options.paramName    = this.options.paramName || this.element.name;
    this.options.tokens       = this.options.tokens || [];
    this.options.frequency    = this.options.frequency || 0.4;
    this.options.minChars     = this.options.minChars || 1;
    this.options.onShow       = this.options.onShow ||
      function(element, update){
        if(!update.style.position || update.style.position=='absolute') {
          update.style.position = 'absolute';
          Position.clone(element, update, {
            setHeight: false,
            offsetTop: element.offsetHeight
          });
        }
        Effect.Appear(update,{duration:0.15});
      };
    this.options.onHide = this.options.onHide ||
      function(element, update){ new Effect.Fade(update,{duration:0.15}) };

    if(typeof(this.options.tokens) == 'string')
      this.options.tokens = new Array(this.options.tokens);
    // Force carriage returns as token delimiters anyway
    if (!this.options.tokens.include('\n'))
      this.options.tokens.push('\n');

    this.observer = null;

    this.element.setAttribute('autocomplete','off');

    Element.hide(this.update);

    Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
    Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
  },

  show: function() {
    if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
    if(!this.iefix &&
      (Prototype.Browser.IE) &&
      (Element.getStyle(this.update, 'position')=='absolute')) {
      new Insertion.After(this.update,
       '<iframe id="' + this.update.id + '_iefix" '+
       'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
       'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
      this.iefix = $(this.update.id+'_iefix');
    }
    if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
  },

  fixIEOverlapping: function() {
    Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
    this.iefix.style.zIndex = 1;
    this.update.style.zIndex = 2;
    Element.show(this.iefix);
  },

  hide: function() {
    this.stopIndicator();
    if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
    if(this.iefix) Element.hide(this.iefix);
  },

  startIndicator: function() {
    if(this.options.indicator) Element.show(this.options.indicator);
  },

  stopIndicator: function() {
    if(this.options.indicator) Element.hide(this.options.indicator);
  },

  onKeyPress: function(event) {
    if(this.active)
      switch(event.keyCode) {
       case Event.KEY_TAB:
       case Event.KEY_RETURN:
         this.selectEntry();
         Event.stop(event);
       case Event.KEY_ESC:
         this.hide();
         this.active = false;
         Event.stop(event);
         return;
       case Event.KEY_LEFT:
       case Event.KEY_RIGHT:
         return;
       case Event.KEY_UP:
         this.markPrevious();
         this.render();
         Event.stop(event);
         return;
       case Event.KEY_DOWN:
         this.markNext();
         this.render();
         Event.stop(event);
         return;
      }
     else
       if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
         (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;

    this.changed = true;
    this.hasFocus = true;

    if(this.observer) clearTimeout(this.observer);
      this.observer =
        setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
  },

  activate: function() {
    this.changed = false;
    this.hasFocus = true;
    this.getUpdatedChoices();
  },

  onHover: function(event) {
    var element = Event.findElement(event, 'LI');
    if(this.index != element.autocompleteIndex)
    {
        this.index = element.autocompleteIndex;
        this.render();
    }
    Event.stop(event);
  },

  onClick: function(event) {
    var element = Event.findElement(event, 'LI');
    this.index = element.autocompleteIndex;
    this.selectEntry();
    this.hide();
  },

  onBlur: function(event) {
    // needed to make click events working
    setTimeout(this.hide.bind(this), 250);
    this.hasFocus = false;
    this.active = false;
  },

  render: function() {
    if(this.entryCount > 0) {
      for (var i = 0; i < this.entryCount; i++)
        this.index==i ?
          Element.addClassName(this.getEntry(i),"selected") :
          Element.removeClassName(this.getEntry(i),"selected");
      if(this.hasFocus) {
        this.show();
        this.active = true;
      }
    } else {
      this.active = false;
      this.hide();
    }
  },

  markPrevious: function() {
    if(this.index > 0) this.index--;
      else this.index = this.entryCount-1;
    this.getEntry(this.index).scrollIntoView(true);
  },

  markNext: function() {
    if(this.index < this.entryCount-1) this.index++;
      else this.index = 0;
    this.getEntry(this.index).scrollIntoView(false);
  },

  getEntry: function(index) {
    return this.update.firstChild.childNodes[index];
  },

  getCurrentEntry: function() {
    return this.getEntry(this.index);
  },

  selectEntry: function() {
    this.active = false;
    this.updateElement(this.getCurrentEntry());
  },

  updateElement: function(selectedElement) {
    if (this.options.updateElement) {
      this.options.updateElement(selectedElement);
      return;
    }
    var value = '';
    if (this.options.select) {
      var nodes = $(selectedElement).select('.' + this.options.select) || [];
      if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
    } else
      value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');

    var bounds = this.getTokenBounds();
    if (bounds[0] != -1) {
      var newValue = this.element.value.substr(0, bounds[0]);
      var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
      if (whitespace)
        newValue += whitespace[0];
      this.element.value = newValue + value + this.element.value.substr(bounds[1]);
    } else {
      this.element.value = value;
    }
    this.oldElementValue = this.element.value;
    this.element.focus();

    if (this.options.afterUpdateElement)
      this.options.afterUpdateElement(this.element, selectedElement);
  },

  updateChoices: function(choices) {
    if(!this.changed && this.hasFocus) {
      this.update.innerHTML = choices;
      Element.cleanWhitespace(this.update);
      Element.cleanWhitespace(this.update.down());

      if(this.update.firstChild && this.update.down().childNodes) {
        this.entryCount =
          this.update.down().childNodes.length;
        for (var i = 0; i < this.entryCount; i++) {
          var entry = this.getEntry(i);
          entry.autocompleteIndex = i;
          this.addObservers(entry);
        }
      } else {
        this.entryCount = 0;
      }

      this.stopIndicator();
      this.index = 0;

      if(this.entryCount==1 && this.options.autoSelect) {
        this.selectEntry();
        this.hide();
      } else {
        this.render();
      }
    }
  },

  addObservers: function(element) {
    Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
    Event.observe(element, "click", this.onClick.bindAsEventListener(this));
  },

  onObserverEvent: function() {
    this.changed = false;
    this.tokenBounds = null;
    if(this.getToken().length>=this.options.minChars) {
      this.getUpdatedChoices();
    } else {
      this.active = false;
      this.hide();
    }
    this.oldElementValue = this.element.value;
  },

  getToken: function() {
    var bounds = this.getTokenBounds();
    return this.element.value.substring(bounds[0], bounds[1]).strip();
  },

  getTokenBounds: function() {
    if (null != this.tokenBounds) return this.tokenBounds;
    var value = this.element.value;
    if (value.strip().empty()) return [-1, 0];
    var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
    var offset = (diff == this.oldElementValue.length ? 1 : 0);
    var prevTokenPos = -1, nextTokenPos = value.length;
    var tp;
    for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
      tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
      if (tp > prevTokenPos) prevTokenPos = tp;
      tp = value.indexOf(this.options.tokens[index], diff + offset);
      if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
    }
    return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
  }
});

Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
  var boundary = Math.min(newS.length, oldS.length);
  for (var index = 0; index < boundary; ++index)
    if (newS[index] != oldS[index])
      return index;
  return boundary;
};

Ajax.Autocompleter = Class.create(Autocompleter.Base, {
  initialize: function(element, update, url, options) {
    this.baseInitialize(element, update, options);
    this.options.asynchronous  = true;
    this.options.onComplete    = this.onComplete.bind(this);
    this.options.defaultParams = this.options.parameters || null;
    this.url                   = url;
  },

  getUpdatedChoices: function() {
    this.startIndicator();

    var entry = encodeURIComponent(this.options.paramName) + '=' +
      encodeURIComponent(this.getToken());

    this.options.parameters = this.options.callback ?
      this.options.callback(this.element, entry) : entry;

    if(this.options.defaultParams)
      this.options.parameters += '&' + this.options.defaultParams;

    new Ajax.Request(this.url, this.options);
  },

  onComplete: function(request) {
    this.updateChoices(request.responseText);
  }
});

// The local array autocompleter. Used when you'd prefer to
// inject an array of autocompletion options into the page, rather
// than sending out Ajax queries, which can be quite slow sometimes.
//
// The constructor takes four parameters. The first two are, as usual,
// the id of the monitored textbox, and id of the autocompletion menu.
// The third is the array you want to autocomplete from, and the fourth
// is the options block.
//
// Extra local autocompletion options:
// - choices - How many autocompletion choices to offer
//
// - partialSearch - If false, the autocompleter will match entered
//                    text only at the beginning of strings in the
//                    autocomplete array. Defaults to true, which will
//                    match text at the beginning of any *word* in the
//                    strings in the autocomplete array. If you want to
//                    search anywhere in the string, additionally set
//                    the option fullSearch to true (default: off).
//
// - fullSsearch - Search anywhere in autocomplete array strings.
//
// - partialChars - How many characters to enter before triggering
//                   a partial match (unlike minChars, which defines
//                   how many characters are required to do any match
//                   at all). Defaults to 2.
//
// - ignoreCase - Whether to ignore case when autocompleting.
//                 Defaults to true.
//
// It's possible to pass in a custom function as the 'selector'
// option, if you prefer to write your own autocompletion logic.
// In that case, the other options above will not apply unless
// you support them.

Autocompleter.Local = Class.create(Autocompleter.Base, {
  initialize: function(element, update, array, options) {
    this.baseInitialize(element, update, options);
    this.options.array = array;
  },

  getUpdatedChoices: function() {
    this.updateChoices(this.options.selector(this));
  },

  setOptions: function(options) {
    this.options = Object.extend({
      choices: 10,
      partialSearch: true,
      partialChars: 2,
      ignoreCase: true,
      fullSearch: false,
      selector: function(instance) {
        var ret       = []; // Beginning matches
        var partial   = []; // Inside matches
        var entry     = instance.getToken();
        var count     = 0;

        for (var i = 0; i < instance.options.array.length &&
          ret.length < instance.options.choices ; i++) {

          var elem = instance.options.array[i];
          var foundPos = instance.options.ignoreCase ?
            elem.toLowerCase().indexOf(entry.toLowerCase()) :
            elem.indexOf(entry);

          while (foundPos != -1) {
            if (foundPos == 0 && elem.length != entry.length) {
              ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
                elem.substr(entry.length) + "</li>");
              break;
            } else if (entry.length >= instance.options.partialChars &&
              instance.options.partialSearch && foundPos != -1) {
              if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
                partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
                  elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
                  foundPos + entry.length) + "</li>");
                break;
              }
            }

            foundPos = instance.options.ignoreCase ?
              elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
              elem.indexOf(entry, foundPos + 1);

          }
        }
        if (partial.length)
          ret = ret.concat(partial.slice(0, instance.options.choices - ret.length));
        return "<ul>" + ret.join('') + "</ul>";
      }
    }, options || { });
  }
});

// AJAX in-place editor and collection editor
// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).

// Use this if you notice weird scrolling problems on some browsers,
// the DOM might be a bit confused when this gets called so do this
// waits 1 ms (with setTimeout) until it does the activation
Field.scrollFreeActivate = function(field) {
  setTimeout(function() {
    Field.activate(field);
  }, 1);
};

Ajax.InPlaceEditor = Class.create({
  initialize: function(element, url, options) {
    this.url = url;
    this.element = element = $(element);
    this.prepareOptions();
    this._controls = { };
    arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
    Object.extend(this.options, options || { });
    if (!this.options.formId && this.element.id) {
      this.options.formId = this.element.id + '-inplaceeditor';
      if ($(this.options.formId))
        this.options.formId = '';
    }
    if (this.options.externalControl)
      this.options.externalControl = $(this.options.externalControl);
    if (!this.options.externalControl)
      this.options.externalControlOnly = false;
    this._originalBackground = this.element.getStyle('background-color') || 'transparent';
    this.element.title = this.options.clickToEditText;
    this._boundCancelHandler = this.handleFormCancellation.bind(this);
    this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
    this._boundFailureHandler = this.handleAJAXFailure.bind(this);
    this._boundSubmitHandler = this.handleFormSubmission.bind(this);
    this._boundWrapperHandler = this.wrapUp.bind(this);
    this.registerListeners();
  },
  checkForEscapeOrReturn: function(e) {
    if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
    if (Event.KEY_ESC == e.keyCode)
      this.handleFormCancellation(e);
    else if (Event.KEY_RETURN == e.keyCode)
      this.handleFormSubmission(e);
  },
  createControl: function(mode, handler, extraClasses) {
    var control = this.options[mode + 'Control'];
    var text = this.options[mode + 'Text'];
    if ('button' == control) {
      var btn = document.createElement('input');
      btn.type = 'submit';
      btn.value = text;
      btn.className = 'editor_' + mode + '_button';
      if ('cancel' == mode)
        btn.onclick = this._boundCancelHandler;
      this._form.appendChild(btn);
      this._controls[mode] = btn;
    } else if ('link' == control) {
      var link = document.createElement('a');
      link.href = '#';
      link.appendChild(document.createTextNode(text));
      link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
      link.className = 'editor_' + mode + '_link';
      if (extraClasses)
        link.className += ' ' + extraClasses;
      this._form.appendChild(link);
      this._controls[mode] = link;
    }
  },
  createEditField: function() {
    var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
    var fld;
    if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
      fld = document.createElement('input');
      fld.type = 'text';
      var size = this.options.size || this.options.cols || 0;
      if (0 < size) fld.size = size;
    } else {
      fld = document.createElement('textarea');
      fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
      fld.cols = this.options.cols || 40;
    }
    fld.name = this.options.paramName;
    fld.value = text; // No HTML breaks conversion anymore
    fld.className = 'editor_field';
    if (this.options.submitOnBlur)
      fld.onblur = this._boundSubmitHandler;
    this._controls.editor = fld;
    if (this.options.loadTextURL)
      this.loadExternalText();
    this._form.appendChild(this._controls.editor);
  },
  createForm: function() {
    var ipe = this;
    function addText(mode, condition) {
      var text = ipe.options['text' + mode + 'Controls'];
      if (!text || condition === false) return;
      ipe._form.appendChild(document.createTextNode(text));
    };
    this._form = $(document.createElement('form'));
    this._form.id = this.options.formId;
    this._form.addClassName(this.options.formClassName);
    this._form.onsubmit = this._boundSubmitHandler;
    this.createEditField();
    if ('textarea' == this._controls.editor.tagName.toLowerCase())
      this._form.appendChild(document.createElement('br'));
    if (this.options.onFormCustomization)
      this.options.onFormCustomization(this, this._form);
    addText('Before', this.options.okControl || this.options.cancelControl);
    this.createControl('ok', this._boundSubmitHandler);
    addText('Between', this.options.okControl && this.options.cancelControl);
    this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
    addText('After', this.options.okControl || this.options.cancelControl);
  },
  destroy: function() {
    if (this._oldInnerHTML)
      this.element.innerHTML = this._oldInnerHTML;
    this.leaveEditMode();
    this.unregisterListeners();
  },
  enterEditMode: function(e) {
    if (this._saving || this._editing) return;
    this._editing = true;
    this.triggerCallback('onEnterEditMode');
    if (this.options.externalControl)
      this.options.externalControl.hide();
    this.element.hide();
    this.createForm();
    this.element.parentNode.insertBefore(this._form, this.element);
    if (!this.options.loadTextURL)
      this.postProcessEditField();
    if (e) Event.stop(e);
  },
  enterHover: function(e) {
    if (this.options.hoverClassName)
      this.element.addClassName(this.options.hoverClassName);
    if (this._saving) return;
    this.triggerCallback('onEnterHover');
  },
  getText: function() {
    return this.element.innerHTML.unescapeHTML();
  },
  handleAJAXFailure: function(transport) {
    this.triggerCallback('onFailure', transport);
    if (this._oldInnerHTML) {
      this.element.innerHTML = this._oldInnerHTML;
      this._oldInnerHTML = null;
    }
  },
  handleFormCancellation: function(e) {
    this.wrapUp();
    if (e) Event.stop(e);
  },
  handleFormSubmission: function(e) {
    var form = this._form;
    var value = $F(this._controls.editor);
    this.prepareSubmission();
    var params = this.options.callback(form, value) || '';
    if (Object.isString(params))
      params = params.toQueryParams();
    params.editorId = this.element.id;
    if (this.options.htmlResponse) {
      var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
      Object.extend(options, {
        parameters: params,
        onComplete: this._boundWrapperHandler,
        onFailure: this._boundFailureHandler
      });
      new Ajax.Updater({ success: this.element }, this.url, options);
    } else {
      var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
      Object.extend(options, {
        parameters: params,
        onComplete: this._boundWrapperHandler,
        onFailure: this._boundFailureHandler
      });
      new Ajax.Request(this.url, options);
    }
    if (e) Event.stop(e);
  },
  leaveEditMode: function() {
    this.element.removeClassName(this.options.savingClassName);
    this.removeForm();
    this.leaveHover();
    this.element.style.backgroundColor = this._originalBackground;
    this.element.show();
    if (this.options.externalControl)
      this.options.externalControl.show();
    this._saving = false;
    this._editing = false;
    this._oldInnerHTML = null;
    this.triggerCallback('onLeaveEditMode');
  },
  leaveHover: function(e) {
    if (this.options.hoverClassName)
      this.element.removeClassName(this.options.hoverClassName);
    if (this._saving) return;
    this.triggerCallback('onLeaveHover');
  },
  loadExternalText: function() {
    this._form.addClassName(this.options.loadingClassName);
    this._controls.editor.disabled = true;
    var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
    Object.extend(options, {
      parameters: 'editorId=' + encodeURIComponent(this.element.id),
      onComplete: Prototype.emptyFunction,
      onSuccess: function(transport) {
        this._form.removeClassName(this.options.loadingClassName);
        var text = transport.responseText;
        if (this.options.stripLoadedTextTags)
          text = text.stripTags();
        this._controls.editor.value = text;
        this._controls.editor.disabled = false;
        this.postProcessEditField();
      }.bind(this),
      onFailure: this._boundFailureHandler
    });
    new Ajax.Request(this.options.loadTextURL, options);
  },
  postProcessEditField: function() {
    var fpc = this.options.fieldPostCreation;
    if (fpc)
      $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
  },
  prepareOptions: function() {
    this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
    Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
    [this._extraDefaultOptions].flatten().compact().each(function(defs) {
      Object.extend(this.options, defs);
    }.bind(this));
  },
  prepareSubmission: function() {
    this._saving = true;
    this.removeForm();
    this.leaveHover();
    this.showSaving();
  },
  registerListeners: function() {
    this._listeners = { };
    var listener;
    $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
      listener = this[pair.value].bind(this);
      this._listeners[pair.key] = listener;
      if (!this.options.externalControlOnly)
        this.element.observe(pair.key, listener);
      if (this.options.externalControl)
        this.options.externalControl.observe(pair.key, listener);
    }.bind(this));
  },
  removeForm: function() {
    if (!this._form) return;
    this._form.remove();
    this._form = null;
    this._controls = { };
  },
  showSaving: function() {
    this._oldInnerHTML = this.element.innerHTML;
    this.element.innerHTML = this.options.savingText;
    this.element.addClassName(this.options.savingClassName);
    this.element.style.backgroundColor = this._originalBackground;
    this.element.show();
  },
  triggerCallback: function(cbName, arg) {
    if ('function' == typeof this.options[cbName]) {
      this.options[cbName](this, arg);
    }
  },
  unregisterListeners: function() {
    $H(this._listeners).each(function(pair) {
      if (!this.options.externalControlOnly)
        this.element.stopObserving(pair.key, pair.value);
      if (this.options.externalControl)
        this.options.externalControl.stopObserving(pair.key, pair.value);
    }.bind(this));
  },
  wrapUp: function(transport) {
    this.leaveEditMode();
    // Can't use triggerCallback due to backward compatibility: requires
    // binding + direct element
    this._boundComplete(transport, this.element);
  }
});

Object.extend(Ajax.InPlaceEditor.prototype, {
  dispose: Ajax.InPlaceEditor.prototype.destroy
});

Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
  initialize: function($super, element, url, options) {
    this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
    $super(element, url, options);
  },

  createEditField: function() {
    var list = document.createElement('select');
    list.name = this.options.paramName;
    list.size = 1;
    this._controls.editor = list;
    this._collection = this.options.collection || [];
    if (this.options.loadCollectionURL)
      this.loadCollection();
    else
      this.checkForExternalText();
    this._form.appendChild(this._controls.editor);
  },

  loadCollection: function() {
    this._form.addClassName(this.options.loadingClassName);
    this.showLoadingText(this.options.loadingCollectionText);
    var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
    Object.extend(options, {
      parameters: 'editorId=' + encodeURIComponent(this.element.id),
      onComplete: Prototype.emptyFunction,
      onSuccess: function(transport) {
        var js = transport.responseText.strip();
        if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
          throw('Server returned an invalid collection representation.');
        this._collection = eval(js);
        this.checkForExternalText();
      }.bind(this),
      onFailure: this.onFailure
    });
    new Ajax.Request(this.options.loadCollectionURL, options);
  },

  showLoadingText: function(text) {
    this._controls.editor.disabled = true;
    var tempOption = this._controls.editor.firstChild;
    if (!tempOption) {
      tempOption = document.createElement('option');
      tempOption.value = '';
      this._controls.editor.appendChild(tempOption);
      tempOption.selected = true;
    }
    tempOption.update((text || '').stripScripts().stripTags());
  },

  checkForExternalText: function() {
    this._text = this.getText();
    if (this.options.loadTextURL)
      this.loadExternalText();
    else
      this.buildOptionList();
  },

  loadExternalText: function() {
    this.showLoadingText(this.options.loadingText);
    var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
    Object.extend(options, {
      parameters: 'editorId=' + encodeURIComponent(this.element.id),
      onComplete: Prototype.emptyFunction,
      onSuccess: function(transport) {
        this._text = transport.responseText.strip();
        this.buildOptionList();
      }.bind(this),
      onFailure: this.onFailure
    });
    new Ajax.Request(this.options.loadTextURL, options);
  },

  buildOptionList: function() {
    this._form.removeClassName(this.options.loadingClassName);
    this._collection = this._collection.map(function(entry) {
      return 2 === entry.length ? entry : [entry, entry].flatten();
    });
    var marker = ('value' in this.options) ? this.options.value : this._text;
    var textFound = this._collection.any(function(entry) {
      return entry[0] == marker;
    }.bind(this));
    this._controls.editor.update('');
    var option;
    this._collection.each(function(entry, index) {
      option = document.createElement('option');
      option.value = entry[0];
      option.selected = textFound ? entry[0] == marker : 0 == index;
      option.appendChild(document.createTextNode(entry[1]));
      this._controls.editor.appendChild(option);
    }.bind(this));
    this._controls.editor.disabled = false;
    Field.scrollFreeActivate(this._controls.editor);
  }
});

//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
//**** This only  exists for a while,  in order to  let ****
//**** users adapt to  the new API.  Read up on the new ****
//**** API and convert your code to it ASAP!            ****

Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
  if (!options) return;
  function fallback(name, expr) {
    if (name in options || expr === undefined) return;
    options[name] = expr;
  };
  fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
    options.cancelLink == options.cancelButton == false ? false : undefined)));
  fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
    options.okLink == options.okButton == false ? false : undefined)));
  fallback('highlightColor', options.highlightcolor);
  fallback('highlightEndColor', options.highlightendcolor);
};

Object.extend(Ajax.InPlaceEditor, {
  DefaultOptions: {
    ajaxOptions: { },
    autoRows: 3,                                // Use when multi-line w/ rows == 1
    cancelControl: 'link',                      // 'link'|'button'|false
    cancelText: 'cancel',
    clickToEditText: 'Click to edit',
    externalControl: null,                      // id|elt
    externalControlOnly: false,
    fieldPostCreation: 'activate',              // 'activate'|'focus'|false
    formClassName: 'inplaceeditor-form',
    formId: null,                               // id|elt
    highlightColor: '#ffff99',
    highlightEndColor: '#ffffff',
    hoverClassName: '',
    htmlResponse: true,
    loadingClassName: 'inplaceeditor-loading',
    loadingText: 'Loading...',
    okControl: 'button',                        // 'link'|'button'|false
    okText: 'ok',
    paramName: 'value',
    rows: 1,                                    // If 1 and multi-line, uses autoRows
    savingClassName: 'inplaceeditor-saving',
    savingText: 'Saving...',
    size: 0,
    stripLoadedTextTags: false,
    submitOnBlur: false,
    textAfterControls: '',
    textBeforeControls: '',
    textBetweenControls: ''
  },
  DefaultCallbacks: {
    callback: function(form) {
      return Form.serialize(form);
    },
    onComplete: function(transport, element) {
      // For backward compatibility, this one is bound to the IPE, and passes
      // the element directly.  It was too often customized, so we don't break it.
      new Effect.Highlight(element, {
        startcolor: this.options.highlightColor, keepBackgroundImage: true });
    },
    onEnterEditMode: null,
    onEnterHover: function(ipe) {
      ipe.element.style.backgroundColor = ipe.options.highlightColor;
      if (ipe._effect)
        ipe._effect.cancel();
    },
    onFailure: function(transport, ipe) {
      alert('Error communication with the server: ' + transport.responseText.stripTags());
    },
    onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
    onLeaveEditMode: null,
    onLeaveHover: function(ipe) {
      ipe._effect = new Effect.Highlight(ipe.element, {
        startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
        restorecolor: ipe._originalBackground, keepBackgroundImage: true
      });
    }
  },
  Listeners: {
    click: 'enterEditMode',
    keydown: 'checkForEscapeOrReturn',
    mouseover: 'enterHover',
    mouseout: 'leaveHover'
  }
});

Ajax.InPlaceCollectionEditor.DefaultOptions = {
  loadingCollectionText: 'Loading options...'
};

// Delayed observer, like Form.Element.Observer,
// but waits for delay after last key input
// Ideal for live-search fields

Form.Element.DelayedObserver = Class.create({
  initialize: function(element, delay, callback) {
    this.delay     = delay || 0.5;
    this.element   = $(element);
    this.callback  = callback;
    this.timer     = null;
    this.lastValue = $F(this.element);
    Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
  },
  delayedListener: function(event) {
    if(this.lastValue == $F(this.element)) return;
    if(this.timer) clearTimeout(this.timer);
    this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
    this.lastValue = $F(this.element);
  },
  onTimerEvent: function() {
    this.timer = null;
    this.callback(this.element, $F(this.element));
  }
});
/*faceboxp*/
if (!window.FaceboxP)
    var FaceboxP = new Object();
    
function fireEvent(element,event){
    if (document.createEventObject){
        // dispatch for IE
        var evt = document.createEventObject();
        return element.fireEvent('on'+event,evt)
    }
    else{
        // dispatch for firefox + others
        var evt = document.createEvent("HTMLEvents");
        evt.initEvent(event, true, true ); // event type,bubbling,cancelable
        return !element.dispatchEvent(evt);
    }
}
    
FaceboxP.Methods = {
    initialized: false,
    active: true,
    options: {
        title: "Notice", // Title of the ModalBox window
        overlayClose: true, // Close modal box by clicking on overlay
        width: 400, // Default width in px
        overlayOpacity: .65, // Default overlay opacity
        overlayDuration: .1, // Default overlay fade in/out duration in seconds
        slideDownDuration: .15, // Default Modalbox appear slide down effect in seconds
        slideUpDuration: .15, // Default Modalbox hiding slide up effect in seconds
        resizeDuration: .25, // Default resize duration seconds
        transitions: true, // Toggles transition effects. Transitions are enabled by default
        loadingString: "Please wait. Loading...", // Default loading string message
        closeString: "Close", // Default title attribute for close window link
        closeValue: "&times;", // Default string for close link in the header
        params: {},
        method: 'get', // Default Ajax request method
        autoFocusing: true // Toggles auto-focusing for form elements. Disable for long text pages.
    },
    _options: new Object,
    
    setOptions: function(options) {
        Object.extend(this.options, options || {});
    },
    
    _init: function(options) {
        // Setting up original options with default options
        Object.extend(this._options, this.options);
        this.setOptions(options);
        
        // Create the overlay
        this.FBoverlay = new Element('div', { id: 'fb_overlay', opacity: '0' });
        
        // Create the window
        this.FBmodal = new Element('div', { id: 'fb_modal' }).update(
            this.FBtable = new Element('table', { 'class': 'modal' })
        ).hide();
        
        var tbody = new Element('tbody');
        
        var tr = new Element('tr');
        tr.insert( new Element('td', { 'class': 'tl' }) );
        tr.insert( new Element('td', { 'class': 'b' }) );
        tr.insert( new Element('td', { 'class': 'tr' }) );
        tbody.insert(tr);
        
        var tr = new Element('tr');
        tr.insert( new Element('td', { 'class': 'b s' }) );
        var body = new Element('td', { 'class': 'body' });
        tr.insert( body );
        tr.insert( new Element('td', { 'class': 'b s' }) );
        tbody.insert(tr);
        
        var tr = new Element('tr');
        tr.insert( new Element('td', { 'class': 'bl' }) );
        tr.insert( new Element('td', { 'class': 'b' }) );
        tr.insert( new Element('td', { 'class': 'br' }) );
        tbody.insert(tr);

        this.FBtable.update( tbody );
        
        this.FBclose = new Element('a', { 'class': 'close', href: '#', title: this.options.closeString });
        body.insert(this.FBclose);
        
        this.FBtitle = new Element('h2', { 'class': 'title' }).update( this.options.title );
        body.insert(this.FBtitle);
        
        this.FBcontent = new Element('div', { id: 'fb_modal_content' });
        body.insert(this.FBcontent);
        
        this.FBactionbar = new Element('div', { id: 'fb_actionbar', 'class': 'action' }).hide();
        body.insert(this.FBactionbar);
        
        // Put in the loading bar until the content gets replaced
        this.FBloading = new Element('div', { 'class': 'loading' });
        this.FBloading.update( new Element('img', { src: '/images/modal/loading.gif' }) );
        this.FBcontent.update( this.FBloading );
        
        this.FBcontentbody = body;
        
        $(document.body).insert({ 'top': this.FBoverlay });
        $(document.body).insert({ 'top': this.FBmodal });
        
        //Adding event observers
        this.hideObserver = this._hide.bindAsEventListener(this);
        this.kbdObserver = this._kbdHandler.bindAsEventListener(this);
        this._initObservers();

        this.initialized = true; // Mark as initialized
    },
    
    _deinit: function() {
        this._removeObservers();
        if(this.options.transitions) {
            Effect.toggle(this.FBoverlay, 'appear', {duration: this.options.overlayDuration, afterFinish: this._removeElements.bind(this) });
        } else {
            this.FBoverlay.hide();
            this._removeElements();
        }
    },
    
    _removeElements: function() {
        $(this.FBoverlay).remove();
        $(this.FBmodal).remove();
        if(typeof this.content == 'object') {
            if(this.content.id && this.content.id.match(/FB_/)) {
                this.content.id = this.content.id.replace(/FB_/, "");
            }
        }
        /* Initialized will be set to false */
        this.initialized = false;
        this.event("afterHide"); // Passing afterHide callback
        this.setOptions(this._options); //Settings options object into intial state
    },
    
    _hide: function(event) {
        Event.stop(event);
        if(event.element().id == 'fb_overlay' && !this.options.overlayClose) return false;
        this.hide();
    },
    
    hide: function(options) {
        if(this.initialized) {
            // Reading for options/callbacks except if event given as a pararmeter
            if(options && typeof options.element != 'function') Object.extend(this.options, options); 
            // Passing beforeHide callback
            this.event("beforeHide");
            if(this.options.transitions){
                Effect.Fade(this.FBmodal, { to: 0, duration: this.options.slideUpDuration, transition: Effect.Transitions.sinoidal, afterFinish: this._deinit.bind(this) } );
            } else {
                $(this.FBmodal).hide();
                this._deinit();
            }
        } else throw('FaceboxP is not initialized.');
    },
    
    show: function(content, options) {
        if(!this.initialized) this._init(options); // Check for is already initialized
        
        this.content = content;
        this.setOptions(options);
        
        if(this.FBmodal.style.display == "none") { // First modal box appearing
            this._appear();
            this.event("onShow"); // Passing onShow callback
        }
        else { // If MB already on the screen, update it
            this._update();
            this.event("onUpdate"); // Passing onUpdate callback
        }
    },
    
    _appear: function() {
        if(this.options.transitions) {
            $(this.FBoverlay).setStyle({opacity: 0});
            $(this.FBmodal).setStyle({opacity: 0}).show();
            
            this._setPosition(); 
            if(!this.loadContent()) return;
            
            new Effect.Fade(this.FBoverlay, {
                to: this.options.overlayOpacity,
                duration: this.options.overlayDuration,
                afterFinish: function() {
                    new Effect.Fade(this.FBmodal, {
                        from: 0.0,
                        to: 1.0,
                        duration: this.options.slideDownDuration, 
                        transition: Effect.Transitions.sinoidal
                    });
                }.bind(this)
            });
        } else {
            $(this.FBoverlay).setStyle({opacity: this.options.overlayOpacity});
            $(this.FBmodal).show();
            this._setPosition(); 
            this.loadContent();
        }
        this._setPositionListener = this._setPosition.bindAsEventListener(this);
        Event.observe(window, "resize", this._setPositionListener);
        Event.observe(window, "scroll", this._setPositionListener);
    },
    
    loadContent: function() {
        if(this.event("beforeLoad") != false) {
            if(typeof this.content == 'string') {
                
                // it's a string, but is it a URL or a HTML block?
                var htmlRegExp = new RegExp(/<\/?[^>]+>/gi);
                if(htmlRegExp.test(this.content)) { // HTML block
                    this._insertContent( this.content.stripScripts() );
                    this._putContent();
                } else // URL given as a parameter. We'll request it via Ajax
                    new Ajax.Request( this.content, {
                        method: this.options.method.toLowerCase(),
                        parameters: this.options.params,
                        onSuccess: function(transport) {
                            var response = new String(transport.responseText);
                            this._insertContent( transport.responseText.stripScripts() );
                            this._putContent();
                        }.bind(this),
                        onException: function(instance, exception){
                            FaceboxP.hide();
                            alert(exception);
                            throw('FaceboxP Loading Error: ' + exception);
                        }
                    });
            } else if (typeof this.content == 'object') {// HTML Object is given
                this._insertContent(this.content);
                this._putContent();
            } else {
                throw('FaceboxP: invalid content type given');
                return false;
            }
        } else
            return false;
        // if everything falls through, we can return true to continue the loading process
        return true;
    },
    
    _insertContent: function(content){
        // clear old content
        $(this.FBcontent).hide().update("");
        if(typeof content == 'string') {
            this.FBcontent.update( content );
        } else if (typeof content == 'object') {
            var _htmlObj = content.cloneNode(true);
            if(content.id) content.id = "FB_" + content.id;
            this.FBcontent.appendChild(_htmlObj);
            this.FBcontent.down().show();
        }
    },
    
    _putContent: function(callback){
        this.updateTitle();
        this.updateActionbar();
        this.FBcontent.show();
        this.focusableElements = this._findFocusableElements();
        this._setFocus(); // Setting focus on first 'focusable' element in content (input, select, textarea, link or button)
        setTimeout(function(){ // MSIE fix
            if(callback != undefined)
                callback(); // Executing internal JS from loaded content
            this.event("afterLoad"); // Passing callback
        }.bind(this),1);
    },
    
    _findFocusableElements: function() {
        return this.FBcontent.select('input:not([type~=hidden]), select, textarea, button, a[href]');
    },
    
    _setFocus: function() {
        /* Setting focus to the first 'focusable' element which is one with tabindex = 1 or the first in the form loaded. */
        if(this.focusableElements.length > 0 && this.options.autoFocusing == true) {
            var firstEl = this.focusableElements.find(function (el){
                return el.tabIndex == 1;
            }) || this.focusableElements.first();
            this.currFocused = this.focusableElements.toArray().indexOf(firstEl);
            firstEl.focus(); // Focus on first focusable element except close button
        } else if($(this.FBclose).visible())
            $(this.FBclose).focus(); // If no focusable elements exist focus on close button
    },
    
    updateTitle: function(){
        var h2 = this.FBcontent.select('h2')[0];
        if(!h2) h2 = this.FBcontent.select('h3')[0];
        if(!h2 && !this.options.title) return
        
        this.FBtitle.show();
        
        if(this.options.title != 'Notice')
            this.FBtitle.update( this.options.title );
        else if(h2 && h2.innerHTML)
            this.FBtitle.update( h2.innerHTML );
        else if(this.options.title)
            this.FBtitle.update( this.options.title );
        else
            this.FBtitle.hide();
        // remove the title inline
        if(h2)
            h2.remove();
    },
    
    updateActionbar: function(){
        var action = this.FBcontent.select('.fb_action')[0];
        if(!action){
            this.FBactionbar.hide();
        } else {
            this.FBactionbar.show();
        }
    },
    
    _update: function() { // Updating MB in case of wizards
        $(this.FBcontent).update("");
        $(this.FBactionbar).hide();
        this.FBcontent.update(this.FBloading);
        //$(this.FBcontent).update(this.options.loadingString);
        this._setPosition();
        this.loadContent();
    },
    
    _setPosition: function() {
        $(this.FBmodal).setStyle({
            width: this.options.width + 'px'
        });
        
		var left = Math.round((Element.getWidth(document.body) - Element.getWidth(this.FBmodal)) / 2 );
		left = (left > 0) ? left : 0;		
		
		var pageScroll = getPageScroll()[1];
		var pageHeight = getPageHeight();
		var modalHeight = $(this.FBmodal).getHeight();
		var modalTop = $(this.FBmodal).positionedOffset().top;		
		var top = modalTop;

		if(pageHeight < modalHeight) {
			if(pageScroll < modalTop) {
				top = 0;
			} else if(pageScroll + pageHeight > modalTop + modalHeight) {
				top = pageScroll + pageHeight - modalHeight;
			}
		} else {
			top = pageScroll + (pageHeight / 10);
		}
        
		$(this.FBmodal).setStyle({
            left : left + "px",
            top  : top + 'px'
        });
    },
    
    _kbdHandler: function(){
    },
    
    _initObservers: function() {
        $(this.FBclose).observe("click", this.hideObserver);
        if(this.options.overlayClose)
            $(this.FBoverlay).observe("click", this.hideObserver);
    },
    
    _removeObservers: function() {
        $(this.FBclose).stopObserving("click", this.hideObserver);
        if(this.options.overlayClose)
            $(this.FBoverlay).stopObserving("click", this.hideObserver);
    },
    
    event: function(eventName) {
        if(this.options[eventName]) {
            var returnValue = this.options[eventName](); // Executing callback
            this.options[eventName] = null; // Removing callback after execution
            if(returnValue != undefined) 
                return returnValue;
            else 
                return true;
        }
        return true;
    },
    
    getContent: function() {
        return $(this.FBcontentbody);
    },
    
    confirm: function(message, callbackYes, callbackNo, options) {
        var container = new Element('div', { 'class': 'confirm' });
        
        var message = new Element('p').update(message);
        container.insert(message);
        
        FaceboxP.show(container, { title: 'Are you sure?' });
        
        var base_options = {
            btnYes: 'Yes',
            btnNo:  'No'
        };
        
        Object.extend(base_options, options || { });
        
        var confirmYes = new Element('input', { type: 'button', 'class': 'button', value: options.btnYes });
        var confirmNo  = new Element('a', { href: '#', 'class': 'cancel' }).update(options.btnNo);
        var or         = new Element('span').update(' or ');
        this.FBactionbar.insert(confirmYes);
        this.FBactionbar.insert(or);
        this.FBactionbar.insert(confirmNo);
        this.FBactionbar.show();
        
        confirmYes.observe('click', function(e){
            e.stop();
            this.FBactionbar.update(null);
            FaceboxP.hide();
            if(typeof callbackYes == 'function')
                callbackYes();
        }.bindAsEventListener(this));
        confirmNo.observe('click', function(e){
            e.stop();
            this.FBactionbar.update(null);
            FaceboxP.hide();
            if(typeof callbackNo == 'function')
                callbackNo();
        }.bindAsEventListener(this));
    }
    
}

Object.extend(FaceboxP, FaceboxP.Methods);

if(!window.Modalbox){
    // Old Modalbox connector...
    var Modalbox = new Object();
    Modalbox.Methods = {
        show: function(content, options) {
            this.MBcontent = FaceboxP.FBcontent;
            FaceboxP.show(content, options);
        },
        hide: function(options) {
            FaceboxP.hide(options);
        }
    };
    Object.extend(Modalbox, Modalbox.Methods);
}

//document.observe('dom:loaded', function(){FaceboxP.show('<div class="test">Test</div>')});

  // getPageScroll() by quirksmode.com
  function getPageScroll() {
    var xScroll, yScroll;
    if (self.pageYOffset) {
      yScroll = self.pageYOffset;
      xScroll = self.pageXOffset;
    } else if (document.documentElement && document.documentElement.scrollTop) {     // Explorer 6 Strict
      yScroll = document.documentElement.scrollTop;
      xScroll = document.documentElement.scrollLeft;
    } else if (document.body) {// all other Explorers
      yScroll = document.body.scrollTop;
      xScroll = document.body.scrollLeft;    
    }
    return new Array(xScroll,yScroll) 
  }

  // Adapted from getPageSize() by quirksmode.com
  function getPageHeight() {
    var windowHeight
    if (self.innerHeight) {    // all except Explorer
      windowHeight = self.innerHeight;
    } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
      windowHeight = document.documentElement.clientHeight;
    } else if (document.body) { // other Explorers
      windowHeight = document.body.clientHeight;
    }    
    return windowHeight
  }
/*prototip*/
//  Prototip 2.0.4 - 05-08-2008
//  Copyright (c) 2008 Nick Stakenburg (http://www.nickstakenburg.com)
//
//  Licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License
//  http://creativecommons.org/licenses/by-nc-nd/3.0/

//  More information on this project:
//  http://www.nickstakenburg.com/projects/prototip2/

var Prototip = {
  Version: '2.0.4'
};

var Tips = {
  options: {
    images: '/images/prototip/', // image path, can be relative to this file or an absolute url
    zIndex: 6000                   // raise if required
  }
};

Prototip.Styles = {
  // The default style every other style will inherit from.
  // Used when no style is set through the options on a tooltip.
  'default': {
    border: 6,
    borderColor: '#c7c7c7',
    className: 'default',
    closeButton: false,
    hideAfter: false,
    hideOn: 'mouseleave',
    hook: false,
	//images: 'styles/creamy/',    // Example: different images. An absolute url or relative to the images url defined above.
    radius: 6,
	showOn: 'mousemove',
    stem: {
      //position: 'topLeft',       // Example: optional default stem position, this will also enable the stem
      height: 12,
      width: 15
    }
  },

  'protoblue': {
    className: 'protoblue',
    border: 6,
    borderColor: '#116497',
    radius: 6,
    stem: { height: 12, width: 15 }
  },

  'darkgrey': {
    className: 'darkgrey',
    border: 3,
    borderColor: '#363636',
    radius: 3,
    stem: { height: 12, width: 15 }
  },

  'creamy': {
    className: 'creamy',
    border: 6,
    borderColor: '#ebe4b4',
    radius: 6,
    stem: { height: 12, width: 15 }
  },

  'protogrey': {
    className: 'protogrey',
    border: 6,
    borderColor: '#606060',
    radius: 6,
    stem: { height: 12, width: 15 }
  }
};

eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('O.11(V,{5F:"1.6.0.2",3R:b(){3.3D("1Y");9(/^(6v?:\\/\\/|\\/)/.6d(c.8.W)){c.W=c.8.W}10{e A=/1Q(?:-[\\w\\d.]+)?\\.4D(.*)/;c.W=(($$("4z 4w[2c]").3v(b(B){N B.2c.2a(A)})||{}).2c||"").3j(A,"")+c.8.W}9(1Y.2r.3d&&!1a.3Y.v){1a.3Y.37("v","5B:5s-5n-5g:59");1a.1e("3I:33",b(){1a.4M().4G("v\\\\:*","4E: 30(#2Z#4B);")})}c.2o();q.1e(2U,"2T",3.2T)},3D:b(A){9((4u 2U[A]=="4q")||(3.2Q(2U[A].4l)<3.2Q(3["4k"+A]))){4i("V 6l "+A+" >= "+3["4k"+A]);}},2Q:b(A){e B=A.3j(/4f.*|\\./g,"");B=6b(B+"0".66(4-B.3f));N A.5S("4f")>-1?B-1:B},46:$w("44 5K"),24:b(A){9(1Y.2r.3d){N A}A=A.2t(b(G,F){e E=O.2z(3)?3:3.k,B=F.5A;5v{e D=E.2x,C=B.2x}5j(H){N}9(V.46.2F(E.2x.1Z())){9(B!=E&&!B.56(E)){G(F)}}10{9(B!=E&&!$A(E.2M("*")).2F(B)){G(F)}}});N A},3g:b(A){N(A>0)?(-1*A):(A).4X()},2T:b(){c.3G()}});O.11(c,{1H:[],18:[],2o:b(){3.2L=3.1r},1o:(b(A){N{1l:(A?"1V":"1l"),15:(A?"1J":"15"),1V:(A?"1V":"1l"),1J:(A?"1J":"15")}})(1Y.2r.3d),3B:{1l:"1l",15:"15",1V:"1l",1J:"15"},2e:{j:"2X",2X:"j",h:"1u",1u:"h",1U:"1U",1f:"1g",1g:"1f"},3y:{p:"1f",o:"1g"},3s:b(A){N!!28[1]?3.2e[A]:A},1j:(b(B){e A=r 4o("4n ([\\\\d.]+)").4m(B);N A?(3u(A[1])<7):Y})(6r.6p),3p:(1Y.2r.6k&&!1a.6i),37:b(A){3.1H.2K(A)},1G:b(A){e B=3.1H.3v(b(C){N C.k==$(A)});9(B){B.4e();9(B.1c){B.n.1G();9(c.1j){B.1p.1G()}}3.1H=3.1H.4c(B)}A.1Q=2i},3G:b(){3.1H.3h(b(A){3.1G(A.k)}.1i(3))},2I:b(C){9(C==3.49){N}9(3.18.3f===0){3.2L=3.8.1r;3e(e B=0,A=3.1H.3f;B<A;B++){3.1H[B].n.f({1r:3.8.1r})}}C.n.f({1r:3.2L++});9(C.T){C.T.f({1r:3.2L})}3.49=C},45:b(A){3.31(A);3.18.2K(A)},31:b(A){3.18=3.18.4c(A)},42:b(){c.18.1S("U")},X:b(B,F){B=$(B),F=$(F);e K=O.11({1d:{x:0,y:0},Q:Y},28[2]||{});e D=K.1x||F.2v();D.j+=K.1d.x;D.h+=K.1d.y;e C=K.1x?[0,0]:F.3T(),A=1a.1F.2A(),G=K.1x?"20":"1b";D.j+=(-1*(C[0]-A[0]));D.h+=(-1*(C[1]-A[1]));9(K.1x){e E=[0,0];E.p=0;E.o=0}e I={k:B.21()},J={k:O.2h(D)};I[G]=K.1x?E:F.21();J[G]=O.2h(D);3e(e H 3P J){3M(K[H]){S"5p":S"5o":J[H].j+=I[H].p;19;S"5k":J[H].j+=(I[H].p/2);19;S"5i":J[H].j+=I[H].p;J[H].h+=(I[H].o/2);19;S"5h":S"5f":J[H].h+=I[H].o;19;S"5d":S"5c":J[H].j+=I[H].p;J[H].h+=I[H].o;19;S"5a":J[H].j+=(I[H].p/2);J[H].h+=I[H].o;19;S"58":J[H].h+=(I[H].o/2);19}}D.j+=-1*(J.k.j-J[G].j);D.h+=-1*(J.k.h-J[G].h);9(K.Q){B.f({j:D.j+"i",h:D.h+"i"})}N D}});c.2o();e 55=54.3J({2o:b(C,E){3.k=$(C);9(!3.k){4i("V: q 53 51, 4Y 3J a 1c.");N}c.1G(3.k);e A=(O.2s(E)||O.2z(E)),B=A?28[2]||[]:E;3.1s=A?E:2i;9(B.1T){B=O.11(O.2h(V.3q[B.1T]),B)}3.8=O.11(O.11({1m:Y,1h:0,3o:"#4L",1n:0,u:c.8.u,13:c.8.4F,1v:!(B.17&&B.17=="1W")?0.14:Y,1A:Y,1K:"1J",3C:Y,X:B.X,1d:B.X?{x:0,y:0}:{x:16,y:16},1I:(B.X&&!B.X.1x)?1k:Y,17:"2p",m:Y,1T:"2Z",1b:3.k,12:Y,1F:(B.X&&!B.X.1x)?Y:1k,p:Y},V.3q["2Z"]),B);3.1b=$(3.8.1b);3.1n=3.8.1n;3.1h=(3.1n>3.8.1h)?3.1n:3.8.1h;9(3.8.W){3.W=3.8.W.2Y("://")?3.8.W:c.W+3.8.W}10{3.W=c.W+"4C/"+(3.8.1T||"")+"/"}9(!3.W.4A("/")){3.W+="/"}9(O.2s(3.8.m)){3.8.m={Q:3.8.m}}9(3.8.m.Q){3.8.m=O.11(O.2h(V.3q[3.8.1T].m)||{},3.8.m);3.8.m.Q=[3.8.m.Q.2a(/[a-z]+/)[0].1Z(),3.8.m.Q.2a(/[A-Z][a-z]+/)[0].1Z()];3.8.m.1C=["j","2X"].2F(3.8.m.Q[0])?"1f":"1g";3.1t={1f:Y,1g:Y}}9(3.8.1m){3.8.1m.8=O.11({2V:1Y.4y},3.8.1m.8||{})}3.1o=$w("4x 44").2F(3.k.2x.1Z())?c.3B:c.1o;9(3.8.X.1x){e D=3.8.X.1q.2a(/[a-z]+/)[0].1Z();3.20=c.2e[D]+c.2e[3.8.X.1q.2a(/[A-Z][a-z]+/)[0].1Z()].2n()}3.3A=(c.3p&&3.1n);3.3z();c.37(3);3.3x();V.11(3)},3z:b(){3.n=r q("R",{u:"1Q"}).f({1r:c.8.1r});9(3.3A){3.n.U=b(){3.f("j:-3w;h:-3w;1N:2m;");N 3};3.n.P=b(){3.f("1N:18");N 3};3.n.18=b(){N(3.2S("1N")=="18"&&3u(3.2S("h").3j("i",""))>-4v)}}3.n.U();9(c.1j){3.1p=r q("4t",{u:"1p",2c:"4s:Y;",4r:0}).f({2l:"2b",1r:c.8.1r-1,4p:0})}9(3.8.1m){3.23=3.23.2t(3.2R)}3.1q=r q("R",{u:"1s"});3.12=r q("R",{u:"12"}).U();9(3.8.13||(3.8.1K.k&&3.8.1K.k=="13")){3.13=r q("R",{u:"2k"}).26(3.W+"2k.2j")}},2G:b(){9(1a.33){3.2P();3.3t=1k;N 1k}10{9(!3.3t){1a.1e("3I:33",3.2P);N Y}}},2P:b(){$(1a.2O).s(3.n);9(c.1j){$(1a.2O).s(3.1p)}9(3.8.1m){$(1a.2O).s(3.T=r q("R",{u:"6u"}).26(3.W+"T.6t").U())}e G="n";9(3.8.m.Q){3.m=r q("R",{u:"6q"}).f({o:3.8.m[3.8.m.1C=="1g"?"o":"p"]+"i"});e B=3.8.m.1C=="1f";3[G].s(3.3r=r q("R",{u:"6n 2N"}).s(3.4h=r q("R",{u:"6m 2N"})));3.m.s(3.1R=r q("R",{u:"6j"}).f({o:3.8.m[B?"p":"o"]+"i",p:3.8.m[B?"o":"p"]+"i"}));9(c.1j&&!3.8.m.Q[1].4g().2Y("6h")){3.1R.f({2l:"6f"})}G="4h"}9(3.1h){e D=3.1h,F;3[G].s(3.27=r q("6e",{u:"27"}).s(3.25=r q("3m",{u:"25 3l"}).f("o: "+D+"i").s(r q("R",{u:"2J 6c"}).s(r q("R",{u:"29"}))).s(F=r q("R",{u:"6a"}).f({o:D+"i"}).s(r q("R",{u:"4d"}).f({1y:"0 "+D+"i",o:D+"i"}))).s(r q("R",{u:"2J 65"}).s(r q("R",{u:"29"})))).s(3.2W=r q("3m",{u:"2W 3l"}).s(3.3i=r q("R",{u:"3i"}).f("2q: 0 "+D+"i"))).s(3.4b=r q("3m",{u:"4b 3l"}).f("o: "+D+"i").s(r q("R",{u:"2J 64"}).s(r q("R",{u:"29"}))).s(F.63(1k)).s(r q("R",{u:"2J 62"}).s(r q("R",{u:"29"})))));G="3i";e C=3.27.2M(".29");$w("5Z 5Y 5X 5W").3h(b(I,H){9(3.1n>0){V.48(C[H],I,{1L:3.8.3o,1h:D,1n:3.8.1n})}10{C[H].2H("47")}C[H].f({p:D+"i",o:D+"i"}).2H("29"+I.2n())}.1i(3));3.27.2M(".4d",".2W",".47").1S("f",{1L:3.8.3o})}3[G].s(3.1c=r q("R",{u:"1c "+3.8.u}).s(3.1X=r q("R",{u:"1X"}).s(3.12)));9(3.8.p){e E=3.8.p;9(O.5O(E)){E+="i"}3.1c.f("p:"+E)}9(3.m){e A={};A[3.8.m.1C=="1f"?"h":"1u"]=3.m;3.n.s(A);3.2f()}3.1c.s(3.1q);9(!3.8.1m){3.3c({12:3.8.12,1s:3.1s})}},3c:b(E){e A=3.n.2S("1N");3.n.f("o:1M;p:1M;1N:2m").P();9(3.1h){3.25.f("o:0");3.25.f("o:0")}9(E.12){3.12.P().43(E.12);3.1X.P()}10{9(!3.13){3.12.U();3.1X.U()}}9(O.2z(E.1s)){E.1s.P()}9(O.2s(E.1s)||O.2z(E.1s)){3.1q.43(E.1s)}3.1c.f({p:3.1c.3F()+"i"});3.n.f("1N:18").P();3.1c.P();e C=3.1c.21(),B={p:C.p+"i"},D=[3.n];9(c.1j){D.2K(3.1p)}9(3.13){3.12.P().s({h:3.13});3.1X.P()}9(E.12||3.13){3.1X.f("p: 34%")}B.o=2i;3.n.f({1N:A});3.1q.2H("2N");9(E.12||3.13){3.12.2H("2N")}9(3.1h){3.25.f("o:"+3.1h+"i");3.25.f("o:"+3.1h+"i");B="p: "+(C.p+2*3.1h)+"i";D.2K(3.27)}D.1S("f",B);9(3.m){3.2f();9(3.8.m.1C=="1f"){3.n.f({p:3.n.3F()+3.8.m.o+"i"})}}3.n.U()},3x:b(){3.3b=3.23.1z(3);3.41=3.U.1z(3);9(3.8.1I&&3.8.17=="2p"){3.8.17="1l"}9(3.8.17==3.8.1K){3.1P=3.40.1z(3);3.k.1e(3.8.17,3.1P)}9(3.13){3.13.1e("1l",b(E){E.26(3.W+"5J.2j")}.1i(3,3.13)).1e("15",b(E){E.26(3.W+"2k.2j")}.1i(3,3.13))}e C={k:3.1P?[]:[3.k],1b:3.1P?[]:[3.1b],1q:3.1P?[]:[3.n],13:[],2b:[]},A=3.8.1K.k;3.3a=A||(!3.8.1K?"2b":"k");3.1O=C[3.3a];9(!3.1O&&A&&O.2s(A)){3.1O=3.1q.2M(A)}e D={1V:"1l",1J:"15"};$w("P U").3h(b(H){e G=H.2n(),F=(3.8[H+"3X"].35||3.8[H+"3X"]);3[H+"3W"]=F;9(["1V","1J","1l","15"].2Y(F)){3[H+"3W"]=(3.1o[F]||F);3["35"+G]=V.24(3["35"+G])}}.1i(3));9(!3.1P){3.k.1e(3.8.17,3.3b)}9(3.1O){3.1O.1S("1e",3.5I,3.41)}9(!3.8.1I&&3.8.17=="1W"){3.2u=3.Q.1z(3);3.k.1e("2p",3.2u)}3.3V=3.U.2t(b(G,F){e E=F.5H(".2k");9(E){E.5G();F.5E();G(F)}}).1z(3);9(3.13){3.n.1e("1W",3.3V)}9(3.8.17!="1W"&&(3.3a!="k")){3.2D=V.24(b(){3.1E("P")}).1z(3);3.k.1e(3.1o.15,3.2D)}e B=[3.k,3.n];3.39=V.24(b(){c.2I(3);3.2C()}).1z(3);3.38=V.24(3.1A).1z(3);B.1S("1e",3.1o.1l,3.39).1S("1e",3.1o.15,3.38);9(3.8.1m&&3.8.17!="1W"){3.2B=V.24(3.3S).1z(3);3.k.1e(3.1o.15,3.2B)}},4e:b(){9(3.8.17==3.8.1K){3.k.1w(3.8.17,3.1P)}10{3.k.1w(3.8.17,3.3b);9(3.1O){3.1O.1S("1w")}}9(3.2u){3.k.1w("2p",3.2u)}9(3.2D){3.k.1w("15",3.2D)}3.n.1w();3.k.1w(3.1o.1l,3.39).1w(3.1o.15,3.38);9(3.2B){3.k.1w(3.1o.15,3.2B)}},2R:b(C,B){9(!3.1c){9(!3.2G()){N}}3.Q(B);9(3.2w){N}10{9(3.3Q){C(B);N}}3.2w=1k;e D={2g:{1D:22.1D(B),1B:22.1B(B)}};e A=O.2h(3.8.1m.8);A.2V=A.2V.2t(b(F,E){3.3c({12:3.8.12,1s:E.5C});3.Q(D);(b(){F(E);e G=(3.T&&3.T.18());9(3.T){3.1E("T");3.T.1G();3.T=2i}9(G){3.P()}3.3Q=1k;3.2w=2i}.1i(3)).1v(0.6)}.1i(3));3.5z=q.P.1v(3.8.1v,3.T);3.n.U();3.2w=1k;3.T.P();3.5y=(b(){r 5x.5w(3.8.1m.30,A)}.1i(3)).1v(3.8.1v);N Y},3S:b(){3.1E("T")},23:b(A){9(!3.1c){9(!3.2G()){N}}3.Q(A);9(3.n.18()){N}3.1E("P");3.5u=3.P.1i(3).1v(3.8.1v)},1E:b(A){9(3[A+"3N"]){5t(3[A+"3N"])}},P:b(){9(3.n.18()){N}9(c.1j){3.1p.P()}9(3.8.3C){c.42()}c.45(3);3.1c.P();3.n.P();9(3.m){3.m.P()}3.k.3O("1Q:5r")},1A:b(A){9(3.8.1m){9(3.T&&3.8.17!="1W"){3.T.U()}}9(!3.8.1A){N}3.2C();3.5q=3.U.1i(3).1v(3.8.1A)},2C:b(){9(3.8.1A){3.1E("1A")}},U:b(){3.1E("P");3.1E("T");9(!3.n.18()){N}3.3L()},3L:b(){9(c.1j){3.1p.U()}9(3.T){3.T.U()}3.n.U();(3.27||3.1c).P();c.31(3);3.k.3O("1Q:2m")},40:b(A){9(3.n&&3.n.18()){3.U(A)}10{3.23(A)}},2f:b(){e C=3.8.m,B=28[0]||3.1t,D=c.3s(C.Q[0],B[C.1C]),F=c.3s(C.Q[1],B[c.2e[C.1C]]),A=3.1n||0;3.1R.26(3.W+D+F+".2j");9(C.1C=="1f"){e E=(D=="j")?C.o:0;3.3r.f("j: "+E+"i;");3.1R.f({"2y":D});3.m.f({j:0,h:(F=="1u"?"34%":F=="1U"?"50%":0),5D:(F=="1u"?-1*C.p:F=="1U"?-0.5*C.p:0)+(F=="1u"?-1*A:F=="h"?A:0)+"i"})}10{3.3r.f(D=="h"?"1y: 0; 2q: "+C.o+"i 0 0 0;":"2q: 0; 1y: 0 0 "+C.o+"i 0;");3.m.f(D=="h"?"h: 0; 1u: 1M;":"h: 1M; 1u: 0;");3.1R.f({1y:0,"2y":F!="1U"?F:"2b"});9(F=="1U"){3.1R.f("1y: 0 1M;")}10{3.1R.f("1y-"+F+": "+A+"i;")}9(c.3p){9(D=="1u"){3.m.f({Q:"3U",5m:"5l",h:"1M",1u:"1M","2y":"j",p:"34%",1y:(-1*C.o)+"i 0 0 0"});3.m.1T.2l="3K"}10{3.m.f({Q:"3Z","2y":"2b",1y:0})}}}3.1t=B},Q:b(B){9(!3.1c){9(!3.2G()){N}}c.2I(3);9(c.1j){e A=3.n.21();9(!3.2E||3.2E.o!=A.o||3.2E.p!=A.p){3.1p.f({p:A.p+"i",o:A.o+"i"})}3.2E=A}9(3.8.X){e J,H;9(3.20){e K=1a.1F.2A(),C=B.2g||{};e G,I=2;3M(3.20.4g()){S"5L":S"5M":G={x:0-I,y:0-I};19;S"5N":G={x:0,y:0-I};19;S"5e":S"5P":G={x:I,y:0-I};19;S"5Q":G={x:I,y:0};19;S"5R":S"5b":G={x:I,y:I};19;S"5T":G={x:0,y:I};19;S"5U":S"5V":G={x:0-I,y:I};19;S"57":G={x:0-I,y:0};19}G.x+=3.8.1d.x;G.y+=3.8.1d.y;J=O.11({1d:G},{k:3.8.X.1q,20:3.20,1x:{h:C.1B||22.1B(B)-K.h,j:C.1D||22.1D(B)-K.j}});H=c.X(3.n,3.1b,J);9(3.8.1F){e M=3.36(H),L=M.1t;H=M.Q;H.j+=L.1g?2*V.3g(G.x-3.8.1d.x):0;H.h+=L.1g?2*V.3g(G.y-3.8.1d.y):0;9(3.m&&(3.1t.1f!=L.1f||3.1t.1g!=L.1g)){3.2f(L)}}H={j:H.j+"i",h:H.h+"i"};3.n.f(H)}10{J=O.11({1d:3.8.1d},{k:3.8.X.1q,1b:3.8.X.1b});H=c.X(3.n,3.1b,O.11({Q:1k},J));H={j:H.j+"i",h:H.h+"i"}}9(3.T){e E=c.X(3.T,3.1b,O.11({Q:1k},J))}9(c.1j){3.1p.f(H)}}10{e F=3.1b.2v(),C=B.2g||{},H={j:((3.8.1I)?F[0]:C.1D||22.1D(B))+3.8.1d.x,h:((3.8.1I)?F[1]:C.1B||22.1B(B))+3.8.1d.y};9(!3.8.1I&&3.k!==3.1b){e D=3.k.2v();H.j+=-1*(D[0]-F[0]);H.h+=-1*(D[1]-F[1])}9(!3.8.1I&&3.8.1F){e M=3.36(H),L=M.1t;H=M.Q;9(3.m&&(3.1t.1f!=L.1f||3.1t.1g!=L.1g)){3.2f(L)}}H={j:H.j+"i",h:H.h+"i"};3.n.f(H);9(3.T){3.T.f(H)}9(c.1j){3.1p.f(H)}}},36:b(C){e E={1f:Y,1g:Y},D=3.n.21(),B=1a.1F.2A(),A=1a.1F.21(),G={j:"p",h:"o"};3e(e F 3P G){9((C[F]+D[G[F]]-B[F])>A[G[F]]){C[F]=C[F]-(D[G[F]]+(2*3.8.1d[F=="j"?"x":"y"]));9(3.m){E[c.3y[G[F]]]=1k}}}N{Q:C,1t:E}}});O.11(V,{48:b(G,H){e F=28[2]||3.8,B=F.1n,E=F.1h,D=r q("60",{u:"61"+H.2n(),p:E+"i",o:E+"i"}),A={h:(H.4a(0)=="t"),j:(H.4a(1)=="l")};9(D&&D.3k&&D.3k("2d")){G.s(D);e C=D.3k("2d");C.52=F.1L;C.4Z((A.j?B:E-B),(A.h?B:E-B),B,0,67.68*2,1k);C.69();C.3H((A.j?B:0),0,E-B,E);C.3H(0,(A.h?B:0),E,E-B)}10{G.s(r q("R").f({p:E+"i",o:E+"i",1y:0,2q:0,2l:"3K",Q:"3U",4W:"2m"}).s(r q("v:4V",{4U:F.1L,4T:"4S",4R:F.1L,6g:(B/E*0.5).4Q(2)}).f({p:2*E-1+"i",o:2*E-1+"i",Q:"3Z",j:(A.j?0:(-1*E))+"i",h:(A.h?0:(-1*E))+"i"})))}}});q.4P({26:b(C,B){C=$(C);e A=O.11({3E:"h j",3n:"4O-3n",32:"4N",1L:""},28[2]||{});C.f(c.1j?{6o:"4K:4J.4I.6s(2c=\'"+B+"\'\', 32=\'"+A.32+"\')"}:{4H:A.1L+" 30("+B+") "+A.3E+" "+A.3n});N C}});V.4j={P:b(){c.2I(3);3.2C();e D={};9(3.8.X){D.2g={1D:0,1B:0}}10{e A=3.1b.2v(),C=3.1b.3T(),B=1a.1F.2A();A.j+=(-1*(C[0]-B[0]));A.h+=(-1*(C[1]-B[1]));D.2g={1D:A.j,1B:A.h}}9(3.8.1m){3.2R(D)}10{3.23(D)}3.1A()}};V.11=b(A){A.k.1Q={};O.11(A.k.1Q,{P:V.4j.P.1i(A),U:A.U.1i(A),1G:c.1G.1i(c,A.k)})};V.3R();',62,404,'|||this|||||options|if||function|Tips||var|setStyle||top|px|left|element||stem|wrapper|height|width|Element|new|insert||className|||||||||||||||||||return|Object|show|position|div|case|loader|hide|Prototip|images|hook|false||else|extend|title|closeButton||mouseout||showOn|visible|break|document|target|tooltip|offset|observe|horizontal|vertical|border|bind|fixIE|true|mouseover|ajax|radius|useEvent|iframeShim|tip|zIndex|content|stemInverse|bottom|delay|stopObserving|mouse|margin|bindAsEventListener|hideAfter|pointerY|orientation|pointerX|clearTimer|viewport|remove|tips|fixed|mouseleave|hideOn|backgroundColor|auto|visibility|hideTargets|eventToggle|prototip|stemImage|invoke|style|middle|mouseenter|click|toolbar|Prototype|toLowerCase|mouseHook|getDimensions|Event|showDelayed|capture|borderTop|setPngBackground|borderFrame|arguments|prototip_Corner|match|none|src||_inverse|positionStem|fakePointer|clone|null|png|close|display|hidden|capitalize|initialize|mousemove|padding|Browser|isString|wrap|eventPosition|cumulativeOffset|ajaxContentLoading|tagName|float|isElement|getScrollOffsets|ajaxHideEvent|cancelHideAfter|eventCheckDelay|iframeShimDimensions|member|build|addClassName|raise|prototip_CornerWrapper|push|zIndexTop|select|clearfix|body|_build|convertVersionString|ajaxShow|getStyle|unload|window|onComplete|borderMiddle|right|include|default|url|removeVisible|sizingMethod|loaded|100|event|getPositionWithinViewport|add|activityLeave|activityEnter|hideElement|eventShow|_update|IE|for|length|toggleInt|each|borderCenter|replace|getContext|borderRow|li|repeat|borderColor|WebKit419|Styles|stemWrapper|inverseStem|_isBuilding|parseFloat|find|9500px|activate|_stemTranslation|setup|fixSafari2|specialEvent|hideOthers|require|align|getWidth|removeAll|fillRect|dom|create|block|afterHide|switch|Timer|fire|in|ajaxContentLoaded|start|ajaxHide|cumulativeScrollOffset|relative|buttonEvent|Action|On|namespaces|absolute|toggle|eventHide|hideAll|update|input|addVisibile|_captureTroubleElements|prototip_Fill|createCorner|_highest|charAt|borderBottom|without|prototip_Between|deactivate|_|toUpperCase|stemBox|throw|Methods|REQUIRED_|Version|exec|MSIE|RegExp|opacity|undefined|frameBorder|javascript|iframe|typeof|9500|script|area|emptyFunction|head|endsWith|VML|styles|js|behavior|closeButtons|addRule|background|Microsoft|DXImageTransform|progid|000000|createStyleSheet|scale|no|addMethods|toFixed|strokeColor|1px|strokeWeight|fillcolor|roundrect|overflow|abs|cannot|arc||available|fillStyle|not|Class|Tip|descendantOf|LEFTMIDDLE|leftMiddle|vml|bottomMiddle|BOTTOMRIGHT|rightBottom|bottomRight|TOPRIGHT|leftBottom|com|bottomLeft|rightMiddle|catch|topMiddle|both|clear|microsoft|rightTop|topRight|hideAfterTimer|shown|schemas|clearTimeout|showTimer|try|Request|Ajax|ajaxTimer|loaderTimer|relatedTarget|urn|responseText|marginTop|stop|REQUIRED_Prototype|blur|findElement|hideAction|close_hover|textarea|LEFTTOP|TOPLEFT|TOPMIDDLE|isNumber|RIGHTTOP|RIGHTMIDDLE|RIGHTBOTTOM|indexOf|BOTTOMMIDDLE|BOTTOMLEFT|LEFTBOTTOM|br|bl|tr|tl|canvas|cornerCanvas|prototip_CornerWrapperBottomRight|cloneNode|prototip_CornerWrapperBottomLeft|prototip_CornerWrapperTopRight|times|Math|PI|fill|prototip_BetweenCorners|parseInt|prototip_CornerWrapperTopLeft|test|ul|inline|arcSize|MIDDLE|evaluate|prototip_StemImage|WebKit|requires|prototip_StemBox|prototip_StemWrapper|filter|userAgent|prototip_Stem|navigator|AlphaImageLoader|gif|prototipLoader|https'.split('|'),0,{}));
/*reviewpips/reviewpips*/
var ReviewPips = {};

if((typeof Prototype=='undefined') ||
   (typeof Element == 'undefined') ||
   (typeof Element.Methods=='undefined')
  )
  throw("ReviewPips requires the Prototype JavaScript framework");

function loadExtScript(file){
    var extScript = new Element('script', { type: 'text/javascript', src: file });
    $(document.getElementsByTagName("head")[0]).insert( extScript );
}
function doRollovers(){
	if(document.getElementById) {
		var images = document.getElementsByTagName('IMG');
		var buttons = document.getElementsByTagName('INPUT');
	}
	else if(document.all) {
		var images = document.all.tags('IMG');
		var buttons = document.all.tags('INPUT');
	}
	else return;
	preloads = new Object();
	for (var i = 0; i < images.length; i++) {
		var imageOffSrc = images[i].src + "";
		if(imageOffSrc.indexOf("_off") != -1) {
			var imageOverSrc = imageOffSrc.replace(/_off/g, "_over");
			preloads['imageOff_' + i] = new Image();
			preloads['imageOff_' + i].src = imageOffSrc;
			preloads['imageOver_' + i] = new Image();
			preloads['imageOver_' + i].src = imageOverSrc;
			images[i].onmouseover = function(){this.src = this.src.replace(/_off/g, "_over");}
			images[i].onmouseout = function(){this.src = this.src.replace(/_over/g, "_off");}
		}
	}
	for (var i = 0; i < buttons.length; i++) {
		if(buttons[i].src) {
			var imageOffSrc = buttons[i].src + "";
			if(imageOffSrc.indexOf("_off") != -1) {
				var imageOverSrc = imageOffSrc.replace(/_off/g, "_over");
				preloads['imageOff_' + i] = new Image();
				preloads['imageOff_' + i].src = imageOffSrc;
				preloads['imageOver_' + i] = new Image();
				preloads['imageOver_' + i].src = imageOverSrc;
				buttons[i].onmouseover = function(){this.src = this.src.replace(/_off/g, "_over");}
				buttons[i].onmouseout = function(){this.src = this.src.replace(/_over/g, "_off");}
			}
		}
	}
}
document.observe('dom:loaded', function(){doRollovers();});

function getPageSize() {
     var xScroll, yScroll;
    
    if (window.innerHeight && window.scrollMaxY) {    
        xScroll = window.innerWidth + window.scrollMaxX;
        yScroll = window.innerHeight + window.scrollMaxY;
    } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
        xScroll = document.body.scrollWidth;
        yScroll = document.body.scrollHeight;
    } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
        xScroll = document.body.offsetWidth;
        yScroll = document.body.offsetHeight;
    }
    
    var windowWidth, windowHeight;
    
    if (self.innerHeight) {    // all except Explorer
        if(document.documentElement.clientWidth){
            windowWidth = document.documentElement.clientWidth; 
        } else {
            windowWidth = self.innerWidth;
        }
        windowHeight = self.innerHeight;
    } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
        windowWidth = document.documentElement.clientWidth;
        windowHeight = document.documentElement.clientHeight;
    } else if (document.body) { // other Explorers
        windowWidth = document.body.clientWidth;
        windowHeight = document.body.clientHeight;
    }    
    
    // for small pages with total height less then height of the viewport
    if(yScroll < windowHeight){
        pageHeight = windowHeight;
    } else { 
        pageHeight = yScroll;
    }

    // for small pages with total width less then width of the viewport
    if(xScroll < windowWidth){    
        pageWidth = xScroll;        
    } else {
        pageWidth = windowWidth;
    }

    return [pageWidth,pageHeight];
}

ReviewPips.Ajax = {

    path: '/',
    
    loading: function() {
        var loading = new Element('span', { 'class': 'loading' });
        return loading;
    }
    
}
ReviewPips.Ajax.FormSubmit = Class.create({
    
    options: {
        keywordOK:  'OK',
        keywordBAD: 'BAD',
        onOK:        function(){},
        onBAD:       function(){},
        onSuccess:   function(tr){},
        onFailure:   function(){},
        showModal:   true
    },
    _options: new Object,
    setOptions: function(options) {
        Object.extend(this.options, options || {});
    },
    initialize: function(form, options){
        // Setting up original options with default options
        Object.extend(this._options, this.options);
        this.setOptions(options);
        
        this.form = form;
        
        var method = form.getAttribute('method') || 'get';
        var action = form.getAttribute('action');
        
        new Ajax.Request(action, {
            method: method,
            parameters: form.serialize(true),
            onSuccess: this.onSuccess.bind(this),
            onFailure: this.onFailure.bind(this)
        });
    },
    onOK: function(tr){
        this.options.onOK(tr);
    },
    onBAD: function(tr){
        this.options.onBAD(tr);
    },
    onSuccess: function(tr){
        this.options.onSuccess(tr);
        
        var resp = tr.responseText;
        var success = null;
        
        if(ReviewPips.User && ReviewPips.User.checkLogin(resp)){
            // handled by Ajax.Responders...
            return;
        } else if(resp.match( this.options.keywordOK )){
            this.onOK(tr);
            success = true;
        } else if(resp.match( this.options.keywordBAD )){
            this.onBAD(tr);
            success = false;
        } else {
            alert('An unknown error occured.');
        }
        
        // handle a JSON response with flash_msg
        if(tr.headerJSON && this.options.showModal && tr.headerJSON.flash_msg){
            var flashClass = (success === true) ? 'success' : 'error';
            var flash_msg = tr.headerJSON.flash_msg;
            Modalbox.show('<div class="flash_msg '+flashClass+'">' + flash_msg + '</div>');
        }
    },
    onFailure: function(){
        alert('An unknown error occured.');
    }
    
});
document.observe('dom:loaded', function(){var headerlink = $('header').select('h1 a')[0]; if(headerlink){ ReviewPips.Ajax.path = headerlink.href; }});

// make rel="extrnal" open a new window
document.observe('dom:loaded', function(){
    $$('a[rel="external"]').each(function(a){
        a.target = '_blank';
    });
});

Event.observe(window,'load',function(){
    // init the tooltips
    $$('.info[title]').each(function(a){
        new Tip(a, a.getAttribute('title'), {
            style: 'darkgrey',
            stem: 'topLeft',
            hook: { tip: 'topLeft', mouse: true },
            offset: { x: 0, y: 16 }
        });
        a.removeAttribute('title');
    });
});

// search field autocompletion
Event.observe(window, 'load', function(){
    if(!$('searchField')) return;
    if(!$('search-form')) return;
    
    var searchResults = new Element('div', { id: 'search-autocomplete', 'class': 'autocomplete' });
    Element.insert( document.body, { bottom: searchResults });
    
    new Ajax.Autocompleter('searchField', searchResults, ReviewPips.Ajax.path + 'search/ajax', {
        paramName:  'q',
        afterUpdateElement: function(text, li) {
            try{
                if(!li.id) return;
                var url = Base64.decode(li.id);
                window.location = url;
                return;
            }catch(ex){}
        }
    });
});

function empty( mixed_var ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Philippe Baumann
    // +      input by: Onno Marsman
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: LH
    // *     example 1: empty(null);
    // *     returns 1: true
    // *     example 2: empty(undefined);
    // *     returns 2: true
    // *     example 3: empty([]);
    // *     returns 3: true
    
    if (mixed_var === "" 
        || mixed_var === 0   
        || mixed_var === "0"
        || mixed_var === null  
        || mixed_var === false
        || mixed_var === undefined    
        || ((typeof mixed_var == 'array' || typeof mixed_var == 'object') && mixed_var.length === 0) ){
        return true;
    }
    
    return false;
}

document.observe('dom:loaded',function(){
    if(!$('sitenotice')) return;
    var resizeNotice = function(){
        var pageSize = getPageSize();
        $('sitenotice').style.width = pageSize[0]+'px';
    }
    Event.observe(window,'resize',resizeNotice);
    resizeNotice();
});
/*reviewpips/user*/
ReviewPips.User = {

    isLoggedIn: function(){
        if($('user-sign-in'))
            return false;
        else
            return true;
    },
    
    checkLogin: function(responseText){
        if(responseText.match('NEED_LOGIN'))
            return true;
        if(responseText.match('BAD_USER_STATUS'))
            return true;
        else
            return false;
    },
    
    requireConfirmation: function() {
        var error = new Element('div', { 'class': 'error' })
            .update('Sorry, you must confirm your email before you can do this. Click the link in the email we sent you. If you would like to resend the confirmation email, please click <a href="#" id="resend-confirm-email">click here</a>.');
        FaceboxP.show(error, { title: 'Confirm Your Email', afterLoad: function(){ 
            var link = FaceboxP.getContent().select('#resend-confirm-email')[0];
            link.observe('click',function(event){
                event.stop();
                FaceboxP.show( ReviewPips.Ajax.path + 'user/resendConfirmation' );
            });
        } });
    }

};
// check for suspended users and the like
document.observe('dom:loaded', function(){
    $$('a.user_confirmemail, input.user_confirmemail').each(function(a){
        a.observe('click', function(event){
            Event.stop(event);
            ReviewPips.User.requireConfirmation();
        });
    });
});
Ajax.Responders.register({
    onComplete: function(aj, tr, json){
        isBadStats = json.bad_status;
        if(tr.responseText.match('BAD_USER_STATUS')){
            if(tr.headerJSON.status == 'inactive')
                FaceboxP.show('<div class="error">Sorry, your account has been suspended.</div>', { title: 'Suspended Account' });
            else
                ReviewPips.User.requireConfirmation();
            return;
        }
    }
});
/*reviewpips/register*/
if(typeof validanguage == 'undefined'){
    try{
        loadExtScript('/js/validanguage.js');
    } catch(ex) {
        throw('validanguage is required for Registration module');
    }
}
if(typeof ReviewPips.Form == 'undefined'){
    try{
        loadExtScript('/js/reviewpips/form.js');
    } catch(ex) {
        throw('ReviewPips.Form is required for Registration module');
    }
}

ReviewPips.Register = Class.create({
    initialize: function(){
        this.form = $('reviewpips_register');
        if(!this.form) throw('ReviewPips Registration form not found.');
        
        this.form.RPform = this;
        
        // get all the fields in the form and create a rowstatus object for it
        this.form.select('input').each(function(field){
            try {
                // does the field have helpful text?
                var helpText = field.getAttribute('title');
                // try to create the rowStatus
                field.rowStatus = new ReviewPips.Form.RowStatus(field, helpText);
            } catch(ex) {
            }
        });
        
        // IE fix to hide captcha empty error
        var captcha = $('recaptcha_response_field');
        if(captcha){
            captcha.rowStatus = new ReviewPips.Form.RowStatus(captcha, 'Prove to us you aren\'t a bot.');
            if(captcha && captcha.rowStatus && captcha.rowStatus.isError() && !captcha.rowStatus.isPopulated())
                captcha.rowStatus.hide();
        }
        
        var toc = this.form.select('input[id="register_toc"]')[0];
        var submitBtn = this.form.select('input[type="submit"]')[0];
        var submitBtnCopy = $$('input.reviewpips_register')[0];
        if(toc && submitBtn){
            submitBtn.disabled = !toc.checked;
            if(submitBtnCopy) submitBtnCopy.disabled = !toc.checked;
            toc.observe('click',function(){ submitBtn.disabled = !toc.checked; if(submitBtnCopy) submitBtnCopy.disabled = !toc.checked; });
        }
        
        var cancel = FaceboxP.getContent().select('.cancel')[0];
        if(cancel){
            cancel.observe('click',function(event){
                Event.stop(event);
                FaceboxP.hide();
            })
        }
        
        // setup validation rules
        validanguage.el.register_nickname = {
            required: true,
            errorMsg: 'Enter a nickname.',
            maxlength: 24,
            minlength: 5,
            regex: {  
                expression: /^([a-zA-Z])[a-zA-Z_-]*[\w_-]*[\S]$|^([a-zA-Z])[0-9_-]*[\S]$|^[a-zA-Z]*[\S]$/,
                errorOnMatch: false,
                errorMsg: 'You can use letters, numbers, or these: . _ -',
                onsubmit: true
            },
            transformations: [
                {
                    name: this.checkNickname,
                    onblur: true
                }
            ],
            onblur: true,
            onsubmit: true
        }
        $('register_nickname').setAttribute('maxlength',24);
        validanguage.el.register_first_name = {
            required: true,
            errorMsg: 'Enter your first name.',
            onblur: true,
            onsubmit: true
        }
        validanguage.el.register_last_name = {
            required: true,
            errorMsg: 'Enter your last name.',
            onblur: true,
            onsubmit: true
        }
        validanguage.el.register_email = {
            required: true,
            errorMsg: 'Please enter a valid email.',
            validations: [
                {
                    name: 'validanguage.validateEmail',
                    errorMsg: 'This isn\'t a valid email.',
                    onblur: true,
                    onsubmit: true
                }
            ],
            transformations: [
                {
                    name: this.checkEmail,
                    onblur: true
                }
            ],
            onblur: true
        }
        validanguage.el.register_password = {
            required: true,
            errorMsg: 'Enter a password.',
            onblur: true,
            onsubmit: true
        }
        validanguage.el.register_confirm_password = {
            required: true,
            errorMsg: $('register_confirm_password').getAttribute('title'),
            validations: [
               {
                  name: function() { return !!(this.value == $('register_password').value); },
                  onblur: true,
                  onsubmit: true,
                  errorMsg: 'This has to match your password'
               }  
            ],
            onblur: true
        }
        validanguage.el.register_toc = {
            required: true,
            errorMsg: 'You have to agree to these conditions to cover our butts.',
            onsubmit: true
        }
        validanguage.el.recaptcha_response_field = {
            required: true,
            errorMsg: 'You must prove you aren\'t a bot.',
            onsubmit: true
        }
        
        // setup validation settings
        validanguage.settings.minlengthErrorMsg = 'This must be at least {!minlength} characters long.';
        validanguage.settings.maxlengthErrorMsg = 'This must be less than {!maxlength} characters long.';
        validanguage.settings.onerror = function(errMsg){
            if(!this.rowStatus) return;
            // if there is an ajaxCheck class, we can't let that error overwrite this, so remove it
            if(this.hasClassName('ajaxCheck')) this.removeClassName('ajaxCheck');
            this.rowStatus.setError(errMsg);
            this.rowStatus.show();
        };
        validanguage.settings.onsuccess = function(){
            if(!this.rowStatus) return;
            if(this.rowStatus.isError()){
                this.rowStatus.hide();
                this.rowStatus.clear();
            }
        };
        
        this.form.observe('submit',function(event){
            var valid = validanguage.validateForm(this.form);
            if(!valid.result){ Event.stop(event); return; };
        }.bindAsEventListener(this));
    },
    ajaxCheck: function(value, url, errorMsg, field, validanguageField){
        var valueBad = function(){
            field.removeClassName('ajaxCheck');
            validanguageField.errorMsg = errorMsg;
            validanguageField.failed = true;
            // delay this because other validations will succeed and overwrite this
            setTimeout(function(){
                field.rowStatus.setError(errorMsg);
                field.rowStatus.show();
            }.bind(this),200);
        }.bind(this);
        
        var valueOk = function(){
            validanguageField.failed = false;
            // only hide if the ajaxcheck class is still there (hasn't been removed by another error)
            if(field.rowStatus.isError() && field.hasClassName('ajaxCheck')){
                field.rowStatus.hide();
                field.rowStatus.clear();
                field.removeClassName('ajaxCheck');
            }
        }.bind(this);
        
        field.addClassName('ajaxCheck');
        new Ajax.Request(url, {
            method: 'post',
            parameters: { checkValue: value },
            onSuccess: function(tr){
                if(tr.responseText.match('TAKEN'))
                    valueBad();
                else
                    valueOk();
            },
            onFailure: function(){
                valueBad();
            }
        });
    },
    checkNickname: function(){
        var nickname = this.value;
        if(empty(nickname)) return false;
        this.form.RPform.ajaxCheck(
            nickname,
            ReviewPips.Ajax.path+'user/checkNickname',
            'Sorry, this nickname is already taken.',
            this,
            validanguage.el.register_nickname
        );
    },
    checkEmail: function(){
        var email = this.value;
        if(empty(email)) return false;
        this.form.RPform.ajaxCheck(
            email,
            ReviewPips.Ajax.path+'user/checkEmail',
            'This email is already in use by another account.',
            this,
            validanguage.el.register_email
        );
    }
});

document.observe('dom:loaded',function(){ if($('reviewpips_register')) new ReviewPips.Register(); });
/*reviewpips/userlogin*/
ReviewPips.UserLogin = {

    showLogin: function(callback) {
        var modalboxopts = {
            title: 'Sign In',
            width: 300,
            params: { showLogin: true },
            afterLoad: function(){
                // rebind login form action
                var loginForm = FaceboxP.getContent().select('form')[0];
                if(loginForm){
                    loginForm.observe('submit',function(event){
                        Event.stop(event);
                        
                        new Ajax.Request( ReviewPips.Ajax.path + 'user/login', {
                            method: 'post',
                            parameters: loginForm.serialize(true),
                            onSuccess: function(tr){
                                if(tr.responseText.match('LOGINOK')){
                                    if(callback){
                                        Modalbox.hide({slideUpDuration: 0.05, transitions:false});
                                        setTimeout(callback,50);
                                        //setTimeout(function(){location.reload(true)}, 1000);
                                    }else
                                        Modalbox.show('<span class="loggedin">You have successfully been logged in.</span>');
                                } else {
                                    Modalbox.show(tr.responseText, modalboxopts);
                                }
                            },
                            onFailure: function(){
                                Modalbox.show('<span class="loggedin">There was an error logging you in. Please wait...</span>');
                                setTimeout(function(){window.location = ReviewPips.Ajax.path + '/user/login';}, 1000);
                            }
                        });
                    });
                }
                var cancel = FaceboxP.getContent().select('.cancel')[0];
                if(cancel){ 
                    cancel.observe('click',function(event){
                        Event.stop(event);
                        FaceboxP.hide();
                    })
                }
                
                // rebind forgotten password link
                var forgotPw = FaceboxP.getContent().select('a.forgotpw')[0];
                if(forgotPw){
                    forgotPw.observe('click',function(event){
                        Event.stop(event);
                        this.showForgotPassword();
                    }.bindAsEventListener(this));
                }
                
               
                // rebind register link
                var register = FaceboxP.getContent().select('a.user_register')[0];
                if(register){
                	 register.observe('click',function(event){
                        Event.stop(event);
                        this.showRegister(function(){
                            Modalbox.show(FaceboxP.FBloading, {title: 'Join ReviewPips.com. Create an Account.', slideDownDuration: 0.5});
                            if(a.href.match('/user/register'))
                                window.location = ReviewPips.Ajax.path + 'my_profile';
                            else
                                window.location = a.href;
                        });
                    }.bindAsEventListener(this));
                }
                
            }.bind(this)
        }
        Modalbox.show( ReviewPips.Ajax.path + 'user/login', modalboxopts );
    },
    
    showForgotPassword: function(callback){
        var modalboxopts = {
            title: 'Forgot Password',
            width: 300,
            afterLoad: function(){
                // rebind the form
                var forgotForm = FaceboxP.getContent().select('form')[0];
                if(forgotForm){
                    forgotForm.observe('submit',function(event){
                        Event.stop(event);
                        
                        Modalbox.show( ReviewPips.Ajax.path + 'user/forgotPassword', {
                            method: 'post',
                            params: forgotForm.serialize(true)
                        });
                    });
                }
                var cancel = FaceboxP.getContent().select('.cancel')[0];
                if(cancel){
                    cancel.observe('click',function(event){
                        Event.stop(event);
                        ReviewPips.UserLogin.showLogin();
                    })
                }
            }
        }
        Modalbox.show( ReviewPips.Ajax.path + 'user/forgotPassword', modalboxopts );
    },
    
    showRegister: function(callback){ 
        var modalboxopts = {
            title: 'Join ReviewPips.com. Create an Account.',
            width: 550,
            afterLoad: function(){
                if($('reviewpips_register')){
                    new ReviewPips.Register();
                    validanguage.populate();
                }
                if($('proof_of_registration')){
                	if(callback) {
                		Modalbox.hide({slideUpDuration: 0.05, transitions:false});
                        setTimeout(callback,50);
                        setTimeout(function(){location.reload(true)}, 1000);                		
                	}
                	else {
	                    setTimeout(function(){
	                        window.location = ReviewPips.Ajax.path + 'my_profile';
	                    },2000);
                	}
                }
               
                // beind the form
                var registerForm = FaceboxP.getContent().select('form')[0];
                if(registerForm){
                    registerForm.observe('submit',function(event){
                        Event.stop(event);
                        
                        var valid = validanguage.validateForm(this.form);
                        if(!valid.result){ return; };
                        
                        FaceboxP.show( ReviewPips.Ajax.path + 'user/register', {
                            method: 'post',
                            params: registerForm.serialize(true),
                            afterLoad: modalboxopts.afterLoad
                        });
                    });
                }
                var cancel = FaceboxP.getContent().select('.cancelReg')[0];
                if(cancel){
                    cancel.observe('click',function(event){ 
                        Event.stop(event);
                        ReviewPips.UserLogin.showLogin();
                    })
                } 
            }
        }
        FaceboxP.show( ReviewPips.Ajax.path + 'user/register', modalboxopts );
    },
    
    isLoggedIn: function(){
        return ReviewPips.User.isLoggedIn();
    },
    
    requireLogin: function(callback){
        return this.showLogin(callback);
    },
    
    bindLinks: function() {
        var self = this;
        $$('a.reqlogin, input.reqlogin').each(function(a){
            a.observe('click',function(event){
                Event.stop(event);
                //var a = Event.element(event); //isn't needed, and won't always return the A tag we need
                self.requireLogin(function(){
                    Modalbox.show(FaceboxP.FBloading, {title: 'Sign In', slideDownDuration: 0.5});
                    if(a.href.match('/user/login')){
                        window.location = ReviewPips.Ajax.path + 'my_profile';
                    }else if(a.type.match('button')){
                    	window.location = ReviewPips.Ajax.path + 'my_profile';
                	}else
                        window.location = a.href;
                });
            });
        });
        $$('a.user_register').each(function(a){
            a.observe('click',function(event){
                Event.stop(event);
                self.showRegister();
            });
        });
    }

};

Ajax.Responders.register({
    onComplete: function(aj, tr, json){
        if(ReviewPips.User.checkLogin(tr.responseText)){
            ReviewPips.UserLogin.requireLogin(function(){
            	aj.options.onComplete = function() { setTimeout(function(){location.reload(true)}, 1000); };
                new Ajax.Request( aj.url, aj.options );
            });
            return;
        }
    }
});

document.observe('dom:loaded',function(){ReviewPips.UserLogin.bindLinks()});

if(typeof ReviewPips.Register == 'undefined'){
    try{
        loadExtScript('/js/reviewpips/register.js');
    } catch(ex) {
        throw('ReviewPips.Register is required for UserLogin module');
    }
}
/*reviewpips/mainmenu*/
ReviewPips.MainMenu = {
    
    init: function(menuID) {
        this.oMenu = $( menuID );
        if(!this.oMenu)
            throw("No such menu with ID of " + menuID);
        
        var baseCats = this.oMenu.select('li.base');
        var self     = this;
        baseCats.each(function(liCat){
            // hide all rows to start with, unless marked as active
            /* actually let's not hide everything by default
            if(!self.rowIsActive(liCat))
                self.hide(liCat);
            */
            self.show(liCat);
            // add the event behavior for clicking on a row
            var a = liCat.select('a');
            if(a[0]) {
                var liParent = liCat;
                a[0].observe('click', function(event){
                    if(self.rowIsHidden(liParent)) {
                        self.show(liParent);
                    } else {
                        self.hide(liParent);
                    }
                    // don't allow the link to go anywhere
                    this.setAttribute('href','javascript:;');
                    Event.stop(event);
                });
                // for all the other links, when clicked, have the parent LI become active
                a.shift(); // remove the first link, it's the parent category title
                a.each(function(s){
                    s.observe('click',function(e){
                        if(s.parentNode.nodeName == 'LI') {
                            a.each(function(s){ if(s.parentNode.nodeName == 'LI') { Element.removeClassName(s.parentNode, 'active'); } });
                            s.parentNode.addClassName('active');
                            if(ReviewPips.Ajax)
                                s.insert( ReviewPips.Ajax.loading() );
                        }
                    });
                });
            }
        });
    },
    
    rowIsActive: function(liCat) {
        return liCat.hasClassName('active');
    },
    
    rowIsHidden: function(liCat) {
        return liCat.hasClassName('hidden');
    },
    
    hide: function(liCat) {
        liCat.removeClassName('active');
        liCat.addClassName('hidden');
    },
    
    show: function(liCat) {
        // hide all
        var self = this;
        //this.oMenu.select('li.base').each(function(s){ self.hide(s); });
        // show one
        liCat.addClassName('active');
        liCat.removeClassName('hidden');
    }
    
}

document.observe('dom:loaded', function(){ ReviewPips.MainMenu.init('nav'); });
/*reviewpips/sidebar*/
ReviewPips.Sidebar = {
    
    SiteStats: {
        
        init: function(statsID) {
            this.stats   = $(statsID);
            this.statsID = statsID;
            this.curStat = null;
            
            if(!this.stats)
                throw("No such element with ID "+statsID+" for sidebar stats");
            
            this.statLinks = this.stats.select('.rp_menu li a');
            var self  = this;
            this.statLinks.each(function(a){
                // don't allow the link to go anywhere
                a.setAttribute('href','javascript:;');
                // is this the current stat?
                if( Element.hasClassName(a.parentNode,'active') )
                    self.curStat = $( a.getAttribute('rel') );
                // bind event on click
                a.observe('click', function(event){
                    try{a.blur();}catch(ex){}
                    Event.stop(event);
                    self.hideStat( self.curStat );
                    self.showStat( a.getAttribute('rel') );
                });
            });
        },
        
        showStat: function(relID) {
            this.statLinks.each(function(a){
                var rel = a.getAttribute('rel');
                if(rel == relID)
                    a.parentNode.addClassName('active');
                else
                    a.parentNode.removeClassName('active');
            });
            
            $(relID).show();
            
            this.curStat = $(relID);
        },
        
        hideStat: function(relID) {
            $(relID).hide();
            this.curStat = null;
        }
        
    },
    
    UserStats: Class.create({
        
        initialize: function(statsID) {
            this.stats   = $(statsID);
            this.statsID = statsID;
            this.curStat = null;
            
            if(!this.stats)
                throw("No such element with ID "+statsID+" for sidebar user stats");
                
            // what nickname is this sidebar for?
            this.nickname = this.stats.select('[name="nickname"]')[0].value;
            
            // initialize the menu for AJAX calls
            var menu = this.stats.select('.rp_menu')[0];
            if(menu) this.initMenu( menu );
            
            // animate the reviewer-o-meter
            var img = this.stats.select('.user_score_graph .graph div img')[0];
            var endWidth = img.width;
            // reset image width
            img.width = 0;
            // animate to the original width
            img.morph('width:'+endWidth+'px;', { duration: 1 });
        },
        
        initMenu: function(menuElem) {
            this.menu = menuElem;
            // bind all the links
            this.menu.select('li a').each(function(a){
                a.observe('click',function(event){
                    // don't follow the link
                    Event.stop(event);
                    // make an AJAX call instead
                    var stats = a.parentNode.id.split('_')[1];
                    var nickname = this.nickname;
                    
                    new Ajax.Request( ReviewPips.Ajax.path + 'user/ajaxStats', {
                        method: 'get',
                        parameters: { nickname: nickname, stats_range: stats },
                        onSuccess: function(tr){
                            // replace the stats container with the result
                            var container = this.stats.parentNode;
                            // remove old stats
                            this.stats.remove();
                            // insert new stats
                            Element.insert(container, tr.responseText);
                            // init the new data
                            new ReviewPips.Sidebar.UserStats( this.statsID );
                        }.bind(this),
                        onFailure: function(tr){
                        }.bind(this)
                    });
                }.bindAsEventListener(this));
            }.bind(this));
        }
        
    })
    
}

// hack for IE: using window onload instead of dom:ready
Event.observe(window,'load', function(){ try { ReviewPips.Sidebar.SiteStats.init('sidebar_sitestats'); } catch(ex) { } });

document.observe('dom:loaded', function(){ try { new ReviewPips.Sidebar.UserStats('sidebar_userstats'); } catch(ex) { } });

