/**
 * Date instance methods
 *
 * @author Ken Snyder (ken d snyder at gmail dot com)
 * @date 2008-09-10
 * @version 2.0.2 (http://kendsnyder.com/sandbox/date/)
 * @license Creative Commons Attribution License 3.0 (http://creativecommons.org/licenses/by/3.0/)
 */
// begin by creating a scope for utility variables
(function() {
  //
  // pre-calculate the number of milliseconds in a day
  //
  var day = 24 * 60 * 60 * 1000;
	//
	// function to add leading zeros
	//
	var zeroPad = function(number, digits) {
		number = String(number);
		while (number.length < digits) number = '0' + number;
		return number;
	};
  //
  // set up integers and functions for adding to a date or subtracting two dates
  //
  var multipliers = {
    millisecond: 1,
    second: 1000,
    minute: 60 * 1000,
    hour: 60 * 60 * 1000,
    day: day,
    week: 7 * day,
    month: {
      // add a number of months
      add: function(d, number) {
        // add any years needed (increments of 12)
        multipliers.year.add(d, Math[number > 0 ? 'floor' : 'ceil'](number / 12));
        // ensure that we properly wrap betwen December and January
        var prevMonth = d.getMonth() + (number % 12);
        if (prevMonth == 12) {
          prevMonth = 0;
          d.setYear(d.getFullYear() + 1);
        } else if (prevMonth == -1) {
          prevMonth = 11;
          d.setYear(d.getFullYear() - 1);
        }
        d.setMonth(prevMonth);
      },
      // get the number of months between two Date objects (decimal to the nearest day)
      diff: function(d1, d2) {
        // get the number of years
        var diffYears = d1.getFullYear() - d2.getFullYear();
        // get the number of remaining months
        var diffMonths = d1.getMonth() - d2.getMonth() + (diffYears * 12);
        // get the number of remaining days
        var diffDays = d1.getDate() - d2.getDate();
        // return the month difference with the days difference as a decimal
        return diffMonths + (diffDays / 30);
      }
    },
    year: {
      // add a number of years
      add: function(d, number) {
        d.setYear(d.getFullYear() + Math[number > 0 ? 'floor' : 'ceil'](number));
      },
      // get the number of years between two Date objects (decimal to the nearest day)
      diff: function(d1, d2) {
        return multipliers.month.diff(d1, d2) / 12;
      }
    }    
  };
  //
  // alias each multiplier with an 's' to allow 'year' and 'years' for example
  //
  for (var unit in multipliers) {
		if (unit.substring(unit.length - 1) != 's') { // IE will iterate newly added properties :|
	    multipliers[unit + 's'] = multipliers[unit];
		}
  }
	//
	// take a date instance and a format code and return the formatted value
	//
	var format = function(d, code) {
		if (Date.prototype.strftime.formatShortcuts[code]) {
			// process any shortcuts recursively
			return d.strftime(Date.prototype.strftime.formatShortcuts[code]);
		} else {
			// get the format code function and toPaddedString() argument
			var getter = (Date.prototype.strftime.formatCodes[code] || '').split('.');
			var nbr = d['get' + getter[0]] ? d['get' + getter[0]]() : '';
			// run toPaddedString() if specified
			if (getter[1]) nbr = zeroPad(nbr, getter[1]);
			// prepend the leading character
			return nbr;
		}	
	};
  //
  // Add methods to Date instances
  //
  var instanceMethods = {
    //
    // Return a date one day ahead (or any other unit)
    //
    // @param string unit
    // units: year | month | day | week | hour | minute | second | millisecond
    // @return object Date
    //
    succ: function(unit) {
      return this.clone().add(1, unit);
    },
    //
    // Add an arbitrary amount to the currently stored date
    //
    // @param integer/float number    
    // @param string unit
    // @return object Date (chainable)    
    //
    add: function(number, unit) {
      var factor = multipliers[unit] || multipliers.day;
      if (typeof factor == 'number') {
        this.setTime(this.getTime() + (factor * number));
      } else {
        factor.add(this, number);
      }
      return this;
    },
    //
    // Find the difference between the current and another date
    //
    // @param string/object dateObj
    // @param string unit
    // @param boolean allowDecimal
    // @return integer/float
    //
    diff: function(dateObj, unit, allowDecimal) {
      // ensure we have a Date object
      dateObj = Date.create(dateObj);
      if (dateObj === null) return null;
      // get the multiplying factor integer or factor function
      var factor = multipliers[unit] || multipliers.day;
      if (typeof factor == 'number') {
        // multiply
        var unitDiff = (this.getTime() - dateObj.getTime()) / factor;
      } else {
        // run function
        var unitDiff = factor.diff(this, dateObj);
      }
      // if decimals are not allowed, round toward zero
      return (allowDecimal ? unitDiff : Math[unitDiff > 0 ? 'floor' : 'ceil'](unitDiff));      
    },
    //
    // Convert a date to a string using traditional strftime format codes
    //
    // @param string formatStr
    // @return string
    //
    strftime: function(formatStr) {
      // default the format string to year-month-day
      var source = formatStr || '%Y-%m-%d', result = '', match;
      // replace each format code
			while (source.length > 0) {
				if (match = source.match(Date.prototype.strftime.formatCodes.matcher)) {
	        result += source.slice(0, match.index);
	        result += (match[1] || '') + format(this, match[2]);
	        source = source.slice(match.index + match[0].length);
	      } else {
	        result += source, source = '';
	      }
	    }
			return result;
		},
    //
    // Return a proper two-digit year integer
    //
    // @return integer
    //
    getShortYear: function() {
      return this.getYear() % 100;
    },
    //
    // Get the number of the current month, 1-12
    //
    // @return integer
    //
    getMonthNumber: function() {
      return this.getMonth() + 1;
    },
    //
    // Get the name of the current month
    //
    // @return string
    //
    getMonthName: function() {
      return Date.MONTHNAMES[this.getMonth()];
    },
    //
    // Get the abbreviated name of the current month
    //
    // @return string
    //
    getAbbrMonthName: function() {
      return Date.ABBR_MONTHNAMES[this.getMonth()];
    },
    //
    // Get the name of the current week day
    //
    // @return string
    //    
    getDayName: function() {
      return Date.DAYNAMES[this.getDay()];
    },
    //
    // Get the abbreviated name of the current week day
    //
    // @return string
    //    
    getAbbrDayName: function() {
      return Date.ABBR_DAYNAMES[this.getDay()];
    },
    //
    // Get the ordinal string associated with the day of the month (i.e. st, nd, rd, th)
    //
    // @return string
    //    
    getDayOrdinal: function() {
      return Date.ORDINALNAMES[this.getDate() % 10];
    },
    //
    // Get the current hour on a 12-hour scheme
    //
    // @return integer
    //
    getHours12: function() {
      var hours = this.getHours();
      return hours > 12 ? hours - 12 : (hours == 0 ? 12 : hours);
    },
    //
    // Get the AM or PM for the current time
    //
    // @return string
    //
    getAmPm: function() {
      return this.getHours() >= 12 ? 'PM' : 'AM';
    },
    //
    // Get the current date as a Unix timestamp
    //
    // @return integer
    //
    getUnix: function() {
      return Math.round(this.getTime() / 1000, 0);
    },
    //
    // Get the GMT offset in hours and minutes (e.g. +06:30)
    //
    // @return string
    //
    getGmtOffset: function() {
      // divide the minutes offset by 60
      var hours = this.getTimezoneOffset() / 60;
      // decide if we are ahead of or behind GMT
      var prefix = hours < 0 ? '+' : '-';
      // remove the negative sign if any
      hours = Math.abs(hours);
      // add the +/- to the padded number of hours to : to the padded minutes
      return prefix + zeroPad(Math.floor(hours), 2) + ':' + zeroPad((hours % 1) * 60, 2);
    },
    //
    // Get the browser-reported name for the current timezone (e.g. MDT, Mountain Daylight Time)
    //
    // @return string
    //
    getTimezoneName: function() {
      var match = /(?:\((.+)\)$| ([A-Z]{3}) )/.exec(this.toString());
			return match[1] || match[2] || 'GMT' + this.getGmtOffset();
    },
    //
    // Convert the current date to an 8-digit integer (%Y%m%d)
    //
    // @return int
    //
    toYmdInt: function() {
      return (this.getFullYear() * 10000) + (this.getMonthNumber() * 100) + this.getDate();
    },	
    //
    // Create a copy of a date object
    //
    // @return object
    //		
		clone: function() {
			return new Date(this.getTime());
		}
  };
	for (var name in instanceMethods) Date.prototype[name] = instanceMethods[name];
  //
  // Add static methods to the date object
  //
  var staticMethods = {
    //
    // The heart of the date functionality: returns a date object if given a convertable value
    //
    // @param string/object/integer date
    // @return object Date
    //
    create: function(date) {
      // If the passed value is already a date object, return it
      if (date instanceof Date) return date;
      // If the passed value is an integer, interpret it as a unix timestamp
      if (typeof date == 'number') return new Date(date * 1000);
      // If the passed value is a string, attempt to parse it using Date.parse()
			var parsable = String(date).replace(/^\s*(.+)\s*$/, '$1'), i = 0, length = Date.create.patterns.length, pattern;
			var current = parsable;
			while (i < length) {
				ms = Date.parse(current);
				if (!isNaN(ms)) return new Date(ms);
				pattern = Date.create.patterns[i];
				if (typeof pattern == 'function') {
					obj = pattern(current);
					if (obj instanceof Date) return obj;
				} else {
					current = parsable.replace(pattern[0], pattern[1]);
				}
				i++;
			}
			return NaN;
    },
    //
    // constants representing month names, day names, and ordinal names
    // (same names as Ruby Date constants)
    //
    MONTHNAMES      : 'January February March April May June July August September October November December'.split(' '),
    ABBR_MONTHNAMES : 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' '),
    DAYNAMES        : 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday'.split(' '),
    ABBR_DAYNAMES   : 'Sun Mon Tue Wed Thu Fri Sat'.split(' '),
    ORDINALNAMES    : 'th st nd rd th th th th th th'.split(' '),
    //
    // Shortcut for full ISO-8601 date conversion
    //
    ISO: '%Y-%m-%dT%H:%M:%S.%N%G',
    //
    // Shortcut for SQL-type formatting
    //
    SQL: '%Y-%m-%d %H:%M:%S',
    //
    // Setter method for month, day, and ordinal names for i18n
    //
    // @param object newNames
    //
  	daysInMonth: function(year, month) {
  		if (month == 2)
  			return new Date(year, 1, 29).getDate() == 29 ? 29 : 28;
  		return [undefined,31,undefined,31,30,31,30,31,31,30,31,30,31][month];
  	}
  };
	for (var name in staticMethods) Date[name] = staticMethods[name];
 	//
  // format codes for strftime
  //
  // each code must be an array where the first member is the name of a Date.prototype function
  // and optionally a second member indicating the number to pass to Number#toPaddedString()
  //
	Date.prototype.strftime.formatCodes = {
    //
    // 2-part regex matcher for format codes
    //
    // first match must be the character before the code (to account for escaping)
    // second match must be the format code character(s)
    //
    matcher: /()%(#?(%|[a-z]))/i,
    // year
    Y: 'FullYear',
    y: 'ShortYear.2',
    // month
    m: 'MonthNumber.2',
 '#m': 'MonthNumber',
    B: 'MonthName',
    b: 'AbbrMonthName',
    // day
    d: 'Date.2',
 '#d': 'Date',
    e: 'Date',
    A: 'DayName',
    a: 'AbbrDayName',
    w: 'Day',
    o: 'DayOrdinal',
    // hours
    H: 'Hours.2',
 '#H': 'Hours',
    I: 'Hours12.2',
 '#I': 'Hours12',
    p: 'AmPm',
    // minutes
    M: 'Minutes.2',
 '#M': 'Minutes',
    // seconds
    S: 'Seconds.2',
 '#S': 'Seconds',
    s: 'Unix',
    // milliseconds
    N: 'Milliseconds.3',
 '#N': 'Milliseconds',
    // timezone
    O: 'TimezoneOffset',
    Z: 'TimezoneName',
    G: 'GmtOffset'  
  };
  //
  // shortcuts that will be translated into their longer version
  //
  // be sure that format shortcuts do not refer to themselves: this will cause an infinite loop
  //
  Date.prototype.strftime.formatShortcuts = {
    // date
    F: '%Y-%m-%d',
    // time
    T: '%H:%M:%S',
    X: '%H:%M:%S',
    // local format date
    x: '%m/%d/%y',
    D: '%m/%d/%y',
    // local format extended
 '#c': '%a %b %e %H:%M:%S %Y',
    // local format short
    v: '%e-%b-%Y',
    R: '%H:%M',
    r: '%I:%M:%S %p',
    // tab and newline
    t: '\t',
    n: '\n',
  '%': '%'
  };
  //
  // A list of conversion patterns (array arguments sent directly to gsub)
  // Add, remove or splice a patterns to customize date parsing ability
  //
	Date.create.patterns = [
    [/-/g, '/'], // US-style time with dashes => Parsable US-style time
		[/st|nd|rd|th/g, ''], // remove st, nd, rd and th    
    [/(3[01]|[0-2]\d)\s*\.\s*(1[0-2]|0\d)\s*\.\s*([1-9]\d{3})/, '$2/$1/$3'], // World time => Parsable US-style time
    [/([1-9]\d{3})\s*-\s*(1[0-2]|0\d)\s*-\s*(3[01]|[0-2]\d)/, '$2/$3/$1'], // ISO-style time => Parsable US-style time
		function(str) { // 12-hour time
			var match = str.match(/^(?:(.+)\s+)?([1-9]|1[012])(?:\s*\:\s*(\d\d))?(?:\s*\:\s*(\d\d))?\s*(am|pm)\s*$/i);
			//                      ^opt. date  ^hour         ^opt. minute       ^opt. second          ^am or pm
			if (match) {
				if (match[1]) {
					var d = Date.create(match[1]);
					if (isNaN(d)) return;
				} else {
					var d = new Date();
					d.setMilliseconds(0);
				}
				var hour = parseFloat(match[2]);
				hour = match[5].toLowerCase() == 'am' ? (hour == 12 ? 0 : hour) : (hour == 12 ? 12 : hour + 12);
				d.setHours(hour, parseFloat(match[3] || 0), parseFloat(match[4] || 0));
				return d;
			}
		}		
  ];  
})();
//
// Create a convenience method for creating dates from strings
//
var $D = Date.create;

/**********************************************************\

|                                                          |

| The implementation of PHPRPC Protocol 3.0                |

|                                                          |

| utf.js                                                   |

|                                                          |

| Release 3.0.1                                            |

| Copyright by Team-PHPRPC                                 |

|                                                          |

| WebSite:  http://www.phprpc.org/                         |

|           http://www.phprpc.net/                         |

|           http://www.phprpc.com/                         |

|           http://sourceforge.net/projects/php-rpc/       |

|                                                          |

| Authors:  Ma Bingyao <andot@ujn.edu.cn>                  |

|                                                          |

| This file may be distributed and/or modified under the   |

| terms of the GNU Lesser General Public License (LGPL)    |

| version 3.0 as published by the Free Software Foundation |

| and appearing in the included file LICENSE.              |

|                                                          |

\**********************************************************/



/* UTF-8 <=> UTF-16 convertion library.

 *

/* Copyright: Masanao Izumo <iz@onicos.co.jp>

 *            Ma Bingyao <andot@ujn.edu.cn>

 * Version: 2.4

 * LastModified: Oct 19, 2007

 * This library is free.  You can redistribute it and/or modify it.

 */



/*

 * Interfaces:

 * var utf8, utf16;

 * utf16 = "我爱中国";

 * utf8 = utf16.toUTF8();

 * utf16 = utf8.toUTF16();

 */



String.prototype.toUTF8 = function() {

    var str = this;

    if (str.match(/^[\x00-\x7f]*$/) != null) {

        return str.toString();

    }

    var out, i, j, len, c, c2;

    out = [];

    len = str.length;

    for (i = 0, j = 0; i < len; i++, j++) {

        c = str.charCodeAt(i);

        if (c <= 0x7f) {

            out[j] = str.charAt(i);

        }

        else if (c <= 0x7ff) {

            out[j] = String.fromCharCode(0xc0 | (c >>> 6),

                                         0x80 | (c & 0x3f));

        }

        else if (c < 0xd800 || c > 0xdfff) {

            out[j] = String.fromCharCode(0xe0 | (c >>> 12),

                                         0x80 | ((c >>> 6) & 0x3f),

                                         0x80 | (c & 0x3f));

        }

        else {

            if (++i < len) {

                c2 = str.charCodeAt(i);

                if (c <= 0xdbff && 0xdc00 <= c2 && c2 <= 0xdfff) {

                    c = ((c & 0x03ff) << 10 | (c2 & 0x03ff)) + 0x010000;

                    if (0x010000 <= c && c <= 0x10ffff) {

                        out[j] = String.fromCharCode(0xf0 | ((c >>> 18) & 0x3f),

                                                     0x80 | ((c >>> 12) & 0x3f),

                                                     0x80 | ((c >>> 6) & 0x3f),

                                                     0x80 | (c & 0x3f));

                    }

                    else {

                       out[j] = '?';

                    }

                }

                else {

                    i--;

                    out[j] = '?';

                }

            }

            else {

                i--;

                out[j] = '?';

            }

        }

    }

    return out.join('');

}



String.prototype.toUTF16 = function() {

    var str = this;

    if ((str.match(/^[\x00-\x7f]*$/) != null) ||

        (str.match(/^[\x00-\xff]*$/) == null)) {

        return str.toString();

    }

    var out, i, j, len, c, c2, c3, c4, s;



    out = [];

    len = str.length;

    i = j = 0;

    while (i < len) {

        c = str.charCodeAt(i++);

        switch (c >> 4) {

            case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:

            // 0xxx xxxx

            out[j++] = str.charAt(i - 1);

            break;

            case 12: case 13:

            // 110x xxxx   10xx xxxx

            c2 = str.charCodeAt(i++);

            out[j++] = String.fromCharCode(((c  & 0x1f) << 6) |

                                            (c2 & 0x3f));

            break;

            case 14:

            // 1110 xxxx  10xx xxxx  10xx xxxx

            c2 = str.charCodeAt(i++);

            c3 = str.charCodeAt(i++);

            out[j++] = String.fromCharCode(((c  & 0x0f) << 12) |

                                           ((c2 & 0x3f) <<  6) |

                                            (c3 & 0x3f));

            break;

            case 15:

            switch (c & 0xf) {

                case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:

                // 1111 0xxx  10xx xxxx  10xx xxxx  10xx xxxx

                c2 = str.charCodeAt(i++);

                c3 = str.charCodeAt(i++);

                c4 = str.charCodeAt(i++);

                s = ((c  & 0x07) << 18) |

                    ((c2 & 0x3f) << 12) |

                    ((c3 & 0x3f) <<  6) |

                     (c4 & 0x3f) - 0x10000;

                if (0 <= s && s <= 0xfffff) {

                    out[j++] = String.fromCharCode(((s >>> 10) & 0x03ff) | 0xd800,

                                                  (s         & 0x03ff) | 0xdc00);

                }

                else {

                    out[j++] = '?';

                }

                break;

                case 8: case 9: case 10: case 11:

                // 1111 10xx  10xx xxxx  10xx xxxx  10xx xxxx  10xx xxxx

                i+=4;

                out[j++] = '?';

                break;

                case 12: case 13:

                // 1111 110x  10xx xxxx  10xx xxxx  10xx xxxx  10xx xxxx  10xx xxxx

                i+=5;

                out[j++] = '?';

                break;

            }

        }

    }

    return out.join('');

}

