// include separated js files
function includeJS(url) { document.writeln("<script type=\"text/javascript\" src=\"" + url + "\"></script>"); }
function includeCSS(url) { document.writeln("<style type=\"text/css\">@import url(\"" + url + "\");</style>"); }


// This code is from the book JavaScript: The Definitive Guide, 5th Edition,
// by David Flanagan. Copyright 2006 O'Reilly Media, Inc. (ISBN #0596101996)
/*
 * runOnLoad.js: portable registration for onload event handlers.
 *
 * This module defines a single runOnLoad() function for portably registering
 * functions that can be safely invoked only when the document is fully loaded
 * and the DOM is available.
 *
 * Functions registered with runOnLoad() will not be passed any arguments when
 * invoked. They will not be invoked as a method of any meaningful object, and
 * the this keyword should not be used.  Functions registered with runOnLoad()
 * will be invoked in the order in which they were registered.  There is no
 * way to deregister a function once it has been passed to runOnLoad().
 *
 * In old browsers that do not support addEventListener() or attachEvent(),
 * this function relies on the DOM Level 0 window.onload property and will not
 * work correctly when used in documents that set the onload attribute
 * of their <body> or <frameset> tags.
 */

function runOnLoad(f) {
    if (runOnLoad.loaded) f();    // If already loaded, just invoke f() now.
    else runOnLoad.funcs.push(f); // Otherwise, store it for later
}

runOnLoad.funcs = []; // The array of functions to call when the document loads
runOnLoad.loaded = false; // The functions have not been run yet.

// Run all registered functions in the order in which they were registered.
// It is safe to call runOnLoad.run() more than once: invocations after the
// first do nothing. It is safe for an initialization function to call
// runOnLoad() to register another function.
runOnLoad.run = function() {
    if (runOnLoad.loaded) return;  // If we've already run, do nothing
    for(var i = 0; i < runOnLoad.funcs.length; i++) {
        try { runOnLoad.funcs[i](); }
        catch(e) { /* An exception in one function shouldn't stop the rest */ }
    }

    runOnLoad.loaded = true; // Remember that we've already run once.
    delete runOnLoad.funcs;  // But don't remember the functions themselves.
    delete runOnLoad.run;    // And forget about this function too!
};

// Register runOnLoad.run() as the onload event handler for the window
if (window.addEventListener)
    window.addEventListener("load", runOnLoad.run, false);
else if (window.attachEvent) window.attachEvent("onload", runOnLoad.run);
else window.onload = runOnLoad.run;






// This code is from the book JavaScript: The Definitive Guide, 5th Edition,
// by David Flanagan. Copyright 2006 O'Reilly Media, Inc. (ISBN #0596101996)
/**
 * getElements(classname, tagname, root):
 * Return an array of DOM elements that are members of the specified class,
 * have the specified tagname, and are descendants of the specified root.
 *
 * If no classname is specified, elements are returned regardless of class.
 * If no tagname is specified, elements are returned regardless of tagname.
 * If no root is specified, the document object is used.  If the specified
 * root is a string, it is an element id, and the root
 * element is looked up using getElementsById()
 */
function getElements(classname, tagname, root) {
    // If no root was specified, use the entire document
    // If a string was specified, look it up
    if (!root) root = document;
    else if (typeof root == "string") root = document.getElementById(root);

    // if no tagname was specified, use all tags
    if (!tagname) tagname = "*";

    // Find all descendants of the specified root with the specified tagname
    var all = root.getElementsByTagName(tagname);

    // If no classname was specified, we return all tags
    if (!classname) return all;

    // Otherwise, we filter the element by classname
    var elements = [];  // Start with an emtpy array
    for(var i = 0; i < all.length; i++) {
        var element = all[i];
        if (isMember(element, classname)) // isMember() is defined below
            elements.push(element);       // Add class members to our array
    }

    // Note that we always return an array, even if it is empty
    return elements;

    // Determine whether the specified element is a member of the specified
    // class.  This function is optimized for the common case in which the
    // className property contains only a single classname.  But it also
    // handles the case in which it is a list of whitespace-separated classes.
    function isMember(element, classname) {
        var classes = element.className;  // Get the list of classes
        if (!classes) return false;             // No classes defined
        if (classes == classname) return true;  // Exact match

        // We didn't match exactly, so if there is no whitespace, then
        // this element is not a member of the class
        var whitespace = /\s+/;
        if (!whitespace.test(classes)) return false;

        // If we get here, the element is a member of more than one class and
        // we've got to check them individually.
        var c = classes.split(whitespace);  // Split with whitespace delimiter
        for(var i = 0; i < c.length; i++) { // Loop through classes
            if (c[i] == classname) return true;  // and check for matches
        }

        return false;  // None of the classes matched
    }
}


/**
 * getOffsets(element):
 * This function calculates the window offsets of a document element by traversing
 * the document hierarchy from the element up to the root and adding all of the
 * offsetLeft and offsetTop values from the elements along the path.  It returns
 * an object that contains four attributes for each of the four sides: offsets.top,
 * offsets.right, offsets.bottom, and offsets.left.
 */
function getOffsets(element) {

    var offsets = {
        left: element.offsetLeft,
        top: element.offsetTop,
        right: element.offsetWidth,
        bottom: element.offsetHeight
    };

    while (element.offsetParent != null) {
        element = element.offsetParent;
        offsets.left += element.offsetLeft;
        offsets.top += element.offsetTop;
    }

    offsets.right += offsets.left;
    offsets.bottom += offsets.top;

    return offsets;
}



/**
 * isDescendant(node, ancestor):
 * Returns true if the node is a descendant of the ancestor (or is the ancestor itself) in the DOM tree, false otherwise.  Recursively traverses the DOM tree from the node to the root element, making O(log(n)) calls.
 */
function isDescendant(node, ancestor) {
    if (!node)
        return false;
    else if (node == ancestor)
        return true;
    else
        return isDescendant(node.parentNode, ancestor);
}





