/*
    :: generic.js - OO and generic utilities for JS. (James Kassemi / Chris Gerber [Ideum])
*/

if(!window.console){
    if(!console || !console.error){
        var console = {};
        console.log = function(msg){};
        console.error = function(msg){ alert("console error: \n\n " + msg); };
        console.warning = function(){};
        console.trace = function(){};
    }
}
var SAFARI = false;
var IE = false;

var lc = navigator.appVersion.toLowerCase();
if(lc.indexOf("safari") != -1)
    SAFARI = true;
else if(lc.indexOf("msie") != -1)
    IE = true;

/* Unsupported browser detection. */

var BROWSER_PASS = true;
var BROWSERS_DISALLOWED = {
    msie: [0, 5.9999],
    safari: [0, 399],
    opera: [0, 8.0],
    firefox: [0, 0.9]
};

function rejectBrowsers(which){
    which = which || BROWSERS_DISALLOWED;

    for(var k in which){
        if(typeof(which[k]) != 'function' &&
            which[k].length &&
            which[k].length > 0){
            if(navigator.userAgent.toLowerCase().indexOf(k.toLowerCase()) != -1 ||
                navigator.appVersion.toLowerCase().indexOf(k.toLowerCase()) != -1) {
                var version = parseFloat(navigator.userAgent.substring(
                    navigator.userAgent.toLowerCase().indexOf(k.toLowerCase()) + k.length + 1));
                if(version > which[k][0] &&
                    version < which[k][1]){
                    BROWSER_PASS = false;
                    break;
                }
            }
        }
    }

    return BROWSER_PASS;
}

Object.prototype.update = function(n){
    for(var k in n){
        if(this[k])
            this["_" + k] = this[k];
        this[k] = n[k];
    }

    return this;
}

Object.prototype.clone = function(d){
  var c = new this.constructor();
  for (var k in this)
    if(!d)
      c[k] = this[k];
    else if (typeof this[k] == 'object')
      c[k] = this[k].clone(true);
    else
      c[k] = this[k];
  return c;
}

var BlankFunction = function(){};
var Class = function(){};
var ClassCounter = 1;
var ObjectCounter = 1;
var ObjectDir = [null];

var getInstance = function(id){
    return ObjectDir[id];
}; var getObj = getInstance;

Class.create = function(){
    ClassCounter++;
    var cls_struct = function(){
        this.__id__ = ObjectCounter;

        ObjectCounter++;
        ObjectDir.push(this);

        if(args[0] !== Class && this.initialize)
            this.initialize.apply(this, arguments);
    }

    var defaults = {
        __class_id__: ClassCounter
    }

    var args = [cls_struct];
    for(var idx=0; idx < arguments.length; idx++)
        args.push(arguments[idx]);

    args.push(defaults);

    return Class.do_extend.apply(this, args);
}

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

Class.do_extend = function(){
    var args = new Array();

    var cls_super;
    var cls_struct = arguments[0];
    var cls_proto = arguments[0].prototype;

    for(var idx=1; idx < arguments.length; idx++)
        args.push(arguments[idx]);

    args.push(this.prototype);

    var do_inherit = function(to, from, from_idx){
        if(!to) return;
        for(var ei=from_idx;ei<from.length;ei++)
            for(var n in from[ei]) to[n] = from[ei][n];
    }

    var extensions = function(to){
        to.create = this.create;
        to.super_class = this.prototype;
    }

    do_inherit(cls_proto, args, 0);
    do_inherit(cls_proto, this.prototype, 0);

    cls_struct.prototype = cls_proto;

    /* Extend the current class with another. */
    cls_struct.subclass = function(new_mthds){
        var me = this.prototype;
        if(new_mthds.__id__)
            return Class.create(me, new_mthds.prototype);
        else
            return Class.create(me, new_mthds);
    }

    /* Mix methods from new classes with ours. */
    cls_struct.mixin = function(){
        for(var idx=0;idx<arguments.length;idx++){
            var methods = arguments[idx];
            if(arguments[idx].prototype) methods = arguments[idx].prototype;
            for(var k in methods)
                this.prototype[k] = methods[k];
        }

    }

    extensions.call(this, cls_struct);

    return cls_struct;
};

/* Event handling. 
    requires: generic.js
    requires: array.js for element.each()
*/

/* Array            ************************************************************************/

Array.prototype.update({
    is_array: true,

    each: function(f){
        for(var i=0;i<this.length;i++){
            f(this[i], i);
        }
    },

	compact: function(v){
		var a = [];
		for(var i=0;i<this.length;i++){
			if(this[i] != v)
				a.push(this[i]);
		}

		return a;
	},

    /* From moo-tools */
	extend: function(array){
		for (var i = 0, j = array.length; i < j; i++) this.push(array[i]);
		return this;
	},


    collect: function(f){
    /* Was map. Applies function 'f' to each item, and
        returns an array with the results. */
        var _a = [];
        for(var i=0;i<this.length;i++){
            _a.push(f(this[i], i));
        }
        return _a;
    },

    saturate: function(f){
        return(this.collect(f));
    },

    filter: function(f){
    /* Apply function f, if it returns true, keep
       value as part of results array. Otherwise, throw away. */
        var _a = [];
        for(var i=0;i<this.length;i++){
            if(f(this[i], i))
                _a.push(this[i]);
        }
        return _a;
    },

    pry: function(f){
    /* Applies function 'f' to each item. If the
        return value is specified, exit and return the value. */
        var v;
        for(var i=0;i<this.length;i++){
            v = f(this[i], i);
            if(v) return v;
        }

        return null;
    },

    every: function(f){
        for(var i=0;i<this.length;i++){
            if(!f(this[i], i)) return false;
        }

        return true;
    },

    /* Is the item in the array? */
    includes: function(v){
        for(var i=0;i<this.length;i++){
            if(this[i] == v)
                return true;
        }

        return false;
    },

    /* If the array does not contain the item, append it,
        otherwise, do nothing. Returns the array. */
    include: function(item){
        if (!this.includes(item)) this.push(item);
        return this;
    },

    /* Includes with custom match function */
    contains: function(value, match){
        match = match || function(v1, v2){ v1 == v2 ? true : false; }

        for(var i=0;i<this.length;i++){
            if(match(this[i], value))
                return true;
        }
        return false;
    },

    inject: function(val, func){
        for(var i=0;i<this.length;i++){
            val = func(val, this[i]);
        }

        return val;
    },

    index: function(idx){
        return this[idx];
    }

});

function $A(a){
    _a = new Array();
    for(var i=0;i<a.length;i++){ _a.push(a[i]); }
    return _a;
}

var __events = {};
var __events_tracker = {};
var __events_counter = 0;

listenGroup = Class.create({
    initialize: function(){
        this.members = [];
        for(var i=0;i<arguments.length;i++){
            if(!arguments[i].__listengroups__)
                arguments[i].__listengroups__ = [];

            arguments[i].__listengroups__.push(this);
            this.members.push(arguments[i]);
        }

    }
});

function trigger(element, event_name, event_obj){
    var success = true;

    if(!element.__id__)
        return;

    var args = [];
    for(var i=2;i<arguments.length;i++)
        args.push(arguments[i]);

    if(__events_tracker[element.__id__] && __events_tracker[element.__id__][event_name]){
        var events = __events_tracker[element.__id__][event_name];
        for(var i=0;i<events.length;i++){
            if(typeof(events[i][2]) == 'function'){
                if(!events[i][2](event_name, args, event_obj)){
                    success = false;
                };
            }
        }

        if(element == window && event_name == 'load'){
            __events_tracker[element.__id__][event_name].each(function(v){
                ignore(v[4]);
            });
        }
    }

    return success;

};

var _ListenObjContainer = Class.create();
var fired = null;
var interval_test;

