var st_utilities = {
        included_files: new Array(),
        PRODUCTION: "production",
        STAGE: "stage",
        DEV: "dev",
        LOCALHOST: "localhost"
};


/**
  * Adds a trim function to the standard javascript string
  * @return returns the trimmed string
  */
String.prototype.trim = function ()
{
    return this.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1");
};

/**
 * Includes a javescript source file in the curernt page so that its functions
 * can be accessed
 * @param script_filename the url of the js file to include
 */
st_utilities.include = function(script_filename)
{
    // If the given script has already been included, return false
    for (var i = 0; i < st_utilities.included_files.length; i++)
    {
        if (st_utilities.included_files[i] == script_filename) return false;
    }

    // Otherwise, include the script
    var head = document.getElementsByTagName('head').item(0);
    var js = document.createElement('script');
    js.setAttribute('language', 'javascript');
    js.setAttribute('type', 'text/javascript');
    js.setAttribute('src', script_filename);
    head.appendChild(js);

    // Record inclusion for future reference and return true
    st_utilities.included_files[st_utilities.included_files.length] = script_filename;
    return true;
}

/**
 * Add the given function to the list of functions being called on page load.
 * @param new_function a reference to the function to be called on load
 */
st_utilities.addOnLoad = function(new_function)
{
    var oldOnLoad = window.onload;
    window.onload = function ()
    {
        if(typeof oldOnLoad == 'function') oldOnLoad();
        new_function();
    }
}

/**
 * Gets the real left relative to the body
 * @param element a reference to the DOM element or it's id
 * @return the x position of the left of the element in pixels
 */
st_utilities.getAbsoluteLeft = function (element)
{
    if (typeof element == 'string')
        element = document.getElementById(element);
    var xPos = element.offsetLeft;
    var tempelement = element.offsetParent;
    while (tempelement != null) {
        xPos += tempelement.offsetLeft;
        tempelement = tempelement.offsetParent;
    }
    return xPos;
}

st_utilities.setAbsoluteLeft = function (element, left)
{
    if (typeof element == 'string')
        element = document.getElementById(element);
    curLeft = st_utilities.getAbsoluteLeft(element)
    element.style.left = left - curLeft + 'px';
}

/**
 * Gets the real top relementative to the body
 * @param element a reference to the DOM element or it's id
 * @return the y position of the top of the element in pixels
 */
st_utilities.getAbsoluteTop = function (element)
{
    if (typeof element == 'string')
        element = document.getElementById(element);
    var yPos = element.offsetTop;
    var tempelement = element.offsetParent;
    while (tempelement != null) {
        yPos += tempelement.offsetTop;
        tempelement = tempelement.offsetParent;
    }
    return yPos;
}

st_utilities.setAbsoluteTop = function(element, top_)
{
    if (typeof element == 'string')
        element = document.getElementById(element);
    curTop = st_utilities.getAbsoluteTop(element);
    element.style.top = top_ - curTop + 'px';
}

/**
 * Gets the height of the current page in pixels
 * @return the height of the current page in pixels
 */
st_utilities.getPageHeight = function()
{
    if( window.innerHeight && window.scrollMaxY ) // Firefox
    {
        return window.innerHeight + window.scrollMaxY;
    }
    else if( document.body.scrollHeight > document.body.offsetHeight ) // all but Explorer Mac
    {
        return document.body.scrollHeight;
    }
    else // works in Explorer 6 Strict, Mozilla (not FF) and Safari
    {
        return document.body.offsetHeight + document.body.offsetTop;
    }
}

/**
 * Gets the width of the current page
 * @return the width of the current page in pixels
 */
st_utilities.getPageWidth = function()
{
    if( window.innerHeight && window.scrollMaxY ) // Firefox
    {
        return window.innerWidth + window.scrollMaxX;
    }
    else if( document.body.scrollHeight > document.body.offsetHeight ) // all but Explorer Mac
    {
        return document.body.scrollWidth;
    }
    else // works in Explorer 6 Strict, Mozilla (not FF) and Safari
    {
        return document.body.offsetWidth + document.body.offsetLeft;
    }
}

st_utilities.getViewportWidth = function()
{
    if (self.innerWidth)
        return self.innerWidth;
    if (document.documentElement && document.documentElement.clientWidth)
        return document.documentElement.clientWidth;
    if (document.body)
        return document.body.clientWidth;
}

st_utilities.getViewportHeight = function()
{
    if (self.innerHeight)
        return self.innerHeight;
    if (document.documentElement && document.documentElement.clientHeight)
        return document.documentElement.clientHeight;
    if (document.body)
        return document.body.clientHeight;
}

/**
 * Gets the height of the iframe frame in pixels
 * @param frame a reference to the frame or the id of the frame whose size to get
 * @return the height of frame in pixels
 */
