function TSFlyouts() {
    // Manages all public flyout snippets

    function TStorage() {
        // Holds the indivual flyout snippets
        this.namedItems = [];
        this.items = [];

        this.addItem = function (name, item) {
            this.namedItems[name] = item;
            this.items.push(item);
        }

        this.getItem = function (name) {
            if (typeof(name) == "string") return this.namedItems[name];
            else return this.items[name];
        }

        this.length = function () {
            return this.items.length;
        }
    } // TSFlyouts.TStorage END

    function TSnippet() {
        // The implementation of a flyout snippet
        this.instanceName = ""; // Unique identifier
        this.triggerId = null;
        this.fadeOut = false;
        this.verticalPlacement = 0;
        this.horizontalPlacement = 0;
        this.flyoutId = "";
        this.imgSrcI = "";
        this.imgSrcA = "";
        this.imgSrcH = "";
        this.clickHandler = null;
        this.active = false;
        this.hiddenElements = [];	// if IE6- then this array will hold all SELECTS that intersects with the flyouts bounding box
        this.element2beFocused = null;

        this.show = function (o) {
            // Displays the snippet
            var inst = null;
            for (var i = 0; i < tsFlyouts.storage.length(); i++) {
                inst = tsFlyouts.storage.getItem(i);
                if (inst.instanceName != this.instanceName) inst.hide(document.getElementById(inst.flyoutId));
            }
            this.active = true;
            var trigger = document.getElementById(this.triggerId);
            var point = this.getPos(trigger);
            var posX = point[0];
            var posY = point[1];

            if (this.verticalPlacement == 0) posY -= o.offsetHeight;
            else posY += trigger.offsetHeight;

            if (this.horizontalPlacement == 0) {
                posX += trigger.offsetWidth;
                posX -= o.offsetWidth;
            }
            o.style.top = posY;
            o.style.left = posX;

            if (document.all) { // Expand check to IE6-
                // hide covered selects
                var point = this.getPos(o);
                var coveredArea = [point[0], point[1], o.clientWidth, o.clientHeight];
                var combolist = document.getElementsByTagName("SELECT");
                if (combolist.length > 0) {
                    for (var i = 0; i < combolist.length; i++) {
                        var cmb = combolist[i];
                        point = this.getPos(cmb);
                        var cArea = [point[0],point[1],cmb.clientWidth,cmb.clientHeight];
                        if (this.intersects(coveredArea, cArea)) {
                            if ((cmb.style.display.toLowerCase() != "none") && (cmb.style.visibility.toLowerCase() != "hidden")) {
                                this.hiddenElements.push(cmb);
                                cmb.style.visibility = "hidden";
                            }
                        }
                    }
                }
            }

            var img = trigger.childNodes[0];
            img.src = this.imgSrcA;
            img.onmouseover = function () {
            };
            img.onmouseout = function () {
            };

            if (this.clickHandler == null) {
                // Add popdown handlers
                this.clickHandler = "tsFlyouts.popDown('" + this.instanceName + "')";

                if (/Safari/.test(navigator.userAgent)) {
                    tsCompat.addEvent(document.body, "onclick", function () {
                        eval(clickHandler)
                    });
                    trigger.onclick = function () {
                    };
                    var tmp = "tsFlyouts.fly(\'trigger\',event); if(window.event) {window.event.cancelBubble=true;} else {e.stopPropagation();}";
                    tsCompat.addEvent(trigger, "onclick", function () {
                        eval(tmp)
                    });
                } else {
                    if (/Mozilla\/5\.0/.test(navigator.userAgent)) tsCompat.addEvent(window, "onclick", function () {
                        eval(clickHandler)
                    });
                    else tsCompat.addEvent(document.body, "onclick", function () {
                        eval(clickHandler)
                    });
                }

                tsCompat.addEvent(o, "onclick", function (e) {
                    eval("if(window.event) {window.event.cancelBubble=true;} else {e.stopPropagation();}")
                });
                var clickHandler = this.clickHandler;
            }
            if (o.filters)
            if (o.filters[0]) {
                o.filters[0].enabled = true;
                o.filters[0].apply();
            }
            o.style.visibility = "visible";
            if (o.filters)
            if (o.filters[0])
                o.filters[0].play();
            var coll = o.getElementsByTagName("INPUT");
            if (coll.length > 0) {
                if (o.filters) {
                    if (o.filters[0]) {
                        for (var i = 0; i < coll.length; i++)
                        {
                            if (coll[i].type != 'hidden')
                            {
                                this.element2beFocused = coll[i];
                                window.setTimeout("tsFlyouts.focusElement('" + this.instanceName + "')", 1000);
                                break;
                            }
                        }
                    } else {
                        for (var i = 0; i < coll.length; i++)
                        {
                            if (coll[i].type != 'hidden')
                            {
                                coll[i].focus();
                                break;
                            }
                        }
                    }
                } else {
                    for (var i = 0; i < coll.length; i++)
                    {
                        if (coll[i].type != 'hidden')
                        {
                            coll[i].focus();
                            break;
                        }
                    }
                }
            }
        }

        this.hide = function (o) {
            // Hides the visible snippet
            this.active = false;
            var img = document.getElementById(this.triggerId).childNodes[0];
            if (this.fadeOut && o.filters)
            if (o.filters[0])
                o.filters[0].apply();
            o.style.visibility = "hidden";
            if (this.fadeOut && o.filters)
            if (o.filters[0])
                o.filters[0].play();
            img.src = this.imgSrcI;
            var func1 = "this.src = \'" + this.imgSrcH + "\';";
            img.onmouseover = function () {
                eval(func1)
            };
            var func2 = "this.src = \'" + this.imgSrcI + "\';";
            img.onmouseout = function () {
                eval(func2)
            };
            if (this.hiddenElements.length > 0) {
                // Show previously hidden selects
                if (o.filters)
                if (o.filters[0])
                    window.setTimeout("tsFlyouts.showSelects('" + this.instanceName + "')", o.filters[0].duration * 1000);
            }
        }

        this.getPos = function (elm) {
            // Gets the absolute position of the element as a point array [x,y]
            if (!elm) return [-1,-1];
            var l = elm.offsetLeft;
            var t = elm.offsetTop;
            var tmp = elm.offsetParent;
            //while (tmp != null && tmp != document.body) {
            while (tmp != null) {
                l += tmp.offsetLeft;
                t += tmp.offsetTop;
                tmp = tmp.offsetParent;
            }
            if (!document.all) l -= 2;
            return [l, t];
        }

        this.intersects = function (r1, r2) {
            // Test the rects for overlap

            // get the radi of each rect
            var width1 = parseInt(r1[2] / 2);
            var height1 = parseInt(r1[3] / 2);
            var width2 = parseInt(r2[2] / 2);
            var height2 = parseInt(r2[3] / 2);

            // compute center of each rect
            var cx1 = r1[0] + width1;
            var cy1 = r1[1] + height1;
            var cx2 = r2[0] + width2;
            var cy2 = r2[1] + height2;

            // compute deltas
            var dx = Math.abs(cx2 - cx1);
            var dy = Math.abs(cy2 - cy1);

            // test if rects overlap
            if (dx < (width1 + width2) && dy < (height1 + height2)) return true;
            else return false;
        }
    } // TSFlyouts.TSnippet END

    this.storage = new TStorage();

    this.getInstance = function (instanceName) {
        if (this.storage.getItem(instanceName) == null) this.storage.addItem(instanceName, new TSnippet());
        return this.storage.getItem(instanceName);
    }

    this.addInstance = function (instanceName, triggerId, fadeOut, verticalPlacement, horizontalPlacement, flyoutId, imgSrcI, imgSrcA, imgSrcH) {
        var instance = this.getInstance(instanceName);
        instance.instanceName = instanceName;
        instance.triggerId = triggerId;
        instance.fadeOut = (fadeOut == 1);
        instance.verticalPlacement = verticalPlacement;
        instance.horizontalPlacement = horizontalPlacement;
        instance.flyoutId = flyoutId;
        instance.imgSrcI = imgSrcI;
        instance.imgSrcA = imgSrcA;
        instance.imgSrcH = imgSrcH;
        return instance;
    }

    this.fly = function (instanceName, e) {
        // Generic flyhandler, either shows or hides the snippet
        if (!e && window.event)
            e = window.event;
        var instance = tsFlyouts.getInstance(instanceName);
        var flyout = document.getElementById(instance.flyoutId);
        if ((flyout.style.visibility == "visible") || (instance.active == true)) instance.hide(flyout);
        else instance.show(flyout);
        if (e.stopPropagation) e.stopPropagation();
        if (window.event) e.cancelBubble = true;
        return false;
    }

    this.popDown = function (instanceName) {
        var instance = tsFlyouts.getInstance(instanceName);
        var flyout = document.getElementById(instance.flyoutId);
        instance.hide(flyout);
    }

    this.showSelects = function (instanceName) {
        // Iterates the hidden selects and redisplays them
        var instance = tsFlyouts.getInstance(instanceName);
        var flyout = document.getElementById(instance.flyoutId);
        while (instance.hiddenElements.length > 0) {
            var e = instance.hiddenElements.pop();
            e.style.visibility = "visible";
        }
    }

    this.focusElement = function (instanceName) {
        var instance = tsFlyouts.getInstance(instanceName);
        if (instance.element2beFocused) instance.element2beFocused.focus();
    }

    this.getParentForm = function (elm) {
        var pN = elm.parentNode;
        while (pN != null && pN.tagName.toLowerCase() != "form")
        {
            pN = pN.parentNode;
        }
        return pN;
    }

} // TSFlyouts END

