/***********************************************************************
 *  Filename: mod25_textWindow.js                                      *
 *  Date Created: 13MAY06                                              *
 *  Date Last Modified: 16JUL06                                        *
 *  Package: mod25                                                     *
 *  Type: Class definition                                             *
 *  Copyright © 2006 Mod25 Solutions, LLC. All Rights Reserved         *
 *  Notes: This class will create a window for showing text.  This     *
 *	window will be able to scroll and the scrollbar will be hidden     *
 *	when not in use.                                                   *
 **********************************************************************/

/***********************************************************************
 * Requirements:                                                       *
 *      mod25_events                                                   *
 *      mod25_misc                                                     *
 *                                                                     *
 * Optional:                                                           *
 *      mod25_scrollbar - If using scrollbar functionality             *
 **********************************************************************/


// An array of all the mod25_textWindow's
mod25_textWindowObjs = new Array();

// Define the class constructor
// Arguments: mainWindow - String ID of the window container; content - String ID of the first content window;
//	vScrollbar - A mod25_scrollbar to be used for scrolling the content vertically; hScrollbar - A mod25_scrollbar
//	used for scrolling the content horizontally
// *** Note *** Neither the vertical or horizontal scrollbars are necessary
function mod25_textWindow(mainWindow, content, vScrollbar, hScrollbar) {
	// Check if getElementById is supported
	if (!document.getElementById)
		return;
	
	// Will hide the scrollbar when there is no information to scroll
	this.hideScroll = true;
	
	// Will resize the scrollbar to fit the amount of information to be scrolled
	this.resizeScroll = true;
	
	// Get the window element
	this.mainWindow = document.getElementById(mainWindow);
	
	// Save the textWindow to the global array
	mod25_textWindowObjs[mainWindow] = this;
	mod25_textWindowObjs.push(this);
	
	// Check for a vertical scrollbar
	if (vScrollbar) {
		this.vScrollbar = vScrollbar;
		
		// Add this instance of a text window to be scrolled
		this.vScrollbar._textWindow = this;
		
		// Add an event handler to scroll the content
		mod25_events.addEvent(this.vScrollbar, 'on_scroll', mod25_textWindow.vScrollContent);
		mod25_events.addEvent(this.vScrollbar, 'on_setScroll', mod25_textWindow.vScrollContent);
	}
	
	// Check for a horizontal scrollbar
	if (hScrollbar) {
		this.hScrollbar = hScrollbar;
		
		// Add this instance of a text window to be scrolled
		this.vScrollbar._textWindow = this;
		
		// Add an event handler to scroll the content
		mod25_events.addEvent(this.hScrollbar, 'on_scroll', mod25_textWindow.hScrollContent);
		mod25_events.addEvent(this.hScrollbar, 'on_setScroll', mod25_textWindow.hScrollContent);
	}
	
	// Setup mouse wheel scrolling
	// Add the event listeners
	mod25_events.addEvent(window, 'DOMMouseScroll', mod25_textWindow.wheelScroll);
	// Add the event listener for IE
	window.onmousewheel = document.onmousewheel = mod25_textWindow.wheelScroll;
	// Can't be done this way because the event is called twice.
	//mod25_events.addEvent(window, 'mousewheel', mod25_textWindow.wheelScroll);
	//mod25_events.addEvent(document, 'mousewheel', mod25_textWindow.wheelScroll);
	
	// Load the first content page
	this.load(content);
	
}

// Load a content page into the window
// Arguments: cntId - String ID of the content page to load;
mod25_textWindow.prototype.load = function(cntId) {
	
	// Check if a layer is already being shown
	if (this.content)
		// Hide the old layer
		this.content.style.visibility = "hidden";
	
	// Get the new content layer
	this.content = document.getElementById(cntId);
	
	// Calculate how much the layer can scroll vertically
	var offsetDiff;
	offsetDiff = this.content.offsetHeight - this.mainWindow.offsetHeight;
	this.maxScrollY = (offsetDiff > 0) ? offsetDiff : 0;
	
	// Calculate how much the layer can scroll horizontally
	offsetDiff = this.content.offsetWidth - this.mainWindow.offsetWidth;
	this.maxScrollX = (offsetDiff > 0) ? offsetDiff : 0;
	
	// Make the content layer visible
	this.content.style.visibility = "visible";
	
	// Check that there is information to be scrolled
	this.checkScroll();
	
	// Update the scrollbar position
	this.updateScrollbars();
	
};

