/**
 * $Id: dropshadowinterface.js 66632 2009-04-09 21:44:43Z kchiu $
 * $Author: kchiu $
 * $Revision: 66632 $
 * $Name$
 * $Date: 2009-04-09 14:44:43 -0700 (Thu, 09 Apr 2009) $
 *
 * @jsRequire DomUtils
 * @jsRequire interfaces.Interface
 * @jsRequire classes.Browser
 * @jsRequire classes.EventManager
 * @jsRequire classes.ResourceManager
 *
 *
 * @version    $Revision: 66632 $
 * @author     Philip Snyder <philip@pricegrabber.com>
 * @copyright  Copyright &copy; 2006, Philip Snyder, PriceGrabber.com
 * @see        interfaces.Interface
 */

/**
 * DropShadowInterface Constructor / Definition
 *
 * This interface is built on top of the Interface object
 * and is NOT intended to be instantiated directly. See
 * documentation on interfaces.Interface for a complete
 * explanation.
 *
 * @access public
 * @since  v1.1
 * @return DropShadowInterface
 */
function DropShadowInterface(color, xOffset, yOffset, blur, opacity, xShrink, yShrink) {
    this.dropShadowId = null;
    this.elemId       = null;
    this.color        = null;
    this.xOffset      = null;
    this.yOffset      = null;
    this.xShrink      = null;
    this.yShrink      = null;
    this.blur         = null;
    this.opacity      = null;
    this.shadowStyle  = null;
    this.images       = new Array;
    this.draw         = DropShadowInterface_Draw;
    this.erase        = DropShadowInterface_Erase;
    this.init         = DropShadowInterface_Init;
    this.setBlur      = DropShadowInterface_SetBlur;
    this.alignElement = DropShadowInterface_AlignElement;
    return this;
} // End DropShadowInterface

// Setup DropShadowInterface prototype chain
DropShadowInterface.prototype             = new Interface;
DropShadowInterface.prototype.constructor = DropShadowInterface;
DropShadowInterface.superclass            = Interface.prototype;




/****** BEGIN EDIT SECTION ******/

/**
 * Drop shadow style definitions.
 *
 * This data structure allows for the definition of various different
 * drop shadow "styles" that can be applied by setting the shadowStyle
 * of the object implementing DropShadowInterface.
 *
 * Example:
 *
 *    <script language="JavaScript">
 *    var popup = new DropShadowPopup();
 *    popup.shadowStyle = 'Default';
 *    </script>
 *
 * You can also define a shadow style at any time after inclusion of
 * this file and then reference that style instead if you like.
 *
 * @access public
 * @since  v1.1
 * @var    DropShadowInterface.styles   struct
 */
DropShadowInterface.styles = {
    DefaultMenu: { color: 'rgb(0,0,0)', xOffset: 10, yOffset: 15, blur: { iRadius: 12, iSigma: 20}, opacity: .2, xShrink: 16, yShrink: 20 },
    Default:     { color: 'rgb(0,0,0)', xOffset: 17, yOffset: 17, blur: { iRadius: 20, iSigma: 20}, opacity: .2, xShrink: 29, yShrink: 24 },
    IEDefault:   { color: 'rgb(0,0,0)', xOffset:  7, yOffset: 10, blur: { iRadius: 10, iSigma: 20}, opacity: .2, xShrink:  9, yShrink: 10 },
    CheckAll:    { color: 'rgb(0,0,0)', xOffset:  7, yOffset:  7, blur: { iRadius: 10, iSigma: 10}, opacity: .2, xShrink:  9, yShrink:  4 },
    oldIe:       { color: 'rgb(0,0,0)', xOffset:  7, yOffset: 10, blur: { iRadius: 10, iSigma: 20}, opacity: .2, xShrink:  9, yShrink: 10 }
};

/**
 * engineUrl holds the path to the php gradient script.
 *
 * This value can be changed at any time after this file
 * is included as follows:
 *
 * <script>
 *  DropShadowInterface.engineUrl = '/any/url/you/want.php';
 * </script>
 *
 * @access public
 * @since  v1.1
 * @var    string
 */
DropShadowInterface.engineUrl = '/gfx/gradient.php';

/****** END EDIT SECTION ******/




/**
 * Internal image ids used for keeping track of image resources.
 *
 * !DO NOT MODIFY THIS!
 *
 * @access private
 * @since  v1.1
 * @var    DropShadowInterface.imgIds   struct
 */
//DropShadowInterface.imgIds = { top: 0, left: 1, bottom: 2, right: 3, topLeft: 4, bottomLeft: 5, bottomRight: 6, topRight: 7, callout: 8 };
DropShadowInterface.imgIds = { top: 0, left: 1, bottom: 2, right: 3, topLeft: 4, bottomLeft: 5, bottomRight: 6, topRight: 7 };






/**
 * Initializes an object that implements the DropShadowInterface.
 * Call this function prior to any draw() functions.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
function DropShadowInterface_Init(color, xOffset, yOffset, blur, opacity, xShrink, yShrink) {
    //window.messageQueue.add( new Message('DropShadowInterface_Init', 'called') );

    if (!this.shadowStyle && DomUtils.browser.isIE()) this.shadowStyle = 'IEDefault';
    else if (!this.shadowStyle)              this.shadowStyle = 'Default';
    var shadowStyle  = DropShadowInterface.styles[this.shadowStyle];
    this.color       = (color)          ? color   : shadowStyle.color;
    this.xOffset     = !isNaN(xOffset)  ? xOffset : shadowStyle.xOffset;
    this.yOffset     = !isNaN(yOffset)  ? yOffset : shadowStyle.yOffset;
    this.blur        = isString(blur)   ? blur    : shadowStyle.blur;
    this.opacity     = isFloat(opacity) ? opacity : shadowStyle.opacity;
    this.xShrink     = !isNaN(xShrink)  ? xShrink : shadowStyle.xShrink;
    this.yShrink     = !isNaN(yShrink)  ? yShrink : shadowStyle.yShrink;

    /**
     * Handle color parameter
     */
    this.hexColor = '';
    this.rgbColor = '';
    var  rgbRegex = /^rgb\(\s?([0-9]{1,3})\s?\,\s?([0-9]{1,3})\s?\,\s?([0-9]{1,3})\s?\)/;
    var  hexRegex = /^\#?[0-9A-Fa-f]{3}$|\#[0-9A-Fa-f]{6}$/;
    if (hexRegex.test(this.color)) {
        var triplets = new Array;
        if (this.color.length > 4) {
            this.hexColor = this.color;
            for (var start=1; start+2<=this.color.length; start += 2) triplets[triplets.length] = this.color.substr(start, 2);
            for (var i=0;     i<triplets.length;          i++)        triplets[i] = parseInt(triplets[i], 16);
            this.rgbColor = triplets.join(',');
        } else if (this.color.length == 4) {
            for (var start=1; start+1<=this.color.length; start++) triplets[triplets.length] = this.color.substr(start, 1)+this.color.substr(start, 1);
            this.hexColor = '#'+triplets.join('');
            for (var i=0;     i<triplets.length;          i++)     triplets[i] = parseInt(triplets[i], 16);
            this.rgbColor = triplets.join(',');
        } else throw new Error('No valid color setting defined! color: '+this.color);
    } else {
        var matches = this.color.match(rgbRegex);
        if (matches && matches.length > 1) {
            matches.shift();
            for (var i=0; i<matches.length; i++) {
                if (parseInt(matches[i]) > 255) throw new Error('Invalid RGB color specified: '+this.color);
            }
            this.rgbColor = matches.join(',');
        } else throw new Error('No valid color setting defined! color: '+this.color);
    }
    /**
     * Handle blur parameter
     */
    if (isString(this.blur)) {
        var radius = parseInt(this.blur);
        var sigma  = 0;
        if (this.blur.indexOf('x') > 0) sigma = parseInt(this.blur.split('x')[1]);
        this.setBlur(radius, sigma);
    }
    
    this.images = new Array;
    this.images[DropShadowInterface.imgIds.top]         = DropShadowInterface.engineUrl+'?grad=linear&dir=btt&height='+this.blur.iRadius+
         '&width='+this.blur.iRadius+'&color='+this.rgbColor+'&gaussian='+this.blur.iRadius+'x'+this.blur.iSigma+'&opacity='+this.opacity;
    this.images[DropShadowInterface.imgIds.bottom]      = DropShadowInterface.engineUrl+'?grad=linear&dir=ttb&height='+this.blur.iRadius+
         '&width='+this.blur.iRadius+'&color='+this.rgbColor+'&gaussian='+this.blur.iRadius+'x'+this.blur.iSigma+'&opacity='+this.opacity;
    this.images[DropShadowInterface.imgIds.left]        = DropShadowInterface.engineUrl+'?grad=linear&dir=rtl&height='+this.blur.iRadius+
         '&width='+this.blur.iRadius+'&color='+this.rgbColor+'&gaussian='+this.blur.iRadius+'x'+this.blur.iSigma+'&opacity='+this.opacity;
    this.images[DropShadowInterface.imgIds.right]       = DropShadowInterface.engineUrl+'?grad=linear&dir=ltr&height='+this.blur.iRadius+
         '&width='+this.blur.iRadius+'&color='+this.rgbColor+'&gaussian='+this.blur.iRadius+'x'+this.blur.iSigma+'&opacity='+this.opacity;
    this.images[DropShadowInterface.imgIds.bottomRight] = DropShadowInterface.engineUrl+'?grad=radial&radius='+(this.blur.iRadius*2)+
         '&height='+this.blur.iRadius+'&width='+this.blur.iRadius+'&opacity='+this.opacity+
         '&x=0&y=0'+'&color='+this.rgbColor+'&gaussian='+this.blur.iRadius+'x'+this.blur.iSigma;
    this.images[DropShadowInterface.imgIds.topRight]    = DropShadowInterface.engineUrl+'?grad=radial&radius='+(this.blur.iRadius*2)+
         '&height='+this.blur.iRadius+'&width='+this.blur.iRadius+'&opacity='+this.opacity+
         '&x=0&y='+(this.blur.iRadius+1)+'&color='+this.rgbColor+'&gaussian='+this.blur.iRadius+'x'+this.blur.iSigma;
    this.images[DropShadowInterface.imgIds.bottomLeft]  = DropShadowInterface.engineUrl+'?grad=radial&radius='+(this.blur.iRadius*2)+
         '&height='+this.blur.iRadius+'&width='+this.blur.iRadius+'&opacity='+this.opacity+
         '&x='+(this.blur.iRadius+1)+'&y=0'+'&color='+this.rgbColor+'&gaussian='+this.blur.iRadius+'x'+this.blur.iSigma;
    this.images[DropShadowInterface.imgIds.topLeft]     = DropShadowInterface.engineUrl+'?grad=radial&radius='+(this.blur.iRadius*2)+
         '&height='+this.blur.iRadius+'&width='+this.blur.iRadius+'&opacity='+this.opacity+
         '&x='+(this.blur.iRadius+1)+'&y='+(this.blur.iRadius+1)+'&color='+this.rgbColor+'&gaussian='+this.blur.iRadius+'x'+this.blur.iSigma;
    //this.images[DropShadowInterface.imgIds.callout]     = '/images/callout_right.png';
    if (typeof(window.preloadImage) == 'function') {
        for (i=0; i<this.images.length; i++) {
            util.resourceManager.get(this.images[i]);
            //util.resourceManager.get(this.images[i], this.blur.iRadius, this.blur.iRadius);
        }
    }

    //window.messageQueue.add( new Message('DropShadowInterface_Init', 'finished') );
} // End DropShadowInterface_Init




