﻿/*
extensions - 1.2.0

A collection of Prototype-based external libraries built mostly by others (but freely available and editable
through MIT-style licensing).  These will serve as the effects for all client-based effects.

Change History:

1.2.0 - 02/20/2009
Added Bloobox (custom rolled lightbox) to replace buggy LightWindow
Removed LightWindow
Added Carousel (custom rolled)
Removed Prototype Carousel & ShowCase (Sorry, Victor, I've decided to roll my own)
Improved Loading functions

1.1.0 - 12/29/2008
Added Prototype Showcase (by Victor Stanciu, http://dev.victorstanciu.ro/experimente/prototype-showcase/).
Added Prototype Carousel (by Victor Stanciu, http://dev.victorstanciu.ro/experimente/prototype-carousel/en/)

1.0.1 - 12/29/2008
Tweaks made to lightwindow for proprietary backward compatibility with moodalbox .

1.0.0 - 12/29/2008
Final list of prototype extensions is complete and committed.  The list is as follows:
- Loading - click any element and produce an AJAX-like loading symbol above if (z-index + 1)
This has been tweaked from the original Protoload (see comments below)
- Tips - put a tip on any element based on class name.
Original design, pretty good considering this is the first version
- Watermark - input watermarker
This has been tweaked from the original undefaultvalue (see comments below)
- Fader - fade a container's child elements in and out
Original design, not the best, but good for a first version
- SkyByte libraries - for mouse effects and drag/drop/resize capabilities
SkyByte verbatim libraries, nothing changed
- LightWindow - modal box for lots of different media types
Tweaked version of the original lightwindow (see comments below)

*/


/*  LoadView
*   Nathan Rose, 12/21/2008
*
*   Based on Protoload (Andreas Kalsch, http://aka-fotos.de/protoload/) with some changes thrown in.
*
*   Major Changes:
*   -  completely prototypey, made the code smaller and got rid of offset bug
*/

Loading = {
    showLoading: function(element, loadingImageSrc) {
        $(element)._waiting = true;

        if (!$(element)._loading) {
            var loading = new Element('div');
            $$('body')[0].appendChild(loading);

            loading.setStyle({
                display: 'none',
                zIndex: $(element).getStyle('zIndex') + 1,
                position: 'absolute',
                left: $(element).cumulativeOffset()[0] + 'px',
                top: $(element).cumulativeOffset()[1] + 'px',
                height: $(element).getHeight() + 'px',
                width: $(element).getWidth() + 'px',
                lineHeight: $(element).getHeight() + 'px',
                textAlign: 'center',
                margin: 'auto',
                verticalAlign: 'middle',
                backgroundColor: '#ffffff',
                backgroundImage: 'url(' + loadingImageSrc + ')',
                backgroundPosition: 'center center',
                backgroundRepeat: 'no-repeat'
            });

            $(element)._loading = loading.identify();

            if (typeof Effect == 'undefined') {
                loading.setOpacity(0.6);
                loading.show();
            }
            else {
                loading.appear({ duration: 0.4, to: 0.6 });
            }
        }
    },

    hideLoading: function(element) {
        if ($(element)._waiting) {
            if (typeof Effect == 'undefined') {
                $($(element)._loading).hide();
            }
            else {
                $($(element)._loading).fade({
                    duration: 0.4,
                    afterFinish: function() {
                        $(element).waiting = false;

                        if ($(element)._loading != null) $($(element)._loading).remove();
                        $(element)._loading = null;
                    }
                });
            }

        }
    }
};

if (Prototype) {
    Element.addMethods(Loading);
    Object.extend(Element, Loading);
}



/*  Tips
*   Nathan Rose, 12/22/2008
*
*   TODO:  Documentation
*
*/
Tips = Class.create({
    initialize: function(element, className) {
        this.element = element;

        //  Make sure we replace all titles and alts with blank strings, 
        //  fill custom element attributes with these values instead
        if (this.element.tagName.toLowerCase() == 'a') {
            this._title = element.title;
            this._tip = element.rel;
            this.element.title = '';
            this.element.rel = '';

            //            if (this.element.firstDescendant().tagName.toLowerCase() == 'img') {
            //                this.element.firstDescendant().alt = '';
            //            }
        }
        else if (this.element.tagName.toLowerCase() == 'img') {
            this._tip = element.alt;
            this.element.alt = '';
        }
        this._tipID = '';
        this._tipClass = className;
        this._tipOffsetX = 20;
        this._tipOffsetY = 25;

        element.observe('mouseover', this.onMouseOver.bind(this));
        element.observe('mousemove', this.onMouseMove.bind(this));
        element.observe('mouseout', this.onMouseOut.bind(this));
    },

    onMouseOver: function(event) {
        if (this._tipID == '') {
            var tip = document.body.appendChild(this.getTipBody(this._title, this._tip));
            this._tipID = tip.identify();

            this.setTipPosition(event);

            if (typeof Effect == 'undefined') {
                tip.show().delay(0.2);
            }
            else {
                tip.appear({ delay: 0.2, duration: 0.2 });
            }
        }
    },

    onMouseMove: function(event) {
        if (this._tipID != '') {
            this.setTipPosition(event);
        }
    },

    onMouseOut: function(event) {
        if (this._tipID != '') {
            var tip = $(this._tipID);
            var tipID = this._tipID;
            this._tipID = '';
            if (typeof Effect == 'undefined') {
                tip.hide();
            }
            else {
                tip.fade({
                    duration: 0.2,
                    afterFinish: function(tipID) {
                        $(tipID.element).remove();
                    }
                });
            }
        }
    },

    getTipBody: function(title, tip) {
        //  The div style is completely dependent upon what was passed into the constructor
        //  Be sure to set your div.<className>, div.<className> h3 and div.<className> div
        //  in your stylesheets.
        var container = new Element('div', { style: 'display: none;' }).addClassName(this._tipClass);
        var title = new Element('div').update(title);
        var tip = new Element('span').update(tip);

        container.appendChild(title);
        container.appendChild(tip);

        return container;
    },

    setTipPosition: function(event) {
        $(this._tipID).setStyle({
            position: 'absolute',
            left: (event.pointerX() + this._tipOffsetX) + 'px',
            top: (event.pointerY() + this._tipOffsetY) + 'px'
        });
    }
});


/*  Watermark
*   Nathan Rose, 04/30/2009
*
*   It's the watermark-iest!
*
*/
Watermark = Class.create({
    initialize: function(elementID, className) {
        if ($(elementID)) {
            var element = $(elementID);

            this._title = element.title;
            this._watermarkClassName = className;
            
            if (this._title.length == 0) {
                this._title = 'Search this site';
            }

            if (element.value.length == 0 || element.value == this._title) {
                element.addClassName(this._watermarkClassName);
                element.value = this._title;
            }

            element.observe('focus', this.onFocus.bind(this));
            element.observe('blur', this.onBlur.bind(this));

            element = null;
        }
    },

    onFocus: function(event) {
        if (event.element().value == this._title) {
            event.element().removeClassName(this._watermarkClassName);
            event.element().value = '';
        }
        else {
            event.element().removeClassName(this._watermarkClassName);
            event.element().select();
        }
    },

    onBlur: function(event) {
        if (event.element().value == '' || event.element().value == this._title) {
            event.element().addClassName(this._watermarkClassName);
            event.element().value = this._title;
        }
    }
});