// Update the position of the scrollbars to be proportionate to the amount the content has scrolled
mod25_textWindow.prototype.updateScrollbars = function() {
	// Check if there is a vertical scrollbar
	if (this.vScrollbar) {
		// Calculate the amount scrolled vertically
		if (this.maxScrollY != 0) {
			var tmp = parseInt(getElementStyle(this.content, 'top', 'top'));
			tmp = (tmp < 0) ? tmp * -1 : tmp;
			this.vScrollbar.setScroll(tmp / this.maxScrollY);
		}
	}

	// Check if there is a horizontal scrollbar
	if (this.hScrollbar) {
		// Calculate the amount scrolled horizontally
		if (this.maxScrollX != 0) {
			var tmp = parseInt(getElementStyle(this.content, 'left', 'left'));
			tmp = (tmp < 0) ? tmp * -1 : tmp;
			this.hScrollbar.setScroll(tmp / this.maxScrollX);
		}
	}
	
};
	
// Show or hide scrollbar depending on if there is information to scroll
mod25_textWindow.prototype.checkScroll = function() {
	// Check if there is vertical scroll
	if (this.vScrollbar) {
	
		// Check if the scrollbar should be resized
		if (this.resizeScroll == true) {
			// Save the old size of the scrollbar
			this.vScrollbar.bar.oldSize = getElementStyle(this.vScrollbar.bar, 'height', 'height');
		
			// Check if there is information to be scrolled
			if (this.content.offsetHeight > this.mainWindow.offsetHeight) {
				// Resize the scrollbar
				this.vScrollbar.bar.style.height = parseInt(this.vScrollbar.track.offsetHeight / (this.content.offsetHeight / this.mainWindow.offsetHeight)) + "px";
				
				// Make the minimum size of the bar 1/5 of the size of the track
				if (parseInt(this.vScrollbar.bar.style.height) < (this.vScrollbar.track.offsetHeight / 5))
					this.vScrollbar.bar.style.height = (this.vScrollbar.track.offsetHeight / 5) + "px";
				
			} else
				// Resize the bar to fit the entire track, e.g. no scrolling
				this.vScrollbar.bar.style.height = this.vScrollbar.track.offsetHeight - (2 * this.vScrollbar.bar.minY) + "px";
			
			// Get the new boundaries for the bar
			mod25_scrollbar.getBoundaries(this.vScrollbar);
		} else {
			// Return the bar to it's original size
			this.vScrollbar.bar.style.height = this.vScrollbar.bar.oldSize;
		}
		
		// Check if the scrollbar should be hidden if there is no information to scroll
		if (this.hideScroll == true) {
			// Check if there is information to scroll
			if (this.maxScrollY > 0)
				// Show the scrollbar
				this.vScrollbar.container.style.visibility = "visible";
			else
				// Hide the scrollbar
				this.vScrollbar.container.style.visibility = "hidden";
		}
	}
	
	// Check if there is horizontal scroll
	if (this.hScrollbar) {
	
		// Check if the scrollbar should be resized
		if (this.resizeScroll == true) {
			// Save the old size of the scrollbar
			this.hScrollbar.bar.oldSize = getElementStyle(this.hScrollbar.bar, 'width', 'width');
		
			// Check if there is information to be scrolled
			if (this.content.offsetWidth > this.mainWindow.offsetWidth)
				// Resize the scrollbar
				this.hScrollbar.bar.style.width = this.hScrollbar.track.offsetWidth / (this.content.offsetWidth / this.mainWindow.offsetWidth) + "px";
			else
				// Resize the bar to fit the entire track, e.g. no scrolling
				this.hScrollbar.bar.style.width = this.hScrollbar.track.offsetWidth - (2 * this.hScrollbar.bar.minX) + "px";
			
			// Get the new boundaries for the bar
			mod25_scrollbar.getBoundaries(this.hScrollbar);
			
		} else {
			// Return the bar to it's original size
			this.hScrollbar.bar.style.width = this.hScrollbar.bar.oldSize;
		}
		
		// Check if the scrollbar should be hidden if there is no information to scroll
		if (this.hideScroll == true) {
			// Check if there is information to scroll
			if (this.maxScrollX > 0)
				// Show the scrollbar
				this.hScrollbar.container.style.visibility = "visible";
			else
				// Hide the scrollbar
				this.hScrollbar.container.style.visibility = "hidden";
		}
	}
	
};

