if (top !== self) {
	alert('The URL ' + self.location.href + ' cannot be viewed inside a frame.  You will be redirected.');
	top.location.href = self.location.href;
}

Array.prototype.inArray = function(value) {
	var i;
	for (i = 0; i < this.length; i++) {
		if (this[i] === value) {
			return true;
		}
	}
	return false;
};
/**
 * Main DOM Utility from YUI
 */
var $D = YAHOO.util.Dom, //
$C = $D.getElementsByClassName, //
$E = YAHOO.util.Event, //
$CONN = YAHOO.util.Connect, //
/**
 * A well known magic dollar, known for its extraordinary ability to get DOM
 * element by just the id.
 */
$ = YAHOO.util.Dom.get, //
$LANG = YAHOO.lang, //
$J = YAHOO.lang.JSON, //
$W = YAHOO.widget, //
$L = YAHOO.log;
/**
 * Main Exception class for all things
 * 
 * @param string
 *            message
 * @param string
 *            exceptionName
 * @return void
 */
var TQException = function(message, exceptionName) {
	this.message = message;
	this.name = exceptionName || "TQException";
};
/**
 * 
 */
oAjaxObject = {
handleSuccess : function(o) {
	$L('39 start handleSuccess ', 'error');
	$L('40 o ' + $LANG.dump(o));
	/**
	 * Turn back all previously disabled buttons and elements to enabled
	 */
	oTQ.formElements.enable();
	oTQ.alerter.hide();

	var el, id, json, sDoc, sTpl, errDiv, strMessage = '', //
	eLogin = $("loginHead"), // was nbar
	strContentType = $LANG.trim(o.getResponseHeader["Content-Type"]);
	// alert(strContentType);
	switch (strContentType) {
	case 'text/json; charset=UTF-8':
		try {
			json = $J.parse(o.responseText);
			// alert($LANG.dump(json));
		} catch (e) {
			alert("Invalid json data in responceText " + $LANG.dump(e) + " strContentType " + strContentType + "\noRespnose: " + $LANG.dump(o.responseText));
		}

		switch (true) {

		case json.hasOwnProperty('exception'):
			alert(json.exception);
			break;
		/*
		 * if (json.hasOwnProperty('errHeader')) { strMessage += '<u>' +
		 * json.errHeader + '</u><br>'; }
		 * 
		 * errDiv = document.createElement('div'); errDiv.id = 'exc'; var
		 * mainDiv = $('main'); $D.insertBefore(errDiv, mainDiv.firstChild);
		 * 
		 * errDiv.innerHTML = strMessage + json.exception; if ($('go')) {
		 * $('go').disabled = false; }
		 */
		break;

	case json.hasOwnProperty('redirect'):
		window.location.assign(json.redirect);
		break;

	case json.hasOwnProperty('welcome'):
		oTQ.processLogin(json);
		break;

	/**
	 * if json contains object 'replace' then replace contents of DOM elements
	 * with id by json.replace keys with corresponding json.replace[key] values
	 */
	case json.hasOwnProperty('replace'):
		for (id in json.replace) {
			$L('87 replace this element id: ' + id, 'error');
			el = $(id);
			$L('94 el: ' + el);
			if (el) {
				el.innerHTML = json.replace[id];
			}
		}
		break;

	/**
	 * TODO the entire string will be sent in json, along with image, so we cant
	 * use onClick then but should instead just subscribe the new element to the
	 * onClick event somehow, maybe by calling subscribeSignup() or something
	 * like that.
	 */
	case json.hasOwnProperty('loginerr'):
		strMessage = '<div class="loginerr">' + json.loginerr + '</div>';
		strMessage = strMessage + '<div class="sign"><img src="/images/signin.png"/ onClick="oTQ.Twitter.startDance()" class="twitsign"><br><span class="signup">Don\'t have an account?<br /> <a href="#">Signup now</a></span></div>';
		alert(strMessage);
		break;

	case json.hasOwnProperty('answer'):
		oTQ.checkAnswer(json.answer);
		break;

	case json.hasOwnProperty('review'):
		oTQ.reviewAnswered(json.review);
		break;

	}

}
},
handleFailure : function(o) {
oTQ.formElements.enable();
alert($LANG.dump(o));
}
};
/**
 * Namespace for all objects and functions
 */