var PHPSerializer = (function () {



    function freeEval(s) {

        return eval(s);

    }

    var prototypePropertyOfArray = function() {

        var result = {};

        for (var p in []) {

            result[p] = true;

        }

        return result;

    }();

    var prototypePropertyOfObject = function() {

        var result = {};

        for (var p in {}) {

            result[p] = true;

        }

        return result;

    }();



    return {

        serialize : function(o) {

            var p = 0, sb = [], ht = [], hv = 1;

            function getClassName(o) {

                if (typeof(o) == 'undefined' || typeof(o.constructor) == 'undefined') return '';

                var c = o.constructor.toString();

                c = c.substr(0, c.indexOf('(')).replace(/(^\s*function\s*)|(\s*$)/ig, '').toUTF8();

                return ((c == '') ? 'Object' : c);

            }

            function isInteger(n) {

                var i, s = n.toString(), l = s.length;

                if (l > 11) return false;

                for (i = (s.charAt(0) == '-') ? 1 : 0; i < l; i++) {

                    switch (s.charAt(i)) {

                        case '0':

                        case '1':

                        case '2':

                        case '3':

                        case '4':

                        case '5':

                        case '6':

                        case '7':

                        case '8':

                        case '9': break;

                        default : return false;

                    }

                }

                return !(n < -2147483648 || n > 2147483647);

            }

            function inHashTable(o) {

                for (var i = 0; i < ht.length; i++) if (ht[i] === o) return i;

                return false;

            }

            function serializeNull() {

                sb[p++] = 'N;';

            }

            function serializeBoolean(b) {

                sb[p++] = (b ? 'b:1;' : 'b:0;');

            }

            function serializeInteger(i) {

                sb[p++] = 'i:' + i + ';';

            }

            function serializeDouble(d) {

                if (isNaN(d)) d = 'NAN';

                else if (d == Number.POSITIVE_INFINITY) d = 'INF';

                else if (d == Number.NEGATIVE_INFINITY) d = '-INF';

                sb[p++] = 'd:' + d + ';';

            }

            function serializeString(s) {

                var utf8 = s.toUTF8();

                sb[p++] = 's:' + utf8.length + ':"';

                sb[p++] = utf8;

                sb[p++] = '";';

            }

            function serializeDate(dt) {

                sb[p++] = 'O:11:"PHPRPC_Date":7:{';

                sb[p++] = 's:4:"year";';

                serializeInteger(dt.getFullYear());

                sb[p++] = 's:5:"month";';

                serializeInteger(dt.getMonth() + 1);

                sb[p++] = 's:3:"day";';

                serializeInteger(dt.getDate());

                sb[p++] = 's:4:"hour";';

                serializeInteger(dt.getHours());

                sb[p++] = 's:6:"minute";';

                serializeInteger(dt.getMinutes());

                sb[p++] = 's:6:"second";';

                serializeInteger(dt.getSeconds());

                sb[p++] = 's:11:"millisecond";';

                serializeInteger(dt.getMilliseconds());

                sb[p++] = '}';

            }

            function serializeArray(a) {

                sb[p++] = 'a:';

                var k, lp = p;

                sb[p++] = 0;

                sb[p++] = ':{';

                for (k in a) {

                    if ((typeof(a[k]) != 'function') && !prototypePropertyOfArray[k]) {

                        isInteger(k) ? serializeInteger(k) : serializeString(k);

                        serialize(a[k]);

                        sb[lp]++;

                    }

                }

                sb[p++] = '}';

            }

            function serializeObject(o) {

                var cn = getClassName(o);

                if (cn == '') serializeNull();

                else if (typeof(o.serialize) != 'function') {

                    sb[p++] = 'O:' + cn.length + ':"' + cn + '":';

                    var lp = p;

                    sb[p++] = 0;

                    sb[p++] = ':{';

                    var k;

                    if (typeof(o.__sleep) == 'function') {

                        var a = o.__sleep();

                        for (k in a) {

                            serializeString(a[k]);

                            serialize(o[a[k]]);

                            sb[lp]++;

                        }

                    }

                    else {

                        for (k in o) {

                            if (typeof(o[k]) != 'function' && !prototypePropertyOfObject[k]) {

                                serializeString(k);

                                serialize(o[k]);

                                sb[lp]++;

                            }

                        }

                    }

                    sb[p++] = '}';

                }

                else {

                    var cs = o.serialize();

                    sb[p++] = 'C:' + cn.length + ':"' + cn + '":' + cs.length + ':{' +cs + '}';

                }

            }

            function serializePointRef(R) {

                sb[p++] = 'R:' + R + ';';

            }

            function serializeRef(r) {

                sb[p++] = 'r:' + r + ';';

            }

            function serialize(o) {

                if (typeof(o) == "undefined" || o == null ||

                    o.constructor == Function) {

                    hv++;

                    serializeNull();

                    return;

                }

                var className = getClassName(o);

                switch (o.constructor) {

                    case Boolean: {

                        hv++;

                        serializeBoolean(o);

                        break;

                    }

                    case Number: {

                        hv++;

                        isInteger(o) ? serializeInteger(o) : serializeDouble(o);

                        break;

                    }

                    case String: {

                        hv++;

                        serializeString(o);

                        break;

                    }

                    case Date: {

                        hv += 8;

                        serializeDate(o);

                        break;

                    }

                    default: {

                        if (className == "Object" || o.constructor == Array) {

                            var r = inHashTable(o);

                            if (r) {

                                serializePointRef(r);

                            }

                            else {

                                ht[hv++] = o;

                                serializeArray(o);

                            }

                            break;

                        }

                        else {

                            var r = inHashTable(o);

                            if (r) {

                                hv++;

                                serializeRef(r);

                            }

                            else {

                                ht[hv++] = o;

                                serializeObject(o);

                            }

                        }

                    }

                }

            }

            serialize(o);

            return sb.join('');

        },

        unserialize : function(ss) {

            var p = 0, ht = [], hv = 1;

            function unserializeNull() {

                p++;

                return null;

            }

            function unserializeBoolean() {

                p++;

                var b = (ss.charAt(p++) == '1');

                p++;

                return b;

            }

            function unserializeInteger() {

                p++;

                var i = parseInt(ss.substring(p, p = ss.indexOf(';', p)));

                p++;

                return i;

            }

            function unserializeDouble() {

                p++;

                var d = ss.substring(p, p = ss.indexOf(';', p));

                switch (d) {

                    case 'NAN': d = NaN; break;

                    case 'INF': d = Number.POSITIVE_INFINITY; break;

                    case '-INF': d = Number.NEGATIVE_INFINITY; break;

                    default: d = parseFloat(d);

                }

                p++;

                return d;

            }

            function unserializeString() {

                p++;

                var l = parseInt(ss.substring(p, p = ss.indexOf(':', p)));

                p += 2;

                var s = ss.substring(p, p += l).toUTF16();

                p += 2;

                return s;

            }

            function unserializeEscapedString(len) {

                p++;

                var l = parseInt(ss.substring(p, p = ss.indexOf(':', p)));

                p += 2;

                var i, sb = new Array(l);

                for (i = 0; i < l; i++) {

                    if ((sb[i] = ss.charAt(p++)) == '\\') {

                        sb[i] = String.fromCharCode(parseInt(ss.substring(p, p += len), 16));

                    }

                }

                p += 2;

                return sb.join('');

            }

            function unserializeArray() {

                p++;

                var n = parseInt(ss.substring(p, p = ss.indexOf(':', p)));

                p += 2;

                var i, k, a = [];

                ht[hv++] = a;

                for (i = 0; i < n; i++) {

                    switch (ss.charAt(p++)) {

                        case 'i': k = unserializeInteger(); break;

                        case 's': k = unserializeString(); break;

                        case 'S': k = unserializeEscapedString(2); break;

                        case 'U': k = unserializeEscapedString(4); break;

                        default: return false;

                    }

                    a[k] = unserialize();

                }

                p++;

                return a;

            }

            function unserializeDate(n) {

                var i, k, a = {};

                for (i = 0; i < n; i++) {

                    switch (ss.charAt(p++)) {

                        case 's': k = unserializeString(); break;

                        case 'S': k = unserializeEscapedString(2); break;

                        case 'U': k = unserializeEscapedString(4); break;

                        default: return false;

                    }

                    if (ss.charAt(p++) == 'i') {

                        a[k] = unserializeInteger();

                    }

                    else {

                        return false;

                    }

                }

                p++;

                var dt = new Date(

                    a.year,

                    a.month - 1,

                    a.day,

                    a.hour,

                    a.minute,

                    a.second,

                    a.millisecond

                );

                ht[hv++] = dt;

                ht[hv++] = a.year;

                ht[hv++] = a.month;

                ht[hv++] = a.day;

                ht[hv++] = a.hour;

                ht[hv++] = a.minute;

                ht[hv++] = a.second;

                ht[hv++] = a.millisecond;

                return dt;

            }

            function unserializeObject() {

                p++;

                var l = parseInt(ss.substring(p, p = ss.indexOf(':', p)));

                p += 2;

                var cn = ss.substring(p, p += l).toUTF16();

                p += 2;

                var n = parseInt(ss.substring(p, p = ss.indexOf(':', p)));

                p += 2;

                if (cn == "PHPRPC_Date") {

                    return unserializeDate(n);

                }

                var i, k, o = createObjectOfClass(cn);

                ht[hv++] = o;

                for (i = 0; i < n; i++) {

                    switch (ss.charAt(p++)) {

                        case 's': k = unserializeString(); break;

                        case 'S': k = unserializeEscapedString(2); break;

                        case 'U': k = unserializeEscapedString(4); break;

                        default: return false;

                    }

                    if (k.charAt(0) == '\0') {

                        k = k.substring(k.indexOf('\0', 1) + 1, k.length);

                    }

                    o[k] = unserialize();

                }

                p++;

                if (typeof(o.__wakeup) == 'function') o.__wakeup();

                return o;

            }

            function unserializeCustomObject() {

                p++;

                var l = parseInt(ss.substring(p, p = ss.indexOf(':', p)));

                p += 2;

                var cn = ss.substring(p, p += l).toUTF16();

                p += 2;

                var n = parseInt(ss.substring(p, p = ss.indexOf(':', p)));

                p += 2;

                var o = createObjectOfClass(cn);

                ht[hv++] = o;

                if (typeof(o.unserialize) != 'function') p += n;

                else o.unserialize(ss.substring(p, p += n));

                p++;

                return o;

            }

            function unserializeRef() {

                p++;

                var r = parseInt(ss.substring(p, p = ss.indexOf(';', p)));

                p++;

                return ht[r];

            }

            function getObjectOfClass(cn, poslist, i, c) {

                if (i < poslist.length) {

                    var pos = poslist[i];

                    cn[pos] = c;

                    var obj = getObjectOfClass(cn, poslist, i + 1, '.');

                    if (i + 1 < poslist.length) {

                        if (obj == null) {

                            obj = getObjectOfClass(cn, poslist, i + 1, '_');

                        }

                    }

                    return obj;

                }

                var classname = cn.join('');

                try {

                    return freeEval('new ' + classname + '()');

                }

                catch (e) {

                    return null;

                }

            }

            function createObjectOfClass(classname) {

                if (freeEval('typeof(' + classname + ') == "function"')) {

                    return freeEval('new ' + classname + '()');

                }

                var poslist = [];

                var pos = classname.indexOf("_");

                while (pos > -1) {

                    poslist[poslist.length] = pos;

                    pos = classname.indexOf("_", pos + 1);

                }

                if (poslist.length > 0) {

                    var cn = classname.split('');

                    var obj = getObjectOfClass(cn, poslist, 0, '.');

                    if (obj == null) {

                        obj = getObjectOfClass(cn, poslist, 0, '_');

                    }

                    if (obj != null) {

                        return obj;

                    }

                }

                return freeEval('new function ' + classname + '(){};');

            }

            function unserialize() {

                switch (ss.charAt(p++)) {

                    case 'N': return ht[hv++] = unserializeNull();

                    case 'b': return ht[hv++] = unserializeBoolean();

                    case 'i': return ht[hv++] = unserializeInteger();

                    case 'd': return ht[hv++] = unserializeDouble();

                    case 's': return ht[hv++] = unserializeString();

                    case 'S': return ht[hv++] = unserializeEscapedString(2);

                    case 'U': return ht[hv++] = unserializeEscapedString(4);

                    case 'r': return ht[hv++] = unserializeRef();

                    case 'a': return unserializeArray();

                    case 'O': return unserializeObject();

                    case 'C': return unserializeCustomObject();

                    case 'R': return unserializeRef();

                    default: return false;

                }

            }

            return unserialize();

        }

    }

})();
/**
 * k.Growler 1.0.0
 *
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * Written by Kevin Armstrong <kevin@kevinandre.com>
 * Last updated: 2008.10.14
 *
 * Growler is a PrototypeJS based class that displays unobtrusive notices on a page. 
 * It functions much like the Growl (http://growl.info) available on the Mac OS X. 
 *
 * Changes in 1.0.1:
 * - 
 *
 * @todo
 */
window.k = window.k || {};
;(function(){

var noticeOptions = {
	header: 			'&nbsp;'
	,speedin: 			0.3
	,speedout: 			0.5
	,outDirection: 		{ y: -20 }
	,life: 				5
	,sticky: 			false
	,className: 		""
};
var growlerOptions = {
	location: 			"tr"
	,width: 			"250px"
};
var IE = (Prototype.Browser.IE) ? parseFloat(navigator.appVersion.split("MSIE ")[1]) || 0 : 0;
function removeNotice(n, o){
	o = o || noticeOptions;
	new Effect.Parallel([
		new Effect.Move(n, Object.extend({ sync: true, mode: 'relative' }, o.outDirection)),
		new Effect.Opacity(n, { sync: true, to: 0 }) 
	], {
		duration: o.speedout
		,afterFinish: function(){
			try {
				var ne = n.down("div.notice-exit");
				if(ne != undefined){
					ne.stopObserving("click", removeNotice);
				}
				if(o.created && Object.isFunction(o.created)){
					n.stopObserving("notice:created", o.created);
				}
				if(o.destroyed && Object.isFunction(o.destroyed)){
					n.fire("notice:destroyed");
					n.stopObserving("notice:destroyed", o.destroyed);
				}
			} catch(e){}
			try {
				n.remove();
			} catch(e){}
		}
	});
}
function createNotice(growler, msg, options){
	var opt = Object.clone(noticeOptions);
	options = options || {};
	Object.extend(opt, options);
	var notice;
	if (opt.className != ""){
		notice = new Element("div", {"class": opt.className}).setStyle({display: "block", opacity: 0});
	} else {
		notice = new Element("div", {"class": "Growler-notice"}).setStyle({display: "block", opacity: 0});
	}
	if(opt.created && Object.isFunction(opt.created)){
		notice.observe("notice:created", opt.created);
	}
	if(opt.destroyed && Object.isFunction(opt.destroyed)){
		notice.observe("notice:destroyed", opt.destroyed);
	}
	if (opt.sticky){
		var noticeExit = new Element("div", {"class": "Growler-notice-exit"}).update("&times;");
		noticeExit.observe("click", function(){ removeNotice(notice, opt); });
		notice.insert(noticeExit);
	}
	notice.insert(new Element("div", {"class": "Growler-notice-head"}).update(opt.header));
	notice.insert(new Element("div", {"class": "Growler-notice-body"}).update(msg));
	growler.insert(notice);
	new Effect.Opacity(notice, { to: 0.85, duration: opt.speedin });
	if (!opt.sticky){
		removeNotice.delay(opt.life, notice, opt);
	}
	notice.fire("notice:created");
	return notice;
}
function specialNotice(g, m, o, t, b, c){
	o.header = o.header || t;
	var n = createNotice(g, m, o);
	n.setStyle({ backgroundColor: b, color: c });
	return n;
}
k.Growler = Class.create({
	initialize: function(options){
		var opt = Object.clone(growlerOptions);
		options = options || {};
		Object.extend(opt, options);
		this.growler = new Element("div", { "class": "Growler", "id": "Growler" });
		this.growler.setStyle({ position: ((IE==6)?"absolute":"fixed"), padding: "10px", "width": opt.width, "z-index": "50000" });
		if(IE==6){
			var offset = { w: parseInt(this.growler.style.width)+parseInt(this.growler.style.padding)*3, h: parseInt(this.growler.style.height)+parseInt(this.growler.style.padding)*3 };
			switch(opt.location){
				case "br":
					this.growler.style.setExpression("left", "( 0 - Growler.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px'");
				  	this.growler.style.setExpression("top", "( 0 - Growler.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px'");
					break;
				case "tl":
					this.growler.style.setExpression("left", "( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px'");
				  	this.growler.style.setExpression("top", "( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px'");
					break;
				case "bl":
					this.growler.style.setExpression("left", "( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px'");
				  	this.growler.style.setExpression("top", "( 0 - Growler.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px'");
					break;
				default:
					this.growler.setStyle({right: "auto", bottom: "auto"});
					this.growler.style.setExpression("left", "( 0 - Growler.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px'");
				  	this.growler.style.setExpression("top", "( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px'");
					break;
			}
		} else {
			switch(opt.location){
				case "br":
					this.growler.setStyle({bottom: 0, right: 0});
					break;
				case "tl":
					this.growler.setStyle({top: 0, left: 0});
					break;
				case "bl":
					this.growler.setStyle({top: 0, right: 0});
					break;
				case "tc":
					this.growler.setStyle({top: 0, left: "25%", width: "50%"});
					break;
				case "bc":
					this.growler.setStyle({bottom: 0, left: "25%", width: "50%"});
					break;
				default:
					this.growler.setStyle({top: 0, right: 0});
					break;
			}
		}
		this.growler.wrap( document.body );		
	}
	,growl: function(msg, options) {
		return createNotice(this.growler, msg, options);
	}
	,warn: function(msg, options){
		return specialNotice(this.growler, msg, options, "Warning!", "#F6BD6F", "#000");
	}
	,error: function(msg, options){
		return specialNotice(this.growler, msg, options, "Critical!", "#F66F82", "#000");
	}
	,info: function(msg, options){
		return specialNotice(this.growler, msg, options, "Information!", "#BBF66F", "#000");
	}
	,ungrowl: function(n, o){
		removeNotice(n, o);
	}
});

})();

/**
 * @author Ryan Johnson <http://syntacticx.com/>
 * @copyright 2008 PersonalGrid Corporation <http://personalgrid.com/>
 * @package LivePipe UI
 * @license MIT
 * @url http://livepipe.net/core
 * @require prototype.js
 */

if(typeof(Control) == 'undefined')
    Control = {};
    
var $proc = function(proc){
    return typeof(proc) == 'function' ? proc : function(){return proc};
};

var $value = function(value){
    return typeof(value) == 'function' ? value() : value;
};

Object.Event = {
    extend: function(object){
        object._objectEventSetup = function(event_name){
            this._observers = this._observers || {};
            this._observers[event_name] = this._observers[event_name] || [];
        };
        object.observe = function(event_name,observer){
            if(typeof(event_name) == 'string' && typeof(observer) != 'undefined'){
                this._objectEventSetup(event_name);
                if(!this._observers[event_name].include(observer))
                    this._observers[event_name].push(observer);
            }else
                for(var e in event_name)
                    this.observe(e,event_name[e]);
        };
        object.stopObserving = function(event_name,observer){
            this._objectEventSetup(event_name);
            if(event_name && observer)
                this._observers[event_name] = this._observers[event_name].without(observer);
            else if(event_name)
                this._observers[event_name] = [];
            else
                this._observers = {};
        };
        object.observeOnce = function(event_name,outer_observer){
            var inner_observer = function(){
                outer_observer.apply(this,arguments);
                this.stopObserving(event_name,inner_observer);
            }.bind(this);
            this._objectEventSetup(event_name);
            this._observers[event_name].push(inner_observer);
        };
        object.notify = function(event_name){
            this._objectEventSetup(event_name);
            var collected_return_values = [];
            var args = $A(arguments).slice(1);
            try{
                for(var i = 0; i < this._observers[event_name].length; ++i)
                    collected_return_values.push(this._observers[event_name][i].apply(this._observers[event_name][i],args) || null);
            }catch(e){
                if(e == $break)
                    return false;
                else
                    throw e;
            }
            return collected_return_values;
        };
        if(object.prototype){
            object.prototype._objectEventSetup = object._objectEventSetup;
            object.prototype.observe = object.observe;
            object.prototype.stopObserving = object.stopObserving;
            object.prototype.observeOnce = object.observeOnce;
            object.prototype.notify = function(event_name){
                if(object.notify){
                    var args = $A(arguments).slice(1);
                    args.unshift(this);
                    args.unshift(event_name);
                    object.notify.apply(object,args);
                }
                this._objectEventSetup(event_name);
                var args = $A(arguments).slice(1);
                var collected_return_values = [];
                try{
                    if(this.options && this.options[event_name] && typeof(this.options[event_name]) == 'function')
                        collected_return_values.push(this.options[event_name].apply(this,args) || null);
                    for(var i = 0; i < this._observers[event_name].length; ++i)
                        collected_return_values.push(this._observers[event_name][i].apply(this._observers[event_name][i],args) || null);
                }catch(e){
                    if(e == $break)
                        return false;
                    else
                        throw e;
                }
                return collected_return_values;
            };
        }
    }
};

/* Begin Core Extensions */

//Element.observeOnce
Element.addMethods({
    observeOnce: function(element,event_name,outer_callback){
        var inner_callback = function(){
            outer_callback.apply(this,arguments);
            Element.stopObserving(element,event_name,inner_callback);
        };
        Element.observe(element,event_name,inner_callback);
    }
});

//mouseenter, mouseleave
//from http://dev.rubyonrails.org/attachment/ticket/8354/event_mouseenter_106rc1.patch
Object.extend(Event, (function() {
    var cache = Event.cache;

    function getEventID(element) {
        if (element._prototypeEventID) return element._prototypeEventID[0];
        arguments.callee.id = arguments.callee.id || 1;
        return element._prototypeEventID = [++arguments.callee.id];
    }

    function getDOMEventName(eventName) {
        if (eventName && eventName.include(':')) return "dataavailable";
        //begin extension
        if(!Prototype.Browser.IE){
            eventName = {
                mouseenter: 'mouseover',
                mouseleave: 'mouseout'
            }[eventName] || eventName;
        }
        //end extension
        return eventName;
    }

    function getCacheForID(id) {
        return cache[id] = cache[id] || { };
    }

    function getWrappersForEventName(id, eventName) {
        var c = getCacheForID(id);
        return c[eventName] = c[eventName] || [];
    }

    function createWrapper(element, eventName, handler) {
        var id = getEventID(element);
        var c = getWrappersForEventName(id, eventName);
        if (c.pluck("handler").include(handler)) return false;

        var wrapper = function(event) {
            if (!Event || !Event.extend ||
                (event.eventName && event.eventName != eventName))
                    return false;

            Event.extend(event);
            handler.call(element, event);
        };
        
        //begin extension
        if(!(Prototype.Browser.IE) && ['mouseenter','mouseleave'].include(eventName)){
            wrapper = wrapper.wrap(function(proceed,event) {    
                var rel = event.relatedTarget;
                var cur = event.currentTarget;             
                if(rel && rel.nodeType == Node.TEXT_NODE)
                    rel = rel.parentNode;      
                if(rel && rel != cur && !rel.descendantOf(cur))      
                    return proceed(event);   
            });     
        }
        //end extension

        wrapper.handler = handler;
        c.push(wrapper);
        return wrapper;
    }

    function findWrapper(id, eventName, handler) {
        var c = getWrappersForEventName(id, eventName);
        return c.find(function(wrapper) { return wrapper.handler == handler });
    }

    function destroyWrapper(id, eventName, handler) {
        var c = getCacheForID(id);
        if (!c[eventName]) return false;
        c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
    }

    function destroyCache() {
        for (var id in cache)
            for (var eventName in cache[id])
                cache[id][eventName] = null;
    }

    if (window.attachEvent) {
        window.attachEvent("onunload", destroyCache);
    }

    return {
        observe: function(element, eventName, handler) {
            element = $(element);
            var name = getDOMEventName(eventName);

            var wrapper = createWrapper(element, eventName, handler);
            if (!wrapper) return element;

            if (element.addEventListener) {
                element.addEventListener(name, wrapper, false);
            } else {
                element.attachEvent("on" + name, wrapper);
            }

            return element;
        },

        stopObserving: function(element, eventName, handler) {
            element = $(element);
            var id = getEventID(element), name = getDOMEventName(eventName);

            if (!handler && eventName) {
                getWrappersForEventName(id, eventName).each(function(wrapper) {
                    element.stopObserving(eventName, wrapper.handler);
                });
                return element;

            } else if (!eventName) {
                //Object.keys(getCacheForID(id)).each(function(eventName) {
                //    element.stopObserving(eventName);
                //});
                return element;
            }

            var wrapper = findWrapper(id, eventName, handler);
            if (!wrapper) return element;

            if (element.removeEventListener) {
                element.removeEventListener(name, wrapper, false);
            } else {
                element.detachEvent("on" + name, wrapper);
            }

            destroyWrapper(id, eventName, handler);

            return element;
        },

        fire: function(element, eventName, memo) {
            element = $(element);
            if (element == document && document.createEvent && !element.dispatchEvent)
                element = document.documentElement;

            var event;
            if (document.createEvent) {
                event = document.createEvent("HTMLEvents");
                event.initEvent("dataavailable", true, true);
            } else {
                event = document.createEventObject();
                event.eventType = "ondataavailable";
            }

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

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

            return Event.extend(event);
        }
    };
})());

Object.extend(Event, Event.Methods);

Element.addMethods({
    fire:            Event.fire,
    observe:        Event.observe,
    stopObserving:    Event.stopObserving
});

Object.extend(document, {
    fire:            Element.Methods.fire.methodize(),
    observe:        Element.Methods.observe.methodize(),
    stopObserving:    Element.Methods.stopObserving.methodize()
});

//mouse:wheel
(function(){
    function wheel(event){
        var delta;
        // normalize the delta
        if(event.wheelDelta) // IE & Opera
            delta = event.wheelDelta / 120;
        else if (event.detail) // W3C
            delta =- event.detail / 3;
        if(!delta)
            return;
        var custom_event = Event.element(event).fire('mouse:wheel',{
            delta: delta
        });
        if(custom_event.stopped){
            Event.stop(event);
            return false;
        }
    }
    document.observe('mousewheel',wheel);
    document.observe('DOMMouseScroll',wheel);
})();

/* End Core Extensions */

//from PrototypeUI
var IframeShim = Class.create({
    initialize: function() {
        this.element = new Element('iframe',{
            style: 'position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);display:none',
            src: 'javascript:void(0);',
            frameborder: 0 
        });
        $(document.body).insert(this.element);
    },
    hide: function() {
        this.element.hide();
        return this;
    },
    show: function() {
        this.element.show();
        return this;
    },
    positionUnder: function(element) {
        var element = $(element);
        var offset = element.cumulativeOffset();
        var dimensions = element.getDimensions();
        this.element.setStyle({
            left: offset[0] + 'px',
            top: offset[1] + 'px',
            width: dimensions.width + 'px',
            height: dimensions.height + 'px',
            zIndex: element.getStyle('zIndex') - 1
        }).show();
        return this;
    },
    setBounds: function(bounds) {
        for(prop in bounds)
            bounds[prop] += 'px';
        this.element.setStyle(bounds);
        return this;
    },
    destroy: function() {
        if(this.element)
            this.element.remove();
        return this;
    }
});

/**
 * @author Ryan Johnson <http://syntacticx.com/>
 * @copyright 2008 PersonalGrid Corporation <http://personalgrid.com/>
 * @package LivePipe UI
 * @license MIT
 * @url http://livepipe.net/control/tabs
 * @require prototype.js, livepipe.js
 */

/*global window, document, Prototype, $, $A, $H, $break, Class, Element, Event, Control */

if(typeof(Prototype) == "undefined") {
    throw "Control.Tabs requires Prototype to be loaded."; }
if(typeof(Object.Event) == "undefined") {
    throw "Control.Tabs requires Object.Event to be loaded."; }

