/* -----------------------------------------------------------------------------  
 * Preview Image widget
 * (c) 2007 Third Light Ltd
 * -----------------------------------------------------------------------------
 */
 
/* -----------------------------------------------------------------------------
 * Globals for timeout coordination, and configuration variables.
 */

PreviewImageConfig = { 
    nHoverTimeShow:      750,
    nHoverTimeHide:      500,
    nFadeDuration:       0.2,
    strPreviewDiv:      "ims_preview_image_popup",
    strPreviewDivOld:   "ims_preview_image_popup_old",
    strPreviewImg:      "ims_preview_image_popup_image",
    strPreviewProgress: "ims_preview_image_popup_progress"
}

TimeoutHelper = {
    nTimeoutID:      0,
    strTimeoutOwner: ""
}

objPreviewImage = null;

function positionNextTo(objNextTo, objElt, objOptions)
{
	var nOffsetTop    = 0;
	var nOffsetLeft   = 0;
	
	objNextTo = $(objNextTo);
  objElt = $(objElt);
	
	if(objOptions) {
		if(objOptions.offsetTop) {
			nOffsetTop = objOptions.offsetTop;
		}
		if(objOptions.offsetLeft) {
			nOffsetLeft = objOptions.offsetLeft;
		}
	}
	
	var bSpaceRight   = false;
	var bSpaceLeft    = false;
	var bSpaceTop     = false;
	var bSpaceBottom  = false;
	var nLeft         = 0;
	var nTop          = 0;
	var farRight      = 0;
	var farLeft       = 0;
	var farTop        = 0;
	var farBottom     = 0;
	var winWidth      = 0;
	var winHeight     = 0;

	var ThumbOffset        = Position.cumulativeOffset(objNextTo);
	var ThumbDimensions    = objNextTo.getDimensions();
	var PreviewDimensions  = objElt.getDimensions();
	var ViewportDimensions = WindowHelper.getViewportDimensions();
	var ScrollDimensions   = WindowHelper.getScrollDimensions();        
	
	farRight  = ThumbOffset[0] + ThumbDimensions.width + 
				PreviewDimensions.width;
	farLeft   = ThumbOffset[0] - PreviewDimensions.width;
	farTop    = ThumbOffset[1] - PreviewDimensions.height;
	farBottom = ThumbOffset[1] + ThumbDimensions.height + 
				PreviewDimensions.height;
	
	vpWidth   = ViewportDimensions.width;
	vpHeight  = ViewportDimensions.height;
	vpRootX   = ScrollDimensions.horiz;
	vpRootY   = ScrollDimensions.vert;

	if (farRight  < vpWidth)  bSpaceRight = true;
	if (farLeft   > vpRootX)  bSpaceLeft = true;
	if (farBottom < vpHeight) bSpaceBottom = true;
	if (farTop    > vpRootY)  bSpaceTop = true;        
	
	if (bSpaceRight || bSpaceLeft) {
		if      (bSpaceRight)  nLeft = ThumbOffset[0] + ThumbDimensions.width;
		else if (bSpaceLeft)   nLeft = ThumbOffset[0] - PreviewDimensions.width;        
		if      (bSpaceTop)    nTop  = ThumbOffset[1] - PreviewDimensions.height;
		else if (bSpaceBottom) nTop  = ThumbOffset[1] + ThumbDimensions.height;                
		else                   nTop  = vpRootY;
	}
	else if (bSpaceTop || bSpaceBottom) {
		nLeft = vpRootX;    
		if      (bSpaceTop)    nTop  = ThumbOffset[1] - PreviewDimensions.height;
		else if (bSpaceBottom) nTop  = ThumbOffset[1] + ThumbDimensions.height;                
	}
	else {
		if (farLeft - vpWidth > farBottom - vpHeight) {
			nTop = vpRootY;
			nLeft = ThumbOffset[0] + ThumbDimensions.width;
		}
		else {
			nLeft = vpRootX;
			nTop = ThumbOffset[1] + ThumbDimensions.height;
		}
	}

	objElt.setStyle({'left': nLeft + nOffsetLeft + "px", 'top':  nTop + nOffsetTop + "px"});    
}	