/**
 * "Draws" the actual drop shadow by creating the necessary dom elements and applying them to
 * the object's element.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
function DropShadowInterface_Draw() {
    //window.messageQueue.add( new Message('DropShadowInterface_Draw', 'called') );
    var opacity = this.opacity;
    // remove the old drop shadow if it exists
    var dropShadow = document.getElementById(this.dropShadowId);
    if (dropShadow) {
        DomUtils.removeElement(dropShadow);
        dropShadow = null;
    }
    var elem = document.getElementById(this.elemId);
    if (elem) {
        // Clone the elem node now before any other draw changes it.
        var zIndex                       = parseInt(DomUtils.getZIndex(elem))-2;
        this.dropShadowId                = this.id+'_DropShadow';
        var dropShadow                   = elem.cloneNode(false);
        dropShadow.id                    = this.dropShadowId;
        dropShadow.style.visibility      = 'hidden';
        dropShadow.style.zIndex          = zIndex;
        dropShadow.className             = '';
        dropShadow.style.position        = 'absolute';
        dropShadow.style.backgroundColor = 'transparent';
        dropShadow.style.border          = 'none';
        dropShadow.style.left            = parseInt(DomUtils.getElementLeft(elem))+'px';
        dropShadow.style.top             = parseInt(DomUtils.getElementTop(elem))+'px';
        dropShadow.xOffset               = parseInt(this.xOffset);
        dropShadow.yOffset               = parseInt(this.yOffset);
        dropShadow.overflow              = 'visible !important';
        // DO NOT move this to the end since it messes up dimension calculations in IE
        //elem.parentNode.appendChild(dropShadow);
        document.getElementsByTagName('body')[0].appendChild(dropShadow);
/**
 * This is the BETTER / easier way to make the drop shadow follow
 * the element. However, this doesn't work on IE. Retain code for
 * possible future uses.
 */
