/********************************************************
*                                                       *
*   ElectricStorm's Cult Template Scripts               *
*   nb, shared ajax pane scripts are now on             *
*   ajaxpanes.js so remember to include that too!       *
*                                                       *
********************************************************/


window.onload = activate;


// on window load, initialize other functions: 
function activate() {
	blurLinks();
}



// blurLinks function
// Gets rid of the annoying dotted line that appears around clicked links.
function blurLinks() {
	
	var links = document.getElementsByTagName('A');
	
	for (var i = 0; i < links.length; i++) { 
		currentLink = links[i];
		currentLink.onfocus = function() { this.blur(); };
	}
	
}




//===========================================
//  Frequently Used Stuff
//===========================================


// isMyEvent function
// checks whether an onmouseover / onmouseout event was fired by the given element.
// (stops annoying flicker when mousing over child elements).
// largely taken from quirksmode (http://www.quirksmode.org/js/events_mouse.html#relatedtarget)
function isMyEvent(theEvent, theElement) { 
		
	//get the related element (the one the mouse has left (if mouseover) or entered (if mouseout))
	if (theEvent.type == 'mouseover') {
		var relEl = theEvent.relatedTarget || theEvent.fromElement;
	}
	else if (theEvent.type == 'mouseout') {
		var relEl = theEvent.relatedTarget || theEvent.toElement;
	}
	else { return false; }
	
	//move up through the DOM until...
	while (relEl) {
		//relEl matches theElement (a child element must have fired the event, so stop):
		if (relEl == theElement) { 
			return false;
			break;
		}
		relEl = relEl.parentNode; //(move up for next loop)
	}
	
	//if we never hit theElement on the way up, event can't have been fired by a child:
	return true;

}




//SLIDE IN / OUT:


// store timeouts for each individual sliding item in array (stops them interfering with each other)
// in global so can be accessed by both slideIn and slideOut functions (so they never overlap and get stuck!)
var slideTimeout = new Array(); 



// slideOut function
// slides open a pane to the given height. 
function slideOut(itemID, toHeight, jumpSize, jumpSpeed) {
	
	//stop the slideIn function for this item (if it is still looping)
	clearTimeout(slideTimeout[itemID]);

	
	//get current height:
	var currentHeight = document.getElementById(itemID).offsetHeight;
		
	//if not already big enough: 
	if (currentHeight < toHeight) {
		
		//+ jumpSize px:
		var newHeight = currentHeight + (jumpSize * 1); //(multiplying converts jumpSize to int (otherwise JS would just append it))
		//if we've jumped above the desired height, shrink back down: 
		if (newHeight > toHeight) { newHeight = toHeight; }
			
		//make the height adjustment:
		document.getElementById(itemID).style.height = newHeight + 'px';
		
		//if height still isn't enough, wait jumpSpeed ms then go again:
		if (newHeight < toHeight) {
			slideTimeout[itemID] = setTimeout("slideOut('"+itemID+"', '"+toHeight+"', '"+jumpSize+"', '"+jumpSpeed+"')", jumpSpeed);
		}
	}		

}



// slideIn function
// slides closed a pane to the given height.
function slideIn(itemID, toHeight, jumpSize, jumpSpeed) {
	
	//stop the slideOut function for this item (if it is still looping)
	clearTimeout(slideTimeout[itemID]);


	//get current height:
	var currentHeight = document.getElementById(itemID).offsetHeight;
	
	//if not already small enough: 
	if (currentHeight > toHeight) {
		
		//- jumpSize px:
		var newHeight = currentHeight - (jumpSize * 1); //(multiplying converts jumpSize to int (otherwise JS would just append it))
		//if we've jumped below the desired height, grow back up: 
		if (newHeight < toHeight) { newHeight = toHeight; }
			
		//make the height adjustment:
		document.getElementById(itemID).style.height = newHeight + 'px';
		
		//if height is still too great, wait jumpSpeed ms then go again:
		if (newHeight > toHeight) {
			slideTimeout[itemID] = setTimeout("slideIn('"+itemID+"', '"+toHeight+"', '"+jumpSize+"', '"+jumpSpeed+"')", jumpSpeed);
		}
	}

}




// SLIDE IN 2 / SLIDE OUT 2 
// (same as above but for horizontal slding)

// store timeouts for each individual sliding item in array (stops them interfering with each other)
// in global so can be accessed by both slideIn2 and slideOut2 functions (so they never overlap and get stuck!)
var slideTimeout2 = new Array(); 