st_utilities.getFramePageHeight = function(frame)
{
    if (typeof frame == 'string')
        frame = document.getElementById(frame);

    if( frame.contentDocument ) // Firefox
        return frame.contentDocument.body.scrollHeight;

    if (frame.contentWindow.document && frame.contentWindow.document.body.scrollHeight && frame.contentWindow.document.body.scrollHeight > frame.contentWindow.document.body.offsetHeight) //ie5+ syntax
        return frame.contentWindow.document.body.scrollHeight;

    return frame.contentWindow.document.body.offsetHeight + frame.contentWindow.document.body.offsetTop;

}

st_utilities.getParentIFrame = function()
{
    var iframes = top.document.getElementsByTagName('iframe');
    for (var i=0; i < iframes.length; i++) {
        var iframe = iframes[i];
        var doc = iframe.contentDocument || iframe.contentWindow;
        if (doc == document)
            return iframe;
    }
    return undefined;
}

st_utilities.callParentIFrameOnload = function()
{
    if (top != window) {
        var iframe = st_utilities.getParentIFrame();
        if (iframe.onload)
            iframe.onload();
    }
}


/**
 * Resizes the height of frame to fit the contained page
 * @param frame the frame to resize or its id
 */
st_utilities.resizeIFrameToFitPageHeight = function(frame)
{
    if (typeof frame == 'string')
        frame = document.getElementById(frame);
    var height = st_utilities.getFramePageHeight(frame);

    if ( frame.contentDocument)
        frame.height = height;
    else frame.style.height = height;


}

/**
 * Displays a floating iframe. If the iframe does not already exist, it attempts to create it
 * Takes the following parameters in a javascript closure
 * @param src the file to display in the iframe. REQUIRED
 * @param id the id of the iframe. Defaults to "st_floating_iframe"
 * @param frameborder whether or not to display a border for the iframe. Defaults to 0 (no border). ONLY USED IF NEW IFRAME IS CREATED
 * @param scrolling whether or not to display scrollbars fro the iframe. Defaults to no. ONLY USED IF NEW IFRAME IS CREATED
 * @param zIndex the zIndex to display the iframe at. Defaults to 500 for creation only
 * @param top the top coordinate of the iframe
 * @param left the left coordinate of the iframe
 * @param height the height of the iframe
 * @param width the width of the iframe
 */
st_utilities.floatIFrame = function(args)
{
    if ( args.id == undefined)
        args.id = "st_floating_iframe";

    if ( args.frameborder == undefined)
        args.frameborder = 0;

    if ( args.scrolling == undefined)
        args.scrolling = "no";

    var iframe = document.getElementById(args.id);
    if (iframe == undefined)
    {
        iframe = document.createElement("iframe");
        iframe.setAttribute("scrolling", args.scrolling);
        iframe.setAttribute("frameborder", args.frameborder);
        iframe.setAttribute("id", args.id);
        if ( args.zIndex == undefined)
            iframe.setAttribute("style", "display: none; position: absolute; z-index: 500");
        else
            iframe.setAttribute("style", "display: none; position: absolute; z-index: " + args.zIndex);
        document.body.appendChild(iframe);
    }

    if ( args.top)
        iframe.style.top = args.top;
    if ( args.left)
        iframe.style.left = args.left;
    if ( args.width)
        iframe.style.height = args.height;
    if ( args.height)
        iframe.style.width = args.width;
    if ( args.zIndex)
        iframe.style.zIndex = args.zIndex;

    iframe.style.display = "block";

    iframe.src = args.src;
}

/**
 * Sets the element's display to "block".
 * @param element a reference to the DOM element, or a string with the
 * id of the element to show
*/
st_utilities.show = function (element)
{
    if ( element.style != undefined)
    {
        element.style.display = "block";
    }
    else if (typeof element == 'string')
    {
        var el = document.getElementById(element)
        if ( el != undefined)
            el.style.display = "block";
    }
}

/**
 * Sets the element's display to "none".
 * @param element a reference to the DOM element, or a string with the
 * id of the element to show
*/
st_utilities.hide = function (element)
{
    if ( element.style != undefined)
    {
        element.style.display = "none";
    }
    else if (typeof element == 'string')
    {
        var el = document.getElementById(element)
        if ( el != undefined)
            el.style.display = "none";
    }
}

/**
 * Sets the focus on a given element
 * @param element a reference to the DOM element, or a string with the
 * id of the element to focus on
 */
st_utilities.focus = function(element)
{
    if ( element.style != undefined)
    {
        element.focus();
    }
    else if (typeof element == 'string')
    {
        var el = document.getElementById(element)
        if ( el != undefined)
            el.focus();
    }
}


/**
 * Hides all direct children of the element with the given id or reference
 * @param el the id of the element or a reference to the element whose children to hide
*/
st_utilities.hideChildren = function (el)
{
    if (typeof el == 'string')
        el = document.getElementById(el);

    if (el == undefined)
        return;
    var children = el.childNodes;
    if (children == undefined)
        return;
    for (i = 0; i < children.length; i++)
    {
        var child = children[i];
        st_utilities.hide(child);
    }
}