//    if (!DomUtils.browser.isIE()) {
//        window.addEvent(this.elem, 'DOMAttrModified', function(e) {
//            if (e.type == 'DOMAttrModified' && e.attrName == 'style') {
//                dropShadow.setAttribute('style', e.newValue);
//                dropShadow.style.zIndex   = parseInt(this.style.zIndex)-2;
//                dropShadow.style.overflow = 'visible !important';
//                dropShadow.style.border   = 'none';
//                dropShadow.style.left     = DomUtils.getElementLeft(this)+'px';
//                dropShadow.style.top      = DomUtils.getElementTop(this)+'px';
//            }
//        }, this.elem, true);
//    }
//    this.elem.parentNode.insertBefore(this.dropShadow, this.elem.nextSibling);
        if (this.xShrink) {
            //window.messageQueue.add( new Message('DropShadowInterface_Draw', 'getting drop shadow width') );
            dropShadow.style.width = parseInt(parseInt(DomUtils.getElementWidth(elem))+(parseInt(this.xShrink)/2))+'px';
        }
        if (this.yShrink) {
            //window.messageQueue.add( new Message('DropShadowInterface_Draw', 'getting drop shadow height') );
            dropShadow.style.height = parseInt(parseInt(DomUtils.getElementHeight(elem))+(parseInt(this.yShrink)/2))+'px';
        }
    
        if (DomUtils.browser.isIE()) {
            var eStyle = DomUtils.getCurrentStyle(elem);
            pLeft   = parseInt(eStyle.paddingLeft);
            pRight  = parseInt(eStyle.paddingRight);
            pTop    = parseInt(eStyle.paddingTop);
            pBottom = parseInt(eStyle.paddingBottom);
            pWidth  = parseInt((!isNaN(pLeft) ? pLeft : 0)+(!isNaN(pRight)  ? pRight  : 0));
            pHeight = parseInt((!isNaN(pTop)  ? pTop  : 0)+(!isNaN(pBottom) ? pBottom : 0));
        } else {
            pHeight = 0;
            pWidth  = 0;
        }
        
        var img;
        var shadow                         = document.createElement('div');
        shadow.id                          = this.id+'_DropShadow_Main';
        shadow.style.position              = 'absolute';
        //window.messageQueue.add( new Message('DropShadowInterface_Draw', 'getting shadow width') );
        shadow.style.width                 = parseInt(parseInt(DomUtils.getElementWidth(elem))-parseInt(this.xShrink))+'px';
        shadow.style.height                = parseInt(parseInt(DomUtils.getElementHeight(elem))-parseInt(this.yShrink))+'px';
        shadow.style.left                  = parseInt(this.xOffset)+'px';
        shadow.style.top                   = parseInt(this.yOffset)+'px';
        shadow.style.border                = 'none';
        shadow.style.backgroundColor       = 'rgb('+this.rgbColor+')';
        shadow.style.zIndex                = zIndex;
        if (DomUtils.browser.isIE()) shadow.style.filter    += 'progid:DXImageTransform.Microsoft.Alpha(opacity='+(this.opacity*100)+')';
        else                         shadow.style.MozOpacity = this.opacity;
        dropShadow.appendChild(shadow);
    
        var bottomEdge                     = document.createElement('div');
        bottomEdge.id                      = this.id+'_DropShadow_Bottom';
        bottomEdge.className               = 'shadow';
        bottomEdge.style.position          = 'absolute';
        bottomEdge.style.top               = parseInt(parseInt(DomUtils.getElementHeight(shadow))+parseInt(this.yOffset))+'px';
        bottomEdge.style.left              = parseInt(this.xOffset)+'px';
        bottomEdge.style.height            = parseInt(this.blur.iRadius)+'px';
        //window.messageQueue.add( new Message('DropShadowInterface_Draw', 'getting bottom width') );
        bottomEdge.style.width             = parseInt(DomUtils.getElementWidth(shadow))+'px';
        //window.messageQueue.add( new Message('DropShadowInterface_Draw', 'bottom width: '+bottomEdge.style.width) );
        bottomEdge.style.zIndex            = zIndex;
        img                                = document.createElement('img');
        img.src                            = util.resourceManager.get(this.images[DropShadowInterface.imgIds.bottom]);
        img.height                         = parseInt(this.blur.iRadius);
        //window.messageQueue.add( new Message('DropShadowInterface_Draw', 'getting image width') );
        img.width                          = parseInt(DomUtils.getElementWidth(shadow));
        img.style.position                 = 'absolute';
        img.style.left                     = '0px';
        img.style.top                      = '0px';

        DropShadowInterface_FixPNG(img);

        bottomEdge.appendChild(img);
        dropShadow.appendChild(bottomEdge);
    
        var rightEdge                      = document.createElement('div');
        rightEdge.id                       = this.id+'_DropShadow_Right';
        rightEdge.className                = 'shadow';
        rightEdge.style.position           = 'absolute';
        //window.messageQueue.add( new Message('DropShadowInterface_Draw', 'getting right width') );
        rightEdge.style.left               = parseInt(parseInt(DomUtils.getElementWidth(shadow))+parseInt(this.xOffset))+'px';
        rightEdge.style.top                = parseInt(this.yOffset)+'px';
        rightEdge.style.height             = parseInt(DomUtils.getElementHeight(shadow))+'px';
        rightEdge.style.width              = parseInt(this.blur.iRadius)+'px';
        rightEdge.style.zIndex             = zIndex;
        img                                = document.createElement('img');
        img.src                            = util.resourceManager.get(this.images[DropShadowInterface.imgIds.right]);
        img.height                         = parseInt(DomUtils.getElementHeight(shadow));
        img.width                          = parseInt(this.blur.iRadius);
        img.style.position                 = 'absolute';
        img.style.left                     = '0px';
        img.style.top                      = '0px';

        DropShadowInterface_FixPNG(img);

        rightEdge.appendChild(img);
        dropShadow.appendChild(rightEdge);
    
        var leftEdge                       = document.createElement('div');
        leftEdge.id                        = this.id+'_DropShadow_Left';
        leftEdge.className                 = 'shadow';
        leftEdge.style.position            = 'absolute';
        leftEdge.style.left                = parseInt(parseInt(this.xOffset)-parseInt(this.blur.iRadius))+'px';
        leftEdge.style.top                 = parseInt(this.yOffset)+'px';
        leftEdge.style.height              = parseInt(DomUtils.getElementHeight(shadow))+'px';
        leftEdge.style.width               = parseInt(this.blur.iRadius)+'px';
        leftEdge.style.zIndex              = zIndex;
        img                                = document.createElement('img');
        img.src                            = util.resourceManager.get(this.images[DropShadowInterface.imgIds.left]);
        img.height                         = parseInt(DomUtils.getElementHeight(shadow));
        img.width                          = parseInt(this.blur.iRadius);
        img.style.position                  = 'absolute';
        img.style.left                      = '0px';
        img.style.top                       = '0px';

        DropShadowInterface_FixPNG(img);

        leftEdge.appendChild(img);
        dropShadow.appendChild(leftEdge);
    
        var topEdge                         = document.createElement('div');
        topEdge.id                          = this.id+'_DropShadow_Top';
        topEdge.className                   = 'shadow';
        topEdge.style.position              = 'absolute';
        topEdge.style.left                  = parseInt(this.xOffset)+'px';
        topEdge.style.top                   = parseInt(parseInt(this.yOffset)-parseInt(this.blur.iRadius))+'px';
        topEdge.style.height                = parseInt(this.blur.iRadius)+'px';
        //window.messageQueue.add( new Message('DropShadowInterface_Draw', 'getting top width') );
        topEdge.style.width                 = parseInt(DomUtils.getElementWidth(shadow))+'px';
        topEdge.style.zIndex                = zIndex;
        img                                 = document.createElement('img');
        img.src                             = util.resourceManager.get(this.images[DropShadowInterface.imgIds.top]);
        img.height                          = parseInt(this.blur.iRadius);
        //window.messageQueue.add( new Message('DropShadowInterface_Draw', 'getting image width') );
        img.width                           = parseInt(DomUtils.getElementWidth(shadow));
        img.style.position                  = 'absolute';
        img.style.left                      = '0px';
        img.style.top                       = '0px';

        DropShadowInterface_FixPNG(img);

        topEdge.appendChild(img);
        dropShadow.appendChild(topEdge);
    
        var brCorner                        = document.createElement('div');
        brCorner.id                         = this.id+'_DropShadow_BottomRightCorner';
        brCorner.className                  = 'shadow';
        brCorner.style.position             = 'absolute';
        //window.messageQueue.add( new Message('DropShadowInterface_Draw', 'getting br width') );
        brCorner.style.top                  = parseInt(parseInt(DomUtils.getElementHeight(shadow))+parseInt(this.yOffset))+'px';
        brCorner.style.left                 = parseInt(parseInt(DomUtils.getElementWidth(shadow))+parseInt(this.xOffset))+'px';
        brCorner.style.height               = parseInt(this.blur.iRadius)+'px';
        brCorner.style.width                = parseInt(this.blur.iRadius)+'px';
        brCorner.style.zIndex               = zIndex;
        img                                 = document.createElement('img');
        img.src                             = util.resourceManager.get(this.images[DropShadowInterface.imgIds.bottomRight]);
        img.height                          = parseInt(this.blur.iRadius);
        img.width                           = parseInt(this.blur.iRadius);
        img.style.position                  = 'absolute';
        img.style.left                      = '0px';
        img.style.top                       = '0px';
        
        DropShadowInterface_FixPNG(img);

        brCorner.appendChild(img);
        dropShadow.appendChild(brCorner);
    
        var trCorner                        = document.createElement('div');
        trCorner.id                         = this.id+'_DropShadow_TopRightCorner';
        trCorner.className                  = 'shadow';
        trCorner.style.position             = 'absolute';
        //window.messageQueue.add( new Message('DropShadowInterface_Draw', 'getting tr width') );
        trCorner.style.left                 = parseInt(parseInt(DomUtils.getElementWidth(shadow))+parseInt(this.xOffset))+'px';
        trCorner.style.top                  = parseInt(parseInt(this.yOffset)-parseInt(this.blur.iRadius))+'px';
        trCorner.style.height               = parseInt(this.blur.iRadius)+'px';
        trCorner.style.width                = parseInt(this.blur.iRadius)+'px';
        trCorner.style.zIndex               = zIndex;
        img                                 = document.createElement('img');
        img.src                             = util.resourceManager.get(this.images[DropShadowInterface.imgIds.topRight]);
        img.height                          = parseInt(this.blur.iRadius);
        img.width                           = parseInt(this.blur.iRadius);
        img.style.position                  = 'absolute';
        img.style.left                      = '0px';
        img.style.top                       = '0px';

        DropShadowInterface_FixPNG(img);

        trCorner.appendChild(img);
        dropShadow.appendChild(trCorner);
    
        var blCorner                        = document.createElement('div');
        blCorner.id                         = this.id+'_DropShadow_BottomLeftCorner';
        blCorner.className                  = 'shadow';
        blCorner.style.position             = 'absolute';
        blCorner.style.left                 = parseInt(parseInt(this.xOffset)-parseInt(this.blur.iRadius))+'px';
        //window.messageQueue.add( new Message('DropShadowInterface_Draw', 'getting bl width') );
        blCorner.style.top                  = parseInt(parseInt(DomUtils.getElementHeight(shadow))+parseInt(this.yOffset))+'px';
        blCorner.style.height               = parseInt(this.blur.iRadius)+'px';
        blCorner.style.width                = parseInt(this.blur.iRadius)+'px';
        blCorner.style.zIndex               = zIndex;
        img                                 = document.createElement('img');
        img.src                             = util.resourceManager.get(this.images[DropShadowInterface.imgIds.bottomLeft]);
        img.height                          = parseInt(this.blur.iRadius);
        img.width                           = parseInt(this.blur.iRadius);
        img.style.position                  = 'absolute';
        img.style.left                      = '0px';
        img.style.top                       = '0px';

        DropShadowInterface_FixPNG(img);

        blCorner.appendChild(img);
        dropShadow.appendChild(blCorner);
    
        var tlCorner                        = document.createElement('div');
        tlCorner.id                         = this.id+'_DropShadow_TopLeftCorner';
        tlCorner.className                  = 'shadow';
        tlCorner.style.position             = 'absolute';
        tlCorner.style.left                 = parseInt(parseInt(this.xOffset)-parseInt(this.blur.iRadius))+'px';
        tlCorner.style.top                  = parseInt(parseInt(this.yOffset)-parseInt(this.blur.iRadius))+'px';
        tlCorner.style.height               = parseInt(this.blur.iRadius)+'px';
        tlCorner.style.width                = parseInt(this.blur.iRadius)+'px';
        tlCorner.style.zIndex               = zIndex;
        img                                 = document.createElement('img');
        img.src                             = util.resourceManager.get(this.images[DropShadowInterface.imgIds.topLeft]);
        img.height                          = parseInt(this.blur.iRadius);
        img.width                           = parseInt(this.blur.iRadius);
        img.style.position                  = 'absolute';
        img.style.left                      = '0px';
        img.style.top                       = '0px';

        DropShadowInterface_FixPNG(img);

        tlCorner.appendChild(img);
        dropShadow.appendChild(tlCorner);
        dropShadow.style.visibility = DomUtils.getCurrentStyle(elem).visibility;

    } else {
        throw new Error('unable to find content element');
    }
    //window.messageQueue.add( new Message('DropShadowInterface_Draw', 'finished') );
} // End DropShadowInterface_Draw




/**
 * "Erases" the drop shadow by removing the dom elements created with DropShadowInterface.draw().
 *
 * @access public
 * @since  v0.0.1a
 * @return void
 */
function DropShadowInterface_Erase() {
    //window.messageQueue.add( new Message('DropShadowInterface_Erase', 'called') );
    var dropShadow = document.getElementById(this.dropShadowId);
    if (dropShadow) DomUtils.removeElement(dropShadow);
    // Clean up dom references for IE
    dropShadow = null;
    //window.messageQueue.add( new Message('DropShadowInterface_Erase', 'finished') );
} // End DropShadowInterface_Erase




/**
 * Aligns the object's element by adjusting its left & top by the proper calculations (which are done
 * in this function) on the left & top of the element.
 *
 * @access public
 * @since  v0.0.1a
 * @return void
 */