var oTQ = {
toString : function() {
	return 'object oTQ';
},
/**
 * Converts unix timestamp into javascript Date object This is used as formatter
 * function in some of the datatable callbacks
 */
myTsParser : function(i) {
	return new Date(i * 1000);
},
/**
 * Formatter for datatable to use the value of string to make an image tag to
 * display user's avatar
 * 
 * @param oData
 *            is just the value of the data for this cell in this case this is
 *            just a string - a full image path
 * 
 * @param oRecord
 *            the complete record for making the row of table, not just this
 *            cell. This can be usefull if we need to have value of userID in
 *            addition to the value of data for this cell, like we can have
 *            username in this cell but we can use userid to make a complete
 *            link to user where userid will be part of href and username is
 *            title of link
 */
myFormatAvatar : function(elCell, oRecord, oColumn, oData) {
	elCell.innerHTML = '<img src="' + oData + '" width="32px" height="32px">';
},
myFormatScreenName : function(elCell, oRecord, oColumn, oData) {
	elCell.innerHTML = '@' + oData;
},
myFormatIsCorrect : function(elCell, oRecord, oColumn, oData) {
	var className = ('Y' == oData) ? 'check' : 'x';
	elCell.innerHTML = '<div class="' + oData + '">&nbsp;</div>';
},
myFormatFav : function(elCell, oRecord, oColumn, oData) {
	var className = ('0' == oData) ? 'myfavorite' : 'notfav';
	elCell.innerHTML = '<div class="stars ' + className + '">&nbsp;</div>';
},
/**
 * Formatter for dataTable date cell
 */
myFormatDate : function(elCell, oRecord, oColumn, oData) {
	var oDate = oData, sMonth;
	switch (oDate.getMonth()) {
	case 0:
		sMonth = "Jan";
		break;
	case 1:
		sMonth = "Feb";
		break;
	case 2:
		sMonth = "Mar";
		break;
	case 3:
		sMonth = "Apr";
		break;
	case 4:
		sMonth = "May";
		break;
	case 5:
		sMonth = "Jun";
		break;
	case 6:
		sMonth = "Jul";
		break;
	case 7:
		sMonth = "Aug";
		break;
	case 8:
		sMonth = "Sep";
		break;
	case 9:
		sMonth = "Oct";
		break;
	case 10:
		sMonth = "Nov";
		break;
	case 11:
		sMonth = "Dec";
		break;
	}
	elCell.innerHTML = sMonth + " " + oDate.getDate() + ", " + oDate.getFullYear();
},
reviewAnswered : function(o) {
	$L('208 this is ' + this); // object oTQ

	oRenderer = this.qRenderer(o);
	eDiv = oRenderer.getRendered();

	$('main2').replaceChild(eDiv, $('main2').firstChild);
	this.checkAnswer(o);
},
/**
 * Create html table dynamically
 * 
 * @param oRows
 *            object must have element 'count' to indicate how many rows to
 *            create
 * 
 * @param object
 *            oCols must have element 'count' to indicate how many 'td' to
 *            create per row
 * 
 * @return DOMElement table This element is not in the DOM tree! must append it
 *         manually somewhere
 */
createTable : function(oRows, oCols) {

	var eRow, eTable = document.createElement('table');
	b = (oRows.count - 1), createTr = function() {
		var eTd, iWidth = Math.round(100 / oCols.count), eTr = document.createElement('tr');
		// alert('width: ' + iWidth);
		for ( var i = 0; i < oCols.count; i += 1) {
			eTd = document.createElement('td');
			eTd.setAttribute('width', iWidth + '%');
			eTr.appendChild(eTd);
		}

		return eTr;
	};

	eRow = createTr();
	eTable.appendChild(eRow);
	for ( var i = 0; i < b; i += 1) {
		eTable.appendChild(eRow.cloneNode(true));
	}

	return eTable;
},
/**
 * Callback to login the user this is called from the oAuth popup window OR can
 * be called from Ajax callback if AsyncRequest was used to check login status
 * 
 * This method will set meta session-tid to user_id, will replace the welcome
 * block with the one from the object and IF not in someone else's page, then
 * will set style, background, etc to styles from o.profile
 */
processLogin : function(o) {
	$L('119 this is: ' + this); // object oTQ when called from popup
	// alert($LANG.dump(o));
	$L('122 o: ' + $LANG.dump(o), 'warn');
	var sCurLocation, eWelcome = $('welcome'), eException = $('excsl');
	;
	this.Twitter.cancelIntervals();
	this.Twitter.cancelAsyncCalls();

	/**
	 * If the page has div id 'exc' with class 'login' this means there was an
	 * error with text Must Login In this case we must reload the current
	 * location
	 * 
	 */

	if (eException && 'login' === eException.className) {
		window.location.reload();
	}

	if (o.welcome && eWelcome) {
		eWelcome.innerHTML = o.welcome;
		setTimeout("oTQ.fColorChange('welcome', '#FF0000', '#00FF00')", 500);
	}

	if (o.profile && o.profile.user_id) {
		this.setMetaTag('session-tid', o.profile.user_id);
		/**
		 * In case the alert window is still opened from displaying an
		 * exception, especially the case with login exception when the oAuth
		 * dance is started from the alerted panel, we must now close it
		 */
		oTQ.alerter.hide();
		/**
		 * Process pending functions that were depending on the user to login
		 */
		this.processPending();
	}

	if (o.profile && o.profile.screen_name) {
		this.setMetaTag('screen_name', o.profile.screen_name);
	}
},
/**
 * Array of pending methods that need to be executed after the user authorized
 * with Twitter
 * 
 * @todo make this an object with closure based private var so that actual
 *       pending queue is private and cannot be accessed directly, then add
 *       addPending(method) and clearPending() methods as well as getPending()
 *       for debugging
 */
aPending : [],
/**
 * Execute the sMethod only after an authorization with Twitter but if already
 * logged in, then execute right away
 * 
 * @param string
 *            sMethod name of method to execute should be full path to method,
 *            not sure which context we will be in, so better to use the full
 *            path.
 */
authAndPost : function(sMethod) {
	$L('126 cp sMethod: ' + sMethod + ' this: ' + this); // this is object
	// oTQ
	if (this.isLoggedIn()) {
		sMethod();
	} else {
		$L('154 user not logged in, adding job to pending', 'error');
		this.aPending.push(sMethod);
		this.Twitter.startDance();
	}
},
/**
 * Execute pending methods after the login
 */
processPending : function() {
	var res, pending, i = 0, count = this.aPending.length;
	$L('164 number of pending jobs: ' + count);

	while (this.aPending.length > 0) {
		(this.aPending.shift())();
	}
},
/**
 * Get value of specific meta tag This assumes that meta tag name is unique -
 * only appears once in the meta tags If meta tag not found then returns false
 * 
 * @param string
 *            sMetaName name of meta tag of which we need the value
 * 
 * @param book
 *            bAsElement if passed and is true then return the actual DOMElement
 *            for that meta tag instead of just the value
 */
getMeta : function(sMetaName, bAsElement) {
	$L('182 looking for meta tag ' + sMetaName);
	var el, i, aMeta = document.getElementsByTagName('meta');
	$L('43 ' + $LANG.dump(aMeta) + ' total metas: ' + aMeta.length);
	if (!aMeta) {
		$L('45 no meta tags in document', 'error');
		return false;
	}

	for (i = 0; i < aMeta.length; i += 1) {
		if (aMeta[i].name && (aMeta[i].name == sMetaName) && aMeta[i].content) {
			if (bAsElement) {
				var el = aMeta[i];
				$L('213 meta tag element ' + el);

				return el;
			}

			return aMeta[i].content;
		}
	}

	return false;
},
/**
 * Test to determine if page is being viewed by a logged in user a logged in
 * user has the session-tid meta tag set to value of twitter userid
 */
isLoggedIn : function() {
	$L('64 this is: ' + this); // oTQ

	var ret, tid = this.getMeta('session-tid');
	$L('67 tid: ' + tid);

	ret = (tid && (tid !== '') && (tid !== '0'));

	$L('66 ret: ' + ret);

	return ret;
},
/**
 * Set the value of meta session-tid
 */
setMetaTag : function(name, val) {
	var eMeta = this.getMeta(name, true);
	if (eMeta) {
		eMeta.content = val;
	}

	$L('249 meta set, now: ' + this.getMeta(name));
},
/**
 * Get value of 'mytoken' meta tag which serves as a security token for form
 * validation.
 */
getToken : function() {
	var token = this.getMeta('mytoken');
	return token;
},
/**
 * Set (update) the value of meta name="mytoken" meta tag with the new value
 */
setToken : function(val) {
	var el = this.getMeta('mytoken', true);
	el.setAttribute('content', val);
},
/**
 * Callback object to handle ajax based returns
 */
oCallback : {
success : oAjaxObject.handleSuccess,
failure : oAjaxObject.handleFailure,
scope : oAjaxObject
}
};
oTQ.fColorChange = function(el, sFromColor, sToColor) {
	$L('starting fColorChange for ' + el);
	var myChange, curBg, myChangeBack, //              
	element = (typeof el === 'string') ? $(el) : el, //
	sToColor = (sToColor && typeof sToColor === 'string') ? sToColor : '#FF0000', //
	sFromColor = (sFromColor && typeof sFromColor === 'string') ? sFromColor : '#FFFFFF';

	$L('element is: ' + element);

	if (element) {

		curBg = $D.getStyle(element, 'background-color');
		$D.setStyle(element, 'background-color', sFromColor);
		myChange = new YAHOO.util.ColorAnim(element, {
			backgroundColor : {
				to : sToColor
			}
		});

		/**
		 * Change the background back to what if was before the animation
		 * started
		 */
		myChangeBack = function() {
			element.style.backgroundColor = curBg;
		};

		myChange.onComplete.subscribe(myChangeBack);
		myChange.animate();

	}
}, //
/**
 * Show the error message on the page
 * 
 * @param string
 *            sMessage error message to display
 * @param string|node
 *            DOMNode before which to insert the div 'error' in case the 'error'
 *            div does not exist yet
 */