// slideOut2 function
// slides open a pane to the given width. 
function slideOut2(itemID, toWidth, jumpSize, jumpSpeed) {

	//stop the slideIn2 function for this item (if it is still looping)
	clearTimeout(slideTimeout2[itemID]);

	
	//get current width:
	var currentWidth = document.getElementById(itemID).offsetWidth;
		
	//if not already big enough: 
	if (currentWidth < toWidth) {
		
		//+ jumpSize px:
		var newWidth = currentWidth + (jumpSize * 1); //(multiplying converts jumpSize to int (otherwise JS would just append it))
		//if we've jumped above the desired width, shrink back down: 
		if (newWidth > toWidth) { newWidth = toWidth; }

		//make the width adjustment:
		document.getElementById(itemID).style.width = newWidth + 'px';
		
		//if width still isn't enough, wait jumpSpeed ms then go again:
		if (newWidth < toWidth) {
			slideTimeout2[itemID] = setTimeout("slideOut2('"+itemID+"', '"+toWidth+"', '"+jumpSize+"', '"+jumpSpeed+"')", jumpSpeed);
		}
	}		

}



// slideIn2 function
// slides closed a pane to the given width.
function slideIn2(itemID, toWidth, jumpSize, jumpSpeed) {
	
	//stop the slideOut2 function for this item (if it is still looping)
	clearTimeout(slideTimeout2[itemID]);


	//get current width:
	var currentWidth = document.getElementById(itemID).offsetWidth;
	
	//if not already small enough: 
	if (currentWidth > toWidth) {
					
		//- jumpSize px:
		var newWidth = currentWidth - (jumpSize * 1); //(multiplying converts jumpSize to int (otherwise JS would just append it))
		//if we've jumped below the desired width, grow back up: 
		if (newWidth < toWidth) { newWidth = toWidth; }

		//make the width adjustment:
		document.getElementById(itemID).style.width = newWidth + 'px';
		
		//if width is still too great, wait jumpSpeed MS then go again:
		if (newWidth > toWidth) {
			slideTimeout2[itemID] = setTimeout("slideIn2('"+itemID+"', '"+toWidth+"', '"+jumpSize+"', '"+jumpSpeed+"')", jumpSpeed);
		}
	}

}




// FADE IN / OUT:

var fadeInStart = 0; //(start fade in from)
var fadeOutStart = 1; //(start fade out from)
var fadeTimeout; //(stop fade in / out functions from overlapping each other)


// fadeIn function
// fades a layer in.
function fadeIn(itemID, fadeSpeed) {
	
	//stop the fadeOut function (if it is still looping)
	clearTimeout(fadeTimeout);
	//(+ also reset global fadeOutStart so it starts correctly next time):
	fadeOutStart = 1;

	var theItem = document.getElementById(itemID);
	theItem.style.opacity = fadeInStart;
	theItem.style.filter = 'alpha(opacity='+ (fadeInStart * 100) +')'; 
	
	if (fadeInStart < 1) {
		fadeInStart += 0.1;
		fadeTimeout = setTimeout('fadeIn("'+itemID+'", "'+fadeSpeed+'")', fadeSpeed);
	}
	else {
		//reset global fadeInStart for next time:
		fadeInStart = 0;
	}
	
}



// fadeOut function
// fades a layer out. 
function fadeOut(itemID, fadeSpeed) {
			
	//stop the fadeIn function (if it is still looping)
	clearTimeout(fadeTimeout);
	//(+ also reset global fadeInStart so it starts correctly next time):
	fadeInStart = 0;
	
	var theItem = document.getElementById(itemID);	
	theItem.style.opacity = fadeOutStart;
	theItem.style.filter = 'alpha(opacity='+ (fadeOutStart * 100) +')'; 
	
	if (fadeOutStart > 0) {
		fadeOutStart -= 0.1;
		fadeTimeout = setTimeout('fadeOut("'+itemID+'", "'+fadeSpeed+'")', fadeSpeed);
	}
	else {
		//reset global fadeOutStart for next time:
		fadeOutStart = 1;	
	}
		
}




// scrollToTop function
// scrolls browser smoothly up to the top of the page.
function scrollToTop() {
	
	//get the distance the user has scrolled down the page:
	//(Nb, pageYOffset works for FF, Opera, Saf, Netscape and Chrome. IE sees as "undefined")
	var distScrolled = window.pageYOffset;
	
	//(IE understands document.documentElement.scrollTop):
	if (distScrolled == undefined) {
		distScrolled = document.documentElement.scrollTop;
	}
	
	//scroll up by 30px:
	window.scrollBy(0, -30); 
    
	//if we're not at the top of the page yet, do it again:
	if (distScrolled > 0) {
		setTimeout('scrollToTop()', 10); 
	}

}