// This code is from the book JavaScript: The Definitive Guide, 5th Edition,
// by David Flanagan. Copyright 2006 O'Reilly Media, Inc. (ISBN #0596101996)
/**
 * Geometry.js: portable functions for querying window and document geometry
 *
 * This module defines functions for querying window and document geometry.
 *
 * getWindowX/Y(): return the position of the window on the screen
 * getViewportWidth/Height(): return the size of the browser viewport area
 * getDocumentWidth/Height(): return the size of the document.
 * getHorizontalScroll(): return the position of the horizontal scrollbar
 * getVerticalScroll(): return the position of the vertical scrollbar
 *
 * Note that there is no portable way to query the overall size of the
 * browser window, so there are no getWindowWidth/Height() functions.
 *
 * IMPORTANT: This module must be included in the <body> of a document
 *            instead of the <head> of the document.
 */
var Geometry = {};

if (window.screenLeft) { // IE and others
    Geometry.getWindowX = function() { return window.screenLeft; };
    Geometry.getWindowY = function() { return window.screenTop; };
}
else if (window.screenX) { // Firefox and others
    Geometry.getWindowX = function() { return window.screenX; };
    Geometry.getWindowY = function() { return window.screenY; };
}

if (window.innerWidth) { // All browsers but IE
    Geometry.getViewportWidth = function() { return window.innerWidth; };
    Geometry.getViewportHeight = function() { return window.innerHeight; };
    Geometry.getHorizontalScroll = function() { return window.pageXOffset; };
    Geometry.getVerticalScroll = function() { return window.pageYOffset; };
}
else if (document.documentElement && document.documentElement.clientWidth) {
    // These functions are for IE6 when there is a DOCTYPE
    Geometry.getViewportWidth =
        function() { return document.documentElement.clientWidth; };
    Geometry.getViewportHeight =
        function() { return document.documentElement.clientHeight; };
    Geometry.getHorizontalScroll =
        function() { return document.documentElement.scrollLeft; };
    Geometry.getVerticalScroll =
        function() { return document.documentElement.scrollTop; };
}
else if (document.body.clientWidth) {
    // These are for IE4, IE5, and IE6 without a DOCTYPE
    Geometry.getViewportWidth =
        function() { return document.body.clientWidth; };
    Geometry.getViewportHeight =
        function() { return document.body.clientHeight; };
    Geometry.getHorizontalScroll =
        function() { return document.body.scrollLeft; };
    Geometry.getVerticalScroll =
        function() { return document.body.scrollTop; };
}

// These functions return the size of the document.  They are not window
// related, but they are useful to have here anyway.
if (document.documentElement && document.documentElement.scrollWidth) {
    Geometry.getDocumentWidth =
        function() { return document.documentElement.scrollWidth; };
    Geometry.getDocumentHeight =
        function() { return document.documentElement.scrollHeight; };
}
else if (document.body.scrollWidth) {
    Geometry.getDocumentWidth =
        function() { return document.body.scrollWidth; };
    Geometry.getDocumentHeight =
        function() { return document.body.scrollHeight; };
}




// This code is from the book JavaScript: The Definitive Guide, 5th Edition,
// by David Flanagan. Copyright 2006 O'Reilly Media, Inc. (ISBN #0596101996)
/*
 * Handler.js -- Portable event handler registration functions
 *
 * This module defines event handler registration and deregistration functions
 * Handler.add() and Handler.remove(). Both functions take three arguments:
 *
 *   element: the DOM element, document, or window on which the handler
 *      is to be added or removed.
 *
 *   eventType: a string that specifies the type of event for which the
 *      handler is to be invoked.  Use DOM-standard type names, which do
 *      not include an "on" prefix. Examples: "click", "load", "mouseover".
 *
 *   handler: The function to be invoked when an event of the specified type
 *      occurs on the specified element.  This function will be invoked as
 *      a method of the element on which it is registered, and the "this"
 *      keyword will refer to that element.  The handler function will be
 *      passed an event object as its sole argument.  This event object will
 *      either be a DOM-standard Event object or a simulated one. If a
 *      simulated event object is passed, it will have the following DOM-
 *      compliant properties: type, target, currentTarget, relatedTarget,
 *      eventPhase, clientX, clientY, screenX, screenY, altKey, ctrlKey,
 *      shiftKey, charCode, stopPropagation(), and preventDefault()
 *
 * Handler.add() and Handler.remove() have no return value.
 *
 * Handler.add() ignores duplicate registrations of the same handler for
 * the same event type and element.  Handler.remove() does nothing if called
 * to remove a handler that has not been registered.
 *
 * Implementation notes:
 *
 * In browsers that support the DOM standard addEventListener() and
 * removeEventListener() event registration functions, Handler.add() and
 * Handler.remove() simply invoke these functions, passing false as the
 * third argument (meaning that the event handlers are never registered as
 * capturing event handlers).
 *
 * In versions of Internet Explorer that support attachEvent(), Handler.add()
 * and Handler.remove() use attachEvent() and detachEvent(). To
 * invoke the handler function with the correct this keyword, a closure is
 * used.  Since closures of this sort cause memory leaks in Internet Explorer,
 * Handler.add() automatically registers an onunload handler to deregister
 * all event handlers when the page is unloaded. To keep track of
 * registered handlers, Handler.add() creates a property named _allHandlers on
 * the window object and creates a property named _handlers on any element on
 * which a handler is registered.
 */
var Handler = {};