oTQ.displayError = function(sMessage, eInsertBefore) {
	$L('52 sMessage: ' + sMessage + ' eInsertBefore ' + eInsertBefore + ' this: ' + this, 'error'); // this
	// object
	// oTQ
	var eParent, eErrDiv = $('err');
	$L('54 eErrDiv: ' + eErrDiv);
	/**
	 * If div #err does not exist, then create it and insert it
	 */
	if (!eErrDiv) {

		eErrDiv = document.createElement('div');
		eErrDiv.id = 'err';

		if (eInsertBefore && $LANG.isString(eInsertBefore)) {
			eInsertBefore = $(eInsertBefore);
		}

		/**
		 * If eInsertBefore is not provided then insert it as the first child of
		 * the #main div
		 */
		if (!eInsertBefore) {
			eInsertBefore = $('main');
		}

		$L('78 eInsertBefore: ' + eInsertBefore);
		eParent = eInsertBefore.parentNode; // undefined for a button object
		// because its not a DOMNode
		$L('80 parent: ' + eParent);

		eErrDiv = eParent.insertBefore(eErrDiv, eInsertBefore);
	}

	if (eErrDiv && $D.hasClass(eErrDiv, 'hidden')) {
		$D.removeClass(eErrDiv, 'hidden');
	}

	eErrDiv.innerHTML = sMessage;
	this.fColorChange(eErrDiv, '#FFFFFF', '#FF0000');

};
/**
 * If div with id 'err' exists on the page and is not hidden, then hide it by
 * adding the 'hidden' class to it
 */
oTQ.removeError = function() {
	var eErrDiv = $('err');
	if (eErrDiv && !$D.hasClass(eErrDiv, 'hidden')) {
		$D.addClass(eErrDiv, 'hidden');
	}

};
/**
 * Listener for all click events inside the #main div
 */
oTQ.handleClick = function(o) {
	var target = $E.getTarget(o);

	$L('44 target is ' + target + ' this: ' + this, 'warn');
	if (target.id) {
		switch (target.id) {

		case 'delExplanation':
			$L('173 going to remove explanation ' + this); // qMaker (good)
			if (this.oQmaker) {
				this.oQmaker.removeExplanation();
			}
			break;

		case 'signin':
			this.Twitter.startDance();
			break;
		}
	} else {
		// $L('182 classname: ' + target.className);
		/**
		 * Cannot just use target.className because target may have multiple
		 * class names so instead must use the hasClass() check
		 */
		switch (true) {

		case $D.hasClass(target, 'delete'):
			if (this.oQmaker) {
				this.oQmaker.deleteAnswer(target);
			}
			break;

		case $D.hasClass(target, 'correct'):
			if (this.oQmaker) {
				this.oQmaker.toggleAsCorrect(target);
			}
			break;

		case $D.hasClass(target, 'answer'):
			this.toggleCheckedAnswer(target);
			break;
		}
	}
};
/**
 * When user clicks inside the element that holds the body of the answer, change
 * the checked/unchecked box for that answer
 * 
 * If answers are radio buttons then select that radio button, (but don't do any
 * 'unselect') for radio button because it just does not make sense
 */
oTQ.toggleCheckedAnswer = function(e) {
	var eTr, input;
	$L('83 e: ' + e);
	eTr = $D.getAncestorByTagName(e, 'tr');
	if (!eTr) {
		throw new TQException('unable to find ancestor tr element');
	}

	input = eTr.getElementsByTagName('input')[0];

	$L('91 input ' + input);
	/**
	 * Don't do any toggle for disabled input elements
	 */
	if (!input.disabled) {
		switch (input.type) {
		case 'checkbox':
			input.checked = (!input.checked);
			break;

		case 'radio':
			input.checked = true;
			break;
		/**
		 * Text input type of answer not yet implemented What should be done
		 * anyway? Probably just set focus, that's all
		 */
		case 'text':
			input.focus();
			break;

		}
	}

};
/**
 * Fired from the 'submit answer' button Must parse the question form and send
 * it to the server via $CONN (via ajax)
 * 
 * But in the preview mode it will NOT submit form to server, instead it will
 * just check the answer against correct answers and render the
 * correct/incorrect and 'result' block and optionally the 'explanation' block
 * 
 * @param object
 *            e Event object that triggered this method
 * 
 * @param object
 *            oBtn - to be removed as we don't really use it anymore because the
 *            this refers to the same object anyway
 */