//===========================================




//===========================================
//  Other Stuff
//===========================================


// openChangeTitleForm function
// slides open the change user title form field on the usercpanel pane
// and also hides the "change" link.
function openChangeTitleForm(theLink) {
	
	slideOut('changetitleform', 28, 10, 70);
	theLink.style.display = 'none';
	
}



// openEditSigForm function
// slides open the edit sig form on the usercpanel pane
// and also hides the "edit signature" link.
function openEditSigForm(theLink) {
	
	slideOut('editsigform', 142, 10, 70);
	theLink.style.display = 'none';	
	
}




// openAdvSearch function 
// slides open the advanced search pane on the nav bar and changes the + link to a -.
function openAdvSearch() {
	
	//fetch the + link and switch it to a -:
	var toggleLink = document.getElementById('searchplus');	
	toggleLink.innerHTML = '&nbsp;-';
	toggleLink.onclick = function() { closeAdvSearch(); return false; };		
	
	//slide out the advanced search pane quickly (height):
	slideOut('advsearchcontainer', 217, 20, 20);
		
	//slide out the advanced search pane quickly (width):
	slideOut2('advsearchcontainer', 219, 20, 20);
	
	//and also fade it in:
	fadeIn('advsearchcontainer', 30);

}



// closeAdvSearch function 
// slides closed the advanced search pane on the nav bar and changes the - link back to a +. 
function closeAdvSearch() {
	
	//fetch the - link and switch it to a +:
	var toggleLink = document.getElementById('searchplus');
	toggleLink.innerHTML = '+';
	toggleLink.onclick = function() { openAdvSearch(); return false; };	
		
	//slide in the advanced search pane quickly (height):
	slideIn('advsearchcontainer', 0, 20, 20);
		
	//slide in the advanced search pane quickly (width):
	slideIn2('advsearchcontainer', 0, 20, 20);

	//and also fade it out:
	fadeOut('advsearchcontainer', 30);

}




// expandMembersViewing function
// slides open the pane on the right to show all of the members viewing.
function expandMembersViewing(theLink) {
	
	//switch the more link to a less link:
	theLink.innerHTML = 'LESS';
	theLink.title = 'close this pane';
	theLink.className = 'lesslink';
	theLink.onclick = function() { contractMembersViewing(theLink); return false; };	
		
	//slide out the members viewing pane to it's full height:
	slideOut('membersviewing', 180, 10, 20);
			
}



// contractMembersViewing function
// slides closed the pane on the right to show only the first 3 members viewing.
function contractMembersViewing(theLink) {
	
	//switch the less link to a more link:
	theLink.innerHTML = 'MORE';
	theLink.title = 'see all members viewing';
	theLink.className = 'morelink';
	theLink.onclick = function() { expandMembersViewing(theLink); return false; };	
		
	//slide in the members viewing pane to it's default height:
	slideIn('membersviewing', 57, 10, 20);
			
}




// showAverageRatingInfo function
// shows the little popup with average rating as a fraction above the little VF faces in the bite us box.
function showAverageRatingInfo() {
		
	var thePopup = document.getElementById('averageratingpopup');
	thePopup.style.display = 'block';
	
	fadeIn('averageratingpopup', 30);
	
}



// hideAverageRatingInfo function
// hides the little popup with average rating as a fraction in. 
function hideAverageRatingInfo() {
		
	fadeOut('averageratingpopup', 30);

	var thePopup = document.getElementById('averageratingpopup');
	thePopup.style.display = 'none';
	
}




// expandRatingForm function
// slides open the pane on the right to show the rating form.
function expandRatingForm(theLink) {
	
	//switch the "rate us" to a "close" link:
	theLink.innerHTML = 'CLOSE';
	theLink.title = 'close this pane';
	theLink.className = 'lesslink';
	theLink.onclick = function() { contractRatingForm(theLink); return false; };	
		
	//slide out the members viewing pane to it's full height:
	slideOut('rateus', 128, 10, 20);
			
}



// contractRatingForm function
// slides closed the pane on the right to hide the rating form.
function contractRatingForm(theLink) {
	
	//switch the "close" link to a "rate us" link:
	theLink.innerHTML = 'RATE US';
	theLink.title = 'rate this cult';
	theLink.className = 'morelink';
	theLink.onclick = function() { expandRatingForm(theLink); return false; };	
		
	//slide in the members viewing pane to it's default height:
	slideIn('rateus', 0, 10, 20);
			
}