function DropShadowInterface_AlignElement(pos) {
    //window.messageQueue.add( new Message('DropShadowInterface_AlignElement', 'called') );
    var elem       = document.getElementById(this.elemId);
    if (!elem)       throw new Error('Unable to find element: '+this.elemId);
    var dropShadow = document.getElementById(this.dropShadowId);
    if (!dropShadow) throw new Error('Unable to find drop shadow element: '+this.dropShadowId);
    // Align the drop shadow with the main element
    dropShadow.style.position = 'absolute';
    dropShadow.style.left     = DomUtils.getElementLeft(elem)+'px';
    dropShadow.style.top      = DomUtils.getElementTop(elem)+'px';
    // fanatic memory cleanup
    dropShadow = null;
    elem       = null;
    //window.messageQueue.add( new Message('DropShadowInterface_AlignElement', 'finished') );
} // End DropShadowInterface_AlignElement




/**
 * Sets the blur values of the drop shadow.
 *
 * radius:   radius of area to blur
 * sigma:    amount of pixels to consider when
 *           averaging pixel values
 *
 * @access public
 * @since  v1.1
 * @param  integer  radius   radius of area to blur
 * @param  integer  sigma    amount of pixels to consider when averaging pixel values
 * @return void
 */
function DropShadowInterface_SetBlur(radius, sigma) {
    this.blur = { iRadius: radius, iSigma: sigma };
} // End DropShadowInterface_SetBlur


/**
 * Fixes alpha transparency issue with PNGs on Microsoft Internet Explorer.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
function DropShadowInterface_FixPNG(img) {
    if (DomUtils.browser.isIE()) {
        var arVersion = navigator.appVersion.split("MSIE");
        var version = 0.0;
        if (arVersion && arVersion.length > 1) version = parseFloat(arVersion[1]);
        if ((version >= 5.5) && (version < 7) && (document.body.filters)) {
            var imgID    = (img.id) ? "id='" + img.id + "' " : "";
            var imgClass = (img.className) ? "class='" + img.className + "' " : "";
            var imgTitle = (img.title)                    ?
                            "title='" + img.title  + "' " :
                            "title='" + img.alt    + "' " ;
            var imgStyle = "display:inline-block;";
            if (img && img.style) { 
              imgStyle += img.style.cssText || ''; 
              img.style.cssText = "display: none";
            }
            var strNewHTML = "<span " + imgID + imgClass + imgTitle
                           + " style=\"" + "width:" + img.width 
                           + "px; height:" + img.height 
                           + "px;" + imgStyle + ";"
                           + "filter: progid:DXImageTransform.Microsoft.AlphaImageLoader"
                           + "(src=\'"+img.src+"\', sizingMethod='scale');\"></span>";
            img.src = "";
            img.outerHTML = strNewHTML;
        }
    }
}
/**
 * $Id: popupinterface.js 64367 2009-02-20 01:56:36Z kchiu $
 * $Author: kchiu $
 * $Revision: 64367 $
 * $Name$
 * $Date: 2009-02-19 17:56:36 -0800 (Thu, 19 Feb 2009) $
 *
 * @jsRequire interfaces.Interface
 * @jsRequire interfaces.PopupInterface
 *
 *
 * @version    $Revision: 64367 $
 * @author     Philip Snyder <philip@pricegrabber.com>
 * @copyright  Copyright &copy; 2006, Philip Snyder, PriceGrabber.com
 * @see        interfaces.Interface
 */

/**
 * PopupInterface Constructor / Definition
 *
 * This interface is built on top of the Interface object
 * and is NOT intended to be instantiated directly. See
 * documentation on interfaces.Interface for a complete
 * explanation.
 *
 * @access public
 * @since  v1.1
 * @return PopupInterface
 */
function PopupInterface() {
    this.elemId  = null;
    this.visible = false;
    this.linked  = new Array;
    this.hide    = PopupInterface_Hide;
    this.show    = PopupInterface_Show;
    this.toggle  = PopupInterface_Toggle;
}

// Setup PopupInterface prototype chain
PopupInterface.prototype             = new Interface;
PopupInterface.prototype.constructor = PopupInterface;
PopupInterface.superclass            = Interface.prototype;

/**
 * Makes the object's element invisible.
 *
 * @access public
 * @since  v1.1
 * @return boolean
 */
function PopupInterface_Hide() {
    this.visible = false;
    var elem = document.getElementById(this.elemId);
    if (!elem) throw new Error('Unable to find element: '+this.elemId);
    elem.style.visibility = 'hidden';
    elem.style.left       = '0px';
    elem.style.top        = '0px';
    for (var i=0; i<this.linked.length; i++) {
        var elem = document.getElementById(this.linked[i]);
        elem.style.visibility = 'hidden';
        elem.style.left       = '0px';
        elem.style.top        = '0px';
    }
    return true;
}

/**
 * Makes the object's element visibile.
 *
 * @access public
 * @since  v1.1
 * @return boolean
 */
function PopupInterface_Show() {
    this.visible = true;
    if (document.getElementById(this.elemId)) document.getElementById(this.elemId).style.visibility = 'visible';
    for (var i=0; i<this.linked.length; i++) document.getElementById(this.linked[i]).style.visibility = 'visible';
    return true;
}

/**
 * Toggles the object's visibility.
 *
 * @access public
 * @since  v1.1
 * @return boolean
 */
function PopupInterface_Toggle() {
    if (this.visible) return this.hide();
    else              return this.show();
}
/**
 * $Id: delayedpopupinterface.js 64367 2009-02-20 01:56:36Z kchiu $
 * $Author: kchiu $
 * $Revision: 64367 $
 * $Name$
 * $Date: 2009-02-19 17:56:36 -0800 (Thu, 19 Feb 2009) $
 *
 * @jsRequire interfaces.Interface
 * @jsRequire interfaces.PopupInterface
 *
 *
 * @version    $Revision: 64367 $
 * @author     Philip Snyder <philip@pricegrabber.com>
 * @copyright  Copyright &copy; 2006, Philip Snyder, PriceGrabber.com
 * @see        interfaces.Interface
 */

/**
 * DelayedPopupInterface Constructor / Definition
 *
 * This interface is built on top of the Interface object
 * and is NOT intended to be instantiated directly. See
 * documentation on interfaces.Interface for a complete
 * explanation.
 *
 * @access public
 * @since  v1.1
 * @return DelayedPopupInterface
 */
function DelayedPopupInterface() {
    this.elemId      = null;
    this.visible     = false;
    this.linked      = new Array;
    this.timer       = null;
    this.delay       = null;
    this.hide        = DelayedPopupInterface_Hide;
    this.show        = DelayedPopupInterface_Show;
    this.toggle      = PopupInterface_Toggle;
    this.cancelTimer = DelayedPopupInterface_CancelTimer;
    this.implement(PopupInterface);
    return this;
}

// Setup DelayedPopupInterface prototype chain
DelayedPopupInterface.prototype             = new PopupInterface;
DelayedPopupInterface.prototype.constructor = DelayedPopupInterface;
DelayedPopupInterface.superclass            = PopupInterface.prototype;

/**
 * Calls PopupInterface_Hide after timer runs out.
 *
 * @access public
 * @since  v1.1
 * @return boolean
 */
function DelayedPopupInterface_Hide() {
    this.cancelTimer();
    var obj = this;
    this.timer = setTimeout(function() {
        PopupInterface_Hide.call(obj);
        obj.timer = null;
    }, this.delay);
    return true;
}

/**
 * Calls PopupInterface_Show after timer runs out.
 *
 * @access public
 * @since  v1.1
 * @return boolean
 */
function DelayedPopupInterface_Show() {
    this.cancelTimer();
    var obj = this;
    this.timer = setTimeout(function() {
        PopupInterface_Show.call(obj);
        obj.timer = null;
    }, this.delay);
    return true;
}

/**
 * Cancels any currently running timers.
 *
 * This effectively stops the show / hide / toggle
 * functions in their tracks, allowing us to cancel
 * them at any time.
 *
 * @access public
 * @since  v1.1
 * @return boolean
 */
function DelayedPopupInterface_CancelTimer() {
    if (this.timer) {
        clearTimeout(this.timer);
        this.timer = null;
    }
    return true;
}
/**
 * $Id: roundedcornersinterface.js 76074 2009-11-19 20:53:10Z kchiu $
 * $Author: kchiu $
 * $Revision: 76074 $
 * $Name$
 * $Date: 2009-11-19 12:53:10 -0800 (Thu, 19 Nov 2009) $
 *
 * @jsRequire DomUtils
 * @jsRequire interfaces.Interface
 * @jsRequire classes.ResourceManager
 *
 *
 * @version    $Revision: 76074 $
 * @author     Philip Snyder <philip@pricegrabber.com>
 * @copyright  Copyright &copy; 2006, Philip Snyder, PriceGrabber.com
 * @see        interfaces.Interface
 */

/**
 * RoundedCornersInterface Constructor / Definition
 *
 * This interface is built on top of the Interface object
 * and is NOT intended to be instantiated directly. See
 * documentation on interfaces.Interface for a complete
 * explanation.
 *
 * @access public
 * @since  v1.1
 * @return RoundedCornersInterface
 */
function RoundedCornersInterface() {
    this.elemId       = null;
    this.cornerStyle  = null;
    this.init         = RoundedCornersInterface_Init;
    this.draw         = RoundedCornersInterface_Draw;
    this.erase        = RoundedCornersInterface_Erase;
    this.cornersDrawn = false;
    this.init();
}

