// MM_PopInfo.js
//
// A class to build and display a popup frame.
//
// Copyright (C) 2006-2007 Mixtur Interactive, Inc. All rights reserved.
// http://www.mixtur.com, 1-866-268-3994. Unlicensed use is prohibited.
//
// Mark Eissler, mark@mixtur.com
//
// $Id: MM_PopInfo.js,v 1.2 2007/01/03 23:47:19 mark Exp $
//

/*
 IMPORTANT:  This Mixtur software is supplied to you by Mixtur Interactive, Inc. ("Mixtur")
 in consideration of your agreement to the following terms, and your use, installation, 
 or modification of this Mixtur software constitutes acceptance of these terms.  If you do
 not agree with these terms, please do not use, install, or modify this Mixtur software.
 
 In consideration of your agreement to abide by the following terms, and subject to these 
 terms, Mixtur grants you a personal, non-exclusive license, under MixturÕs copyrights in 
 this original Mixtur software (the "Mixtur Software"), to use, reproduce and modify the
 Mixtur Software.
 
 IMPORTANT:  THIS AGREEMENT DOES NOT PROVIDE FOR NOR DOES IT ALLOW REDISTRIBUTION OF THIS
 MIXTUR SOFTWARE. YOU MAY NOT REDISTRIBUTE THIS SOFTWARE WITH OR WITHOUT MODIFICATIONS.

 Neither the name, trademarks, service marks or logos of Mixtur Interactive, Inc. may be 
 used to endorse or promote products derived from the Mixtur Software without specific 
 prior written permission from Mixtur. Except as expressly stated in this notice, no other
 rights or licenses, express or implied, are granted by Mixtur herein, including but not
 limited to any patent rights that may be infringed by your derivative works or by other
 works in which the Mixtur Software may be incorporated.
 
 The Mixtur Software is provided by Mixtur on an "AS IS" basis.  MIXTUR MAKES NO WARRANTIES, 
 EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, 
 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE MIXTUR SOFTWARE OR ITS 
 USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
 
 IN NO EVENT SHALL MIXTUR BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL 
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 
 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, 
 REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE MIXTUR SOFTWARE, HOWEVER CAUSED AND 
 WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR 
 OTHERWISE, EVEN IF MIXTUR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

function MM_PopInfo(window, id, body, left, top, width) {

    this.window = window;
    this.id = id;
    this.body = body;
    
    // save ref to this instance in the global instances array
    this.instance_id = MM_PopInfo.Instances.length;
    MM_PopInfo.Instances[this.instance_id] = this;
    
    // put css
    var doc = window.document;
    var leftStr = '0px';
    var topStr = '0px';
    var widthStr = '0px';
    
    if(left) leftStr = 'left: ' + left + 'px;';
    if(top) topStr = 'top: ' + top + 'px;';
    if(width) widthStr = 'width: ' + width + 'px;';
    
//     doc.writeln('<style type="text/css">');
//     doc.write('#' + id + ' { position: absolute;' + leftStr + topStr + widthStr + 'background-color: #ff3366; }');
//     doc.writeln('</style>');

    return;
}

// an array of refs to all of this classes' instances.
MM_PopInfo.Instances = new Array();


// init()
//
// Setup remaining params and functions based on browser capability.
//
MM_PopInfo.prototype.init = function() {

    var doc = this.window.document;

    // output the element in a DIV tag
    doc.writeln('<div class="popInfo" >');
    doc.writeln('<div class="popInfo_sub" id="' + this.id + '">');
    doc.writeln('<div>');
    doc.writeln('<div>&nbsp;</div>');
    doc.writeln('<table id="popInfoText"><tr><td><span id="popInfoText">' + this.body + '</span></td></tr></table>');
    doc.writeln('&nbsp;</div>');    
    doc.writeln('</div>');    
    doc.writeln('</div>'); 
    
    // setup data members depending browser support
//     if(document.getElementById && document.getElementById(this.id)) {
	if(bCode == "MOZ" || bCode == "SAF") {
        this.element = document.getElementById(this.id);
        this.element.opacity = 100;
        this.element.fadeStep = 0;          // fade in/out? call setFadeStep() to change
        this.element.fadeInterval = 40;     // change the smoothness of the fade effect
        this.style = this.element.style;
        this.style.Moz = 1;
        this.alpha = 1.0;
        this.alpha.on = 0;
//     } else if (document.all && document.all(this.id)) {
} else if (bCode == "MSIE" && bVers >= 5) {

        // save a reference to the layer object that we just created
        this.element = document.all[this.id];
        this.element.opacity = 100;
        this.element.fadeStep = 0;          // fade in/out? call setFadeStep() to change
        this.element.fadeInterval = 40;     // change the smoothness of the fade effect
        this.style = this.element.style;
        this.style.Exp = 1;
        this.alpha = 100;
        this.alpha.on = 0;
//     } else if (document.layers && document.layers[this.id]) {
	} else if (bCode == "NS") {
        // save a reference to the layer object that we just created
        this.layer = document.layers[objectId];
    }
    
    
    //
    // setup a bunch of accessor functions
    //
    if(this.style) {
    
        // mozilla or exploder
    
        // methods for moving, hiding, stacking, manipulating the MM_PopInfo
        if(this.style.Moz) {
            MM_PopInfo.prototype.moveTo = function(x,y) { this.style.moveTo(x,y); }
            MM_PopInfo.prototype.moveBy = function(x,y) { this.style.moveBy(x,y); }
        } else {
        
            // this should be exploder
            MM_PopInfo.prototype.moveTo = function(x,y) { 
                this.style.pixelLeft = x; 
                this.style.pixelTop = y;
            }
            
            MM_PopInfo.prototype.moveBy = function(x,y) {
                this.style.pixelLeft += x; 
                this.style.pixelTop += y;
            }
        }
        
        MM_PopInfo.prototype.show = function() {
        
            if(!this.element.fadeStep) {
        
                this.style.visibility = "visible";
                this.element.opacity = 100;
                
                return;
            }
        
            // set timer for fadein
            this.fade('in');
            
            return;
        }
        
        MM_PopInfo.prototype.hide = function() { 
            
            if(!this.element.fadeStep) {
        
                this.style.visibility = "hidden";
                this.element.opacity = 0;
                
                return;
            }
        
            // set time for fadeout
            this.fade('out');
            
            return;
        }
        
        MM_PopInfo.prototype.fade = function(inDirection) {
        
            var theElement = this.element;
        
            if ( ! inDirection.match(/^in|out$/) )
                inDirection = theElement.isOut ? 'in' : 'out';
                
            // avoid deadlocks, don't initiate a fade unless we have to
            if ( (inDirection === 'in') && theElement.opacity == 100 ) return false;
            if ( (inDirection === 'out') && theElement.opacity == 0 ) return false;

            if(theElement.isRunning) {
            
                if(theElement.direction == inDirection) return false;
                
                // looks like we're running but the user changed their mind
                //
                // clear the current timer
                clearInterval(theElement.lastFadeInterval);

            }
            
            theElement.direction = inDirection;
            theElement.isRunning = 1;
            theElement.style.visibility = 'visible';
        
            // fire the callback immediately to setup the opacity    
            this._fadeCallback();
        
            // setup the timer    
            theElement.lastFadeInterval = setInterval('MM_PopInfo.Instances['+this.instance_id+']._fadeCallback()', theElement.fadeInterval);            
        
            return;
        }

        MM_PopInfo.prototype._fadeCallback = function() {
        
            var theElement = this.element;
        
            if (theElement.direction === 'out') {
            
                // fade out
            
                if (theElement.opacity < 0) {
                    theElement.opacity = 0;
                    theElement.style.visibility = 'hidden';
        
                    // we're done, clear the interval
                    clearInterval(theElement.lastFadeInterval);
                    
                    theElement.isRunning = 0;
                   
                    return true;
                }
                
                theElement.opacity -= theElement.fadeStep;
                
            } else {
                
                // fade in
            
                if (theElement.opacity > 100) {
                    theElement.opacity = 100;
                    theElement.style.visibility = 'visible';
                    
                    // we're done, clear the interval
                    clearInterval(theElement.lastFadeInterval);
                    
                    theElement.isRunning = 0;
                    
                    return true;
                }

                theElement.opacity += theElement.fadeStep;
            }

            if(this.style.Moz)  {        
                var theNewOpacity = theElement.opacity/100;
                theElement.style.opacity = theNewOpacity;    
           } else {
                var theNewOpacity = theElement.opacity;
                theElement.style.filter = "alpha(opacity="+theNewOpacity+")";    
            }
            
            return;    
        }
        
        MM_PopInfo.prototype.setStackingOrder = function(z) { this.style.visibility.zIndex = z; }
        MM_PopInfo.prototype.setBgColor = function(color) { this.style.bgColor = color; }
        MM_PopInfo.prototype.setBgImage = function(image) { this.style.background.src = image; }
        
        // get methods
        MM_PopInfo.prototype.getStackingOrder = function() { return this.style.zIndex; }
        MM_PopInfo.prototype.isVisible = function() { return this.style.visibility == "visible"; }
        MM_PopInfo.prototype.getWidth = function() { return this.style.width; }
        MM_PopInfo.prototype.getHeight = function() { return this.style.height; }
    
        if(this.style.Moz) {
            MM_PopInfo.prototype.getX = function() { return this.style.left; }
            MM_PopInfo.prototype.getY = function() { return this.style.top; }
        } else {
        
            // this should be exploder
            MM_PopInfo.prototype.getX = function() { return this.style.pixelLeft; }
            MM_PopInfo.prototype.getY = function() { return this.style.pixelTop; }
        }
        
    } else if(this.layer) {
    
        // methods for moving, hiding, stacking, manipulating the MM_PopInfo
        MM_PopInfo.prototype.moveTo = function(x,y) { this.layer.moveTo(x,y); }
        MM_PopInfo.prototype.moveBy = function(x,y) { this.layer.moveBy(x,y); }
        MM_PopInfo.prototype.show = function() { this.layer.visibility = "show"; }
        MM_PopInfo.prototype.hide = function() { this.layer.visibility = "hide"; }
        MM_PopInfo.prototype.setStackingOrder = function(z) { this.layer.visibility.zIndex = z; }
        MM_PopInfo.prototype.setBgColor = function(color) { this.layer.bgColor = color; }
        MM_PopInfo.prototype.setBgImage = function(image) { this.layer.background.src = image; }
        
        // get methods
        MM_PopInfo.prototype.getX = function() { return this.layer.left; }
        MM_PopInfo.prototype.getY = function() { return this.layer.top; }
        MM_PopInfo.prototype.getWidth = function() { return this.layer.width; }
        MM_PopInfo.prototype.getHeight = function() { return this.layer.height; }
        MM_PopInfo.prototype.getStackingOrder = function() { return this.layer.zIndex; }
        MM_PopInfo.prototype.isVisible = function() { return this.layer.visibility == "show"; }
        
    }
    
    return;
}


// setFadeStep()
//
// Set the fade step. If you set it to 0 (the default) fade will be turned off.
// The min value is 0; the max value is 100;
//
MM_PopInfo.prototype.setFadeStep = function(inFadeStep) {

    if(inFadeStep < 0)
        inFadeStep = 0;
    else if(inFadeStep > 100)
        inFadeStep = 100;
        
    if(this.element)
        this.element.fadeStep = inFadeStep;
    
    return;
}


// setFadeInterval()
//
// Set the fade interval. This affects the smoothness of the transition. In
// general, the default (40) is suitable.
//
MM_PopInfo.prototype.setFadeInterval = function(inFadeInterval) {

    inFadeInterval = inFadeInterval > 0 ? inFadeInterval : 50;

    if(this.element.fadeInterval)
        this.element.fadeInterval = inFadeInterval;
    
    return;
}


// update the body
//
// Supply one or more arguments which are HTML strings that are output
// directly into the document.
MM_PopInfo.prototype.setBody = function() {

    if(!this.style && !this.layer) return;

    if(this.style) {
    
        // mozilla or exploder
    
        var body = "";
        for(var i = 0; i < arguments.length; i++)
            body += arguments[i] + "\n";
            
        this.element.innerHTML = body;
    
    } else if(this.layer) {

        for(var i = 0; i < arguments.length; i++)
            theLayer.document.writeln(arguments[i]);
            
        theLayer.document.close();
    }
    
    return;
}


// addEventHandler()
//
// This method registers a handler for the named even on the element. The
// event name argument should be the name of an event handler property, such
// as "onmousedown" or "onkeypress." The event handler is a function that
// takes whatever action is necessary.
//
// The handler will be passed nine arguments:
//
// 1) a reference to the MM_PopInfo object
// 2) a string containing the event type
// 3) the x-coord of the mouse (relative to the MM_PopInfo object)
// 4) the y-coord of the mouse
// 5) the mouse button that was clicked (if any)
// 6) the unicode code of the key pressed
// 7) a bool specifying whether the shift key was down
// 8) a bool specifying whether the control key was down
// 9) a bool specifying whether the alt key was down
//
// Event handlers that are not interested in all these arguments do not
// have to declare them all in their argument lists.
//
MM_PopInfo.prototype.addEventHandler = function(eventName, eventHandler) {

    if(!this.style && !this.layer) return;

    if(this.style) {

        // mozilla or exploder
        if(this.style.Moz) {

             this.element.addEventListener(eventName, eventHandler, false);
        
        } else {

            var popInfoObj = this; // current MM_PopInfo object for use in the nested func.
        
            this.element[eventName] = function() {
            
                var eventObj = popInfoObj.window.event;
                eventObj.cancelBubble = true;
                
                return eventHandler(popInfoObj, eventObj.type, eventObj.x, eventObj.y,
                    eventObj.button, eventObj.keyCode, eventObj.shiftKey,
                    eventObj.ctrlKey, eventObj.altKey);
            }
        }        

    } else if(this.layer) {
    
        // arrange to capture events on this layer
        this.layer.captureEvents(MM_PopInfo._eventmasks[eventName]);
        
        var popInfoObj = this; // current MM_PopInfo object for use in the nested func.
        
        // define an event handler that will invoke the specified handler,
        // and pass it the nine arguments specified above.
        this.layer[eventName] = function(event) {
        
            return eventHandler(popInfoObj, event.type, event.x, event.y,
                event.which, event.which,
                ((event.modifiers & Event.SHIFT_MASK) != 0),
                ((event.modifiers & Event.CTRL_MASK) != 0),
                ((event.modifiers & Event.ALT_MASK) != 0));
                
        }
        
    }        
    
    return;
}


// removeEventHandler()
//
// Unregister the named event handler.
//
MM_PopInfo.prototype.removeEventHandler = function(eventName) {

    if(!this.style && !this.layer) return;

    if(this.style) {
    
        // mozilla or exploder
        
        // mozilla or exploder
        if(this.style.Moz) {
        
            this.element.addEventListener(eventName, false);

        } else {
        
            delete this.element[eventName];
        }
        
    } else if(this.layer) {

        this.layer.releaseEvents(MM_PopInfo._eventmasks[eventName]);
        delete this.layer[eventName];
    }

    
    return;
}

// create eventmasks array only if Netscape 4.
//
if(this.layer) {

    // internal array to map from event name to event type
    MM_PopInfo._eventmasks = {
    
        onabort:Event.ABORT,
        onblur:Event.BLUR,
        onchange:Event.CHANGE,
        onclick:Event.CLICK,
        ondblclick:Event.DBLCLICK,
        ondragdrop:Event.DRAGDROP,
        onerror:Event.ERROR,
        onfocus:Event.FOCUS,
        onkeydown:Event.KEYDOWN,
        onkeypress:Event.KEYPRESS,
        onkeyup:Event.KEYUP,
        onload:Event.LOAD,
        onmousedown:Event.MOUSEDOWN,
        onmousemove:Event.MOUSEMOVE,
        onmouseout:Event.MOUSEOUT,
        onmouseover:Event.MOUSEOVER,
        onmouseup:Event.MOUSEUP,
        onmove:Event.MOVE,
        onreset:Event.RESET,
        onresize:Event.RESIZE,
        onselect:Event.SELECT,
        onsubmit:Event.SUBMIT,
        onunload:Event.UNLOAD
    };
}