/* -----------------------------------------------------------------------------
 * WindowHelper returns cross-browser browser window dimensions.
 */
 
var WindowHelper = {
    getViewportWidth: function() {
        if (typeof(window.innerWidth) == 'number') {
            return window.innerWidth;
        }
        else if (document.documentElement && 
            document.documentElement.clientWidth) {
            return document.documentElement.clientWidth;
        }
        else if (document.body && document.body.clientWidth) {
            return document.body.clientWidth;
        }
        else {
            return 0;
        }
    },
    getViewportHeight: function() {
        if (typeof(window.innerHeight) == 'number') {
            return window.innerHeight;
        }
        else if (document.documentElement &&  
            document.documentElement.clientHeight) {
            return document.documentElement.clientHeight;
        }
        else if (document.body && document.body.clientHeight) {
            return document.body.clientHeight;
        }
        else {
            return 0;
        }
    },
    getViewportDimensions: function() {
        return {width: this.getViewportWidth(), height: this.getViewportHeight()};
    },
    getPageWidth: function() {
        var xScroll = 0;
        if (window.innerWidth && window.scrollMaxX) {
            xScroll = window.innerWidth + window.scrollMaxX;
        }
        else if (document.body.scrollWidth > document.body.offsetWidth ) {
            xScroll = document.body.scrollWidth;
        }
        else {
            xScroll = document.body.offsetWidth;
        }
        return Math.max( this.getViewportWidth(), xScroll );
    },
    getPageHeight: function() {
        var yScroll = 0;
        if (window.innerHeight && window.scrollMaxY) {
            yScroll = window.innerHeight + window.scrollMaxY;
        }
        else if (document.body.scrollHeight > document.body.offsetHeight ) {
            yScroll = document.body.scrollHeight;
        }
        else {
            yScroll = document.body.offsetHeight;
        }     
        return Math.max( this.getViewportHeight(), yScroll );
    },
    getPageDimensions: function() {
        return {width: this.getPageWidth(), height: this.getPageHeight()};
    },
    getHorizontalScroll: function() {
        if (document.body && document.body.scrollLeft) {
            return document.body.scrollLeft;
        }
        else if (document.documentElement && 
            document.documentElement.scrollLeft) {
            return document.documentElement.scrollLeft;
        }
        else if (window.pageXOffset) {
            return window.pageXOffset;
        }
        else {       
            return 0;
        }
    },
    getVerticalScroll: function() {
        if (document.body && document.body.scrollTop) {
            return document.body.scrollTop;
        }
        else if (document.documentElement && 
            document.documentElement.scrollTop) {
            return document.documentElement.scrollTop;
        }
        else if (window.pageYOffset) {
            return window.pageYOffset;
        }
        else {
            return 0;
        }
    },
    getScrollDimensions: function() {
        return {horiz: this.getHorizontalScroll(), vert: this.getVerticalScroll()};
    }
};

/* -----------------------------------------------------------------------------
 * PreviewImage coordinates the creation, display and removal of the preview.
 */
 