oTQ.processAnswer = function(e) {

	var o = e.target;
	$L('50 this is ' + this); // object Button doit
	$L('53 ' + $LANG.dump(o.form)); // object HTMLForm

	/**
	 * Regardless of where we at (preview mode or actual answering of question)
	 * we must first do a small validation to make sure at least one answer was
	 * selected
	 */

	oTQ.removeError();
	if (!oTQ.isAnswerSelected()) {
		/**
		 * @todo translate string
		 */
		oTQ.displayError('You have not selected any answers yet', 'doit');

		return false;
	}
	/**
	 * This is how we know we are in the editor/preview mode: because we have
	 * the oTQ.oQmaker object
	 */
	if (oTQ.oQmaker) {
		oTQ.checkAnswer();
	} else {

		// call method to submit form via Ajax
		/**
		 * Need to disable to form so that user cannot change anything after the
		 * answer was selected/submitted but before the response is received
		 * from the server.
		 */
		/*
		 * var i, elements = o.form.elements; for (i = 0; i < elements.length; i +=
		 * 1) { if (elements[i].type !== 'hidden') { elements[i].disabled =
		 * true; } }
		 */
		this.set('disabled', true);

		// $D.addClass($('doit-button'), 'button-loading');
		oTQ.authAndPost(oTQ.postAnswer);
		oTQ.formElements.addLoaderClass($('doit-button'));
	}

};
/**
 * Parse the question form and post it to server via YUI connection manager but
 * first extract the value of security token from meta and append it to the form
 * 
 */
oTQ.postAnswer = function() {
	$L("536 this is: " + this); // object Window
	var elToken, sToken = oTQ.getToken(), oFrm = $('tq'), i, elements = oFrm.elements;
	$L('538 cp sToken: ' + sToken);
	/**
	 * Must manually add token to form it's safer than using setForm and then
	 * adding it as extra param because $CONN gets confused and threads 4th arg
	 * as indication that form has file upload
	 */
	elToken = document.createElement('input');
	elToken.setAttribute('type', 'hidden');
	elToken.setAttribute('name', 'token');
	elToken.setAttribute('value', sToken);
	oFrm.appendChild(elToken);

	/**
	 * Must run setForm before disabling input elements otherwise the setForm
	 * will not be able to extract the value of these selected elements
	 */
	$CONN.setForm(oFrm);
	oTQ.connObj = $CONN.asyncRequest('POST', "/index.php", oTQ.oCallback); // ,
	// "token="
	// +
	// sToken

	for (i = 0; i < elements.length; i += 1) {
		if (elements[i].type !== 'hidden') {
			elements[i].disabled = true;
		}
	}
};
/**
 * Check to see wheather or not at least one answer choice has been selected
 * 
 * @todo add special validation for textarea/text type of answers
 */
oTQ.isAnswerSelected = function() {
	$L('281 cp', 'error');
	var i, oFrm = $('tq'), aInputs, input;

	$L('283 cp', 'error');
	if (!oFrm) {
		alert('104 no tq');
		throw new TQException('Form with id "tq" not found on the page');
	}

	aInputs = oFrm.elements;
	$L('290 aInputs: ' + aInputs.length);

	for (i = 0; i < aInputs.length; i += 1) {
		input = aInputs[i];
		// $L('294 ' + input);
		switch (input.type) {
		case 'radio':
		case 'checkbox':
			$L('298 cp ' + input.type);
			if (input.checked) {

				return true;
			}
			break;

		case 'text':
		case 'textarea':
			if ('' !== $LANG.trim(input.value)) {
				return true;
			}
			break;
		}
	}

	$L('314 cp ', 'warn');
	return false;

};
/**
 * Check the submitted answer against the correct answers the correct answers
 * are present in the oQ.aAnswers array
 * 
 * But in review mode no oQ is passed, so we will just get it from the
 * oTQ.oQmaker object and it already has some answers marked as 'iscorrect' by
 * the question maker
 * 
 * @param object
 *            oQ object of question when returned from server via Ajax after the
 *            'submit answer' call, it must contain the aAnswers key with array
 *            of answers and each answer must contain aid, and iscorrect
 * 
 */