// Setup RoundedCornersInterface prototype chain
RoundedCornersInterface.prototype             = new Interface;
RoundedCornersInterface.prototype.constructor = RoundedCornersInterface;
RoundedCornersInterface.superclass            = Interface.prototype;






/****** BEGIN EDIT SECTION ******/

/**
 * Rounded corners style definitions.
 *
 * This data structure allows for the definition of various different
 * rounded corners "styles" that can be applied by setting the roundedCornersStyle
 * of the object implementing RoundedCornersInterface.
 *
 * Example:
 *
 *    <script language="JavaScript">
 *    RoundedCornersInterface.settings.style = 'Default';
 *    var popup = new RoundedCornersPopup();
 *    </script>
 *
 * You can also define a rounded corner style at any time after
 * inclusion of this file and then reference that style instead if you
 * like.
 *
 * Note: This style definition is site-wide, not object specific. This
 * will be changing in the near future as this interface adopts the
 * same style interface that DropShadowInterface uses.
 *
 * @access public
 * @since  v1.1
 * @todo   Add .roundedCornersStyle to interface (see DropShadowInterface)
 * @var    RoundedCornersInterface.styles   struct
 */
RoundedCornersInterface.styles = {
    Default: {
        images: {
            tr: { src: 'http://i.pgcdn.com/images/balloon/top_right_6x6.gif',    width: 6, height: 6 },
            tl: { src: 'http://i.pgcdn.com/images/balloon/top_left_6x6.gif',     width: 6, height: 6 },
            bl: { src: 'http://i.pgcdn.com/images/balloon/bottom_left_6x6.gif',  width: 6, height: 6 },
            br: { src: 'http://i.pgcdn.com/images/balloon/bottom_right_6x6.gif', width: 6, height: 6 }
        }
    }
};

/**
 * General settings struct.
 *
 * @access public
 * @since  v1.1
 * @var    RoundedCornersInterface.settings  struct
 *
 */
RoundedCornersInterface.settings = { style: 'Default' };

/****** END EDIT SECTION ******/








/**
 * Internal image ids used for keeping track of image resources.
 *
 * !DO NOT MODIFY THIS!
 *
 * @access private
 * @since  v1.1
 * @var    RoundedCornersInterface.imgIds   struct
 */
RoundedCornersInterface.imgIds   = { tr: 0, tl: 1, bl: 2, br: 3 };

/**
 * Initializes an object that implements the RoundedCornersInterface.
 * Call this function prior to any draw() functions.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
function RoundedCornersInterface_Init() {
    var style = RoundedCornersInterface.styles[RoundedCornersInterface.settings.style];
    if (typeof(window.preloadImage) == 'function') {
        window.preloadImage(style.images.tr.src, style.images.tr.width, style.images.tr.height);
        window.preloadImage(style.images.tl.src, style.images.tl.width, style.images.tl.height);
        window.preloadImage(style.images.bl.src, style.images.bl.width, style.images.bl.height);
        window.preloadImage(style.images.br.src, style.images.br.width, style.images.br.height);
    }
} // End RoundedCornersInterface_Init

/**
 * "Draws" the actual rounded corners by creating the necessary dom elements and applying them to
 * the object's element.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
function RoundedCornersInterface_Draw() {
    //window.messageQueue.add( new Message('RoundedCornersInterface_Draw', 'called') );
    if (this.cornersDrawn) { RoundedCornersInterface_Erase.call(this); }
    var elem = document.getElementById(this.elemId);
    if (elem) {
        //if (typeof(writeDebug) == 'function') writeDebug('drawing background...');
        var style = RoundedCornersInterface.styles[RoundedCornersInterface.settings.style];
        /** BACKGROUND **/
        var div                   = document.createElement('div');
        div.id                    = 'roundedCorners_Background';
        div.style.position        = 'absolute';
        div.style.left            = style.images.tl.width+'px';
        div.style.top             = style.images.tl.height+'px';
        var eHeight  = DomUtils.getElementHeight(elem);
        var tlHeight = style.images.tl.height;
        var blHeight = style.images.bl.height;
        //window.messageQueue.add( new Message(funcname(this), 'getting width') );
        var eWidth   = DomUtils.getElementWidth(elem);
        var tlWidth  = style.images.tl.width;
        var blWidth  = style.images.bl.width;
        div.style.height          = (parseInt(eHeight)-tlHeight-blHeight)+'px';
        div.style.width           = (parseInt(eWidth)-tlWidth-blWidth)+'px';
        div.style.backgroundColor = '#ffffff';
        div.style.zIndex          = '-1';
        //if (typeof(writeDebug) == 'function') writeDebug('background zIndex: '+div.style.zIndex);
        elem.appendChild(div);
        elem.style.backgroundColor = 'transparent';
        
        /** EDGES **/
        //if (typeof(writeDebug) == 'function') writeDebug('drawing bottom edge...');
        // Bottom edge
        div                       = document.createElement('div');
        div.id                    = 'roundedCorners_BottomEdge';
        div.style.position        = 'absolute';
        div.style.left            = style.images.bl.width+'px';
        div.style.top             = (parseInt(DomUtils.getElementHeight(elem))-style.images.bl.height)+'px';
        div.style.height          = (style.images.bl.height)+'px'; // -1 accounts for bottom border
        //window.messageQueue.add( new Message(funcname(this), 'getting bottom width') );
        div.style.width           = (parseInt(DomUtils.getElementWidth(elem)) - style.images.bl.width - style.images.br.width)+'px';
        div.style.borderBottom    = '1px solid #999999';
        div.style.backgroundColor = '#ffffff';
        div.style.overflow        = 'hidden';
        elem.appendChild(div);
        //if (typeof(writeDebug) == 'function') writeDebug('drawing top edge...');
        // Top edge
        div                       = document.createElement('div');
        div.id                    = 'roundedCorners_TopEdge';
        div.style.position        = 'absolute';
        div.style.left            = style.images.tl.width+'px';
        div.style.top             = '0px';
        div.style.height          = (style.images.tl.height)+'px'; // -1 accounts for top border
        //window.messageQueue.add( new Message(funcname(this), 'getting top width') );
        div.style.width           = (parseInt(DomUtils.getElementWidth(elem))-style.images.tl.width-style.images.tr.width)+'px';
        div.style.borderTop       = '1px solid #999999';
        div.style.backgroundColor = '#ffffff';
        div.style.overflow        = 'hidden';
        elem.appendChild(div);
        // Left edge
        //if (typeof(writeDebug) == 'function') writeDebug('drawing left edge...');
        div                       = document.createElement('div');
        div.id                    = 'roundedCorners_LeftEdge';
        div.style.position        = 'absolute';
        div.style.left            = '0px';
        div.style.top             = style.images.tl.height+'px';
        div.style.width           = (style.images.tl.width)+'px'; // -1 accounts for left border
        div.style.height          = (parseInt(DomUtils.getElementHeight(elem)) - style.images.tl.height - style.images.bl.height)+'px';
        div.style.borderLeft      = '1px solid #999999';
        div.style.backgroundColor = '#ffffff';
        div.style.overflow        = 'hidden';
        elem.appendChild(div);
        //if (typeof(writeDebug) == 'function') writeDebug('drawing right edge...');
        // Right edge
        div                       = document.createElement('div');
        div.id                    = 'roundedCorners_RightEdge';
        div.style.position        = 'absolute';
        //window.messageQueue.add( new Message(funcname(this), 'getting right width') );
        div.style.left            = (parseInt(DomUtils.getElementWidth(elem))-style.images.tr.width)+'px';
        div.style.top             = style.images.tr.height+'px';
        div.style.width           = (style.images.tr.width)+'px';
        div.style.height          = (parseInt(DomUtils.getElementHeight(elem))-style.images.tr.height-style.images.br.height)+'px';
        div.style.borderRight     = '1px solid #999999';
        div.style.backgroundColor = '#ffffff';
        div.style.overflow        = 'hidden';
        elem.appendChild(div);
        /** CORNERS **/
        //if (typeof(writeDebug) == 'function') writeDebug('drawing top right corner...');
        // Top right
        var img                   = document.createElement('img');
        img.id                    = 'roundedCorners_TopRightCorner';
        img.src                   = style.images.tr.src;
        img.height                = style.images.tr.height;
        img.width                 = style.images.tr.width;
        img.border                = 0;
        img.style.position        = 'absolute';
        //window.messageQueue.add( new Message(funcname(this), 'getting tr width') );
        img.style.left            = parseInt(parseInt(DomUtils.getElementWidth(elem))-(img.width))+'px';
        img.style.top             = '0px';
        elem.appendChild(img);
        //if (typeof(writeDebug) == 'function') writeDebug('drawing top left corner...');
        // Top left
        var img                   = document.createElement('img');
        img.id                    = 'roundedCorners_TopLeftCorner';
        img.src                   = style.images.tl.src;
        img.height                = style.images.tl.height;
        img.width                 = style.images.tl.width;
        img.border                = 0;
        img.style.position        = 'absolute';
        img.style.left            = '0px';
        img.style.top             = '0px';
        elem.appendChild(img);
        //if (typeof(writeDebug) == 'function') writeDebug('drawing bottom left corner...');
        // Bottom left
        var img                   = document.createElement('img');
        img.id                    = 'roundedCorners_BottomLeftCorner';
        img.src                   = style.images.bl.src;
        img.height                = style.images.bl.height;
        img.width                 = style.images.bl.width;
        img.border                = 0;
        img.style.position        = 'absolute';
        img.style.left            = '0px';
        img.style.top             = parseInt(parseInt(DomUtils.getElementHeight(elem))-parseInt(img.height))+'px';
        elem.appendChild(img);
        // Bottom right
        var img                   = document.createElement('img');
        img.id                    = 'roundedCorners_BottomRightCorner';
        img.src                   = style.images.br.src;
        img.height                = style.images.br.height;
        img.width                 = style.images.br.width;
        img.border                = 0;
        img.style.position        = 'absolute';
        //window.messageQueue.add( new Message(funcname(this), 'getting br width') );
        img.style.left            = parseInt(parseInt(DomUtils.getElementWidth(elem))-(img.width))+'px';
        img.style.top             = parseInt(parseInt(DomUtils.getElementHeight(elem))-(img.height))+'px';
        elem.appendChild(img);
        
        this.cornersDrawn = true;
    }
    //window.messageQueue.add( new Message('RoundedCornersInterface_Draw', 'finished') );
} // End RoundedCornersInterface_Draw