/**
 * Changes the class of an element given its id or a reference to it
 * @param el the id of the element or a reference to the element whose class
 *      to change
 * @param className the name of the class to change the element's class to
 */
st_utilities.changeClass = function(el, className)
{
    if (typeof el == 'string')
        el = document.getElementById(el);
    if (el == undefined)
	    return;
    el.className = className;
}

/**
 * Changes CSS style of all direct children of the element with the given id or reference to class with name childClassName
 * @param el the id of the element or a reference to the element whose children you want to change
 * @param childClassName the name of the CSS class that you want to assign to the child element
*/
st_utilities.changeChildClass =  function (el, childClassName)
{
    if (typeof el == 'string')
        el = document.getElementById(el);
    if (el == undefined)
        return;
    var children = el.childNodes;
    if (children == undefined)
        return;
    for (i = 0; i < children.length; i++)
    {
        var child = children[i];
        if (child.className != undefined)
        {
            child.className = childClassName;
        }
    }
}

/**
 * Gets an array of elements in a form that have a given name
 * @param form a reference to the form or its ID
 * @param name the name of the elements to find
 */
st_utilities.getNamedElementsInForm = function(form, name)
{
    if (typeof form == 'string')
        form = document.getElementById(form);
    if (form == undefined)
        return;
    var elements = document.getElementsByName(name);
    var ret = new Array();
    for (var i=0; i<elements.length; i++)
    {
        var el = elements[i];
        if ( el.form == form)
            ret.push(el);
    }
    return ret;
}

/**
 * Checks or unchecks a checkbox given a reference to it or its id
 * @param checkbox either a reference to or the ID of the checkbox to check
 * @param checked true to check the checkbox, false to uncheck it. Defauts to true
 */
st_utilities.check = function(checkbox, checked)
{
    if ( typeof checkbox == 'string')
        checkbox = document.getElementById(checkbox);
    if ( checkbox == undefined)
        return;
    if (checked == undefined)
        checked = true;
    checkbox.checked = checked;
}

/**
  * Executes an operation for each item in items
  * @param items an array of objects to excetue the operation on
  * @param operation a referece to a function to execute on each item in items.
  *  The function represtented by oepration must take item as its sole parameter
  * @return an array containing the results of each operation
  */
st_utilities.forEach = function(items, operation)
{
    var ret = new Array();
    for (var i=0; i<items.length; i++)
    {
        ret.push(operation.call(undefined, items[i]));
    }
    return ret;
}

/**
 * Covers the page with a transparent black layer at z-index 100; The transparency of the layer
 * is determined by the value of alpha
 * @param alpha a floating point number between 0 (totally transparent) and 1 (totally opaque)
 */
st_utilities.maskBackground = function(alpha)
{
    if (top.document.body)
    {
        var div = top.document.createElement('div');
        div.style.position = 'fixed';
        div.style.top = 0;
        div.style.left = 0;
        div.style.height = "100%";
        div.style.width = "100%";
        div.style.background = 'url(/img/cmn/shim_000.gif) top left repeat';
        div.style.filter = 'alpha(opacity=' + (alpha * 100) + ')';
        div.style.opacity = alpha;
        div.style.zIndex = '100';
        div.id = 'st_utilities.bgmask';
        top.document.body.appendChild(div);
        return div;
    }
}

/**
 * destroys the background mask
 */
st_utilities.destroyBackgroundMask = function()
{
    var mask = document.getElementById('st_utilities.bgmask');
    if (mask)
        st_utilities.destroyElement(mask);
}

/**
 * Removes an object from the document
 * @param id the id of or a reference to the object to remove
 */
st_utilities.destroyElement = function(el)
{
    if (typeof el == 'string')
        el = document.getElementById(el);
    if (el)
        el.parentNode.removeChild(el);
}

/**
 * Centers an absolute element in the viewport
 * @param the id of or a reference to the absolute element to center
 */
st_utilities.centerAbsoluteElement = function(el)
{
    if (typeof el == 'string')
        el = document.getElementById(el);

    if (el == undefined)
        return;

    var width = el.innerWidth || el.clientWidth;
    var height = el.innerHeight || el.clientHeight;

    if (!el.style.left)
        el.style.left = ((st_utilities.getPageWidth() - width) / 2) + 'px';
    if (!el.style.top)
        el.style.top = ((st_utilities.getPageHeight() - height) / 3) + 'px';
}

/**
 * Masks the page with a transparent black layer and creates a "popup" at z-index 200. The popup
 * is attached to the document body
 * @param el the id of or a reference to the div to clone and render as an in-page popup
 * @param alpha a floating point number between 0 (totally transparent) and 1 (totally opaque)
 */