oTQ.checkAnswer = function(oQ) {
	$L('638 checking answer. this is: ' + this, 'error'); // object oTQ
	this.oResult = oQ;
	var i, j,
	/**
	 * Object of one answer this is from the oQ (not the user's responce, but
	 * the actual answer as returned from server via AJAX or if in preview mode,
	 * the actual oQ.aAnswers[i] object
	 */
	ans,
	/**
	 * Array like object of correct answers. Keys are answer id (aid) values are
	 * answer letters
	 */
	oCorrect = {},
	/**
	 * Real array of correct answers, holds answer letters of correct answers I
	 * know this duplicates some data in oCorrect but its for conveniencse so we
	 * can use the length property of aCorrect and compare to length property of
	 * aYours
	 */
	aCorrect = [],
	/**
	 * Real array with user answers 'your answers' where values are answer
	 * letters This will be used for displaying 'your answers' in the results
	 * block
	 */
	aYours = [],
	/**
	 * Array of user responces that are correct this is for convenience to
	 * determine if user answer is correct or not
	 */
	aYoursCorrect = [],
	/**
	 * Array of tr elements with class 'choice'
	 */
	aTrs;
	if (!oQ) {
		if (!oTQ.oQmaker) {
			throw new TQException('object oQ not supplied and NOT in question maker mode');
		}

		oQ = oTQ.oQmaker.getQuestion();
	}

	$L('99 oQ: ' + $LANG.dump(oQ), 'error');

	if (!$('tq')) {
		alert('104 no tq');
		throw new TQException('Form with id "tq" not found on the page');
	}

	aTrs = $C('choice', 'tr', $('tq'));

	/**
	 * Array of answers the correct answers will have iscorrect = true
	 */
	var aAns = oQ.aAnswers;
	$L('114 aAns: ' + $LANG.dump(aAns), 'error');

	/**
	 * Make array-like object of correct answers key is aid (answer ID), value
	 * is answer letter (A,B,C...)
	 */
	for (i = 0; i < aAns.length; i += 1) {
		// $L('132 cp');
		ans = aAns[i];
		$L('133 ans: ' + $LANG.dump(ans));
		if (aAns[i].iscorrect) {
			oCorrect[ans['aid']] = ans['letter'];
			aCorrect.push(ans['letter']);
		}
	}

	$L('139 ' + $LANG.dump(oCorrect) + ' aCorrect ' + $LANG.dump(aCorrect));

	var checkTr = function(eTr) {
		var input, eTdAns, val, letter, eAnsTd = $C('answer', 'td', eTr)[0];
		input = eTr.getElementsByTagName('input')[0];

		/**
		 * Remove all extra classes from eAnsTd This is necessary in the preview
		 * mode when creator of questions tests the answer choices so that on
		 * every 'answer' click the correct-choice and incorrect-choice classes
		 * are removed in case they were set during the previous answer test
		 */
		eAnsTd.className = 'answer';

		switch (input.type) {
		case 'radio':
		case 'checkbox':
			$L('142 input ' + input.type);
			val = input.value;
			letter = $C('order', 'td', eTr)[0].innerHTML;
			$L('166 letter: ' + letter);
			/**
			 * Correct choices are always visually marked as 'correct'
			 */
			if (oCorrect[val]) {

				$D.addClass(eAnsTd, 'correct-choice');
			}

			if (input.checked) {
				$L('144 radio/checkbox selected', 'info');
				aYours.push(letter);

				/**
				 * Incorrect choices are marked as incorrect and added to
				 * aIncorrect array
				 */
				if (!oCorrect[val]) {
					$L('446 selected value is INCORRECT', 'error');
					eAnsTd = $C('answer', 'td', eTr)[0];

					$D.addClass(eAnsTd, 'incorrect-choice');
				} else {
					$L('462 selected value is correct', 'window');
					aYoursCorrect.push(letter);
				}
			}

			break;
		/**
		 * Not yet implemented
		 */
		case 'text':

			break;

		}

		$L('168 letter: ' + letter + ' val: ' + val, 'window');
	};

	/**
	 * Check if user's responce is the correct answer If oQ has iscorrect
	 * property, then return it, otherwise return correct IF aYoursCorrect has
	 * the same number of elements as aCorrect
	 */
	var isAnsweredCorrectly = function() {
		$L('475 cp has oQ: ' + oQ);

		if (oQ && oQ.iscorrect) {
			$L('478 have result of isCorrect in supplied oQ: ' + oQ.iscorrect);

			return oQ.iscorrect;
		}
		/**
		 * In case of checkboxes we say the answer is correct ONLY when user
		 * selected ALL correct answerws and NONE of incorrect answers
		 * 
		 * This extra check does not change the outcome in case of radio boxes
		 * 
		 * @todo in case of text or textarea input we need a different way to
		 *       determine correct answer
		 * 
		 * @todo in case of partial credit we need an extra method calculate a
		 *       partial credit in case user selects only 'some' of correct
		 *       answers and in case user selects some of 'incorrect' answers we
		 *       need to deduct points for that We also need the return value to
		 *       be 1 of 3 possible choices: correct, incorrect or partially
		 *       correct
		 * 
		 */
		$L('495 aYours: ' + $LANG.dump(aYours) + ' aYoursCorrect: ' + $LANG.dump(aYoursCorrect) + ' aCorrect: ' + $LANG.dump(aCorrect));
		var ret = ((aYoursCorrect.length === aYours.length) && (aYoursCorrect.length === aCorrect.length));
		$L('496 ret: ' + ret, 'window');

		return ret;

	};
	/**
	 * Get the text for the 'passfail' td element 'Congratulations your answer
	 * is correct' Or 'Your answer is incorrect'
	 * 
	 * @return string text of the pass/fail result
	 * 
	 * @todo translate the string
	 */
	var getPassFailText = function() {
		$L('511 getting pass/fail');
		var sRet = isAnsweredCorrectly() ? 'Congratulations! Your answer is correct' : 'Your answer is incorrect';
		$L('487 ret: ' + sRet);

		return sRet;
	};

	/**
	 * The div with id "result" must be somewhere on the html page Its just
	 * there as a template, it always has the 'hidden' class
	 * 
	 * we then clone it, fill the tds with data and insert into DOM after the
	 * button.
	 * 
	 */
	var showResultBlock = function() {
		var eRes = $('result'),
		/**
		 * Div that holds 'result' block
		 */
		eResultDiv,
		/**
		 * DOM element 'td' with id 'passfail' this is where we put text like:
		 * Congratulation or 'Incorrect'
		 */
		tdPassFail,
		/**
		 * Classname for the 'td' of results text Congratulations! or 'Your
		 * answer is incorrect'
		 */
		sClassname = (isAnsweredCorrectly()) ? 'pass' : 'fail';
		$L('546 sClassname: ' + sClassname);

		/**
		 * If eMyRes already made and appended then just skip this step This is
		 * in case question maker keeps testing different answers
		 */
		if (!$('myresult')) {
			if (!eRes) {
				throw new TQException('Div with id "result" not found on page');
			}

			eResultDiv = eRes.cloneNode(true);
			$D.removeClass(eResultDiv, 'hidden');
			eResultDiv.id = 'myresult';

			$('qdiv').appendChild(eResultDiv);
		}

		tdPassFail = $('passorfail');
		$L('566 tdPassFail: ' + tdPassFail);
		tdPassFail.className = sClassname;
		tdPassFail.innerHTML = getPassFailText();
		$('correct').innerHTML = aCorrect.join(', ');
		$('yours').innerHTML = aYours.join(', ');
		if (oQ.explanation && '' !== oQ.explanation) {
			$D.removeClass($('qexplain'), 'hidden');
			$C('expl', 'td', $('qexplain'))[0].innerHTML = oQ.explanation;
		}

	};
	/**
	 * After answer has been checked on server, the server sends the complete
	 * html for the result block we just have to append it
	 */
	var makeResultBlock = function() {
		$L('883 makeResultBlock this is ' + this); // object Window

		var toggleClass = function() {
			var sClass = ('addfav' === $('favorite').className) ? 'favorite' : 'addfav';
			$('favorite').className = sClass;
		};
		var eTable, //
		aTs, //
		oBtnLike, //
		oBtnTweetAns, //
		eResultDiv = document.createElement('div'), //
		eTweetThis = document.createElement('div'), //
		eFavDiv = document.createElement('div'), //
		eLike = document.createElement('div');
		eLike.id = 'like';
		eLike.className = 'rounded';

		eFavDiv.id = 'favorite';

		eTable = oTQ.createTable( {
			count : 1
		}, {
			count : 3
		});
		eTable.id = 'tweetbtns';
		aTds = eTable.getElementsByTagName('td');

		eResultDiv.id = 'myresult';
		$('qdiv').appendChild(eResultDiv);
		eResultDiv.innerHTML = oQ.result;

		eTweetThis.id = 'tweetthis';
		eTweetThis.className = 'rounded';

		aTds[0].appendChild(eTweetThis);
		aTds[1].appendChild(eLike);

		if (oQ.fav) {
			/**
			 * Initially set className to addfav
			 */
			eFavDiv.className = (!oQ.fav.is_fav) ? 'addfav' : 'favorite';

			if (oQ.fav.text) {
				eFavDiv.innerHTML = oQ.fav.text;
			}

			if (oQ.fav.ttl) {
				eFavDiv.title = oQ.fav.ttl;
			}

			$E.addListener(eFavDiv, "click", function(e) {
				var target = $E.getTarget(e), token = oTQ.getToken();
				toggleClass();
				$CONN.asyncRequest('POST', "/index.php", oTQ.oCallback, 'a=addfavorite&token=' + token + '&qid=' + oQ.qid);
			});

			aTds[2].appendChild(eFavDiv);
			aTds[2].className = 'vm';
		}

		$('qdiv').appendChild(eTable);

		oTQ.oBtnTweetAns = new $W.Button( {
		id : "btntweetans",
		type : "button",
		label : "Tweet your result",
		title : "Tweet about this question",
		container : eTweetThis
		});
		oTQ.oBtnTweetAns.on("mousedown", oTQ.tweetResult); // , oQ, oTQ

		oBtnLike = new $W.Button( {
		id : "btnlike",
		type : "button",
		label : "Like!   ",
		title : "Click if you like this question",
		container : eLike
		});
		oBtnLike.on("mousedown", oTQ.postLike, oBtnLike);

	};

	/**
	 * Traverse the tr elements with class 'choice' and check the input elements
	 * in its' td class 'check' add to aSelected and visually mark the 'td' as
	 * correct/incorrect choice
	 * 
	 * Correct answers are always marked with adding green class
	 * 
	 * Incorrect choices are makred with adding red class
	 */
	for (j = 0; j < aTrs.length; j += 1) {
		checkTr(aTrs[j]);
	}

	$L('467 Yours: ' + $LANG.dump(aYours), 'window');
	if (oQ.result) {
		makeResultBlock();
	} else {
		showResultBlock();
	}

};
/**
 * Object responsible for rendering the actual question: question body, form,
 * answer choices, answer bodies, 'answer' button
 * 
 * as well as 'result' block
 * 
 * 
 * @constructor makes object that will render the HTML to display the question
 *              form
 * 
 * @param oQ
 *            object Question
 */