/**
 * "Erases" the rounded corners by removing the dom elements created with RoundedCornersInterface.draw().
 *
 * @access public
 * @since  v0.0.1a
 * @return void
 */
function RoundedCornersInterface_Erase() {
    //if (typeof(writeDebug) == 'function') writeDebug('>> RoundedCornersInterface_Erase() called.', '#000000', '#ffff00');
    var elem = document.getElementById(this.elemId);
    if (elem.hasChildNodes()) {
        //if (typeof(writeDebug) == 'function') writeDebug('elem has child nodes: '+elem.childNodes.length);
        for (var i=elem.childNodes.length; i>0; i--) {
            var nodeId = elem.childNodes[i-1].id;
            var eq = '!=';
            var idPre = 'roundedCorners_';
            if (nodeId && nodeId.substr(0, idPre.length) == idPre) {
                eq = '==';
                //elem.removeChild(elem.childNodes[i-1]);
                DomUtils.removeElement(elem.childNodes[i-1]);
            }
            //if (typeof(writeDebug) == 'function') writeDebug(nodeId.substr(0, idPre.length)+' '+eq+' '+idPre);
        }
    } //else if (typeof(writeDebug) == 'function') writeDebug('no child nodes!');
    this.cornersDrawn = false;
    //if (typeof(writeDebug) == 'function') writeDebug('<< RoundedCornersInterface_Erase() finished.', '#000000', '#ffff00');
} // End RoundedCornersInterface_Erase







function ResourceManager() {

    var resourceManager = this;

    this.preloadedImages = new Array;


    window.preloadImage = ResourceManager_PreloadImage;
    window.getImage     = ResourceManager_GetImage;
    window.getImageSrc  = ResourceManager_GetImageSrc;
    window.swapImageSrc = ResourceManager_SwapImageSrc;


    return this;
}




function ResourceManager_PreloadImage(url, width, height) {
    if (!window.resourceManager.preloadedImages) window.resourceManager.preloadedImages = new Array;
//    if (typeof(writeDebug) == 'function') writeDebug('ResourceManager_PreloadImage(): checking for preloaded '+url);
    if (!window.resourceManager.preloadedImages[url]) {
//        if (typeof(writeDebug) == 'function') { writeDebug('ResourceManager_PreloadImage(): preloading '+url+', w: '+width+', h: '+height); }
        var image = new Image(width, height);
        image.src = url;
        window.resourceManager.preloadedImages[url] = image;
    }// else if (typeof(writeDebug) == 'function') writeDebug('ResourceManager_PreloadImage(): image already preloaded: '+url);
    return window.resourceManager.preloadedImages[url];
}

function ResourceManager_GetImage(url, width, height) {
    return window.preloadImage(url, width, height);
}

function ResourceManager_GetImageSrc(url) {
    return window.getImage(url).src;
}

function ResourceManager_SwapImageSrc(imgElem, url) {
    if (imgElem && imgElem.nodeType == 'IMG') {
        imgElem.oldSrc = imgElem.src;
        imgElem.src    = window.getImageSrc(url);
    }
}




window.resourceManager = new ResourceManager();/**
 * $Id: definitionpopup.js 64367 2009-02-20 01:56:36Z kchiu $
 * $Author: kchiu $
 * $Revision: 64367 $
 * $Name$
 * $Date: 2009-02-19 17:56:36 -0800 (Thu, 19 Feb 2009) $
 *
 * @jsRequire DomUtils
 * @jsRequire classes.BaseObject
 * @jsRequire classes.EventManager
 * @jsRequire interfaces.DropShadowInterface
 * @jsRequire interfaces.CalloutInterface
 * @jsRequire interfaces.DelayedPopupInterface
 * @jsRequire interfaces.AnchoredInterface
 * @jsRequire interfaces.RoundedCornersInterface
 *
 *
 *
 *
 * @version    $Revision: 64367 $
 * @author     Philip Snyder <philip@pricegrabber.com>
 * @copyright  Copyright &copy; 2006 2007, Philip Snyder, PriceGrabber.com
 * @see        classes.BaseObject
 * @see        interfaces.DropShadowInterface
 * @see        interfaces.CalloutInterface
 * @see        interfaces.DelayedPopupInterface
 * @see        interfaces.AnchoredInterface
 * @see        interfaces.RoundedCornersInterface
 */

/**
 * DefinitionPopup Constructor / Definition
 *
 * This is NOT intended to be instantiated directly. Instead, use the
 * singleton accessor methods DefinitionPopup.getInstance(),
 * DefinitionPopup.show(), DefinitionPopup.hide() and DefinitionPopup.toggle().
 *
 * @access public
 * @since  v1.1
 * @param  DOMElement       anchor
 * @return DefinitionPopup
 */
function DefinitionPopup(anchor) {
    this.elemId            = null;
    // Callout interface implementation
    this.calloutId         = null;
    this.calloutPadding    = 0;
    // Drop shadow interface implementation
    this.dropShadowId      = null;
    this.color             = null;
    this.xOffset           = null;
    this.yOffset           = null;
    this.blur              = { iRadius: null, iSigma: null };
    this.opacity           = null;
    this.xShrink           = null;
    this.yShrink           = null;
    this.shadowStyle       = null;
    this.images            = new Array;
    this.setBlur           = DropShadowInterface_SetBlur;
    // Delayed popup interface implementation
    this.timer             = null;
    this.visible           = false;
    this.delay             = null;
    this.linked            = new Array;
    this.cancelTimer       = DelayedPopupInterface_CancelTimer;
    this.hide              = DelayedPopupInterface_Hide;
    this.toggle            = PopupInterface_Toggle;
    // Anchored interface implementation
    this.anchorId          = anchor || null;
    this.disableScroll     = true;
    this.getAnchorX        = AnchoredInterface_GetAnchorX;
    this.getAnchorY        = AnchoredInterface_GetAnchorY;
    this.getAnchorZ        = AnchoredInterface_GetAnchorZ;
    this.getAnchorWidth    = AnchoredInterface_GetAnchorWidth;
    this.getAnchorHeight   = AnchoredInterface_GetAnchorHeight;
    this.getAnchorPosition = AnchoredInterface_GetAnchorPosition;
    this.getElemWidth      = AnchoredInterface_GetElemWidth;
    this.getElemHeight     = AnchoredInterface_GetElemHeight;
    this.setAnchor         = AnchoredInterface_SetAnchor;
    // Rounded corners interface implementation
    this.cornerStyle       = null;
    this.cornersDrawn      = false;
    // Drop shadow interface && Callout interface joint implementation
    this.erase             = DefinitionPopup_Erase;
    this.draw              = DefinitionPopup_Draw;
    this.init              = DefinitionPopup_Init;
    // Drop shadow interface && Delayed popup interface joint implementation
    this.show              = DefinitionPopup_Show;
    // Drop shadow interface && Anchored interface joint implementation
    this.alignElement      = DefinitionPopup_AlignElement;

    this.implement(DropShadowInterface);
    this.implement(CalloutInterface);
    this.implement(DelayedPopupInterface);
    this.implement(AnchoredInterface);
    this.implement(RoundedCornersInterface);
    
    this.setElement        = DefinitionPopup_SetElement;
    this.setDefinition     = DefinitionPopup_SetDefinition;
    this.setTerm           = DefinitionPopup_SetTerm;
    this.setTermColor      = DefinitionPopup_SetTermColor;

    this.id                = 'DefinitionPopup';
    this.style             = 'Default';
    this.delay             = 500;
    this.elemId            = this.id;
    this.defId             = this.elemId+'_def';
    this.termId            = this.elemId+'_term';
   
    this.init();
} // End DefinitionPopup

// Setup DefinitionPopup prototype chain
DefinitionPopup.prototype             = new BaseObject;
DefinitionPopup.prototype.constructor = DefinitionPopup;
DefinitionPopup.superclass            = BaseObject.prototype;









/****** BEGIN EDIT SECTION ******/

/**
 * Style definitions for DefinitionPopup widget.
 *
 * These style settings can be overridden by a simple variable set call.
 * Note that if you set the backgroundColor to anything other than #ffffff
 * you will most likely want to create some rounded corner images and define
 * them too.
 * 
 * Example:
 *   <?php
 *   if (!$pricegrabber_site)
 *       echo "    DefinitionPopup.styles.Default.term.color = '".$color."';\n";
 *   ?>
 */