var PreviewImage = Class.create({
    initialize: function(strThumbID, strPreviewURL, nPreviewWidth, nPreviewHeight, bBrowserSecurityEnabled, JSONMetadata) {
        this.strThumbID = strThumbID;
        this.strPreviewURL = strPreviewURL;
        this.nPreviewWidth = nPreviewWidth;
        this.nPreviewHeight = nPreviewHeight;  
        this.bImageLoaded = false;
        this.bBrowserSecurityEnabled = bBrowserSecurityEnabled ;
        this.JSONMetadata = JSONMetadata;
    },
    previewHide: function() {
        if ($(PreviewImageConfig.strPreviewDiv)) {
            elPreview = $(PreviewImageConfig.strPreviewDiv);
            elPreview.id = PreviewImageConfig.strPreviewDivOld;
            Effect.Fade(
                PreviewImageConfig.strPreviewDivOld, {
                    duration: PreviewImageConfig.nFadeDuration, 
                    afterFinish: this.removeOldPreview
                }
            );
        }    
    },
    removeOldPreview: function() {
        $(PreviewImageConfig.strPreviewDivOld).remove();
    },
    ImageShow: function() {
        if ($(PreviewImageConfig.strPreviewProgress)) $(PreviewImageConfig.strPreviewProgress).remove();
        new Effect.Appear(
            PreviewImageConfig.strPreviewImg, {duration: PreviewImageConfig.nFadeDuration}
        );                       
    },
    previewShow: function() {                
        var elThumb = $(this.strThumbID);

        var elPreviewDiv = document.createElement("div");
        Element.extend(elPreviewDiv);
        elPreviewDiv.addClassName('thumbnailPopupPreviewBorder');
        elPreviewDiv.id = PreviewImageConfig.strPreviewDiv;
        elPreviewDiv.setStyle ({
            backgroundColor:     '#ffffff',
            position:    'absolute',
            display:     'none',
            'float':     'none',
            left:        '0px',
            top:         '0px',
            zIndex:      100,
            width:       this.nPreviewWidth + "px",
            padding:'10px'
        });
        
        // Tweak for IE less than 7 to solve div over select issue.
        // This only *looks* like a comment! Do not delete.
    	/*@cc_on
            if (typeof(document.body.style.maxHeight) == "undefined") {
                var elPreviewDivOpacity = document.createElement("iframe");
                $(elPreviewDivOpacity).id = PreviewImageConfig.strPreviewDiv + "_opacity";
                elPreviewDivOpacity.src = "/images/transparent.gif";
                elPreviewDivOpacity.height = this.nPreviewHeight + "px";
                elPreviewDivOpacity.width = this.nPreviewWidth + "px";
                elPreviewDivOpacity.style.position = "absolute"; 
                elPreviewDivOpacity.style.left = "0px";
                elPreviewDivOpacity.style.top = "0px";
                elPreviewDivOpacity.frameBorder = 0;
                elPreviewDivOpacity.zIndex = 2;     
            	elPreviewDiv.insert({bottom: elPreviewDivOpacity});
            }    	   
        @*/
    	        
        var elPreviewImgDiv = document.createElement("div");
        Element.extend(elPreviewImgDiv);
        elPreviewImgDiv.setStyle ({
            width:       this.nPreviewWidth + "px",
            height:      this.nPreviewHeight + "px"
        }); 
        var elPreviewImg = document.createElement("img");
        Element.extend(elPreviewImg);
        elPreviewImg.id = PreviewImageConfig.strPreviewImg;        
        elPreviewDiv.insert({bottom: elPreviewImgDiv});
        elPreviewImgDiv.insert({bottom: elPreviewImg});
        elThumb.insert({before: elPreviewDiv});
        
        // Print a text box below the image containing image metadata
        if (this.JSONMetadata) {
          var elPreviewTableDiv = document.createElement("div");
          var elPreviewTable = document.createElement("table");
          var elPreviewTableBody = document.createElement("tbody");
          Element.extend(elPreviewTable);
          elPreviewTable.appendChild(elPreviewTableBody);
          elPreviewTable.addClassName('tnConfig_PopupPreviewText');
          elPreviewTable.addClassName('thumbnailPopupPreviewText');
          elPreviewTable.setStyle({
            marginTop:'10px',
            background: '#FFFFFF',
            width: '100%'
            });
        
          // Display all metadata from JSON object
          for(field in this.JSONMetadata) {
              var elPreviewRow = document.createElement("tr");
              var elPreviewCell = document.createElement("td");
              var elPreviewCell2 = document.createElement("td");
              Element.extend(elPreviewCell);
              elPreviewCell.innerHTML = String(field).escapeHTML();
              elPreviewCell.setStyle({
                fontWeight: 'bold',
                verticalAlign: 'top',
                textAlign: 'left'
              });
              Element.extend(elPreviewCell2);
              elPreviewCell2.innerHTML = String(this.JSONMetadata[field]).escapeHTML().replace(/\n/g, '<br/>');
              elPreviewCell2.setStyle({
                textAlign: 'left'
              });
              elPreviewTableBody.appendChild(elPreviewRow);
              elPreviewRow.appendChild(elPreviewCell);
              elPreviewRow.appendChild(elPreviewCell2);
          };
          elPreviewTableDiv.appendChild(elPreviewTable);
          Element.extend(elPreviewTableDiv);
          elPreviewDiv.insert({bottom: elPreviewTableDiv}); 
        }
        
        var myself = this;
        Event.observe(elPreviewImg, "load", function() {myself.bImageLoaded = true; myself.ImageShow()});
        
        if(this.bBrowserSecurityEnabled) {
          Event.observe(elPreviewImg, "contextmenu", function() { alert("These pictures are copyrighted material. Please do not take copies."); return false; } );
        }
        
        elPreviewImg.src    = this.strPreviewURL;
        elPreviewImg.width  = this.nPreviewWidth;
        elPreviewImg.height = this.nPreviewHeight;
        elPreviewImg.setStyle ({
                border: '0px solid #000000',
                display:  'none', 
                margin:   '0px',
                position: "relative",
                left:     "0px",
                top:      "0px",
                zIndex:   3                
        });
        
        // Only do progress bar if image is not already loaded (ie, not cached)
        if (!this.bImageLoaded)
        {       
            var elProgressBar = document.createElement("img");
            Element.extend(elProgressBar);
            elProgressBar.id = PreviewImageConfig.strPreviewProgress;
                                   
            elProgressBar.src    = "/graphics/inprogress.gif";
            elProgressBar.width  = 16;
            elProgressBar.height = 16;
            elProgressBar.setStyle({
                    left:     (this.nPreviewWidth / 2) + "px", 
                    display:  'block', 
                    position: 'absolute',
                    top:      (this.nPreviewHeight / 2) + "px"
            });
            
            elPreviewDiv.insert({bottom: elProgressBar});
        }
        
        positionNextTo(elThumb, elPreviewDiv, {offsetTop: 7});
        
        new Effect.Appear(
            PreviewImageConfig.strPreviewDiv, {duration: PreviewImageConfig.nFadeDuration}
        );    
    }
});