function listen(elements, event_name, observer, scope){
    if(!elements.is_array)
        elements = [elements];

    elements.each(function(element){
        if(event_name == 'domready'){
            /* This was inspired by the mootools version... */
            listen(_ListenObjContainer, "trigger_ondomready", observer, scope);

            var fire = function(){
                try{ clear_interval(interval_test); }catch(e){}
                if(!fired){
                    fired = true;
                    trigger(_ListenObjContainer, "trigger_ondomready");
                }
            }

            if(document.readyState && window.webkit){
                interval_test = setInterval(30, function(){
                    if(document.readyState == 'loaded' || document.readyState == 'complete') fire();
                });
            }else if(document.readyState && IE){
                if (!$('ie_ready')){
                    var src = (window.location.protocol == 'https:') ? '://0' : 'javascript:void(0)';
                    document.write('<script id="ie_ready" defer src="' + src + '"><\/script>');
                    $('ie_ready').onreadystatechange = function(){
                        if (this.readyState == 'complete') fire();
                    }
                }
            }else{
                listen(document, "DOMContentLoaded", fire);
                listen(window, "load", fire);
            }

        }else{
            if (event_name == 'keypress' &&
                (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
                || element.attachEvent))
              event_name = 'keydown';

            if(scope == undefined || scope == null)
                scope = element;

            if(scope){
                var ob = function(e, args){ var args = [e].concat(args); return observer.apply(scope, args); }
            }else{
                var ob = observer;
            }

            __events_counter++;
            ob.event_hndl = __events_counter;

            var eventObj = [element, event_name, ob, observer, __events_counter];
            eventObj.event_hndl = __events_counter;
            __events[__events_counter] = eventObj;

            if(!element.__id__){
                element.__id__ = ObjectCounter;
                ObjectDir.push(element);
                ObjectCounter++;
            }

            if(!__events_tracker[element.__id__])
                __events_tracker[element.__id__] = {};

            if(!__events_tracker[element.__id__][event_name]){
                __events_tracker[element.__id__][event_name] = [eventObj];

                var action_call = function(e){
                    var r = trigger(element, event_name, e);
                }

                if(element.addEventListener){
                    element.addEventListener(event_name, action_call, false);

                }else if(element.attachEvent){
                    element.attachEvent('on' + event_name, action_call);
                }
            }else{
                __events_tracker[element.__id__][event_name].push(eventObj);
            }
        }
    });

    if(elements.length == 1)
        return __events_counter;
    else
        return [__events_counter - elements.length, elements.length];

}

function ignore(hndl){
    if(hndl.length == 2){
        for(var i=0;i<hndl[1];i++){
            ignore(i + hndl);
        }

    }else{
        var eventObj = __events[hndl];
        var element = eventObj[0];
        var event_name = eventObj[1];

        __events_tracker[element.__id__][event_name] = __events_tracker[element.__id__][event_name].filter(function(v){
            return(v[4] != hndl);
        });

        if(element.removeEventListener){
            element.removeEventListener(eventObj[1], eventObj[3], false);

        }else if(element.detachEvent){
            var b = eventObj[1] + eventObj[3];
            element.detachEvent('on' + eventObj[1]);
            element[b] = null;
        }else{
            console.error("No way to detach events!");
        }

        delete __events[hndl];
    }
}

function cleanup(){
    while(__events.length > 0){
        var focus = __events[0];
        ignore(focus[0], focus[1], focus[2], focus[3]);
    }
}
/* Element          ************************************************************************/

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

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

Element.__extend = function(element) {
  if (!element) return;
  if (_nativeExtensions) return element;

  if (!element._extended && element.tagName && element != window) {
    if((IE && element.nodeType == 1) || !IE){
        var methods = Element.Methods, cache = Element.__extend.cache;
        for (property in methods) {
          var value = methods[property];
          if (typeof value == 'function')
		try{
            element[property] = cache.findOrStore(value);
		}catch(e){}
        }
    }
  }

  if((IE && element.nodeType == 1) || !IE)
      element['_extended'] = true;

  return element;
}

var $E = Element.__extend;

Element.__extend.cache = {
  findOrStore: function(value) {
    return this[value] = this[value] || function() {
      var a = [this];
      for(var i=0;i<arguments.length;i++){ a.push(arguments[i]); }
      return value.apply(null, a);
    }
  }
}

Element.Styles = {'border': [], 'padding': [], 'margin': []};

$A(['Top', 'Right', 'Bottom', 'Left']).each(function(direction){
    for(var s in Element.Styles){
        if(typeof Element.Styles[s] != 'function')
            Element.Styles[s].push(s + direction);
    }
});


Element.borderShort = ['borderWidth', 'borderStyle', 'borderColor'];