// In DOM-compliant browsers, our functions are trivial wrappers around
// addEventListener() and removeEventListener().
if (document.addEventListener) {
    Handler.add = function(element, eventType, handler) {
        element.addEventListener(eventType, handler, false);
    };

    Handler.remove = function(element, eventType, handler) {
        element.removeEventListener(eventType, handler, false);
    };
}
// In IE 5 and later, we use attachEvent() and detachEvent(), with a number of
// hacks to make them compatible with addEventListener and removeEventListener.
else if (document.attachEvent) {
    Handler.add = function(element, eventType, handler) {
        // Don't allow duplicate handler registrations
        // _find() is a private utility function defined below.
        if (Handler._find(element, eventType, handler) != -1) return;

        // To invoke the handler function as a method of the
        // element, we've got to define this nested function and register
        // it instead of the handler function itself.
        var wrappedHandler = function(e) {
            if (!e) e = window.event;

            // Create a synthetic event object with partial compatibility
            // with DOM events.
            var event = {
                _event: e,    // In case we really want the IE event object
                type: e.type,           // Event type
                target: e.srcElement,   // Where the event happened
                currentTarget: element, // Where we're handling it
                relatedTarget: e.fromElement?e.fromElement:e.toElement,
                eventPhase: (e.srcElement==element)?2:3,

                // Mouse coordinates
                clientX: e.clientX, clientY: e.clientY,
                screenX: e.screenX, screenY: e.screenY,

                // Key state
                altKey: e.altKey, ctrlKey: e.ctrlKey,
                shiftKey: e.shiftKey, charCode: e.keyCode,

                // Event management functions
                stopPropagation: function() {this._event.cancelBubble = true;},
                preventDefault: function() {this._event.returnValue = false;}
            }

            // Invoke the handler function as a method of the element, passing
            // the synthetic event object as its single argument.
            // Use Function.call() if defined; otherwise do a hack
            if (Function.prototype.call)
                handler.call(element, event);
            else {
                // If we don't have Function.call, fake it like this
                element._currentHandler = handler;
                element._currentHandler(event);
                element._currentHandler = null;
            }
        };

        // Now register that nested function as our event handler.
        element.attachEvent("on" + eventType, wrappedHandler);

        // Now we must do some record keeping to associate the user-supplied
        // handler function and the nested function that invokes it.

        // We have to do this so that we can deregister the handler with the
        // remove() method and also deregister it automatically on page unload.

        // Store all info about this handler into an object
        var h = {
            element: element,
            eventType: eventType,
            handler: handler,
            wrappedHandler: wrappedHandler
        };

        // Figure out what document this handler is part of.
        // If the element has no "document" property, it is not
        // a window or a document element, so it must be the document
        // object itself.
        var d = element.document || element;
        // Now get the window associated with that document
        var w = d.parentWindow;

        // We have to associate this handler with the window,
        // so we can remove it when the window is unloaded
        var id = Handler._uid();  // Generate a unique property name
        if (!w._allHandlers) w._allHandlers = {};  // Create object if needed
        w._allHandlers[id] = h; // Store the handler info in this object

        // And associate the id of the handler info with this element as well
        if (!element._handlers) element._handlers = [];
        element._handlers.push(id);

        // If there is not an onunload handler associated with the window,
        // register one now.
        if (!w._onunloadHandlerRegistered) {
            w._onunloadHandlerRegistered = true;
            w.attachEvent("onunload", Handler._removeAllHandlers);
        }
    };

    Handler.remove = function(element, eventType, handler) {
        // Find this handler in the element._handlers[] array.
        var i = Handler._find(element, eventType, handler);
        if (i == -1) return;  // If the handler was not registered, do nothing

        // Get the window of this element
        var d = element.document || element;
        var w = d.parentWindow;

        // Look up the unique id of this handler
        var handlerId = element._handlers[i];
        // And use that to look up the handler info
        var h = w._allHandlers[handlerId];
        // Using that info, we can detach the handler from the element
        element.detachEvent("on" + eventType, h.wrappedHandler);
        // Remove one element from the element._handlers array
        element._handlers.splice(i, 1);
        // And delete the handler info from the per-window _allHandlers object
        delete w._allHandlers[handlerId];
    };

    // A utility function to find a handler in the element._handlers array
    // Returns an array index or -1 if no matching handler is found
    Handler._find = function(element, eventType, handler) {
        var handlers = element._handlers;
        if (!handlers) return -1;  // if no handlers registered, nothing found

        // Get the window of this element
        var d = element.document || element;
        var w = d.parentWindow;

        // Loop through the handlers associated with this element, looking
        // for one with the right type and function.
        // We loop backward because the most recently registered handler
        // is most likely to be the first removed one.
        for(var i = handlers.length-1; i >= 0; i--) {
            var handlerId = handlers[i];        // get handler id
            var h = w._allHandlers[handlerId];  // get handler info
            // If handler info matches type and handler function, we found it.
            if (h.eventType == eventType && h.handler == handler)
                return i;
        }
        return -1;  // No match found
    };

    Handler._removeAllHandlers = function() {
        // This function is registered as the onunload handler with
        // attachEvent.  This means that the this keyword refers to the
        // window in which the event occurred.
        var w = this;

        // Iterate through all registered handlers
        for(id in w._allHandlers) {
            // Get handler info for this handler id
            var h = w._allHandlers[id];
            // Use the info to detach the handler
            h.element.detachEvent("on" + h.eventType, h.wrappedHandler);
            // Delete the handler info from the window
            delete w._allHandlers[id];
        }
    }

    // Private utility to generate unique handler ids
    Handler._counter = 0;
    Handler._uid = function() { return "h" + Handler._counter++; };
}


function wrapEventHandler(object, eventHandler) {
    return function() { object[eventHandler].apply(object, arguments); }
}



/**
 * Browser Detection by QuirksMode.org (http://www.quirksmode.org/js/detect.html)
 *
 * Browser name: BrowserDetect.browser
 * Browser version: BrowserDetect.version
 * OS name: BrowserDetect.OS
 */