st_utilities.showPopup = function(el, alpha)
{
    if (typeof el == 'string')
        el = document.getElementById(el);
    if (el)
    {
        // reparent if neccessary. Fixes issues with zindexes on IE7
        if (top.document.body && el.parentNode != top.document.body)
        {
            el.parentNode.removeChild(el);
            top.document.body.appendChild(el);
        }

        el.style.position = 'absolute';
        el.style.zIndex = '200';
        el.style.display = 'block';
        var left = (st_utilities.getViewportWidth() - (el.offsetWidth || el.clientWidth)) / 2;
        var top_ = (st_utilities.getViewportHeight() - (el.offsetHeight || el.clientHeight)) / 2;
        el.style.left = left + 'px';
        el.style.top = top_ + 'px';
        var mask = st_utilities.maskBackground(alpha);
        mask.style.width = st_utilities.getPageWidth();
        mask.style.height = st_utilities.getPageHeight();
    }
}

st_utilities.showClonedPopup = function(el, alpha)
{
    if (typeof el == 'string')
        el = document.getElementById(el);
    if (el)
    {
        var popup = el.cloneNode(true);
        popup.id = 'st_utilities.popup.' + el.id;
        return st_utilities.showPopup(popup, alpha);
    }
}

/**
 * close a popup and remove any background masks
 * @param id the id corresponding to or a reference to a popup created with st_utilities.showPopup
 */
st_utilities.closeClonedPopup = function(el)
{
    if (typeof el == 'string')
        el = document.getElementById('st_utilities.popup.' + el);
    if (el)
    {
        st_utilities.closePopup(el);
        st_utilities.destroyElement(el);
    }
}

st_utilities.closePopup = function(el)
{
    if (typeof el == 'string')
        el = document.getElementById(el);
    if (el)
        el.style.display = 'none';
    st_utilities.destroyBackgroundMask();
}


/**
 * returns an associative array of all query string parameters.
 * keys or parameters containing '+' are normalized to ' '
 */
st_utilities.getQueryMap = function ()
{
    var arr = new Array();
    var qs = location.search.substring(1, location.search.length);
    if (qs.length == 0)
        return arr;
    qs = qs.replace(/\+/g, ' ');
    var args = qs.split('&');
    for (var i=0; i < args.length; i++)
    {
        var pair = args[i].split('=');
        var key = unescape(pair[0]);
        arr[unescape(pair[0])] = (pair.length == 2) ? unescape(pair[1]) : null;
    }
    return arr;
}

st_utilities.getEnvFromURL = function()
{
    switch(window.location.hostname)
    {
        case "www.squaretrade.com":
            return st_utilities.PRODUCTION;
        case "www-stage.squaretrade.com":
            return st_utilities.STAGE;
        case "www-dev.squaretrade.com":
            return st_utilities.DEV;
        default:
            return st_utilities.LOCALHOST;
    }
}

/**
 * Javascript code to display a swf on a SquareTrade page
 * Takes in a closure containing the following parameters:
 * @param swfFile the swf file to display, REQUIRED. This must be an absolute
 *          path from the servers root, E.g /flash/quote/quotetootv3/.swf
 * @param elementID the ID of the page element to display the flash object in, REQUIRED.
 * @param width the width of the swf, REQUIRED.
 * @param height the height of the swf, REQUIRED.
 * @param minFlashVersion the minimum flash version to support, OPTIONAL. Defaults to 8
 * @param background the background color of the flash display area, OPTIONAL.
 *          Defaults to #FFFFFF
 * @param wmode the flash wmode param, OPTIONAL. Defaults to 'transparent'
 * @param alternateServer an alternate server to host the flash from, OPTIONAL.
 *          NOTE: DO NOT USE THIS PARAM UNLESS YOU ABSOLUTELY KNOW WHAT YOU ARE DOING
 * @param swfID a specific ID to assign to the swf object, OPTIONAL. Defaults to the {elementID}_swf
 * @param allowCaching set to true to allow browser caching of the swf file, OPTIONAL.
 *          Defaults to false in non-production environments, false in production
 */