//===========================================
//  The New Thread / Post GUI
//===========================================


// simpleBut function
// handles simple buttons on the new thread / post guis.
// (b, i, u, strike, code)
function simpleBut(theForm, tag, name) {

	//first see if any text is selected within the message field:
	var txt = getSelectedText(theForm.message);
		
	//if nothing is selected ask for some text to format:
	if (txt == '' || txt == null) { 	
		txt = prompt('Enter the text to be formatted as '+name+':', ''); 
	}

	//if we got some from somewhere, tag it and insert it: 
	if (txt != '' && txt != null) { 
		
		//nb, if but pressed was code return html-entiterized text instead of tagging it:
		if (tag == 'code') {
			txt = txt.replace(/</g, "&lt;");
			txt = txt.replace(/>/g, "&gt;");
		}
		else {
			txt = '<'+tag+'>'+txt+'</'+tag+'>';  
		}
		
		//insert the final text:
		insertAtCur(theForm.message, txt);	
	}
	
	//if no text to insert, show an error:
	else {
		alert('You didn\'t enter any text to format!');
	}
	
}



// complexBut function 
// handles complex buttons on the new thread / post guis.
// (image, link, image link)
function complexBut(theForm, name) {
	
	//for images: 
	if (name == 'image') { 
		var txt = prompt('Enter the FULL path to your image:', 'http://'); 
	
		if (txt == '' || txt == null || txt == 'http://') { 
			alert('You didn\'t enter an image path!'); 
		}
		else {
			txt = '<img src="'+txt+'" />'; 
		}
	}
	
	//for links / image links:  
	else {		
		var txt = prompt('Enter the FULL address of the page you want to link to:', 'http://'); 
		
		if (txt == '' || txt == null || txt == 'http://') { 
			alert('You didn\'t enter a page url!'); 
		}
		else {
			
			//if it's a plain text link...
			if (name == 'link') {
				//ask for the text to make clickable (page url as default):
				var txt2 = prompt('Enter the text to make clickable:', txt);

				if (txt2 == '' || txt2 == null) { txt2 = txt; }
				txt = '<a href="'+txt+'">[ '+txt2+' ]</a>'; 
			}
			
			//if it's an image link...
			else {
				var txt2 = prompt('Enter the FULL path to your image:', 'http://'); 
	
				if (txt2 == '' || txt2 == null || txt2 == 'http://') { 
					alert('You didn\'t enter an image path!'); 
				}
				else {
					txt = '<a href="'+txt+'"><img src="'+txt2+'" /></a>'; 
				}
			}	
		}
	}

	//if there is text to insert, insert it.
	if (txt != '' && txt != null && txt != 'http://') { 
		insertAtCur(theForm.message, txt);	
	}

}



// selectBox function
// handles select boxes on the new thread / post guis.
// (color, font size, font face)
function selectBox(theForm, name, value) {
	
	//first see if any text is selected within the message field:
	var txt = getSelectedText(theForm.message);
		
	//if nothing is selected ask for some text to format:
	if (txt == '' || txt == null) { 	
		txt = prompt('Enter the text to be formatted in '+name+' '+value+':', ''); 			
	}

	//if we got some from somewhere, tag it and insert it: 
	if (txt != '' && txt != null) { 
		txt = '<font '+name+'="'+value+'">'+txt+'</font>';  
		insertAtCur(theForm.message, txt);	
	}
	
}



// getSelectedText function 
// returns any selected text in the given form field.
function getSelectedText(theField) {	
	
	var txt = '';
	
	//IE6 / Opera9 / Netscape8IE / Aol / Msn / Avant1 / Crazy2
	if (document.selection && document.selection.createRange().text.length > 0) { 
		txt = document.selection.createRange().text;
	}
	//Mozilla1.5 / Netscape8FF
	else if (theField.selectionEnd - theField.selectionStart > 0) { 
		txt = theField.value.substring(theField.selectionStart, theField.selectionEnd); 
	}

	return txt;

}



// insertAtCur function
// inserts new content at the cursor position (within the given field)
// nb, if there is selected text, it will be replaced by the new content.
function insertAtCur(theField, str) {
	
	//IE / Opera / NetscapeIE / Avant / Msn / Crazy etc.
	if (document.selection) {
		theField.focus();
		var sel = document.selection.createRange();
		sel.text = str;
	}
	//Mozilla / NetscapeFF etc.
	else if (theField.selectionStart || theField.selectionStart == 0) {
		var startPos = theField.selectionStart;
		var endPos = theField.selectionEnd;
		theField.value = theField.value.substring(0, startPos) + str + theField.value.substring(endPos, theField.value.length);
	} 
	//Safari / Mac IE / everything else:
	else { 
		//(just tag it on to the end)
		theField.value += str; 
	}

}