var BrowserDetect = {
    init: function () {
        this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
        this.version = this.searchVersion(navigator.userAgent)
            || this.searchVersion(navigator.appVersion)
            || "an unknown version";
        this.OS = this.searchString(this.dataOS) || "an unknown OS";
    },
    searchString: function (data) {
        for (var i=0;i<data.length;i++)    {
            var dataString = data[i].string;
            var dataProp = data[i].prop;
            this.versionSearchString = data[i].versionSearch || data[i].identity;
            if (dataString) {
                if (dataString.indexOf(data[i].subString) != -1)
                    return data[i].identity;
            }
            else if (dataProp)
                return data[i].identity;
        }
    },
    searchVersion: function (dataString) {
        var index = dataString.indexOf(this.versionSearchString);
        if (index == -1) return;
        return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
    },
    dataBrowser: [
        {     string: navigator.userAgent,
            subString: "OmniWeb",
            versionSearch: "OmniWeb/",
            identity: "OmniWeb"
        },
        {
            string: navigator.vendor,
            subString: "Apple",
            identity: "Safari"
        },
        {
            prop: window.opera,
            identity: "Opera"
        },
        {
            string: navigator.vendor,
            subString: "iCab",
            identity: "iCab"
        },
        {
            string: navigator.vendor,
            subString: "KDE",
            identity: "Konqueror"
        },
        {
            string: navigator.userAgent,
            subString: "Firefox",
            identity: "Firefox"
        },
        {
            string: navigator.vendor,
            subString: "Camino",
            identity: "Camino"
        },
        {        // for newer Netscapes (6+)
            string: navigator.userAgent,
            subString: "Netscape",
            identity: "Netscape"
        },
        {
            string: navigator.userAgent,
            subString: "MSIE",
            identity: "Explorer",
            versionSearch: "MSIE"
        },
        {
            string: navigator.userAgent,
            subString: "Gecko",
            identity: "Mozilla",
            versionSearch: "rv"
        },
        {         // for older Netscapes (4-)
            string: navigator.userAgent,
            subString: "Mozilla",
            identity: "Netscape",
            versionSearch: "Mozilla"
        }
    ],
    dataOS : [
        {
            string: navigator.platform,
            subString: "Win",
            identity: "Windows"
        },
        {
            string: navigator.platform,
            subString: "Mac",
            identity: "Mac"
        },
        {
            string: navigator.platform,
            subString: "Linux",
            identity: "Linux"
        }
    ]

};
BrowserDetect.init();



/**
 * hasClass:
 * Test if a DOM node has a CSS class with the given name.
 *
 * @param node the DOM node in which to look for the class
 * @param className the class to look for
 *
 * @return true if the node has the class, false otherwise
 */
function hasClass(node, className) {
    return node && node.className.match(new RegExp("(\\s|^)" + className + "(\\s|$)"));
}

/**
 * addClass:
 * Adds a CSS class to a DOM node, if the node does not already have that class.
 *
 * @param node the DOM node to which the class should be added
 * @param className the class to be added
 *
 * @return true if the class is added to the node, false if the class already exists in the node
 */
function addClass(node, className) {
    if (node && !hasClass(node,className)) {
        node.className += " " + className;
        return true;
    }
    else
        return false;
}

/**
 * removeClass:
 * Remove a CSS class from a DOM node, if the node has the class.
 *
 * @param node the DOM node from which to remove the class
 * @param className the class to remove
 *
 * @return true if the class is removed from the node, false if the node does not have the class to be removed
 */
function removeClass(node, className) {
    if (hasClass(node,className)) {
        node.className = node.className.replace(new RegExp("(\\s+|^)" + className + "(\\s+|$)"), " ");
        return true;
    }
    else
        return false;
}

/**
 * replaceClass:
 * Replaces one CSS class with another CSS class in a DOM node.
 *
 * @param node the node for which to swap classes
 * @param oldClassName the class that is to be replaced out of the node
 * @param newClassName the class that is to be replaced into the node
 *
 * @return true if the class is replaced, false if the class that is to be replaced does not exist in the node
 */
function replaceClass(node, oldClassName, newClassName)  {
    if (hasClass(node, oldClassName)) {
        node.className = node.className.replace(new RegExp("(\\s|^)" + oldClassName + "(\\s|$)"), " " + newClassName + " ");
        return true;
    }
    else
        return false;
}


/**
 * Dropdown(dropdown, options):
 * @author Benjamin Black
 *
 * For making dropdowns.  Documentation TK.
 */
function Dropdown(dropdownNode, options)
{
    this.options = ((options) ? options : Dropdown.defaultOptions);

    this.nodes = { };
    with (this.nodes) {
        this.nodes.dropdown = dropdownNode;
        this.nodes.contentarea = getElements("dd_contentarea", "div", dropdown)[0];
        this.nodes.content = getElements("dd_content", "div", contentarea)[0];
        this.nodes.list = content.getElementsByTagName("ul")[0];
        this.nodes.listItems = list.getElementsByTagName("li");
        this.nodes.selector = getElements("dd_selector", "div", dropdown)[0];
        this.nodes.leftborder = getElements("dd_leftborder", "div", selector)[0];
        this.nodes.title = getElements("dd_title", "div", selector)[0];
        this.nodes.button = getElements("dd_button", "div", selector)[0];
        this.nodes.rightborder = getElements("dd_rightborder", "div", selector)[0];
        this.nodes.parent = dropdown.parentNode;
        this.nodes.nextSibling = dropdown.nextSibling;
    }

/*
    this.listeners = { };
    with (this.options.listeners) {
        this.listeners.dropdownNode = (typeof dropdownNode == "function" ? dropdownNode: Dropdown.emptyFunction);
        this.listeners.contentAreaNode = (typeof contentAreaNode == "function" ? contentAreaNode : Dropdown.emptyFunction);
        this.listeners.contentNode = (typeof contentNode == "function" ? contentNode : Dropdown.emptyFunction);
    }
*/
    if (typeof this.options.display.contentAreaOffset != "number")
        this.options.display.contentAreaOffset = 0;

    if (typeof this.options.display.contentOffset != "number")
        this.options.display.contentOffset = 0;

    if (typeof this.options.display.windowPadding != "number")
        this.options.display.windowPadding = 25;

    if (typeof this.options.display.autoWidthScrollbarPadding != "number")
        this.options.display.autoWidthScrollbarPadding = 10;

    Dropdown.registerDropdown(this);

    Handler.add(this.nodes.selector, "click", wrapEventHandler(this, "toggleDropdown"));

}

Dropdown.defaultOptions = {
/*
    listeners: {

    },
*/

    display: {
        windowPadding: 25,
        maxItemsShowing: 10,
//        minWidth: 300,
//        maxWidth: 100,
//        minHeight: 300,
//        maxHeight: 100,
        fitWidth: true,
        autoWidthScrollbarPadding: 10,
        contentAreaOffset: -5,
        contentOffset: 5
    }
};

// An empty function that does nothing and returns.  Used as the default dropdown event listener function when none is specified by the user.
Dropdown.emptyFunction = function() { };

// Array that stores created dropdowns.  used to ensure that the runOnLoad event doesn't create duplicate dropdowns, in case the user has manually created a dropdown in order to customize it via options.
Dropdown.dropdowns = [ ];

