﻿
var _peekBox = new PeekBox("_peekBox");

function onPeekableMouseOver(item, itemKey, orientation, enablePointer, boxWidth, boxHeight, type, verticalOrientation){
    if(_peekBox == null) return;
    _peekBox.handleMouseOver(item, itemKey, orientation, enablePointer, boxWidth, boxHeight, type, verticalOrientation);
}

function PeekBox(variableName, id){
    this._variableName = variableName;
    if(id == null) { id = "1" };
    this._id = id;
    this._built = false;
    this._itemKey = null;
    this._mainDiv = null;
    this._borderDiv = null;
    this._contentsDiv = null;
    this._leftPointerDiv = null;
    this._rightPointerDiv = null;
    this._boxShadowDiv = null;
    this._shadowDiv_TM = null;
    this._shadowDiv_TR = null;
    this._shadowDiv_ML = null;
    this._shadowDiv_MM = null;
    this._shadowDiv_MR = null;
    this._shadowDiv_BL = null;
    this._shadowDiv_BM = null;
    this._shadowDiv_BR = null;
    this._boxPaddingTop = 8;
    this._boxPaddingBottom = 8;
    this._boxPaddingLeft = 8;
    this._boxPaddingRight = 8;
    this._boxOrientationDefault = "right";
    this._pointerOrientation = "left";  // "left" or "right" for now
    this._verticalOrientationDefault = "bottom";
    this._verticalOrientation = "bottom";
    this._pointerLocation = new Point(0, 0);
    this._boxLocation = new Point(0, 0);
    this._boxSize = new Size(400, 300);
    this._boxSizeDefault = new Size(300, 250);
    this._maxPointerDistanceX = 80;
    this._minPointerDistanceX = 15;
    this._boxPointerPaddingTop = 20;
    this._boxPointerPaddingBottom = 20;
    this._target = null;
    this._targetRectangle = new Rectangle(0, 0, 0, 0);
    this._boxLockGrid = new LockGrid(200, 400, 0, 300);
    this._contentsCache = new Array();
    this._enableDropShadow = true;
    this._dropShadowOffsetX = 10;
    this._dropShadowOffsetY = 10;
    this._hideDelay = 500;      //milliseconds
    this._showDelay = 0;      //milliseconds
    this._hideTimeout = null;
    this._showTimeout = null;
    this._boxIsVisible = false;
    this._boxIsLoaded = false;
    this._enablePointerDefault = true;
    this._enablePointer = true;
    this._isBoxMouseOver = false;
    this._enableTransparentPNGs = true;             // todo, depends on browser
    this._leftPointerImageOffset = new Point(20, 15);   // location of pointer wrt the pointer image
    this._rightPointerImageOffset = new Point(245, 15); // location of pointer wrt the pointer image
    this._delayedShowArgs = new Array();
}
PeekBox.prototype.handleMouseOver = function(item, itemKey, orientation, enablePointer, boxWidth, boxHeight, type, verticalOrientation){
    if(this._showDelay == null || this._showDelay == 0){
        this.handleMouseOverNow(item, itemKey, orientation, enablePointer, boxWidth, boxHeight, type, verticalOrientation);
    }else{
        this.clearShowTimeout();    // reset the timer
        if(this._boxIsVisible){
            this.handleMouseOverNow(item, itemKey, orientation, enablePointer, boxWidth, boxHeight, type, verticalOrientation);
        }else{
            var me = this;
            item.onmouseout = function(){ me.clearShowTimeout(); }
            this._delayedShowArgs[0] = item;
            this._delayedShowArgs[1] = itemKey;
            this._delayedShowArgs[2] = orientation;
            this._delayedShowArgs[3] = enablePointer;
            this._delayedShowArgs[4] = boxWidth;
            this._delayedShowArgs[5] = boxHeight;
            this._delayedShowArgs[6] = type;
            this._delayedShowArgs[7] = verticalOrientation;
            this._showTimeout = setTimeout(this._variableName + ".handleMouseOverDelayed();", this._showDelay, "javascript");
        }
    }
}
PeekBox.prototype.handleMouseOverDelayed = function(){
    if(this._showTimeout == null) return;
    this.clearShowTimeout();
    this.handleMouseOverNow(this._delayedShowArgs[0], this._delayedShowArgs[1], this._delayedShowArgs[2], this._delayedShowArgs[3], this._delayedShowArgs[4], this._delayedShowArgs[5], this._delayedShowArgs[6], this._delayedShowArgs[7]);
}
PeekBox.prototype.handleMouseOverNow = function(item, itemKey, orientation, enablePointer, boxWidth, boxHeight, type, verticalOrientation){
    if(orientation == null){ orientation = this._boxOrientationDefault; }
    if(verticalOrientation == null){ verticalOrientation = this._verticalOrientationDefault; }
    this._verticalOrientation = verticalOrientation;
    if(enablePointer == null){ enablePointer = this._enablePointerDefault; }
    if(boxWidth == null){ boxWidth = this._boxSizeDefault.width; }
    if(boxHeight == null){ boxHeight = this._boxSizeDefault.height; }
    this._boxSize.width = boxWidth + this._boxPaddingLeft + this._boxPaddingRight;
    this._boxSize.height = boxHeight + this._boxPaddingTop + this._boxPaddingBottom;
    this._enablePointer = enablePointer;
    this._target = item;
    var me = this;
    this._target.onmouseout = function(e){ me.onTargetMouseOut(e); }
    this.registerPeekBoxTarget(item);
    var position = GetElementPosition(item);
    this._targetRectangle.x = position.x;
    this._targetRectangle.y = position.y;
    this._targetRectangle.width = position.width;
    this._targetRectangle.height = position.height;
    if(type == null){ type = "service"; }
    this._type = type;
    //reverse the orientation to get pointerOrientation
    switch(orientation){
        case "left":
            this._pointerOrientation = "right";
            break;
        case "right":
            this._pointerOrientation = "left";
            break;
        default:
            break;
    }
    this.show(itemKey);
}
PeekBox.prototype.onMainDivMouseOver = function(e){
    //this.clearHideTimeout();
}
PeekBox.prototype.onBoxMouseOver = function(e){
    // this is in case the the mouse goes off the box and then back on within the delay period
    //if(!this._isBoxMouseOver){
        this._isBoxMouseOver = true;
        this.clearHideTimeout();
        this.clearShowTimeout();
    //}
}
PeekBox.prototype.onBoxMouseOut = function(e){
    if(!this._built) return;
    if (!e) var e = window.event;
	var tg = (window.event) ? e.srcElement : e.target;
	var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
	if(tg == this._target && isDOMAncestor(this._mainDiv, reltg)) return;
	if(isDOMAncestor(this._borderDiv, reltg)) return;
	this.clearShowTimeout();
    this._isBoxMouseOver = false;
	this.waitHide();
	if(this._target != null){
	    this._target.onmouseout = null;
	    this._target = null;
	}
}
PeekBox.prototype.onTargetMouseOut = function(e){
    if(!this._built) return;
    if (!e) var e = window.event;
	var tg = (window.event) ? e.srcElement : e.target;
	var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
	if(tg == this._target && isDOMAncestor(this._mainDiv, reltg)) return;
	if(isDOMAncestor(this._borderDiv, reltg)) return;
	this.clearShowTimeout();
	this.waitHide();
	if(this._target != null){
	    this._target.onmouseout = null;
	    this._target = null;
	}
}
PeekBox.prototype.show = function(itemKey){
    this.clearHideTimeout();
    this.clearContents();
    if(!this._built){
        this.build();
        this.clearContents();
    }
    this.updatePositions();
    this._mainDiv.style.display = "block";
    this._mainDiv.style.visibility = "visible";
    this._boxIsVisible = true;
    if(this._itemKey != itemKey){
        // load the data
        this._itemKey = itemKey;
        this.loadContents(itemKey);
    }
}
PeekBox.prototype.waitHide = function(){
    if(this._hideTimout != null) return;
    this._hideTimeout = setTimeout(this._variableName + ".hide();", this._hideDelay, "javascript");
}
PeekBox.prototype.hide = function(){
    if(!this._built) return;
    if(this._hideTimout != null) return;
    this.clearContents();
    this._mainDiv.style.visibility = "hidden";
    this._mainDiv.style.display = "none";
    this._boxIsVisible = false;
}
PeekBox.prototype.clearShowTimeout = function(){
    if(this._showTimeout == null) return;
    clearTimeout(this._showTimeout);
    this._showTimeout = null;
}
PeekBox.prototype.clearHideTimeout = function(){
    if(this._hideTimeout == null) return;
    clearTimeout(this._hideTimeout);
    this._hideTimeout = null;
}
PeekBox.prototype.clearContents = function(){
    this._boxIsLoaded = false;
    this._itemKey = null;
    if(!this._built) return;
    //this.setContents("loading...");
    this._contentsDiv.innerHTML = "loading...";
}
PeekBox.prototype.setContents = function(html){
    if(!this._built) return;
    this._contentsDiv.innerHTML = html;
    this._boxIsLoaded = true;
}
PeekBox.prototype.loadContents = function(itemKey){
    if(!this._built) return;
    if(this._contentsCache[itemKey] == null){
        var me = this;
        if(this._type == "service"){
            PeekBoxService.GetPeekBoxResult(itemKey, function(result){me.succeededCallback(result);}, function(error, userContext, methodName){me.failedCallback(error, userContext, methodName);});  
        }else{
            if(this._type == "swf"){
                var html = getLoadFlashHtml( "", this._itemKey, "#000000", this._boxSize.width-16, this._boxSize.height-16 );
                this._contentsCache[itemKey] = html;
                this.setContents(this._contentsCache[itemKey]);
            }
        }
    }else{
        this.setContents(this._contentsCache[itemKey]);
    }      
}
PeekBox.prototype.succeededCallback = function(result){
    if(result == null) return;
    if(this._contentsCache[result.ItemKey] != null) return;
    var html = "";
    if(result.HtmlFromJavaScript != null && result.HtmlFromJavaScript != ""){
        html = eval(result.HtmlFromJavaScript);
    }else{
        if(result.SwfFile != null && result.SwfFile != ""){
            alert(result.SwfFile);
        }else{
            html = result.Html;
        }
    }
    if(result.JavaScript != null && result.JavaScript != ""){
        eval(result.JavaScript);
    }
    this._contentsCache[result.ItemKey] = html;
    if(this._itemKey == result.ItemKey && this._boxIsVisible && !this._boxIsLoaded){
        this.setContents(html);
    }
}
PeekBox.prototype.failedCallback = function(error, userContext, methodName){
}
PeekBox.prototype.build = function(){
    var me = this;
    this._mainDiv = document.getElementById(this.getID("main"));
    this._borderDiv = document.getElementById(this.getID("border"));
    this._contentsDiv = document.getElementById(this.getID("contents"));
    this._leftPointerDiv = document.getElementById(this.getID("leftPointer"));
    this._rightPointerDiv = document.getElementById(this.getID("rightPointer"));
    this._boxShadowDiv = document.getElementById(this.getID("boxShadow"));
    this._shadowDiv_TM = document.getElementById(this.getID("shadowTM"));
    this._shadowDiv_TR = document.getElementById(this.getID("shadowTR"));
    this._shadowDiv_ML = document.getElementById(this.getID("shadowML"));
    this._shadowDiv_MM = document.getElementById(this.getID("shadowMM"));
    this._shadowDiv_MR = document.getElementById(this.getID("shadowMR"));
    this._shadowDiv_BL = document.getElementById(this.getID("shadowBL"));
    this._shadowDiv_BM = document.getElementById(this.getID("shadowBM"));
    this._shadowDiv_BR = document.getElementById(this.getID("shadowBR"));
    if(this._mainDiv == null || this._borderDiv == null || this._contentsDiv == null || this._leftPointerDiv == null || this._rightPointerDiv == null){
        //alert("unable to build");
    }else{
        // attach events
        this._mainDiv.onmouseover = function(e){ me.onMainDivMouseOver(e); } 
        this._borderDiv.onmouseover = function(e){ me.onBoxMouseOver(e); } 
        this._borderDiv.onmouseout = function(e){ me.onBoxMouseOut(e); }
        this._built = true;
    }
}
PeekBox.prototype.updatePositions = function(){
   // the box locks to grid
   if(this._enablePointer){
       switch(this._pointerOrientation){
            case "left":
               this._pointerLocation.x = this._targetRectangle.x + this._targetRectangle.width + 10;
               this._pointerLocation.y = this._targetRectangle.y + 10;
               this._boxLocation.x = this._pointerLocation.x + 40;
               this._boxLocation.y = this._pointerLocation.y - 20;
               this._boxLockGrid.adjustPoint(this._boxLocation);
               while((this._boxLocation.x - this._maxPointerDistanceX) > this._pointerLocation.x){ this._boxLockGrid.moveX(this._boxLocation, -0.25); }
               while((this._boxLocation.x - this._minPointerDistanceX) < this._pointerLocation.x){ this._boxLockGrid.moveX(this._boxLocation, 0.25); }
               while((this._boxLocation.y + this._boxPointerPaddingTop) > this._pointerLocation.y){ this._boxLockGrid.moveY(this._boxLocation, -0.25); }
               while((this._boxLocation.y + this._boxSize.height - this._boxPointerPaddingBottom) < this._pointerLocation.y){ this._boxLockGrid.moveY(this._boxLocation, 0.25); }
               break;
            case "right":
               this._pointerLocation.x = this._targetRectangle.x - 10;
               this._pointerLocation.y = this._targetRectangle.y + 10;
               this._boxLocation.x = this._pointerLocation.x - this._boxSize.width - 40;
               this._boxLocation.y = this._pointerLocation.y - 20;
               this._boxLockGrid.adjustPoint(this._boxLocation);
               while((this._boxLocation.x + this._boxSize.width + this._maxPointerDistanceX) < this._pointerLocation.x){ this._boxLockGrid.moveX(this._boxLocation, 0.25); }
               while((this._boxLocation.x + this._boxSize.width + this._minPointerDistanceX) > this._pointerLocation.x){ this._boxLockGrid.moveX(this._boxLocation, -0.25); }
               while((this._boxLocation.y + this._boxPointerPaddingTop) > this._pointerLocation.y){ this._boxLockGrid.moveY(this._boxLocation, -0.25); }
               while((this._boxLocation.y + this._boxSize.height - this._boxPointerPaddingBottom) < this._pointerLocation.y){ this._boxLockGrid.moveY(this._boxLocation, 0.25); }
               break;
       }
   }else{
      switch(this._pointerOrientation){
            case "left":
               this._boxLocation.x = this._targetRectangle.x + this._targetRectangle.width + 5;
               //this._boxLocation.y = this._targetRectangle.y + 5;
               //this._boxLockGrid.adjustPoint(this._boxLocation);
               break;
            case "right":
               this._boxLocation.x = this._targetRectangle.x - 5 - this._boxSize.width;
               //this._boxLocation.y = this._targetRectangle.y + 5;
               //this._boxLockGrid.adjustPoint(this._boxLocation);
               break;
       }
       switch(this._verticalOrientation){
            case "top":
                this._boxLocation.y = this._targetRectangle.y - this._boxSize.height - 5;
                break;
            case "bottom":
                this._boxLocation.y = this._targetRectangle.y + 5;
            
                break;
       }
   }
   this.setPositions(this._boxLocation.x, this._boxLocation.y, this._boxSize.width, this._boxSize.height, this._pointerLocation.x, this._pointerLocation.y, this._pointerOrientation, this._enablePointer);
}
PeekBox.prototype.getID = function(type){
    switch(type){
        case "main":
            return "pbd_" + this._id + "_main";
        case "border":
            return "pbd_" + this._id + "_border";
        case "contents":
            return "pbd_" + this._id + "_contents";
        case "leftPointer":
            return "pbd_" + this._id + "_leftPointer";
        case "rightPointer":
            return "pbd_" + this._id + "_rightPointer";
        case "boxShadow":
            return "pbd_" + this._id + "_boxShadow";
        case "shadowTM":
            return "pbd_" + this._id + "_tm";
        case "shadowTR":
            return "pbd_" + this._id + "_tr";
        case "shadowML":
            return "pbd_" + this._id + "_ml";
        case "shadowMM":
            return "pbd_" + this._id + "_mm";
        case "shadowMR":
            return "pbd_" + this._id + "_mr";
        case "shadowBL":
            return "pbd_" + this._id + "_bl";
        case "shadowBM":
            return "pbd_" + this._id + "_bm";
        case "shadowBR":
            return "pbd_" + this._id + "_br";
        default:
            //alert("error");
            return "";
    }
}
PeekBox.prototype.registerPeekBoxTarget = function(obj){
    obj._isPeekBoxTarget = true;
}
PeekBox.prototype.getIsPeekBoxTarget = function(obj){
    return obj._isPeekBoxTarget == true;
}
PeekBox.prototype.setPositions = function(boxX, boxY, boxWidth, boxHeight, pointerX, pointerY, pointerOrientation, enablePointer){

    setElementLocation(this._mainDiv, boxX, boxY);
    
    setElementSize(this._borderDiv, boxWidth, boxHeight);
    setElementLocation(this._contentsDiv, this._boxPaddingLeft, this._boxPaddingTop);
    setElementSize(this._contentsDiv, boxWidth - this._boxPaddingLeft - this._boxPaddingRight, boxHeight - this._boxPaddingTop - this._boxPaddingBottom);
    setElementWidth(this._shadowDiv_TM, boxWidth - 19);
    setElementWidth(this._shadowDiv_BM, boxWidth - 19);
    setElementHeight(this._shadowDiv_ML, boxHeight - 19);
    setElementHeight(this._shadowDiv_MR, boxHeight - 19);
    
    setElementX(this._shadowDiv_TR, boxWidth + 1);
    setElementX(this._shadowDiv_MR, boxWidth + 1);
    setElementX(this._shadowDiv_BR, boxWidth + 1);
    
    setElementY(this._shadowDiv_BL, boxHeight + 1);
    setElementY(this._shadowDiv_BM, boxHeight + 1);
    setElementY(this._shadowDiv_BR, boxHeight + 1);
    
    if(enablePointer){
        switch(pointerOrientation){
            case "left":
                setElementLocation(this._leftPointerDiv, pointerX - this._leftPointerImageOffset.x - boxX, pointerY - this._leftPointerImageOffset.y - boxY);
                this._leftPointerDiv.style.visibility = "visible";
                this._leftPointerDiv.style.display = "block";
                this._rightPointerDiv.style.visibility = "hidden";
                this._rightPointerDiv.style.display = "none";
                break;
            case "right":
                setElementLocation(this._rightPointerDiv, pointerX - this._rightPointerImageOffset.x - boxX, pointerY - this._rightPointerImageOffset.y - boxY);
                this._leftPointerDiv.style.visibility = "hidden";
                this._leftPointerDiv.style.display = "none";
                this._rightPointerDiv.style.visibility = "visible";
                this._rightPointerDiv.style.display = "block";
                break;
            case "none":
            default:
                this._leftPointerDiv.style.visibility = "hidden";
                this._leftPointerDiv.style.display = "none";
                this._rightPointerDiv.style.visibility = "hidden";
                this._rightPointerDiv.style.display = "none";
                break;
        }
    }else{
        this._leftPointerDiv.style.visibility = "hidden";
        this._leftPointerDiv.style.display = "none";
        this._rightPointerDiv.style.visibility = "hidden";
        this._rightPointerDiv.style.display = "none";
    }
    
}
PeekBox.prototype.setBoxSize = function(width, height){
    
}