/*  Fader
*   Nathan Rose, 12/27/2008
*
*   Fades all elements in a container in and out based on their index in the container childElements array.
*
*/
Fader = Class.create({
    initialize: function(container, fadeDuration, staticDuration) {
        if ($(container) && $(container).childElements().length > 1) {
            this.container = $(container);
            this.currentIndex = 0;
            this.childElements = this.container.childElements();
            this.fadeDuration = fadeDuration;
            this.staticDuration = staticDuration;
            this.mouseOver = false;

            this.container.setStyle({ position: 'relative' });
            if (this.container.tagName.toLowerCase() == 'ul') this.container.setStyle({ listStyleType: 'none', margin: '0px', padding: '0px' });

            this.container.observe('mouseover', this.onMouseOver.bind(this));
            this.container.observe('mouseout', this.onMouseOut.bind(this));

            this.childElements.each(function(e) {
                e.setStyle({ position: 'absolute' });
                if (this.currentIndex++ > 0) {
                    e.hide();
                }
            } .bind(this));

            this.currentIndex = 0;

            new PeriodicalExecuter(function() {
                if (!this.mouseover) {
                    this.childElements[this.currentIndex].fade({ duration: this.fadeDuration });
                    if (this.currentIndex == this.childElements.length - 1) {
                        this.currentIndex = 0;
                    }
                    else {
                        this.currentIndex++;
                    }
                    this.childElements[this.currentIndex].appear({ duration: this.fadeDuration });
                }
            } .bind(this), this.staticDuration);
        }
    },

    onMouseOver: function(event) {
        this.mouseover = true;
    },

    onMouseOut: function(event) {
        this.mouseover = false;
    }
});

/*******************************************************************************************************************************************************************/
/*                                                                         SkyByte Library                                                                         */
/*******************************************************************************************************************************************************************/


/*  SkyByte.js v1.0-beta, May 17 2007
*  (c) 2007 Aleksandras Ilarionovas (Alex)
*
*  SkyByte.js is freely distributable under the terms of an MIT-style license.
*  For details, see the SkyByte.net web site: http://www.skybyte.net/scripts/
*
*--------------------------------------------------------------------------*/

if (typeof Prototype === 'undefined') { throw ("SkyByte.js requires Prototype.js library"); }
var SkyByte = { Version: '1.2' };

//--------------------------------------------------------------------------
var Browser = {
    cursor: function(cur) { document.body.style.cursor = cur; }
};
function debug(o) { s = ''; for (var n in o) { s += n + ':' + o[n] + '\n'; } alert(s); }

//--------------------------------------------------------------------------
// Syntax: Mouse.start(object: optional) where object._mouseMove(e) = callback function or empty parameter
//         Mouse.stop(object: optional)
// Return: Mouse.x, Mouse.y = current mouse coordinates
var Mouse = {
    callbacks: [], x: 0, y: 0, event: null,
    start: function(obj) { //start callback or just start observing mouse coordinates
        obj = obj || 'global';
        if (this.callbacks.length === 0) {
            this.eventMouseMove = this._mouseMove.bindAsEventListener(this); Event.observe(document, "mousemove", this.eventMouseMove);
        }
        var found = this.callbacks.detect(function(d) { return d == obj; });
        if (!found) { this.callbacks.push(obj); }
    },
    stop: function(obj) { //stop callback or stop observing all
        obj = obj || 'global';
        this.callbacks = this.callbacks.reject(function(d) { return d == obj; });
        if (this.callbacks.length === 0) {
            Event.stopObserving(document, "mousemove", this.eventMouseMove);
        }
    },
    _mouseMove: function(e) {
        var o, i; this.x = Event.pointerX(e); this.y = Event.pointerY(e); this.event = e;
        if (Mouse.callbacks) {
            for (i = 0, len = Mouse.callbacks.length; i < len; ++i) {
                o = Mouse.callbacks[i];
                if (typeof o == 'object') { o._mouseMove(e); }
            }
        }
    }
};
//--------------------------------------------------------------------------
Object.extend(Element, {
    add: function(el, attr, style, opt) {
        var d;
        for (var n in opt) { val = opt[n]; if (n == 'clone') { d = val.cloneNode(true); } }
        if (!d) { d = document.createElement(el); }
        for (n in attr) { d.setAttribute(n, attr[n]); }
        for (n in style) { d.style[n.camelize()] = style[n]; }
        for (n in opt) {
            val = opt[n];
            switch (n) {
                case 'a': if (typeof val == 'string') { val = $(val); } d = val.appendChild(d); break;
                case 'c': d.className = val; break;
                case 'id': d.id = val; break;
                case 'txt': //IE6 bug: The innerHTML property of the TABLE, TFOOT, THEAD, and TR elements are read-only.
                    if (d.tagName == "TABLE" || d.tagName == "TFOOT" || d.tagName == "THEAD" || d.tagName == "TR") {

                    } else if (d.innerHTML) { d.innerHTML = val; }
                    break;
            }
        } return d;
    },
    rem: function(el) { if (el.parentNode) { d = el.parentNode.removeChild(el); return d; } },
    putAt: function(target, c) {
        if (target) {
            target.style.left = c.x + 'px';
            target.style.top = c.y + 'px';
        }
    },
    showAt: function(target, c) {
        if (target) {
            target.style.left = c.x + 'px';
            target.style.top = c.y + 'px';
            target.style.width = c.w + 'px';
            target.style.height = c.h + 'px';
        }
    },
    xywh: function(el) {  //x,y,width,height
        var d = Element.getDimensions(el); 	//={w,h} of the object
        var c = Position.cumulativeOffset(el); //={x,y} absolute offset from the top-left corner
        return { x: c[0], y: c[1], w: d.width, h: d.height };
    },
    wh: function(el) {	//=width/height
        var d = Element.getDimensions(el); 	//={w,h} of the object
        return { w: d.width, h: d.height };
    }
});

/*  SkyByteDD.js v1.0-beta, May 17 2007
*  (c) 2007 Aleksandras Ilarionovas (Alex)
*
*  SkyByteDD.js is freely distributable under the terms of an MIT-style license.
*  For details, see the SkyByte.net web site: http://www.skybyte.net/scripts/
*
*--------------------------------------------------------------------------*/

if (typeof Prototype == 'undefined') { throw ("SkyByteDD.js requires Prototype.js library"); }
else if (typeof SkyByte == 'undefined') { throw ("SkyByteDD.js requires SkyByte.js library"); }

var SkyByteDD = { Version: '1.2' };

