/************************* DivTrigger.js *************************
version 2.1, modified by Jon to fix IE7 overflow bug by manually setting the height of an expanding div rather than assuming setting its width to 100% would suffice.

PURPOSE
Lays a transparent "trigger" div over another "wrapped" div; the "trigger" permits zooming to a predetermined size on mouseover.

ARGUMENTS
All dimensions include "px" unless indicated as Int.
argObj can include (* = required):
    wrappedElement*
    containerElement
    triggerWidth
    expandToWidth
    triggerHeight
    offset (where the trigger lies relative to the wrapped div--usually "center")
    justification ("center", "upper-left", "lower-left", "upper-right", "lower-right", "center-right", "center-left", "center-top", "center-bottom")
    zoomDuration (milliseconds)
    incrementDuration (milliseconds)
    functionAtEnd (eg, function() { alert(this) } )
    functionReturning (eg, function() { alert(this) } )
    functionOnClick (eg, function() { alert(this) } )

TRIGGER STYLES
You set the other style properties in a CSS class called zoomTrigger.
Give this class a low opacity (eg, .05) or IE6 will bubble incorrectly to the underlying div.

WRAPPED STYLES
You will probably want to give the div to zoom an absolute position.
If you want an image in that div to zoom, set its width to that of the wrapped div, eg ".div-to-expand img { width: 100% }"
You need to set the positions of the wrapped divs directly in HTML, or you can't refer to them in this constructor.

UPGRADE
Future versions should permit setting animation parameters (eg, opacity and increment of "20") via argObj.
**************************************/
function ZoomTrigger(argObj) {
    // Create the trigger div that overlays the div to expand.
    this.htmlElement = document.createElement('div') ;
    (typeof argObj.containerElement == "undefined" )? document.body.appendChild(this.htmlElement) : argObj.containerElement.appendChild(this.htmlElement) ;
    // Define handles.
    this.htmlElement.JSObject = this ;
    this.htmlElement.id = "wrapper-for_" + argObj.wrappedElement.id ;
    this.htmlElement.wrappedElement = argObj.wrappedElement ; // The image div inside the rollover div.
    this.htmlElement.wrappedElement.triggerElement = this.htmlElement ;
    // Set the target sizes for the wrapped div's expansion and contraction. Default value is arbitrary.
    this.htmlElement.shrinkToWidth =  (typeof argObj.shrinkToWidth == "undefined" )? this.htmlElement.wrappedElement.style.width  : argObj.shrinkToWidth ;
    this.htmlElement.shrinkToHeight =  (typeof argObj.shrinkToHeight == "undefined" )? this.htmlElement.wrappedElement.style.height  : argObj.shrinkToHeight ;
    this.htmlElement.expandToWidth =  (typeof argObj.expandToWidth == "undefined" )? "300px" : argObj.expandToWidth ;
    this.htmlElement.aspectRatio = parseInt(this.htmlElement.wrappedElement.style.width) / parseInt(this.htmlElement.wrappedElement.style.height) ;
    this.htmlElement.expandToHeight = parseInt( parseInt(this.htmlElement.expandToWidth) / this.htmlElement.aspectRatio ) + "px" ;
    // Size the trigger div. Default values are arbitrary.
    this.htmlElement.style.width = (typeof argObj.triggerWidth == "undefined" )? this.htmlElement.expandToWidth : argObj.triggerWidth ;
    this.htmlElement.style.height = (typeof argObj.triggerHeight == "undefined" )? this.htmlElement.expandToHeight : argObj.triggerHeight ;
    // Style the trigger div via the CSS class zoomTrigger.
    this.htmlElement.className = "zoom-trigger" ;
    this.htmlElement.style.zIndex = 100 ;
    // Position the trigger div.
    this.htmlElement.offset =  (typeof argObj.offset == "undefined" )? "center" : argObj.offset ;
    this.htmlElement.style.position = "absolute" ;
    var triggerWidthInt = parseInt(this.htmlElement.style.width) ;
    // DEBUG: jon changed these from variables to properties so they could be referenced later.
    this.htmlElement.wrappedElement.wrappedLeftInt = parseInt(this.htmlElement.wrappedElement.style.left) ;
    this.htmlElement.wrappedElement.wrappedWidthInt = parseInt(this.htmlElement.wrappedElement.style.width) ;
    var triggerHeightInt = parseInt(this.htmlElement.style.height) ;
    this.htmlElement.wrappedElement.wrappedTopInt = parseInt(this.htmlElement.wrappedElement.style.top) ;
    this.htmlElement.wrappedElement.wrappedHeightInt = parseInt(this.htmlElement.wrappedElement.style.height) ;
    switch (this.htmlElement.offset) { // I don't think this will get used that often, so I didn't finish many options here. UPGRADE: It could also be used to offset by particular px values.
        case "center" :
            this.htmlElement.style.left = this.htmlElement.wrappedElement.wrappedLeftInt + this.htmlElement.wrappedElement.wrappedWidthInt/2 - triggerWidthInt/2 + "px" ;
            this.htmlElement.style.top = this.htmlElement.wrappedElement.wrappedTopInt + this.htmlElement.wrappedElement.wrappedHeightInt/2 - triggerHeightInt/2 + "px" ;
            break ;
        case "upper-left" :
            this.htmlElement.style.top = this.htmlElement.wrappedElement.style.top ;
            this.htmlElement.style.left = this.htmlElement.wrappedElement.style.left ;
            break ;
        case "upper-right" :
            this.htmlElement.style.left = this.htmlElement.wrappedElement.wrappedLeftInt + this.htmlElement.wrappedElement.wrappedWidthInt - triggerWidthInt + "px" ;
            this.htmlElement.style.top = this.htmlElement.wrappedElement.style.top ;
            break ;
    }
    // Calculate animation parameters. Note that it's crucial not to reduce the increments to integers too soon.
    this.htmlElement.justification =  (typeof argObj.justification == "undefined" )? "center" : argObj.justification ;
    this.htmlElement.zoomDuration =  (typeof argObj.zoomDuration == "undefined" )? 300 : argObj.zoomDuration ; // Was 500.
    this.htmlElement.incrementDuration =  (typeof argObj.incrementDuration == "undefined" )? 50 : argObj.incrementDuration ; // Was 50.
    this.htmlElement.numberOfSteps = parseInt( this.htmlElement.zoomDuration / this.htmlElement.incrementDuration ) ;
    // Pre-calculate and populate an array with all the widths required for the zoom.
    this.htmlElement.zoomWidthDifference = parseInt(this.htmlElement.expandToWidth) - parseInt(this.htmlElement.shrinkToWidth) ;
    this.htmlElement.zoomWidthIncrementFlo =  this.htmlElement.zoomWidthDifference / this.htmlElement.numberOfSteps-1 ; // Also used below for centering. Floating point number.
    this.htmlElement.zoomWidthArray = new Array() ;
    for( var stepNum = 0 ; stepNum < this.htmlElement.numberOfSteps ; stepNum++ ){
        this.htmlElement.zoomWidthArray[stepNum] = Math.round(    parseInt(this.htmlElement.shrinkToWidth) + (  ( this.htmlElement.zoomWidthIncrementFlo ) * stepNum  )    ) ;
    }
    this.htmlElement.zoomHeightIncrementFlo = this.htmlElement.zoomWidthIncrementFlo * (1/this.htmlElement.aspectRatio) ; 
    aspect = this.htmlElement.aspectRatio ; debug("aspect")
	zoomHeightIncrementFlo =	this.htmlElement.zoomHeightIncrementFlo ; debug("zoomHeightIncrementFlo") ;
    // Opacities aren't as fussy as widths, so you don't need an array with all the opacities required for the zoom.
    // UPGRADE: Enable zoom to sub-100% opacity.
    if (browsers.ie) {
        this.htmlElement.opacityDifference = 100 - eval(this.htmlElement.wrappedElement.filters.alpha.opacity) ;
        this.htmlElement.opacityIncrement = parseInt( this.htmlElement.opacityDifference / this.htmlElement.numberOfSteps ) ;
    }
    else {
        this.htmlElement.opacityDifference = 1 - eval(this.htmlElement.wrappedElement.style.opacity) ;
        opacity_original = this.htmlElement.wrappedElement.style.opacity ; debug("opacity_original")

        this.htmlElement.opacityIncrement = this.htmlElement.opacityDifference / this.htmlElement.numberOfSteps ;
        opacity_increment = this.htmlElement.opacityIncrement ; debug("opacity_increment")
    }
    // Rolling over this trigger div should zoom the wrapped div.
    this.htmlElement.onmouseover = function() { startExpansionLoop(this) ; } ;
    this.htmlElement.onmouseout =  function() { startContractionLoop(this) ; } ;
    // These flags keep weird loops from happening.
    this.htmlElement.wrappedElement.isExpanding = false ;
    this.htmlElement.wrappedElement.isContracting = false ;
    // Add function call for various stages of the zoom.
    this.htmlElement.functionAtEnd = (argObj.functionAtEnd)? argObj.functionAtEnd : "" ;
    this.htmlElement.functionReturning = (argObj.functionReturning)? argObj.functionReturning : "" ;
    this.htmlElement.onclick = (argObj.functionOnClick)? argObj.functionOnClick : "" ;
}
function startExpansionLoop( triggerMousedOnEle ) { // The arg is the overlay div that was moused over or off.
//     gonnaExpandTo = triggerMousedOnEle.expandToWidth; debug( "gonnaExpandTo" )
    if (triggerMousedOnEle.wrappedElement.isExpanding || triggerMousedOnEle.wrappedElement.isContracting) {
         // Don't interfere with existing zooms.
//         expansionNotTriggeredFor = triggerMousedOnEle.id; debug("expansionNotTriggeredFor") ;
    }
    else {
        triggerMousedOnEle.wrappedElement.isExpanding = true ;
//         triggerEleExpanding_id = triggerMousedOnEle.id ; debug("triggerEleExpanding_id") ;
        triggerMousedOnEle.stepNum = 0 ;
        triggerMousedOnEle.expandLoop = setInterval(   function() {  expandDivABit(triggerMousedOnEle) } , triggerMousedOnEle.incrementDuration ) ; // 50    ) ;
     }
}
function startContractionLoop( triggerMousedOffEle ) { // The arg is the overlay div that was moused over or off.
//     gonnaContractTo = triggerMousedOffEle.shrinkToWidth ; debug("gonnaContractTo")
    if (triggerMousedOffEle.wrappedElement.isContracting) {  // Don't interfere with existing contraction.
//         contractionNotTriggeredFor = triggerMousedOffEle.id; debug("contractionNotTriggeredFor") ;
    }
     else {
         if (triggerMousedOffEle.expandLoop) { // Abort any expansions in process.
             clearInterval(triggerMousedOffEle.expandLoop) ;
             triggerMousedOffEle.wrappedElement.isExpanding = false ;
        }
        // Begin contraction.
        triggerMousedOffEle.wrappedElement.isContracting = true ;
//         triggerEleContracting_id = triggerMousedOffEle.id ; debug("triggerEleContracting_id") ;
        triggerMousedOffEle.shrinkLoop = setInterval(   function() {  contractDivABit(triggerMousedOffEle) } , triggerMousedOffEle.incrementDuration ) ; //50    ) ;
        if (triggerMousedOffEle.functionReturning) eval( triggerMousedOffEle.functionReturning() ) ;
    }
}
function expandDivABit(triggerExpandingEle) {
    triggerExpandingEle.stepNum++
    if (triggerExpandingEle.stepNum >= triggerExpandingEle.numberOfSteps) { // Stop expanding.
        clearInterval(triggerExpandingEle.expandLoop) ;
        triggerExpandingEle.wrappedElement.isExpanding = false ;
        if (browsers.ie) {
            triggerExpandingEle.wrappedElement.filters.alpha.opacity = 100 ;
        }
        else {
            triggerExpandingEle.wrappedElement.style.opacity = 1 ; // DEBUG: added this.
        }
        if (triggerExpandingEle.functionAtEnd) eval( triggerExpandingEle.functionAtEnd() ) ;
    }
    else { // Continue expanding.
        triggerExpandingEle.wrappedElement.style.width = triggerExpandingEle.zoomWidthArray[triggerExpandingEle.stepNum] + "px" ;
        triggerExpandingEle.wrappedElement.style.height = parseInt( parseInt(triggerExpandingEle.wrappedElement.style.width) * triggerExpandingEle.aspectRatio ) + "px" ;
        switch (triggerExpandingEle.justification ) {
            case "center" :
                triggerExpandingEle.wrappedElement.style.left = parseInt( triggerExpandingEle.wrappedElement.style.left ) - parseInt(triggerExpandingEle.zoomWidthIncrementFlo/2) + "px" ;
                triggerExpandingEle.wrappedElement.style.top = parseInt( triggerExpandingEle.wrappedElement.style.top ) - parseInt(triggerExpandingEle.zoomHeightIncrementFlo/2) + "px" ;
                break ;
            case "upper-right" :
                triggerExpandingEle.wrappedElement.style.left = parseInt( triggerExpandingEle.wrappedElement.style.left ) - parseInt(triggerExpandingEle.zoomWidthIncrementFlo) + "px" ;
                break ;
            case "lower-left" :
                triggerExpandingEle.wrappedElement.style.top = parseInt( triggerExpandingEle.wrappedElement.style.top ) - parseInt(triggerExpandingEle.zoomHeightIncrementFlo) + "px" ;
                break ;
            case "lower-right" :
                triggerExpandingEle.wrappedElement.style.left = parseInt( triggerExpandingEle.wrappedElement.style.left ) - parseInt(triggerExpandingEle.zoomWidthIncrementFlo) + "px" ;
                triggerExpandingEle.wrappedElement.style.top = parseInt( triggerExpandingEle.wrappedElement.style.top ) - parseInt(triggerExpandingEle.zoomHeightIncrementFlo) + "px" ;
                break ;
            case "upper-left" :
                break ; // Divs naturally expand from this corner.
            case "center-right" :
                triggerExpandingEle.wrappedElement.style.left = parseInt( triggerExpandingEle.wrappedElement.style.left ) - parseInt(triggerExpandingEle.zoomWidthIncrementFlo) + "px" ;
                triggerExpandingEle.wrappedElement.style.top = parseInt( triggerExpandingEle.wrappedElement.style.top ) - parseInt(triggerExpandingEle.zoomHeightIncrementFlo/2) + "px" ;
                break ;
            case "center-left" :
                triggerExpandingEle.wrappedElement.style.left = parseInt( triggerExpandingEle.wrappedElement.style.left ) - parseInt(triggerExpandingEle.zoomWidthIncrementFlo) + "px" ;
                triggerExpandingEle.wrappedElement.style.top = parseInt( triggerExpandingEle.wrappedElement.style.top ) - parseInt(triggerExpandingEle.zoomHeightIncrementFlo/2) + "px" ;
                break ;
            case "center-top" :
                triggerExpandingEle.wrappedElement.style.left = parseInt( triggerExpandingEle.wrappedElement.style.left ) - parseInt(triggerExpandingEle.zoomWidthIncrementFlo/2) + "px" ;
                break ;
            case "center-bottom" :
                triggerExpandingEle.wrappedElement.style.left = parseInt( triggerExpandingEle.wrappedElement.style.left ) - parseInt(triggerExpandingEle.zoomWidthIncrementFlo/2) + "px" ;
                triggerExpandingEle.wrappedElement.style.top = parseInt( triggerExpandingEle.wrappedElement.style.top ) - parseInt(triggerExpandingEle.zoomHeightIncrementFlo) + "px" ;
                break ;
        }
        if (browsers.ie) {
            triggerExpandingEle.wrappedElement.filters.alpha.opacity = eval( triggerExpandingEle.wrappedElement.filters.alpha.opacity ) + (triggerExpandingEle.opacityIncrement ) ; // Note that a crossbrowser opacityIncrement (100% v. 1) was normalized above.
        }
        else {
            triggerExpandingEle.wrappedElement.style.opacity = eval( triggerExpandingEle.wrappedElement.style.opacity ) + triggerExpandingEle.opacityIncrement  ;
        }
    }
    // ele_id=triggerEle.wrappedElement.id;debug("ele_id")
        // ele_isExpanding = triggerEle.wrappedElement.isExpanding ; debug("ele_isExpanding")
}
function contractDivABit(triggerContractingEle) {
    triggerContractingEle.stepNum--
    if (triggerContractingEle.stepNum <= 0) { // Stop shrinking.
        // debug("'gonna stop shrinking now'")
        clearInterval(triggerContractingEle.shrinkLoop) ;
        triggerContractingEle.wrappedElement.isContracting = false ;
        // DEBUG: Jon added manual assignments below.
        triggerContractingEle.wrappedElement.style.left = triggerContractingEle.wrappedElement.wrappedLeftInt + "px" ;
        triggerContractingEle.wrappedElement.style.width = triggerContractingEle.wrappedElement.wrappedWidthInt + "px" ;
        triggerContractingEle.wrappedElement.style.top = triggerContractingEle.wrappedElement.wrappedTopInt + "px" ;
        triggerContractingEle.wrappedElement.style.height = triggerContractingEle.wrappedElement.wrappedHeightInt + "px" ;
        // debug("'stopped shrinking!'")
        // var contractionStoppedFor = triggerContractingEle.id ; debug("contractionStoppedFor") ;
    }
    else { // Continue shrinking.
        triggerContractingEle.wrappedElement.style.width = triggerContractingEle.zoomWidthArray[triggerContractingEle.stepNum] + "px" ;
        switch (triggerContractingEle.justification ) {
            case "center" :
                triggerContractingEle.wrappedElement.style.left = parseInt( triggerContractingEle.wrappedElement.style.left ) + parseInt(triggerContractingEle.zoomWidthIncrementFlo/2) + "px" ;
                triggerContractingEle.wrappedElement.style.top = parseInt( triggerContractingEle.wrappedElement.style.top ) + parseInt(triggerContractingEle.zoomHeightIncrementFlo/2) + "px" ;
                break ;
            case "upper-right" :
                triggerContractingEle.wrappedElement.style.left = parseInt( triggerContractingEle.wrappedElement.style.left ) + parseInt(triggerContractingEle.zoomWidthIncrementFlo) + "px" ;
                break ;
            case "lower-left" :
                triggerContractingEle.wrappedElement.style.top = parseInt( triggerContractingEle.wrappedElement.style.top ) + parseInt(triggerContractingEle.zoomHeightIncrementFlo) + "px" ;
                break ;
            case "lower-right" :
                triggerContractingEle.wrappedElement.style.left = parseInt( triggerContractingEle.wrappedElement.style.left ) + parseInt(triggerContractingEle.zoomWidthIncrementFlo) + "px" ;
                triggerContractingEle.wrappedElement.style.top = parseInt( triggerContractingEle.wrappedElement.style.top ) + parseInt(triggerContractingEle.zoomHeightIncrementFlo) + "px" ;
                break ;
            case "upper-left" :
                break ; // Divs naturally expand from this corner.
            case "center-right" :
                triggerContractingEle.wrappedElement.style.left = parseInt( triggerContractingEle.wrappedElement.style.left ) + parseInt(triggerContractingEle.zoomWidthIncrementFlo) + "px" ;
                triggerContractingEle.wrappedElement.style.top = parseInt( triggerContractingEle.wrappedElement.style.top ) + parseInt(triggerContractingEle.zoomHeightIncrementFlo/2) + "px" ;
                break ;
            case "center-left" :
                triggerContractingEle.wrappedElement.style.left = parseInt( triggerContractingEle.wrappedElement.style.left ) + parseInt(triggerContractingEle.zoomWidthIncrementFlo) + "px" ;
                triggerContractingEle.wrappedElement.style.top = parseInt( triggerContractingEle.wrappedElement.style.top ) + parseInt(triggerContractingEle.zoomHeightIncrementFlo/2) + "px" ;
                break ;
            case "center-top" :
                triggerContractingEle.wrappedElement.style.left = parseInt( triggerContractingEle.wrappedElement.style.left ) + parseInt(triggerContractingEle.zoomWidthIncrementFlo/2) + "px" ;
                break ;
            case "center-bottom" :
                triggerContractingEle.wrappedElement.style.left = parseInt( triggerContractingEle.wrappedElement.style.left ) + parseInt(triggerContractingEle.zoomWidthIncrementFlo/2) + "px" ;
                triggerContractingEle.wrappedElement.style.top = parseInt( triggerContractingEle.wrappedElement.style.top ) + parseInt(triggerContractingEle.zoomHeightIncrementFlo) + "px" ;
                break ;
        }
        if (browsers.ie) {
            triggerContractingEle.wrappedElement.filters.alpha.opacity = eval( triggerContractingEle.wrappedElement.filters.alpha.opacity ) - (triggerContractingEle.opacityIncrement) ; // WAS .08
        }
        else {
            triggerContractingEle.wrappedElement.style.opacity = eval( triggerContractingEle.wrappedElement.style.opacity ) - triggerContractingEle.opacityIncrement ;
        }
    }
    // ele_id=triggerEle.wrappedElement.id;debug("ele_id")
    // ele_isExpanding = triggerEle.wrappedElement.isExpanding ; debug("ele_isExpanding")
}