Dropdown.registerDropdown = function(dropdown) {
    Dropdown.dropdowns[Dropdown.dropdowns.length] = dropdown.nodes.dropdown;
}

Dropdown.prototype.getState = function() {
    if (hasClass(this.nodes.selector, "active"))
        return "active";
    else
        return "inactive";
}

Dropdown.prototype.getSelectorWidth = function() {
    return this.nodes.leftborder.offsetWidth + this.nodes.title.offsetWidth + this.nodes.button.offsetWidth + this.nodes.rightborder.offsetWidth;
}

Dropdown.prototype.toggleState = function() {
    if (this.getState() == "active") {
        replaceClass(this.nodes.selector, "active", "inactive");
    }
    else {
        replaceClass(this.nodes.selector, "inactive", "active");
    }
}

Dropdown.prototype.toggleDropdown = function(e) {
    if (this.nodes.listItems.length == 0) {
        return;
    }

    this.toggleState();
    if (this.getState() == "active") {
        this.activate();
        this.documentClick = wrapEventHandler(this, "documentClickHandler");
        this.windowResize = wrapEventHandler(this, "windowResizeHandler");
        Handler.add(document, "click", this.documentClick);
        Handler.add(window, "resize", this.windowResize);
    }
    else {
        this.deactivate();
        Handler.remove(document, "click", this.documentClick);
        Handler.remove(window, "resize", this.windowResize);
    }
}

Dropdown.prototype.activate = function() {
    var offsets = getOffsets(this.nodes.selector);

    this.nodes.contentarea.style.visibility = "hidden";
    this.nodes.contentarea.style.display = "block";
    (document.body) ? document.body.appendChild(this.nodes.contentarea) : document.documentElement.appendChild(this.nodes.contentarea);

    this.nodes.selector.style.visibility = "hidden";
    (document.body) ? document.body.appendChild(this.nodes.selector) : document.documentElement.appendChild(this.nodes.selector);

    var spaceLeft = offsets.right - Geometry.getHorizontalScroll() - 2 * this.options.display.windowPadding;
    var spaceRight = Geometry.getViewportWidth() - (offsets.left - Geometry.getHorizontalScroll()) - 2 * this.options.display.windowPadding;
    var spaceAbove = offsets.top - Geometry.getVerticalScroll() - 2 * this.options.display.windowPadding;
    var spaceBelow = Geometry.getViewportHeight() - (offsets.top - Geometry.getVerticalScroll()) - 2 * this.options.display.windowPadding;

    var isWidthMinimized = typeof this.options.display.minWidth == "number" && this.nodes.content.offsetWidth < this.options.display.minWidth;
    var isWidthMaximized = typeof this.options.display.maxWidth == "number" && this.nodes.contentarea.offsetWidth > this.options.display.maxWidth;
    var isWidthFitted = typeof this.options.display.fitWidth == "boolean";
    var isHeightMinimized = typeof this.options.display.minHeight == "number" && this.nodes.contentarea.offsetHeight < this.options.display.minHeight;
    var isHeightMaximized = typeof this.options.display.maxHeight == "number" && this.nodes.contentarea.offsetHeight > this.options.display.maxHeight;

    if (isWidthMinimized) {
        this.nodes.content.style.width = this.options.display.minWidth + "px";
        this.nodes.content.style.width = (this.options.display.minWidth - (this.nodes.content.offsetWidth - this.options.display.minWidth)) + "px";
    }

    if (isWidthMaximized) {
        this.nodes.content.style.width = this.options.display.maxWidth + "px";
        this.nodes.content.style.width = (this.options.display.maxWidth - (this.nodes.content.offsetWidth - this.options.display.maxWidth)) + "px";
    }
    else if (isWidthFitted) {
        this.nodes.content.style.width = this.nodes.selector.offsetWidth + "px";
        this.nodes.content.style.width = (this.nodes.selector.offsetWidth - (this.nodes.contentarea.offsetWidth - this.nodes.contentarea.clientWidth)) + "px";
        isWidthFitted = true;
    }

    if (!isWidthMinimized && !isWidthMaximized && !isWidthFitted) {
        this.nodes.content.style.whiteSpace = "nowrap";
    }

    if (isHeightMinimized) {
        this.nodes.content.style.height = this.options.display.minHeight + "px";
        this.nodes.content.style.height = (this.options.display.minHeight - (this.nodes.content.offsetHeight - this.options.display.minHeight)) + "px";
    }
    else if (isHeightMaximized) {
        this.nodes.content.style.height = this.options.display.maxHeight + "px";
        this.nodes.content.style.height = (this.options.display.maxHeight - (this.nodes.contentarea.offsetHeight - this.nodes.contentarea.clientHeight)) + "px";
        isHeightMaximized = true;
    }

    var isBottomAligned = false;
    if (this.nodes.contentarea.offsetHeight > spaceBelow && spaceAbove > spaceBelow) {
        isBottomAligned = true;
    }

    if (typeof this.options.display.maxItemsShowing == "number") {
        var height = 0;
        for (var i = 0; i < this.options.display.maxItemsShowing && i < this.nodes.listItems.length; ++i)
            height += this.nodes.listItems[i].offsetHeight;
        this.nodes.content.style.height = height + "px";
    }

    if (isBottomAligned) {
        if (this.nodes.contentarea.offsetHeight > spaceAbove) {
            this.nodes.content.style.height = spaceAbove + "px";
            this.nodes.content.style.height = (spaceAbove - (this.nodes.content.offsetHeight - spaceAbove)) + "px";
        }
        this.nodes.contentarea.style.top = (offsets.top - this.nodes.contentarea.offsetHeight - this.options.display.contentAreaOffset) + "px";
        this.nodes.content.style.marginBottom = this.options.display.contentOffset + "px";
    }
    else {
        if (this.nodes.contentarea.offsetHeight > spaceBelow) {
            this.nodes.content.style.height = spaceBelow + "px";
            this.nodes.content.style.height = (spaceBelow - (this.nodes.content.offsetHeight - spaceBelow)) + "px";
        }
        this.nodes.contentarea.style.top = (offsets.bottom + this.options.display.contentAreaOffset) + "px";
        this.nodes.content.style.marginTop = this.options.display.contentOffset + "px";
    }

    if (this.nodes.content.clientWidth < this.nodes.content.scrollWidth) {
        var width = this.nodes.content.clientWidth;
        while (this.nodes.content.clientWidth < this.nodes.content.scrollWidth) {
            this.nodes.content.style.width = ++width + "px";
        }
        if (typeof this.options.display.autoWidthScrollbarPadding == "number")
            this.nodes.content.style.width = (width + this.options.display.autoWidthScrollbarPadding) + "px";
    }

    this.nodes.contentarea.style.left = offsets.left + "px";

    this.nodes.selector.style.top = offsets.top + "px";
    this.nodes.selector.style.left = offsets.left + "px";
    this.nodes.selector.style.position = "absolute";

    this.nodes.contentarea.style.visibility = "visible";
    this.nodes.selector.style.visibility = "visible";
}