var Drags = {
    drag: null,
    drags: [],
    hide: { x: -100, y: -100, w: 0, h: 0 },
    register: function(obj) {
        if (this.drags.length === 0) {
            Mouse.start(this);
            this.eventMouseUp = this._mouseUp.bindAsEventListener(this); Event.observe(document, "mouseup", this.eventMouseUp);
            if (navigator.appVersion.match(/\bMSIE\b/)) {
                this.eventMouseOver = this._mouseOver.bindAsEventListener(this);
                this.eventMouseOut = this._mouseOut.bindAsEventListener(this);
            }
            this.div = Element.add('div', {}, {}, { a: document.body, c: 'dragmove' });
            document.body.onselectstart = function() { return false; }; //disable selection in IE
        }
        this.drags.push(obj);
    },
    unregister: function(el) {
        this.drags = this.drags.reject(function(d) { return d.element == el; });
    },
    is_drag: function(el) {
        return this.drags.detect(function(d) { return d.element == el; });
    },
    destroy: function() {
        var i, o, len;
        if (this.drags.length > 0) {
            this.drag = null; //could be that elements activated with Drags.activate(el) function
            $A(this.drags).each(function(o) {
                if (typeof o.destroy === 'function') { o.destroy(); } //so they don't have destroy function from the start
            });
        }
        if (this.drags.length === 0 && this.div) {
            Element.rem(this.div); Mouse.stop(this);
            Event.stopObserving(document, "mouseup", this.eventMouseUp);
        }
    },
    activate: function(drag, e) {
        this.drag = drag; this.drag.IE = false;
        if (this.drag.element.tagName === 'IMG' && navigator.appVersion.match(/\bMSIE\b/)) {
            //IE6 fix: when dragging images, loosing mouseover/mouseout event, so we fire those events on entire document
            this.drag.IE = true;
            Event.observe(document, "mouseover", this.eventMouseOver);
            Event.observe(document, "mouseout", this.eventMouseOut);
        }
    },
    deactivate: function() {
        if (this.drag.IE) {
            Event.stopObserving(document, "mouseover", this.eventMouseOver);
            Event.stopObserving(document, "mouseout", this.eventMouseOut);
        }
        this.drag = null;
    },
    //--------------------IE only----------------------
    //IE6 ugly walkaround: manually detect if drop zone is over mouse and fire event
    _mouseOver: function(e) {
        var d = Drops.is_drop(Event.element(e));
        if (d) {
            Drops.drop = d;
            Drops.show_frame();
        }
    },
    //IE6 ugly walkaround
    _mouseOut: function(e) {
        if (Drops && Drops.lastActive && typeof Drops.lastActive.options.mouseOut === 'function') {
            Drops.lastActive.options.mouseOut(Drops.lastActive.element);
            Drops.lastActive = null;
        }
        Drops.hide_frame();
        Drops.drop = null;
    },
    //--------------------ALL Other--------------------
    _mouseMove: function(e) {
        if (!this.drag) { return; }
        this.drag._mouseMove(e); //Call MouseMove
        Event.stop(e);
    },
    _mouseUp: function(e) {
        if (!this.drag) { return; }
        this.drag._mouseUp(e);  //Call MouseUp
        this.drag = null;
        Event.stop(e);
    }
};
//---------------------------------------------------------------------------------------------

var Drag = Class.create();
Drag.prototype = {
    initialize: function(el) {
        this.element = $(el);
        this.options = Object.extend({
            self: false,
            classname: 'drag',
            caption: '', 	//moving...
            affect: false 	//set different rules for all drop zones
        }, arguments[1] || {});
        if (this.options.self) {
            this.options.self = this.element.parentNode; Element.makePositioned(this.options.self);
        }
        this.eventMouseDown = this._mouseDown.bindAsEventListener(this); Event.observe(this.element, "mousedown", this.eventMouseDown);
        Drags.register(this);
    },
    destroy: function() {
        Event.stopObserving(this.element, "mousedown", this.eventMouseDown);
        Drags.unregister(this.element);
    },
    currentDelta: function() {
        return ([
	  parseInt(Element.getStyle(this.options.self, 'left') || '0'),
	  parseInt(Element.getStyle(this.options.self, 'top') || '0')]);
    },
    _mouseDown: function(e) {
        var el, pointer, pos;
        if (this.options.self) {
            el = this.options.self;
            pointer = [Mouse.x, Mouse.y];
            pos = Position.cumulativeOffset(el);
            this.offset = [0, 1].map(function(i) { return (pointer[i] - pos[i]); });
        }

        Browser.cursor('default');
        Drops.affect = this.options.affect; //tell Drops that this element needs different rules
        Drags.activate(this);
        Event.stop(e);
    },
    _mouseUp: function(e) {
        var ok;
        //.........call drop function when mouse released
        Element.putAt(Drags.div, Drags.hide);
        if (this.element && Drops.drop && (this.element != Drops.drop.element)) {
            if (Drops.drop.options.accept === this.element.tagName) { ok = true; }
            if (Drops.drop.options.accept === '') { ok = true; }
            if (Drops.affect) { ok = true; }
            if (ok) {
                if (typeof Drops.drop.options.mouseUp === 'function') {
                    Drops.drop.options.mouseUp(Drops.drop.element, this.element);
                }
            }
        }
        //.........
        Drops.affect = false; //tell Drops to return to normal state
        Drags.deactivate();
        Drops.hide_frame();
        //Event.stop(e); //already stopped
    },
    _mouseMove: function(e) {
        var ok, d, pos, point, p, style, el, div, caption;
        if (this.options.self) {
            el = this.options.self;
            pos = Position.cumulativeOffset(el);
            d = this.currentDelta();
            pos[0] -= d[0]; pos[1] -= d[1];
            point = []; point.push(Mouse.x); point.push(Mouse.y);
            p = [0, 1].map(function(i) { return (point[i] - pos[i] - this.offset[i]) } .bind(this));
            style = el.style;
            style.left = p[0] + "px";
            style.top = p[1] + "px";
        } else {
            //.........set default drag style and caption
            div = Drags.div; div.className = 'dragmove'; caption = this.options.caption;
            if (this.element && Drops.drop && (this.element != Drops.drop.element)) {
                if (Drops.drop.options.accept && Drops.drop.options.accept === this.element.tagName) { ok = true; }
                if (Drops.drop.options.accept === '') { ok = true; }
                if (Drops.affect) { ok = true; }
                if (ok) {
                    cap = Drops.drop.options.caption;
                    if (cap) { caption = cap; } //take message from Drop Area?
                    div.className = this.options.classname;
                    if (typeof Drops.drop.options.mouseOver === 'function') {
                        Drops.lastActive = Drops.drop;
                        Drops.drop.options.mouseOver(Drops.drop.element, this.element);
                    }
                }
            }
            //.........place div at cursor
            div.innerHTML = caption; Mouse.x += 15; Mouse.y += 10; Element.putAt(div, Mouse);
            //.........
        }
        //Event.stop(e); //already stopped
    }

};

//---------------------------------------------------------------------------------------------
var Drops = {
    lastActive: null,
    frameactive: null,
    drop: null,
    affect: null,
    drops: [],
    hide: { x: -10, y: -10, w: 0, h: 0 },
    register: function(obj) {
        if (this.drops.length === 0) {
            this.L = Element.add('div', {}, {}, { a: document.body, c: 'drop' });
            this.R = Element.add('div', {}, {}, { a: document.body, c: 'drop' });
            this.T = Element.add('div', {}, {}, { a: document.body, c: 'drop' });
            this.B = Element.add('div', {}, {}, { a: document.body, c: 'drop' });
        }
        this.drops.push(obj);
    },
    unregister: function(el) {
        this.hide_frame(); //hide frame if mouse over zone
        this.drops = this.drops.reject(function(d) { return d.element == el; });
    },
    destroy: function() {
        var i, o, len;
        if (this.drops.length > 0) {
            Element.rem(this.L); Element.rem(this.R); Element.rem(this.T); Element.rem(this.B);
            $A(this.drops).each(function(o) {
                if (typeof o.destroy === 'function') { o.destroy(); } //so they don't have destroy function from the start
            });
            this.drop = null;
            this.hide_frame(); //hide frame if mouse over zone
        }
    },
    is_drop: function(el) {
        return this.drops.detect(function(d) { return d.element == el; });
    },
    show_frame: function() {
        this.frameactive = true;
        var pointer = Element.xywh(this.drop.element);
        this.L.className = this.drop.options.classname;
        this.R.className = this.drop.options.classname;
        this.T.className = this.drop.options.classname;
        this.B.className = this.drop.options.classname;
        Element.showAt(this.L, { x: pointer.x, y: pointer.y, w: 1, h: pointer.h });
        Element.showAt(this.R, { x: (pointer.x + pointer.w), y: pointer.y, w: 1, h: pointer.h });
        Element.showAt(this.T, { x: pointer.x, y: pointer.y, w: pointer.w, h: 1 });
        Element.showAt(this.B, { x: pointer.x, y: (pointer.y + pointer.h), w: pointer.w, h: 1 });
    },
    hide_frame: function() {
        if (this.drops.length > 0 && this.frameactive) {
            this.frameactive = false;
            Element.showAt(this.L, this.hide);
            Element.showAt(this.R, this.hide);
            Element.showAt(this.T, this.hide);
            Element.showAt(this.B, this.hide);
        }
    }
};