st_utilities.displaySwf = function(args)
{
    // get environment
    var env = st_utilities.getEnvFromURL();
    if ( args.env != undefined)
        env = args.env;

    // get path
    var swfFilePath;
    // if page url starts with www.squaretrade.com use CDN //resource.squaretrade.com
    if ( args.alternateServer != undefined)
    {
        swfFilePath = args.alternateServer;
        if (args.alternateServer.lastIndexOf("/") != args.alternateServer.length - 1
                && args.swfFile.indexOf("/") != 0)
            swfFilePath += "/";
        swfFilePath += args.swfFile;
    }
    else if ( env == st_utilities.PRODUCTION)
    {
        swfFilePath = "//resource.squaretrade.com";
        if ( !args.swfFile.indexOf("/") != 0)
            swfFilePath += "/";
        swfFilePath += args.swfFile;
    }
    else
    {
        swfFilePath = args.swfFile;
    }

    // add random param on to swfFilePath to eliminate browser caching
    var allowCaching = (env == st_utilities.PRODUCTION);
    if ( args.allowCaching != undefined && typeof(args.allowCaching) == "boolean")
        allowCaching = args.allowCaching;

    if (!allowCaching)
    {
        if ( swfFilePath.indexOf("?") == -1)
            swfFilePath += "?random=";
        else swfFilePath += "&random=";
        swfFilePath += "" + new Date().getTime();
    }


    // set min flash version to 8 if not defined
    var minFlashVersion = "8";
    if ( args.minFlashVersion != undefined)
        minFlashVersion = args.minFlashVersion;

    // get background
    var background = "#FFFFFF";
    if ( args.background != undefined)
        background = args.background;

    var swfID;
    if ( args.swfID == undefined)
        swfID = args.elementID + "_swf";
    else swfID = args.swfID;

    var swf = new SWFObject(
        swfFilePath,
        swfID,
        args.width,
        args.height,
        minFlashVersion,
        background);

    swf.addParam('allowScriptAccess', 'always');

    var wmode = "transparent";
    if ( args.wmode != undefined)
        wmode = args.wmode;
    swf.addParam('wmode', wmode);

    if ( env == st_utilities.LOCALHOST)
    {
        if ( args.alternateServer != undefined)
            swf.addVariable('env', args.alternateServer);
        else swf.addVariable('env', window.location.protocol + "//" + window.location.hostname + "/");
    }
    else if (env != st_utilities.PRODUCTION)
    {
        swf.addVariable('env', env);
    }

    for (attr in args)
    {
        if (attr == "elementID" || attr == "swfFile" || attr == "swfID"
                || attr == "width" || attr == "height" || attr
                == "minFlashVersion" || attr == "background" || attr == "env"
                || attr == "alternateServer" || attr == "wmode"
                || attr == "allowCaching")
            continue;
        var value = args[attr];
        if (typeof(value) == 'string')
        {
            if (attr != 'quotes')
                value = escape(value);
        }
        else if (typeof(value) != 'number')
            continue;

        swf.addVariable(attr, value);
    }
    swf.write(args.elementID);

    var swfElement = document.getElementById(swfID);
    // form workaround
    window[swfID] = swfElement;

    return swfElement;
}

/**
 * Takes in an object/closure and returns a querystring made up of name/value
 * pairs based on the properties of the object
 * @param args the object to derive a query string from
 * @return a query string
 */
st_utilities.toQueryString = function(args)
{
    var qs = "";
    for ( var name in args)
    {
        qs += name + "=" + escape(args[name]) + "&";
    }
    return (qs.length > 0) ? qs.substring(0, qs.length-1) : qs;
}

/**
 * returns true if s is null or is an empty string
 */
st_utilities.isNullOrEmpty = function(s)
{
    if (s == null || s == '')
        return true;
    return false;
}

/**
 * Copies properties from object from to object to. If overwrite is set to
 * true it will overwrite pre-existing values in to.
 * @param from the object to copy from
 * @param to the object to copy to
 * @param overwrite whether or not to overwrite pre-existing proeprties in to.
 *          Set to true to overwrite. Defaults to false
 */
st_utilities.copyProperties = function(from, to, overwrite){

    for (var p in from){
        if (to[p] == undefined || overwrite)
            to[p] = from[p];
    }
}

/**
 * Copies only defined properties from object from to object to. If overwrite is set to
 * true it will overwrite pre-existing values in to.
 * @param from the object to copy from
 * @param to the object to copy to
 * @param overwrite whether or not to overwrite pre-existing proeprties in to.
 *          Set to true to overwrite. Defaults to false
 */
st_utilities.copyDefinedProperties = function(from, to, overwrite){

    for (var p in from){
        if (from[p] != undefined && (to[p] == undefined || overwrite) )
            to[p] = from[p];
    }
}

/** get a cookie value given its name
 * @param coockie_name the name of coockie
 * @return value of the cookie
 */
st_utilities.getCookie = function(cookie_name)
{
    var results = document.cookie.match ( '(^|;) ?' + cookie_name + '=([^;]*)(;|$)' );

    if ( results )
      return ( unescape ( results[2] ) );
    else
      return null;
}

//////////////////// WINDOW FUNCTIONS /////////////////////////////////////////////
/*
a good size for a lrg window is 690x480
scr, menu, stat, tool are set as either 0 (no) or 1 (yes)
name can be set to 0 as well unless you specifically need to have it named
*/