var _GROUPS = {};
Element.Methods = {
    getValue: function(element){
        switch(element.tagName.toLowerCase()){
            case 'input':
            case 'select':
                switch(element.type.toLowerCase()){
                    case 'checkbox':
                        return element.checked;
                    case 'text':
                    case 'password':
                        return element.value;
                }
                return element.value;
            case 'textarea':
                return(element.value || element.innerHTML);

        }
    },

    /* for MSIE browsers only atm...I'm using this for advanced positioning via get parent border width...
    getStyle: function(element, style) {
        if(element.currentStyle)
            return element.currentStyle[style];
        else if (window.getComputedStyle)
            return document.defaultView.getComputedStyle(element, null).getPropertyValue(style);
    },*/

	getStyle: function(element, property){
		property = property.camelCase();
		var result = element.style[property];
		if (!$chk(result)){
			if (property == 'opacity') return element.$tmp.opacity;
			result = [];
			for (var style in Element.Styles){
				if (property == style){
					Element.Styles[style].each(function(s){
						var style = element.getStyle(s);
						result.push(parseInt(style) ? style : '0px');
					}, element);
					if (property == 'border'){
						var every = result.every(function(bit){
							return (bit == result[0]);
						});
						return (every) ? result[0] : false;
					}
					return result.join(' ');
				}
			}
			if (property.contains('border')){
				if (Element.Styles.border.contains(property)){
					return ['Width', 'Style', 'Color'].map(function(p){
						return element.getStyle(property + p);
					}, element).join(' ');
				} else if (Element.borderShort.contains(property)){
					return ['Top', 'Right', 'Bottom', 'Left'].map(function(p){
						return element.getStyle('border' + p + property.replace('border', ''));
					}, element).join(' ');
				}
			}
			if (document.defaultView) result = document.defaultView.getComputedStyle(element, null).getPropertyValue(property.hyphenate());
			else if (element.currentStyle) result = element.currentStyle[property];
		}
		if (window.ie) result = Element.fixStyle(property, result, element);
		if (result && property.test(/color/i) && result.contains('rgb')){
			return result.split('rgb').splice(1,4).map(function(color){
				return color.rgbToHex();
			}).join(' ');
		}
		return result;
	},

    getBorderAdjusts: function(element, style) {
        if (!IE) {
            return(0);
        } else {
            var b = 0; var s = '';
            do {
                s = element.getStyle(style);
                s = parseInt(s.replace(/\D/g, ''));
                if (s) b += s;
                element = Element.__extend(element.parentNode);
            } while(element.parentNode.nodeType == 1);
            return b;
        }
    },

    prependChild: function(element, child){
        if(element.childNodes.length > 0){
            return(element.insertBefore(child, element.childNodes[0]));
        }else{
            return(element.appendChild(child));
        }
    },

    toggle: function(element){
        if(element.visible()){
            for(var i=1;i<arguments.length;i++) {
                $(arguments[i]).show();
            }

            element.hide();

        }else{
            for( var i=1;i<arguments.length;i++)
                $(arguments[i]).hide();

            element.show();
        }
    },

    /* Like toggle, but takes an argument with the alternative text for
        the second argument, the element with which to toggle the text */
    flip: function(element, text, target, target_avec){
        try{ target = $E(target); }catch(e){}

        if(element.getAttribute('old_text')){
            target.innerHTML = element.getAttribute('old_text');
            element.removeAttribute('old_text');
            target.show(target_avec);
        }else{
            element.setAttribute('old_text', target.innerHTML);
            if(!text) target.hide();
            target.innerHTML = text; 
        }

        if(element.visible()){
            element.hide();
        }else{
            element.show();
        }
    },

    /* same as trip, works only with className of the element and replaces class_a with b, and class_b with a dependant upon the match */
    css_trip: function(element, class_a, class_b) {
        var regxp = "";
        var classes = $A(element.className.split(" "));
        if(classes.includes("on")){
            classes = classes.filter(function(v){
                if(v == "on") return false; return true;
            });

            classes.push("off");
        }else{
            classes = classes.filter(function(v){
                if(v == "off") return false; return true;
            });

            classes.push("on");
        }

        element.className = classes.join(" ");
    },

    /* Gets the proper top position in IE. 
    So now we work in IE6||7/Firefox/Opera */
    top: function(element){
        if(IE){
            var top = 0; 

            do{
                top = element.offsetTop + top;
                element = element.offsetParent;

            }while(element.offsetParent);

            return(top);

        }else{
            return(element.offsetTop);
        }
    },

    /* Gets the proper left position in IE. 
    So now we work in IE6||7/Firefox/Opera */
    left: function(element){
        if(IE){
            var left = 0;

            do {
                left = element.offsetLeft + left;
                element = element.offsetParent;

            }while(element.offsetParent);

            return(left);

        }else{
            return(element.offsetLeft);
        }
    },

    /* Add member to a group. This is currently an
    _exclusive_ group that only performs actions on show and
    hide... If you show an element in the group, all the other
    elements in the group will be hidden. */
    group: function(element, group){
        if(!element._groups)
            element._groups = [];

        element._groups.push(group);

        if(!_GROUPS[group])
            _GROUPS[group] = [];

        if(!_GROUPS[group].contains(element))
            _GROUPS[group].push(element);
    },

    /* Hide element. */
    hide: function(element){
        element.style.display = 'none';
    },

	off: function(element){
		element._href = element.getAttribute("href");
		element.removeAttribute("href");
	},

	on: function(element){
		element.setAttribute("href", element._href);
	},

    /* Show element. */
    show: function(element, avec){
        avec = avec || 'block';
        if(element.style.display == avec)
            return;

        if(element._groups){
            for(var i=0;i<element._groups.length;i++){
                var group = _GROUPS[element._groups[i]];
                for(var j=0;j<group.length;j++){
                    group[j].hide();
                }
            }
        }

        element.style.display = avec;
    },

    /* Aligns 'element' with 'target' based on following arguments:

        // Moves element1's top left to element2's top left.
        element1.move_to(element2, 'top', 'left');

        // Moves element1's top left to element2's bottom left.
        element1.move_to(element2, 'bottom', 'left');

        // Moves element1's top left to the center of element2
        element1.move_to(element2, 'middle', 'center');

      I JUST learned about Flash's reference point stuff... We should
      do something like that with this:

        // Move center of each element over each other.
        element1.set_reference_point('middle', 'center');
        element1.move_to(element2, 'middle', 'center'); 
        
        // Moves element1's top right to element2's bottom left.
        element1.move_to(element2, 'bottom', 'left', 'top', 'right');
        */
    move_to: function(element, target, y, x, my_y, my_x){
        my_y = my_y || 'top'; my_x = my_x || 'left';

        var _aligns = {
            // Y
            bottom: function(e){ return(e.top() + e.offsetHeight); },
            top: function(e){ return(e.top()); },
            middle: function(e){ return(e.top() + (e.offsetHeight / 2)); },

            // X
            left: function(e){ return(e.left()); },
            center: function(e){ return(e.left() + (e.offsetWidth / 2)); },
            right: function(e){ return(e.left() + e.offsetWidth); }
        };

        var _adjusts = {
            bottom: function(e){ return(e.offsetHeight); },
            top: function(e){ return(0); },
            middle: function(e){ return(e.offsetHeight / 2); },
            left: function(e){ return(0); },
            center: function(e){ return(e.offsetWidth / 2); },
            right: function(e){ return(e.offsetWidth); }
        };

        target = Element.__extend(target);

        element.parentNode.removeChild(element);
        document.getElementsByTagName('BODY')[0].appendChild(element);

        element.style.position = 'absolute';
        element.style.left = (_aligns[x](target) - _adjusts[my_x](element)) + 'px';
        element.style.top = (_aligns[y](target) - _adjusts[my_y](element)) + 'px';
    },

    // TODO: Merge this somehow with above.
    move_to_nobreak: function(element, target, y, x, my_y, my_x){
        my_y = my_y || 'top'; my_x = my_x || 'left';

        var _aligns = {
            // Y
            bottom: function(e){ return(e.top() + e.offsetHeight); },
            top: function(e){ return(e.top()); },
            middle: function(e){ return(e.top() + (e.offsetHeight / 2)); },

            // X
            left: function(e){ return(e.left()); },
            center: function(e){ return(e.left() + (e.offsetWidth / 2)); },
            right: function(e){ return(e.left() + e.offsetWidth); }
        };

        var _adjusts = {
            bottom: function(e){ return(e.offsetHeight); },
            top: function(e) { return e.getBorderAdjusts('borderTopWidth') * -1; },
            middle: function(e){ return(e.offsetHeight / 2); },
            left: function(e) { return e.getBorderAdjusts('borderLeftWidth') * -1; },
            center: function(e){ return(e.offsetWidth / 2); },
            right: function(e){ return(e.offsetWidth); }
        };

        target = Element.__extend(target);
        element.style.position = 'absolute';
        element.style.left = (_aligns[x](target) - _adjusts[my_x](element)) + 'px';
        element.style.top = (_aligns[y](target) - _adjusts[my_y](element)) + 'px';

    },

    width: function(element){ return(element.offsetWidth); },
    height: function(element){ return(element.offsetHeight); },

    getFirstChildById: function(element, the_id){
       var idx, focus;
       for(idx=0;idx<element.childNodes.length;idx++){
           if(IE)
               focus = Element.__extend(element.childNodes[idx]);
           else
               focus = element.childNodes[idx];

           if(focus.nodeType == 1){
               if(focus.id.match(the_id)){
                   return focus;
               }else{
                   var rec = focus.getFirstChildById(the_id);
                   if(rec != false)
                       return rec;
               }
           }
       }

       return false;
    },

	visualEffect: function(element, effect_name){
		var effect = new Fx.Color(element.id, 'color', { duration: 500 } );
		effect.custom("000000", "ffffff");
	},

	fade_in: function(element){
		var effect = new Fx.Opacity(element, { duration: 500 } );
		effect.opacity_in();
	},

	fade_out: function(element){
		var effect = new Fx.Opacity(element, { duration: 500 } );
		effect.opacity_out();
	},

    getChildrenById: function(element, the_id){
        var idx = null;
        var focus = null;
        var ret = new Array();
        for(idx=0;idx<element.childNodes.length;idx++){
            if(IE)
                focus = Element.__extend(element.childNodes[idx]);
            else
                focus = element.childNodes[idx];

            if(focus.nodeType == 1){
                if(focus.id.match(the_id)){
                    ret.push(focus);
                }else{
                    var rec = focus.getChildrenById(the_id);
                    if(rec != false) {
                        for ( var jdx = 0; jdx < rec.length; jdx++ ) {
                            ret.push(rec[jdx]);
                        }
                    }
                }

            }
        }

        return ret.length == 0 ? false : ret ;
    },

	update: function(element, html) {
		html = typeof html == 'undefined' ? '' : html.toString();
		element.innerHTML = html.stripScripts();
		setTimeout(function() {html.evalScripts()}, 10);
		return element;
	},

    traverse: function(element, f){
        var node;
        for(var i=0;i<element.childNodes.length;i++){
            node = $E(element.childNodes[i]);
            f(node);
            if(node.nodeType == 1)
                node.traverse(f);
        };
    },

    getChildElementsByTagName: function(element, tagname){
        var matches = [];
        tagname = tagname.toUpperCase();
        element.traverse(function(node){
            if(node.tagName == tagname)
                matches.push($E(node));
        });

        return matches;
    },

    getStyle: function(element, style){
        /* Be sure to pass the style as the css value. We'll camelize it. */
        if(element.currentStyle)
            return element.currentStyle[style.camelCase()];
        else if(window.getComputedStyle)
            return document.defaultView.getComputedStyle(element, null).getPropertyValue(style);
        else
            return undefined;

    },

    visible: function(element){
        var d = element.style.display;
        if(element.style.display == 'none'){
            return false;
        }else{
            return true;
        }
    },

    setLoading: function(element){
        if(!document._loading_element){
            var l = Element.__extend(document.createElement("div"));
            l.innerHTML = loadingText;

            document._loading_element = l;  
            document._loading_element.style.position = 'absolute';
            document._loading_element.style.zIndex = '30000';
            document.documentElement.appendChild(document._loading_element);
        }

        document._loading_element.show();

        var offsetLeft = (element.width() - document._loading_element.width()) / 2;
        var offsetTop = (element.height() - document._loading_element.height()) / 2;

        document._loading_element.style.left = '0px';
        document._loading_element.style.top = '0px';
        document._loading_element.style.left = element.left() + offsetLeft + 'px';
        document._loading_element.style.top = element.top() + offsetTop + 'px';

        
    },

    unsetLoading: function(element){
        setTimeout("document._loading_element.hide();", 700);
    }
};

