// JavaScript Document
/*
	Calendar Pop-up Edit Window
	mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
	
	Author: Ian Carr
	Date: July 2009
	
	Javascript Functions that allow a
	user to edit many diffrent mini
	documents in rich text with just one
	editor instance. Currently is designed
	to work with tinyMCE editor.
*/

/*
	Global Variables to save us time and money
*/
var current = "0"; // Our current document we are editing - uses arbitrary integer id numbers to find via special css id values
var edWindowOpen = false; // Is our editor currently open?
var edName = "edWindow"; // The css id name used to name parts of our editor window
var edDivName = edName + "pop"; // id of the main div of the window
var mceName = edName + "mce"; // name of the textarea that tinyMCE turns into a full editor

//Initialized Variables:
var ed = null; // Our tinyMCE instance
var edDiv = null; // the div that becomes the editor popup
var edTitle = null; // The div of the edit window title

var arrayBox = null; // Array of every day box (used for resizing)
var lenBox = null; //number of elements in arrayBox
var arrayMsg = null; // Array of every "(more...)" message (used for resizing)
var lenMsg = null; //number of elements in arrayMsg

var isResize = false; //Used to lock out multible calls to reDraw

var isLink = false; //Used to prevent editor from opening when user clicks on a link

var isIE6  = false; //Used to change behaviors for silly old ie6
var isIE7  = false; //Used to change behaviors for silly old ie7

var jump = true; //If true will auto-jump so Calendar fills the screen on load

var edInitCallback = null; //If set and is a function, will be called at end of initED()
var edInitEdComplete = false; //Set to true at the end of initED()
var edTinyMCEInitComplete = false; //Set to true by callback from tinyMCE editor when it has been init.

// Callback fuction used by tinyMCE to indicate it has fully loaded
function onTinyMCEInitComplete() {
	edTinyMCEInitComplete = true;
	
	// Support a callback when initED is completed AND tinyMCE is loaded too ...
	if (edInitCallback != null && edInitEdComplete) {
		if(typeof(edInitCallback) == 'function') {
			edInitCallback();
		}
		edInitCallback = null;
	}
}

// Sets up our variables and does our initial resize call
function initED(){
	// Try to get the tinyMCE editor window object
	var myed = tinyMCE.get(mceName);
	if (typeof(myed) != 'object')
		return;
	
	// Successfully got it, finish initialization
	ed = myed;

	//Collect all of the day boxes into an array
	//arrayBox = getElementsByClass("daybox");
	arrayBox = $$(".daybox");
	lenBox = arrayBox.length;
	
	//Collect all of the "(more...)" daymsgs into an array
	//arrayMsg = getByClass("daymsg");
	arrayMsg = $$(".daymsg");
	lenMsg = arrayMsg.length;
	
	//resize everything
	reDraw();

	//make our links disable the ed popup behavior
	linkCheck();
	
	//initalize our remaining varaibles
	edTitle = $("popName");
	edDiv = $(edDivName);
	
	//Make resizing activate on window resize
	window.onresize = resize;
	
	//Display the Calendar Boxes
	paint();
	
	//Jump to the Calendar
	//scrollToMenubar();
	
	//Display the Chrome on top
	//document.getElementById("TheChrome").style.display = "block";

	// initED is finished
	edInitEdComplete = true;

	// Support a callback when initED is completed AND tinyMCE is loaded too ...
	if (edInitCallback != null && edTinyMCEInitComplete) {
		if(typeof(edInitCallback) == 'function') {
			edInitCallback();
		}
		edInitCallback = null;
	}
}

function paint(){
	for( i = 0; i < lenBox; i++)
		arrayBox[i].style.display = "block";
}