/**
 * Opens a popup window. Parameters are passes as a closure
 * @param url the url to display in the popup, REQUIRED
 * @param name the name for the popup window. Defaults to "_blank"
 * @param width the width of the window. Should not be used if widthPct is used
 * @param height the height of the window. Should not be used if heightPct is used
 * @param widthPct the percentage of the screen width to make the window width. Should not be used if width is used
 * @param heightPct the percentage of the sceen height to the the window height. Should not be uses if height is used
 * @param top the top coordinate of the window in pixels. Defaults to 0
 * @param left the left coordinate of the window in pixels. Defaults to 0
 * @param scrollbars whether or not to display scrollbars. Defautls to yes
 * @param resizable whether or not the window is to be resizable. Defaults to yes
 * @param menubar whether or not to display the menubar. Defaults to no
 * @param status whether or not to display a status bar. Defaults to no
 * @param toolbar whether or not to display a toolbar. Defaults to no
 * @return returns a reference to the window
 */
st_utilities.openWin = function (args)
{
    if ( !args.name )
        args.name = "_blank";

    if ( !args.resizable)
        args.resizable = "yes";
    var params = "resizable=" + args.resizable;

    if ( args.width )
        params += ",width=" + args.width;
    else if ( args.widthPct )
        params += ",width=" + (screen.availWidth * args.widthPct);

    if ( args.height )
        params += ",height=" + args.height;
    else if (args.heightPct )
        params += ",height=" + (screen.availHeight * args.heightPct);

    params += ",scrollbars=";
    if ( args.scrollbars )
        params += args.scrollbars;
    else params += "yes";

    params += ",menubar=";
    if ( args.menubar )
        params += args.menubar;
    else params += "no";

    params += ",status=";
    if ( args.status )
        params += args.status;
    else params += "no";

    params += ",toolbar=";
    if ( args.toolbar )
        params += args.toolbar;
    else params += "no";

    params += ",top=";
    if ( args.top )
        params += args.top;
    else params += "0";

    params += ",left=";
    if ( args.left )
        params += args.left;
    else params += "0";

    var win = window.open(args.url, args.name, params);
    if ( win )
        win.focus();

    return win;

}
/////////////////// END WINDOW FUNCTIONS /////////////////////////////////////////////////


////////////////// XMLHTTP/AJAX FUNCTIONS //////////////////////////////////////////////
/** XHConn - Simple XMLHTTP Interface - bfults@gmail.com - 2005-04-08        **
 ** Code licensed under Creative Commons Attribution-ShareAlike License      **
 ** http://creativecommons.org/licenses/by-sa/2.0/                           **/
/**
  * XMLHttp request wrapper method. Based on XHConn.
  * Takes in a CLOSURE containing the following parameters:
  * @param url the url to access. REQUIRED
  * @param method the HTTP method to use. GET and POST are supported. Defaults to GET
  * @param onLoad a callback function for when the url is successfully loaded
  * @param postQueryString the query string to use when making a POST request.
  *         This should be left out when making a GET request
  * @param onError a callback function for when the url is not successfully loaded
  * @return true if there are no unexpected errors, false otherwise
  *
  * Example:
  * var fnOnLoad = function(xmlhttpobj) {alert(xmlhttpobj.responseText);};
  * st_utilities.xmlHttp({url : 'http://www.google.com' , onLoad : fnOnLoad});
  */