//---------------------------------------------------------------------------------------------
var Drop = Class.create();
Drop.prototype = {
    initialize: function(el) {
        this.element = $(el);
        this.options = Object.extend({
            caption: '', 	//drop here
            classname: 'drop',
            accept: this.element.tagName,
            mouseUp: null,
            mouseOver: null,
            mouseOut: null
        }, arguments[1] || {});
        this.eventMouseOver = this._mouseOver.bindAsEventListener(this); Event.observe(this.element, "mouseover", this.eventMouseOver);
        this.eventMouseOut = this._mouseOut.bindAsEventListener(this); Event.observe(this.element, "mouseout", this.eventMouseOut);
        Drops.register(this);
    },
    destroy: function() {
        Event.stopObserving(this.element, "mouseover", this.eventMouseOver);
        Event.stopObserving(this.element, "mouseout", this.eventMouseOut);
        Drops.unregister(this.element);
    },
    _mouseOver: function(e) {
        var d = Drops.is_drop(Event.element(e));
        if (!d) { d = Drops.is_drop(this.element); }
        if (d) {
            Drops.drop = d;
            Drops.show_frame();
        }
        Event.stop(e);
    },
    _mouseOut: function(e) {
        if (Drops.lastActive && typeof Drops.lastActive.options.mouseOut === 'function') {
            Drops.lastActive.options.mouseOut(Drops.lastActive.element);
            Drops.lastActive = null;
        }
        Drops.drop = null;
        Drops.hide_frame();
        Event.stop(e);
    }
};
//---------------------------------------------------------------------------------------------

/*  SkyByteRS.js, May 17 2007
*  (c) 2007 Aleksandras Ilarionovas (Alex)
*
*  SkyByteRS.js is freely distributable under the terms of an MIT-style license.
*  For details, see the SkyByte.net web site: http://www.skybyte.net/scripts/
*
*--------------------------------------------------------------------------*/
if (!Prototype) { throw ("SkyByteRS.js requires Prototype.js library"); }
else if (!SkyByte) { throw ("SkyByteRS.js requires SkyByte.js library"); }
else if (!SkyByteDD) { throw ("SkyByteRS.js requires SkyByteDD.js library"); }

var SkyByteRS = { Version: '1.2.3' };