// addEmote function 
// adds an emote code to the given field.
function addEmote(emote) {
	var theField = document.getElementById('postguimsg');
	insertAtCur(theField, emote);
}


//===========================================




// showPollOpts function
// opens the poll options bit on the new thread pane.
function showPollOpts(theBut) {
	
	//slide out the poll options pane to its full height:
	slideOut('postnewpoll', 300, 10, 20);

	//when done, scroll the content div so the poll options show:
	scrollToPollOpts();
	
	//hide the add a poll button:
	theBut.style.display = 'none';

}



// scrollToPollOpts function 
// scrolls the new thread / poll container so that the poll options show.
function scrollToPollOpts() {
	
	var pollBit = document.getElementById('postnewpoll');
	
	//if the poll container isn't at full height yet:
	if (pollBit.offsetHeight < 300) {		
		//run this function again:
		setTimeout('scrollToPollOpts()', 20);
	}

	//scroll to view the poll options 
	//(move by a bit everytime this function goes round to keep the scrolling smooth):
	var theContainer = document.getElementById('newthreadpanecontent');		
	var imgBit = document.getElementById('threadattimage');
	theContainer.scrollTop = imgBit.offsetHeight + pollBit.offsetHeight;

}





// showAttImage function
// opens the attach image(s) bit on the new thread pane.
function showAttImage(theBut) {
	
	//slide out the threadattimage pane to its full height:
	slideOut('threadattimage', 135, 10, 20);

	//when done, scroll the content div so the attach image(s) bit shows:
	scrollToAttImage();
	
	//hide the add an image button:
	theBut.style.display = 'none';

}



// scrollToAttImage function 
// scroll the new thread / poll container so that the attach image(s) bit shows.
function scrollToAttImage() {
	
	var imgBit = document.getElementById('threadattimage');

	//if the attach image(s) container isn't at full height yet:
	if (imgBit.offsetHeight < 135) {		
		//run this function again:
		setTimeout('scrollToAttImage()', 20);
	}

	//scroll to view the attach image(s) bit 
	//(move by a bit everytime this function goes round to keep the scrolling smooth):
	var theContainer = document.getElementById('newthreadpanecontent');		
	var pollBit = document.getElementById('postnewpoll');

	if (pollBit.offsetHeight == 0) {
		theContainer.scrollTop = imgBit.offsetHeight;
	}
	else {
		//(if the poll bit is open need to jump up first):
		theContainer.scrollTop = theContainer.offsetHeight - pollBit.offsetHeight + imgBit.offsetHeight;
	}
	
}




// expandForum function
// slides out the threads for the given forum.
function expandForum(forumID, theTd) {
	
	var theTable = document.getElementById('forum'+forumID+'threadstable');
	
	//slide out the forum to the content height:
	slideOut('forum'+forumID+'threads', theTable.offsetHeight, 15, 10);
	
	//change the td onclick action to contract:
	theTd.onclick = function() { contractForum(forumID, theTd); };		

	//get the expand link (arrow in the top right) and change it to a contract link:
	var theLink = document.getElementById('forum'+forumID+'openlink1');
	theLink.title = 'collapse this forum';
	theLink.className = 'forumclose';
	
}



// contractForum function
// slides in the threads for the given forum.
function contractForum(forumID, theTd) {
		
	//slide in the forum to 0:
	slideIn('forum'+forumID+'threads', 0, 15, 10);
	
	//change the td onclick action to contract:
	theTd.onclick = function() { expandForum(forumID, theTd); };		

	//get the contract link (arrow in the top right) and change it to an expand link:
	var theLink = document.getElementById('forum'+forumID+'openlink1');
	theLink.title = 'expand this forum';
	theLink.className = 'forumopen';

//give the forumforumIDthreads div it's slideoutsection class (isn't preset on initially open forums)
document.getElementById('forum'+forumID+'threads').className = 'slideoutsection';
	
}




// stickyTime function
// shows the stickytime select box if "sticky" selected on main staff action select
// (or hides it if another option is selected).
function stickyTime(forumID, optSelected) {
	
	if (optSelected == 'stick') {
		document.getElementById('stickytime'+forumID).style.display = 'inline';
	} 
	else {
		document.getElementById('stickytime'+forumID).style.display = 'none';
	}

}