Control.Tabs = Class.create({
    initialize: function(tab_list_container,options){
        if(!$(tab_list_container)) {
            throw "Control.Tabs could not find the element: " + tab_list_container; }
        this.activeContainer = false;
        this.activeLink = false;
        this.containers = $H({});
        this.links = [];
        Control.Tabs.instances.push(this);
        this.options = {
            beforeChange: Prototype.emptyFunction,
            afterChange: Prototype.emptyFunction,
            hover: false,
            linkSelector: 'li a',
            setClassOnContainer: false,
            activeClassName: 'active',
            defaultTab: 'first',
            autoLinkExternal: true,
            targetRegExp: /#(.+)$/,
            showFunction: Element.show,
            hideFunction: Element.hide
        };
        Object.extend(this.options,options || {});
        (typeof(this.options.linkSelector == 'string') ? 
            $(tab_list_container).select(this.options.linkSelector) : 
            this.options.linkSelector($(tab_list_container))
        ).findAll(function(link){
            return (/^#/).exec((Prototype.Browser.WebKit ? decodeURIComponent(link.href) : link.href).replace(window.location.href.split('#')[0],''));
        }).each(function(link){
            this.addTab(link);
        }.bind(this));
        this.containers.values().each(Element.hide);
        if(this.options.defaultTab == 'first') {
            this.setActiveTab(this.links.first());
        } else if(this.options.defaultTab == 'last') {
            this.setActiveTab(this.links.last());
        } else {
            this.setActiveTab(this.options.defaultTab); }
        var targets = this.options.targetRegExp.exec(window.location);
        if(targets && targets[1]){
            targets[1].split(',').each(function(target){
                this.setActiveTab(this.links.find(function(link){
                    return link.key == target;
                }));
            }.bind(this));
        }
        if(this.options.autoLinkExternal){
            $A(document.getElementsByTagName('a')).each(function(a){
                if(!this.links.include(a)){
                    var clean_href = a.href.replace(window.location.href.split('#')[0],'');
                    if(clean_href.substring(0,1) == '#'){
                        if(this.containers.keys().include(clean_href.substring(1))){
                            $(a).observe('click',function(event,clean_href){
                                this.setActiveTab(clean_href.substring(1));
                            }.bindAsEventListener(this,clean_href));
                        }
                    }
                }
            }.bind(this));
        }
    },
    addTab: function(link){
        this.links.push(link);
        link.key = link.getAttribute('href').replace(window.location.href.split('#')[0],'').split('#').last().replace(/#/,'');
        var container = $(link.key);
        if(!container) {
            throw "Control.Tabs: #" + link.key + " was not found on the page."; }
        this.containers.set(link.key,container);
        link[this.options.hover ? 'onmouseover' : 'onclick'] = function(link){
            if(window.event) {
                Event.stop(window.event); }
            this.setActiveTab(link);
            return false;
        }.bind(this,link);
    },
    setActiveTab: function(link){
        if(!link && typeof(link) == 'undefined') {
            return; }
        if(typeof(link) == 'string'){
            this.setActiveTab(this.links.find(function(_link){
                return _link.key == link;
            }));
        }else if(typeof(link) == 'number'){
            this.setActiveTab(this.links[link]);
        }else{
            if(this.notify('beforeChange',this.activeContainer,this.containers.get(link.key)) === false) {
                return; }
            if(this.activeContainer) {
                this.options.hideFunction(this.activeContainer); }
            this.links.each(function(item){
                (this.options.setClassOnContainer ? $(item.parentNode) : item).removeClassName(this.options.activeClassName);
            }.bind(this));
            (this.options.setClassOnContainer ? $(link.parentNode) : link).addClassName(this.options.activeClassName);
            this.activeContainer = this.containers.get(link.key);
            this.activeLink = link;
            this.options.showFunction(this.containers.get(link.key));
            this.notify('afterChange',this.containers.get(link.key));
        }
    },
    next: function(){
        this.links.each(function(link,i){
            if(this.activeLink == link && this.links[i + 1]){
                this.setActiveTab(this.links[i + 1]);
                throw $break;
            }
        }.bind(this));
    },
    previous: function(){
        this.links.each(function(link,i){
            if(this.activeLink == link && this.links[i - 1]){
                this.setActiveTab(this.links[i - 1]);
                throw $break;
            }
        }.bind(this));
    },
    first: function(){
        this.setActiveTab(this.links.first());
    },
    last: function(){
        this.setActiveTab(this.links.last());
    }
});
Object.extend(Control.Tabs,{
    instances: [],
    findByTabId: function(id){
        return Control.Tabs.instances.find(function(tab){
            return tab.links.find(function(link){
                return link.key == id;
            });
        });
    }
});
Object.Event.extend(Control.Tabs);

/**
 * @author Ryan Johnson <http://syntacticx.com/>
 * @copyright 2008 PersonalGrid Corporation <http://personalgrid.com/>
 * @package LivePipe UI
 * @license MIT
 * @url http://livepipe.net/control/window
 * @require prototype.js, effects.js, draggable.js, resizable.js, livepipe.js
 */

//adds onDraw and constrainToViewport option to draggable
if(typeof(Draggable) != 'undefined'){
    //allows the point to be modified with an onDraw callback
    Draggable.prototype.draw = function(point) {
        var pos = Position.cumulativeOffset(this.element);
        if(this.options.ghosting) {
            var r = Position.realOffset(this.element);
            pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
        }
        
        var d = this.currentDelta();
        pos[0] -= d[0]; pos[1] -= d[1];
        
        if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
            pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
            pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
        }
        
        var p = [0,1].map(function(i){ 
            return (point[i]-pos[i]-this.offset[i]) 
        }.bind(this));
        
        if(this.options.snap) {
            if(typeof this.options.snap == 'function') {
                p = this.options.snap(p[0],p[1],this);
            } else {
                if(this.options.snap instanceof Array) {
                    p = p.map( function(v, i) {return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this))
                } else {
                    p = p.map( function(v) {return Math.round(v/this.options.snap)*this.options.snap }.bind(this))
                  }
            }
        }
        
        if(this.options.onDraw)
            this.options.onDraw.bind(this)(p);
        else{
            var style = this.element.style;
            if(this.options.constrainToViewport){
                var viewport_dimensions = document.viewport.getDimensions();
                var container_dimensions = this.element.getDimensions();
                var margin_top = parseInt(this.element.getStyle('margin-top'));
                var margin_left = parseInt(this.element.getStyle('margin-left'));
                var boundary = [[
                    0 - margin_left,
                    0 - margin_top
                ],[
                    (viewport_dimensions.width - container_dimensions.width) - margin_left,
                    (viewport_dimensions.height - container_dimensions.height) - margin_top
                ]];
                if((!this.options.constraint) || (this.options.constraint=='horizontal')){ 
                    if((p[0] >= boundary[0][0]) && (p[0] <= boundary[1][0]))
                        this.element.style.left = p[0] + "px";
                    else
                        this.element.style.left = ((p[0] < boundary[0][0]) ? boundary[0][0] : boundary[1][0]) + "px";
                } 
                if((!this.options.constraint) || (this.options.constraint=='vertical')){ 
                    if((p[1] >= boundary[0][1] ) && (p[1] <= boundary[1][1]))
                        this.element.style.top = p[1] + "px";
                  else
                        this.element.style.top = ((p[1] <= boundary[0][1]) ? boundary[0][1] : boundary[1][1]) + "px";               
                }
            }else{
                if((!this.options.constraint) || (this.options.constraint=='horizontal'))
                  style.left = p[0] + "px";
                if((!this.options.constraint) || (this.options.constraint=='vertical'))
                  style.top     = p[1] + "px";
            }
            if(style.visibility=="hidden")
                style.visibility = ""; // fix gecko rendering
        }
    };
}

if(typeof(Prototype) == "undefined")
    throw "Control.Window requires Prototype to be loaded.";
if(typeof(IframeShim) == "undefined")
    throw "Control.Window requires IframeShim to be loaded.";
if(typeof(Object.Event) == "undefined")
    throw "Control.Window requires Object.Event to be loaded.";
/*
    known issues:
        - when iframe is clicked is does not gain focus
        - safari can't open multiple iframes properly
        - constrainToViewport: body must have no margin or padding for this to work properly
        - iframe will be mis positioned during fade in
        - document.viewport does not account for scrollbars (this will eventually be fixed in the prototype core)
    notes
        - setting constrainToViewport only works when the page is not scrollable
        - setting draggable: true will negate the effects of position: center
*/
Control.Window = Class.create({
    initialize: function(container,options){
        Control.Window.windows.push(this);
        
        //attribute initialization
        this.container = false;
        this.isOpen = false;
        this.href = false;
        this.sourceContainer = false; //this is optionally the container that will open the window
        this.ajaxRequest = false;
        this.remoteContentLoaded = false; //this is set when the code to load the remote content is run, onRemoteContentLoaded is fired when the connection is closed
        this.numberInSequence = Control.Window.windows.length + 1; //only useful for the effect scoping
        this.indicator = false;
        this.effects = {
            fade: true,
            appear: true
        };
        this.indicatorEffects = {
            fade: false,
            appear: false
        };
        
        //options
        this.options = Object.extend({
            //lifecycle
            beforeOpen: Prototype.emptyFunction,
            afterOpen: Prototype.emptyFunction,
            beforeClose: Prototype.emptyFunction,
            afterClose: Prototype.emptyFunction,
            //dimensions and modes
            height: null,
            width: null,
            className: false,
            position: 'center', //'center', 'relative', [x,y], [function(){return x;},function(){return y;}]
            offsetLeft: 0, //available only for anchors opening the window, or windows set to position: hover
            offsetTop: 0, //""
            iframe: false, //if the window has an href, this will display the href as an iframe instead of requesting the url as an an Ajax.Request
            hover: false, //element object to hover over, or if "true" only available for windows with sourceContainer (an anchor or any element already on the page with an href attribute)
            indicator: false, //element to show or hide when ajax requests, images and iframes are loading
            closeOnClick: false, //does not work with hover,can be: true (click anywhere), 'container' (will refer to this.container), or element (a specific element)
            iframeshim: true, //whether or not to position an iFrameShim underneath the window 
            //effects
            fade: false,
            fadeDuration: 0.75,
            //draggable
            draggable: false,
            onDrag: Prototype.emptyFunction,
            //resizable
            resizable: false,
            minHeight: false,
            minWidth: false,
            maxHeight: false,
            maxWidth: false,
            onResize: Prototype.emptyFunction,
            //draggable and resizable
            constrainToViewport: false,
            //ajax
            method: 'post',
            parameters: {},
            onComplete: Prototype.emptyFunction,
            onSuccess: Prototype.emptyFunction,
            onFailure: Prototype.emptyFunction,
            onException: Prototype.emptyFunction,
            //any element with an href (image,iframe,ajax) will call this after it is done loading
            onRemoteContentLoaded: Prototype.emptyFunction,
            insertRemoteContentAt: false //false will set this to this.container, can be string selector (first returned will be selected), or an Element that must be a child of this.container
        },options || {});
        
        //container setup
        this.indicator = this.options.indicator ? $(this.options.indicator) : false;
        if(container){
            if(typeof(container) == "string" && container.match(Control.Window.uriRegex))
                this.href = container;
            else{
                this.container = $(container);
                //need to create the container now for tooltips (or hover: element with no container already on the page)
                //second call made below will not create the container since the check is done inside createDefaultContainer()
                this.createDefaultContainer(container);
                //if an element with an href was passed in we use it to activate the window
                if(this.container && ((this.container.readAttribute('href') && this.container.readAttribute('href') != '') || (this.options.hover && this.options.hover !== true))){                        
                    if(this.options.hover && this.options.hover !== true)
                        this.sourceContainer = $(this.options.hover);
                    else{
                        this.sourceContainer = this.container;
                        this.href = this.container.readAttribute('href');
                        var rel = this.href.match(/^#(.+)$/);
                        if(rel && rel[1]){
                            this.container = $(rel[1]);
                            this.href = false;
                        }else
                            this.container = false;
                    }
                    //hover or click handling
                    this.sourceContainerOpenHandler = function(event){
                        this.open(event);
                        event.stop();
                        return false;
                    }.bindAsEventListener(this);
                    this.sourceContainerCloseHandler = function(event){
                        this.close(event);
                    }.bindAsEventListener(this);
                    this.sourceContainerMouseMoveHandler = function(event){
                        this.position(event);
                    }.bindAsEventListener(this);
                    if(this.options.hover){
                        this.sourceContainer.observe('mouseenter',this.sourceContainerOpenHandler);
                        this.sourceContainer.observe('mouseleave',this.sourceContainerCloseHandler);
                        if(this.options.position == 'mouse')
                            this.sourceContainer.observe('mousemove',this.sourceContainerMouseMoveHandler);
                    }else
                        this.sourceContainer.observe('click',this.sourceContainerOpenHandler);
                }
            }
        }
        this.createDefaultContainer(container);
        if(this.options.insertRemoteContentAt === false)
            this.options.insertRemoteContentAt = this.container;
        var styles = {
            margin: 0,
            position: 'absolute',
            zIndex: Control.Window.initialZIndexForWindow()
        };
        if(this.options.width)
            styles.width = $value(this.options.width) + 'px';
        if(this.options.height)
            styles.height = $value(this.options.height) + 'px';
        this.container.setStyle(styles);
        if(this.options.className)
            this.container.addClassName(this.options.className);
        this.positionHandler = this.position.bindAsEventListener(this);
        this.outOfBoundsPositionHandler = this.ensureInBounds.bindAsEventListener(this);
        this.bringToFrontHandler = this.bringToFront.bindAsEventListener(this);
        this.container.observe('mousedown',this.bringToFrontHandler);
        this.container.hide();
        this.closeHandler = this.close.bindAsEventListener(this);
        //iframeshim setup
        if(this.options.iframeshim){
            this.iFrameShim = new IframeShim();
            this.iFrameShim.hide();
        }
        //resizable support
        this.applyResizable();
        //draggable support
        this.applyDraggable();
        
        //makes sure the window can't go out of bounds
        Event.observe(window,'resize',this.outOfBoundsPositionHandler);
        
        this.notify('afterInitialize');
    },
    open: function(event){
        if(this.isOpen){
            this.bringToFront();
            return false;
        }
        if(this.notify('beforeOpen') === false)
            return false;
        //closeOnClick
        if(this.options.closeOnClick){
            if(this.options.closeOnClick === true)
                this.closeOnClickContainer = $(document.body);
            else if(this.options.closeOnClick == 'container')
                this.closeOnClickContainer = this.container;
            else if (this.options.closeOnClick == 'overlay'){
                Control.Overlay.load();
                this.closeOnClickContainer = Control.Overlay.container;
            }else
                this.closeOnClickContainer = $(this.options.closeOnClick);
            this.closeOnClickContainer.observe('click',this.closeHandler);
        }
        if(this.href && !this.options.iframe && !this.remoteContentLoaded){
            //link to image
            this.remoteContentLoaded = true;
            if(this.href.match(/\.(jpe?g|gif|png|tiff?)$/i)){
                var img = new Element('img');
                img.observe('load',function(img){
                    this.getRemoteContentInsertionTarget().insert(img);
                    this.position();
                    if(this.notify('onRemoteContentLoaded') !== false){
                        if(this.options.indicator)
                            this.hideIndicator();
                        this.finishOpen();
                    }
                }.bind(this,img));
                img.writeAttribute('src',this.href);
            }else{
                //if this is an ajax window it will only open if the request is successful
                if(!this.ajaxRequest){
                    if(this.options.indicator)
                        this.showIndicator();
                    this.ajaxRequest = new Ajax.Request(this.href,{
                        method: this.options.method,
                        parameters: this.options.parameters,
                        onComplete: function(request){
                            this.notify('onComplete',request);
                            this.ajaxRequest = false;
                        }.bind(this),
                        onSuccess: function(request){
                            this.getRemoteContentInsertionTarget().insert(request.responseText);
                            this.notify('onSuccess',request);
                            if(this.notify('onRemoteContentLoaded') !== false){
                                if(this.options.indicator)
                                    this.hideIndicator();
                                this.finishOpen();
                            }
                        }.bind(this),
                        onFailure: function(request){
                            this.notify('onFailure',request);
                            if(this.options.indicator)
                                this.hideIndicator();
                        }.bind(this),
                        onException: function(request,e){
                            this.notify('onException',request,e);
                            if(this.options.indicator)
                                this.hideIndicator();
                        }.bind(this)
                    });
                }
            }
            return true;
        }else if(this.options.iframe && !this.remoteContentLoaded){
            //iframe
            this.remoteContentLoaded = true;
            if(this.options.indicator)
                this.showIndicator();
            this.getRemoteContentInsertionTarget().insert(Control.Window.iframeTemplate.evaluate({
                href: this.href
            }));
            var iframe = this.container.down('iframe');
            iframe.onload = function(){
                this.notify('onRemoteContentLoaded');
                if(this.options.indicator)
                    this.hideIndicator();
                iframe.onload = null;
            }.bind(this);
        }
        this.finishOpen(event);
        return true
    },
    close: function(event){ //event may or may not be present
        if(!this.isOpen || this.notify('beforeClose',event) === false)
            return false;
        if(this.options.closeOnClick)
            this.closeOnClickContainer.stopObserving('click',this.closeHandler);
        if(this.options.fade){
            this.effects.fade = new Effect.Fade(this.container,{
                queue: {
                    position: 'front',
                    scope: 'Control.Window' + this.numberInSequence
                },
                from: 1,
                to: 0,
                duration: this.options.fadeDuration / 2,
                afterFinish: function(){
                    if(this.iFrameShim)
                        this.iFrameShim.hide();
                    this.isOpen = false;
                    this.notify('afterClose');
                }.bind(this)
            });
        }else{
            this.container.hide();
            if(this.iFrameShim)
                this.iFrameShim.hide();
        }
        if(this.ajaxRequest)
            this.ajaxRequest.transport.abort();
        if(!(this.options.draggable || this.options.resizable) && this.options.position == 'center')
            Event.stopObserving(window,'resize',this.positionHandler);
        if(!this.options.draggable && this.options.position == 'center')
            Event.stopObserving(window,'scroll',this.positionHandler);
        if(this.options.indicator)
            this.hideIndicator();
        if(!this.options.fade){
            this.isOpen = false;
            this.notify('afterClose');
        }
        return true;
    },
    position: function(event){
        //this is up top for performance reasons
        if(this.options.position == 'mouse'){
            var xy = [Event.pointerX(event),Event.pointerY(event)];
            this.container.setStyle({
                top: xy[1] + $value(this.options.offsetTop) + 'px',
                left: xy[0] + $value(this.options.offsetLeft) + 'px'
            });
            return;
        }
        var container_dimensions = this.container.getDimensions();
        var viewport_dimensions = document.viewport.getDimensions();
        Position.prepare();
        var offset_left = (Position.deltaX + Math.floor((viewport_dimensions.width - container_dimensions.width) / 2));
        var offset_top = (Position.deltaY + ((viewport_dimensions.height > container_dimensions.height) ? Math.floor((viewport_dimensions.height - container_dimensions.height) / 2) : 0));
        if(this.options.position == 'center'){
            this.container.setStyle({
                top: (container_dimensions.height <= viewport_dimensions.height) ? ((offset_top != null && offset_top > 0) ? offset_top : 0) + 'px' : 0,
                left: (container_dimensions.width <= viewport_dimensions.width) ? ((offset_left != null && offset_left > 0) ? offset_left : 0) + 'px' : 0
            });
        }else if(this.options.position == 'relative'){
            var xy = this.sourceContainer.cumulativeOffset();
            var top = xy[1] + $value(this.options.offsetTop);
            var left = xy[0] + $value(this.options.offsetLeft);
            this.container.setStyle({
                top: (container_dimensions.height <= viewport_dimensions.height) ? (this.options.constrainToViewport ? Math.max(0,Math.min(viewport_dimensions.height - (container_dimensions.height),top)) : top) + 'px' : 0,
                left: (container_dimensions.width <= viewport_dimensions.width) ? (this.options.constrainToViewport ? Math.max(0,Math.min(viewport_dimensions.width - (container_dimensions.width),left)) : left) + 'px' : 0
            });
        }else if(this.options.position.length){
            var top = $value(this.options.position[1]) + $value(this.options.offsetTop);
            var left = $value(this.options.position[0]) + $value(this.options.offsetLeft);
            this.container.setStyle({
                top: (container_dimensions.height <= viewport_dimensions.height) ? (this.options.constrainToViewport ? Math.max(0,Math.min(viewport_dimensions.height - (container_dimensions.height),top)) : top) + 'px' : 0,
                left: (container_dimensions.width <= viewport_dimensions.width) ? (this.options.constrainToViewport ? Math.max(0,Math.min(viewport_dimensions.width - (container_dimensions.width),left)) : left) + 'px' : 0
            });
        }
        if(this.iFrameShim)
            this.updateIFrameShimZIndex();
    },
    ensureInBounds: function(){
        if(!this.isOpen)
            return;
        var viewport_dimensions = document.viewport.getDimensions();
        var container_offset = this.container.cumulativeOffset();
        var container_dimensions = this.container.getDimensions();
        if(container_offset.left + container_dimensions.width > viewport_dimensions.width){
            this.container.setStyle({
                left: (Math.max(0,viewport_dimensions.width - container_dimensions.width)) + 'px'
            });
        }
        if(container_offset.top + container_dimensions.height > viewport_dimensions.height){
            this.container.setStyle({
                top: (Math.max(0,viewport_dimensions.height - container_dimensions.height)) + 'px'
            });
        }
    },
    bringToFront: function(){
        Control.Window.bringToFront(this);
        this.notify('bringToFront');
    },
    destroy: function(){
        this.container.stopObserving('mousedown',this.bringToFrontHandler);
        if(this.draggable){
            Draggables.removeObserver(this.container);
            this.draggable.handle.stopObserving('mousedown',this.bringToFrontHandler);
            this.draggable.destroy();
        }
        if(this.resizable){
            Resizables.removeObserver(this.container);
            this.resizable.handle.stopObserving('mousedown',this.bringToFrontHandler);
            this.resizable.destroy();
        }
        if(this.container && !this.sourceContainer)
            this.container.remove();
        if(this.sourceContainer){
            if(this.options.hover){
                this.sourceContainer.stopObserving('mouseenter',this.sourceContainerOpenHandler);
                this.sourceContainer.stopObserving('mouseleave',this.sourceContainerCloseHandler);
                if(this.options.position == 'mouse')
                    this.sourceContainer.stopObserving('mousemove',this.sourceContainerMouseMoveHandler);
            }else
                this.sourceContainer.stopObserving('click',this.sourceContainerOpenHandler);
        }
        if(this.iFrameShim)
            this.iFrameShim.destroy();
        Event.stopObserving(window,'resize',this.outOfBoundsPositionHandler);
        Control.Window.windows = Control.Window.windows.without(this);
        this.notify('afterDestroy');
    },
    //private
    applyResizable: function(){
        if(this.options.resizable){
            if(typeof(Resizable) == "undefined")
                throw "Control.Window requires resizable.js to be loaded.";
            var resizable_handle = null;
            if(this.options.resizable === true){
                resizable_handle = new Element('div',{
                    className: 'resizable_handle'
                });
                this.container.insert(resizable_handle);
            }else
                resizable_handle = $(this.options.resziable);
            this.resizable = new Resizable(this.container,{
                handle: resizable_handle,
                minHeight: this.options.minHeight,
                minWidth: this.options.minWidth,
                maxHeight: this.options.constrainToViewport ? function(element){
                    //viewport height - top - total border height
                    return (document.viewport.getDimensions().height - parseInt(element.style.top || 0)) - (element.getHeight() - parseInt(element.style.height || 0));
                } : this.options.maxHeight,
                maxWidth: this.options.constrainToViewport ? function(element){
                    //viewport width - left - total border width
                    return (document.viewport.getDimensions().width - parseInt(element.style.left || 0)) - (element.getWidth() - parseInt(element.style.width || 0));
                } : this.options.maxWidth
            });
            this.resizable.handle.observe('mousedown',this.bringToFrontHandler);
            Resizables.addObserver(new Control.Window.LayoutUpdateObserver(this,function(){
                if(this.iFrameShim)
                    this.updateIFrameShimZIndex();
                this.notify('onResize');
            }.bind(this)));
        }
    },
    applyDraggable: function(){
        if(this.options.draggable){
            if(typeof(Draggables) == "undefined")
                throw "Control.Window requires dragdrop.js to be loaded.";
            var draggable_handle = null;
            if(this.options.draggable === true){
                draggable_handle = new Element('div',{
                    className: 'draggable_handle'
                });
                this.container.insert(draggable_handle);
            }else
                draggable_handle = $(this.options.draggable);
            this.draggable = new Draggable(this.container,{
                handle: draggable_handle,
                constrainToViewport: this.options.constrainToViewport,
                zindex: this.container.getStyle('z-index'),
                starteffect: function(){
                    if(Prototype.Browser.IE){
                        this.old_onselectstart = document.onselectstart;
                        document.onselectstart = function(){
                            return false;
                        };
                    }
                }.bind(this),
                endeffect: function(){
                    document.onselectstart = this.old_onselectstart;
                }.bind(this)
            });
            this.draggable.handle.observe('mousedown',this.bringToFrontHandler);
            Draggables.addObserver(new Control.Window.LayoutUpdateObserver(this,function(){
                if(this.iFrameShim)
                    this.updateIFrameShimZIndex();
                this.notify('onDrag');
            }.bind(this)));
        }
    },
    createDefaultContainer: function(container){
        if(!this.container){
            //no container passed or found, create it
            this.container = new Element('div',{
                id: 'control_window_' + this.numberInSequence
            });
            $(document.body).insert(this.container);
            if(typeof(container) == "string" && $(container) == null && !container.match(/^#(.+)$/) && !container.match(Control.Window.uriRegex))
                this.container.update(container);
        }
    },
    finishOpen: function(event){
        this.bringToFront();
        if(this.options.fade){
            if(typeof(Effect) == "undefined")
                throw "Control.Window requires effects.js to be loaded."
            if(this.effects.fade)
                this.effects.fade.cancel();
            this.effects.appear = new Effect.Appear(this.container,{
                queue: {
                    position: 'end',
                    scope: 'Control.Window.' + this.numberInSequence
                },
                from: 0,
                to: 1,
                duration: this.options.fadeDuration / 2,
                afterFinish: function(){
                    if(this.iFrameShim)
                        this.updateIFrameShimZIndex();
                    this.isOpen = true;
                    this.notify('afterOpen');
                }.bind(this)
            });
        }else
            this.container.show();
        this.position(event);
        if(!(this.options.draggable || this.options.resizable) && this.options.position == 'center')
            Event.observe(window,'resize',this.positionHandler,false);
        if(!this.options.draggable && this.options.position == 'center')
            Event.observe(window,'scroll',this.positionHandler,false);
        if(!this.options.fade){
            this.isOpen = true;
            this.notify('afterOpen');
        }
        return true;
    },
    showIndicator: function(){
        this.showIndicatorTimeout = window.setTimeout(function(){
            if(this.options.fade){
                this.indicatorEffects.appear = new Effect.Appear(this.indicator,{
                    queue: {
                        position: 'front',
                        scope: 'Control.Window.indicator.' + this.numberInSequence
                    },
                    from: 0,
                    to: 1,
                    duration: this.options.fadeDuration / 2
                });
            }else
                this.indicator.show();
        }.bind(this),Control.Window.indicatorTimeout);
    },
    hideIndicator: function(){
        if(this.showIndicatorTimeout)
            window.clearTimeout(this.showIndicatorTimeout);
        this.indicator.hide();
    },
    getRemoteContentInsertionTarget: function(){
        return typeof(this.options.insertRemoteContentAt) == "string" ? this.container.down(this.options.insertRemoteContentAt) : $(this.options.insertRemoteContentAt);
    },
    updateIFrameShimZIndex: function(){
        if(this.iFrameShim)
            this.iFrameShim.positionUnder(this.container);
    }
});
//class methods
Object.extend(Control.Window,{
    windows: [],
    baseZIndex: 9999,
    indicatorTimeout: 250,
    iframeTemplate: new Template('<iframe src="#{href}" width="100%" height="100%" frameborder="0"></iframe>'),
    uriRegex: /^(\/|\#|https?\:\/\/|[\w]+\/)/,
    bringToFront: function(w){
        Control.Window.windows = Control.Window.windows.without(w);
        Control.Window.windows.push(w);
        Control.Window.windows.each(function(w,i){
            var z_index = Control.Window.baseZIndex + i;
            w.container.setStyle({
                zIndex: z_index
            });
            if(w.isOpen){
                if(w.iFrameShim)
                w.updateIFrameShimZIndex();
            }
            if(w.options.draggable)
                w.draggable.options.zindex = z_index;
        });
    },
    open: function(container,options){
        var w = new Control.Window(container,options);
        w.open();
        return w;
    },
    //protected
    initialZIndexForWindow: function(w){
        return Control.Window.baseZIndex + (Control.Window.windows.length - 1);
    }
});
Object.Event.extend(Control.Window);

//this is the observer for both Resizables and Draggables
Control.Window.LayoutUpdateObserver = Class.create({
    initialize: function(w,observer){
        this.w = w;
        this.element = $(w.container);
        this.observer = observer;
    },
    onStart: Prototype.emptyFunction,
    onEnd: function(event_name,instance){
        if(instance.element == this.element && this.iFrameShim)
            this.w.updateIFrameShimZIndex();
    },
    onResize: function(event_name,instance){
        if(instance.element == this.element)
            this.observer(this.element);
    },
    onDrag: function(event_name,instance){
        if(instance.element == this.element)
            this.observer(this.element);
    }
});

//overlay for Control.Modal
Control.Overlay = {
    id: 'control_overlay',
    loaded: false,
    container: false,
    lastOpacity: 0,
    styles: {
        position: 'fixed',
        top: 0,
        left: 0,
        width: '100%',
        height: '100%',
        zIndex: 9998,
        backgroundColor:'white',
        color:'white'
    },
    ieStyles: {
        position: 'absolute',
        top: 0,
        left: 0,
        zIndex: 9998
    },
    effects: {
        fade: false,
        appear: false
    },
    load: function(){
        if(Control.Overlay.loaded)
            return false;
        Control.Overlay.loaded = true;
        Control.Overlay.container = new Element('div',{
            id: Control.Overlay.id
        });
        $(document.body).insert(Control.Overlay.container);
        if(Prototype.Browser.IE){
            Control.Overlay.container.setStyle(Control.Overlay.ieStyles);
            Event.observe(window,'scroll',Control.Overlay.positionOverlay);
            Event.observe(window,'resize',Control.Overlay.positionOverlay);
            Control.Overlay.observe('beforeShow',Control.Overlay.positionOverlay);
        }else
            Control.Overlay.container.setStyle(Control.Overlay.styles);
        Control.Overlay.iFrameShim = new IframeShim();
        Control.Overlay.iFrameShim.hide();
        Event.observe(window,'resize',Control.Overlay.positionIFrameShim);
        Control.Overlay.container.hide();
        return true;
    },
    unload: function(){
        if(!Control.Overlay.loaded)
            return false;
        Event.stopObserving(window,'resize',Control.Overlay.positionOverlay);
        Control.Overlay.stopObserving('beforeShow',Control.Overlay.positionOverlay);
        Event.stopObserving(window,'resize',Control.Overlay.positionIFrameShim);
        Control.Overlay.iFrameShim.destroy();
        Control.Overlay.container.remove();
        Control.Overlay.loaded = false;
        return true;
    },
    show: function(opacity,fade){
        if(Control.Overlay.notify('beforeShow') === false)
            return false;
        Control.Overlay.lastOpacity = opacity;
        Control.Overlay.positionIFrameShim();
        Control.Overlay.iFrameShim.show();
        if(fade){
            if(typeof(Effect) == "undefined")
                throw "Control.Window requires effects.js to be loaded."
            if(Control.Overlay.effects.fade)
                Control.Overlay.effects.fade.cancel();
            Control.Overlay.effects.appear = new Effect.Appear(Control.Overlay.container,{
                queue: {
                    position: 'end',
                    scope: 'Control.Overlay'
                },
                afterFinish: function(){
                    Control.Overlay.notify('afterShow');
                },
                from: 0,
                to: Control.Overlay.lastOpacity,
                duration: (fade === true ? 0.75 : fade) / 2
            });
        }else{
            Control.Overlay.container.setStyle({
                opacity: opacity || 1
            });
            Control.Overlay.container.show();
            Control.Overlay.notify('afterShow');
        }
        return true;
    },
    hide: function(fade){
        if(Control.Overlay.notify('beforeHide') === false)
            return false;
        if(Control.Overlay.effects.appear)
            Control.Overlay.effects.appear.cancel();
        Control.Overlay.iFrameShim.hide();
        if(fade){
            Control.Overlay.effects.fade = new Effect.Fade(Control.Overlay.container,{
                queue: {
                    position: 'front',
                    scope: 'Control.Overlay'
                },
                afterFinish: function(){
                    Control.Overlay.notify('afterHide');
                },
                from: Control.Overlay.lastOpacity,
                to: 0,
                duration: (fade === true ? 0.75 : fade) / 2
            });
        }else{
            Control.Overlay.container.hide();
            Control.Overlay.notify('afterHide');
        }
        return true;
    },
    positionIFrameShim: function(){
        if(Control.Overlay.container.visible())
            Control.Overlay.iFrameShim.positionUnder(Control.Overlay.container);
    },
    //IE only
    positionOverlay: function(){
        Control.Overlay.container.setStyle({
            width: document.body.clientWidth + 'px',
            height: document.body.clientHeight + 'px'
        });
    }
};
Object.Event.extend(Control.Overlay);

Control.ToolTip = Class.create(Control.Window,{
    initialize: function($super,container,tooltip,options){
        $super(tooltip,Object.extend(Object.extend(Object.clone(Control.ToolTip.defaultOptions),options || {}),{
            position: 'mouse',
            hover: container
        }));
    }
});
Object.extend(Control.ToolTip,{
    defaultOptions: {
        offsetLeft: 10
    }
});

Control.Modal = Class.create(Control.Window,{
    initialize: function($super,container,options){
        Control.Modal.InstanceMethods.beforeInitialize.bind(this)();
        $super(container,Object.extend(Object.clone(Control.Modal.defaultOptions),options || {}));
    }
});
Object.extend(Control.Modal,{
    defaultOptions: {
        overlayOpacity: 0.7,
        closeOnClick: 'overlay'
    },
    current: false,
    open: function(container,options){
        var modal = new Control.Modal(container,options);
        modal.open();
        return modal;
    },
    close: function(){
        if(Control.Modal.current)
            Control.Modal.current.close();
    },
    InstanceMethods: {
        beforeInitialize: function(){
            Control.Overlay.load();
            this.overlayFinishedOpening = false;
            this.observe('beforeOpen',Control.Modal.Observers.beforeOpen.bind(this));
            this.observe('afterOpen',Control.Modal.Observers.afterOpen.bind(this));
            this.observe('afterClose',Control.Modal.Observers.afterClose.bind(this));
        }
    },
    Observers: {
        beforeOpen: function(){
            if(!this.overlayFinishedOpening){
                Control.Overlay.observeOnce('afterShow',function(){
                    this.overlayFinishedOpening = true;
                    this.open();
                }.bind(this));
                Control.Overlay.show(this.options.overlayOpacity,this.options.fade ? this.options.fadeDuration : false);
                throw $break;
            }else
            Control.Window.windows.without(this).invoke('close');
        },
        afterOpen: function(){
            Control.Modal.current = this;
        },
        afterClose: function(){
            Control.Overlay.hide(this.options.fade ? this.options.fadeDuration : false);
            Control.Modal.current = false;
            this.overlayFinishedOpening = false;
        }
    }
});

Control.LightBox = Class.create(Control.Window,{
    initialize: function($super,container,options){
        this.allImagesLoaded = false;
        if(options.modal){
            var options = Object.extend(Object.clone(Control.LightBox.defaultOptions),options || {});
            options = Object.extend(Object.clone(Control.Modal.defaultOptions),options);
            options = Control.Modal.InstanceMethods.beforeInitialize.bind(this)(options);
            $super(container,options);
        }else
            $super(container,Object.extend(Object.clone(Control.LightBox.defaultOptions),options || {}));
        this.hasRemoteContent = this.href && !this.options.iframe;
        if(this.hasRemoteContent)
            this.observe('onRemoteContentLoaded',Control.LightBox.Observers.onRemoteContentLoaded.bind(this));
        else
            this.applyImageObservers();
        this.observe('beforeOpen',Control.LightBox.Observers.beforeOpen.bind(this));
    },
    applyImageObservers:function(){
        var images = this.getImages();
        this.numberImagesToLoad = images.length;
        this.numberofImagesLoaded = 0;
        images.each(function(image){
            image.observe('load',function(image){
                ++this.numberofImagesLoaded;
                if(this.numberImagesToLoad == this.numberofImagesLoaded){
                    this.allImagesLoaded = true;
                    this.onAllImagesLoaded();
                }
            }.bind(this,image));
            image.hide();
        }.bind(this));
    },
    onAllImagesLoaded: function(){
        this.getImages().each(function(image){
            this.showImage(image);
        }.bind(this));
        if(this.hasRemoteContent){
            if(this.options.indicator)
                this.hideIndicator();
            this.finishOpen();
        }else
            this.open();
    },
    getImages: function(){
        return this.container.select(Control.LightBox.imageSelector);
    },
    showImage: function(image){
        image.show();
    }
});
Object.extend(Control.LightBox,{
    imageSelector: 'img',
    defaultOptions: {},
    Observers: {
        beforeOpen: function(){
            if(!this.hasRemoteContent && !this.allImagesLoaded)
                throw $break;
        },
        onRemoteContentLoaded: function(){
            this.applyImageObservers();
            if(!this.allImagesLoaded)
                throw $break;
        }
    }
});

if(!PB) var PB = {};

PB.onLoadQueue = {};

PB.onDomLoad = function()
{
  $H(PB.onLoadQueue).each(function(item)
                          {
                             eval(item[0])(String(item[1]));
                          });
}

PB.addToDomLoad = function(funkshun,args)
{
 
  PB.onLoadQueue[funkshun] = String(args);
}

document.observe('dom:loaded',PB.onDomLoad);


/*
Load External JS/CSS Files
*/
PB.loadFile = function(filename,async)
{
  var filetype = $A(filename.split('.')).last();
  if(filetype =='js')
    $$('head')[0].insert($script({type:'text/javascript',src:filename}));

  else if(filetype=='css')
    $$('head')[0].insert($link({type:'text/css',rel:'stylesheet',href:filename}));

  else alert('you can only add js or css dummy!');
}

/*
MODALS
*/
if(!PB) var PB = {};

var browser = Class.create({
	initialize:function()
	{
		if($('browse_category'))
			$('browse_category').observe('change',function(){$('browse_filter_form').submit();});
		
		if($('business_category'))
		{
			if($('browse_filter_form'))
			{
				$('business_category').observe('change',function(){$('browse_filter_form').submit();});
			}
		}
		
		if($('selling_category'))
		{
			if($('browse_filter_form'))
			{
				$('selling_category').observe('change',function(){$('browse_filter_form').submit();});
			}
		}
		
		if($('sort_results'))
			$('sort_results').observe('change',function(){$('browse_filter_form').submit();});
		
		if($('custom_category'))
			$('custom_category').observe('change',function(){$('browse_filter_form').submit();});
	}
	
});

function initBrowser()
{
	if($('browse_filter_form'))
		PB.Browser = new browser();
}
PB.addToDomLoad('initBrowser','');

if(!PB) var PB = {};

var pager = Class.create({
	initialize:function()
	{
	}
});
if(!PB.Modals) PB.Modals = {};

PB.Modal = Class.create({
  initialize:function(element,content,options)
  {
    this.element = $(element);
    this.content = content;
    this.overlay = $('overlay');
    this.options = Object.extend(
      {
      closeEffect:'fade',
      openEffect:'fade',
      onOpen:Prototype.emptyFunction,
      onBeforeOpen:Prototype.emptyFunction,
      onAfterOpen:Prototype.emptyFunction
    },options || {});
  },
  open:function()
  {
    this.element.update(this.content);
    this.element.center();
    this.overlay.show();
    this.options.onBeforeOpen();
    this.element.show();
    this.options.onAfterOpen();
  },
  close:function()
  {
    this.element.hide();
    this.overlay.hide();
  }
});

/*
Used to retrieve templates from the server.
NEEDS MORE SECURITY!!!!!
*/


PB.Template = Class.create({
  initialize:function(which,options)
  {
    this.options = Object.extend({
      params:null
    },options || {});
    this.template_name = which;
    this.fetchContent(which);
  },
  fetchContent:function(which)
  {
    if(!PB.Template.loadedTemplates[which])
      $ajax('/templates.php',{action:'fetch',which:which},this.handleServerResponse.bind(this));

    else
      return PB.Template.loadedTemplates[which];
  },
  handleServerResponse:function(response)
  {
    //		window.thetpl = this;
    this.content = response.content;
    if(this.options.params)
      this.parseTemplate(this.options.params);

    else if(this.options.onFetch)
      this.options.onFetch(this.content);

    //console.log('firing.. template:'+this.template_name);
    document.fire('template:'+this.template_name,this.content);
  },
  parseParam:function(param)
  {
    var patternRE = new RegExp('\\{\\{\\s*\\$'+param[0]+'\\s*\\}\\}','ig');
    var content = this.content.replace(patternRE,param[1]);
    this.content = content;
  },
  parseTemplate:function(params)
  {
    // /\{\{\s*\$'+param[0]+'\s*\}\}/ig
    $H(params).each(function(param)
                    {
                      this.parseParam(param);
                    }.bind(this));
  },
  getContent:function()
  {
    return this.content;
  }
});


PB.Template.loadedTemplates = new Array();

function initTabs()
{
	if($$('.tab_container').length >0)
  {
  	$$('.tab_container').each(
  	  function(item)
  	  {
  			window.c_tabs = new Control.Tabs(item,{setClassOnContainer:true});
			});
	}
	if($('year_tabs'))
	{
		window.year_tabs = new Control.Tabs('year_tabs',
		{
			setClassOnContainer:true,
  		afterChange:function(new_container){
  			if($('year_select_box'))
  			{
  				$A($('year_select_box').options).each(function(option,i){
  					if(option.value == new_container.id){
  						$('year_select_box').options.selectedIndex = i;
  						throw $break;
  					}
  				});
  			}
  		}
  		
		});
	}
	///set the action on the year select box
	if($('year_select_box'))
  {
  	$('year_select_box').observe('change',function(evt){
  		
  		window.year_tabs.setActiveTab($('year_select_box').options.selectedIndex);
  		year = $('year_select_box').value.gsub('year_month_select_','');
  		//year = evt.element().readAttribute('id').gsub('year_select_box_','');
  		
  		window.month_tabs.setActiveTab($('year_month_select_box_'+year).value);
  	});
	}
	
	
	if($('year_month_tabs'))
	{
		window.month_tabs = new Control.Tabs('year_month_tabs',
		{
			setClassOnContainer:true,
  			afterChange:function(new_container){
  				if($$('.year_month_select_box').length > 0)
  				{
  					$$('.year_month_select_box').each(function(month_box){
							$A($(month_box).options).each(function(option,i){
								if(option.value == new_container.id){
									$(month_box).options.selectedIndex = i;
									throw $break;
								}
							});
  					});
  				}
  			}
  	});
	}
	
	if($$('.year_month_select_box'))
  {
  	$$('.year_month_select_box').each(function(item){
 		 	$(item).observe('change',function(){
  			window.month_tabs.setActiveTab($(item).selectedIndex + 1);
  		});
		});
	}
	
/*
	if($('year_month_tabs').length > 0)
	{
		mo_cnt = 0;
		$$('.year_month_tabs').each(function(item){
			
			window.month_tabs[mo_cnt++] = new Control.Tabs(item,
			{	
				setClassOnContainer:true,
  			afterChange:function(new_container){
  				if($(item))
  				{
  					$A($(item).options).each(function(option,i){
  						if(option.value == new_container.id){
  							$(item).options.selectedIndex = i;
  							throw $break;
  						}
  					});
  				}
  			}	
			});
		}.bind(this));
	}
*/
	///set the action on the year select box
}

function initFMTabs()
{

}

function initPagerTabs()
{
window.tab_count = 0;
window.tabs = new Array();
  if($$('.pager_tab_container').length >0)
  {
      $$('.pager_tab_container').each(
      function(item)
      {
      	window.tabs[window.tab_count] = 
      	new Control.Tabs(item,
        {
					setClassOnContainer:true
        });
				if($('page_first'))
				{
					$('page_first').observe('click',function(event){
						this.first();
						Event.stop(event);
					}.bindAsEventListener(window.tabs[window.tab_count]));
				}
				if($('page_prev'))
				{
					$('page_prev').observe('click',function(event){
						this.previous();
						Event.stop(event);
					}.bindAsEventListener(window.tabs[window.tab_count]));
				}
				if($('page_next'))
				{	
					$('page_next').observe('click',function(event){
						this.next();
						Event.stop(event);
					}.bindAsEventListener(window.tabs[window.tab_count]));
				}
				if($('page_last'))
				{
					$('page_last').observe('click',function(event){
						this.last();
						Event.stop(event);
					}.bindAsEventListener(window.tabs[window.tab_count]));
				}
				/*
				window.tabs[window.tab_count].observe('beforeChange',
					function(old_container,new_container)
					{
						new_id = new_container.readAttribute('id');
						cleaned = document.location.href.split('#')[0];
						document.location = cleaned+'#'+new_id;
					}
				);
				*/
				window.tab_count++;
			});
  }
}

//--- nicEditor -->
function initNicEdit(textarea)
{
/*  
  if($(textarea))
  {
   	
});
	}
*/
}
//--- ROUNDED CORNERS -->
function doRoundedCorners(){
  $$('.rounded').each(function(item){
    $(item).insert('<div class="tr"></div><div class="tl"></div><div class="br"></div><div class="bl"></div>');
  });
}

function initSearchBar()
{
  //IE BUG
  if($('search_bar_category'))
    {
/*
$('search_bar_category').observe('change',
function(event)
{
$('search_bar_form').action = '/browse/'+$('search_bar_category').value;
});
*/
    }
}


/*
COMMENT WIDGET
*/

var CommentWidget = Class.create({
  initialize:function()
  {

  },
  add:function(){},
  remove:function(){},
  read:function(){},
  submitComment:function(form_id)
  {
    if($(form_id+'_comment_field').value == '')
      {	
        window.growler.error('You must enter some text.',{header: "ERROR",life:2});
        return;
      }
      var content = String($(form_id+'_comment_field').value);
      var params = {
        action:'post_comment',
        comment_for:form_id,
        comment_body:content
      };
      $(form_id+'_comment_field').value = '';
      $ajax('/comments.php',params,this.handleServerResponse.bind(this,form_id));
  },
  postToServer:function()
  {
  },
  handleServerResponse:function(form_id,response)
  {
    window.response = response;
    window.form_id = form_id;
    switch(response.code)
    {
      case 200:
        this.addComments(response.comments,form_id);
      break;
      case 210:
        if(response.errors)
      {
        var errors = '';
        $A(response.errors).each(function(error)
                                 {
                                   errors += error+'\n';
                                 }.bind(this));
                                 window.growler.error(errors,{header: "ERROR"});
      }
      if(response.error)
        {
          window.growler.error(response.error,{header: "ERROR"});
        }
        break;
        case 201:

          if(response.errors)
        {
          var errors = '';
          $A(response.errors).each(function(error)
                                   {
                                     errors += error;
                                   }.bind(this));
                                   alert(errors);
        }
        if(response.error)
          {
            alert(response.error);
          }
          break;
    }
  },
  deleteComment:function(comment_id,form_id)
  {
    params = {};
    params.action = 'delete_comment';
    params.comment_id = comment_id;
    params.form_id = form_id;
    $ajax('/comments.php',params,this.handleServerResponse.bind(this,form_id));
  },
  addComments:function(comments,form_id)
  {
    $(form_id+'_comments').update(comments);
  }
});


/*
Comments Widgets
*/

function initCommentWidgets()
{
  PB.CommentWidget = new CommentWidget();
  if($$('.comment_widget').length >0)
    {	
      $$('.comment_widget').each(function(elm)
                                 {	
                                   params = {};
                                   params.comment_id = elm.readAttribute('id').gsub('_comment_widget','');
                                   document.observe('template:comments_add',function(event)
                                                    {
                                                      elm.update(event.memo);
                                                      document.stopObserving('template:comments_add');
                                                    });

                                                    my_tpl = new PB.Template('comments_add',{params:params});
                                 }.bind(this));
    }
  window.CommentWidget = PB.CommentWidget;
}
function initInboxPeriodicalUpdater()
{
  if($('inbox_num_messages'))
    {
      window.inboxUpdater = new Ajax.PeriodicalUpdater('inbox_num_messages', '/index.php',{frequency:30,parameters:{action:'inbox_count'}});
    }
}

function initAdsPeriodicalUpdater() {
	if ($$('.ad_vert').length == 0) {
		return;
	}
  
	window.adsUpdater = new Ajax.PeriodicalUpdater($$('.ad_vert')[0], '/probrowse.php', {
		frequency: 15
		,parameters: {
			action: 'rotate_ads'
			,query_string: location.search
			,url_path: location.pathname
		}
	});
}

PB.addToDomLoad('initAdsPeriodicalUpdater','');

var FriendSelecter = Class.create({
	initialize:function(){},
	open:function(which,which_id)
	{
		if(!which_id)
			which_id = 0;
		
		$ajax('/user',{action:'get_friend_selecter',which:which,which_id:which_id},this.handleServerResponse.bind(this));
	},
	handleServerResponse:function(response)
	{
		window.response;
		switch(response.code)
		{
			case 200:
				this.requestOK(response);
			break;
		}
	},
	close:function()
	{
		this.modal.close();
	},
	requestOK:function(response)
	{

		if(!this.modal)
		this.modal = new Control.Modal();
		
		this.modal.container.update(response.content);
		this.modal.open();
    /*
      $$('.fm_item').each(function(item){
        item.observe('click',this.action.bindAsEventListener(this));
      }.bind(this));
		*/
	}
});

function initGrowler()
{
  window.growler = new k.Growler({location:'br'});
}
var Actions = Class.create({
  initialize:function()
  {

  },
  addTag:function()
  {
    $('tag_form').show();
  },
  saveTag:function(for_what,what_id)
  {
    this.last_tag_name = tag_name = $('new_tag_name').value;
    this.last_tag_name_url  = tag_name.gsub(' ','_');
    $ajax('/probrowse',{action:'add_tag',tag_name:tag_name,for_what:for_what,what_id:what_id},this.handleServerResponse.bind(this));
    
    //$('share_btn').show();
  },
  acceptSponsor:function(request_id)
  {
  	$ajax('/probrowse',{action:'accept_sponsor',request_id:request_id},this.handleServerResponse.bind(this));
  	
  },
  addTagMarkup:function(tag_id)
  {
  	markup = '<span id="tag_'+tag_id+'">'+
  		'<span class="delete_this">'+
  			'<a title="delete this tag" href="javascript:PB.Action.deleteTag('+tag_id+');"><span class="icon"/></a></span>'+
  				'<a href="/browse/all/tag_'+this.last_tag_name_url+'"> '+this.last_tag_name+'</a>,</span>';
  	
  	$('tags').insert(markup);
    $('new_tag_name').value = '';
    $('tag_form').hide();
  	this.last_tag_name = '';
  	this.last_tag_name_url = '';
  },
  deleteTag:function(tag_id)
  {
    $ajax('/probrowse',{action:'delete_tag',tag_id:tag_id},this.handleServerResponse.bind(this));
  },
  deleteSelling:function(selling_id)
  {
    $ajax('/probrowse',{action:'delete_selling',selling_id:selling_id},this.handleServerResponse.bind(this));
  },
  cancelTag:function()
  {
    $('new_tag_name').value = '';
    $('tag_form').hide();
  },
  approveOrg:function(which)
  {
  	$ajax('/probrowse',{action:'approve_org',which:which},this.handleServerResponse.bind(this));
  },
  deleteEvent:function(which)
  {
  	$ajax('/user',{action:'delete_event',which:which},this.handleServerResponse.bind(this));
  },
  deleteDeal:function(which)
  {
  	$ajax('/user',{action:'delete_deal',which:which},this.handleServerResponse.bind(this));
  },
  denyOrg:function(which)
  {
  	$ajax('/probrowse',{action:'disapprove_org',which:which},this.handleServerResponse.bind(this));
  },
  saveDeal:function(deal_id)
  {
    $ajax('/probrowse',{action:'save_deal',deal_id:deal_id},this.handleServerResponse.bind(this));
  },
  Feature:function(what,what_id)
  {
    $ajax('/probrowse',{action:'feature_content',what:what,what_id:what_id},this.handleServerResponse.bind(this));
  },
  unFeature:function(what,what_id)
  {
    $ajax('/probrowse',{action:'unfeature_content',what:what,what_id:what_id},this.handleServerResponse.bind(this));
  },
  reportContent:function(what,what_id)
  {	
    document.location = '/report/?what='+what+'&what_id='+what_id;
    //$ajax('/probrowse',{action:'report_content',what:what,what_id:what_id},this.handleServerResponse.bind(this));
  },
  acceptTestimonial:function(testimonial_id)
  {
    $ajax('/user',{action:'accept_testimonial',which:testimonial_id},this.handleServerResponse.bind(this));
  },
  deleteSharedItem:function(what_id)
  {
  	$ajax('/user',{action:'delete_shared_item',what_id:what_id},this.handleServerResponse.bind(this));
  },
  deleteInvolvement:function(inv_id)
  {
  	$ajax('/user',{action:'delete_involvement',which:inv_id},this.handleServerResponse.bind(this));
  },
  deleteTestimonial:function(testimonial_id)
  {
    $ajax('/user',{action:'delete_testimonial',which:testimonial_id},this.handleServerResponse.bind(this));
  },
  unpublishTestimonial:function(testimonial_id)
  {
    $ajax('/user',{action:'unpublish_testimonial',which:testimonial_id},this.handleServerResponse.bind(this));
  },
  watchAuction:function(auction_id)
  {
    $ajax('/probrowse',{action:'watch_auction',auction_id:auction_id},this.handleServerResponse.bind(this));
  },
  deleteCustomTab:function(tab_id)
  {
  	$ajax('/user',{action:'delete_custom_tab',which:tab_id},this.handleServerResponse.bind(this));
  },
  banBidder:function(bidder_id)
  {
      $ajax('/probrowse',{action:'ban_bidder',bidder_id:bidder_id},this.handleServerResponse.bind(this));
  },
  unBanBidder:function(bidder_id)
  {
      $ajax('/probrowse',{action:'unban_bidder',bidder_id:bidder_id},this.handleServerResponse.bind(this));
  },
  rejectBid:function(bid_id)
  {
    $ajax('/probrowse',{action:'reject_bid',bid_id:bid_id},this.handleServerResponse.bind(this));
  },
  rateBiz:function(score)
  {
  	$ajax('/user',{action:'rate_biz',score:score},this.handleServerResponse.bind(this));
  },
  deleteFile:function(which)
  {
    $ajax('/user',{action:'delete_file',which:which},this.handleServerResponse.bind(this));
  },
  editSponsor:function(id,image_src,title,phone,email,website,details)
  {
  	if(!PB.Forms.edit_sponsor)
  		PB.Forms.edit_sponsor = new PB.Form('update_sponsor_form');
  	
  	$('edit_sponsor').show();
  	
  	$('esponsor[id]').value = id;
  	$('esponsor[image_src]').src = image_src || '/img/default/no_image_90.jpg';
  	$('esponsor[title]').value = title;
  	$('esponsor[phone]').value = phone;
  	$('esponsor[email]').value = email;
  	$('esponsor[website]').value = website;
  	$('esponsor[details]').value = details;
  	$('sponsor_cancel_btn').stopObserving('click');
  	$('sponsor_cancel_btn').observe('click',function(e){$('edit_sponsor').hide();});
  },
  placeBid:function(selling_id)
  {
    auction_id = selling_id;
    bid_amount = $('bid_amount').value;
    if(bid_amount.length <= 0)
    {
      window.growler.error('you must enter a bid amount',{header:'Error.'});
      return;
    }
    if(bid_amount.match(/[^\d\.\$]/))
    {
      window.growler.error('invalid bid. ex: $20.00',{header:'Error.'});
      return;
    }
    $ajax('/probrowse.php',{action:'auction_bid','auction_id':auction_id,'bid_amount':bid_amount},this.handleServerResponse.bind(this));
  },
  answerSellingInquiry:function(inquiry_id)
  {
    body = $('selling_inquiry_answer_text').value;
    if(body.length <= 0)
      {
        window.growler.error('you must enter an answer.',{header:'Error.'});
        return;
      }
    $ajax('/probrowse',{action:'answer_selling_inquiry',answer:body,which:inquiry_id},this.handleServerResponse.bind(this));
  },
  addRelatedLink:function()
  {
  	
  	my_count = $$('.related_link').length;
  	my_count++;
  	li_markup = '<div class="related_link  clear clearfix" id="related_link_'+my_count+'">'+
         '<li class="clearfix">'+
         	'<div class="floatLeft spaceRight">'+
      	   	'<label for="">Link '+my_count+' Title:</label>'+
      	   	'<input type="text"  name="related_links['+my_count+']title]" id="related_links['+my_count+'][title]" value="" size="20" />'+
     	    		'<div class="form_error"></div>'+
     	 		'</div>'+
     	 '<div class="floatLeft">'+
     		    '<label for="">Link '+my_count+':</label>'+
     	    '<input type="text"  name="related_links['+my_count+'][href]" id="related_links['+my_count+'][href]" value="" size="20" />'+
         '<div class="form_error"></div>'+
     	 '</div>'+
     	 		'<div class="floatRight white_btn">'+
		   	 	'<a class="" href="javascript:PB.Action.removeRelatedLink('+my_count+');">remove</a>'+
		   	 '</div>'+
         '</li>'+
		  	'</div>';

  	$('related_links_add').insert(li_markup);
  },
  removeRelatedLink:function(link_id)
  {
  	$('related_link_'+link_id).remove();
  },
  sellingInquiry:function(selling_id)
  {
    body = $('selling_inquiry_text').value;
    if(body.length <= 0)
      {
        window.growler.error('you must enter a question.',{header:'Error.'});
        return;
      }
    $ajax('/probrowse',{action:'selling_inquiry',body:body,selling_id:selling_id},this.handleServerResponse.bind(this));
  },
  removeSponsor:function(which)
  {
  	$ajax('/user',{action:'remove_sponsor',which:which},this.handleServerResponse.bind(this));
  },	
  acceptFriend:function(friend_id){$ajax('/probrowse',{action:'accept_friend','friend_id':friend_id || ''},this.handleServerResponse.bind(this));},
  rejectFriend:function(friend_id){$ajax('/probrowse',{action:'reject_friend','friend_id':friend_id || ''},this.handleServerResponse.bind(this));},
  blockFriend:function(friend_id){$ajax('/probrowse',{action:'block_friend','friend_id':friend_id || ''},this.handleServerResponse.bind(this));},
  requestFriend:function(friend_id){$ajax('/probrowse',{action:'request_friend','friend_id':friend_id || ''},this.handleServerResponse.bind(this));},
  handleServerResponse:function(response)
  {
    switch(response.code)
    {
      // all good
      case 200:
        this.onSuccess(response);
      break;
      //validation errors
      case 210:
        this.onValidationErrors(response);
      break;

      //server errors
      case 211:
        this.onServerErrors(response);
      break;

      //custom function callback
      case 201:
        this.on[response.funk](response);
      break;
    }
  },
  isArray:function()
  {
    if (typeof arguments[0] == 'object') 
      {  
        var criterion = arguments[0].constructor.toString().match(/array/i); 
        return (criterion != null);  
      }
      return false;
  },
  onValidationErrors:function(response)
  {
    errors = response.errors;
    growl_errors = '';
    if(this.isArray(errors))
      {
        $A(errors).each(function(error)
                        {
                          growl_errors += '<div>'+error+'</div>';
                        });
      }
      else
        {
          $H(errors).each(function(error)
                          {
                            window.error = error;
                            growl_errors += '<div>'+error.value+'</div>';
                            if($(error.key))
                              {
                                $(error.key).addClassName('error');
                                $(error.key).writeAttribute('title',error.value);

                                if($(error.key).up('li') && $(error.key).up('li').down('.form_error'))
                                  $(error.key).up('li').down('.form_error').update(error.value);
                              }
                          }.bind(this));
        }
        window.growler.error(growl_errors,{header: "Please Fix These Errors."});
        this.options.onValidationError();
  },
  onServerErrors:function(response)
  {
    this.options.onServerErrors();
  },
  signedInError:function()
  {
    window.growler.error('you must be signed in.',{header: "Error."});
  },
  onSuccess:function(response)
  {
    if(response.info)
      {
        window.growler.info(response.info,{header:'Success.'});
      }
			if(response.tag_id)
			{
				$('tag_'+response.tag_id).remove();
			}

			if(response.new_tag_id)
			{
				this.addTagMarkup(response.new_tag_id);
				//$('tag_'+response.tag_id).remove();
			}

      if(response.location)
			document.location = document.location;
        //document.location = response.location;
  }
});


function initActions()
{
  PB.FriendSelecter = new FriendSelecter();
  PB.Action = new Actions();
}
PB.addToDomLoad('initTabs','');
PB.addToDomLoad('initPagerTabs','');
PB.addToDomLoad('initCommentWidgets','');
PB.addToDomLoad('initSearchBar','');
PB.addToDomLoad('doRoundedCorners','');
PB.addToDomLoad('initInboxPeriodicalUpdater','');
PB.addToDomLoad('initActions','');

/* Growler */
PB.addToDomLoad('initGrowler','');

if(!PB) var PB = {};

PB.Ajax = Class.create({
	initialize:function(url,params,callback)
	{
		this.url = url;
		this.params = params;
		this.callback = callback;
		new Ajax.Request(this.url,
		{
			method:'post',
			parameters:this.params,
			onSuccess:this.process.bind(this)
		});
	},
	process:function(transport,json)
	{
		var return_data = eval('('+transport.responseText+')');
		this.callback(return_data);
	}
});

function $ajax(url,params,callback)
{
	PB.currAjaxRequest = new PB.Ajax(url,params,callback);
}
if(!PB) var PB = {};

PB.Form = Class.create({
	initialize: function(element,options) {
		if(!$(element))
			return;
		
		this.element = $(element);
		this.url = this.element.readAttribute('action') || document.location;
		this.validations = {};
		this.onblurs = {};
		this.onchanges = {};
		this.onkeyups = {};
		this.element.observe('submit', this.submit.bindAsEventListener(this));
		
	    this.options = Object.extend({
			onSuccess:Prototype.emptyFunction,
			onServerErrors:Prototype.emptyFunction,
			onValidationErrors:Prototype.emptyFunction
		},options || {});
		
		this.setUpDefaultActions();
	},
	setUpDefaultActions:function()
	{
		$$('#'+this.element.readAttribute('id')+' input,textarea,select').each(function(element)
		{
			element.observe('focus',function(event)
			{
				if(event.element().up('li') && event.element().up('li').down('.input_details'))
					event.element().up('li').down('.input_details').show();
			});
			element.observe('blur',function(event)
			{
				if(event.element().up('li') && event.element().up('li').down('.input_details'))
					event.element().up('li').down('.input_details').hide();
			});
		}.bind(this));
		
		
	},
	validates:function(){},
	showHelp:function(element)
	{
		$(element).removeClassName('hidden');
		//new Effect.Appear($(element));
		//$(element).observe('mouseout',function(){new Effect.Fade($(element));});
	},
	showInputProgress:function(element)
	{
		$(element).wrap('div');
		$(element).up('div').insert('<img id="'+element+'_progress" style="position:absolute" src="/img/dev/small_throbber.gif"/>');
	},
	hideInputProgress:function(element)
	{
		$(element+'_progress').remove();
	},
	submit:function(call_back)
	{
		if (typeof(tinyMCE) !== 'undefined') {
			tinyMCE.triggerSave();
		}
		
		$$('.form_error').each(function(item) {
			item.update();
		});
		
		if(this.preSubmit && !this.preSubmit())
			return false;
		
		if(this.options.onSubmit && !this.options.onSubmit())
			return;
		
		if (this.form_data) {
			var form_data = this.form_data;
		} else {
			var form_data = PHPSerializer.serialize(this.element.serialize(true));
		}

		$ajax(this.url, {action:'process_form','form':this.element.readAttribute('id'),form_data:form_data},this.handleServerResponse.bind(this));
		return false;
	},
	handleServerResponse:function(response)
	{
		switch(response.code)
		{
			// all good
			case 200:
				this.onSuccess(response);
			break;
			//validation errors
			case 210:
				this.onValidationErrors(response.errors);
			break;
			
			//server errors
			case 211:
				this.onServerErrors(response.errors);
			break;
			
			//custom function callback
			case 201:
				this.on[response.funk](response);
			break;
		}
	},
	isArray:function()
	{
		if (typeof arguments[0] == 'object') 
		{  
			var criterion = arguments[0].constructor.toString().match(/array/i); 
 			return (criterion != null);  
 		}
 		return false;
 	},
	notifyWarn:function(){},
	notifyError:function(args)
	{
		$(args.field).addClassName('error');
	},
	onValidationErrors:function(errors)
	{
		growl_errors = '';
		if(this.isArray(errors))
		{
			$A(errors).each(function(error)
			{
					growl_errors += '<div>'+error+'</div>';
			});
		}
		else
		{
			$H(errors).each(function(error)
			{
				window.error = error;
				growl_errors += '<div>'+error.value+'</div>';
				if($(error.key))
				{
					$(error.key).addClassName('error');
					$(error.key).writeAttribute('title',error.value);
				
				if($(error.key).up('li') && $(error.key).up('li').down('.form_error'))
					$(error.key).up('li').down('.form_error').update(error.value);
				}
			}.bind(this));
		}
		window.growler.error(growl_errors,{header: "Please Fix These Errors."});
		this.options.onValidationError();
	},
	onServerErrors:function()
	{
		this.options.onServerErrors();
	},
	onSuccess:function(response)
	{
    this.options.onSuccess(response);
		if (response.info) {
			//document.location = document.location.href.split('#')[0];
			window.growler.info(response.info,{header:'Success.'});
		}
		
		if (response.location) {
			document.location = response.location.split('#')[0];
		}
	},
	onKeyUp:function(element)
	{
		this.onkeyups[$(element).readAttribute('id')]();
	},
	onBlur:function(element)
	{
		this.onblurs[$(element).readAttribute('id')]();
	},
	onChange:function(element)
	{
		this.onchanges[$(element).readAttribute('id')]();
	}
});

PB.Forms = {};

var signInForm = Class.create(PB.Form,{
	initialize:function($super,element,options)
	{
		$super(element,options || {});
	},
	preSubmit:function()
	{
		if($('email').value != '' && $('clear_pass').value != '')
			return true;
		
		else
			window.growler.error('You need to fill out the form completely.',{header:'Error.'});
		
		return false;
	},
	onSuccess:function(response)
	{
		foo = eval(response);
		if(foo.location)
			document.location = foo.location;
	}
});
function initSignInForm()
{
	if($('signin_form'))
		PB.Forms.sign_in_form = new signInForm('signin_form');
}
PB.addToDomLoad('initSignInForm','');


function initPager()
{
	if($$('.pager_bar').length > 0)
		PB.Pager = new pager();
}
PB.addToDomLoad('initPager','');

// lightwindow.js v2.0
//
// Copyright (c) 2007 stickmanlabs
// Author: Kevin P Miller | http://www.stickmanlabs.com
// 
// LightWindow is freely distributable under the terms of an MIT-style license.
//
// I don't care what you think about the file size...
//   Be a pro: 
//	    http://www.thinkvitamin.com/features/webapps/serving-javascript-fast
//      http://rakaz.nl/item/make_your_pages_load_faster_by_combining_and_compressing_javascript_and_css_files
//

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

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

// This will stop image flickering in IE6 when elements with images are moved
try {
	document.execCommand("BackgroundImageCache", false, true);
} catch(e) {}

var lightwindow = Class.create();	
lightwindow.prototype = {
	//
	//	Setup Variables
	//
	element : null,
	contentToFetch : null,
	windowActive : false,
	dataEffects : [],
	dimensions : {
		cruft : null,
		container : null,
		viewport : {
			height : null,
			width : null,
			offsetTop : null,
			offsetLeft : null
		}
	},
	pagePosition : {
		x : 0,
		y : 0
	},
	pageDimensions : {
		width : null,
		height : null
	},
	preloadImage : [],
	preloadedImage : [],
	galleries : [],
	resizeTo : {
		height : null,
		heightPercent : null,
		width : null,
		widthPercent : null,
		fixedTop : null,
		fixedLeft : null
	},
	scrollbarOffset : 18,
	navigationObservers : {
		previous : null,
		next : null
	},
	containerChange : {
		height : 0,
		width : 0
	},
	activeGallery : false,
	galleryLocation : {
		current : 0,
		total : 0
	},
	//
	//	Initialize the lightwindow.
	//
	initialize : function(options) {
		this.options = Object.extend({
			resizeSpeed : 8,
			contentOffset : {
				height : 0,
				width : 0
			},
			dimensions : {
				image : {height : 250, width : 250},
				page : {height : 250, width : 250},
				inline : {height : 350, width : 350},
				media : {height : 250, width : 250},
				external : {height : 250, width : 250},
				titleHeight : 25
			},
			classNames : {	
				standard : 'lightwindow',
				action : 'lightwindow_action'
			},
			fileTypes : {
				page : ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'pl', 'php4', 'php3', 'php', 'php5', 'phtml', 'rhtml', 'shtml', 'txt', 'vbs', 'rb'],
				media : ['aif', 'aiff', 'asf', 'avi', 'divx', 'm1v', 'm2a', 'm2v', 'm3u', 'mid', 'midi', 'mov', 'moov', 'movie', 'mp2', 'mp3', 'mpa', 'mpa', 'mpe', 'mpeg', 'mpg', 'mpg', 'mpga', 'pps', 'qt', 'rm', 'ram', 'swf', 'viv', 'vivo', 'wav'],
				image : ['bmp', 'gif', 'jpg', 'png', 'tiff']
			},
			mimeTypes : {
				avi : 'video/avi',
				aif : 'audio/aiff',
				aiff : 'audio/aiff',
				gif : 'image/gif',
				bmp : 'image/bmp',
				jpeg : 'image/jpeg',
				m1v : 'video/mpeg',
				m2a : 'audio/mpeg',
				m2v : 'video/mpeg',
				m3u : 'audio/x-mpequrl',
				mid : 'audio/x-midi',
				midi : 'audio/x-midi',
				mjpg : 'video/x-motion-jpeg',
				moov : 'video/quicktime',
				mov : 'video/quicktime',
				movie : 'video/x-sgi-movie',
				mp2 : 'audio/mpeg',
				mp3 : 'audio/mpeg3',
				mpa : 'audio/mpeg',
				mpa : 'video/mpeg',
				mpe : 'video/mpeg',
				mpeg : 'video/mpeg',
				mpg : 'audio/mpeg',
				mpg : 'video/mpeg',
				mpga : 'audio/mpeg',
				pdf : 'application/pdf',
				png : 'image/png',
				pps : 'application/mspowerpoint',
				qt : 'video/quicktime',
				ram : 'audio/x-pn-realaudio-plugin',
				rm : 'application/vnd.rn-realmedia',
				swf	: 'application/x-shockwave-flash',
				tiff : 'image/tiff',
				viv : 'video/vivo',
				vivo : 'video/vivo',
				wav : 'audio/wav',
				wmv : 'application/x-mplayer2'			
			},	
			classids : {
				mov : 'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B',
				swf : 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000',
				wmv : 'clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6'
			},
			codebases : {
				mov : 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0',
				swf : 'http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0',
				wmv : 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,4,5,715'
			},	
			viewportPadding : 10,
			EOLASFix : 'swf,wmv,fla,flv',
			overlay : {
				opacity : 0.7,
				image : '/img/lightwindow/black.png',
				presetImage : '/img/lightwindow/black-70.png'
			},
			skin : 	{
				main : '<div id="lightwindow_container" >'+
							'<div id="lightwindow_title_bar" >'+
								'<div id="lightwindow_title_bar_inner" >'+
									'<span id="lightwindow_title_bar_title"></span>'+
									'<a id="lightwindow_title_bar_close_link" >close</a>'+
								'</div>'+
							'</div>'+
							
							'<div id="lightwindow_stage" >'+
								'<div id="lightwindow_contents" >'+
								'</div>'+
								'<div id="lightwindow_navigation" >'+
									'<a href="#" id="lightwindow_previous" >'+
										'<span id="lightwindow_previous_title"></span>'+
									'</a>'+
									'<a href="#" id="lightwindow_next" >'+
										'<span id="lightwindow_next_title"></span>'+
									'</a>'+
									'<iframe name="lightwindow_navigation_shim" id="lightwindow_navigation_shim" src="javascript:false;" frameBorder="0" scrolling="no"></iframe>'+
								'</div>'+								
								'<div id="lightwindow_galleries">'+
									'<div id="lightwindow_galleries_tab_container" >'+
										'<a href="#" id="lightwindow_galleries_tab" >'+
											'<span id="lightwindow_galleries_tab_span" class="up" >Galleries</span>'+
										'</a>'+
									'</div>'+
									'<div id="lightwindow_galleries_list" >'+
									'</div>'+
								'</div>'+
							'</div>'+
							'<div id="lightwindow_data_slide" >'+
								'<div id="lightwindow_data_slide_inner" >'+
									'<div id="lightwindow_data_details" >'+
										'<div id="lightwindow_data_gallery_container" >'+
											'<span id="lightwindow_data_gallery_current"></span>'+
											' of '+
											'<span id="lightwindow_data_gallery_total"></span>'+
										'</div>'+
										'<div id="lightwindow_data_author_container" >'+
											'by <span id="lightwindow_data_author"></span>'+
										'</div>'+
									'</div>'+
									'<div id="lightwindow_data_caption" >'+
									'</div>'+
								'</div>'+
							'</div>'+
						'</div>',	
				loading : 	'<div id="lightwindow_loading" >'+
								'<img src="/img/lightwindow/ajax-loading.gif" alt="loading" />'+
								'<span>Loading or <a href="javascript: myLightWindow.deactivate();">Cancel</a></span>'+
								'<iframe name="lightwindow_loading_shim" id="lightwindow_loading_shim" src="javascript:false;" frameBorder="0" scrolling="no"></iframe>'+
							'</div>',
				iframe : 	'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'+
							'<html xmlns="http://www.w3.org/1999/xhtml">'+
								'<body>'+
									'{body_replace}'+
								'</body>'+
							'</html>',
				gallery : {
					top :		'<div class="lightwindow_galleries_list">'+
									'<h1>{gallery_title_replace}</h1>'+
									'<ul>',
					middle : 			'<li>'+
											'{gallery_link_replace}'+
										'</li>',
					bottom : 		'</ul>'+
								'</div>'
				}
			},
			formMethod : 'get',
			hideFlash : false,
			hideGalleryTab : false,
			showTitleBar : true,
			animationHandler : false,
			navigationHandler : false,
			transitionHandler : false,
			finalAnimationHandler : false,
			formHandler : false,
			galleryAnimationHandler : false,
			showGalleryCount : true
		}, options || {});
		this.duration = ((11-this.options.resizeSpeed)*0.15);
		this._setupLinks();
		this._getScroll();
		this._getPageDimensions();
		this._browserDimensions();
		this._addLightWindowMarkup(false);
		this._setupDimensions(); 
		this.buildGalleryList();
	},
	//
	//	Activate the lightwindow.
	//
	activate : function(e, link){		
		// Clear out the window Contents
		this._clearWindowContents(true);
			
		// Add back in out loading panel
		this._addLoadingWindowMarkup();

		// Setup the element properties
		this._setupWindowElements(link);
		
		// Setup everything
		this._getScroll();
		this._browserDimensions();
		this._setupDimensions();
		this._toggleTroubleElements('hidden', false);
		this._displayLightWindow('block', 'hidden');
		this._setStatus(true);
		this._monitorKeyboard(true);
		this._prepareIE(true);
		this._loadWindow();
		
		if($$('.reply_btn').length > 0)
		{
			$$('.reply_btn').each(function(item){
				item.stopObserving('click');
				item.observe('click',PB.Inbox.reply.bindAsEventListener(this));
			}.bind(this));
		}
	},
	//
	//	Turn off the window
	//
	deactivate : function(){
		// The window is not active
		this.windowActive = false;
		
		// There is no longer a gallery active
		this.activeGallery = false;
		if (!this.options.hideGalleryTab) {
			this._handleGalleryAnimation(false);
		}
		
		// Kill the animation
		this.animating = false;
		
		// Clear our element
		this.element = null;
		
		// hide the window.
		this._displayLightWindow('none', 'visible');
		
		// Clear out the window Contents
		this._clearWindowContents(false);
		
		// Stop all animation
		var queue = Effect.Queues.get('lightwindowAnimation').each(function(e){e.cancel();});
		
		// Undo the setup
		this._prepareIE(false);
		this._setupDimensions();
		this._toggleTroubleElements('visible', false);	
		this._monitorKeyboard(false);	
	},
	//
	//  Initialize specific window
	//
	createWindow : function(element, attributes) {
		this._processLink($(element));
	},
	//
	//  Open a Window from a hash of attributes
	//
	activateWindow : function(options) {
		this.element = Object.extend({
			href : null,
			title : null,
			author : null,
			caption : null,
			rel : null,
			top : null,
			left : null,
			type : null,
			showImages : null,
			height : null,
			width : null,
			loadingAnimation : null,
			iframeEmbed : null,
			form : null
		}, options || {});
		
		// Set the window type
		this.contentToFetch = this.element.href;
		this.windowType = this.element.type ? this.element.type : this._fileType(this.element.href);	
		
		// Clear out the window Contents
		this._clearWindowContents(true);
			
		// Add back in out loading panel
		this._addLoadingWindowMarkup();
		
		// Setup everything
		this._getScroll();
		this._browserDimensions();
		this._setupDimensions();
		this._toggleTroubleElements('hidden', false);
		this._displayLightWindow('block', 'hidden');
		this._setStatus(true);
		this._monitorKeyboard(true);
		this._prepareIE(true);
		this._loadWindow();
	},
	//
	//  Fire off our Form handler
	//
	submitForm : function(e) {
		if (this.options.formHandler) {
			this.options.formHandler(e);
		} else {
			this._defaultFormHandler(e);
		}
	},
	//
	//	Reload the window with another location
	//
	openWindow : function(element) {
		var element = $(element);

		// The window is active
		this.windowActive = true;
		
		// Clear out the window Contents
		this._clearWindowContents(true);
		
		// Add back in out loading panel
		this._addLoadingWindowMarkup();
		
		// Setup the element properties
		this._setupWindowElements(element);

		this._setStatus(true);
		this._handleTransition();
	},
	//
	//  Navigate the window
	//
	navigateWindow : function(direction) {
		this._handleNavigation(false);
		if (direction == 'previous') {
			this.openWindow(this.navigationObservers.previous);
		} else if (direction == 'next'){ 
			this.openWindow(this.navigationObservers.next);
		}
	},
	//
	//  Build the Gallery List and Load it
	//
	buildGalleryList : function() {
		var output = '';
		var galleryLink;
		for (i in this.galleries) {
			if (typeof this.galleries[i] == 'object') {
				output += (this.options.skin.gallery.top).replace('{gallery_title_replace}', unescape(i));
				for (j in this.galleries[i]) {
					if (typeof this.galleries[i][j] == 'object') {						
						galleryLink = '<a href="#" id="lightwindow_gallery_'+i+'_'+j+'" >'+unescape(j)+'</a>';
						output += (this.options.skin.gallery.middle).replace('{gallery_link_replace}', galleryLink);
					}
				}
				output += this.options.skin.gallery.bottom;
			}
		}
		new Insertion.Top('lightwindow_galleries_list', output);
		
		// Attach Events
		for (i in this.galleries) {
			if (typeof this.galleries[i] == 'object') {
				for (j in this.galleries[i]) {
					if (typeof this.galleries[i][j] == 'object') {
						Event.observe($('lightwindow_gallery_'+i+'_'+j), 'click', this.openWindow.bind(this, this.galleries[i][j][0]), false);
						$('lightwindow_gallery_'+i+'_'+j).onclick = function() {return false;};	
					}
				}
			}
		}
	},
	// 
	//  Set Links Up
	//
	_setupLinks : function() {
		var links = $$('.'+this.options.classNames.standard);
		links.each(function(link) {
			this._processLink(link);
		}.bind(this));	
	},
	//
	//  Process a Link
	//
	_processLink : function(link) {
		if ((this._fileType(link.getAttribute('href')) == 'image' || this._fileType(link.getAttribute('href')) == 'media')) {
			if (gallery = this._getGalleryInfo(link.rel)) {
				if (!this.galleries[gallery[0]]) {
					this.galleries[gallery[0]] = new Array();
				}
				if (!this.galleries[gallery[0]][gallery[1]]) {
					this.galleries[gallery[0]][gallery[1]] = new Array();
				}
				this.galleries[gallery[0]][gallery[1]].push(link);
			}
		}
		
		// Take care of our inline content
		var url = link.getAttribute('href');
		if (url.indexOf('?') > -1) {
			url = url.substring(0, url.indexOf('?'));
		}
		
		var container = url.substring(url.indexOf('#')+1);
		if($(container)) {
			$(container).setStyle({
				display : 'none'
			});
		}
		
		Event.observe(link, 'click', this.activate.bindAsEventListener(this, link), false);
		link.onclick = function() {return false;};		
	},
	//
	//	Setup our actions
	//
	_setupActions : function() {
		var links = $$('#lightwindow_container .'+this.options.classNames.action);
		links.each(function(link) {
			Event.observe(link, 'click', this[link.getAttribute('rel')].bindAsEventListener(this, link), false);
			link.onclick = function() {return false;};
		}.bind(this));
	},
	//
	//	Add the markup to the page.
	//
	_addLightWindowMarkup : function(rebuild) {
		var overlay = Element.extend(document.createElement('div'));
		overlay.setAttribute('id', 'lightwindow_overlay');		
		// FF Mac has a problem with putting Flash above a layer without a 100% opacity background, so we need to use a pre-made
		if (Prototype.Browser.Gecko) {
			overlay.setStyle({
				backgroundImage: 'url('+this.options.overlay.presetImage+')',
				backgroundRepeat: 'repeat',
				height: this.pageDimensions.height+'px'
			});			
		} else {
			overlay.setStyle({
				opacity: this.options.overlay.opacity,
				backgroundImage: 'url('+this.options.overlay.image+')',
				backgroundRepeat: 'repeat',
				height: this.pageDimensions.height+'px'
			});
		}
		
		var lw = document.createElement('div');
		lw.setAttribute('id', 'lightwindow');
		lw.innerHTML = this.options.skin.main;
		
		var body = document.getElementsByTagName('body')[0];
		body.appendChild(overlay);
		body.appendChild(lw);	
				
		if ($('lightwindow_title_bar_close_link')) {
			Event.observe('lightwindow_title_bar_close_link', 'click', this.deactivate.bindAsEventListener(this));
			$('lightwindow_title_bar_close_link').onclick = function() {return false;};
		}
			
		Event.observe($('lightwindow_previous'), 'click', this.navigateWindow.bind(this, 'previous'), false);
		$('lightwindow_previous').onclick = function() {return false;};		
		Event.observe($('lightwindow_next'), 'click', this.navigateWindow.bind(this, 'next'), false);
		$('lightwindow_next').onclick = function() {return false;};

		if (!this.options.hideGalleryTab) {
			Event.observe($('lightwindow_galleries_tab'), 'click', this._handleGalleryAnimation.bind(this, true), false);
			$('lightwindow_galleries_tab').onclick = function() {return false;};
		}
		
		// Because we use position absolute, kill the scroll Wheel on animations
		if (Prototype.Browser.IE) {
			Event.observe(document, 'mousewheel', this._stopScrolling.bindAsEventListener(this), false);
		} else {
			Event.observe(window, 'DOMMouseScroll', this._stopScrolling.bindAsEventListener(this), false);
		}
				
		Event.observe(overlay, 'click', this.deactivate.bindAsEventListener(this), false);
		overlay.onclick = function() {return false;};
	},
	//
	//  Add loading window markup
	//
	_addLoadingWindowMarkup : function() {
		$('lightwindow_contents').innerHTML += this.options.skin.loading;
	},
	//
	//  Setup the window elements
	//
	_setupWindowElements : function(link) {
		this.element = link;
		this.element.title = null ? '' : link.getAttribute('title');
		this.element.author = null ? '' : link.getAttribute('author');
		this.element.caption = null ? '' : link.getAttribute('caption');
		this.element.rel = null ? '' : link.getAttribute('rel');
		this.element.params = null ? '' : link.getAttribute('params');

		// Set the window type
		this.contentToFetch = this.element.href;
		this.windowType = this._getParameter('lightwindow_type') ? this._getParameter('lightwindow_type') : this._fileType(this.contentToFetch);	
	},
	//
	//  Clear the window contents out
	//
	_clearWindowContents : function(contents) {
		// If there is an iframe, its got to go
		if ($('lightwindow_iframe')) {
			Element.remove($('lightwindow_iframe'));
		}

		// Stop playing an object if its still around
		if ($('lightwindow_media_primary')) {
			try {
				$('lightwindow_media_primary').Stop();
			} catch(e) {}
			Element.remove($('lightwindow_media_primary'));
		}

		// Stop playing an object if its still around		
		if ($('lightwindow_media_secondary')) {
			try {
				$('lightwindow_media_secondary').Stop();
			} catch(e) {}
			Element.remove($('lightwindow_media_secondary'));
		}
		
		this.activeGallery = false;
		this._handleNavigation(this.activeGallery);
		
		if (contents) {
			// Empty the contents
			$('lightwindow_contents').innerHTML = '';
			
			// Reset the scroll bars
			$('lightwindow_contents').setStyle({
				overflow: 'hidden'
			});		
			
			if (!this.windowActive) {
				$('lightwindow_data_slide_inner').setStyle({
					display: 'none'
				});

				$('lightwindow_title_bar_title').innerHTML = '';
			}

			// Because of browser differences and to maintain flexible captions we need to reset this height at close
			$('lightwindow_data_slide').setStyle({
				height: 'auto'
			});
		}
		
		this.resizeTo.height = null;
		this.resizeTo.width = null;
	},
	//
	//	Set the status of our animation to keep things from getting clunky
	//
	_setStatus : function(status) {
		this.animating = status;
		if (status) {
			Element.show('lightwindow_loading');
		}
		if (!(/MSIE 6./i.test(navigator.userAgent))) {
			this._fixedWindow(status);
		}
	},
	//
	//  Make this window Fixed
	//
	_fixedWindow : function(status) {
		if (status) {
			if (this.windowActive) {
				this._getScroll();
				$('lightwindow').setStyle({
					position: 'absolute',
					top: parseFloat($('lightwindow').getStyle('top'))+this.pagePosition.y+'px',
					left: parseFloat($('lightwindow').getStyle('left'))+this.pagePosition.x+'px'
				});		
			} else {
				$('lightwindow').setStyle({
					position: 'absolute'
				});						
			}
		} else {
			if (this.windowActive) {
				this._getScroll();
				$('lightwindow').setStyle({
					position: 'fixed',
					top: parseFloat($('lightwindow').getStyle('top'))-this.pagePosition.y+'px',
					left: parseFloat($('lightwindow').getStyle('left'))-this.pagePosition.x+'px'
				});		
			} else {
				if ($('lightwindow_iframe')) {
					// Ideally here we would set a 50% value for top and left, but Safari rears it ugly head again and we need to do it by pixels
					this._browserDimensions();
				}
				$('lightwindow').setStyle({
					position: 'fixed',
					top: (parseFloat(this._getParameter('lightwindow_top')) ? parseFloat(this._getParameter('lightwindow_top'))+'px' : this.dimensions.viewport.height/2+'px'),
					left: (parseFloat(this._getParameter('lightwindow_left')) ? parseFloat(this._getParameter('lightwindow_left'))+'px' : this.dimensions.viewport.width/2+'px')
				});
			}
		}
	},
	//
	//	Prepare the window for IE.
	//
	_prepareIE : function(setup) {
		if (Prototype.Browser.IE) {
			var height, overflowX, overflowY;
			if (setup) { 
				var height = '100%';
			} else {
				var height = 'auto';
			}
			var body = document.getElementsByTagName('body')[0];
			var html = document.getElementsByTagName('html')[0];
			html.style.height = body.style.height = height;
		}
	},
	_stopScrolling : function(e) {
		if (this.animating) {
			if (e.preventDefault) {
				e.preventDefault();
			}
			e.returnValue = false;		
		}
	},
	//
	//	Get the scroll for the page.
	//
	_getScroll : function(){
      	if(typeof(window.pageYOffset) == 'number') {
        	this.pagePosition.x = window.pageXOffset;
        	this.pagePosition.y = window.pageYOffset;
      	} else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
	       	this.pagePosition.x = document.body.scrollLeft;
        	this.pagePosition.y = document.body.scrollTop;
		} else if(document.documentElement) {
        	this.pagePosition.x = document.documentElement.scrollLeft;
        	this.pagePosition.y = document.documentElement.scrollTop;
      	}
	},
	//
	//	Reset the scroll.
	//
	_setScroll : function(x, y) {
		document.documentElement.scrollLeft = x; 
		document.documentElement.scrollTop = y; 
	},
	//
	//	Hide Selects from the page because of IE.
	//     We could use iframe shims instead here but why add all the extra markup for one browser when this is much easier and cleaner
	//
	_toggleTroubleElements : function(visibility, content){
		
		if (content) {
			var selects = $('lightwindow_contents').getElementsByTagName('select');
		} else {
			var selects = document.getElementsByTagName('select');
		}
		
		for(var i = 0; i < selects.length; i++) {
			selects[i].style.visibility = visibility;
		}
		
		if (!content) {
			if (this.options.hideFlash){
				var objects = document.getElementsByTagName('object');
				for (i = 0; i != objects.length; i++) {
					objects[i].style.visibility = visibility;
				}
				var embeds = document.getElementsByTagName('embed');
				for (i = 0; i != embeds.length; i++) {
					embeds[i].style.visibility = visibility;
				}
			}
			var iframes = document.getElementsByTagName('iframe');
			for (i = 0; i != iframes.length; i++) {
				iframes[i].style.visibility = visibility;
			}
		}
	},
	// 
	//  Get the actual page size
	//
	_getPageDimensions : function() {
		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){ 
			xScroll = document.body.scrollWidth;
			yScroll = document.body.scrollHeight;
		} else { 
			xScroll = document.body.offsetWidth;
			yScroll = document.body.offsetHeight;
		}

		var windowWidth, windowHeight;
		if (self.innerHeight) {	
			windowWidth = self.innerWidth;
			windowHeight = self.innerHeight;
		} else if (document.documentElement && document.documentElement.clientHeight) { 
			windowWidth = document.documentElement.clientWidth;
			windowHeight = document.documentElement.clientHeight;
		} else if (document.body) { 
			windowWidth = document.body.clientWidth;
			windowHeight = document.body.clientHeight;
		}	

		if(yScroll < windowHeight){
			this.pageDimensions.height = windowHeight;
		} else { 
			this.pageDimensions.height = yScroll;
		}

		if(xScroll < windowWidth){	
			this.pageDimensions.width = windowWidth;
		} else {
			this.pageDimensions.width = xScroll;
		}
	},
	//
	//	Display the lightWindow.
	//
	_displayLightWindow : function(display, visibility) {
		$('lightwindow_overlay').style.display = $('lightwindow').style.display = $('lightwindow_container').style.display = display;	
		$('lightwindow_overlay').style.visibility = $('lightwindow').style.visibility = $('lightwindow_container').style.visibility = visibility;
	},
	//
	//	Setup Dimensions of lightwindow.

	//
	_setupDimensions : function() {

		var originalHeight, originalWidth;
		switch (this.windowType) {
			case 'page' :
				originalHeight = this.options.dimensions.page.height;
				originalWidth = this.options.dimensions.page.width;
				break;

			case 'image' :
				originalHeight = this.options.dimensions.image.height;
				originalWidth = this.options.dimensions.image.width;
				break;
				
			case 'media' :
				originalHeight = this.options.dimensions.media.height;
				originalWidth = this.options.dimensions.media.width;
				break;
			
			case 'external' : 
				originalHeight = this.options.dimensions.external.height;
				originalWidth = this.options.dimensions.external.width;
				break;
				
			case 'inline' :
				originalHeight = this.options.dimensions.inline.height;
				originalWidth = this.options.dimensions.inline.width;
				break;
				
			default :
				originalHeight = this.options.dimensions.page.height;
				originalWidth = this.options.dimensions.page.width;
				break;
				
		}

		var offsetHeight = this._getParameter('lightwindow_top') ? parseFloat(this._getParameter('lightwindow_top'))+this.pagePosition.y : this.dimensions.viewport.height/2+this.pagePosition.y;
		var offsetWidth = this._getParameter('lightwindow_left') ? parseFloat(this._getParameter('lightwindow_left'))+this.pagePosition.x : this.dimensions.viewport.width/2+this.pagePosition.x;
	//	alert('top: '+offsetHeight+'
		
		// So if a theme has say shadowed edges, they should be consistant and take care of in the contentOffset
	//	$('lightwindow').setStyle({
	//		top: offsetHeight+'px',
	//		left: offsetWidth+'px'
	//	});
		
		$('lightwindow_container').setStyle({
			height: originalHeight+'px',
			width: originalWidth+'px',
			left: -(originalWidth/2)+'px',
			top: -(originalHeight/2)+'px'
		});

		$('lightwindow_contents').setStyle({
			height: originalHeight+'px',
			width: originalWidth+'px'
		});
	},
	//
	//	Get the type of file.
	//
	_fileType : function(url) {
		var image = new RegExp("[^\.]\.("+this.options.fileTypes.image.join('|')+")\s*$", "i");
		if (image.test(url)) return 'image';
		if (url.indexOf('#') > -1 && (document.domain == this._getDomain(url))) return 'inline';		
		if (url.indexOf('?') > -1) url = url.substring(0, url.indexOf('?'));
		var type = 'unknown';
		var page = new RegExp("[^\.]\.("+this.options.fileTypes.page.join('|')+")\s*$", "i");
		var media = new RegExp("[^\.]\.("+this.options.fileTypes.media.join('|')+")\s*$", "i");
		if (document.domain != this._getDomain(url)) type = 'external';
	  	if (media.test(url)) type = 'media';
		if (type == 'external' || type == 'media') return type;
	  	if (page.test(url) || url.substr((url.length-1), url.length) == '/') type = 'page';
		return type;
	},
	//
	//  Get file Extension
	//
	_fileExtension : function(url) {
		if (url.indexOf('?') > -1) {
			url = url.substring(0, url.indexOf('?'));
		}
		var extenstion = '';
		for (var x = (url.length-1); x > -1; x--) {
			if (url.charAt(x) == '.') {
				return extenstion;
			}
			extenstion = url.charAt(x)+extenstion;
		}
	},
	//
	//	Monitor the keyboard while this lightwindow is up
	//
	_monitorKeyboard : function(status) {
		if (status) document.onkeydown = this._eventKeypress.bind(this); 
		else document.onkeydown = '';
	},
	//
	//  Perform keyboard actions
	//
	_eventKeypress : function(e) {
		if (e == null) {
			var keycode = event.keyCode;
		} else {
			var keycode = e.which;
		}
		
		switch (keycode) { 
			case 27: 
				this.deactivate(); 
				break;
			
			case 13:
				return;
				
			default:
				break;
		}
	
		// Gotta stop those quick fingers
		if (this.animating) {
			return false;
		}
		
		switch (String.fromCharCode(keycode).toLowerCase()) {
			case 'p':
				if (this.navigationObservers.previous) {
					this.navigateWindow('previous');
				}
				break;
				
			case 'n':
				if (this.navigationObservers.next) {
					this.navigateWindow('next');
				}
				break;
				
			default:
				break;
		}
	},
	//
	//	Get Gallery Information
	//
	_getGalleryInfo : function(rel) {
		if (!rel) return false;
		if (rel.indexOf('[') > -1) {
			return new Array(escape(rel.substring(0, rel.indexOf('['))), escape(rel.substring(rel.indexOf('[')+1, rel.indexOf(']'))));
		} else {
			return false;
		}
	},
	//
	//	Get the domain from a string.
	//
	_getDomain : function(url) {    
        var leadSlashes = url.indexOf('//');
        var domainStart = leadSlashes+2;
        var withoutResource = url.substring(domainStart, url.length);
        var nextSlash = withoutResource.indexOf('/');
        var domain = withoutResource.substring(0, nextSlash);
		if (domain.indexOf(':') > -1){
			var portColon = domain.indexOf(':');
			domain = domain.substring(0, portColon);
       	}
		return domain;
    },
	//
	//	Get the value from the params attribute string.
	//
	_getParameter : function(parameter, parameters) {
		if (!this.element) return false;
		if (parameter == 'lightwindow_top' && this.element.top) {
			return unescape(this.element.top);
		} else if (parameter == 'lightwindow_left' && this.element.left) {
			return unescape(this.element.left);
		} else if (parameter == 'lightwindow_type' && this.element.type) {
			return unescape(this.element.type);
		} else if (parameter == 'lightwindow_show_images' && this.element.showImages) {
			return unescape(this.element.showImages);
		} else if (parameter == 'lightwindow_height' && this.element.height) {
			return unescape(this.element.height);
		} else if (parameter == 'lightwindow_width' && this.element.width) {
			return unescape(this.element.width);
		} else if (parameter == 'lightwindow_loading_animation' && this.element.loadingAnimation) {
			return unescape(this.element.loadingAnimation);
		} else if (parameter == 'lightwindow_iframe_embed' && this.element.iframeEmbed) {
			return unescape(this.element.iframeEmbed);
		} else if (parameter == 'lightwindow_form' && this.element.form) {
			return unescape(this.element.form);
		} else {
			if (!parameters) {
				if (this.element.params) parameters = this.element.params;
				else return;
			}
			var value;
			var parameterArray = parameters.split(',');
			var compareString = parameter+'=';
			var compareLength = compareString.length;
			for (var i = 0; i < parameterArray.length; i++) {
				if (parameterArray[i].substr(0, compareLength) == compareString) {
					var currentParameter = parameterArray[i].split('=');
					value = currentParameter[1];
					break;
				}
			}
			if (!value) return false;
			else return unescape(value);
		}
	},
	//
	//  Get the Browser Viewport Dimensions
	//
	_browserDimensions : function() {
		if (Prototype.Browser.IE) {
            this.dimensions.viewport.height = document.documentElement.clientHeight;
            this.dimensions.viewport.width = document.documentElement.clientWidth;   
        } else {
            this.dimensions.viewport.height = window.innerHeight;
            this.dimensions.viewport.width = document.width || document.body.offsetWidth;
        }
	},
	//
	//  Get the scrollbar offset, I don't like this method but there is really no other way I can find.
	//
	_getScrollerWidth : function() {
	    var scrollDiv = Element.extend(document.createElement('div'));
		scrollDiv.setAttribute('id', 'lightwindow_scroll_div');
		scrollDiv.setStyle({
			position: 'absolute',
			top: '-10000px',
			left: '-10000px',
			width: '100px',
			height: '100px',
			overflow: 'hidden'
		});



	    var contentDiv = Element.extend(document.createElement('div'));
		contentDiv.setAttribute('id', 'lightwindow_content_scroll_div');
		contentDiv.setStyle({
			width: '100%',
			height: '200px'
		});

	    scrollDiv.appendChild(contentDiv);

		var body = document.getElementsByTagName('body')[0];
		body.appendChild(scrollDiv);

	    var noScroll = $('lightwindow_content_scroll_div').offsetWidth;
	    scrollDiv.style.overflow = 'auto';
    	var withScroll = $('lightwindow_content_scroll_div').offsetWidth;

	   	Element.remove($('lightwindow_scroll_div'));

	    this.scrollbarOffset = noScroll-withScroll;
	},
	

	//
	//  Add a param to an object dynamically created
	//
	_addParamToObject : function(name, value, object, id) {
		var param = document.createElement('param');
		param.setAttribute('value', value);
		param.setAttribute('name', name);
		if (id) {
			param.setAttribute('id', id);
		}
		object.appendChild(param);
		return object;
	},
	//
	//  Get the outer HTML of an object CROSS BROWSER
	//
	_outerHTML : function(object) {
 		if (Prototype.Browser.IE) {
			return object.outerHTML;
		} else {
			var clone = object.cloneNode(true);
			var cloneDiv = document.createElement('div');
			cloneDiv.appendChild(clone);
			return cloneDiv.innerHTML;
		}
	},
	//
	//  Convert an object to markup
	//
	_convertToMarkup : function(object, closeTag) {
		var markup = this._outerHTML(object).replace('</'+closeTag+'>', '');
		if (Prototype.Browser.IE) {
			for (var i = 0; i < object.childNodes.length; i++){
				markup += this._outerHTML(object.childNodes[i]);
			}
			markup += '</'+closeTag+'>';
		}
		return markup;
	},
	//
	//  Depending what type of browser it is we have to append the object differently... DAMN YOU IE!!
	//
	_appendObject : function(object, closeTag, appendTo) {
		if (Prototype.Browser.IE) {
			appendTo.innerHTML += this._convertToMarkup(object, closeTag);
			
			// Fix the Eolas activate thing but only for specified media, for example doing this to a quicktime film breaks it.
			if (this.options.EOLASFix.indexOf(this._fileType(this.element.href)) > -1) {
				var objectElements = document.getElementsByTagName('object');
				for (var i = 0; i < objectElements.length; i++) {
					if (objectElements[i].getAttribute("data")) objectElements[i].removeAttribute('data');
					objectElements[i].outerHTML = objectElements[i].outerHTML;
					objectElements[i].style.visibility = "visible";
				}
			}
		} else {
			appendTo.appendChild(object);	
		}	
	},
	//
	//  Add in iframe
	//
	_appendIframe : function(scroll) {
		var iframe = document.createElement('iframe');
		iframe.setAttribute('id', 'lightwindow_iframe');
		iframe.setAttribute('name', 'lightwindow_iframe');
		iframe.setAttribute('src', 'about:blank');
		iframe.setAttribute('height', '100%');
		iframe.setAttribute('width', '100%');
		iframe.setAttribute('frameborder', '0');
		iframe.setAttribute('marginwidth', '0');
		iframe.setAttribute('marginheight', '0');
		iframe.setAttribute('scrolling', scroll);	
		
		this._appendObject(iframe, 'iframe', $('lightwindow_contents'));
	},
	//
	//  Write Content to the iframe using the skin
	//
	_writeToIframe : function(content) {
		var template = this.options.skin.iframe;
		template = template.replace('{body_replace}', content); 
		if ($('lightwindow_iframe').contentWindow){
			$('lightwindow_iframe').contentWindow.document.open();
			$('lightwindow_iframe').contentWindow.document.write(template);
			$('lightwindow_iframe').contentWindow.document.close();
		} else {
			$('lightwindow_iframe').contentDocument.open();
			$('lightwindow_iframe').contentDocument.write(template);
			$('lightwindow_iframe').contentDocument.close();
		}
	},
	//
	//  Load the window Information
	//  
	_loadWindow : function() {
		switch (this.windowType) {
			case 'image' :

				var current = 0;
				var images = [];
				this.checkImage = [];
				this.resizeTo.height = this.resizeTo.width = 0;
				this.imageCount = this._getParameter('lightwindow_show_images') ? parseInt(this._getParameter('lightwindow_show_images')) : 1;

				// If there is a gallery get it
				if (gallery = this._getGalleryInfo(this.element.rel)) {	
					for (current = 0; current < this.galleries[gallery[0]][gallery[1]].length; current++) {
						if (this.contentToFetch.indexOf(this.galleries[gallery[0]][gallery[1]][current].href) > -1) {
							break;
						}
					}
					if (this.galleries[gallery[0]][gallery[1]][current-this.imageCount]) {
						this.navigationObservers.previous = this.galleries[gallery[0]][gallery[1]][current-this.imageCount];
					} else {
						this.navigationObservers.previous = false;
					}
					if (this.galleries[gallery[0]][gallery[1]][current+this.imageCount]) {
						this.navigationObservers.next = this.galleries[gallery[0]][gallery[1]][current+this.imageCount];
					} else {
						this.navigationObservers.next = false;
					}
					
					this.activeGallery = true;
				} else {
					this.navigationObservers.previous = false;
					this.navigationObservers.next = false;					

					this.activeGallery = false;
				}
				
				for (var i = current; i < (current+this.imageCount); i++) {
		
					if (gallery && this.galleries[gallery[0]][gallery[1]][i]) {
						this.contentToFetch = this.galleries[gallery[0]][gallery[1]][i].href;
						
						this.galleryLocation = {current: (i+1)/this.imageCount, total: (this.galleries[gallery[0]][gallery[1]].length)/this.imageCount};
											
						if (!this.galleries[gallery[0]][gallery[1]][i+this.imageCount]) {
							$('lightwindow_next').setStyle({
								display: 'none'
							});
						} else {
							$('lightwindow_next').setStyle({
								display: 'block'
							});
							$('lightwindow_next_title').innerHTML = this.galleries[gallery[0]][gallery[1]][i+this.imageCount].title;
						}
						
						if (!this.galleries[gallery[0]][gallery[1]][i-this.imageCount]) {
							$('lightwindow_previous').setStyle({
								display: 'none'
							});
						} else {
							$('lightwindow_previous').setStyle({
								display: 'block'
							});
							$('lightwindow_previous_title').innerHTML = this.galleries[gallery[0]][gallery[1]][i-this.imageCount].title;
						}
					}

					images[i] = document.createElement('img');
					images[i].setAttribute('id', 'lightwindow_image_'+i);
					images[i].setAttribute('border', '0');
					images[i].setAttribute('src', this.contentToFetch);
					$('lightwindow_contents').appendChild(images[i]);

					// We have to do this instead of .onload 
					this.checkImage[i] = new PeriodicalExecuter(function(i) {
						if (!(typeof $('lightwindow_image_'+i).naturalWidth != "undefined" && $('lightwindow_image_'+i).naturalWidth == 0)) {
	
							this.checkImage[i].stop();
	
							var imageHeight = $('lightwindow_image_'+i).getHeight();
							if (imageHeight > this.resizeTo.height) {
								this.resizeTo.height = imageHeight;
							}
							this.resizeTo.width += $('lightwindow_image_'+i).getWidth();
							this.imageCount--;
	
							$('lightwindow_image_'+i).setStyle({
								height: '100%'
							});
	
						 	if (this.imageCount == 0) {
								this._processWindow();
						 	}
						}
					
					}.bind(this, i), 1);			
				}


			break;
		
		case 'media' :			
		
			var current = 0;
			this.resizeTo.height = this.resizeTo.width = 0;

			// If there is a gallery get it
			if (gallery = this._getGalleryInfo(this.element.rel)) {	
				for (current = 0; current < this.galleries[gallery[0]][gallery[1]].length; current++) {
					if (this.contentToFetch.indexOf(this.galleries[gallery[0]][gallery[1]][current].href) > -1) {
						break;
					}
				}
				
				if (this.galleries[gallery[0]][gallery[1]][current-1]) {
					this.navigationObservers.previous = this.galleries[gallery[0]][gallery[1]][current-1];
				} else {
					this.navigationObservers.previous = false;
				}
				if (this.galleries[gallery[0]][gallery[1]][current+1]) {
					this.navigationObservers.next = this.galleries[gallery[0]][gallery[1]][current+1];
				} else {
					this.navigationObservers.next = false;
				}
		
				this.activeGallery = true;
			} else {
				this.navigationObservers.previous = false;
				this.navigationObservers.next = false;
				
				this.activeGallery = false;
			}
		

			if (gallery && this.galleries[gallery[0]][gallery[1]][current]) {
				this.contentToFetch = this.galleries[gallery[0]][gallery[1]][current].href;

				this.galleryLocation = {current: current+1, total: this.galleries[gallery[0]][gallery[1]].length};
				
				if (!this.galleries[gallery[0]][gallery[1]][current+1]) {
					$('lightwindow_next').setStyle({
						display: 'none'
					});
				} else {
					$('lightwindow_next').setStyle({
						display: 'block'
					});
					$('lightwindow_next_title').innerHTML = this.galleries[gallery[0]][gallery[1]][current+1].title;
				}
				
				if (!this.galleries[gallery[0]][gallery[1]][current-1]) {
					$('lightwindow_previous').setStyle({
						display: 'none'
					});
				} else {
					$('lightwindow_previous').setStyle({
						display: 'block'
					});
					$('lightwindow_previous_title').innerHTML = this.galleries[gallery[0]][gallery[1]][current-1].title;
				}
			}
			
			if (this._getParameter('lightwindow_iframe_embed')) {
				this.resizeTo.height = this.dimensions.viewport.height;
				this.resizeTo.width = this.dimensions.viewport.width;	
			} else {
				this.resizeTo.height = this._getParameter('lightwindow_height');
				this.resizeTo.width = this._getParameter('lightwindow_width');				
			}
			
			this._processWindow();
			
			break;

		case 'external' :		

			this._appendIframe('auto');

			this.resizeTo.height = this.dimensions.viewport.height;
			this.resizeTo.width = this.dimensions.viewport.width;
						
			this._processWindow();

			break;
				
		case 'page' :	
			
			var newAJAX = new Ajax.Request(
				this.contentToFetch, {
					method: 'get', 
					parameters: '', 
					onComplete: function(response) {
						$('lightwindow_contents').innerHTML += response.responseText;
						this.resizeTo.height = $('lightwindow_contents').scrollHeight+(this.options.contentOffset.height);
						this.resizeTo.width = $('lightwindow_contents').scrollWidth+(this.options.contentOffset.width);
						this._processWindow();
					}.bind(this)
				}
			);
			
			break;
			
		case 'inline' : 
		
			var content = this.contentToFetch;
			if (content.indexOf('?') > -1) {
				content = content.substring(0, content.indexOf('?'));
			}
			content = content.substring(content.indexOf('#')+1);
			
			new Insertion.Top($('lightwindow_contents'), $(content).innerHTML);
			
			this.resizeTo.height = $('lightwindow_contents').scrollHeight+(this.options.contentOffset.height);
			this.resizeTo.width = $('lightwindow_contents').scrollWidth+(this.options.contentOffset.width);
			
			this._toggleTroubleElements('hidden', true); 			
			this._processWindow();
			
			break;
			
		default : 
			throw("Page Type could not be determined, please amend this lightwindow URL "+this.contentToFetch);
			break;
		}
	},
	//
	//  Resize the Window to fit the viewport if necessary
	//
	_resizeWindowToFit : function() {
		if (this.resizeTo.height+this.dimensions.cruft.height > this.dimensions.viewport.height) {
			var heightRatio = this.resizeTo.height/this.resizeTo.width;
			this.resizeTo.height = this.dimensions.viewport.height-this.dimensions.cruft.height-(2*this.options.viewportPadding);
			// We only care about ratio's with this window type			
			if (this.windowType == 'image' || (this.windowType == 'media' && !this._getParameter('lightwindow_iframe_embed'))) {
				this.resizeTo.width = this.resizeTo.height/heightRatio;
				$('lightwindow_data_slide_inner').setStyle({
					width: this.resizeTo.width+'px'
				});			
			}
		} 
		if (this.resizeTo.width+this.dimensions.cruft.width > this.dimensions.viewport.width) {
			var widthRatio = this.resizeTo.width/this.resizeTo.height;
			this.resizeTo.width = this.dimensions.viewport.width-2*this.dimensions.cruft.width-(2*this.options.viewportPadding);
			// We only care about ratio's with this window type
			if (this.windowType == 'image' || (this.windowType == 'media' && !this._getParameter('lightwindow_iframe_embed'))) {
				this.resizeTo.height = this.resizeTo.width/widthRatio;
				$('lightwindow_data_slide_inner').setStyle({
					height: this.resizeTo.height+'px'
				});
			}
		}
			
	},
	//
	//  Set the Window to a preset size
	//
	_presetWindowSize : function() {
		if (this._getParameter('lightwindow_height')) {
			this.resizeTo.height = parseFloat(this._getParameter('lightwindow_height'));
		}
		if (this._getParameter('lightwindow_width')) {
			this.resizeTo.width = parseFloat(this._getParameter('lightwindow_width'));
		}
	},
	//
	//  Process the Window
	//
	_processWindow : function() {
		// Clean out our effects
		this.dimensions.dataEffects = [];

		// Set up the data-slide if we have caption information
		if (this.element.caption || this.element.author || (this.activeGallery && this.options.showGalleryCount)) {
			if (this.element.caption) {
				$('lightwindow_data_caption').innerHTML = this.element.caption;
				$('lightwindow_data_caption').setStyle({
					display: 'block'
				});
			} else {
				$('lightwindow_data_caption').setStyle({
					display: 'none'
				});				
			}
			if (this.element.author) {
				$('lightwindow_data_author').innerHTML = this.element.author;
				$('lightwindow_data_author_container').setStyle({
					display: 'block'
				});
			} else {
				$('lightwindow_data_author_container').setStyle({
					display: 'none'
				});				
			}
			if (this.activeGallery && this.options.showGalleryCount) {
				$('lightwindow_data_gallery_current').innerHTML = this.galleryLocation.current;
				$('lightwindow_data_gallery_total').innerHTML = this.galleryLocation.total;
				$('lightwindow_data_gallery_container').setStyle({
					display: 'block'
				});
			} else {
				$('lightwindow_data_gallery_container').setStyle({
					display: 'none'
				});				
			}

			$('lightwindow_data_slide_inner').setStyle({
				width: this.resizeTo.width+'px',
				height: 'auto',
				visibility: 'visible',
				display: 'block'
			});
			$('lightwindow_data_slide').setStyle({
				height: $('lightwindow_data_slide').getHeight()+'px',
				width: '1px',
				overflow: 'hidden',
				display: 'block'
			});
		} else {
			$('lightwindow_data_slide').setStyle({
				display: 'none',
				width: 'auto'
			});
			$('lightwindow_data_slide_inner').setStyle({
				display: 'none',
				visibility: 'hidden',
				width: this.resizeTo.width+'px',
				height: '0px'
			});
		}
				
		if (this.element.title != 'null') {		
			$('lightwindow_title_bar_title').innerHTML = this.element.title;
		} else {
			$('lightwindow_title_bar_title').innerHTML = '';
		}
		
		var originalContainerDimensions = {height: $('lightwindow_container').getHeight(), width: $('lightwindow_container').getWidth()};
		// Position the window
    	$('lightwindow_container').setStyle({
			height: 'auto',
			// We need to set the width to a px not auto as opera has problems with it
			width: $('lightwindow_container').getWidth()+this.options.contentOffset.width-(this.windowActive ? this.options.contentOffset.width : 0)+'px'
		});
		var newContainerDimensions = {height: $('lightwindow_container').getHeight(), width: $('lightwindow_container').getWidth()};
 		
		// We need to record the container dimension changes
		this.containerChange = {height: originalContainerDimensions.height-newContainerDimensions.height, width: originalContainerDimensions.width-newContainerDimensions.width};

		// Get out general dimensions
		this.dimensions.container = {height: $('lightwindow_container').getHeight(), width: $('lightwindow_container').getWidth()};
		this.dimensions.cruft = {height: this.dimensions.container.height-$('lightwindow_contents').getHeight()+this.options.contentOffset.height, width: this.dimensions.container.width-$('lightwindow_contents').getWidth()+this.options.contentOffset.width};
		
		// Set Sizes if we need too
		this._presetWindowSize();
		this._resizeWindowToFit(); // Even if the window is preset we still don't want it to go outside of the viewport

		if (!this.windowActive) {
			// Position the window
		   	$('lightwindow_container').setStyle({
				left: -(this.dimensions.container.width/2)+'px',
				top: -(this.dimensions.container.height/2)+'px'
			});
		}
	   	$('lightwindow_container').setStyle({
			height: this.dimensions.container.height+'px',
			width: this.dimensions.container.width+'px'
		});
		
		// We are ready, lets show this puppy off!
		this._displayLightWindow('block', 'visible');
		this._animateLightWindow();
	},
	//
	//  Fire off our animation handler
	//
	_animateLightWindow : function() {
		if (this.options.animationHandler) {
			this.options.animationHandler().bind(this);
		} else {
			this._defaultAnimationHandler();
		}
	},
	//
	//  Fire off our transition handler
	//
	_handleNavigation : function(display) {
		if (this.options.navigationHandler) {
			this.options.navigationHandler().bind(this, display);
		} else {
			this._defaultDisplayNavigation(display);
		}
	},
	//
	//  Fire off our transition handler
	//
	_handleTransition : function() {
		if (this.options.transitionHandler) {
			this.options.transitionHandler().bind(this);
		} else {
			this._defaultTransitionHandler();
		}
	},
	//
	//  Handle the finish of the window animation
	// 
	_handleFinalWindowAnimation : function(delay) {
		if (this.options.finalAnimationHandler) {
			this.options.finalAnimationHandler().bind(this, delay);
		} else {
			this._defaultfinalWindowAnimationHandler(delay);
		}		
	},
	//
	//  Handle the gallery Animation
	// 
	_handleGalleryAnimation : function(list) {
		if (this.options.galleryAnimationHandler) {
			this.options.galleryAnimationHandler().bind(this, list);
		} else {
			this._defaultGalleryAnimationHandler(list);
		}		
	},
	//
	//  Display the navigation 
	//
	_defaultDisplayNavigation : function(display) {
		if (display) {
			$('lightwindow_navigation').setStyle({
				display: 'block',
				height: $('lightwindow_contents').getHeight()+'px',
				width: '100%',
				marginTop: this.options.dimensions.titleHeight+'px'
			});			
		} else {
			$('lightwindow_navigation').setStyle({
				display: 'none',
				height: 'auto',
				width: 'auto'
			});			
		}
	},
	//
	//  This is the default animation handler for LightWindow
	//
	_defaultAnimationHandler : function() {	
		// Now that we have figures out the cruft lets make the caption go away and add its effects
		if (this.element.caption || this.element.author || (this.activeGallery && this.options.showGalleryCount)) {
			$('lightwindow_data_slide').setStyle({
				display: 'none',
				width: 'auto'
			});
			this.dimensions.dataEffects.push(
				new Effect.SlideDown('lightwindow_data_slide', {sync: true}),
				new Effect.Appear('lightwindow_data_slide', {sync: true, from: 0.0, to: 1.0})
			);
		}

		// Set up the Title if we have one
		$('lightwindow_title_bar_inner').setStyle({
			height: '0px',
			marginTop: this.options.dimensions.titleHeight+'px'
		});
		
		// We always want the title bar as well
		this.dimensions.dataEffects.push(
			new Effect.Morph('lightwindow_title_bar_inner', {sync: true, style: {height: this.options.dimensions.titleHeight+'px', marginTop: '0px'}}),
		 	new Effect.Appear('lightwindow_title_bar_inner', {sync: true, from: 0.0, to: 1.0})
		);		
		
		if (!this.options.hideGalleryTab) {
			this._handleGalleryAnimation(false);
			if ($('lightwindow_galleries_tab_container').getHeight() == 0) {
				this.dimensions.dataEffects.push(
					new Effect.Morph('lightwindow_galleries_tab_container', {sync: true, style: {height: '20px', marginTop: '0px'}})
				);
				$('lightwindow_galleries').setStyle({
					width: '0px'
				});
			}
		}
		
		var resized = false;
		var ratio = this.dimensions.container.width-$('lightwindow_contents').getWidth()+this.resizeTo.width+this.options.contentOffset.width;
		if (ratio != $('lightwindow_container').getWidth()) {
			new Effect.Parallel([
					new Effect.Scale('lightwindow_contents', 100*(this.resizeTo.width/$('lightwindow_contents').getWidth()), {scaleFrom: 100*($('lightwindow_contents').getWidth()/($('lightwindow_contents').getWidth()+(this.options.contentOffset.width))), sync: true,  scaleY: false, scaleContent: false}),
					new Effect.Scale('lightwindow_container', 100*(ratio/(this.dimensions.container.width)), {sync: true, scaleY: false, scaleFromCenter: true, scaleContent: false})
				], {
					duration: this.duration, 
					delay: 0.25,
					queue: {position: 'end', scope: 'lightwindowAnimation'}
				}
			);		
		}
		
		ratio = this.dimensions.container.height-$('lightwindow_contents').getHeight()+this.resizeTo.height+this.options.contentOffset.height;
		if (ratio != $('lightwindow_container').getHeight()) {
			new Effect.Parallel([
					new Effect.Scale('lightwindow_contents', 100*(this.resizeTo.height/$('lightwindow_contents').getHeight()), {scaleFrom: 100*($('lightwindow_contents').getHeight()/($('lightwindow_contents').getHeight()+(this.options.contentOffset.height))), sync: true, scaleX: false, scaleContent: false}),
					new Effect.Scale('lightwindow_container', 100*(ratio/(this.dimensions.container.height)), {sync: true, scaleX: false, scaleFromCenter: true, scaleContent: false})
				], {
					duration: this.duration, 
					afterFinish: function() {				
						if (this.dimensions.dataEffects.length > 0) {
							if (!this.options.hideGalleryTab) {
								$('lightwindow_galleries').setStyle({
									width: this.resizeTo.width+'px'
								});
							}
							new Effect.Parallel(this.dimensions.dataEffects, {
									duration: this.duration,
									afterFinish: function() {
										this._finishWindow();
									}.bind(this),
									queue: {position: 'end', scope: 'lightwindowAnimation'} 
								}
							);
						}
					}.bind(this), 
					queue: {position: 'end', scope: 'lightwindowAnimation'} 
				}
			);
			resized = true;
		}
		
		// We need to do our data effect since there was no resizing
		if (!resized && this.dimensions.dataEffects.length > 0) {	
			new Effect.Parallel(this.dimensions.dataEffects, {
					duration: this.duration,
					beforeStart: function() {
						if (!this.options.hideGalleryTab) {
							$('lightwindow_galleries').setStyle({
								width: this.resizeTo.width+'px'
							});
						}
						if (this.containerChange.height != 0 || this.containerChange.width != 0) {
							new Effect.MoveBy('lightwindow_container', this.containerChange.height, this.containerChange.width, {transition: Effect.Transitions.sinoidal});
						}
					}.bind(this),			
					afterFinish: function() {
						this._finishWindow();
					}.bind(this),
					queue: {position: 'end', scope: 'lightwindowAnimation'} 
				}
			);
		}			
		
	},
	//
	//  Finish up Window Animation
	//
	_defaultfinalWindowAnimationHandler : function(delay) {
		if (this.windowType == 'media' || this._getParameter('lightwindow_loading_animation')) {	
			// Because of major flickering with the overlay we just hide it in this case
			Element.hide('lightwindow_loading');
			this._handleNavigation(this.activeGallery);
			this._setStatus(false);
		} else {
			Effect.Fade('lightwindow_loading', {
				duration: 0.75,
				delay: 1.0, 
				afterFinish: function() {
					// Just in case we need some scroll goodness (this also avoids the swiss cheese effect)
					if (this.windowType != 'image' && this.windowType != 'media' && this.windowType != 'external') {
						$('lightwindow_contents').setStyle({
							overflow: 'auto'
						});
					}
					this._handleNavigation(this.activeGallery);
					this._defaultGalleryAnimationHandler();
					this._setStatus(false);
				}.bind(this),
				queue: {position: 'end', scope: 'lightwindowAnimation'}
			});
		}
	},
	//
	//  Handle the gallery Animation
	//
	_defaultGalleryAnimationHandler : function(list) {
		if (this.activeGallery) {
			$('lightwindow_galleries').setStyle({
				display: 'block',
				marginBottom: $('lightwindow_data_slide').getHeight()+this.options.contentOffset.height/2+'px'
			});
			$('lightwindow_navigation').setStyle({
				height: $('lightwindow_contents').getHeight()-20+'px'
			});
		} else {
			$('lightwindow_galleries').setStyle({
				display: 'none'
			});	
			$('lightwindow_galleries_tab_container').setStyle({
				height: '0px',
				marginTop: '20px'
			});
			$('lightwindow_galleries_list').setStyle({
				height: '0px'
			});
			return false;
		}
		
		if (list) {
			if ($('lightwindow_galleries_list').getHeight() == 0) {
				var height = $('lightwindow_contents').getHeight()*0.80;
				$('lightwindow_galleries_tab_span').className = 'down';
			} else {
				var height = 0;
				$('lightwindow_galleries_tab_span').className = 'up';
			}

			new Effect.Morph('lightwindow_galleries_list', {
				duration: this.duration,
				transition: Effect.Transitions.sinoidal,
				style: {height: height+'px'},
				beforeStart: function() {
					$('lightwindow_galleries_list').setStyle({
						overflow: 'hidden'
					});					
				},
				afterFinish: function() {
					$('lightwindow_galleries_list').setStyle({
						overflow: 'auto'
					});
				},
				queue: {position: 'end', scope: 'lightwindowAnimation'}
			});	
		}
		
		
	},
	//
	//  Default Transition Handler
	//
	_defaultTransitionHandler : function() {
		// Clean out our effects
		this.dimensions.dataEffects = [];

		// Now that we have figures out the cruft lets make the caption go away and add its effects
		if ($('lightwindow_data_slide').getStyle('display') != 'none') {
			this.dimensions.dataEffects.push(
				new Effect.SlideUp('lightwindow_data_slide', {sync: true}),
				new Effect.Fade('lightwindow_data_slide', {sync: true, from: 1.0, to: 0.0})
			);
		}
		
		if (!this.options.hideGalleryTab) {
			if ($('lightwindow_galleries').getHeight() != 0 && !this.options.hideGalleryTab) {
				this.dimensions.dataEffects.push(
					new Effect.Morph('lightwindow_galleries_tab_container', {sync: true, style: {height: '0px', marginTop: '20px'}})
				);
			}
			
			if ($('lightwindow_galleries_list').getHeight() != 0) {
				$('lightwindow_galleries_tab_span').className = 'up';
				this.dimensions.dataEffects.push(
					new Effect.Morph('lightwindow_galleries_list', {
						sync: true, 
						style: {height: '0px'},
						transition: Effect.Transitions.sinoidal,
						beforeStart: function() {
							$('lightwindow_galleries_list').setStyle({
								overflow: 'hidden'
							});					
						},
						afterFinish: function() {
							$('lightwindow_galleries_list').setStyle({
								overflow: 'auto'
							});
						}
					})
				);
			}
		}
		
		// We always want the title bar as well
		this.dimensions.dataEffects.push(
			new Effect.Morph('lightwindow_title_bar_inner', {sync: true, style: {height: '0px', marginTop: this.options.dimensions.titleHeight+'px'}}),
		 	new Effect.Fade('lightwindow_title_bar_inner', {sync: true, from: 1.0, to: 0.0})
		);

		new Effect.Parallel(this.dimensions.dataEffects, {
				duration: this.duration,
				afterFinish: function() {
					this._loadWindow();
				}.bind(this),
				queue: {position: 'end', scope: 'lightwindowAnimation'} 
			}
		);	
	},
	//
	//	Default Form handler for LightWindow
	//
	_defaultFormHandler : function(e) {
		var element = Event.element(e).parentNode;
		var parameterString = Form.serialize(this._getParameter('lightwindow_form', element.getAttribute('params')));
		if (this.options.formMethod == 'post') {
			var newAJAX = new Ajax.Request(element.href, { 
				method: 'post', 
				postBody: parameterString, 
				onComplete: this.openWindow.bind(this, element)
			});
		} else if (this.options.formMethod == 'get') {
			var newAJAX = new Ajax.Request(element.href, { 
				method: 'get', 
				parameters: parameterString, 
				onComplete: this.openWindow.bind(this, element)
			});
		}
	},
	// 
	//  Wrap everything up
	//
	_finishWindow : function() {
		if (this.windowType == 'external') {
			// We set the externals source here because it allows for a much smoother animation
			$('lightwindow_iframe').setAttribute('src', this.element.href);
			this._handleFinalWindowAnimation(1);	
		} else if (this.windowType == 'media') {

			var outerObject = document.createElement('object');
			outerObject.setAttribute('classid', this.options.classids[this._fileExtension(this.contentToFetch)]);
			outerObject.setAttribute('codebase', this.options.codebases[this._fileExtension(this.contentToFetch)]);
			outerObject.setAttribute('id', 'lightwindow_media_primary');
			outerObject.setAttribute('name', 'lightwindow_media_primary');
			outerObject.setAttribute('width', this.resizeTo.width);
			outerObject.setAttribute('height', this.resizeTo.height);
			outerObject = this._addParamToObject('movie', this.contentToFetch, outerObject);
			outerObject = this._addParamToObject('src', this.contentToFetch, outerObject);
			outerObject = this._addParamToObject('controller', 'true', outerObject);
			outerObject = this._addParamToObject('wmode', 'transparent', outerObject);
			outerObject = this._addParamToObject('cache', 'false', outerObject);
			outerObject = this._addParamToObject('quality', 'high', outerObject);

			if (!Prototype.Browser.IE) {
				var innerObject = document.createElement('object');
				innerObject.setAttribute('type', this.options.mimeTypes[this._fileExtension(this.contentToFetch)]);
				innerObject.setAttribute('data', this.contentToFetch);
				innerObject.setAttribute('id', 'lightwindow_media_secondary');
				innerObject.setAttribute('name', 'lightwindow_media_secondary');
				innerObject.setAttribute('width', this.resizeTo.width);
				innerObject.setAttribute('height', this.resizeTo.height);
				innerObject = this._addParamToObject('controller', 'true', innerObject);
				innerObject = this._addParamToObject('wmode', 'transparent', innerObject);
				innerObject = this._addParamToObject('cache', 'false', innerObject);
				innerObject = this._addParamToObject('quality', 'high', innerObject);
			
				outerObject.appendChild(innerObject);
			}	
			
			if (this._getParameter('lightwindow_iframe_embed')) {
				this._appendIframe('no');
				this._writeToIframe(this._convertToMarkup(outerObject, 'object'));
			} else {
				this._appendObject(outerObject, 'object', $('lightwindow_contents'));
			}

			this._handleFinalWindowAnimation(0);
		} else {
			this._handleFinalWindowAnimation(0);
		}

		// Initialize any actions
		this._setupActions();
	}
}

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

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

//
//	Set up all of our links
//
var myLightWindow = null;
function lightwindowInit() {
	myLightWindow = new lightwindow();
}
if(!PB) var PB = {};

var FileManager = Class.create({
	initialize:function(where_am_i)
	{
		//this.initFileManager();
	},
	initModal:function()
	{
		
	},
	initFileManager:function(what,what_else,another)
	{
      window.what = what;
      window.what_else = what_else;
      window.another = another;
      for_what = 'default';
      this.what = what;	
      switch(what)
      {
        case 'selling_image':
          this.actionHandler = this.sellingImage.bindAsEventListener(this);
        	for_what = 'images';
        break;
        case 'selling_images':
          this.actionHandler = this.sellingImages.bindAsEventListener(this);
        	for_what = 'images';
        break;
         case 'mailer_image':
        	this.actionHandler = this.changeMailerImage.bindAsEventListener(this);
        	for_what = 'images';
        break;
        case 'sponsor_image':
        	this.actionHandler = this.changeSponsorImage.bindAsEventListener(this);
        	for_what = 'images';
        break;
         case 'esponsor_image':
        	this.actionHandler = this.editSponsorImage.bindAsEventListener(this);
        	for_what = 'images';
        break;
        case 'mailer_file':
        	this.actionHandler = this.attachFileToMailer.bindAsEventListener(this,what_else,another);
        	for_what = 'files';
        break;
        case 'edit_deal_image':
        	this.actionHandler = this.editDealImage.bindAsEventListener(this);
        	for_what = 'images';
        break;
        case 'new_deal_image':
        	this.actionHandler = this.newDealImage.bindAsEventListener(this);
        	for_what = 'images';
        break;
        case 'edit_event_image':
        	this.actionHandler = this.editEventImage.bindAsEventListener(this);
        	for_what = 'images';
        break;
        case 'new_event_image':
        	this.actionHandler = this.newEventImage.bindAsEventListener(this);
        	for_what = 'images';
        break;
        case 'sharing':
        	this.actionHandler = this.shareStuff.bindAsEventListener(this);
        break;
        default:
          this.actionHandler = this.shareItem.bindAsEventListener(this,'users');
       
            
      }
      $ajax('/probrowse/',{action:'file_manager',do_command:'init',for_what:for_what},this.handleServerResponse.bind(this));
	},
	handleServerResponse:function(response)
	{
		switch(response.code)
		{
			case 200:
				this.requestOK(response);
			break;
		}
	},
	requestOK:function(response)
	{
		if(!this.modal)
			this.modal = new Control.Modal();
		
		this.modal.container.update(response.content);
		this.modal.open();
      $$('.fm_item').each(function(item){
        item.observe('click',this.action.bindAsEventListener(this));
      }.bind(this));
      initFMTabs();
	},
	onGLobalZone:function(response)
	{
		
	},
	openImageGallery:function()
	{
		
	},
	attachFileToMailer:function(event,section_id,article_id)
	{
		if(!event.element().hasClassName('fm_file'))// || !event.element().hasClassName('fm_image') || !event.element().hasClassName('fm_video'))
      {
        window.growler.error('Invalid file type.',{header:'Error.'});
        return;
      }

      this.close();
      file_count = $$('#section_'+section_id+'_content #article_'+article_id+' .article_file').length++;
      
		  file_inp = '<input type="hidden" class="article_file" name="section[section_'+section_id+'][articles][article_'+article_id+'][files][file_'+file_count+'][file_src]" value="'+event.element().readAttribute('title')+'"/>';
		  file_notify = '<div>'+event.element().innerHTML+'</div>';
		  window.file_inp = file_inp;
		  window.file_notify = file_notify;
		  $('section_'+section_id+'_content').down('#article_'+article_id).down('.article_files').insert(file_notify);
		  $('section_'+section_id+'_content').down('#article_'+article_id).down('.article_files').insert(file_inp);
	},
	openVideoGallery:function(){},
	onManagerOpen:function(){},
	onItemSelect:function(){},
	shareStuff:function(event)
	{
	  window.event = event;

    what = event.element().readAttribute('id').split('_')[0];
    what_id = event.element().readAttribute('id').split('_')[1];
    
    $('user_share_content_form').down('#what').value = what;
    $('user_share_content_form').down('#what_id').value = what_id;
    $('new_share_list').insert('<div class="title">'+event.element().readAttribute('title')+'</div>');
    $('share_btn').hide();
    this.close();

  },
  changeMailerImage:function(event)
  {
  	if(event.element().tagName != 'IMG')
      {
        window.growler.error('you can only add an image.',{header:'Error.'});
        return;
      }
      lightwindow_a = new Element('a',{id:'mailer_image', rel:'lightbox',href:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      new_img = new Element('img',{src:event.element().readAttribute('src')});
      lightwindow_a.update(new_img);
			lightwindow_a.insert('<div class="tr"></div><div class="tl"></div><div class="br"></div><div class="bl"></div>');
      $('mailer_image').replace(lightwindow_a);
      this.close();
      img_input = new Element('input',{type:'hidden',name:'mailers[image_src]',id:'mailers[image_src]',value:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      if($('mailers[image_src]'))
      $('mailers[image_src]').remove();
      $('new_mailer_form').insert(img_input);
	},
	changeSponsorImage:function(event)
   {
  		if(event.element().tagName != 'IMG')
      {
        window.growler.error('you can only add an image.',{header:'Error.'});
        return;
      }
		
      lightwindow_a = new Element('a',{rel:'lightbox',href:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      new_img = new Element('img',{src:event.element().readAttribute('src')});
      lightwindow_a.update(new_img);
		lightwindow_a.insert('<div class="tr"></div><div class="tl"></div><div class="br"></div><div class="bl"></div>');
      $('sponsor_image').update(lightwindow_a);
      this.close();
      img_input = new Element('input',{type:'hidden',name:'sponsor[image_src]',id:'sponsor[image_src]',value:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      if($('sponsor[image_src]'))
      $('sponsor[image_src]').remove();
      $('add_sponsor_form').insert(img_input);
	},
	editSponsorImage:function(event)
   {
  		if(event.element().tagName != 'IMG')
      {
        window.growler.error('you can only add an image.',{header:'Error.'});
        return;
      }
		
      lightwindow_a = new Element('a',{rel:'lightbox',href:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      new_img = new Element('img',{src:event.element().readAttribute('src')});
      lightwindow_a.update(new_img);
		lightwindow_a.insert('<div class="tr"></div><div class="tl"></div><div class="br"></div><div class="bl"></div>');
      $('esponsor_image').update(lightwindow_a);
      this.close();
      img_input = new Element('input',{type:'hidden',name:'sponsor[image_src]',id:'sponsor[image_src]',value:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      if($('sponsor[image_src]'))
      $('sponsor[image_src]').remove();
      $('update_sponsor_form').insert(img_input);
	},
  sellingImage:function(event)
   {
     if(event.element().tagName != 'IMG')
      {
        window.growler.error('you can only add an image.',{header:'Error.'});
        return;
      }
      lightwindow_a = new Element('a',{rel:'lightbox',href:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      new_img = new Element('img',{src:event.element().readAttribute('src')});
      lightwindow_a.update(new_img);
			lightwindow_a.insert('<div class="tr"></div><div class="tl"></div><div class="br"></div><div class="bl"></div>');
      $('selling_image').update(lightwindow_a);
      this.close();
      img_input = new Element('input',{type:'hidden',name:'selling_image[1]',id:'selling_image[1]',value:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      if($('selling_image[1]'))
      $('selling_image[1]').remove();
      
      if($('user_new_selling_form'))
      	$('user_new_selling_form').insert(img_input);
			
			 if($('user_edit_selling_form'))
      	$('user_edit_selling_form').insert(img_input);
   },
   newDealImage:function(event)
   {
     if(event.element().tagName != 'IMG')
      {
        window.growler.error('you can only add an image.',{header:'Error.'});
        return;
      }
      lightwindow_a = new Element('a',{rel:'lightbox',href:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      new_img = new Element('img',{src:event.element().readAttribute('src')});
      lightwindow_a.update(new_img);
			lightwindow_a.insert('<div class="tr"></div><div class="tl"></div><div class="br"></div><div class="bl"></div>');
      $('deal_image').update(lightwindow_a);
      this.close();
      img_input = new Element('input',{type:'hidden',name:'deals[image_src]',id:'deals[image_src]',value:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
			if($('deals[image_src]'))
			$('deals[image_src]').remove();     
      $('user_new_deals_form').insert(img_input);

   },
   editDealImage:function(event)
   {
     if(event.element().tagName != 'IMG')
      {
        window.growler.error('you can only add an image.',{header:'Error.'});
        return;
      }
      lightwindow_a = new Element('a',{rel:'lightbox',href:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      new_img = new Element('img',{src:event.element().readAttribute('src')});
      lightwindow_a.update(new_img);
			lightwindow_a.insert('<div class="tr"></div><div class="tl"></div><div class="br"></div><div class="bl"></div>');
      $('deal_image').update(lightwindow_a);
      this.close();
      img_input = new Element('input',{type:'hidden',name:'deals[image_src]',id:'deals[image_src]',value:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      if($('deals[image_src]'))
      $('deals[image_src]').remove();
      $('user_edit_deals_form').insert(img_input);

   },
   newEventImage:function(event)
   {
     if(event.element().tagName != 'IMG')
      {
        window.growler.error('you can only add an image.',{header:'Error.'});
        return;
      }
      lightwindow_a = new Element('a',{rel:'lightbox',href:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      new_img = new Element('img',{src:event.element().readAttribute('src')});
      lightwindow_a.update(new_img);
			lightwindow_a.insert('<div class="tr"></div><div class="tl"></div><div class="br"></div><div class="bl"></div>');
      $('event_image').update(lightwindow_a);
      this.close();
      img_input = new Element('input',{type:'hidden',name:'events[image_src]',id:'events[image_src]',value:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      if($('events[image_src]'))
      $('events[image_src]').remove();
      $('user_new_events_form').insert(img_input);

   },
   editEventImage:function(event)
   {
     if(event.element().tagName != 'IMG')
      {
        window.growler.error('you can only add an image.',{header:'Error.'});
        return;
      }
      lightwindow_a = new Element('a',{rel:'lightbox',href:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      new_img = new Element('img',{src:event.element().readAttribute('src')});
      lightwindow_a.update(new_img);
			lightwindow_a.insert('<div class="tr"></div><div class="tl"></div><div class="br"></div><div class="bl"></div>');
      $('event_image').update(lightwindow_a);
      this.close();
       img_input = new Element('input',{type:'hidden',name:'events[image_src]',id:'events[image_src]',value:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      if($('events[image_src]'))
      $('events[image_src]').remove();
      $('user_events_edit_form').insert(img_input);

   },
   sellingImages:function(event)
   {
      if($$('#selling_images img').length >= 4)
      {
        window.growler.error('you already have 4 images.',{header:'Error.'});
        return;
      }

      lightwindow_a = new Element('a',{rel:'lightbox[selling_images]',href:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      new_img = new Element('img',{src:event.element().readAttribute('src')});
      lightwindow_a.update(new_img);
			lightwindow_a.insert('<div class="edit_btns"><a href="">delete</a></div><div class="tr"></div><div class="tl"></div><div class="br"></div><div class="bl"></div>');
      image_holder = new Element('div',{'class':'image'});
			image_holder.update(lightwindow_a);
			$('selling_images').insert(image_holder);
      this.close();

      img_input = new Element('input',{type:'hidden',name:'selling_image['+($$('#selling_images img').length +1)+']',id:'selling_image['+($$('#selling_images img').length +1)+']',value:event.element().readAttribute('src').gsub('/thumbs','').replace(/_thumb_[\d]{0,4}/,'')});
      if($('selling_image['+($$('#selling_images img').length +1)+']'))
      $('selling_image['+($$('#selling_images img').length +1)+']').remove();
     
     	if($('user_new_selling_form'))
      	$('user_new_selling_form').insert(img_input);
			
			 if($('user_edit_selling_form'))
      	$('user_edit_selling_form').insert(img_input);

   },
   action:function(event)
   {
    this.actionHandler(event);
   },
   open:function(what,what_else,another)
	{
		if(!what_else)
			what_else = null;
		
		if(!another)
			another = null;
		
		this.initFileManager(what,what_else,another);
	},
	close:function()
   {
    this.modal.close();
   }
});

function initFileManager()
{
	PB.FileManager = new FileManager();
}

PB.addToDomLoad('initFileManager','');