DefinitionPopup.styles = {
    Default: {
        term: {
            font: {
                family:  'Arial, Helvetica, sans-serif',
                size:    '13px',
                weight:  'bold'
            },
            color:       '#589c1c'
        },
        font: {
            family:      'Arial, Helvetica, sans-serif',
            size:        '13px',
            weight:      'normal'
        },
        backgroundColor: '#ffffff',
        color:           '#656565'
    }
} // End DefinitionPopup.styles

/****** END EDIT SECTION ******/


















/**
 * Sets the DOMElement that the DefinitionPopup works with.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
function DefinitionPopup_SetElement(elem) {
    //if (typeof(writeDebug) == 'function') writeDebug('DefinitionPopup_SetContent() called.');
    this.elemId = elem.id;
    //if (typeof(writeDebug) == 'function') writeDebug('DefinitionPopup_SetContent() finished.');
}

/**
 * Initializes the DefinitionPopup in preparation for drawing.
 *
 * Call this method before any draw methods as it handles initialization of
 * any implemented interfaces as well.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
function DefinitionPopup_Init() {
    //if (typeof(writeDebug) == 'function') writeDebug('DefinitionPopup_Init() called.');
    var elem = document.getElementById(this.elemId);
    if (!elem) {
        elem = document.createElement('div');
        document.getElementsByTagName('body')[0].appendChild(elem);
        elem.id = this.elemId;
    }

    var term = document.getElementById(this.termId);
    if (!term) {
        term = document.createElement('div');
        elem.appendChild(term);
        term.id = this.termId;
    }

    var def = document.getElementById(this.defId);
    if (!def) {
        def = document.createElement('div');
        elem.appendChild(def);
        def.id = this.defId;
    }

    elem.style.backgroundColor = DefinitionPopup.styles[this.style].backgroundColor;
    term.style.color           = DefinitionPopup.styles[this.style].term.color;
    term.style.paddingBottom   = '5px';
    term.style.fontFamily      = DefinitionPopup.styles[this.style].term.font.family;
    term.style.fontSize        = DefinitionPopup.styles[this.style].term.font.size;
    term.style.fontWeight      = DefinitionPopup.styles[this.style].term.font.weight;
    def.style.color            = DefinitionPopup.styles[this.style].color;
    def.style.fontFamily       = DefinitionPopup.styles[this.style].font.family;
    def.style.fontSize         = DefinitionPopup.styles[this.style].font.size;
    def.style.fontWeight       = DefinitionPopup.styles[this.style].font.weight;
    
    this.calloutPadding = 20;
    this.cornerStyle = 'Default';
    RoundedCornersInterface_Init.call(this);
    this.shadowStyle = 'Default';
    DropShadowInterface_Init.call(this);
    //if (typeof(writeDebug) == 'function') writeDebug('DefinitionPopup_Init() finished.');
} // End DefinitionPopup_Init

/**
 * Erases the definition popup by removing the dom elements created in DefinitionPopup_Draw.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
function DefinitionPopup_Erase() {
    CalloutInterface_Erase.call(this);
    DropShadowInterface_Erase.call(this);
    RoundedCornersInterface_Erase.call(this);
    this.linked = new Array;
} // End DefinitionPopup_Erase

/**
 * Draws the definition popup by creating the necessary dom elements and attaching them to the document accordingly.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
function DefinitionPopup_Draw() {
    //if (typeof(writeDebug) == 'function') writeDebug('>> DefinitionPopup_Draw() called.', '#ffffff', '#0000ff');
    var elem = document.getElementById(this.elemId);
    if (!elem) throw new Error('Unable to find element: '+this.elemId);

    var term = document.getElementById(this.termId);
    if (!term) throw new Error('Unable to find element: '+this.termId);

    var def = document.getElementById(this.defId);
    if (!def) throw new Error('Unable to find element: '+this.defId);

    this.linked = new Array;
    bHeight = 2;
    elem.style.border = '1px solid '+DefinitionPopup.styles[this.style].backgroundColor;
    elem.style.backgroundColor = DefinitionPopup.styles[this.style].backgroundColor;
    elem.style.color = DefinitionPopup.styles[this.style].color;
    RoundedCornersInterface_Draw.call(this);
    CalloutInterface_Draw.call(this);
    DropShadowInterface_Draw.call(this);
    window.addEvent(elem, 'mouseover', this.cancelTimer, this, true);
    window.addEvent(elem, 'mouseout',  this.hide,        this, true);
    elem.style.border = 'none';
    elem.style.backgroundColor = 'transparent';

    this.linked.push(this.dropShadowId);
    this.linked.push(this.calloutId);
    //if (typeof(writeDebug) == 'function') writeDebug('<< DefinitionPopup_Draw() finished.', '#ffffff', '#0000ff');
} // End DefinitionPopup_Draw

/**
 * Shows the definition popup on the screen.
 *
 * @access public
 * @since  v1.1
 * @return boolean
 */
function DefinitionPopup_Show() {
    //if (typeof(writeDebug) == 'function') writeDebug('>> DefinitionPopup_Show() called.', '#ffffff', '#0000ff');
    this.cancelTimer();
    var wasVisible = this.visible;
    if (this.visible) {
        PopupInterface_Hide.call(this);
        this.erase();
    }
    this.draw();

    var anchor     = document.getElementById(this.anchorId);
    if (!anchor)     throw new Error('Unable to find anchor element: '+this.anchorId);

    var elem       = document.getElementById(this.elemId);
    if (!elem)       throw new Error('Unable to find element: '+this.elemId);

    var dropShadow = document.getElementById(this.dropShadowId);
    if (!elem)       throw new Error('Unable to find drop shadow element: '+this.dropShadowId);

    var callout    = document.getElementById(this.calloutId);
    if (!callout)    throw new Error('Unable to find callout element: '+this.calloutId);


    // Get the z-index of our anchor element
    var zIndex = parseInt(DomUtils.getZIndex(anchor));
    // If it doesn't have one make it 1000
    if (zIndex == 0) {
        zIndex = 1000;
        anchor.style.zIndex = zIndex;
    }
    dropShadow.style.zIndex = zIndex+1;
    callout.style.zIndex    = zIndex+2;
    elem.style.zIndex       = zIndex+3;
    //window.messageQueue.add( new Message('ItineraryPopup_Show', 'anchor zIndex: '+zIndex) );
    //window.messageQueue.add( new Message('ItineraryPopup_Show', 'drop shadow zIndex: '+dropShadow.style.zIndex) );
    //window.messageQueue.add( new Message('ItineraryPopup_Show', 'callout zIndex: '+callout.style.zIndex) );
    //window.messageQueue.add( new Message('ItineraryPopup_Show', 'elem zIndex: '+elem.style.zIndex) );
    //this.alignElement(this.getAnchorPosition());
    this.alignElement();
    if (wasVisible) PopupInterface_Show.call(this);
    else            DelayedPopupInterface_Show.call(this);
    return true;
} // End DefinitionPopup_Show

/**
 * Aligns the definition popup by calling implemented interfaces' AlignElement functions.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
function DefinitionPopup_AlignElement() {
    //if (typeof(writeDebug) == 'function') writeDebug('>> DefinitionPopup_AlignElement() called.', '#ffffff', '#0000ff');
    AnchoredInterface_AlignElement.call(this)
    CalloutInterface_AlignElement.call(this);
    DropShadowInterface_AlignElement.call(this);
    //if (typeof(writeDebug) == 'function') writeDebug('<< DefinitionPopup_AlignElement() finished.', '#ffffff', '#0000ff');
} // End DefinitionPopup_AlignElement

/**
 * Sets the definition in the definition popup.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
function DefinitionPopup_SetDefinition(definition) {
    //if (typeof(writeDebug) == 'function') writeDebug('>> DefinitionPopup_SetDefinition() called.', '#ff0000', '#ffffff');
    var defElem = document.getElementById(this.defId);
    if (!defElem) throw new Error('Unable to find definition element: '+this.defId);
    while (defElem.hasChildNodes()) DomUtils.removeElement(defElem.firstChild);
    var txtDef = document.createTextNode(definition);
    defElem.appendChild(txtDef);
    //if (typeof(writeDebug) == 'function') writeDebug('<< DefinitionPopup_SetDefinition() finished.', '#ff0000', '#ffffff');
}

/**
 * Sets the term in the definition popup.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
function DefinitionPopup_SetTerm(term) {
    //if (typeof(writeDebug) == 'function') writeDebug('>> DefinitionPopup_SetTerm() called.', '#ff0000', '#ffffff');
    var termElem = document.getElementById(this.termId);
    if (!termElem) throw new Error('Unable to find term element: '+this.termId);
    while (termElem.hasChildNodes()) DomUtils.removeElement(termElem.firstChild);
    var txtTerm = document.createTextNode(term);
    termElem.appendChild(txtTerm);
    //if (typeof(writeDebug) == 'function') writeDebug('<< DefinitionPopup_SetTerm() finished.', '#ff0000', '#ffffff');
}

/**
 * Sets the term color of the definition popup.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
function DefinitionPopup_SetTermColor(color) {
    //if (typeof(writeDebug) == 'function') writeDebug('>> DefinitionPopup_SetTermColor() called.', '#ff0000', '#ffffff');
    var term = document.getElementById(this.termId);
    if (!term) throw new Error('Unable to find term element: '+this.termId);
    term.style.color = color;
    //if (typeof(writeDebug) == 'function') writeDebug('<< DefinitionPopup_SetTermColor() finished.', '#ff0000', '#ffffff');
}








/****** SINGLETON ACCESSORS SECTION ******/