// Reacts to any click in a daybox Will launch
// or load the editor window as is needed.
function activate(cur){
	//Do nothing if link is clicked
	if(isLink)
		return;
	//Handle case where activate is called before initED() or before tinyMCE is loaded
	if(edInitEdComplete == false || edTinyMCEInitComplete == false) {
		// Create a callback to call ourselves after initED() and/or tinyMCE is done
		if (edInitCallback == null)
			edInitCallback = function() { activate(cur); };
		return;
	}
	//Do nothing if current is cur
	if(current == cur && edWindowOpen) {
		setTimeout ( "ed.focus();", 10); // Make editor the cursor focus
		return;
	}
	//If allready open, save contents of current day box pressed and turn off color
	if(edWindowOpen){
		changeText(true);
		selectOFF();
	} else //or launch the new window
		openEd();
	//update variables, editor window
	current = cur;
	titleUpdate();
	loadText(cur);
	selectON();
	setTimeout ( "ed.focus();", 10); // Make editor the cursor focus
}

function getScrollTop() {
  var scrOfY=0;
  //var scrOfX=0;
  if( typeof( window.pageYOffset ) == 'number' ) {
    //Netscape compliant
    scrOfY = window.pageYOffset;
    //scrOfX = window.pageXOffset;
  } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
    //DOM compliant
    scrOfY = document.body.scrollTop;
    //scrOfX = document.body.scrollLeft;
  } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
    //IE6 standards compliant mode
    scrOfY = document.documentElement.scrollTop;
    //scrOfX = document.documentElement.scrollLeft;
  }
  return scrOfY;
}
// Displays the editor window and calls the grey out function
function openEd(){
	greyON();
	edDiv.style.display="block";
	edWindowOpen = true;
	var centerHeight = (document.body.offsetHeight / 2) - 150;
	edDiv.style.top = (getScrollTop()+centerHeight)+"px";
}

// Hides the editor window (saving any changes) and calls the un-grey out funciton
function closeEd(){
	changeText(true);
	greyOFF();
	edDiv.style.display="none";
	edWindowOpen = false;
	selectOFF();
}

// Text and border effect used when edit window is open
// Works through magic of css inheritance (all elements
// that change inherit their colors from the div w/ id of "thePage")
function greyON(){
	//if(isTemplate)
	//	return;
	var page = $("thePage");
	page.style.borderColor="#AAA";
	page.style.color="#666";
}

// Reverses effects of greyOn()
function greyOFF(){
	//if(isTemplate)
	//	return;
	var page = $("thePage");
	page.style.borderColor="";
	page.style.color="";
}

// Background effect used for the daybox currently
// being edited.
function selectON(){
	//if(isTemplate)
	//	return;
	$(current + 'div').style.backgroundColor = "#D1F2F7";
}

// Reverses effects of selectON
function selectOFF(){
	//if(isTemplate)
	//	return;
	$(current + 'div').style.backgroundColor = "";
}

// Automatically called by tinyMCE when ever the user interacts with it
// -- only called when tinyMCE adds an 'undo level' which may not always
//    happen on every key press.
function autoSave(){
	changeText(false);
}

// Saves to day box with Edited content (and activates autosave)
function changeText(instantSave){
	if (typeof(ed.settings.readonly) == 'undefined' || !ed.settings.readonly) {
		var text = ed.getContent(); //Get the content from editor
		
		// Don't update anything if its still really the same
		if (text != $(current + 'up').innerHTML) {
			$(current + 'up').innerHTML = text; // put it into the visible day box
			$(current + 'hi').value = text; // Also put it into hidden input feild used for autosaving
			
			if (typeof(instantSave) != 'undefined' && instantSave === true) {
				calendarDayHasChanged(current); //Flag the day as changed which is useful if autoSave fails
				calendarAutoSave(current); //Trigger the instant autosave event by hand
			}
			else
				calendarHandleInput(current); //Trigger the delayed autosave event by hand
		}
	}
	if (numInCol <= 10) {
		isMore(current); //Checks if a "(more...)" bar is needed, except for event view which is autosizing
	}
	linkCheck(); //Checks for any new links
}