oTQ.qRenderer = function(oQ) {

	/**
	 * Private vars through closure initially will create <div id="qdiv"> <form
	 * name="quest" id="quest" action="/index.php" method="post"> <table
	 * id="qtable">
	 * <tr>
	 * <td colspan="3"> <div id="qbody">
	 * 
	 * </div> </td>
	 * </tr>
	 * 
	 * 
	 * </table> </form> </div>
	 */

	var that, eDiv, eTable, eTd1, eTdCheck, eTdAns, eTr, eQbody, eTdBody, eFrm, eTblResult,
	/**
	 * The YUI button for the 'submit answer' button We need to destroy it when
	 * switching back to edit mode so that the event listener will be removed
	 */
	oBtn;
	eDiv = document.createElement('div');
	eDiv.id = 'qdiv';

	eFrm = document.createElement('form');
	eFrm.name = eFrm.id = 'tq';
	eFrm.method = 'POST';
	eFrm.action = '/index.php';
	eFrm.enctype = 'application/x-www-form-urlencoded';
	eFrm.acceptCharset = 'utf-8';

	var eInputA = document.createElement('input');
	eInputA.setAttribute('type', 'hidden');
	eInputA.setAttribute('name', 'a');
	eInputA.setAttribute('value', 'answer');

	var eInputB = document.createElement('input');
	eInputB.setAttribute('type', 'hidden');
	eInputB.setAttribute('name', 'qid');
	eInputB.setAttribute('value', oQ.qid);

	eFrm.appendChild(eInputA);
	eFrm.appendChild(eInputB);

	eDiv.appendChild(eFrm);

	eTable = document.createElement('table');
	eTable.id = 'qtable';
	eTable.setAttribute('cellpadding', '5');
	eTable.setAttribute('cellspacing', '0');

	eFrm.appendChild(eTable);

	eTdBody = document.createElement('td');
	eTdBody.setAttribute('colspan', '3');

	eQbody = document.createElement('div');
	eQbody.id = 'qbody';

	eTdBody.appendChild(eQbody);

	eTable.appendChild(document.createElement('tr')).appendChild(eTdBody);

	eTd1 = document.createElement('td');
	eTd1.className = 'order';

	eTdCheck = document.createElement('td');
	eTdCheck.className = 'check';

	eTdAns = document.createElement('td');
	eTdAns.className = 'answer';
	eTdAns.setAttribute('width', '98%');

	eTr = document.createElement('tr');
	eTr.className = 'choice';
	eTr.appendChild(eTd1);
	eTr.appendChild(eTdCheck);
	eTr.appendChild(eTdAns);

	/**
	 * Create submit button but don't attach to DOM yet
	 */
	var eSubmit = document.createElement('input');
	eSubmit.setAttribute('type', 'submit');
	eSubmit.name = eSubmit.id = 'doit';
	eSubmit.value = 'Submit answer';

	that = {

	destroySubmitButton : function() {
		if (oBtn) {
			oBtn.destroy();
		}
	},
	/**
	 * Render the question table inxide the div and return the div element
	 * 
	 * @todo add validation of oQ to make sure it has required elements
	 * 
	 * @return object DOMNode div with id 'qdiv'
	 */
	getRendered : function() {
		var i, aAns = oQ.aAnswers;
		$L('1051 cp' + this, 'warn');
		$L('1052 aAns ' + aAns.length, 'warn');
		eQbody.innerHTML = oQ.qbody;
		$L('124 ' + oQ.qbody);

		for (i = 0; i < aAns.length; i += 1) {
			this.makeAnswerRow(aAns[i]);
		}

		/**
		 * If oQ contains result property this means we got the json for the
		 * question for reviewing the answer history in this case we don't need
		 * the 'submit answer' button at all
		 */
		if (!oQ.result) {
			eFrm.appendChild(eSubmit);
			oBtn = new $W.Button(eSubmit);
			oBtn.on("click", oTQ.processAnswer, oBtn);
			/**
			 * When clicking a button the form is also being submitted, so we
			 * must add preventDefault for the onSubmit for our form
			 */
			$E.addListener(eFrm, "submit", function(e) {
				$E.preventDefault(e);
			});
		} else {
			$L('1206 NOT adding submit button because this is a review mode', 'error');
		}

		/**
		 * If oQ contains nocite property this means that we must show this
		 * notice right away this is usually a notice saying that user has
		 * already answered this question
		 */
		if (oQ.notice && oQ.notice.bd) {
			$L('1049 this is ' + this);
			oTQ.showNotice(oQ.notice.bd, 'main', oQ.notice.hd);
		}

		return eDiv;
	},
	/**
	 * Make DOMNode 'tr' complete with answer letter, input element for answer
	 * choice, answer body and then append it to table 'qtable'
	 * 
	 * @param object
	 *            o object of one answer from aAnswers array in oQ
	 */
	makeAnswerRow : function(o) {
		$L('962 cp o: ' + $LANG.dump(o));
		var aTDs, eInput, eAnswerTr = eTr.cloneNode(true);

		aTDs = eAnswerTr.getElementsByTagName('td');
		aTDs[0].innerHTML = o.letter;

		eInput = this.makeAnswerInput(o);
		$L('150 eInput: ' + eInput);
		aTDs[1].appendChild(eInput);
		aTDs[2].innerHTML = o.body;

		eTable.appendChild(eAnswerTr);
	},
	/**
	 * Make form input element for one answer choice Input type is based on the
	 * question type Look in oQ.qtype for that (oQ is private var through
	 * closure)
	 * 
	 * @return object DOMNode of type 'input'
	 */
	makeAnswerInput : function(oAns) {
		var eInput, sInputType;
		$L('168 cp oAns[id]: ' + oAns.aid);
		switch (oQ.qtype) {
		case 'single':
			$L('170 single');
			sInputType = 'radio';
			break;

		case 'multi':
			$L('175 multi');
			sInputType = 'checkbox';
			break;
		}

		eInput = document.createElement('input');
		eInput.type = sInputType;
		eInput.name = 'ans[]';
		eInput.value = oAns.aid;

		/**
		 * In review mode, when the oQ is sent from server and includes the
		 * 'yours' object we must also select the answers from the 'yours'
		 * object
		 * 
		 */
		if (oQ.yours) {
			if (oQ.yours.inArray(oAns.aid)) {
				$L('1298 marking as answered ' + oAns.aid, 'warn');
				eInput.checked = true;
			}
			eInput.disabled = true;
		}
		return eInput;
	},

	toString : function() {
		return 'object qRenderer';
	}

	};

	return that;

};
oTQ.tweetResult = function() {
	/**
	 * oTQ.oResult has been set to what we got in ajax response
	 */
	var tid, token = oTQ.getToken(), ic = (oTQ.oResult.ic) ? oTQ.oResult.ic : 'U', vmode = (oTQ.oResult.yours) ? 'review' : 'answer';
	this.set('disabled', true);

	$D.addClass($('btntweetans-button'), 'button-loading');

	$L('1116 tweetResult qid: ' + oTQ.oResult.qid + ' isCorrect: ' + oTQ.oResult.ic + ' mode:  ' + vmode + ' this is ' + this, 'window'); // this
	// is // oTQ

	tid = oTQ.getMeta('session-tid');
	$L('1144 tid: ' + tid);

	$CONN.asyncRequest('POST', "/index.php", oTQ.oCallback, 'a=tweetresult&tid=' + tid + '&vmode=' + vmode + '&token=' + token + '&ic=' + ic + '&qid=' + oTQ.oResult.qid);

};
/**
 * Process the "Like" button push Will send out an Async post request and pass
 * question id (qid), twitter user id (tid), but this is only for validation and
 * we must compare it with session oViewer, token id
 */