// Scroll the content.  Called by a scroll event
mod25_textWindow.vScrollContent = function(pct) {

	// Check if the scroll percent is effectively zero.
	// *** Fix for problems encountered when using a minimum bar size with a large amount
	// 	of information.  Bar would never actually return 0 and the larger the amount
	//	of information the farther from the top it would scroll up to.
	if (pct < .01)
		pct = 0;
	
	// Check if there is vertical scroll
	if (this._textWindow.maxScrollY > 0)
		var newY = parseInt(this._textWindow.maxScrollY * pct) * -1;
	else
		return;
	
	// Move the content
	this._textWindow.content.style.top = newY + "px";
	
}

// Scroll the content horizontally.  Called by a scroll event
mod25_textWindow.hScrollContent = function(pct) {
	// Check if there is horizontal scroll
	if (this._textWindow.maxScrollX > 0)
		var newX = parseInt(this._textWindow.maxScrollX * pct) * -1;
	else
		return;
	
	// Move the content
	this._textWindow.content.style.left = newX + "px";
	
}

// Handle the mouse wheel scrolling
mod25_textWindow.wheelScroll = function(e) {
	var delta = 0;
	var textWindow;
	var pct = 0;
	
	// Get the event object on all platforms
	e = mod25_events.processEvent(e);
	
	// Loop through all the text windows and check if the mouse is over any of them
	var i;
	for (i = 0; i < mod25_textWindowObjs.length; i++) {
		// Get the textWindow
		textWindow = mod25_textWindowObjs[i];
	
		// Check if the mouse in located over the main window
		var minX, maxX, minY, maxY;
		minX = getAbsoluteX(textWindow.mainWindow);
		maxX = minX + textWindow.mainWindow.offsetWidth;
		minY = getAbsoluteY(textWindow.mainWindow);
		maxY = minY + textWindow.mainWindow.offsetHeight;
		
		// Compensate if the window has been scrolled
		var clickX, clickY;
		// Check if we are using mozilla
		if (e.pageX || e.pageY) {
			clickX = e.screenX + window.pageXOffset;
			clickY = e.screenY + window.pageYOffset;
		} else {
			clickX = e.clientX + document.body.scrollLeft;
			clickY = e.clientY + document.body.scrollTop;
		}
	
		if ((clickX > minX) && (clickX < maxX) && (clickY > minY) && (clickY < maxY))
			break;
	}
	
	// Check if we found a good one
	if (i == mod25_textWindowObjs.length)
		return false;
	
	// Check if using IE
	if (e.wheelDelta) {
		delta = e.wheelDelta / 120;
		
		// Opera uses a different sign
		if (window.opera)
			delta = -delta;
		
	} else if (e.detail) { // Mozilla
		delta = -(e.detail / 3);
	}
	
	// Check if we received a delta
	if (delta) {
		var maxScrolled;
		// Get the percent of scroll
		pct = parseInt(getElementStyle(textWindow.content, 'top', 'top'));
		pct = (pct < 0) ? pct * -1 : pct;
		pct = pct / textWindow.maxScrollY;
		
		// Check if at max scroll
		if (pct == 0 || pct == 1)
			maxScrolled = true;
		
		// If delta is negative the scroll action is down
		if (delta < 0)
			pct += .1;
		else
			pct -= .1;
		
		// Check if the percent of the scroll is now out of bounds
		pct = Math.min(Math.max(pct, 0), 1);
		
		// Update the new scroll position
		textWindow.vScrollbar.setScroll(pct);
		
		if (!(maxScrolled == true && (pct == 1 || pct == 0))) {
			e.cancelBubble = true;
			e.preventDefault();
			e.stopPropagation();
			
			return false;
		}
	}
	
	return true;
}