Dropdown.prototype.deactivate = function() {
    this.nodes.contentarea.style.visibility = "hidden";
    this.nodes.contentarea.style.display = "none";
    this.nodes.selector.style.visibility = "hidden";

    this.nodes.contentarea.style.position = "";
    this.nodes.contentarea.style.top = "";
    this.nodes.contentarea.style.left = "";

    this.nodes.selector.style.position = "";
    this.nodes.selector.style.top = "";
    this.nodes.selector.style.left = "";

    this.nodes.content.style.height = "";
    this.nodes.content.style.width = "";

    this.nodes.content.style.whiteSpace = "";

    this.nodes.dropdown.appendChild(this.nodes.contentarea);
    this.nodes.dropdown.appendChild(this.nodes.selector);

    this.nodes.selector.style.visibility = "visible";
}


Dropdown.prototype.documentClickHandler = function(e) {
    if (!isDescendant(e.target, this.nodes.selector) && !isDescendant(e.target, this.nodes.contentarea)) {
        this.toggleDropdown();
    }
}

Dropdown.prototype.windowResizeHandler = function(e) {
    this.toggleDropdown();
    this.toggleDropdown();
}


// This function runs on page load.  It loops through all the dropdowns in the document and creates an instance of Dropdown for each, checking to make sure that a Dropdown object does not already exist for that dropdown.
runOnLoad(function() {
    var dropdowns = getElements("dropdown", "*", document);
    for (var i = 0; i < dropdowns.length; ++i) {
        var found = false;
        for (var j = 0; j < Dropdown.dropdowns.length; ++j) {
            if (dropdowns[i] == Dropdown.dropdowns[j]) {
                found = true;
                break;
            }
        }
        if (!found) {
            try {
                new Dropdown(dropdowns[i], Dropdown.default_options);
            }
            catch (e) {
                alert("Error creating dropdown:\nNode id: \"" + dropdowns[i].id + "\"\nNode class: \"" + dropdowns[i].className + "\"");
            }
        }
    }
});

function mainNavMenus(id, display)
{

var navID;
var navEl;
var ulEl;

var bodyId = document.body.id;

navID = id.replace(/dd_/,"");

if (document.getElementById(id))
    {
        ulEl = document.getElementById(id);
    }

if (display)
    {
        if (document.getElementById(navID))
        {
            navEl = document.getElementById(navID);
            navEl.style.backgroundColor = "#0e1113";
            navEl.style.color = "#9cc5dc";
        }

        if (ulEl && bodyId != 'trendsshopping_candy_index')
            ulEl.style.visibility = "visible";

    }

else
    {
        if (document.getElementById(navID))
        {
            navEl = document.getElementById(navID);
            navEl.style.backgroundColor = "transparent";
            navEl.style.color = "#fff";
        }

        if (ulEl && bodyId != 'trendsshopping_candy_index')
            ulEl.style.visibility = "hidden";

    }
}

function searchInput(state)
{
    var inputEl;

    if (document.getElementById("google_input"))
    {
        inputEl = document.getElementById("google_input");

        if (state)
        {
            inputEl.value = "";
            inputEl.style.color = "#000";
        }

        if (!state && inputEl.value == "")
        {
            inputEl.style.color = "#999";
            inputEl.value = "Search Style.com";
        }
    }

}

function openSlideshow(url) {

    if (BrowserDetect.browser == "Explorer" && BrowserDetect.version == "6")
    {
        var slideShowWindow = window.open(url,'Slideshow','menubar=no,toolbar=no,location=no,directories=no,status=no,scrollbars=yes,resizable=no,width=931,height=670');
    }
    else
    if (BrowserDetect.browser == "Firefox")

    {
        var slideShowWindow = window.open(url,'Slideshow','menubar=no,toolbar=no,location=no,directories=no,status=no,scrollbars=yes,resizable=no,width=915,height=670');
    }
    else
    if (BrowserDetect.browser == "Safari")

    {
        var slideShowWindow = window.open(url,'Slideshow','menubar=no,toolbar=no,location=no,directories=no,status=no,scrollbars=yes,resizable=no,width=930,height=670');
    }
    else
    {
        var slideShowWindow = window.open(url,'Slideshow','menubar=no,toolbar=no,location=no,directories=no,status=no,scrollbars=yes,resizable=no,width=920,height=670');
    }

}

var popUpBigImage, popUpTallImage;
popUpBigImage = popUpTallImage = openSlideshow;


function popUpVideoConsole(url) {
      var videoWindow = "";
      videoWindow = window.open(url,'videoConsole','menubar=no,toolbar=no,location=no,directories=no,status=no,scrollbars=no,resizable=no,width=1050,height=723');
}

// END Standard popup window script END //


function popWinners(url) {
   var detWindow=""
   detWindow=window.open(url,'Winners','menubar=no,toolbar=no,location=no,directories=no,status=no,scrollbars=yes,resizable=yes,width=350,height=550');
}

/**
 *AdRefresh functions for flash content
 *
 **/
function updateAd(args) {
     var tileNum = parseInt(args), div, script;
     var divName ='';
     if(tileNum == 1){
         divName = 'banner';
     }
     if(tileNum == 2){
         divName = 'box_ad';
     }
     editBody(divName, args.substr(args.indexOf("|") + 1));
}