var loadingText = "\n    <div class=\"loading\"><img src=\"<%= BASE_PATH %>/images/spinner.gif\"> Please wait...</div>\n";


Element.__extend(Element.Methods);

var _nativeExtensions = false;

if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
  var HTMLElement = {}
  HTMLElement.prototype = document.createElement('div').__proto__;
}

Element.addMethods = function(methods) {
  if(methods)
	  Object.__extend(Element.Methods, methods);

  // Non-IE
  if(typeof HTMLElement != 'undefined') {
    var methods = Element.Methods, cache = Element.__extend.cache;
    for (property in methods) {
	  if(property == 'update')
		  console.log(methods[property] + "");

      var value = methods[property];
      if (typeof value == 'function')
        HTMLElement.prototype[property] = cache.findOrStore(value);
    }
    _nativeExtensions = true;
  }
}

Element.addMethods();

listen(window, "load", function(){
    try{
        document.bodyElement = document.getElementsByTagName("body")[0];
    }catch(e){}
});


function $exists(id){
    return(document.getElementById(id));
}

function $(id){
    var t = document.getElementById(id);

    /*if(!t){
        console.error("No such element: " + id);
        return false;
    }*/

    return Element.__extend(t);
}

if(IE){
    var oldgetElementsByTagName = document.getElementsByTagName;
    document.getElementsByTagName = function(tag){
        var es = oldgetElementsByTagName(tag); var nes = [];
        for(var i=0;i<es.length;i++){ nes.push(Element.__extend(es[i])); }
        return nes;
    };
}

function $T(id, gid, gid_on, gid_off){
    var f = $(id);
    if(f.style.display == 'none'){
        f.style.display = 'block';
        $(gid).innerHTML = gid_on;

    }else{
        f.style.display = 'none';
        $(gid).innerHTML = gid_off;
    }
}

function update_set(dest, n){
    for(var k in n){
        try{
            if(k.indexOf('$') == 0){
                ky = k.substr(1);
                if(dest[ky] == undefined)
                    dest[ky] = new Hash();
                update_set(dest[ky], n[k]);
            }else{
                dest[k] = n[k];
            }
        }catch(e){}
    }
}

function Attempt(){
    for(var i=0;i<arguments.length;i++){
        try{
            return arguments[i]();
        }catch(e){}
    }
}

function DoAll(){
    var focus;
    for(var i=0;i<arguments.length;i++){
        if(arguments[i] instanceof String){
            focus = eval(arguments[i]);
        }else{
            focus = arguments[i];
        }

        try{ focus(); }catch(e){}
    }
}

Function.prototype.bind = function() {
  var __method = this, object = arguments[0];
  var args = new Array();
  for(var i=1;i<arguments.length;i++)
    args.push(arguments[i]);

  return function() {
    return __method.apply(object, args);
  }
}

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

function epoch(){
    var date = new Date();
    return(Math.floor(date.getTime() / 1000));
}
/* 
    :: overlay.js (jamesk@ideum.com 2007)
    Control for creating an overlay over the screen.
*/

function getPageSize(){
/* 

    :: page size utilities originally from - (http://www.huddletogether.com)

ripped from

Lightbox JS: Fullsize Image Overlays 
by Lokesh Dhakar - http://www.huddletogether.com */

    var xScroll, yScroll;

    if (window.innerHeight && window.scrollMaxY) {  
        xScroll = document.body.scrollWidth;
        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
        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 = windowWidth;
    } else {
        pageWidth = xScroll;
    }


    return({
        page: {
            width: pageWidth,
            height: pageHeight
        },

        window: {
            width: windowWidth,
            height: windowHeight
        }
    });
}

function getPageScroll(){
    var yScroll;

    if (self.pageYOffset) {
        yScroll = self.pageYOffset;
    } else if (document.documentElement && document.documentElement.scrollTop){  // Explorer 6 Strict
        yScroll = document.documentElement.scrollTop;
    } else if (document.body) {// all other Explorers
        yScroll = document.body.scrollTop;
    }

    return yScroll;
}

/* Ajax Utilities

    Based heavily on prototype.js

    We'll be working our own roll more into this shortly... For now though,
    this has everything that we need.
    */


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

  activeRequestCount: 0
}

Ajax.Base = function() {};
Ajax.Base.prototype = {}