st_utilities.xmlHttp = function(args)
{
    var xmlhttp, bComplete = false;
    if (!args)
        return false;

    if ( !args.url)
        return false;
    try
    {
        xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e)
    {
        try
        {
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        catch (e)
        {
            try
            {
                xmlhttp = new XMLHttpRequest();
            }
            catch (e)
            {
                xmlhttp = false;
            }
        }
    }

    if (!xmlhttp) return false;

    bComplete = false;
    if ( !args.method)
        args.method = "GET";
    else args.method = args.method.toUpperCase();

    try
    {
        if (args.method == "GET")
        {
            xmlhttp.open(args.method, args.url, true);
            args.postQueryString = "";
        }
        else
        {
            xmlhttp.open(args.method, args.url, true);
            xmlhttp.setRequestHeader("Method", "POST " + args.url
                    + " HTTP/1.1");
            xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        }

        xmlhttp.onreadystatechange = function()
        {
            if (xmlhttp.readyState == 4 && !bComplete)
            {
                bComplete = true;
                if ( xmlhttp.status == 200)
                {
                    if (args.onLoad) args.onLoad(xmlhttp);
                }
                else
                {
                    if (args.onError) args.onError(xmlhttp);
                }
            }
        };
        xmlhttp.send(args.postQueryString);
    }
    catch(z)
    {
        return false;
    }
    return true;
}

/**
 * Replaces innerHTML of element with contents of url
 * @param url the url to load into the element
 * @param element either the id of the element or a reference to the element
 *      in which to write the loaded html
 */
st_utilities.ajaxElement = function(url, element)
{
    if (typeof element == 'string')
        element = document.getElementById(element);

    var onLoad = function(ret) { if (element) {element.innerHTML = ret.responseText;} };
    st_utilities.xmlHttp({url : url, onLoad : onLoad});
}

////////////////// END XMLHTTP/AJAX FUNCTIONS //////////////////////////////////////////////

///////////////////////////LEGACY FUNCTIONS ///////////////////////////////////

function openWin(file,w,h,scr,menu,stat,tool,name)
{
	var win = window.open(file,name,"scrollbars="+scr+",resizable=yes,menubar="+menu+",status="+stat+",toolbar="+tool+",width="+w+",height="+h+",screenx=0,screeny=0,top=0,left=0");
    if ( win )
        win.focus();
}

/*
This code resizes the popup window to height and width defined by
the available screen resolution. This can be a percentage of the screen
by using the aw, ah variables.
*/
function openWinRes(file,wpct,hpct,scr,menu,stat,tool,name)
{

    var screenRes = getScreenRes(80);
    var width;
    var height;

    if ( screenRes == "1280x1024")
    {
      width = 1200;
      height = 500;
    }
    else if ( screenRes == "1152x864")
    {
      width = 1072;
      height = 500;
    }
    else if ( screenRes == "1024x768")
    {
      width = 944;
      height = 500;
    }
    else
    {
      width = 740;
      height = 500;
    }

    var aw = screen.availWidth * wpct;
    var ah = screen.availHeight * hpct;
    var winRes = window.open(file,name,"scrollbars="+scr+",resizable=yes,menubar="+menu+",status="+stat+",toolbar="+tool+",width="+width+",height="+height+",screenx=0,screeny=0,top=0,left=0");
    winRes.focus();
}


function getScreenRes(errorMargin)
{
    var screenX = screen.availWidth;

    if ( screenX >= (1280-errorMargin))
        return "1280x1024";

    if (screenX >= (1152-errorMargin))
        return "1152x864";

    if ( screenX >= (1024-errorMargin))
        return "1024x768";

    return "800x600";

}

//////////////////////// END LEGACY FUNCTIONS ///////////////////////////////////

///////////////////////// INCLUDED SWF OBJECT ///////////////////////////////////
/**
 * SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
 *
 * SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */
if(typeof deconcept=="undefined"){var deconcept=new Object();}if(typeof deconcept.util=="undefined"){deconcept.util=new Object();}if(typeof deconcept.SWFObjectUtil=="undefined"){deconcept.SWFObjectUtil=new Object();}deconcept.SWFObject=function(_1,id,w,h,_5,c,_7,_8,_9,_a){if(!document.getElementById){return;}this.DETECT_KEY=_a?_a:"detectflash";this.skipDetect=deconcept.util.getRequestParameter(this.DETECT_KEY);this.params=new Object();this.variables=new Object();this.attributes=new Array();if(_1){this.setAttribute("swf",_1);}if(id){this.setAttribute("id",id);}if(w){this.setAttribute("width",w);}if(h){this.setAttribute("height",h);}if(_5){this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));}this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion();if(!window.opera&&document.all&&this.installedVer.major>7){deconcept.SWFObject.doPrepUnload=true;}if(c){this.addParam("bgcolor",c);}var q=_7?_7:"high";this.addParam("quality",q);this.setAttribute("useExpressInstall",false);this.setAttribute("doExpressInstall",false);var _c=(_8)?_8:window.location;this.setAttribute("xiRedirectUrl",_c);this.setAttribute("redirectUrl","");if(_9){this.setAttribute("redirectUrl",_9);}};deconcept.SWFObject.prototype={useExpressInstall:function(_d){this.xiSWFPath=!_d?"expressinstall.swf":_d;this.setAttribute("useExpressInstall",true);},setAttribute:function(_e,_f){this.attributes[_e]=_f;},getAttribute:function(_10){return this.attributes[_10];},addParam:function(_11,_12){this.params[_11]=_12;},getParams:function(){return this.params;},addVariable:function(_13,_14){this.variables[_13]=_14;},getVariable:function(_15){return this.variables[_15];},getVariables:function(){return this.variables;},getVariablePairs:function(){var _16=new Array();var key;var _18=this.getVariables();for(key in _18){_16[_16.length]=key+"="+_18[key];}return _16;},getSWFHTML:function(){var _19="";if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","PlugIn");this.setAttribute("swf",this.xiSWFPath);}_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\"";_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";var _1a=this.getParams();for(var key in _1a){_19+=[key]+"=\""+_1a[key]+"\" ";}var _1c=this.getVariablePairs().join("&");if(_1c.length>0){_19+="flashvars=\""+_1c+"\"";}_19+="/>";}else{if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","ActiveX");this.setAttribute("swf",this.xiSWFPath);}_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\">";_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";var _1d=this.getParams();for(var key in _1d){_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";}var _1f=this.getVariablePairs().join("&");if(_1f.length>0){_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";}_19+="</object>";}return _19;},write:function(_20){if(this.getAttribute("useExpressInstall")){var _21=new deconcept.PlayerVersion([6,0,65]);if(this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version"))){this.setAttribute("doExpressInstall",true);this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));document.title=document.title.slice(0,47)+" - Flash Player Installation";this.addVariable("MMdoctitle",document.title);}}if(this.skipDetect||this.getAttribute("doExpressInstall")||this.installedVer.versionIsValid(this.getAttribute("version"))){var n=(typeof _20=="string")?document.getElementById(_20):_20;n.innerHTML=this.getSWFHTML();return true;}else{if(this.getAttribute("redirectUrl")!=""){document.location.replace(this.getAttribute("redirectUrl"));}}return false;}};deconcept.SWFObjectUtil.getPlayerVersion=function(){var _23=new deconcept.PlayerVersion([0,0,0]);if(navigator.plugins&&navigator.mimeTypes.length){var x=navigator.plugins["Shockwave Flash"];if(x&&x.description){_23=new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));}}else{if(navigator.userAgent&&navigator.userAgent.indexOf("Windows CE")>=0){var axo=1;var _26=3;while(axo){try{_26++;axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_26);_23=new deconcept.PlayerVersion([_26,0,0]);}catch(e){axo=null;}}}else{try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");_23=new deconcept.PlayerVersion([6,0,21]);axo.AllowScriptAccess="always";}catch(e){if(_23.major==6){return _23;}}try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(e){}}if(axo!=null){_23=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));}}}return _23;};deconcept.PlayerVersion=function(_29){this.major=_29[0]!=null?parseInt(_29[0]):0;this.minor=_29[1]!=null?parseInt(_29[1]):0;this.rev=_29[2]!=null?parseInt(_29[2]):0;};deconcept.PlayerVersion.prototype.versionIsValid=function(fv){if(this.major<fv.major){return false;}if(this.major>fv.major){return true;}if(this.minor<fv.minor){return false;}if(this.minor>fv.minor){return true;}if(this.rev<fv.rev){return false;}return true;};deconcept.util={getRequestParameter:function(_2b){var q=document.location.search||document.location.hash;if(_2b==null){return q;}if(q){var _2d=q.substring(1).split("&");for(var i=0;i<_2d.length;i++){if(_2d[i].substring(0,_2d[i].indexOf("="))==_2b){return _2d[i].substring((_2d[i].indexOf("=")+1));}}}return "";}};deconcept.SWFObjectUtil.cleanupSWFs=function(){var _2f=document.getElementsByTagName("OBJECT");for(var i=_2f.length-1;i>=0;i--){_2f[i].style.display="none";for(var x in _2f[i]){if(typeof _2f[i][x]=="function"){_2f[i][x]=function(){};}}}};if(deconcept.SWFObject.doPrepUnload){if(!deconcept.unloadSet){deconcept.SWFObjectUtil.prepUnload=function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};window.attachEvent("onunload",deconcept.SWFObjectUtil.cleanupSWFs);};window.attachEvent("onbeforeunload",deconcept.SWFObjectUtil.prepUnload);deconcept.unloadSet=true;}}if(!document.getElementById&&document.all){document.getElementById=function(id){return document.all[id];};}var getQueryParamValue=deconcept.util.getRequestParameter;var FlashObject=deconcept.SWFObject;var SWFObject=deconcept.SWFObject;
////////////////////////// END INCLUDED SWF OBJECT //////////////////////////////



///////////////////////// AST Event Tracking Object ///////////////////////////////////

/**
  * This creates an AST event tracker object: astEventTracker
  * To use astEventTracker objet, call astEventTracker.trackEvent(args);
  * args.eventType can be any valid ASt event type, it assumes 'PAGE_VIEW' if left unspecified
  * Single page view will not be tracked multiple times even if called more than once
  * Examples of calling this tracking object:
  *    astEventTracker.trackEvent({eventType:'PAGE_VIEW', itemId:'MyItem123', campaignCode:'bs_war_wbe_1_cpi1'});
  *    astEventTracker.trackEvent({itemId:'MyItem123', campaignCode:'bs_war_wbe_1_cpi1'});
  *    astEventTracker.trackEvent({eventType:'ACTION_SUBMIT', itemId:'MyItem123', campaignCode:'bs_war_quote'});
  */
var astEventTracker = new function() {
    var trackedPageView = false;

    this.trackEvent = function(args) {
        var query = "pageUrl=" + window.location;
        var eventType = null;
        for (arg in args) {
            if (arg == 'eventType') {
                eventType = args[arg];
            }
            query += "&" + arg +"=" + args[arg];
        }
        // add default eventType as 'PAGE_VIEW' if it is not passed in
        if (eventType == null) {
            eventType = 'PAGE_VIEW';
            query += "&eventType=" + eventType;
        }

        if (eventType == 'PAGE_VIEW') {
            if (trackedPageView) {
                return; // exit
            } else {
                trackedPageView = true; // remember now we've traced PAGE_VIEW
            }
        }
        st_utilities.xmlHttp({url: '/squaretrade/ast/EventTracker_submit.action?'+query, method: 'GET' });
    }
    return this;
}

///////////////////////// End AST Event Tracking Object ///////////////////////////////////