var Resizes = {
    resizes: [],
    resize: {},
    resizing: null,
    frameactive: false,
    register: function(obj) {
        if (this.resizes.length === 0) {

            this.L = Element.add('div', {}, { position: 'absolute', top: '-50px', left: '-50px' }, { c: 'resizel', a: document.body });
            this.R = Element.add('div', {}, { position: 'absolute', top: '-50px', left: '-50px' }, { c: 'resizer', a: document.body });
            this.T = Element.add('div', {}, { position: 'absolute', top: '-50px', left: '-50px' }, { c: 'resizet', a: document.body });
            this.B = Element.add('div', {}, { position: 'absolute', top: '-50px', left: '-50px' }, { c: 'resizeb', a: document.body });
            this.box = Element.add('div', {}, { position: 'absolute', top: '-50px', left: '-50px' }, { c: 'resizebox', a: document.body });

            this.TM = Element.add('div', {}, { cursor: 's-resize', overflow: 'hidden', position: 'absolute', top: '-50px', left: '-50px' }, { c: 'resizeknob', a: document.body }); Drags.register(this.TM);
            this.BM = Element.add('div', {}, { cursor: 's-resize', overflow: 'hidden', position: 'absolute', top: '-50px', left: '-50px' }, { c: 'resizeknob', a: document.body }); Drags.register(this.BM);
            this.LT = Element.add('div', {}, { cursor: 'se-resize', overflow: 'hidden', position: 'absolute', top: '-50px', left: '-50px' }, { c: 'resizeknob', a: document.body }); Drags.register(this.LT);
            this.LM = Element.add('div', {}, { cursor: 'e-resize', overflow: 'hidden', position: 'absolute', top: '-50px', left: '-50px' }, { c: 'resizeknob', a: document.body }); Drags.register(this.LM);
            this.LB = Element.add('div', {}, { cursor: 'ne-resize', overflow: 'hidden', position: 'absolute', top: '-50px', left: '-50px' }, { c: 'resizeknob', a: document.body }); Drags.register(this.LB);
            this.RT = Element.add('div', {}, { cursor: 'sw-resize', overflow: 'hidden', position: 'absolute', top: '-50px', left: '-50px' }, { c: 'resizeknob', a: document.body }); Drags.register(this.RT);
            this.RM = Element.add('div', {}, { cursor: 'e-resize', overflow: 'hidden', position: 'absolute', top: '-50px', left: '-50px' }, { c: 'resizeknob', a: document.body }); Drags.register(this.RM);
            this.RB = Element.add('div', {}, { cursor: 'nw-resize', overflow: 'hidden', position: 'absolute', top: '-50px', left: '-50px' }, { c: 'resizeknob', a: document.body }); Drags.register(this.RB);

            this.eventMouseDown = this._mouseDown.bindAsEventListener(this); //knob event
            this.eventMouseOver = this._mouseOver.bindAsEventListener(this); //knob event
            this.eventMouseOut = this._mouseOut.bindAsEventListener(this); //knob event
            this.eventClick = this._observeClick.bindAsEventListener(this); Event.observe(document, "mousedown", this.eventClick); //catch clicks outside element

            Event.observe(this.TM, "mousedown", this.eventMouseDown); Event.observe(this.TM, "mouseover", this.eventMouseOver); Event.observe(this.TM, "mouseout", this.eventMouseOut);
            Event.observe(this.BM, "mousedown", this.eventMouseDown); Event.observe(this.BM, "mouseover", this.eventMouseOver); Event.observe(this.BM, "mouseout", this.eventMouseOut);
            Event.observe(this.LT, "mousedown", this.eventMouseDown); Event.observe(this.LT, "mouseover", this.eventMouseOver); Event.observe(this.LT, "mouseout", this.eventMouseOut);
            Event.observe(this.LM, "mousedown", this.eventMouseDown); Event.observe(this.LM, "mouseover", this.eventMouseOver); Event.observe(this.LM, "mouseout", this.eventMouseOut);
            Event.observe(this.LB, "mousedown", this.eventMouseDown); Event.observe(this.LB, "mouseover", this.eventMouseOver); Event.observe(this.LB, "mouseout", this.eventMouseOut);
            Event.observe(this.RT, "mousedown", this.eventMouseDown); Event.observe(this.RT, "mouseover", this.eventMouseOver); Event.observe(this.RT, "mouseout", this.eventMouseOut);
            Event.observe(this.RM, "mousedown", this.eventMouseDown); Event.observe(this.RM, "mouseover", this.eventMouseOver); Event.observe(this.RM, "mouseout", this.eventMouseOut);
            Event.observe(this.RB, "mousedown", this.eventMouseDown); Event.observe(this.RB, "mouseover", this.eventMouseOver); Event.observe(this.RB, "mouseout", this.eventMouseOut);
        }

        this.resizes.push(obj);
    },
    unregister: function(el) {
        this.hide_frame();
        this.resizes = this.resizes.reject(function(d) { return d.element == el; });
    },
    destroy: function() {
        var i, o;
        if (this.resizes.length > 0) {
            $A(this.resizes).each(function(o) {
                if (o.destroy) { o.destroy(); }
            });
        }
        if (this.resizes.length === 0 && this.TM) {
            this.resize = {};
            Element.rem(this.T); Element.rem(this.B); Element.rem(this.L); Element.rem(this.R);
            Drags.unregister(this.TM); Element.rem(this.TM);
            Drags.unregister(this.TB); Element.rem(this.BM);
            Drags.unregister(this.LT); Element.rem(this.LT);
            Drags.unregister(this.LM); Element.rem(this.LM);
            Drags.unregister(this.LB); Element.rem(this.LB);
            Drags.unregister(this.RT); Element.rem(this.RT);
            Drags.unregister(this.RM); Element.rem(this.RM);
            Drags.unregister(this.RB); Element.rem(this.RB);
            Event.stopObserving(this, "mousedown", this.eventMouseDown);
            Event.stopObserving(this, "mouseover", this.eventMouseOver);
            Event.stopObserving(this, "mouseout", this.eventMouseOut);
            Event.stopObserving(document, "mousedown", this.eventClick);
        }
        this.hide_frame();
    },
    is_resize: function(el) {
        return this.resizes.detect(function(d) { return d.element == el; });
    },
    activate: function(el) {
        var r = Resizes.is_resize(el); if (!r) { return; }
        Resizes.resize = r; this.element = el;
        this.show_frame(Element.xywh(this.element));
    },
    deactivate: function() {
        this.hide_frame();
    },
    show_frame: function(c) {
        var opt = this.resize.options; if (this.resizes.length == 0) { return; }
        this.frameactive = true;
        if (opt.indicator == true) {
            this.box.innerHTML = c.w + 'x' + c.h; var bb = Element.wh(this.box);
            Element.putAt(this.box, { x: c.x + (c.w / 2) - (bb.w / 2), y: c.y + (c.h / 2) - (bb.h / 2) });
        }
        Element.showAt(this.L, { x: c.x, y: c.y, w: 1, h: c.h });
        Element.showAt(this.R, { x: (c.x + c.w), y: c.y, w: 1, h: c.h });
        Element.showAt(this.T, { x: c.x, y: c.y, w: c.w, h: 1 });
        Element.showAt(this.B, { x: c.x, y: (c.y + c.h), w: c.w, h: 1 });

        Element.putAt(this.TM, { x: c.x + ((c.w / 2) - 4), y: (c.y - 2) });
        Element.putAt(this.BM, { x: c.x + ((c.w / 2) - 4), y: c.y + (c.h - 4) });
        Element.putAt(this.LT, { x: (c.x - 3), y: (c.y - 2) });
        Element.putAt(this.LM, { x: (c.x - 3), y: c.y + ((c.h / 2) - 3) });
        Element.putAt(this.LB, { x: (c.x - 3), y: c.y + (c.h - 4) });
        Element.putAt(this.RT, { x: c.x + (c.w - 4), y: (c.y - 2) });
        Element.putAt(this.RM, { x: c.x + (c.w - 4), y: c.y + ((c.h / 2) - 3) });
        Element.putAt(this.RB, { x: c.x + (c.w - 4), y: c.y + (c.h - 4) });
    },
    hide_frame: function() {
        if (this.frameactive) {
            this.show_frame({ x: -50, y: -50, w: 10, h: 10 }); this.frameactive = false;
        }
    },
    border: function(el) {
        var cl = Element.add('div', {}, { background: 'red', border: '0', margin: 0, padding: 0, visibility: 'hidden' }, { clone: el, a: el.parentNode });
        var cwh = Element.wh(cl); var ewh = Element.wh(el); Element.rem(cl);
        return { w: (ewh.w - cwh.w), h: (ewh.h - cwh.h) };
    },
    minmax: function(src) {
        var i, o, xy;
        var minW = 0; var minH = 0; var maxW = 0; var maxH = 0;
        //1. find parent outer dimensions 760px;
        var div0 = Element.add('div', {}, {}, { a: src.parentNode }); var parXY = Element.wh(div0); Element.rem(div0);

        //2. find owner inner dimensions 300px;
        var div1 = Element.add('div', {}, { position: 'absolute', top: '0px', left: '0px' }, { a: document.body });
        var div2 = Element.add('div', {}, { width: 'auto', height: 'auto', float: 'left' }, { clone: src, txt: '', a: div1 });

        //3. find owner margins
        var outXY = Element.xywh(div1); var innXY = Element.xywh(div2); Element.rem(div1);
        var ml = innXY.x; var mt = innXY.y; var mr = outXY.w - (innXY.x + innXY.w); var mb = outXY.h - (innXY.y + innXY.h);

        //4. find owner inner dimensions 300px;
        var ownXY = Element.xywh(src);  //target element dimensions
        var els = src.getElementsByTagName('*');
        for (i = 0, len = els.length; i < len; ++i) {
            o = els[i];
            xy = Element.xywh(o); mW = xy.x + xy.w; mH = xy.y + xy.h; if (mW > minW) { minW = mW; } if (mH > minH) { minH = mH; }
        }

        var a = {};
        a.minW = minW - ownXY.x; if (a.minW < 0) { a.minW = 0; }
        a.minH = minH - ownXY.y; if (a.minH < 0) { a.minH = 0; }
        a.maxW = (parXY.w - mr - ml); a.maxH = (parXY.h - mt - mb); //= maxW(760) - margin left - margin right = 740
        a.w = ownXY.w; a.h = ownXY.h;
        //IE bug: element "margin:0 auto;" will return huge margins, [ ...300...] [element] [...300...]
        if (a.maxW <= 0 || a.maxW < ownXY.w) { a.maxW = parXY.w; } //=parXY.w 
        if (a.maxH <= 0 || a.maxH < ownXY.h) { a.maxH = 0; } //=parXY.h  
        return a;
    },
    _mouseMove: function(e) {
        var rA; if (!this.init) { return; }
        var opt = this.resize.options;
        var m0 = this.init.mouse;
        var mm = this.init.wh;
        var mb = this.init.border;
        var mx = this.init.minmax;
        var pr = opt.proportional;
        var dX = (m0.x - Mouse.x); var dY = (m0.y - Mouse.y); if (mm.h > 0) { rA = (mm.w / mm.h); } else { rA = 1; }
        var newX = (mm.w - dX); var newY = (mm.h - dY);
        switch (this.init.knob) {
            case this.RM: newX = (mm.w - dX); newY = mm.h; break;
            case this.LM: newX = (mm.w + dX); newY = mm.h; break;
            case this.TM: newX = mm.w; newY = (mm.h + dY); break;
            case this.BM: newX = mm.w; newY = (mm.h - dY); break;
            case this.RT: if (pr) { newX = Math.round((mm.w - (dX * rA))); newY = (mm.h - dX); } break;
            case this.LT: if (pr) { dX = -dX; newX = Math.round((mm.w - (dX * rA))); newY = (mm.h - dX); } break;
            case this.RB: if (pr) { newX = Math.round((mm.w - (dX * rA))); newY = (mm.h - dX); } break;
            case this.LB: if (pr) { dX = -dX; newX = Math.round((mm.w - (dX * rA))); newY = (mm.h - dX); } break;
        }
        //control inner and outer dimensions
        if (mx.minW) { if (newX <= mx.minW) { newX = mx.minW; } }
        if (mx.minH) { if (newY <= mx.minH) { newY = mx.minH; } }
        if (mx.maxW) { if (newX >= mx.maxW) { newX = mx.maxW; } }
        if (mx.maxH) { if (newY >= mx.maxH) { newY = mx.maxH; } }

        newX = newX - mb.w; if (newX < 0) { newX = 0; }
        newY = newY - mb.h; if (newY < 0) { newY = 0; }

        this.element.style.width = newX + 'px';
        this.element.style.height = newY + 'px';
        var p = Element.xywh(this.element);
        this.show_frame(p);
        if (typeof opt.mouseMove === 'function') { opt.mouseMove(this.element); }
        return p;
    },
    _mouseDown: function(e) {
        var src = Event.element(e); Event.stop(e);
        if (src.className != 'resizeknob') { return; }
        switch (src) {
            case this.TM: Drags.activate(this); break;
            case this.BM: Drags.activate(this); break;
            case this.LT: Drags.activate(this); break;
            case this.LM: Drags.activate(this); break;
            case this.LB: Drags.activate(this); break;
            case this.RT: Drags.activate(this); break;
            case this.RM: Drags.activate(this); break;
            case this.RB: Drags.activate(this); break;
        }
        var mx = this.minmax(this.element); var opt = this.resize.options;
        if (opt.min.w) { mx.minW = opt.min.w; }
        if (opt.min.h) { mx.minH = opt.min.h; }
        if (opt.max.w) { mx.maxW = opt.max.w; }
        if (opt.max.h) { mx.maxH = opt.max.h; }
        this.init = {
            knob: src,
            mouse: { x: Mouse.x, y: Mouse.y },
            wh: { w: mx.w, h: mx.h },
            border: this.border(this.element),
            minmax: mx
        };
        if (typeof opt.startResize === 'function') { opt.startResize(this.element); }
    },
    _observeClick: function(e) {
        var el, click;
        if (!this.frameactive) { return; }
        var src = Event.element(e);
        var r = Resizes.is_resize(this.element);
        if (r) {
            click = r.options.click;
            if (click == true) {
                if (src != this.element) { this.deactivate(); }
            } else if (click == false) {
                //do not destroy selection
            } else {
                el = $(click); if (el == src) { this.deactivate(); }
            }
        }
    },
    _mouseUp: function(e) {
        var opt = this.resize.options;
        if (typeof opt.endResize === 'function') { opt.endResize(this.element); }
        this.init = false; Browser.cursor('default');
    },
    _mouseOver: function(e) {
        var src = Event.element(e); if (src.className === 'resizeknob') { src.style.background = 'black'; }
    },
    _mouseOut: function(e) {
        var src = Event.element(e); if (src.className === 'resizeknob') { src.style.background = 'white'; }
    }

};

