/*
* DiceRoller.js  v0.5
*
* Javascript functions associated with the DiceRoller extension
*
*
Copyright 2007 Arturo Gonzalez-Escribano
This file is part of Lussumo's Software Library.
Lussumo's Software Library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
Lussumo's Software Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Vanilla; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
The latest source code is available at www.lussumo.com
Contact Arturo González-Escribano at arturo [at] infor [dot] uva [dot] es

*
*/


/*
* DR_beb: DiceRoller 'block edit button'
*
*	Invoked just after the Comment options has been rendered, it searchs and
*	blocks the edit button for that comment.
*
*	For eficiency, the php code should include the call to this script
*	only when the AuthUserID is the UserID, but if the button does not exist 
*	the script does not complain.
*
*/
function DR_beb( id, editText ) {
	var scriptElement=document.getElementById(id); 
	var parentElement=scriptElement.parentNode; 
	var i=0; 
	var sibling=parentElement.childNodes[0]; 

	/* Locate an anchor sibling with the text of the edit button */
	while(sibling!=null) {
		if (sibling.nodeType==1 
					&& sibling.nodeName == "A" 
					&& sibling.innerHTML == editText ) {
			// Eliminate the link
			parentElement.removeChild( sibling );
			break;
		} 
		i=i+1; 
		sibling=parentElement.childNodes[i]; 
	}
} 


/*
* Functions for presentation of dice-roll results
*
* Several functions associated with the presentation of dice results in the
* comment text, and with the selection of options through a context menu.
*/


/*
* On-load of the page, if javascript is active and the main show/hide
* functions will work, hide all the rolls. I let the rolls visible on load
* only for browsers which do not have javascript active.
*/
var DR_oldOnload = window.onload;
window.onload = DR_hideRolls;

/*
* DR_hideRolls: Hide all the rolls in the page (to be activated on page load)
*/
function DR_hideRolls() {
	var allRolls = document.getElementsByName("DR_rolls");
	for (i=0; i<allRolls.length; i++) {
		allRolls[i].innerHTML = "";
	}
	DR_oldOnload;
}

/*
* Global variables for the context menu
*/
var DR_menu = null;
// This array is filled with language dependent definitions from the PHP code
var DR_options = new Array(4);  

/*
* DR_joinMenu: Joins the hidden menu to an element. It creates it the first
*	time.
*/
function DR_joinMenu( event ) {
	// Create it the first time
	if (DR_menu == null) {
		DR_menu = document.createElement("div");
		DR_menu.className = "DR_menu";

		for (i=0; i<DR_options.length; i++) {
			// New lines for all except first
			if (i!==0) {
				br = document.createElement("br");
				DR_menu.appendChild( br );
			}
			// Create and add option
			option = document.createElement("a");
			option.className = "DR_menuOption";
			option.onmouseup = DR_menuOption;

			// Trick to simulate correct CSS hover behaviour in IExplorer
			option.onmouseover = new Function("this.className = 'DR_menuOptionOver'");
			option.onmouseout = new Function("this.className = 'DR_menuOption'");

			option.innerHTML = DR_options[i];
			option.setAttribute( "numOpt", i );

			DR_menu.appendChild( option );
		}
	}
	// Join it	
	var parentElem = this.parentNode;
	parentElem.appendChild( DR_menu );

	var pos = DR_getMousePos( event );
	DR_menu.style.left= pos.x + "px";
	DR_menu.style.top= pos.y + "px";

	// Stop selecting text
	document.onmousedown = new Function("return false;"); // NE browser family
	document.onselectstart = new Function("return false;"); // IE browser family

	// Close menu when releasing the button outside of the menu options 
	document.onmouseup = DR_closeMenu; // NE browser family
}


/*
* DR_getMousePos: Adapter to get mouse position on as many browses as possible
*/
function DR_getMousePos(e) {
	var result = new Object();

	if (!e) e = window.event;
	if (e.pageX) {
		result.x = e.pageX;
		result.y = e.pageY;
		}
	else if (e.clientX) {
		result.x = e.clientX;
		result.y = e.clientY;
		if ( ! document.documentElement.scrollLeft )
			result.x += document.body.scrollLeft;
		else result.x += document.documentElement.scrollLeft;

		if ( ! document.documentElement.scrollTop ) 
			result.y += document.body.scrollTop;
		else result.y += document.documentElement.scrollTop;
	}
	else return null;

	return result;
}


/*
* DR_diceShow: Show dice-roll information
*/
function DR_diceShow( elem, info ) {
	var parentElem = elem.parentNode;
	var rollText = parentElem.childNodes[1];

	parentElem.DR_info = info;
	info["task"]="hide";
	rollText.style.margin = "0 4px 0 4px";
	rollText.style.padding = "0 8px 0 8px";
	rollText.onmousedown = DR_joinMenu;
	rollText.onmouseup = DR_closeMenu;
	DR_rollShow ( rollText, info );
}