Ajax.Request = Class.create({
	  setOptions: function(options) {
		this.options = {
		  method:       'post',
		  asynchronous: true,
		  contentType:  'application/x-www-form-urlencoded',
		  encoding:     'UTF-8',
		  parameters:   ''
		}
		Object.extend(this.options, options || {});

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

    Events: ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'],

    _transport: function() {
      return Attempt(
          function() {return new XMLHttpRequest()},
          function() {return new ActiveXObject('Msxml2.XMLHTTP')},
          function() {return new ActiveXObject('Microsoft.XMLHTTP')}
      );
    },

    initialize: function(url, options) {
        this.transport = this._transport();
        this.options = {
          method:       'post',
          asynchronous: true,
          contentType:  'application/x-www-form-urlencoded',
          parameters:   '',
		  encoding: 	'UTF-8'
        }

        this.options.update(options);
        this.request(url);
    },

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

        this.url = url.replace(/\ |\n/g, '');

        if (this.options.method == 'get' && parameters.length > 0)
            this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;

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

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

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

        this.setRequestHeaders();

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

        if(!this.called && !this.options.asynchronous){
            this.onStateChange();
        }

    },

    setRequestHeaders: function() {
        var requestHeaders =
            ['X-Requested-With', 'XMLHttpRequest',
                'Accept', 'text/javascript, text/html, application/xml, text/xml, */*'];

        if (this.options.method == 'post') {
            requestHeaders.push('Content-type', this.options.contentType);

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

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

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

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

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

    respondToReadyState: function(readyState) {
        var event = this.Events[readyState];
        var transport = this.transport;
        if (event == 'Complete') {
            (this.options['on' + this.transport.status] || function(){})(transport, this);
            if(this.transport.status != 200 && this.transport.status != 302){
                try{
                    this.options['fail'](transport, this);
                }catch(e){}
            }else{
				var mdiv = document.createElement("div");
				mdiv.innerHTML = this.transport.responseText;
				$A($E(mdiv).getChildElementsByTagName("script")).each(function(v){
					console.log(v.innerHTML);
					//eval(v.innerHTML);
				});

				//if(this.options.evalScripts)
				//		eval(this.transport.responseText);

                if(this.options.onSuccess)
                    this.options.onSuccess(transport, this);
            }
        }

        try {
            (this.options['on' + event] || function(){})(transport, this);
        } catch (e) {
            console.error(e);
        }

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

Ajax.Updater = Class.create();

Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
  initialize: function(container, url, options) {
	this.update_on = $(container);

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

    var onComplete = this.options.onComplete || BlankFunction;
    this.options.onComplete = (function(transport, param) {
      this.updateContent();
      onComplete(transport, param);
    }).bind(this);

    this.request(url);
  },

  updateContent: function() {
	this.update_on.innerHTML = this.transport.responseText;

	/*
    var receiver = this.container[this.success() ? 'success' : 'failure'];
    var response = this.transport.responseText;

	
    if (!this.options.evalScripts) response = response.stripScripts();
	*/
	/*
    if (receiver = $(receiver)) {
      if (this.options.insertion)
        new this.options.insertion(receiver, response);
      else
        receiver.update(response);
    }

    if (this.success()) {
      if (this.onComplete)
        setTimeout(this.onComplete.bind(this), 10);
    }
	  */
  }
});

var BACKGROUND = false;
var OVERLAY_DISPLAYED = false;

function overlay_from_div(div_id, width, height, callback){
    if(OVERLAY_DISPLAYED) return false;

    overlay_from_html($(div_id).innerHTML, width, height, callback);

}

function overlay_from_url(url, width, height, callback){
    if(OVERLAY_DISPLAYED) return false;

    new Ajax.Request(url,
        { onComplete: function(ro){
            overlay_from_html(ro.responseText, width, height);
        }
    });
}


function overlay_from_html(content, width, height, callback){
    if(OVERLAY_DISPLAYED) return false;
    OVERLAY_DISPLAYED = true;
    generate_background();

    var newOverlay = new Overlay(content, width, height, callback);
    newOverlay.show();

}

function generate_background(){
    if(BACKGROUND) return false;

    BACKGROUND = document.createElement('div')
    BACKGROUND.className = "background_overlay";
    var ps = getPageSize();
    BACKGROUND.style.height = ps.page.height + 'px';
    BACKGROUND.style.width = ps.page.width + 'px';
    BACKGROUND.style.position = "absolute";
    BACKGROUND.style.top = "0px";
    BACKGROUND.style.left = "0px";
    BACKGROUND.style.zIndex = 300;

    document.bodyElement.appendChild(BACKGROUND);
}

var Overlay = Class.create({
    initialize: function(content, width, height, callback){
        this.rendered = false;
        this.content = content;
        this.width = width;
        this.height = height;
        this.callback = callback;
    },

    show: function(){
        if(!this.rendered) this.render();
        BACKGROUND.show();
        this.element.show();
        this.element.move_to(document.bodyElement,
            'middle', 'center', 'middle', 'center');
        this.element.style.top = getPageScroll() + (getPageSize().window.height / 2) - (this.element.height() / 2) + "px";
        this.element.style.zIndex = 1000;
    },

    destroy: function(){
        BACKGROUND.hide();
        OVERLAY_DISPLAYED = false;
        document.bodyElement.removeChild(this.element);

        if(this.callback)
            this.callback();
    },

    render: function(){
        this.element = document.createElement('div');

        if(this.height)
            var h = "height:" + this.height + "px;";
        else
            var h = "";

        if(this.width)
            var w = "width:" + this.width + "px;";
        else
            var w = "";

        this.element.innerHTML = "\n            <div style=\"border:2px solid #000;\" class=\"overlay\">\n            <div style=\"text-align:right;background-color:#333;color:white;padding:5px;\">\n                <a href=\"#\" onclick=\"getInstance(" + this.__id__ + ").destroy();return false;\">\n                    Close\n                </a>\n            </div>\n            <div style=\"overflow:auto;background-color:white;" + w + h + "px;padding:5px;\">\n            " + this.content + " \n            </div>\n            </div>\n        ";


        document.bodyElement.appendChild(this.element);

        this.rendered = true;
    }
});
/*
    :: Flash Player Version Detection v1.7 (Copyright 2005-2007 Adobe Systems)
*/

var isIE  = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false;
var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false;
var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false;

function ControlVersion()
{
    var version;
    var axo;
    var e;

    // NOTE : new ActiveXObject(strFoo) throws an exception if strFoo isn't in the registry

    try {
        // version will be set for 7.X or greater players
        axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
        version = axo.GetVariable("$version");
    } catch (e) {
    }

    if (!version)
    {
        try {
            // version will be set for 6.X players only
            axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
            
            // installed player is some revision of 6.0
            // GetVariable("$version") crashes for versions 6.0.22 through 6.0.29,
            // so we have to be careful. 
            
            // default to the first public version
            version = "WIN 6,0,21,0";

            // throws if AllowScripAccess does not exist (introduced in 6.0r47)     
            axo.AllowScriptAccess = "always";

            // safe to call for 6.0r47 or greater
            version = axo.GetVariable("$version");

        } catch (e) {
        }
    }

    if (!version)
    {
        try {
            // version will be set for 4.X or 5.X player
            axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");
            version = axo.GetVariable("$version");
        } catch (e) {
        }
    }

    if (!version)
    {
        try {
            // version will be set for 3.X player
            axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");
            version = "WIN 3,0,18,0";
        } catch (e) {
        }
    }

    if (!version)
    {
        try {
            // version will be set for 2.X player
            axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
            version = "WIN 2,0,0,11";
        } catch (e) {
            version = -1;
        }
    }
    
    return version;
}

// JavaScript helper required to detect Flash Player PlugIn version information
function GetSwfVer(){
    // NS/Opera version >= 3 check for Flash plugin in plugin array
    var flashVer = -1;
    
    if (navigator.plugins != null && navigator.plugins.length > 0) {
        if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) {
            var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";
            var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;
            var descArray = flashDescription.split(" ");
            var tempArrayMajor = descArray[2].split(".");           
            var versionMajor = tempArrayMajor[0];
            var versionMinor = tempArrayMajor[1];
            var versionRevision = descArray[3];
            if (versionRevision == "") {
                versionRevision = descArray[4];
            }
            if (versionRevision[0] == "d") {
                versionRevision = versionRevision.substring(1);
            } else if (versionRevision[0] == "r") {
                versionRevision = versionRevision.substring(1);
                if (versionRevision.indexOf("d") > 0) {
                    versionRevision = versionRevision.substring(0, versionRevision.indexOf("d"));
                }
            }
            var flashVer = versionMajor + "." + versionMinor + "." + versionRevision;
        }
    }
    // MSN/WebTV 2.6 supports Flash 4
    else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.6") != -1) flashVer = 4;
    // WebTV 2.5 supports Flash 3
    else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.5") != -1) flashVer = 3;
    // older WebTV supports Flash 2
    else if (navigator.userAgent.toLowerCase().indexOf("webtv") != -1) flashVer = 2;
    else if ( isIE && isWin && !isOpera ) {
        flashVer = ControlVersion();
    }   
    return flashVer;
}

// When called with reqMajorVer, reqMinorVer, reqRevision returns true if that version or greater is available
function DetectFlashVer(reqMajorVer, reqMinorVer, reqRevision)
{
    versionStr = GetSwfVer();
    if (versionStr == -1 ) {
        return false;
    } else if (versionStr != 0) {
        if(isIE && isWin && !isOpera) {
            // Given "WIN 2,0,0,11"
            tempArray         = versionStr.split(" ");  // ["WIN", "2,0,0,11"]
            tempString        = tempArray[1];           // "2,0,0,11"
            versionArray      = tempString.split(",");  // ['2', '0', '0', '11']
        } else {
            versionArray      = versionStr.split(".");
        }
        var versionMajor      = versionArray[0];
        var versionMinor      = versionArray[1];
        var versionRevision   = versionArray[2];

            // is the major.revision >= requested major.revision AND the minor version >= requested minor
        if (versionMajor > parseFloat(reqMajorVer)) {
            return true;
        } else if (versionMajor == parseFloat(reqMajorVer)) {
            if (versionMinor > parseFloat(reqMinorVer))
                return true;
            else if (versionMinor == parseFloat(reqMinorVer)) {
                if (versionRevision >= parseFloat(reqRevision))
                    return true;
            }
        }
        return false;
    }
}

function AC_AddExtension(src, ext)
{
  if (src.indexOf('?') != -1)
    return src.replace(/\?/, ext+'?');
  else
    return src + ext;
}

function AC_Generateobj(objAttrs, params, embedAttrs)
{

  var str = '';
  if (isIE && isWin && !isOpera)
  {
    str += '<object ';
    for (var i in objAttrs)
    {
      if(typeof(objAttrs[i]) != 'function')
          str += i + '="' + objAttrs[i] + '" ';
    }
    str += '>';
    for (var i in params)
    {
      if(typeof(params[i]) != 'function')
          str += '<param name="' + i + '" value="' + params[i] + '" /> ';
    }
    str += '</object>';
  }
  else
  {
    str += '<embed swliveconnect="true" ';
    for (var i in embedAttrs)
    {
      if(typeof(embedAttrs[i]) != 'function')
          str += i + '="' + embedAttrs[i] + '" ';
    }
    str += '> </embed>';
  }

  document.write(str);
}

var fl_embeds = [];

function AC_FL_RunContent(){
  for(var i=0;i<arguments.length;i++){
	if(arguments[i] == "name"){
		fl_embeds.push(arguments[i+1]);
		break;
	}
  }

  var ret =
    AC_GetArgs
    (  arguments, ".swf", "movie", "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
     , "application/x-shockwave-flash"
    );
  AC_Generateobj(ret.objAttrs, ret.params, ret.embedAttrs);
}

function AC_SW_RunContent(){
  var ret = 
    AC_GetArgs
    (  arguments, ".dcr", "src", "clsid:166B1BCA-3F9C-11CF-8075-444553540000"
     , null
    );
  AC_Generateobj(ret.objAttrs, ret.params, ret.embedAttrs);
}

function AC_GetArgs(args, ext, srcParamName, classid, mimeType){
  var ret = new Object();
  ret.embedAttrs = new Object();
  ret.params = new Object();
  ret.objAttrs = new Object();
  for (var i=0; i < args.length; i=i+2){
    var currArg = args[i].toLowerCase();    
	console.log(currArg);
    switch (currArg){   
      case "classid":
        break;
      case "pluginspage":
        ret.embedAttrs[args[i]] = args[i+1];
        break;
      case "src":
      case "movie": 
        args[i+1] = AC_AddExtension(args[i+1], ext);
        ret.embedAttrs["src"] = args[i+1];
        ret.params[srcParamName] = args[i+1];
        break;
      case "flashVars":
	  case "flashvars":
		cookie = "cookie=" + encodeURI(document.cookie);

		try{
			if(args[i+1].trim() != "")
				cookie = "&" + cookie;
		}catch(e){}

        ret.embedAttrs["flashVars"] = args[i+1] + cookie;
        ret.params["flashVars"] = args[i+1] + cookie;
        break;
      case "onafterupdate":
      case "onbeforeupdate":
      case "onblur":
      case "oncellchange":
      case "onclick":
      case "ondblclick":
      case "ondrag":
      case "ondragend":
      case "ondragenter":
      case "ondragleave":
      case "ondragover":
      case "ondrop":
      case "onfinish":
      case "onfocus":
      case "onhelp":
      case "onmousedown":
      case "onmouseup":
      case "onmouseover":
      case "onmousemove":
      case "onmouseout":
      case "onkeypress":
      case "onkeydown":
      case "onkeyup":
      case "onload":
      case "onlosecapture":
      case "onpropertychange":
      case "onreadystatechange":
      case "onrowsdelete":
      case "onrowenter":
      case "onrowexit":
      case "onrowsinserted":
      case "onstart":
      case "onscroll":
      case "onbeforeeditfocus":
      case "onactivate":
      case "onbeforedeactivate":
      case "ondeactivate":
      case "type":
      case "codebase":
      case "id":
        ret.objAttrs[args[i]] = args[i+1];
        break;
      case "width":
      case "height":
      case "align":
      case "vspace": 
      case "hspace":
      case "class":
      case "title":
      case "accesskey":
      case "name":
      case "tabindex":
        ret.embedAttrs[args[i]] = ret.objAttrs[args[i]] = args[i+1];
        break;
      default:
        ret.embedAttrs[args[i]] = ret.params[args[i]] = args[i+1];
    }
  }
  ret.objAttrs["classid"] = classid;
  if (mimeType) ret.embedAttrs["type"] = mimeType;
  return ret;
}

var requiredMajorVersion = 8;
var requiredMinorVersion = 0;
var requiredRevision = 0;
_Tabs = Class.create({
    initialize: function(options){
        this.options = options;
        this.container = $(this.options.container);

        this.tabs = this.container.getChildElementsByTagName(this.options.tab_element);
        this.values = this.container.getChildElementsByTagName(this.options.value_element);

        var that = this;
        this.tabs.each(function(n, idx){
            n.idx = idx;
            n.style.cursor = "pointer";
            listen(n, "click", function(n, e){
                that.set(e.target);
            });
        });

        this.values.each(function(n, idx){
            n.hide();
        });
    },

    set: function(tab){
        if(tab - tab == 0)
            tab = this.tabs[tab];

        this.values.each(function(n){
            n.hide();
        });

        this.values[tab.idx].show();
        trigger(this.tabs[0], "tab_on");
        trigger(this, "tab_on", tab);
        this.unset_all_but(tab.idx);
    },

    unset_all_but: function(idx){
        var that = this;
        this.tabs.each(function(n, i){
            if(i != idx){
                trigger(that.tabs[i], "tab_off");
                trigger(that, "tab_off", n);
            }
        });
    }
});

Tabs = {};
Tabs.create = function(container, tab_element, value_element){
    return(new _Tabs({ "container": container, "tab_element": tab_element, "value_element": value_element}));
}
/* Until we write our own, we'll use prototype's library. (grr))) */
/*--------------------------------------------------------------------------*/


var Form = {
  serialize: function(form) {
    var elements = Form.getElements(form);
    var queryComponents = new Array();

    for (var i = 0; i < elements.length; i++) {
      var queryComponent = Form.Element.serialize(elements[i]);
      if (queryComponent)
        queryComponents.push(queryComponent);
    }

    return queryComponents.join('&');
  },

  hash: function(form){
    var elements = Form.getElements(form);
    var hash = {};
    for(var i=0;i<elements.length;i++)
        hash[elements[i].name] = $F(elements[i]);

    return hash;
  },

  getElements: function(form) {
    var elements = new Array();

    for (var tagName in Form.Element.Serializers) {
      var tagElements = form.getElementsByTagName(tagName);
      for (var j = 0; j < tagElements.length; j++)
        elements.push(tagElements[j]);
    }
    return elements;
  },

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

    if (!typeName && !name)
      return inputs;

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

    return matchingInputs;
  },

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

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

  findFirstElement: function(form) {
    return Form.getElements(form).find(function(element) {
      return element.type != 'hidden' && !element.disabled &&
        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
    });
  },

  focusFirstElement: function(form) {
    Field.activate(Form.findFirstElement(form));
  },

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

Form.Element = {
  serialize: function(element) {
    var method = element.tagName.toLowerCase();
    var parameter = Form.Element.Serializers[method](element);

    if (parameter) {
      var key = encodeURIComponent(parameter[0]);
      if (key.length == 0) return;

      if (parameter[1].constructor != Array)
        parameter[1] = [parameter[1]];

      return parameter[1].map(function(value) {
        return key + '=' + encodeURIComponent(value);
      }).join('&');
    }
  },

  getValue: function(element) {
    var method = element.tagName.toLowerCase();
    var parameter = Form.Element.Serializers[method](element);

    if (parameter)
      return parameter[1];
  }
}

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

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

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

  select: function(element) {
    return Form.Element.Serializers[element.type == 'select-one' ?
      'selectOne' : 'selectMany'](element);
  },

  selectOne: function(element) {
    var value = '', opt, index = element.selectedIndex;
	console.log(index);
	console.log(element.options[index]);
	console.log(element.options[index].value);
    if (index >= 0) {
      opt = element.options[index];
	  value = opt.value;
	  if(!opt.getAttribute("value") && typeof(value) != 'string')
			value = opt.text
    }
    return [element.name, value];
  },

  selectMany: function(element) {
    var value = [];
    for (var i = 0; i < element.length; i++) {
      var opt = element.options[i];
      if (opt.selected)
        value.push(opt.value || opt.text);
    }
    return [element.name, value];
  }
}

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

var $F = Form.Element.getValue;

/*--------------------------------------------------------------------------*/
String.prototype.update({
	ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',

	test: function(regex, params){
		return (($type(regex) == 'string') ? new RegExp(regex, params) : regex).test(this);
	},

	toInt: function(){
		return parseInt(this, 10);
	},

	toFloat: function(){
		return parseFloat(this);
	},

	camelCase: function(){
		return this.replace(/-\D/g, function(match){
			return match.charAt(1).toUpperCase();
		});
	},

	hyphenate: function(){
		return this.replace(/\w[A-Z]/g, function(match){
			return (match.charAt(0) + '-' + match.charAt(1).toLowerCase());
		});
	},

	capitalize: function(){
		return this.replace(/\b[a-z]/g, function(match){
			return match.toUpperCase();
		});
	},

	trim: function(){
		return this.replace(/^\s+|\s+$/g, '');
	},

	clean: function(){
		return this.replace(/\s{2,}/g, ' ').trim();
	},

	rgbToHex: function(array){
		var rgb = this.match(/\d{1,3}/g);
		return (rgb) ? rgb.rgbToHex(array) : false;
	},

	hexToRgb: function(array){
		var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
		return (hex) ? hex.slice(1).hexToRgb(array) : false;
	},

	contains: function(string, s){
		return (s) ? (s + this + s).indexOf(s + string + s) > -1 : this.indexOf(string) > -1;
	},

	escapeRegExp: function(){
		return this.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
	},

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

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

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

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

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



});
/*
    :: effect.js ((c) 2006 Valerio Proietti (http://www.mad4milk.net), MIT-style license.
    :: effects.js (2007 James Kassemi (jamesk@ideum.com) - rewritten for generics library)
   ::  transitions (c) 2003 Robert Penner (http://www.robertpenner.com/easing/), BSD License.
*/

//(c) 2006 Valerio Proietti (http://mad4milk.net). MIT-style license.
//moo.fx.js - depends on prototype.js OR prototype.lite.js
//version 2.0

var Fx = fx = {};
Fx.Base = function(){};

Fx.Base.prototype = {
	setOptions: function(options){
		this.options = Object.extend({
			onStart: function(){},
			onComplete: function(){},
			transition: Fx.Transitions.linear,
			duration: 300,
			unit: 'px',
			wait: true,
			fps: 500
		}, options || {});
	},

	step: function(){
		var time = new Date().getTime();
		if (time < this.time + this.options.duration){
			this.cTime = time - this.time;
			this.setNow();
		} else {
			setTimeout(this.options.onComplete.bind(this, this.element), 10);
			this.clearTimer();
			this.now = this.to;
		}
		this.increase();
	},

	setNow: function(){
		this.now = this.compute(this.from, this.to);
	},

	compute: function(from, to){
		var change = to - from;
		return this.options.transition(this.cTime, from, change, this.options.duration);
	},

	clearTimer: function(){
		clearInterval(this.timer);
		this.timer = null;
		return this;
	},

	_start: function(from, to){
		if (!this.options.wait) this.clearTimer();
		if (this.timer) return;
		setTimeout(this.options.onStart.bind(this, this.element), 10);
		this.from = from;
		this.to = to;
		this.time = new Date().getTime();
		this.timer = setInterval(this.step.bind(this), Math.round(1000/this.options.fps));
		return this;
	},

	custom: function(from, to){
		return this._start(from, to);
	},

	set: function(to){
		this.now = to;
		this.increase();
		return this;
	},

	hide: function(){
		return this.set(0);
	},

	setStyle: function(e, p, v){
		if (p == 'opacity'){
			if (v == 0 && e.style.visibility != "hidden") e.style.visibility = "hidden";
			else if (e.style.visibility != "visible") e.style.visibility = "visible";
			if (window.ActiveXObject) e.style.filter = "alpha(opacity=" + v*100 + ")";
			e.style.opacity = v;
		} else e.style[p] = v + this.options.unit;
	}

};

Fx.Style = Class.create();
Fx.Style.prototype = Object.extend(new Fx.Base(), {
	initialize: function(el, property, options){
        if(!el.nodeType)
            this.element = $(el);
        else
            this.element = el;

		this.setOptions(options);
		this.property = property.camelCase();
	},

	increase: function(){
		this.setStyle(this.element, this.property, this.now);
	}

});

Fx.Styles = Class.create();
Fx.Styles.prototype = Object.extend(new Fx.Base(), {
	initialize: function(el, options){
		this.element = $(el);
		this.setOptions(options);
		this.now = {};
	},

	setNow: function(){
		for (p in this.from) this.now[p] = this.compute(this.from[p], this.to[p]);
	},

	custom: function(obj){
		if (this.timer && this.options.wait) return;
		var from = {};
		var to = {};
		for (p in obj){
			from[p] = obj[p][0];
			to[p] = obj[p][1];
		}
		return this._start(from, to);
	},

	increase: function(){
		for (var p in this.now) this.setStyle(this.element, p, this.now[p]);
	}
});

//Transitions (c) 2003 Robert Penner (http://www.robertpenner.com/easing/), BSD License.
Fx.Transitions = {
	linear: function(t, b, c, d) { return c*t/d + b; },
	sineInOut: function(t, b, c, d) { return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; }
};
/*
    :: Valerio Proietti (http://mad4milk.net) (MIT)
    :: James Kassemi (jamesk@ideum.com)
*/

Fx.Scroll = Class.create();
Fx.Scroll.prototype = Object.extend(new Fx.Base(), {
	initialize: function(el, options) {
		this.element = $(el);
		this.setOptions(options);
		this.element.style.overflow = 'hidden';
	},

	down: function(){
		return this.custom(this.element.scrollTop, this.element.scrollHeight-this.element.offsetHeight);
	},

	up: function(){
		return this.custom(this.element.scrollTop, 0);
	},

	increase: function(){
		this.element.scrollTop = this.now;
	}
});

//fx.Color, originally by Tom Jensen (http://neuemusic.com) MIT-style LICENSE.

Fx.Color = Class.create();
Fx.Color.prototype = Object.extend(new Fx.Base(), {
	initialize: function(el, property, options){
		if(typeof(el) == 'string')
			this.element = $(el);
		else
			this.element = el;

		this.setOptions(options);
		this.property = property;
		this.now = [];
	},

	custom: function(from, to){
		return this._start(from.hexToRgb(true), to.hexToRgb(true));
	},

	setNow: function(){
        for(i=0;i<3;i++)
			this.now[i] = Math.round(this.compute(this.from[i], this.to[i]));
	},

	increase: function(){
		this.element.style[this.property] = "rgb("+this.now[0]+","+this.now[1]+","+this.now[2]+")";
	}

});

Object.extend(String.prototype, {
    rgbTextToRgb: function(rgb_text){
        rgb_text = rgb_text.splice(3, rgb_text.length);
        console.log("rgbtext: " + rgb_text);
    },

	rgbToHex: function(array){
		var rgb = this.match(new RegExp('([\\d]{1,3})', 'g'));
		if (rgb[3] == 0) return 'transparent';
		var hex = [];
		for (var i = 0; i < 3; i++){
			var bit = (rgb[i]-0).toString(16);
			hex.push(bit.length == 1 ? '0'+bit : bit);
		}
		var hexText = '#'+hex.join('');
		if (array) return hex;
		else return hexText;
	},

	hexToRgb: function(array){
		var hex = this.match(new RegExp('^[#]{0,1}([\\w]{1,2})([\\w]{1,2})([\\w]{1,2})$'));
		var rgb = [];
		for (var i = 1; i < hex.length; i++){
			if (hex[i].length == 1) hex[i] += hex[i];
			rgb.push(parseInt(hex[i], 16));
		}
		var rgbText = 'rgb('+rgb.join(',')+')';
		if (array) return rgb;
		else return rgbText;
	}
});
//by Valerio Proietti (http://mad4milk.net). MIT-style license.
//moo.fx.utils.js - depends on prototype.js OR prototype.lite.js + moo.fx.js
//version 2.0

Fx.Height = Class.create();
Fx.Height.prototype = Object.extend(new Fx.Base(), {

	initialize: function(el, options){
		this.element = $(el);
		this.setOptions(options);
		this.element.style.overflow = 'hidden';
	},

	toggle: function(){
		if (this.element.offsetHeight > 0) return this.custom(this.element.offsetHeight, 0);
		else return this.custom(0, this.element.scrollHeight);
	},

	show: function(){
		return this.set(this.element.scrollHeight);
	},

	increase: function(){
		this.setStyle(this.element, 'height', this.now);
	}

});

Fx.Width = Class.create();
Fx.Width.prototype = Object.extend(new Fx.Base(), {

	initialize: function(el, options){
		this.element = $(el);
		this.setOptions(options);
		this.element.style.overflow = 'hidden';
		this.iniWidth = this.element.offsetWidth;
	},

	toggle: function(){
		if (this.element.offsetWidth > 0) return this.custom(this.element.offsetWidth, 0);
		else return this.custom(0, this.iniWidth);
	},

	show: function(){
		return this.set(this.iniWidth);
	},

	increase: function(){
		this.setStyle(this.element, 'width', this.now);
	}

});

Fx.Opacity = Class.create();
Fx.Opacity.prototype = Object.extend(new Fx.Base(), {

	initialize: function(el, options){
		if(typeof(el) == 'string')
			this.element = $(el);
		else
			this.element = el;

		this.setOptions(options);
		this.now = 1;
	},

	toggle: function(){
		if (this.now > 0) return this.custom(1, 0);
		else return this.custom(0, 1);
	},

	show: function(){
		return this.set(1);
	},

	opacity_in: function(){
		return this.custom(0, 1);
	},

	opacity_out: function(){
		return this.custom(1, 0);
	},

	increase: function(){
		this.setStyle(this.element, 'opacity', this.now);
	}

});
//moo.fx.transitions.js - depends on prototype.js or prototype.lite.js + moo.fx.js
//Author: Robert Penner, <http://www.robertpenner.com/easing/>, modified to be used with mootools.
//License: Easing Equations v1.5, (c) 2003 Robert Penner, all rights reserved. Open Source BSD License.

Fx.Transitions = {

	linear: function(t, b, c, d){
		return c*t/d + b;
	},

	quadIn: function(t, b, c, d){
		return c*(t/=d)*t + b;
	},

	quadOut: function(t, b, c, d){
		return -c *(t/=d)*(t-2) + b;
	},

	quadInOut: function(t, b, c, d){
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},

	cubicIn: function(t, b, c, d){
		return c*(t/=d)*t*t + b;
	},

	cubicOut: function(t, b, c, d){
		return c*((t=t/d-1)*t*t + 1) + b;
	},

	cubicInOut: function(t, b, c, d){
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	},

	quartIn: function(t, b, c, d){
		return c*(t/=d)*t*t*t + b;
	},

	quartOut: function(t, b, c, d){
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},

	quartInOut: function(t, b, c, d){
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},

	quintIn: function(t, b, c, d){
		return c*(t/=d)*t*t*t*t + b;
	},

	quintOut: function(t, b, c, d){
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},

	quintInOut: function(t, b, c, d){
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	},

	sineIn: function(t, b, c, d){
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},

	sineOut: function(t, b, c, d){
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},

	sineInOut: function(t, b, c, d){
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},

	expoIn: function(t, b, c, d){
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},

	expoOut: function(t, b, c, d){
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},

	expoInOut: function(t, b, c, d){
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	},

	circIn: function(t, b, c, d){
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},

	circOut: function(t, b, c, d){
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},

	circInOut: function(t, b, c, d){
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	},

	elasticIn: function(t, b, c, d, a, p){
		if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (!a) a = 1;
		if (a < Math.abs(c)){ a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin(c/a);
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},

	elasticOut: function(t, b, c, d, a, p){
		if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (!a) a = 1;
		if (a < Math.abs(c)){ a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin(c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},

	elasticInOut: function(t, b, c, d, a, p){
		if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); if (!a) a = 1;
		if (a < Math.abs(c)){ a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin(c/a);
		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
	},

	backIn: function(t, b, c, d, s){
		if (!s) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},

	backOut: function(t, b, c, d, s){
		if (!s) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},

	backInOut: function(t, b, c, d, s){
		if (!s) s = 1.70158;
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},

	bounceIn: function(t, b, c, d){
		return c - Fx.Transitions.bounceOut (d-t, 0, c, d) + b;
	},

	bounceOut: function(t, b, c, d){
		if ((t/=d) < (1/2.75)){
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)){
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else {
			return c*(7.5625*(t-=(2.6/2.75))*t + .984375) + b;
		}
        /*
		if ((t/=d) < (1/2.75)){
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)){
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else if (t < (2.5/2.75)){
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
    */
	},

	bounceInOut: function(t, b, c, d){
		if (t < d/2) return Fx.Transitions.bounceIn(t*2, 0, c, d) * .5 + b;
		return Fx.Transitions.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
	}

};

function over_star(element, index, new_source){
    for(var i=1;i<=index;i++){
        var f = $('star_' + i);
        if(!f.old_src) f.old_src = f.src;
        f.src = new_source;
    }
}

function outof_star(element, index){
    for(var i=1;i<=index;i++){
        var f= $('star_' + i);
        f.src = f.old_src;
    }
}


function get_flash(movieName){
	if(window.document[movieName])
		return window.document[movieName];

	if(IE)
		if(document.embeds && document.embeds[movieName])
			return document.embeds[movieName];
	else
		return $(movieName);
}


/* js -> flash */
function flash_showLogin(movieName){
	var mov = get_flash(movieName);
	mov.showLogin();
}

function flash_showRegistration(movieNme){
	var mov = get_flash(movieName);
	mov.showRegistration();
}

/* flash -> js */

function flash_signedUp(){
	if(!$exists('flash')){
		var lb = $("login_bar")
		var an = lb.nextSibling;
		var nn = document.createElement("div");
		nn.setAttribute("id", "flash");
		lb.parentNode.insertBefore(nn, an);
	}

	var fl = $("flash");
	fl.show();
	fl.innerHTML = "<div class=\"flash_notice\">You are now an official member of GorillaSpot!</div>";
	fl.childNodes[0].fade_in()

}

function flash_login(){
	$("login_bar").hide();
	$("logged_in_bar").show();

	try {
		$('flash').innerHTML = "";
	}catch(e){}
}

function flashAjax(resource, options){
	var complete = options["onComplete"];
	options["onComplete"] = function(res){
		sendToFlash(complete, res.responseText);
	}

	var fail = options["onFailure"];
	options["fail"] = function(res){
		sendToFlash(fail);
	}

	new Ajax.Request(resource, options)
}

function sendToFlash(command, args){
	args = args || [];
	get_flash(fl_embeds[0])[command](args[0], args[1], args[2]);
}

function flash_UserLoggedIn(username){
	$('logged_in').innerHTML = "Welcome, " + username;
	$('login_bar_in').hide();
	$('login_bar_out').show();
	$('logged_in').show();
}