function setElementX(element, x){
    if(!element || !element.style) return;
    element.style.left = x + "px";
}
function setElementY(element, y){
    if(!element || !element.style) return;
    element.style.top = y + "px";
}
function setElementLocation(element, x, y){
    if(!element || !element.style) return;
    element.style.left = x + "px";
    element.style.top = y + "px";
}

function setElementWidth(element, width){
    if(!element || !element.style) return;
    element.style.width = width + "px";
}

function setElementHeight(element, height){
    if(!element || !element.style) return;
    element.style.height = height + "px";
}

function setElementSize(element, width, height){
    if(!element || !element.style) return;
    element.style.width = width + "px";
    element.style.height = height + "px";
}

function setElementRectangle(element, x, y, width, height){
    if(!element || !element.style) return;
    element.style.left = x + "px";
    element.style.top = y + "px";
    element.style.width = width + "px";
    element.style.height = height + "px";
}

function isDOMAncestor(potentialAncestor, item){
    if(item.nodeName == "BODY") return false;
    var parent = item;
    while (parent != null && parent.nodeName != "BODY"){
	    if (parent == potentialAncestor) return true;
	    parent = parent.parentNode;
	}
	return false;
}

function Point(x, y){
    this.x = x;
    this.y = y;
}

function Size(width, height){
    this.width = width;
    this.height = height;
}

function Rectangle(x, y, width, height){
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
}

function LockGrid(width, height, offsetX, offsetY){
    if(offsetX == null){ offsetX = 0; }
    if(offsetY == null){ offsetY = 0; }
    this.size = new Size(width, height);
    this.offset = new Point(offsetX, offsetY);
    this.enabled = true;
}
LockGrid.prototype.adjustPoint = function(point){
    // find nearest point
    var x = Math.round((point.x - this.offset.x) / this.size.width) * this.size.width + this.offset.x;   
    var y = Math.round((point.y - this.offset.y) / this.size.height) * this.size.height + this.offset.y;    
    point.x = x;
    point.y = y;
    return;
}
LockGrid.prototype.moveX = function(point, count){
    point.x += Math.round(this.size.width * count);
}
LockGrid.prototype.moveY = function(point, count){
    point.y += Math.round(this.size.height * count);
}


//if (typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();