/*
* DR_diceToggle: Toggle (hide/show) dice-roll information
*/
function DR_diceToggle( elem, info ) {
	var parentElem = elem.parentNode;
	var rollText = parentElem.childNodes[1];
	var taskValue = info["task"];

//	parentElem.DR_info = info;

	if (taskValue == "hide") {
		info["task"] = "show";
		rollText.innerHTML = "";
		rollText.style.margin = "0px";
		rollText.style.padding = "0px";
	}
	else {
		info["task"] = "hide";
		DR_rollShow ( rollText, info );
		rollText.style.margin = "0 4px 0 4px";
		rollText.style.padding = "0 8px 0 8px";
	}
}


/*
* DR_rollShow: Update content when mouse over rolls
*/
function DR_rollShow( elem, info ) {
	elem.innerHTML = DR_rollString( info["roll"], info["sort"], 
												info["sum"], info["types"] );
}


/*
* DR_rollString: Build the roll string, sorting if necessary
*/
function DR_rollString( rollValue, sortValue, sumValue, typesValue ) {
	var rollString;

	// Split array of numbers
	var arr = rollValue.split(" ");

	// Sorting
	if ( sortValue != "no" ) {
		arr.sort();
		if ( sortValue == "down" ) arr.reverse();
		}

	// v0.5: Process values (hide/show sizes and optional sum)
	var total = 0;
	for (i=0; i<arr.length; i++) {
		// v0.4 patch:
		// Force base 10 parsing, to avoid 08 and 09 to be incorrectly 
		// parsed as base 8 numbers
		result = parseInt(arr[i], 10); 

		// Sum
		if ( sumValue=="yes" && arr.length>1) {
			total += result;
			}

		// Modifier
		if (arr[i][0]=='+' || arr[i][0]=='-') {
			// v0.4: Mark modifiers with brackets in the sum
			if ( sumValue=="yes" && arr.length>1 ) arr[i] = "[" + arr[i] + "]"; 
			// Skip other processing
			continue;
		}

		// Dice results: Size c=100, and keep two digits only for d100 results
		var sizes = arr[i].split("d");
		if (sizes[1]=="c") { sizes[1]="100"; }
		else sizes[0] = "" + parseInt(sizes[0], 10);

		// Dice results: Skip or add dice sizes string
		if ( typesValue=="yes") {
			arr[i]= sizes[0] + "<sub>d" + sizes[1] + "</sub>";
		}
		else arr[i]= sizes[0];
	}

	// Join elements
	if ( sumValue=="yes" && arr.length>1) {
		rollString = arr.join(" + ");
 		rollString += " = " + total;
	}
	else if ( typesValue=="yes") {
		rollString = arr.join("&nbsp; ");
	}
	else {
		rollString = arr.join(", ");
	}

	return rollString;
}


/*
* DR_menuOption: Actions associated with the options of the menu
*/
function DR_menuOption( ) {
	elem = this;
	var parentElem = elem.parentNode;
	var ancestorElem = parentElem.parentNode;
	var rollElem = ancestorElem.childNodes[1];

	var info = ancestorElem.DR_info;

	opt = elem.getAttribute("numOpt");
	if ( opt==0 ) {
		info["sort"] = "no";		
		DR_rollShow( rollElem, info );
	}
	else if ( opt==1 ) {
		info["sort"] = "up";		
		DR_rollShow( rollElem, info );
	}
	else if ( opt==2 ) {
		info["sort"] = "down";		
		DR_rollShow( rollElem, info );
	}
	else if ( opt==3 ) {
		info["sum"] = (info["sum"]=="no") ? "yes":"no";
		DR_rollShow( rollElem, info );
	}
	else if ( opt==4 ) {
		info["types"] = (info["types"]=="no") ? "yes":"no";
		DR_rollShow( rollElem, info );
	}

	// Trick to simulate pseudoclass :hover normal behaviour in IExplorer 
	// (back to non-highlighted class)
	elem.className = "DR_menuOption";

	// Any option chosen: Hide menu
	DR_closeMenu();
}


/*
* DR_closeMenu: Hide menu removing it from the document hierarchy
*/
function DR_closeMenu() {
	var parentElem = DR_menu.parentNode;
	parentElem.removeChild( DR_menu );

	// Normal mouse behaviour
	document.onmousedown = null; // NE browser family;
	document.onmouseup = null; // NE browser family;
	document.onselectstart = null; // IE browser family;
}