oTQ.postLike = function() {
	/**
	 * oTQ.oResult has been set to what we got in ajax response
	 */
	$L('1224 postLike this is: ' + this); // Button btnlike
	var tid, token = oTQ.getToken(), ic = (oTQ.oResult.ic) ? oTQ.oResult.ic : 'U';
	// this.set('disabled', true);

	$D.addClass($('btnlike-button'), 'button-loading');
	oTQ.formElements.disable(this);

	$L('1116 tweetResult qid: ' + oTQ.oResult.qid + ' this is ' + this, 'window');

	tid = oTQ.getMeta('session-tid');
	$L('1144 tid: ' + tid);

	$CONN.asyncRequest('POST', "/index.php", oTQ.oCallback, 'a=like&tid=' + tid + '&token=' + token + '&qid=' + oTQ.oResult.qid);

};

oTQ.showNotice = function(message, parent, sHeader) {
	$L('1111 cp', 'error');
	var oPanel = new $W.Panel("panel2", {
	width : "420px",
	visible : false,
	draggable : true,
	context : [ parent, 'tl', 'tl', null, [ 20, 20 ] ],
	close : true
	});

	$L("1118 cp");
	if (sHeader) {
		oPanel.setHeader(sHeader);
	}
	$L("1122 cp");
	oPanel.setBody('<div class="notice">' + message + '</div>');
	$L("1124 cp");
	oPanel.render('content');
	$L("1126 cp");
	oPanel.show();
	$L("1128 cp");

}
/**
 * Modal is the object to show 'loading modal' when ajax call starts and to hide
 * it when it ends
 */
oTQ.modal = (function() {
	var oModal;

	return {
	show : function(sText) {
		$L('modal show');
		if (!oModal) {
			$L('1189 cp');
			oModal = new $W.Panel("mywait", {
			width : "240px",
			fixedcenter : true,
			close : false,
			draggable : false,
			zindex : 4,
			modal : true,
			visible : false
			});
			$L('1199 cp');

			oModal.setHeader('');
			oModal.setBody("<img src=\"/images/loading-bar.gif\"/>");
			oModal.render(document.body);
		}

		sText = (sText) ? sText : 'Loading, please wait...';
		oModal.setHeader(sText);
		oModal.show();
	},
	hide : function() {
		if (oModal) {
			oModal.hide();
		}
	}
	}
})();
oTQ.alerter = (function() {
	var oPanel;

	return {

	getInstance : function() {
		if (!oPanel) {
			oPanel = new $W.SimpleDialog("dlg1", {
			width : "400px",
			fixedcenter : true,
			modal : true,
			visible : false,
			close : true,
			constraintoviewport : true,
			buttons : [ {
			text : "close",
			handler : function() {
				this.hide();
			},
			isDefault : true
			} ],
			draggable : false,
			effect : [ {
			effect : $W.ContainerEffect.FADE,
			duration : 0.2
			} ]

			});

			oPanel.setHeader("Alert");
			oPanel.render(document.body);
		}

		return oPanel;
	},
	/**
	 * Useful if we need to call destructor
	 */
	destroy : function() {
		if (oPanel) {
			oPanel.destroy();
		}
	},
	/**
	 * If panel exists call the hide() method
	 */
	hide : function() {
		if (oPanel) {
			oPanel.hide();
		}
	},
	toString : function() {
		return 'object created with oTQ.showAlert()';
	}
	}

})();