//----------------------------------------------------------------------------

var Resize = Class.create();
Resize.prototype = {
    initialize: function(el) {
        this.element = $(el);
        this.options = Object.extend({
            event: 'mousedown',
            startResize: null,
            mouseMove: null,
            endResize: null,
            indicator: true,
            click: true,
            proportional: true,
            min: { w: 0, h: 0 },
            max: { w: 0, h: 0 }
        }, arguments[1] || {});
        //check for min, max here once, because we may want to pass initial element dimensions, before resizing it
        if (typeof this.options.min === 'function') {
            this.options.min = this.options.min(this); if (!this.options.min) { this.options.min = { w: 0, h: 0 }; }
        }
        if (typeof this.options.max === 'function') {
            this.options.max = this.options.max(this); if (!this.options.max) { this.options.max = { w: 0, h: 0 }; }
        }
        this.eventActivate = this.activate.bindAsEventListener(this); Event.observe(this.element, this.options.event, this.eventActivate);
        Resizes.register(this);
    },
    activate: function(e) {
        var el = Event.element(e);
        Resizes.activate(el);
    },
    destroy: function() {
        Event.stopObserving(this.element, this.options.event, this.eventActivate);
        Resizes.unregister(this.element);
    }
};

//----------------------------------------------------------------------------



Carousel = Class.create({
    initialize: function(containerElement, width) {
        this._disabled = false;
        this.currentIndex = 0;
        this.itemCount = $(containerElement).getElementsBySelector('.carouselItem').length;
        this.containerElement = $(containerElement);
        this.itemContainer = this.containerElement.getElementsBySelector('.carouselContent')[0];
        this.width = width;

        if (this.itemCount > 1) {
            this.carouselControlLeft = this.containerElement.getElementsBySelector('.carouselControlLeftLink')[0]; this.carouselControlLeft.hidden = true;
            this.carouselControlRight = this.containerElement.getElementsBySelector('.carouselControlRightLink')[0]; this.carouselControlRight.hidden = true;

            if (this.carouselControlLeft.hasClassName('out')) {
                this.carouselControlRight.removeClassName('out');
            }
            this.carouselControlRight.setStyle({ visibility: 'visible' });
            this.carouselControlRight.hidden = false;

            this.carouselControlLeft.observe('click', this.onLeftClick.bind(this));
            this.carouselControlRight.observe('click', this.onRightClick.bind(this));
        }
    },

    toggleControl: function(element) {
        if (element.hasClassName('out')) element.setOpacity(0).setStyle({ visibility: 'hidden' }).removeClassName('out');

        if (element.hidden) {
            element.setOpacity(0).setStyle({ visibility: 'visible' });
            new Effect.Opacity(element, {
                duration: 0.4,
                transition: Effect.Transitions.sinoidal,
                from: 0,
                top: 1,
                afterFinish: function() {
                    element.hidden = false;
                } .bind(this)
            });
        }
        else {
            new Effect.Opacity(element, {
                duration: 0.4,
                transition: Effect.Transitions.sinoidal,
                from: 1,
                top: 0,
                afterFinish: function() {
                    element.setStyle({ visibility: 'hidden' });
                    element.hidden = true;
                } .bind(this)
            });
        }
    },

    onLeftClick: function(event) {
        event.stop();
        if (!this._disabled) {
            //  Disable further clicking for all those click maniacs
            this._disabled = true;
            this.scrollToItem(this.currentIndex - 1, 1);

            if (this.currentIndex == 1) this.toggleControl(this.carouselControlLeft);
            if (this.carouselControlRight.hidden) this.toggleControl(this.carouselControlRight);

            this.currentIndex -= 1;
        }
    },

    onRightClick: function(event) {
        event.stop();
        if (!this._disabled) {
            //  Disable further clicking for all those click maniacs
            this._disabled = true;
            this.scrollToItem(this.currentIndex + 1, -1);

            if (this.currentIndex == this.itemCount - 2) this.toggleControl(this.carouselControlRight);
            if (this.carouselControlLeft.hidden) this.toggleControl(this.carouselControlLeft);

            this.currentIndex += 1;
        }
    },

    scrollToItem: function(index, modifier) {
        new Effect.Move(this.itemContainer, {
            mode: 'relative',
            x: (this.width * modifier),
            y: 0,
            duration: 0.4,
            transition: Effect.Transitions.sinoidal,
            afterFinish: function() {
                this._disabled = false;
            } .bind(this)
        });
    }
});