function TSSlideShows() {

    function TStorage() {
        this.namedItems = [];
        this.items = [];

        this.addItem = function (name, item) {
            this.namedItems[name] = item;
            this.items.push(item);
        }

        this.getItem = function (name) {
            if (typeof(name) == "string") return this.namedItems[name];
            else return this.items[name];
        }

        this.length = function () {
            return this.items.length;
        }
    } // TSSlideShows.TStorage END

    function TSlideShow() {
        this.position = 1;
        this.timeout = 1000;
        this.fadeOut = false;
        this.instanceName = "";
        this.init = function () {
            var s = "slideShows_nextSlide('" + this.instanceName + "')";
            window.setTimeout(s, this.timeout);
        }

        this.nextSlide = function () {
            var curI = document.getElementById(this.instanceName + this.position);
            if (this.fadeOut && curI.filters)
            if (curI.filters[0])
                curI.filters[0].apply();
            curI.style.visibility = "hidden";
            if (this.fadeOut && curI.filters)
            if (curI.filters[0])
                curI.filters[0].play();

            var nextI = document.getElementById(this.instanceName + (this.position + 1));
            if (nextI == null) {
                this.position = 1;
                nextI = document.getElementById(this.instanceName + this.position);
            } else this.position += 1;
            if (nextI.filters)
            if (nextI.filters[0])
                nextI.filters[0].apply();
            nextI.style.visibility = "visible";
            if (nextI.filters)
            if (nextI.filters[0])
                nextI.filters[0].play();
            var s = "slideShows_nextSlide('" + this.instanceName + "')";
            window.setTimeout(s, this.timeout);
        }

    } // TSSlideShows.TSlideShow END

    this.storage = new TStorage();

    this.getInstance = function (instanceName) {
        if (this.storage.getItem(instanceName) == null) this.storage.addItem(instanceName, new TSlideShow());
        return this.storage.getItem(instanceName);
    }

    this.addInstance = function (instanceName, timeout, fadeOut) {
        var instance = this.getInstance(instanceName);
        instance.instanceName = instanceName;
        instance.timeout = timeout;
        instance.fadeOut = fadeOut;
        instance.init();
        return instance;
    }

} // TSSlideShows END

function slideShows_nextSlide(instanceName) {
    tsSlideShows.getInstance(instanceName).nextSlide();
}

tsFlyouts = new TSFlyouts();
tsSlideShows = new TSSlideShows();