oTQ.Twitter = {
/**
 * Popup window object
 */
popupWindow : null,
/**
 * Array of Async requests This is just a stack, there should only be one async
 * request and no more, so we add async request object to this stack, then open
 * success we clear it and before each new request we must check if another
 * request is still running
 */
aRequests : [],

/**
 * Interval object There should be only one of this if we already have an
 * interval then we should not start another login process OR clear previous
 * interval first
 */
oInterval : null,

/**
 * Start the oAuth login process by opening the popup window
 */
startDance : function() {
	$L('1084 starting oAuth dance this is: ' + this, 'window');
	var popupParams = 'location=0,status=0,width=800,height=450,alwaysRaised=yes,modal=yes', mydomain = window.location.hostname;

	// alert('1528 ' + mydomain);

	/**
	 * Prevent user from opening more than one Twitter oAuth popup windows. This
	 * is helpful when the already opened window has gone out of focus (turned
	 * into popunder) accedentally
	 * 
	 */
	if (this.popupWindow && !this.popupWindow.closed) {
		this.popupWindow.location.href = 'http://' + mydomain + '/index.php?a=oauth';
		this.popupWindow.focus();
		return;
	}

	this.popupWindow = window.open('http://' + mydomain + '/index.php?a=oauth', 'twitterWindow', popupParams);

	if (!this.popupWindow) {
		alert('Unable to open login window. Please make sure to disable popup blockers in your browser');
		return;
	}

	/**
	 * This is very important to cancel any already running intervaled jobs,
	 * otherwise the next one will override prev one but the job will still be
	 * running in the background, so it will never be cancelled, resulting in
	 * continuesly issuing asyncRequests to the server like crazy
	 * 
	 * This can happend when someone opens multiple browser windows by clickin
	 * on 'signin with twitter' several times
	 */
	if (oTQ.Twitter.oInterval) {
		alert('1109 something is still running');
		window.clearInterval(oTQ.Twitter.oInterval);
		oTQ.Twitter.oInterval = null;
	}

	this.oInterval = window.setInterval(this.checkLogin, 500);
	$L('1085 this.oInterval ' + this.oInterval, 'warn');
},

/**
 * This method is check via oInterval, every half a second to check if popup
 * window has been closed on not. If popup has been closed then we assume that
 * the first step in oAuth dance is done and can check with the server to see if
 * session now has user object
 */
checkLogin : function() {
	$L('11125 checking login', 'window');
	var transaction, cObj;

	if (!oTQ.Twitter.popupWindow || oTQ.Twitter.popupWindow.closed) {

		oTQ.Twitter.cancelIntervals();
		oTQ.Twitter.cancelAsyncCalls();

		var sToken = oTQ.getToken();
		$L('1150 cp sToken: ' + sToken);
		cObj = $CONN.asyncRequest("POST", "/index.php", oTQ.oCallback, "a=login&token=" + sToken);
		oTQ.Twitter.aRequests.push(cObj);
		$L('1153 ' + $CONN.isCallInProgress(cObj));
	}
},
/**
 * In case there are any jobs still running at intervals we must cancell the job
 * and null the interval
 * 
 * This will also be called from the processLogin() method as well as from the
 * checkLogin() when we detect that popup has been closed
 */
cancelIntervals : function() {

	$L('1150 cancellng pending intervals this: ' + this, 'window');
	if (oTQ.Twitter.oInterval) {
		$L(' 1131 killing interval');
		window.clearInterval(oTQ.Twitter.oInterval);
		oTQ.Twitter.oInterval = null;
	}
},
/**
 * If any other XHR transactions are still running we abort them before starting
 * this one This will also be called from the processLogin() method because its
 * very possible that when popup passes the data to opener and then closes, the
 * opener will also detect that popup has closed and will fire the async request
 * to check login
 */
cancelAsyncCalls : function() {

	$L('1147 cancelling all XHR calls this: ' + this, 'error');

	if (oTQ.Twitter.aRequests.length > 0) {
		for ( var i = 0; i < oTQ.Twitter.aRequests.length; i += 1) {
			transaction = oTQ.Twitter.aRequests[i];
			if ($CONN.isCallInProgress(transaction)) {
				$CONN.abort(transaction);
			}
		}
	}
},
toString : function() {
	return 'object oTQ.Twitter';
}
};

oTQ.formElements = (function() {
	/**
	 * Array to store all elements, objects that have to be disabled/enabled
	 */
	var aElements = [], aLoading = [];

	that = {
	/**
	 * This the state of this element to enabled if object is not passed then
	 * enable all previosly disable elements and remove them from aElements
	 * array
	 */
	enable : function(o) {
		var element;
		while (aElements.length > 0) {
			element = aElements.shift();
			if (element.set) {
				element.set('disabled', false);
			} else {
				element.disabled = false;
			}
		}

		while (aLoading.length > 0) {

			$D.removeClass((aLoading.shift()), 'button-loading');
		}
	},
	/**
	 * Disable element or object and add to aElements storage array
	 */
	disable : function(o) {
		$L('1522 disabling ' + o);
		if (o.set) {
			$L('1524 disabling ' + o);
			o.set('disabled', true);
		} else {
			o.disabled = true;
		}
		aElements.push(o);
	},
	/**
	 * Convenient way to add button-loading class to html element and store
	 * reference to that element in array to we can easily remove it later
	 */
	addLoaderClass : function(el) {
		$L('1284 adding loader class to ' + el);
		$D.addClass(el, 'button-loading');
		aLoading.push(el);
	}
	}

	return that;

})();

$E.onDOMReady(function() {

	/**
	 * Always init logger first
	 */
	if ($W.LogReader) {
		var myLogReader = new $W.LogReader();
	} else {

	}

	/**
	 * This must be in global js file so we will always have listener for the
	 * onClick inside the main div
	 */
	$E.addListener( [ 'main', 'welcome' ], "click", oTQ.handleClick, oTQ, true);

	window.alert = function(text) {
		var oAlert = oTQ.alerter.getInstance();
		oAlert.cfg.setProperty("text", text);
		oAlert.show();
	};

});