VCarousel = Class.create({
    initialize: function(containerElement, height) {
        this._disabled = false;
        this.currentIndex = 0;
        this.itemCount = $(containerElement).getElementsBySelector('.carouselItem').length;
        this.containerElement = $(containerElement);
        this.itemContainer = this.containerElement.getElementsBySelector('.carouselContent')[0];
        this.height = height;

        if (this.itemCount > 1) {
            this.carouselControlUp = this.containerElement.getElementsBySelector('.carouselControlUpLink')[0]; this.carouselControlUp.hidden = true;
            this.carouselControlDown = this.containerElement.getElementsBySelector('.carouselControlDownLink')[0]; this.carouselControlDown.hidden = true;

            if (this.carouselControlUp.hasClassName('out')) {
                this.carouselControlDown.removeClassName('out');
            }
            this.carouselControlDown.setStyle({ visibility: 'visible' });
            this.carouselControlDown.hidden = false;

            this.carouselControlUp.observe('click', this.onUpClick.bind(this));
            this.carouselControlDown.observe('click', this.onDownClick.bind(this));
        }
    },

    toggleControl: function(element) {
        if (element.hasClassName('out')) element.setStyle({ visibility: 'hidden' }).setOpacity(0).removeClassName('out');

        if (element.hidden) {
            element.setStyle({ visibility: 'visible' });
            new Effect.Opacity(element, {
                duration: 0.4,
                transition: Effect.Transitions.sinoidal,
                from: 0,
                top: 1,
                afterFinish: function() {
                    element.hidden = false;
                } .bind(this)
            });
        }
        else {
            new Effect.Opacity(element, {
                duration: 0.4,
                transition: Effect.Transitions.sinoidal,
                from: 1,
                top: 0,
                afterFinish: function() {
                    element.setStyle({ visibility: 'hidden' });
                    element.hidden = true;
                } .bind(this)
            });
        }
    },

    onUpClick: function(event) {
        event.stop();
        if (!this._disabled) {
            //  Disable further clicking for all those click maniacs
            this._disabled = true;
            this.scrollToItem(this.currentIndex - 1, 1);

            if (this.currentIndex == 1) this.toggleControl(this.carouselControlUp);
            if (this.carouselControlDown.hidden) this.toggleControl(this.carouselControlDown);

            this.currentIndex -= 1;
        }
    },

    onDownClick: function(event) {
        event.stop();
        if (!this._disabled) {
            //  Disable further clicking for all those click maniacs
            this._disabled = true;
            this.scrollToItem(this.currentIndex + 1, -1);

            if (this.currentIndex == this.itemCount - 2) this.toggleControl(this.carouselControlDown);
            if (this.carouselControlUp.hidden) this.toggleControl(this.carouselControlUp);

            this.currentIndex += 1;
        }
    },

    scrollToItem: function(index, modifier) {
        new Effect.Move(this.itemContainer, {
            mode: 'relative',
            x: 0,
            y: (this.height * modifier),
            duration: 0.4,
            transition: Effect.Transitions.sinoidal,
            afterFinish: function() {
                this._disabled = false;
            } .bind(this)
        });
    }
});