/* -----------------------------------------------------------------------------
 * Attach these functions to thumbnail onmouseover / onmouseout events
 */  

function previewStart(
    strThumbID, strPreviewURL, nPreviewWidth, nPreviewHeight, bBrowserSecurityEnabled, JSONMetadata 
) {
    objPreviewImage = new PreviewImage(strThumbID, strPreviewURL, nPreviewWidth, nPreviewHeight, bBrowserSecurityEnabled, JSONMetadata);
    if (strThumbID == TimeoutHelper.strTimeoutOwner) {
        window.clearTimeout(TimeoutHelper.nTimeoutID);    
    }
    else {
        objPreviewImage.previewHide();
    }
    if (!$(PreviewImageConfig.strPreviewDiv)) {    
        TimeoutHelper.nTimeoutID = window.setTimeout(
            function() {objPreviewImage.previewShow()}, 
            PreviewImageConfig.nHoverTimeShow
        );
        TimeoutHelper.strTimeoutOwner = strThumbID;
    }
}

function previewStop(strThumbID) {
    window.clearTimeout(TimeoutHelper.nTimeoutID);    
    if ($(PreviewImageConfig.strPreviewDiv)) TimeoutHelper.nTimeoutID = window.setTimeout(
        function() {objPreviewImage.previewHide()}, 
        PreviewImageConfig.nHoverTimeHide
    );
}