function styleFlash_DoFSCommand(command, args) {
    var tileNum = parseInt(args), div, script;
    var divName ='';
 if (command == "updateAd") {
         if(tileNum == 1){
             divName = 'banner';
         }
         if(tileNum == 2){
             divName = 'box_ad';
         }
        if(tileNum == 3){
             divName = 'box_ad2';
         }
         //call edit body
         editBody(divName, args.substr(args.indexOf("|") + 1));
     }
}

if (navigator.appName && navigator.appName.indexOf("Microsoft") != -1 && navigator.userAgent.indexOf("Windows") != -1 && navigator.userAgent.indexOf("Windows 3.1") == -1) {
  document.write('<SCRIPT LANGUAGE=VBScript\> \n');
  document.write('on error resume next \n');
  document.write('Sub styleFlash_FSCommand(ByVal command, ByVal args)\n');
  document.write(' call styleFlash_DoFSCommand(command, args)\n');
  document.write('end sub\n');
  document.write("</SCRIPT\> \n");
}

function editBody(rootName, code) {
    if(document.getElementById(rootName)!=null){
        document.getElementById(rootName).innerHTML = code;
    }
}

window.name="opener";

function go(url) {
    if (opener && !opener.closed) {
        opener.location.href = url;
        window.close();
    } else {
    self.location.href = url;
    }
}

/* Vogue legacy static slideshow pop-up */
    function popUpVogue(url) {
        var detWindow=""; detWindow=window.open(url,'BIGPopUp','menubar=no,toolbar=no,location=no,directories=no,status=no,scrollbars=no,resizable=no,width=733,height=471');
    }

/*From Registration.js*/
/*************************************************************************************************************************
// File:    Registration.js
// Author:     Matthew Hammond Mah, CondeNet
// Date:     4/2/2007
// Summary: This javascript library is intended for the generic registration process that is used across all of CondeNet's
//             desitnation sites (Style.com,Mens.Style.com,Concierge.com,Epicurious.com)
//
*************************************************************************************************************************/

var agt=navigator.userAgent.toLowerCase();
var is_safari = true;

function ReadCookie(cookieName) {
     var theCookie=""+document.cookie;
    var ind=theCookie.indexOf(cookieName);
    if (ind==-1 || cookieName=="") return "";
     var ind1=theCookie.indexOf(';',ind);
    if (ind1==-1) ind1=theCookie.length;
    return unescape(theCookie.substring(ind+cookieName.length+1,ind1));
}

var currEntryId;

function UserInfo () {
}

UserInfo.USERNAME_COOKIE = 'amg_user_info';

UserInfo.prototype.getUserName =
    function () {
        var cookieVal = ReadCookie(UserInfo.USERNAME_COOKIE);
        if (cookieVal == '') {
            return null;
        }

        return cookieVal;
        };

UserInfo.prototype.isLoggedIn =
    function () {
        return this.getUserName() != null;
    };

function showMouseOverPointer(e) {
    document.getElementById(this.id).style.cursor = 'pointer';
}

function appendReturnto() {
        window.location = '/user/login/retrieve?returnto=' + escape(window.location.pathname + window.location.search);
    }

function doLogoutPost() {
    var opt = {
        method: 'post',
        onSuccess:
            function(response) {
                window.location = window.location;
            }
    }
//        if (confirm("Are you sure that you want to log out?")) {
        new Ajax.Request('/user/logout', opt);
//        }
}

function gotoLogin() {
    window.location = '/user/login?returnto=' + escape(window.location.pathname + window.location.search);
}

// Register Nav Bar events
function registerLoginLink(){
    var login_link = document.getElementById('login_link');
    if(login_link)
    {
        if(login_link.addEventListener)        //IE6 does not support addEventListener
            login_link.addEventListener("click", gotoLogin, false);
        else
            login_link.attachEvent("onclick", gotoLogin);

    }

}

runOnLoad(showUserStatusInNav);
runOnLoad(registerLoginLink);


function showUserStatusInNav() {
    if (new UserInfo().isLoggedIn()) {
        doShowSignedInNavbar();
    } else {
        doShowSignedOutNavbar();
    }
}

function doShowSignedOutNavbar() {
    if (document.getElementById('logged_out') != null) {
        document.getElementById('logged_out').style.display = 'block';
    }
    if (document.getElementById('logged_in') != null) {
        document.getElementById('logged_in').style.display = 'none';
    }
    if (document.getElementById('userId') != null) {
        document.getElementById('userId').innerHTML = '';
    }
}

function doShowSignedInNavbar() {
    if (document.getElementById('logged_in') != null) {
        document.getElementById('logged_in').style.display = 'block';
    }
    if (document.getElementById('logged_out') != null) {
        document.getElementById('logged_out').style.display = 'none';
    }
    if (document.getElementById('userId') != null) {
        document.getElementById('userId').innerHTML = '<a id="userProfileHome" href="/user/preferences">' + new UserInfo().getUserName() + '</a>';
    }

}
/*end registration.js*/

/*from dart.js*/
/* empty array to prevent js error in debugging info */
var dartCalls = new Array();
var noDart = false;
// dart global code
// Defines a dart object and global random number and tile counter.
var dart = new Object();
dart["tile_num"] = undefined;
dart["ord"] = Math.random()*10000000000000000;
dart["url"] = "http://ad.doubleclick.net/adj/";


// dart ad reloading code.
// Grabs the DART code from the hidden iframe and places that in the ad's div.
function dartSwap(placement) {
  var frameRef = document.getElementById('dartFrame_'+placement);
  var htmlRef = (frameRef.contentDocument || frameRef.contentWindow.document).getElementById('adHolder').innerHTML;
  // Destroy the content in the iframe. This prevents double ads running (i hope).
  (frameRef.contentDocument || frameRef.contentWindow.document).location.replace("/nolayout/blankadcontent");

  // Now strip out the doubleclick call that ends up in the iframe's innerHTML. This avoids double doubleclick hits.
  htmlRef = htmlRef.toString();
  var regExp = new RegExp(dart[placement].dartCall,'i');
  var frameHTML = new String(htmlRef);
  frameHTML = frameHTML.replace(regExp, '');
  frameHTML = frameHTML.replace(/<script .*?src="\?".*?><\/script>/i,'');
  // Finally plop the iframe's html into the div.
  document.getElementById('dartTarget_'+placement).innerHTML = frameHTML;
}