// Loads to editor with Day box content
function loadText(id){
	var text = $(id + 'up').innerHTML; //Get content
	ed.setContent(text); // Load it to editor
}

//updates the edit widnow title with the current edited days date
function titleUpdate(){
	var date, year, month, day;
	
	date = $(current + "date").parentNode.id; // get encoded year-MM-DD date
	date = date.split("-"); //turn encoded date into an array
	year = date[0]; //get year number
	
	switch(date[1]){ //turn month number into word
		case "01":
			month = "January";
			break;
		case "02":
			month = "February";
			break;
		case "03":
			month = "March";
			break;
		case "04":
			month = "April";
			break;
		case "05":
			month = "May";
			break;
		case "06":
			month = "June";
			break;
		case "07":
			month = "July";
			break;
		case "08":
			month = "August";
			break;
		case "09":
			month = "September";
			break;
		case "10":
			month = "October";
			break;
		case "11":
			month = "November";
			break;
		default:
			month = "December";
			break;
	}
	day = date[2]; //get day number
	if (day.charAt(0) == '0') //remove preceding 0 on day number
    	day = day.substr(1,day.length-1)
	edTitle.innerHTML = month + " " + day + ", " + year; //set edit box's title to date string.
}

//Simple container function to prevent too many calls to reSize.
function resize(){
	if(!isResize){
		isResize = true;
		setTimeout ( "resize2()", 50 );
	}
}

//helper function to actually call resize and on completion turn off the lock
function resize2(){
	reDraw();
	isResize = false;
}

//Resizes all of the day boxes such that the calendar alone will exactly fill the entier browser window
function reDraw() {
	//default values for old browsers
	var pageW = 530, pageH = 460;
	var noff;
	var ieoff;
	if(iframe){ //if iframe = true will not take scroll bar sizes into account when rendering calendar
		noff = 0;
		ieoff = 0;
	} else {
		noff = 26;
		ieoff = 30;
	}

	if(isIE6) {
		$("thePage").style.height="auto"; // added this so that we can set a height on the calendar div area to prevent IE7/8 from jumping during paging (because of no height)
	}

	//Get size of window (either browser or iframe size) and subtract scroll bar offset from it
	if (parseInt(navigator.appVersion)>3) {
		if (navigator.appName=="Netscape") {
				//pageW = window.innerWidth-noff;
				pageW = $('thePage').offsetWidth;
				pageH = window.innerHeight - 30;
		}
		if (navigator.appName.indexOf("Microsoft")!=-1) {
				//pageW = document.body.offsetWidth-ieoff;
				pageW = $('thePage').offsetWidth;
				pageH = document.body.offsetHeight - 30;
		}
	}
	
	if(pageW < 530)
		pageW = 530;
	if(pageH < 460)
		pageH = 460;
		
	if(isIE6) {
		$("thePage").style.width = pageW;
	}
	if ($('cal_horizontal_ad') != null) {
		pageH -= $('cal_horizontal_ad').offsetHeight; // in case an add is being displayed
	}
	pageW -= 3; // for the left border

	// calculate rounded size for day boxes 
	// (we are conservative because so much as a single pixle too wide will
	// cause the whole calendar to have a broken display)
	error = 1.5; // 1 for border width, .5 so we always get the number rounded down.
	boxW = Math.round((pageW / numInRow) - error);
	boxH = Math.round((pageH / numInCol) - error);

	// adjust the width and height of all calendar days
	for( i = 0; i < lenBox; i++ ){
		if (numInCol <= 10) {
			arrayBox[i].style.width= boxW + "px";
			arrayBox[i].style.height= boxH + "px";
		} else {
			arrayBox[i].style.width= boxW+"px"; //99%";
			arrayBox[i].style.height = "auto"; // let it scale to the required height
		}
	}

	if (numInCol <= 10) {
		$('thePage').style.height = ((boxH * numInCol)+10)+"px";// set the div height, helps prevent IE from growing/shrinking
	} else {
		$('thePage').style.height = pageH+"px";
	}

	// adjust the width and height of any visible "(more...)" bars
	for( i = 0; i < lenMsg; i++ ){
		if(arrayMsg[i].style.display != "none"){
			arrayMsg[i].style.top= (boxH - 15)+ "px";
			arrayMsg[i].style.height= "20px";
		}
	}
	scrollToMenubar();
}

