/*
  votex.js - VoteX javascript snippet

  Version:      1.0.5
  Date:         13/04/2009
  Author(s):
        David Oliveira <david.oliveira -at- co -dot- sapo -dot- pt>
 */



// Object

VoteX = function(opts) { this.init(opts); }


// Object prototype

VoteX.prototype = {

	init: function(opts) {

		// Set some properties

		this.pollID		= null;
		this.poll		= null;
		this.key		= null;
		this.answer		= null;
		this.curAskBox		= null;
		this.curCBox		= null;
		this.msgElement		= null;
		this.errorEl		= null;
		this.commentsTarget	= null;
		this.commentsFrmURL	= "/services/votex/comments.html";
		this.voteBtnText	= "Votar";
		this.voteBtn		= null;
		this.target		= null;
		this.container		= null;
		this.voting		= false;
		this.voted		= false;

		// Copy some other

		var props = ['pollID','commentsFrmURL','voteBtnText','commentsFrmURL','voteBtnText','css'];
		for ( var p, x = 0 ; p = props[x] ; x++ )
			if ( opts[p] != null ) this[p] = opts[p];

		// Validate options

		if ( (this.target = document.getElementById(opts.target)) == null ) return false;
		if ( this.pollID == null || this.target == null ) return false;

		// Fetch some required elements

		if ( opts.commentsTarget ) this.commentsTarget = document.getElementById(opts.commentsTarget);


		// Show

		this.show();
		return true;

	},


	// Show poll

	show: function() {

		// Pre-create message element so we can show errors

		this.msgElement = this._util_newDomEl( "SPAN", { className: 'message' } );
		this.target.appendChild(this.msgElement);

		// Get and show poll

		var
			me = this,
			synd = new SAPO.Communication.Syndication(),
			itemsId = synd.push('/services/votex/?type=poll&id='+this.pollID, {
				objectName:	'objpoll',
				timeout:	10,

	                        onComplete:	function(data) { me._cb_voteShow(data) },
	                        onTimeout:	function() { me._cb_voteShow_error() }
			} );

		// Get it!

		synd.run(itemsId);

	},

	_cb_voteShow: function ( data ) {

		var
			me = this,
			poll = this.poll = data.poll,
			c, ul;

		// Got error ?

	        if ( data.error ) return this._cb_voteShow_error();


		// Set key

		this.key = data.key;

		// Create elements

		c = this.container = this._util_newDomEl ( "DIV", { className: 'pollCont' });
		c.style.visibility = 'hidden';
		c.appendChild(this._util_newDomEl("H3",{innerHTML: 'Vote e diga porqu&ecirc;'}));
		c.appendChild(this._util_newDomEl("H4",{innerHTML: poll.title}));
		c.appendChild(this._util_newDomEl("H5",{innerHTML: "Vote"}));

		ul = this._util_newDomEl("UL",{className: 'options'});
		for ( var x = 0 ; x < poll.answers.length ; x++ ) {
			var
				ans = poll.answers[x],
				li = this._util_newDomEl("LI",{id:"a_"+ans.id}),
				itemClick = function() { me._click_option(this); return true; };

			li.appendChild(this._util_newDomEl( "INPUT", { id: "o_"+ans.id, type: "radio", name: "votex_"+this.pollID, className: "option", onclick: itemClick } ));
			li.appendChild(this._util_newDomEl( "LABEL", { id: "l_"+ans.id, innerHTML: ans.answer, htmlFor: "o_"+ans.id, onclick: itemClick } ));
			ul.appendChild(li);
		}
		c.appendChild(ul);

		this.voteBtn = this._util_newDomEl( "INPUT", { type: 'button', className: "btnVotar", value: this.voteBtnText, onclick: function(){me.vote()} } );
		c.appendChild(this.voteBtn);

		// Message element

		this.msgElement = this._util_newDomEl( "SPAN", { className: 'message' } );
		c.appendChild(this.msgElement);

		// Apply

		this.target.innerHTML = "";
		this.target.appendChild(c);

		// Show results or show poll?

		if ( document.cookie.indexOf("votex_"+this.pollID+"=1") >= 0 ) {
			this.voted = true;
			this.showResults();
		}
		else
			c.style.visibility = 'visible';

		return true;

	},

	_cb_voteShow_error: function() {
		this.showError("Erro ao mostrar a vota&ccedil;&atilde;o. Por favor volte a tentar mais tarde.")
	},


	// Options

	_click_option: function(link) {

		var
			aid, aLI, askbox;

                // Check radio button (IE needs this)

                if ( this.answer ) {
                        var oLI = document.getElementById("o_"+this.answer);
                        oLI.checked = false;
                }
                link.checked = true;

		// Get answer ID

		if ( !link.id.match(/^[ol]_(\d+)$/) ) return false;
		this.answer = aid = RegExp.$1;

		// Get answer element

		if ( (aLI = document.getElementById("a_"+aid)) == null ) return false;

		// Show comments

		this.showComments();


		if ( !this.voted ) {

			// Add askbox (text box and title)

			if ( this.curAskBox ) { this._util_remDomEl(this.curAskBox); this.curAskBox = null; }
			this.curAskBox = askbox = this._util_newDomEl( "DIV", { className: 'askbox' } );

			if ( this.curCBox ) { this._util_remDomEl(this.curCBox); this.curCBox = null; }
			this.curCBox = this._util_newDomEl( "TEXTAREA", { id: "c_"+aid, className: "cbox" } );

			askbox.appendChild( this._util_newDomEl( "H5", { innerHTML: "Diga porqu&ecirc;" }) );
			askbox.appendChild(this.curCBox);

			aLI.appendChild(askbox);
			this.curCBox.focus();
		}

		return false;

	},


	// Show comments for current answer

	showComments: function() {

		var
			poll = this.poll, ct;

		if ( this.answer == null ) return false;

		// Show comments for this answer

		if ( (ct = this.commentsTarget) == null ) return false;

		// Find answer with this id

		var answer = null;
		for ( var x = 0 ; x < poll.answers.length ; x++ )
			if ( poll.answers[x].id == this.answer) answer = poll.answers[x];

		// Show comments

		if ( answer != null ) {
			ct.innerHTML = "";
			ct.appendChild(this._util_newDomEl( "H3", { innerHTML: "Pessoas que votaram" }) );
			ct.appendChild(this._util_newDomEl( "QUOTE", { innerHTML: answer.answer }) );
			ct.appendChild(this._util_newDomEl( "IFRAME", { id: 'if_comments_'+this.pollID, src: this.commentsFrmURL+'?id='+this.pollID+'&answer='+this.answer, frameBorder: '0' }) );
		}

		return true;

	},


	// Show results

	showResults: function() {

		var
			poll = this.poll,
			bar, perc;

		// Change target element class

		this.container.className = "pollCont results";

		// For each answer

		var aLI, ans = null;
		for ( var x = 0 ; x < poll.answers.length ; x++ ) {
			ans = poll.answers[x];
			perc = Math.round((ans.votes/poll.total)*100)+"%";

			// Get answer element

			if ( (aLI = document.getElementById("a_"+ans.id)) == null ) return false;

			// Add bar

			var bar = this._util_newDomEl( "SPAN", { className: "bar", innerHTML: perc } );
			bar.style.width = perc;
			aLI.appendChild(bar);

		}

		this.container.style.visibility = 'visible';

		return true;

	},


	// Vote

	vote: function() {

		var
			me = this,
			comment;

		if ( this.voted || this.voting ) return false;
		this.voting = true;

		// Avoid voting without answering ...

		if ( this.answer == null ) return false;

		// Change target element class

		this.container.className = "pollCont voting";

		// Get comment text

		comment = this.curCBox ? this.curCBox.value : "";

		// Remove current ask box and comment box

		if ( this.curAskBox ) { this._util_remDomEl(this.curAskBox); this.curAskBox = null; }
		if ( this.curCBox ) { this._util_remDomEl(this.curCBox); this.curCBox = null; }

		// Vote

		new Ajax.Request ( "/services/votex/?key="+this.key+"&op=vote&id="+this.pollID, {
			method: 'post',
			parameters: null,
			postBody: 'answer='+this.answer+"&comment="+escape(comment),
			encoding: 'UTF-8',
			onComplete: function (data) { me._cb_vote(data.responseJSON); }
		} );

	},

	_cb_vote: function(data) {

		if ( data == null ) return false;

		// Error voting ?

		if ( data.error )
			return this._cb_vote_error();
		else if ( data.poll && data.poll.error )
			this._cb_vote_error(data.poll.error);

		// No error ?

		if ( data.poll && !data.poll.error ) {

			// Show information message

			this.showInfo("O seu voto foi registado com sucesso. Obrigado.");

			// Show comments

			this.showComments();

		}

		// He just voted

		this.voted = true;

		// Set cookie

		document.cookie = "votex_"+this.pollID+"=1";

		// Show results

		this.showResults();

		this.voting = false;
		return true;

	},

	_cb_vote_error: function(error) {
		this.showError(error || "Erro ao processar o seu voto. Por favor volte a tentar mais tarde.");
	},


	// Show an information

	showInfo: function(msg) {
		this.msgElement.innerHTML = msg;
		this.msgElement.className = "message infomsg";
		this.container.className = "pollCont info";
	},


	// Show an error

	showError: function(msg) {
		this.msgElement.innerHTML = msg;
		this.msgElement.className = "message errormsg";
		this.container.className = "pollCont error";
	},

	// Util functions

	_util_newDomEl: function(tag,props) {
		var el = document.createElement(tag);
		this._util_cp(el,props);
		return el;
	},	
	_util_remDomEl: function(el) {
		if(el && el.parentNode) el.parentNode.removeChild(el);
	},
	_util_fe: function(o,fn){
		for(var p in o)fn(p);
	},
	_util_cp: function(o,pr) {
		if(!o)return;this._util_fe(pr,function(p){if(typeof(pr[p])=="object")this._util_cp(o[p],pr[p]);else try{o[p]=pr[p];}catch(e){}});
	}

};