Bloobox = Class.create({
    initialize: function() {
        if ($('bloobox')) {
            $('bloobox').remove();
        }
        this.imageExtensions = ['.bmp', '.gif', '.jpg', '.jpeg', '.png', '.tif', '.tiff'];

        $$('[rel^="bloobox"]').each(function(element) {
            element._blooboxOptions = $H({
                bloom: 0,
                glass: 1,
                width: document.viewport.getWidth() - 40,
                height: document.viewport.getHeight() - 40,
                gallery: '',
                type: this.getType(element.href)
            }).merge(element.rel.replace('bloobox', '').evalJSON());

            //  do we need to preload glass images?
            if (element._blooboxOptions.get('glass') == 1 && !this.glassLoaded) this.preloadGlass();

            //  do we need to preload bloom image?
            if (element._blooboxOptions.get('bloom') == 1 && !this.bloomLoaded) this.preloadBloom();

            element.observe('click', this.onClick.bind(this));
        } .bind(this));

        this.preloadImages();

        $(document.body).insert({ 'bottom': '<div id="bloobox" style="display: none;"></div>' });
    },

    getType: function(href) {
        var trueHref = (href.indexOf('?') >= 0) ? (href.substring(0, href.indexOf('?'))) : (href);

        //  bloobox only supports image, inline and page
        var image = new RegExp("[^\.]\.(" + this.imageExtensions.join('|') + ")\s*$", "i");
        if (image.test(trueHref)) return 'image';

        var sPath = window.location.pathname;
        var sPage = sPath.substring(sPath.lastIndexOf('/') + 1);

        if ((trueHref.indexOf('#') >= 0) && (trueHref.indexOf(sPage) >= 0) && (trueHref.indexOf(sPage) + sPage.length == trueHref.indexOf('#'))) return 'inline';

        return 'page';
    },

    preloadImages: function() {
        this.overlay = new Image();
        this.overlay.src = '/images/bloobox/overlay-100x100.png';

        this.contentBackground = new Image();
        this.contentBackground.src = '/images/bloobox/content-background-100x100.png';

        this.close = new Image();
        this.close.src = '/images/bloobox/close-button-28x28.png';

        this.next = new Image();
        this.next.src = '/images/bloobox/next-arrow-29x22.png';

        this.prev = new Image();
        this.prev.src = '/images/bloobox/prev-arrow-29x22.png';
    },

    preloadGlass: function() {
        this.topLeft = new Image();
        this.topLeft.src = '/images/bloobox/topleft-25x21.png';

        this.top = new Image();
        this.top.src = '/images/bloobox/top-25x21.png';

        this.topRight = new Image();
        this.topRight.src = '/images/bloobox/topright-25x21.png';

        this.left = new Image();
        this.left.src = '/images/bloobox/left-25x25.png';

        this.right = new Image();
        this.right.src = '/images/bloobox/right-25x25.png';

        this.bottomLeft = new Image();
        this.bottomLeft.src = '/images/bloobox/bottomleft-25x21.png';

        this.bottom = new Image();
        this.bottom.src = '/images/bloobox/bottom-25x21.png';

        this.bottomRight = new Image();
        this.bottomRight.src = '/images/bloobox/bottomright-25x21.png';

        this.glassLoaded = true;
    },

    preloadBloom: function() {
        this.bloom = new Image();
        this.bloom.src = '/images/bloobox/bloom-1200x1200.png';
        this.bloomLoaded = true;
    },

    createBloobox: function(element) {
        var layerText = '';

        layerText += '	<div id="blooboxOverlay" style="width: ' + document.body.getWidth() + 'px; height: ' + ((document.body.getHeight() < document.viewport.getHeight()) ? (document.viewport.getHeight()) : (document.body.getHeight())) + 'px;">';
        if (element._blooboxOptions.get('bloom'))
            layerText += '		<div id="blooboxBloom" style="width: ' + document.body.getWidth() + 'px; height: ' + ((document.body.getHeight() < document.viewport.getHeight()) ? (document.viewport.getHeight()) : (document.body.getHeight())) + 'px;"></div>';
        layerText += '	</div>';
        layerText += '	<div id="blooboxContainerOuter">';
        layerText += '		<div id="blooboxContainer"">';  //  Set width/height (content) + glass cruft (if used); Set location based on total width/height vs. viewport
        if (element._blooboxOptions.get('glass')) {
            layerText += '			<table id="blooboxGlass" cellspacing="0" cellpadding="0">';

            //  Glass - Top Row
            layerText += '				<tr>';
            layerText += '					<td><img src="/images/bloobox/topleft-25x21.png" alt="" /></td>';
            layerText += '					<td id="blooboxGlassTop">&nbsp;</td>';
            layerText += '					<td><img src="/images/bloobox/topright-25x21.png" alt="" /></td>';
            layerText += '				</tr>';

            //  Glass - Middle Row
            layerText += '				<tr>';
            layerText += '					<td id="blooboxGlassLeft">&nbsp;</td>';
            layerText += '					<td>';
        }
        layerText += '						<div id="blooboxContainerInner"">';  //  Set width/height of content

        if (element._blooboxOptions.get('gallery').length > 0) {
            //  Gallery Box
            layerText += '							<table id="blooboxGallery" cellspacing="0" cellpadding="0">';
            layerText += '								<tr>';
            layerText += '									<td id="blooboxGalleryLeft">';
            layerText += '										<a href="#" title="Previous"><img src="/images/bloobox/prev-arrow-29x22.png" alt="Previous" /></a>';
            layerText += '									</td>';
            layerText += '									<td id="blooboxGalleryCenter">Image 1 of 9 (test gallery)</td>';
            layerText += '									<td id="blooboxGalleryRight">';
            layerText += '										<a href="#" title="Next"><img src="/images/bloobox/next-arrow-29x22.png" alt="Next" /></a>';
            layerText += '									</td>';
            layerText += '								</tr>';
            layerText += '							</table>';
        }

        //  Content Box
        layerText += '							<div id="blooboxContent">';
        switch (element._blooboxOptions.get('type')) {
            case 'image':
                layerText += '							<img id="blooboxContentInner" />';
                break;
            case 'inline':
                layerText += '							<div id="blooboxContentInner"></div>';
                break;
            case 'page':
                layerText += '							<iframe id="blooboxContentInner" style="background: #ffffff;" src="' + element.href + '" scrolling="auto" width="' + element._blooboxOptions.get('width') + '" height="' + element._blooboxOptions.get('height') + '" frameborder="0"></iframe>';
                break;
        }
        layerText += '							</div>';

        //  Info Box
        layerText += '							<div id="blooboxInfo">';
        layerText += '								<div id="blooboxCaption">' + element.title + '</div>';
        layerText += '								<div id="blooboxClose">';
        layerText += '									<a id="bloowareClose" href="#" title="Close"><img src="/images/bloobox/close-button-28x28.png" alt="Close" /></a>';
        layerText += '								</div>';
        layerText += '							</div>';
        layerText += '						</div>';

        if (element._blooboxOptions.get('glass')) {
            layerText += '					</td>';
            layerText += '					<td id="blooboxGlassRight">&nbsp;</td>';
            layerText += '				</tr>';

            //  Glass - Bottom Row
            layerText += '				<tr>';
            layerText += '					<td><img src="/images/bloobox/bottomleft-25x21.png" alt="" /></td>';
            layerText += '					<td id="blooboxGlassBottom">&nbsp;</td>';
            layerText += '					<td><img src="/images/bloobox/bottomright-25x21.png" alt="" /></td>';
            layerText += '				</tr>';
            layerText += '			</table>';
        }
        layerText += '		</div>';
        layerText += '	</div>';

        return layerText;
    },

    getContent: function(element) {
        switch (element._blooboxOptions.get('type')) {
            case 'image':
                //  We load a mock image for its onload event.
                //  TODO:  Figure out a better way of doing this
                var image = new Image();
                image.onload = function(element) {
                    element._blooboxOptions.set('width', image.width);
                    element._blooboxOptions.set('height', image.height);

                    this.setSize(element);
                    this.setLocation(element);

                    this.showBloobox();

                    image = null;
                    delete image;

                    if ($(element).hideLoading) $(element).hideLoading();
                } .bind(this, element);

                image.src = element.href;
                $('blooboxContentInner').src = element.href;
                break;
            case 'inline':
                //  Do nothing, either use defaults or what was specified in width/height options
                var inlineElement = element.href.substring(element.href.indexOf('#') + 1);
                if ($(inlineElement))
                    $('blooboxContentInner').innerHTML = $(inlineElement).innerHTML;

                this.setSize(element);
                this.setLocation(element);

                this.showBloobox();

                if ($(element).hideLoading) $(element).hideLoading();
                break;
            case 'page':
                //  Do nothing, either use defaults or what was specified in width/height options
                var content = new Ajax.Request(element.href, {
                    method: 'post',
                    parameters: '',
                    onComplete: function(response) {

                        //$('blooboxContentInner').innerHTML += response.responseText;
                        //  If we're doing dynamic resizing based on content, uncomment the following
                        //  Be careful to not let the scroll height/width become bigger than the viewport
                        //element._blooboxOptions.set('width', $('blooboxContentInner').scrollWidth);
                        //element._blooboxOptions.set('height', $('blooboxContentInner').scrollHeight);

                        this.setSize(element);
                        this.setLocation(element);

                        this.showBloobox();

                        if ($(element).hideLoading) $(element).hideLoading();
                    } .bind(this)
                });
                break;
        }
    },

    setSize: function(element) {
        $('blooboxContainer').absolutize();
        $('blooboxContainer').setStyle({
            width: (element._blooboxOptions.get('width') + ((element._blooboxOptions.get('glass')) ? (70) : (20))) + 'px',
            height: (element._blooboxOptions.get('height') +
						((element._blooboxOptions.get('glass')) ? (62) : (20)) +
						((element._blooboxOptions.get('gallery').length > 0) ? (40) : (0))) + 'px'
        });
    },

    setLocation: function(element) {
        var x = element._blooboxOptions.get('width');
        if (element._blooboxOptions.get('glass')) x += 50;

        var y = element._blooboxOptions.get('height');
        if (element._blooboxOptions.get('glass')) y += 42;
        if (element._blooboxOptions.get('gallery').length > 0) y += 40;

        $('blooboxContainer').setStyle({
            top: ((document.viewport.getHeight() - $('blooboxContainer').getStyle('height').replace('px', '')) / 2) + document.viewport.getScrollOffsets()[1] + 'px',
            left: ((document.viewport.getWidth() - $('blooboxContainer').getStyle('width').replace('px', '')) / 2) + document.viewport.getScrollOffsets()[0] + 'px'
        });
    },

    onClick: function(event) {
        event.stop();

        var actualElement = event.element();

        while (!actualElement._blooboxOptions) {
            actualElement = actualElement.up();
        }

        if ($(actualElement).showLoading) $(actualElement).showLoading('/images/loadingSmall.gif');

        if ($('bloobox')) {
            $('bloobox').childElements().each(function(element) {
                element.remove();
            });

            $('bloobox').insert({ 'top': this.createBloobox(actualElement) });

            $('blooboxClose').observe('click', this.hideBloobox.bind(this));
            $('blooboxClose').observe('click', function(event) { event.stop(); return false; });
        }

        this.getContent(actualElement);
    },

    moveBloobox: function() {
        new Effect.Move('blooboxContainer', {
            mode: 'absolute',
            x: ((document.viewport.getWidth() - $('blooboxContainer').getStyle('width').replace('px', '')) / 2) + document.viewport.getScrollOffsets()[0],
            y: ((document.viewport.getHeight() - $('blooboxContainer').getStyle('height').replace('px', '')) / 2) + document.viewport.getScrollOffsets()[1],
            duration: 0.3,
            delay: 0.2
        });

    },

    showBloobox: function() {
        //this._windowScrollEventHandler = this.moveBloobox.bindAsEventListener(this);
        //Event.observe(window, 'scroll', this._windowScrollEventHandler);
        //Event.observe(window, 'scroll', this.moveBloobox.bind(this));

        $('bloobox').appear({
            duration: 0.3
        });
    },

    hideBloobox: function() {
        //Event.stopObserving(window, 'scroll', this._windowScrollEventHandler);
        //Event.stopObserving(window, 'scroll');

        $('bloobox').fade({
            duration: 0.3
        });
    }
});







//  Custom Initialization
//  This is proprietary to all SV clients

document.observe('dom:loaded', function() {
    //  Set each watermark
    $$('.watermark').each(function(element) {
        new Watermark(element, 'watermark');
    });

    //  Set each tooltip
    $$('.tip').each(function(element) {
        new Tips(element, 'tip');
    });

    //  Test for autocompleter search textbox
    if ($('tSearch') && $('tSearchUpdate')) {
        var searchAutocompleter = new Ajax.Autocompleter('tSearch', 'tSearchUpdate', '/User-Search-Parameters.aspx', { paramName: 'tSearch', minChars: 3, parameters: 'max=6'/*, afterUpdateElement: function(e) { document.location = '/SearchResults.aspx?tSearch=' + $('tSearch').value; }*/ });
    }

    //  This would be a good place to preload images for the Loading object extensions
    var loadingSmall = new Image();
    loadingSmall.src = '/images/design/loadingSmall.gif';

    var loadingMedium = new Image();
    loadingMedium.src = '/images/design/loadingMedium.gif';

    var loadingLarge = new Image();
    loadingLarge.src = '/images/design/loadingLarge.gif';

    var bloobox = new Bloobox();
});