// Goes through all of the ads on the page and refreshes them.
function dartReload() {
  // refresh the ord.
  dart["ord"] = Math.random()*10000000000000000;
  var adUnits = document.getElementsByTagName('iframe')
  for(i=0; i <adUnits.length;i++) {
   if(adUnits[i].className == 'hiddenDAU') {
     adParts = adUnits[i].id.split('_');
     if(i == 0) {dart["tile_num"] = undefined; }
     dartRequest(adParts[1]);
   }
  }
 }

 // Makes a DART request. Request is in hidden iframe. Callback in the iframe calls
 // dartSwap when the ad is finished loading.
 function dartRequest(posId) {
     if (typeof dart["tile_num"] == "undefined"){ dart["tile_num"]=1;} else { dart["tile_num"]++; }
     var sysparams = 'tile='+dart["tile_num"]+';ord='+dart["ord"],
         dartCall = dart[posId].dartCall,
         dartURL = '/nolayout/displayad';

     dartCall = dartSiteModifier.setSite(dartCall),
     dart[posId].dartCall= dart["url"]+ dartCall + dart[posId].dcopt+dart[posId].placement+sysparams+'?',
     dartURL = dartURL + '?exe=dartSwap("'+posId+'")' + '&req='+dart[posId].dartCall;

    if (noDart == true) {
        document.write('No Ads, removed in DartCall.js');
    } else {
        document.write('<scr'+'ipt type="text/javascript" src="'+dart[posId].dartCall+ '"></scr'+'ipt>');
    }
}


var dartSiteModifier = (function(ua){
    var suff="",
        pat=/.*\.[\w\.]+\/.*/;

    //If browser is iPad based, add the iPad specific dart string.
    if (ua.indexOf('ipad')!==-1){
            suff ='.ipad';
    }

    return {
        setSite : function(dartCall){
            return dartCall.match(pat)[0].split('/').join(suff+'/');
        }
    }
 })(navigator.userAgent.toLowerCase())


var isSafari = 'false'; // Delete once going back to iframes.

// Not currently used.
var debug = {
    log: function(data) {
        var head = document.getElementsByTagName('head').item(0)
        debugCSS = document.createElement('link');
        debugCSS.href = '/css/debug.css';
        debugCSS.type = 'text/css';
        debugCSS.rel = 'stylesheet';
        var body = document.getElementsByTagName('body').item(0)
        var debugLayer = document.getElementById('debug');
        if(!debugLayer) {
            head.appendChild(debugCSS);
            debugLayer = document.createElement('div');
            debugLayer.id = 'debug';
            body.appendChild(debugLayer);
            $('debug').innerHTML = 'Debug Output window <span><a href=\"javascript: $(\'debug\').style.display=\'none\'; void 0;\">[X]Close</a></span><hr>'
        }

        $('debug').innerHTML = $('debug').innerHTML + data + '<br>' ;
     }
}
includeJS("/scripts/flashDetect.js");

/**
  * This is a wrapper call to /scripts/ads/ads-1.5.js
  * cnp.ad.manager.reloadAds()
  * it is used to refresh ads from flash or any other
  * caller with out refreshing the page
  */

function flashupdateads(){
    //call reload ads defined in ad.jsp
    CN.dart.refresh()
}

/**
Includes the libraries for Powersearch functionality
*/
if(typeof jQuery === 'undefined'){
    includeJS("/scripts/jquery-1.4.4.min.js");
}
if (/\/user\/preferences/i.test(location.href)
    || /\/user\/registration/i.test(location.href)
    || /\/community\/lookbooks/i.test(location.href)
    || /\/community\/mylookbooks/i.test(location.href)
    || /\/stylefile/i.test(location.href)
    || /\/trendsshopping\/shopthelook/i.test(location.href)
    || /\/beautycounter/i.test(location.href)
    || /\/vogue\/scene/i.test(location.href)
    || /\/vogue\/voguedaily/i.test(location.href)
    || /\/fashionshows\/sartorialist/i.test(location.href)
) {
    includeJS("/scripts/prototype/prototype.js");
    includeJS("/scripts/yui/build/yahoo-dom-event/yahoo-dom-event.js");
    includeJS("/scripts/yui/build/container/container_core-min.js");
}

if (/\/fashionshows\/powersearch/i.test(location.href)
 || /\/peopleparties\/celebritysearch/i.test(location.href)
 || /\/peopleparties\/modelsearch/i.test(location.href)
 || /\/beauty\/beautysearch/i.test(location.href)
) {
    includeJS("/scripts/clearcase/prototype/prototype.js");
    includeJS("/scripts/prototype/scriptaculous/effects.js");
}

if (/\/vogue\/voguediaries/i.test(location.href)
) {
    includeJS("/scripts/vogue/voguediaries/jquery-1.2.1.pack.js");
    includeJS("/scripts/jquery_noconflict.js");
}

if(/\/vogue\/$/i.test(location.href)
   || /.com\/$/i.test(location.href)) {
    includeJS("/scripts/stats/gwo.js");
    includeJS("/scripts/stats/gtrack.js");

}

if(/\/services\/newsletters\/vogue\/$/i.test(location.href)) {
    includeJS("/scripts/stats/gtrack.js");
    var gaCallType = 'test';
};

if(/\/services\/newsletters\/vogue\/thankyou/i.test(location.href)) {
    includeJS("/scripts/stats/gtrack.js");
    var gaCallType = 'goal';
};


/**
 * Simple plugin for toggling embeded/iframe
 * mode for style ad calls.
 *
 * To enable iframes, set CN.dart.style embed to false, or add the zone
 * to the test pattern below.
 *
 */

CN.dart.style = (function () {

    return {
        init        : function() {
            return {


                embed: false

            }
        },
        name        : "CN Ad Style plugin"

    };
})()
CN.dart.register(CN.dart.style);