//disables the ability to launch the editor popup when a user has a mouse over a link. Restores the ability when the user moves the mouse off the link.
//based on code from: http://www.webmonkey.com/tutorial/Get_Started_With_Prototype
function linkCheck(){
	// Gather every link and give it mouseover code to turn isLink on
	// and a mouseout event to turn isLink off. The editor popup will
	// not launch when isLink is true, thus allowing links to work as expected.
	$$('a').each(function(elmt) {
		elmt.observe('mouseover', function(ev) {
			isLink = true;
		});
		elmt.observe('mouseout', function(ev) {
			isLink = false;
			//alert(ev.target.innerHTML);
		});
	});
}

//Checks if a "(more...)" bar should be turned on
function isMore(cur){
	box = $(cur + 'up'); //get current day's text box
	height = box.offsetHeight + box.offsetTop; //get it's height
	if(arrayBox[1].offsetHeight <= height){ //activate "(more...)" bar if needed
		var element = $(cur + 'msg');
		element.style.display = "block";
		element.setOpacity(0.8);
	}
}

//Browser compliant way to make "(more...)" bars go transparent
/* This is available through prototype
function setOpacity(value) {
	$(current + 'msg').style.opacity = value/10;
	$(current + 'msg').style.filter = 'alpha(opacity=' + value*10 + ')';
}
*/

//Gets all objects with a particular class
//From: http://www.dustindiaz.com/getelementsbyclass/
/* Prototype does this--see documentation for $$
function getElementsByClass(searchClass,node,tag) {
	var classElements = new Array();
	if ( node == null )
		node = document;
	if ( tag == null )
		tag = '*';
	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
	var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
	for (i = 0, j = 0; i < elsLen; i++) {
		if ( pattern.test(els[i].className) ) {
			classElements[j] = els[i];
			j++;
		}
	}
	return classElements;
}
*/

//Gets all objects with a particular class
//From: http://www.snook.ca/archives/javascript/your_favourite_1
// Warning!! getClass() is a pre-defined browser function... renamed it to getByClass()
/* Prototype does this--see documentation for $$
function getByClass(xx){
	var rl=new Array();
	var ael=document.all?document.all:document.getElementsByTagName('*'); //not here ";" originally
	for(i=0,j=0;i<ael.length;i++){
		if((ael[i].className==xx)){
			rl[j]=ael[i];
			j++;
		}
	}
	return rl;
}
*/

//Replaces all classes with another class
// Currently not used , but may be useful for resizing the editor window
//From: http://www.snook.ca/archives/javascript/your_favourite_1
/* Its not used--nor is it prototype-ified
function classRepl(whatReplace,withWhatReplace){
	for(var i=0;i<getByClass(whatReplace).length;i++){
		getByClass(whatReplace)[i].onclick=function(){
			this.className=this.className==withWhatReplace?whatReplace:withWhatReplace;
		}
	}
}
*/

//Following three functons taken from the Photo App's Code.

function scrollToTop() {
	setTimeout("scroll(0,0);", 100);
}

function scrollToMenubar() {
	if ($('menuBar') != null) {
		setTimeout("scroll(0, findPos($('menuBar'))[0]);", 100);
	}
} 

function findPos(obj) {
	var cleft = 0;
	var ctop = 0;
	if (obj.offsetParent) {
		do {
			cleft += obj.offsetLeft;
			ctop += obj.offsetTop;
		} while (obj = obj.offsetParent);
	}
	return [ctop,cleft];
} 
