// this script provides functions to add a more info/less info button to a div.
// i.e. long lists of tags, long video descriptions.
// Simon Doerksen - Workerbee.tv
// sept 23 / 2010

var moreInfoObject = new Object(); // moreInfoObject holds information for each initialized div

function initializeMoreInfo(localTargetP, localTargetWidth, localCharLimit, localMoreText, localLessText, localStyleRules, localBreakAt, localBlockBoolean){
	// initializeMoreInfo
	// call this function to initialize the more/less button
	// localTargetP: id of the div to collapse
	// localCharLimit: maximum number of characters in collapsed mode
	// localMoreText: text to use in the more button. defaults to More Info
	// localLessText: text to use in the less button. defaults to Less Info
	// localStyleRules: styleing to apply to the more/less buttons i.e "color:#333333;"

	// DEFAULTS //
	if(!localMoreText){localMoreText="More...";};
	if(!localLessText){localLessText="Less...";};
	if(!localStyleRules){localStyleRules="";};
	if(!localBreakAt){localBreakAt=new Array(" ", ".", "!", "?", ",");};
	if(!localBlockBoolean){localBlockBoolean=false};
	
	// pObject holds all the needed information for this div //
	var pObject = new Object();
	pObject.target = document.getElementById(localTargetP);
	pObject.targetString = pObject.target.innerHTML;
	pObject.targetWidth = localTargetWidth;
	pObject.stringLength = pObject.targetString.length;
	pObject.currentState = "collapsed";	
	pObject.moreText = localMoreText;
	pObject.lessText = localLessText;
	pObject.styleRules = localStyleRules;
	
	pObject.target.parentNode.style.textAlign = "left";
	var orgFloat = "none";
	var worked = false;
	try{if(worked == false){orgFloat = pObject.target.style.cssFloat;worked=true;} pObject.target.style.cssFloat = "left";}catch(err) {}
 	try{if(worked == false){orgFloat = pObject.target.style.styleFloat;worked=true;} pObject.target.style.styleFloat = "left";}catch(err) {}
 	try{if(worked == false){orgFloat = pObject.target.style.float;worked=true;} pObject.target.style.float = "left";}catch(err) {}
 	if(orgFloat == undefined){
 		orgFloat = "none"
 	}
 	
 	if(localBlockBoolean == false){
 		var charWidth = calculateCharWidth(pObject.target, "K");	
		var maxChars = (pObject.targetWidth / charWidth)*localCharLimit;
		var displayedCharacters = 0;
		var htmlCharacters = 0;
		
		var targetChildren = pObject.target.childNodes;
		for(var i in targetChildren){
			if(targetChildren[i].innerHTML != undefined && getOuterHTML(targetChildren[i]) != undefined){
				displayedCharacters += targetChildren[i].innerHTML.length;
				htmlCharacters += getOuterHTML(targetChildren[i]).length;
				pObject.stringLength = displayedCharacters;
				if(displayedCharacters >= maxChars){
					pObject.charLimit = htmlCharacters;
					break;
				}
			}
		}
	} else {
		var charWidth = calculateCharWidth(document.getElementById(localTargetP), "K");
		var maxChars = (pObject.targetWidth / charWidth)*localCharLimit;
		pObject.charLimit = maxChars;
		htmlCharacters = maxChars;
	} 
	
	if(pObject.stringLength > maxChars){
		pObject.cutPosition = 0;
		for(var a=0; a<9999; a++){
		    pObject.cutPosition = htmlCharacters - a;
		    var allowedToBreak = false;
		    for(var v in localBreakAt){
		    	if(pObject.targetString.charAt(pObject.cutPosition) == localBreakAt[v]){
		    		allowedToBreak = true;
		    		break;
		    	}
		    }
		    if(allowedToBreak == true){
		    	if((pObject.targetString.charAt(pObject.cutPosition) != "<") && (pObject.targetString.charAt(pObject.cutPosition) != ">")){
		    		if(charWithinTag(pObject.targetString, pObject.cutPosition) == false){
		    			break;
		    		}
		    	}
		    }
		}
		pObject.keptString = pObject.targetString.slice(0, pObject.cutPosition);
		pObject.cutString = pObject.targetString.slice(pObject.cutPosition, pObject.targetString.length);
		moreInfoObject[localTargetP] = pObject;
		pObject.target.innerHTML = pObject.keptString + " <a style='"+pObject.styleRules+"' href='#' onClick='toggleInfo(\""+localTargetP+"\");return false;'>"+pObject.moreText+"</a>";
	}
	
 	try{pObject.target.style.cssFloat = orgFloat;}catch(err) {}
 	try{pObject.target.style.styleFloat = orgFloat;}catch(err) {}
 	try{pObject.target.style.float = orgFloat;}catch(err) {}
}

function charWithinTag(localString, localPosition){
	// accepts a string and a character position
	// returns true if the character is within <someTag >, false if not
	var cutString = localString.slice(0, localPosition);
	for(var i=0; i<localPosition; i++){
		if(cutString.charAt(cutString.length - i) == ">"){
			return false;
		} else if (cutString.charAt(cutString.length - i) == "<"){
			return true;
		}
	}
	return false;
}

function calculateCharWidth(localTarget, localString){
	var newDiv = document.createElement("div");
	//newDiv.style = localTarget.style;
	newDiv.style.width = "auto";
	try{newDiv.style.cssFloat = "left";}catch(err) {}
 	try{newDiv.style.styleFloat = "left";}catch(err) {}
 	try{newDiv.style.float = "left";}catch(err) {}
 	
	newDiv.innerHTML = localString.charAt("M");
	document.body.appendChild(newDiv);
	var width = newDiv.clientWidth-2;
	document.body.removeChild(newDiv);
	return width;
}

function toggleInfo(localTargetP){
	// function called by the button
	// switches the div content based on the information
	// stored by initializeMoreInfo
	if(moreInfoObject[localTargetP].currentState == "collapsed"){
	moreInfoObject[localTargetP].currentState = "full";
		moreInfoObject[localTargetP].target.innerHTML = moreInfoObject[localTargetP].keptString + moreInfoObject[localTargetP].cutString + " <a style='"+moreInfoObject[localTargetP].styleRules+"' href='#' onClick='toggleInfo(\""+localTargetP+"\"); return false;'>"+moreInfoObject[localTargetP].lessText+"</a>"
	} else {
		moreInfoObject[localTargetP].currentState = "collapsed";
		moreInfoObject[localTargetP].target.innerHTML = moreInfoObject[localTargetP].keptString + " <a style='"+moreInfoObject[localTargetP].styleRules+"' href='#' onClick='toggleInfo(\""+localTargetP+"\"); return false;'>"+moreInfoObject[localTargetP].moreText+"</a>";
	}
}

function moreLessRefresh() {
	for(var localTarget in moreInfoObject){
		moreInfoObject[localTarget].target = document.getElementById(localTarget);
	}
}

function getOuterHTML(object) {
	var element;
	if (!object) return null;
	element = document.createElement("div");
	element.appendChild(object.cloneNode(true));
	return element.innerHTML;
}
