// ---------------------------------------------------------------
// Class Faq
// Version: 3.0
// Date: 2004-07-28
// Author: Andreas Doelling (doelling@publicform.de)
//
// Creates dynamic questions & answer list from HTML nodes with 
// the CSS class "question" or "answer" respectively, that are 
// nested in a container with the id [elementId].
// The questions are visible and clickable. The answers are hidden
// and appear when the question is clicked.
// ---------------------------------------------------------------

function Faq(elementId) {
	// -----------------------------------------------------
	// Properties
	// -----------------------------------------------------
	this.faqObj = document.getElementById(elementId);
	this.activeQuestionObj;
	
	
	// -----------------------------------------------------
	// Method init
	// Gets all nodes with the CSS class "answer" that are
	// child nodes of the node with the id [elementId] and 
	// hides them.
	// -----------------------------------------------------
	this.init = function() {
		for(var i=0; i<this.faqObj.childNodes.length; i++) {
			if(this.faqObj.childNodes[i].className == "answer") {
				this.faqObj.childNodes[i].style.display = "none";
			}
		}
	}
	
	
	// -----------------------------------------------------
	// Method addEntry
	// Adds a question/answer pair dynamically.
	// -----------------------------------------------------
	this.addEntry = function(questionHtml, answerHtml) {
		var questionObj = document.createElement("P");
		var questionLinkObj = document.createElement("A");
		questionObj.setAttribute("class", "question");
		questionObj.className = "question"; // for IE
		questionLinkObj.setAttribute("href", "#");
		questionLinkObj.innerHTML = questionHtml;
		this.faqObj.appendChild(questionObj);
		questionObj.appendChild(questionLinkObj);
		var answerObj = document.createElement("P");
		answerObj.setAttribute("class", "answer");
		answerObj.className = "answer"; // for IE
		answerObj.style.display = "none";
		answerObj.innerHTML = answerHtml;
		this.faqObj.appendChild(answerObj);
	}
	
	
	// -----------------------------------------------------
	// Method click
	// Handles click events propagated by a Controller object.
	// -----------------------------------------------------
	this.click = function(evt) {
		if(this != arguments.callee.scope){
			if(typeof arguments.callee.apply == "function") {
			  	return arguments.callee.apply(arguments.callee.scope, arguments);
			} else {
		  		return  arguments.callee.scope.click(evt);
			}
	    }
		var srcElement = (evt.srcElement)? evt.srcElement : evt.target;
		if(this.isResponsible(srcElement)) {
			this.showAnswer(this.getQuestionObj(srcElement));
			return false;
		} else {
			return true;
		}
	}
	this.click.scope = this;
	
	
	// -----------------------------------------------------
	// Method keypress
	// Handles keypress events propagated by a Controller object.
	// -----------------------------------------------------
	this.keypress = this.click;
	this.keypress.scope = this;
	
	
	// -----------------------------------------------------
	// Method keypress
	// Checks if the current Faq instance is responsible for
	// handling the propagated event, i.e. if the source elements
	// CSS class name is "question" and if it a child node
	// of faqObj.
	// -----------------------------------------------------
	this.isResponsible = function(srcElement) {
		var parent = (srcElement.tagName == "BODY")? srcElement : srcElement.parentNode;
		while(parent.tagName != "BODY" && parent.id != this.faqObj.id) {
			srcElement = parent;
			parent = parent.parentNode;
		}
		return (parent.id == this.faqObj.id && srcElement.className == "question");
	}
	
	
	// -----------------------------------------------------
	// Method getQuestionObj
	// Returns the questions container element (e.g. if the
	// event was fired by a STRONG node within the question
	// node.
	// -----------------------------------------------------
	this.getQuestionObj = function(srcElement) {
		var parent = srcElement.parentNode;
		while(parent.id != this.faqObj.id) {
			srcElement = parent;
				parent = parent.parentNode;
		}
		return srcElement;
	}
	
	
	// -----------------------------------------------------
	// Method showAnswer
	// Displays the answer node of the active question node
	// and hides the previously active answer node.
	// -----------------------------------------------------
	this.showAnswer = function(questionObj) {
		if(typeof(this.activeQuestionObj) == "object" && !(questionObj === this.activeQuestionObj)) {
			var currentAnswerObj = this.getAnswerObj(this.activeQuestionObj);
			currentAnswerObj.style.display = "none";
		}
		var answerObj = this.getAnswerObj(questionObj);
		answerObj.style.display = (answerObj.style.display == "block")? "none" : "block";
		this.activeQuestionObj = questionObj;
	}
	
	
	// -----------------------------------------------------
	// Method getAnswerObj
	// Returns the answer object following the given question
	// object.
	// -----------------------------------------------------
	this.getAnswerObj = function(questionObj) {
		var sibling = questionObj.nextSibling;
		while(sibling.tagName != "P" && sibling.className != "answer") {
			sibling = sibling.nextSibling;
		}
		return sibling;
	}
}