/**
 * Singleton instance variable.
 *
 * @access public
 * @since  v1.1
 * @var    instance   DefinitionPopup
 */
DefinitionPopup.instance = null;

/**
 * Singleton accessor for retrieving the definition popup instance.
 *
 * @access public
 * @since  v1.1
 * @return DefinitionPopup
 */
DefinitionPopup.getInstance = function() {
    if (!DefinitionPopup.instance) DefinitionPopup.instance = new DefinitionPopup();
    return DefinitionPopup.instance;
} // End DefinitionPopup.getInstance

/**
 * Singleton accessor for initializing the definition popup.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
//DefinitionPopup.initInstance = function() {
//    if (typeof(writeDebug) == 'function') writeDebug('>> DefinitionPopup.init() called.', '#ff0000', '#ffff00');
//    DefinitionPopup.instance = new DefinitionPopup();
//    if (typeof(writeDebug) == 'function') writeDebug('<< DefinitionPopup.init() finished.', '#ff0000', '#ffff00');
//} // End DefinitionPopup.init

/**
 * Singleton accessor for showing the definition popup.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
DefinitionPopup.show = function(anchor, term, def) {
    //if (typeof(writeDebug) == 'function') writeDebug('>> DefinitionPopup.show() called.', '#ff0000', '#ffff00');
    DefinitionPopup.getInstance().setAnchor(anchor);
    DefinitionPopup.getInstance().setDefinition(def);
    DefinitionPopup.getInstance().setTerm(term);
    DefinitionPopup_Show.call(DefinitionPopup.getInstance());
    //if (typeof(writeDebug) == 'function') writeDebug('<< DefinitionPopup.show() finished.', '#ff0000', '#ffff00');
} // End DefinitionPopup.show

/**
 * Singleton accessor for hiding the definition popup.
 *
 * @access public
 * @since  v1.1
 * @return void
 */
DefinitionPopup.hide = function() {
    DelayedPopupInterface_Hide.call(DefinitionPopup.getInstance());
} // End DefinitionPopup.hide

/**
 * Singleton accessor for toggling the definition popup.
 *
 * @access public
 * @since  v1.1
 * @param  DOMElement  anchor
 * @param  string      def
 * @return void
 */
DefinitionPopup.toggle = function(anchor, term, def) {
    if (DefinitionPopup.getInstance().visible) DefinitionPopup.hide();
    else                                       DefinitionPopup.show(anchor, term, def);
}

function MM_preloadImages() { 
  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}

function MM_swapImgRestore() { 
  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}

function MM_findObj(n, d) { 
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document); return x;
}

function MM_swapImage() { 
  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
   if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}

function setfocus() {
	if (document.forms['mastsearch'].form_keyword) document.forms['mastsearch'].form_keyword.focus();
}
var show;
function showmenu()
{
  var el = document.getElementById("channels");
  var iframe_menu = document.getElementById('iframe_menu');
  var moretab=document.getElementById("menupos");
  if (el) {
	  	el.style.top=(DomUtils.getElementTop(moretab)+23)+"px";
		el.style.left=(DomUtils.getElementLeft(moretab)-100)+"px";
    el.style.visibility = "visible";
    el.style.zIndex = '100';
      iframe_menu.style.width = el.offsetWidth;
      iframe_menu.style.height = el.offsetHeight;
      iframe_menu.style.top = el.style.top;
      iframe_menu.style.left = el.style.left;
      iframe_menu.style.zIndex = el.style.zIndex - 1;
      iframe_menu.style.display = "block";
    show = 1;
  }
}


function hidemenu()
{
  show = 0;
  setTimeout("hide()", 600);
}
function hide()
{
  var el = document.getElementById("channels");
  var iframe_menu = document.getElementById('iframe_menu');
  if (el) {
    if (!show)
    {
      el.style.visibility = "hidden";
      iframe_menu.style.display = "none";
    }
  }
}
function showmenu2()
{
  var el = document.getElementById("back");
  if (el) {
    el.style.visibility = "visible";
    show = 1;
  }
}
function hidemenu2()
{
  show = 0;
  setTimeout("hide2()", 400);
}
function hide2()
{
  var el = document.getElementById("back");
  if (el) {
    if (!show)
    {
      el.style.visibility = "hidden";
    }
  }
}



/**
 * Append this JavaScript to every page
 */
if (document.getElementById('footerMenuContent') != undefined) {
	var footerMenuContentEl = document.getElementById('footerMenuContent');
}

// When there is no footer menu in action in the page, we should not try to execute
// this series of actions.  It is not just pointless but also causes JS errors.
if (typeof footerMenuContentEl != undefined && footerMenuContentEl) {
  window.addOnLoad(padPopupLinks);
  new ypSlideOutMenu('footerMenu', 'up', getMenuLeftPos(), getMenuTopPos(), 140, 155);
  window.addOnResize(repositionMenu);
  initCursorTargets();

  // position main menu pointer needle
  // possible x coords
  var cursorTimeout;

  // init menu pointer
  setMenuCursorPos();
}

function padPopupLinks() {
    var anchorElements = footerMenuContentEl.getElementsByTagName('a');
	for (var i = 0; i < anchorElements.length; i++) {
		var text = anchorElements[i].firstChild.nodeValue;
		anchorElements[i].removeChild( anchorElements[i].firstChild );
		var span = document.createElement('span');
		span.style.position = 'relative';
		span.style.top  = '5px';
		span.style.left = '10px';
		span.appendChild( document.createTextNode(text) );
		anchorElements[i].appendChild( span );
	}
}

function getMenuLeftPos() {
	var targetLeft = DomUtils.getElementLeft( document.getElementById('i18nMoreButton') );
	var x = targetLeft - 67;
	return x;
}

function getMenuTopPos() {
	var cursorTop = DomUtils.getElementTop( document.getElementById('cursorElement') );
	var y = cursorTop - 160;
	return y;
}

function repositionMenu() {
	ypSlideOutMenu.repositionMenu('footerMenu', getMenuLeftPos(), getMenuTopPos());
}

function initCursorTargets() {
	var i18nEl = document.getElementById('i18n');
	var li = i18nEl.getElementsByTagName('li'); // make global
	var cursorEl = document.getElementById('cursorElement');
	var cursorElWidth = 0;
	for ( var i = 0; i < li.length; i++ ) {
		if ( document.all ) { /* IE */
			cursorElWidth += DomUtils.getElementWidth(li[i]) + 15;
		}
		else {
			cursorElWidth += DomUtils.getElementWidth(li[i]);
		}
		if ( i == (li.length - 1) ) break; /* skip more button element */
		window.addEvent(li[i], 'mouseover', setMenuCursorPos, cursorEl, false);
		window.addEvent(li[i], 'mouseout', resetMenuCursorPos, cursorEl, false);
	}
	cursorEl.style.width = cursorElWidth + 'px';
	i18nEl.style.width = cursorElWidth + 'px';
	var moreLangEl = document.getElementById('footerMenuContent');
	window.addEvent(moreLangEl, 'mouseover', hideMenuCursor, document, false);
	window.addEvent(moreLangEl, 'mouseout', resetMenuCursorPos, document, false);
	var moreLangButton = document.getElementById('i18nMoreButton');
	window.addEvent(moreLangButton, 'mouseover', hideMenuCursor, document, false);
	window.addEvent(moreLangButton, 'mouseout', resetMenuCursorPos, document, false);
}

function setMenuCursorPos(e) {
	var cursorElement;
	var targetEl;
	if (e) {
	/* 
	 * event triggered 
	 * e.target ( moz target )
	 * e.srcElement ( ie target )
	 */
		cursorElement = this;
		targetEl = (e.target) ? e.target : (e.srcElement) ? e.srcElement : null;
	}
	else {
		cursorElement = document.getElementById('cursorElement');
		var anchorElements = cursorElement.getElementsByTagName('a');
		for (var i = 0; i < anchorElements.length; i++) {
			if ( anchorElements[i].hreflang == PG_LOCALE ) {
				targetEl = anchorElements[i];
				break;
			}
		}
	}
	var absContainerLeft = DomUtils.getElementLeft(cursorElement);
	var absTargetLeft = DomUtils.getElementLeft(targetEl);
	var targetLeft = absTargetLeft - absContainerLeft;
	var targetWidth = DomUtils.getElementWidth(targetEl);
	// minus anchor left padding
	targetWidth = targetWidth - 5;
	cursorElement.style.backgroundPosition = ( targetLeft + (targetWidth / 2) ) +'px bottom';
	if ( cursorTimeout )
		clearTimeout(cursorTimeout);
}

function resetMenuCursorPos() {
	cursorTimeout = setTimeout('setMenuCursorPos()', 500);
}

function hideMenuCursor(e) {
	var cursorElement = this.getElementById('cursorElement');
	cursorElement.style.backgroundPosition = '-10px bottom';
	
	if ( cursorTimeout )
		clearTimeout(cursorTimeout);
}
