// seta variaveis global
var xIE     = (document.all) ? 1 : 0;
var sWidth  = parseInt(window.screen.width);
var sHeight = parseInt(window.screen.Height);

// (C) Andrea Giammarchi - JSL 1.8+ - 2007/11/03
(function(prototype){
	var	key, value, tmp;
	if(!Object.prototype.hasOwnProperty) Object.prototype.hasOwnProperty = function(key){
		var	result = false,
			value;
		key = String(key);
		if(/constructor|toString|valueOf/.test(key))
			result = Object.prototype[key] !== this[key];
		else{
			for(value in this){
				if(value === key){
					result = this === Object.prototype ? false : Object.prototype[key] !== this[key];
					break;
				}
			}
		};
		return	result;
	};
	for(key in prototype){
		if(prototype.hasOwnProperty(key)){
			switch(typeof prototype[key]){
				case	"function":
					if(!this[key])
						this[key] = prototype[key];
				break;
				case	"object":
					for(value in prototype[key]){
						if(prototype[key].hasOwnProperty(value)){
							if(!this[key].prototype[value] || (prototype[key][value].test && prototype[key][value].test()))
								this[key].prototype[value] = prototype[key][value].callback;
						}
					};
				break;
			}
		};
	};
	try{
		prototype = key = value = undefined;
	}
	catch(e){
		this.undefined = prototype = key = value = tmp;
	};
	/*@cc_on
	(function(callback){
		this.setTimeout = callback(this.setTimeout);
		this.setInterval = callback(this.setInterval);
	})(function(value){
		return	function(callback, i){
			var	tmp = Array.prototype.slice.call(arguments, 2);
			if(typeof callback != "function")
				callback = new Function(callback);
			return	value(function(){callback.apply(this, tmp);}, i);
		};
	});
	XMLHttpRequest = (function(XMLHttpRequest){
		function init(XMLHttpRequest){
			if(!XMLHttpRequest){
				var	tmp = ["MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
				while(!XMLHttpRequest && tmp.length){
					try{XMLHttpRequest = new ActiveXObject(tmp.shift())}
					catch(e){}
				};
			}
			else
				XMLHttpRequest = new XMLHttpRequest;
			return	XMLHttpRequest;
		};
		return	function(){
			var	Object = this;
			(this["class"] = init(XMLHttpRequest)).onreadystatechange = function(){
				var	XMLHttpRequest = Object["class"];
				if(Object["synchronized"]()){
					Object.responseText = XMLHttpRequest.responseText;
					Object.responseXML = XMLHttpRequest.responseXML;
					Object.status = XMLHttpRequest.status;
					Object.statusText = XMLHttpRequest.statusText;
				};
				if(Object.onreadystatechange)
					Object.onreadystatechange.call(Object.onreadystatechange);
			};
		};
	})(this.XMLHttpRequest);
	XMLHttpRequest.prototype = {
		abort:function(){
			this["class"].abort();
		},
		getAllResponseHeaders:function(){
			return	this["synchronized"]() ? this["class"].getAllResponseHeaders() : [];
		},
		getResponseHeader:function(key){
			return	this["synchronized"]() ? this["class"].getResponseHeader(key) : null;
		},
		open:function(){
			this["class"].open(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
		},
		send:function(value){
			this["class"].send(value || null);
		},
		setRequestHeader:function(key, value){
			return	this["class"].setRequestHeader(key, value);
		},
		"synchronized":function(){
			return	(this.readyState = this["class"].readyState) == 4;
		},
		readyState:0,
		status:0,
		responseText:"",
		statusText:"",
		responseXML:null
	};
	@*/
})({
	Array:{
		every:{callback:function(callback){
			for(var
				i = 0,
				result = true,
				scope = arguments[1] || null,
				value = this instanceof Array;
				i < this.length && result;
				i++
			){
				if(value ? this.hasOwnProperty(i) : this[i] !== undefined)
					result = callback.call(scope, this[i], i, this);
			};
			return	result;
		}},
		filter:{callback:function(callback){
			for(var
				i = 0,
				result = [],
				scope = arguments[1] || null,
				value = this instanceof Array;
				i < this.length;
				i++
			){
				if((value ? this.hasOwnProperty(i) : this[i] !== undefined) && callback.call(scope, this[i], i, this))
					result[result.length] = this[i];
			};
			return	result;
		}},
		forEach:{callback:function(callback){
			for(var
				i = 0,
				scope = arguments[1] || null,
				value = this instanceof Array;
				i < this.length;
				i++
			){
				if(value ? this.hasOwnProperty(i) : this[i] !== undefined)
					callback.call(scope, this[i], i, this);
			};
		}},
		indexOf:{callback:function(value, i){
			for(var
				j = this.length,
				i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0;
				i < j && this[i] !== value;
				i++
			);
			return	j <= i ? -1 : i;
		}},
		lastIndexOf:{callback:function(value, i){
			return	Array.prototype.slice.call(this).reverse().indexOf(value, i);
		}},
		map:{callback:function(callback){
			for(var
				i = 0,
				result = new Array(this.length),
				scope = arguments[1] || null,
				value = this instanceof Array;
				i < this.length;
				i++
			){
				if(value ? this.hasOwnProperty(i) : this[i] !== undefined)
					result[i] = callback.call(scope, this[i], i, this);
			};
			return	result;
		}},
		pop:{callback:function(callback){
			var	length = this.length,
				result;
			if(length)
				result = this[--length];
			this.length = length;
			return	result;
		}},
		push:{callback:function(){
			for(var
				i = 0;
				i < arguments.length;
				i++
			)
				this[this.length] = arguments[i];
			return	this.length;
		}},
		shift:{callback:function(){
			var	result = Array.prototype.reverse.call(this).pop();
			Array.prototype.reverse.call(this);
			return	result;
		}},
		some:{callback:function(callback){
			for(var
				i = 0,
				result = false,
				scope = arguments[1] || null,
				value = this instanceof Array;
				i < this.length && !result;
				i++
			){
				if(value ? this.hasOwnProperty(i) : this[i] !== undefined)
					result = callback.call(scope, this[i], i, this);
			};
			return	result;
		}},
		splice:{callback:function(){
			var	result = [],
				tmp = [],
				i = 0, j = this.length, k = 0, length = arguments.length;
			switch(length) {
				case	0:break;
				case	1:arguments[1] = !length++ || this.length - arguments[0];
				default:
					k = arguments[0] + arguments[1];
					for(; i < j; i++){
						if(i < arguments[0] || i >= k){
							if(i === k && length > 2){
								for(i = 2; i < length; i++)
									tmp[tmp.length] = arguments[i];
								i = k;
							};
							tmp[tmp.length] = this[i];
						}
						else
							result[result.length] = this[i];
					};
					for(i = 0, j = tmp.length; i < j; i++)
						this[i] = tmp[i];
					this.length = i;
					break;
			};
			return	result;
		}},
		unshift:{
		test:function(){
			var	Array = [4,5];
			return	!(Array.unshift(1,2,3) === 5 && Array.join("-") === "1-2-3-4-5");
		},
		callback:function(){
			var	length = arguments.length;
			Array.prototype.reverse.call(this);
			while(length--)
				this[this.length] = arguments[length];
			return	Array.prototype.reverse.call(this).length
		}}
	},
	Date:{
		getYear:{
		test:function(){
			return	String((new Date).getYear()).length === 4;
		},
		callback:function(){
			return	this.getFullYear() - 1900;
		}},
		setYear:{
		test:function(){
			return	String((new Date).getYear()).length === 4;
		},
		callback:function(setYear){
			return	this.setFullYear(setYear + 1900);
		}}
	},
	Function:{
		apply:{callback:function(scope, arguments){
			var	i = arguments ? arguments.length : 0,
				result = new Array(i),
				call;
			switch(typeof scope){
				case	"boolean":	scope = new Boolean(scope);break;
				case	"number":	scope = new Number(scope);break;
				case	"string":	scope = new String(scope);break;
				default:		scope = scope || (function(){return this})();break;
			};
			do call = "*" + Math.random();
			while(scope[call] !== undefined);
			while(i--)
				result[i] = "arguments[" + i + "]";
			scope[call] = this;
			result = eval("scope[call](" + result.join(",") + ")");
			try{delete scope[call]}
			catch(e){scope[call] = undefined};
			return	result;
		}},
		call:{callback:function(scope){
			for(var	i = 1, result = []; i < arguments.length; i++)
				result[result.length] = arguments[i];
			return	this.apply(scope, result);
		}}
	},
	Number:{
		toFixed:{callback:function(max){
			var	result = Math.pow(10, parseInt(max)),
				tmp = new Array(2);
			result = String(Math.round(this * result) / result);
			if(max > 0){
				tmp = result.split(".");
				tmp[1] = (tmp[1] || "") + new Array(++max - (tmp[1] ? tmp[1].length : 0)).join("0");
				result = tmp.join(".");
			};
			return	result;
		}}
	},
	String:{
		lastIndexOf:{callback:function(tmp, i){
			var	value = String(this),
				result = value.split("").reverse().join("").indexOf(String(tmp).split("").reverse().join(""), i || 0);
			return	result < 0 ? result : value.length - result;
		}},
		replace:{
		test:function(){
			return	"aa".replace(/a/g,function(a,b){return b + " "}) != "0 1 ";
		},
		callback:(function(replace){return function(key, callback){
			var	value = String(this),
				result = value;
			if(typeof callback != "function")
				result = replace.apply(value, arguments);
			else {
				var	k = !/\/.*g.*$/.test(key),
					i = 0,
					tmp = [];
				while(arguments = key.exec(result)){
					tmp[tmp.length] = result.substr(0, arguments.index);
					tmp[tmp.length] = callback.apply(null, arguments.concat([value.indexOf(arguments[0], i), value]));
					result = value.substring(i += (arguments.index + arguments[0].length));
					if(k)
						break;
				};
				result = tmp.join("") + result;
			};
			return	result
		}})(String.prototype.replace)
		}
	},
	decodeURIComponent:function(value){
		return	String(value).replace(
			/(%F[0-9A-F]%E[0-9A-F]%[A-B][0-9A-F]%[8-9A-B][0-9A-F])|(%E[0-9A-F]%[A-B][0-9A-F]%[8-9A-B][0-9A-F])|(%[C-D][0-9A-F]%[8-9A-B][0-9A-F])|(%[0-9A-F]{2})/g,
			function(value, key, k, j, i){return String.fromCharCode(
				i ? parseInt(i.substr(1, 2), 16) :
				j ? ((parseInt(j.substr(1, 2), 16) - 0xC0) << 6) + (parseInt(j.substr(4, 2), 16) - 0x80) :
				k ? ((parseInt(k.substr(1, 2), 16) - 0xE0) << 12) + ((parseInt(k.substr(4, 2), 16) - 0x80) << 6) + (parseInt(k.substr(7, 2), 16) - 0x80) :
				((parseInt(key.substr(1, 2), 16) - 0xF0) << 18) + ((parseInt(key.substr(4, 2), 16) - 0x80) << 12) + ((parseInt(key.substr(7, 2), 16) - 0x80) << 6) + (parseInt(key.substr(10, 2), 16) - 0x80)
			)}
		);
	},
	encodeURIComponent:function(value){
		function charCodeAt(i, length){
			var	result = i.toString(16).toUpperCase();
			length = (length || 2) - result.length;
			return	length == 0 ? result : new Array(++length).join("0").concat(result);
		};
		return	String(value)
			.replace(/[\x00-\x20]|[\x25|\x3C|\x3E|\x5B|\x5D|\x5E|\x60|\x7F]|[\x7B-\x7D]|[\x80-\uFFFF]/g, function(value){
				var	i = value.charCodeAt(0),
					tmp = [];
				if(i < 128)
					tmp[tmp.length] = charCodeAt(i);
				else if(i < 2048){
					tmp[tmp.length] = charCodeAt(0xC0 + (i >> 6));
					tmp[tmp.length] = charCodeAt(0x80 + (i & 0x3F));
				}
				else if(i < 65536){
					tmp[tmp.length] = charCodeAt(0xE0 + (i >> 12));
					tmp[tmp.length] = charCodeAt(0x80 + (i >> 6 & 0x3F));
					tmp[tmp.length] = charCodeAt(0x80 + (i & 0x3F));
				}
				else{
					tmp[tmp.length] = charCodeAt(0xF0 + (i >> 18));
					tmp[tmp.length] = charCodeAt(0x80 + (i >> 12 & 0x3F));
					tmp[tmp.length] = charCodeAt(0x80 + (i >> 6 & 0x3F));
					tmp[tmp.length] = charCodeAt(0x80 + (i & 0x3F));
				};
				return	"%" + tmp.join("%");
			})
			.replace(/[\x23|\x24|\x26|\x2B|\x2C|\x2F|\x3A|\x3B|\x3D|\x3F|\x40]/g, function(value){
				return	"%" + charCodeAt(value.charCodeAt(0));
			})
			.replace(/"/g, "%22")
			.replace(/\\/g, "%5C");
	},
	execScript:function(value){
		var	tmp = document.createElement("script");
		tmp.type = "text/javascript";
		tmp.appendChild(document.createTextNode(value));
		with(document.documentElement)
			removeChild(appendChild(tmp));
	}
});

document.importNode = function(node, allChildren) {
	/* find the node type to import */
	switch (node.nodeType) {
		case 1:
			/* create a new element */
			var newNode = document.createElement(node.nodeName);
			/* does the node have any attributes to add? */
			if (node.attributes && node.attributes.length > 0)
				/* add all of the attributes */
				for (var i = 0, il = node.attributes.length; i < il;)
					newNode.setAttribute(node.attributes[i].nodeName, node.getAttribute(node.attributes[i++].nodeName));
			/* are we going after children too, and does the node have any? */
			if (allChildren && node.childNodes && node.childNodes.length > 0)
				/* recursively get all of the child nodes */
				for (var i = 0, il = node.childNodes.length; i < il;)
					newNode.appendChild(document.importNode(node.childNodes[i++], allChildren));
		    if (node.getAttribute("class")) newNode.className = node.getAttribute("class");
			return newNode;
			break;
		case 3: case 4:	case 8:
			return document.createTextNode(node.nodeValue);
			break;
	}
};

function getElementsByClassName(className, tag, elm){
	var testClass = new RegExp("(^|\\s)" + className + "(\\s|$)");
	var tag = tag || "*";
	var elm = elm || document;
	var elements = (tag == "*" && elm.all)? elm.all : elm.getElementsByTagName(tag);
	var returnElements = [];
	var current;
	var length = elements.length;
	for(var i=0; i<length; i++){
		current = elements[i];
		if(testClass.test(current.className)){
			returnElements.push(current);
		}
	}
	return returnElements;
}

var EventCache = function(){
	var listEvents = [];
	
	return {
		listEvents : listEvents,
	
		add : function(node, sEventName, fHandler, bCapture){
			listEvents.push(arguments);
		},
	
		flush : function(){
			var i, item;
			for(i = listEvents.length - 1; i >= 0; i = i - 1){
				item = listEvents[i];
				
				if(item[0].removeEventListener){
					item[0].removeEventListener(item[1], item[2], item[3]);
				};
				
				/* From this point on we need the event names to be prefixed with 'on" */
				if(item[1].substring(0, 2) != "on"){
					item[1] = "on" + item[1];
				};
				
				if(item[0].detachEvent){
					item[0].detachEvent(item[1], item[2]);
				};
				
				item[0][item[1]] = null;
			};
		}
	};
}();

function addEvent(elm, evType, fn, useCapture){
var wrappedFn = fn;

    var scope = elm;
    var wrappedFn = function(event){
        var e = event || window.event;
        return fn.call(scope, e);
    };

    var result;
    if (elm.addEventListener){
        elm.addEventListener(evType, wrappedFn, useCapture);
        result = true;
    } else if (elm.attachEvent){
        var r = elm.attachEvent('on' + evType, wrappedFn);
        result = r;
    } else {
        elm['on' + evType] = wrappedFn;
        result = true;
    }

    EventCache.add(elm, evType, wrappedFn, useCapture);
    return result;
}

function hasClass(ele,cls) {
	return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
}

function addClass(ele,cls) {
	if (!this.hasClass(ele,cls)) ele.className += " "+cls;
}

function removeClass(ele,cls) {
	if (hasClass(ele,cls)) {
    	var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
		ele.className=ele.className.replace(reg,' ');
	}
}

function toggleClass(ele,cls) {
    if (hasClass(ele,cls)) {
        removeClass(ele,cls);
    } else {
        addClass(ele,cls);
    }
}

function getTextContent(node)
{
    return node.textContent ? node.textContent : node.innerText;
}

/*--------------------------------------------------------------*/
// HTML TABLE SORTER
// OBJECT ORIENTED JAVASCRIPT IMPLEMENTATION OF QUICKSORT
// @author	Terrill Dent 
// @source	http://www.terrill.ca
// @date	August 28th, 2006
/*--------------------------------------------------------------*/
function TSorter(){
	var table = Object;
	var trs = Array;
	var ths = Array;
	var curSortCol = 0;
	var sortType = Object;

	function get(){}

	function getCell(index){
		return trs[index].cells[curSortCol] 
	}

	this.init = function(tableName)
	{
		table = document.getElementById(tableName);
		ths = table.getElementsByTagName("th");
		for(var i = 0; i < ths.length ; i++)
		{
			addEvent(ths[i],"click",function()
			{
				sort(this,true);
			});
			ths[i].title = "Clique para Ordenar";
		}
		return true;
	};
	
	this.sortNow = function()
	{
	    sort(false,false);
	};
	
	function sort(oTH,reverse)
	{
	    oTH = oTH?oTH:ths[curSortCol];
		curSortCol = oTH.cellIndex;
		if (hasClass(oTH,"sortable-numeric")) {
    		sortType = "sortable-numeric";
		} else if (hasClass(oTH,"sortable-text")) {
    		sortType = "sortable-text";
		} else if (hasClass(oTH,"sortable-date")) {
    		sortType = "sortable-date";
		} else {
		    sortType = "";
		}
		trs = table.tBodies[0].getElementsByTagName("tr");

		setGet(sortType);
		
		Array.prototype.forEach.call(ths,function(el){
		    if (el == oTH) return;
            removeClass(el,"ascend");
            removeClass(el,"descend");
		});
		
		quicksort(0, trs.length);
	    if (reverse) {
	        if (hasClass(oTH,"ascend")) {
	            removeClass(oTH,"ascend");
	            addClass(oTH,"descend");
	            reverseTable();
	        } else {
	            removeClass(oTH,"descend");
	            addClass(oTH,"ascend");
	        }
        } else {
            if (hasClass(oTH,"descend")) {
	            reverseTable();
	        }
        }

	}
	
	function setGet(sortType)
	{
		switch(sortType)
		{   
		    case "sortable-date":
				get = function(index){ 
				    n = getTextContent(getCell(index)).replace(/(\D)+/g,'-').split('-');
				    return (n[2]*31556926)+parseInt(n[1]*2629743.83)+(n[0]*86400)+(n[3]*3600)+(n[4]*60)+n[5];
			    };
		        break;
		    case "sortable-text":
				get = function(index){ return getTextContent(getCell(index));};
		        break;
		    case "sortable-numeric":
				get = function(index){ 
				    n = getTextContent(getCell(index)).replace(/\D/g,'');
				    if (n == '') return 0;
				    else return parseInt(n);
			    };
		        break;
			default:
				get = function(index){ return getTextContent(getCell(index));};
				break;
		};	
	}

	function exchange(i, j)
	{
		if(i == j+1) {
			table.tBodies[0].insertBefore(trs[i], trs[j]);
		} else if(j == i+1) {
			table.tBodies[0].insertBefore(trs[j], trs[i]);
		} else {
			var tmpNode = table.tBodies[0].replaceChild(trs[i], trs[j]);
			if(typeof(trs[i]) == "undefined") {
				table.appendChild(tmpNode);
			} else {
				table.tBodies[0].insertBefore(tmpNode, trs[i]);
			}
		}
	}
	
	function reverseTable()
	{
		for(var i = 1; i<trs.length; i++)
		{
			table.tBodies[0].insertBefore(trs[i], trs[0]);
		}
	}

	/*----------------------QUICKSORT-------------------------------*/
	// This quicksort implementation is a modified version of this tutorial: 
	// http://www.the-art-of-web.com/javascript/quicksort/
	// @param: lo - the low index of the array to sort
	// @param: hi - the high index of the array to sort
	/*--------------------------------------------------------------*/
	function quicksort(lo, hi)
	{
		if(hi <= lo+1) return;
		 
		if((hi - lo) == 2) {
			if(get(hi-1) > get(lo)) exchange(hi-1, lo);
			return;
		}
		
		var i = lo + 1;
		var j = hi - 1;
		
		if(get(lo) > get(i)) exchange(i, lo);
		if(get(j) > get(lo)) exchange(lo, j);
		if(get(lo) > get(i)) exchange(i, lo);
		
		var pivot = get(lo);
		
		while(true) {
			j--;
			while(pivot > get(j)) j--;
			i++;
			while(get(i) > pivot) i++;
			if(j <= i) break;
			exchange(i, j);
		}
		exchange(lo, j);
		
		if((j-lo) < (hi-j)) {
			quicksort(lo, j);
			quicksort(j+1, hi);
		} else {
			quicksort(j+1, hi);
			quicksort(lo, j);
		}
	}
}

function sData(){var zeit=new Date();var ms=(zeit.getHours() * 24 * 60 * 1000) + (zeit.getMinutes() * 60 * 1000) + (zeit.getSeconds() * 1000) + zeit.getMilliseconds();return ms;}

/*
**    File: widgEdit.js
**    Created by: Cameron Adams (http://www.themaninblue.com/)
**    Created on: 2005-01-16
**    Last modified: 2005-03-09
**
**
**
**
**    License Information:
**    -------------------------------------------------------------------------
**    Copyright (C) 2005 Cameron Adams
**
**    This program 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.
**    
**    This program 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 this program; if not, write to the Free Software Foundation, Inc.,
**    59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
**    
**    
**    
**    
**    Purpose:
**    -------------------------------------------------------------------------
**
**    Replaces all textareas (class="widgEditor") in a HTML document with
**    enhanced editing windows to allow basic HTML formatting in a WYSIWYG
**    manner.
**
**
**
**
**    Function list:
**    -------------------------------------------------------------------------
**
**    run()
**
**    widgInit()
**
**    widgEditor(replacedTextareaID)
**    widtEditor.cleanPaste()
**    widgEditor.cleanSource()
**    widgEditor.convertSPANs(theSwitch)
**    widgEditor.detectPaste(e)
**    widgEditor.initEdit()
**    widgEditor.insertNewParagraph()
**    widgEditor.modifyFormSubmit()
**    widgEditor.paragraphise()
**    widgEditor.refreshDisplay()
**    widgEditor.switchMode()
**    widgEditor.updateWidgInput()
**    widgEditor.writeDocument()
**
**    widgToolbar()
**    widgToolbar.addButton(theID, theClass, theLabel, theAction)
**    widgToolbar.addSelect(theID, theClass, theContentArray, theAction)
**    widgToolbar.disable()
**    widgToolbar.enable()
**    widgToolbar.setState(theState, theStatus)
**
**    widgToolbarAction()
**
**    widgToolbarCheckState(theWidgEditor, resubmit)
**
**    widgToolbarMouseover()
**
**    acceptableChildren(theNode)
**
**    changeNodeType(theNode, nodeType)
**
**    replaceNodeWithChildren()
**
**    String.addClass(theClass)
**    String.classExists(theClass)
**    String.isAcceptedElementName()
**    String.isInlineName()
**    String.removeClass(theClass)
**    String.reverse()
**    String.validTags()
*/




/******************************************************************************
**    CONFIGURATION VARIABLES
******************************************************************************/

/* Location of stylesheet file for editor content */
var widgStylesheet = "style/widgeditor.css";

/* Items to appear in toolbar. */
var widgToolbarItems = new Array();

widgToolbarItems.push("bold");
widgToolbarItems.push("italic");
widgToolbarItems.push("hyperlink");
widgToolbarItems.push("unorderedlist");
widgToolbarItems.push("orderedlist");
widgToolbarItems.push("image");
widgToolbarItems.push("blockformat");

/* Options on block format select element. Consists of string pairs (option value, option label) */
var widgSelectBlockOptions = new Array();

widgSelectBlockOptions.push("", "Estilo");
widgSelectBlockOptions.push("<h4>", "Título Secundário");
widgSelectBlockOptions.push("<h5>", "Título Terciário");
widgSelectBlockOptions.push("<h6>", "Título Quartenário");
widgSelectBlockOptions.push("<p>", "Parágrafo");

/* If widgInsertParagraphs = true, when content is submitted paragraphs will be
** inserted around text without a parent element. Mozilla does not
** automatically do this, so if this is set to false you will end up with some
** plain text blocks. Uses a double <br /> as a pargraph marker.
*/

var widgInsertParagraphs = true;

/* If widgAutoClean = true, when content is pasted into the WYSIWYG view, it
** will automatically be cleaned. If widgAutoClean = false, the user will be
** prompted as to whether they wish to clean the content.
*/

var widgAutoClean = true;

/******************************************************************************
**    END CONFIGURATION
******************************************************************************/




run();




function run()
{
	var oldOnload = window.onload;

	if (typeof(window.onload) != "function")
	{
		window.onload = widgInit;
	}
	else
	{
		window.onload = function()
		{
			oldOnload();
			widgInit();
		}
	}
}




function widgInit()
{
	/* Detects if designMode is available, and also if browser is IE or Mozilla (excludes Safari) */
	if (typeof(document.designMode) == "string" && (document.all || document.designMode == "off"))
	{
		var theTextareas = document.getElementsByTagName("textarea");
		
		for (var i = 0; i < theTextareas.length; i++)
		{
			var theTextarea = theTextareas[i];
			
			if (theTextarea.className.classExists("widgEditor"))
			{
				if (theTextarea.id == "")
				{
					theTextarea.id = theTextarea.name;
				}
				
				
				setTimeout("new widgEditor('" + theTextarea.id + "')", 500 * (i));
			}
		}
	}
	else
	{
		return false;
	}
	
	return true;
}




function widgEditor(replacedTextareaID)
{
	var self = this;
	
	this.theTextarea = document.getElementById(replacedTextareaID);
	this.theContainer = document.createElement("div");
	this.theIframe = document.createElement("iframe");
	this.theInput = document.createElement("input");
	this.theExtraInput = document.createElement("input");
	this.IE = false;
	this.locked = true;
	this.pasteCache = "";
	this.wysiwyg = true;
	
	if (document.all)
	{
		this.IE = true;
	}
	
	if (this.theTextarea.id == null)
	{
		this.theTextarea.id = this.theTextarea.name;
	}
	
	this.theTextarea.style.visibility = "hidden";

	/* Modify DOM objects for editor */
	this.theContainer.id = this.theTextarea.id + "WidgContainer";
	this.theContainer.className = "widgContainer";
	
	this.theIframe.id = this.theTextarea.id + "WidgIframe";
	this.theIframe.className = "widgIframe";
	
	this.theInput.type = "hidden";
	this.theInput.id = this.theTextarea.id;
	this.theInput.name = this.theTextarea.name;
	this.theInput.value = this.theTextarea.value;

	
	/* An extra input to determine if the submitted data is from the normal textarea or from the widgEditor */
	this.theExtraInput.type = "hidden";	
	this.theExtraInput.id = this.theTextarea.id + "WidgEditor";
	this.theExtraInput.name = this.theTextarea.name + "WidgEditor";
	this.theExtraInput.value = "true";
	
	this.theTextarea.id += "WidgTextarea";
	this.theTextarea.name += "WidgTextarea";
	
//	this.theContainer.appendChild(this.theIframe);
	this.theContainer.innerHTML += "<iframe id=\""+this.theIframe.id + "\" allowtransparency=\"true\" class=\"widgIframe\" ></iframe>";
	this.theIframe = this.theContainer.getElementsByTagName("iframe")[0];

	this.theToolbar = new widgToolbar(this);
	this.theContainer.insertBefore(this.theToolbar.theList, this.theContainer.firstChild);
	this.theContainer.appendChild(this.theInput);
	this.theContainer.appendChild(this.theExtraInput);
	this.theContainer.style.visibility = "hidden";

	this.theInput.widgEditorObject = this;
	
	this.theTextarea.parentNode.replaceChild(this.theContainer, this.theTextarea);

	/* Fill editor with old textarea content */
	this.writeDocument(this.theInput.value);
	
	/* Make editor editable */
	this.initEdit();
	
	/* Attach onsubmit to parent form */
	this.modifyFormSubmit();

	
	return true;
}




/* Clean pasted content */
widgEditor.prototype.cleanPaste = function()
{
	if (widgAutoClean || confirm("Deseja limpar o conteúdo que acabou de colar?"))
	{
		var matchedHead = "";
		var matchedTail = "";
		var newContent = this.theIframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML;
		var newContentStart = 0;
		var newContentFinish = 0;
		var newSnippet = "";
		var tempNode = document.createElement("div");

		/* Find start of both strings that matches */
		for (newContentStart = 0; newContent.charAt(newContentStart) == this.pasteCache.charAt(newContentStart); newContentStart++)
		{
			matchedHead += this.pasteCache.charAt(newContentStart);
		}
		
		/* If newContentStart is inside a HTML tag, move to opening brace of tag */
		for (var i = newContentStart; i >= 0; i--)
		{
			if (this.pasteCache.charAt(i) == "<")
			{
				newContentStart = i;
				matchedHead = this.pasteCache.substring(0, newContentStart);
				
				break;
			}
			else if(this.pasteCache.charAt(i) == ">")
			{
				break;
			}
		}

		newContent = newContent.reverse();
		this.pasteCache = this.pasteCache.reverse();

		/* Find end of both strings that matches */
		for (newContentFinish = 0; newContent.charAt(newContentFinish) == this.pasteCache.charAt(newContentFinish); newContentFinish++)
		{
			matchedTail += this.pasteCache.charAt(newContentFinish);
		}

		/* If newContentFinish is inside a HTML tag, move to closing brace of tag */
		for (var i = newContentFinish; i >= 0; i--)
		{
			if (this.pasteCache.charAt(i) == ">")
			{
				newContentFinish = i;
				matchedTail = this.pasteCache.substring(0, newContentFinish);
				
				break;
			}
			else if(this.pasteCache.charAt(i) == "<")
			{
				break;
			}
		}

		matchedTail = matchedTail.reverse();

		/* If there's no difference in pasted content */
		if (newContentStart == newContent.length - newContentFinish)
		{
			return false;
		}

		newContent = newContent.reverse();
		newSnippet = newContent.substring(newContentStart, newContent.length - newContentFinish);
		newSnippet = newSnippet.validTags();

		/* Replace opening bold tags with strong */
		newSnippet = newSnippet.replace(/<b(\s+|>)/g, "<strong$1");
		/* Replace closing bold tags with closing strong */
		newSnippet = newSnippet.replace(/<\/b(\s+|>)/g, "</strong$1");

		/* Replace italic tags with em */
		newSnippet = newSnippet.replace(/<i(\s+|>)/g, "<em$1");
		/* Replace closing italic tags with closing em */
		newSnippet = newSnippet.replace(/<\/i(\s+|>)/g, "</em$1");

		/* Strip out unaccepted attributes */
		newSnippet = newSnippet.replace(/<[^>]*>/g, function(match)
			{
				match = match.replace(/ ([^=]+)="[^"]*"/g, function(match2, attributeName)
					{
						if (attributeName == "alt" || attributeName == "href" || attributeName == "src" || attributeName == "title")
						{
							return match2;
						}

						return "";
					});

				return match;
			}
			);

		tempNode.innerHTML = newSnippet;

		acceptableChildren(tempNode);
		
		this.theInput.value = matchedHead + tempNode.innerHTML + matchedTail;

		/* Final cleanout for MS Word cruft */
		this.theInput.value = this.theInput.value.replace(/<\?xml[^>]*>/g, "");
		this.theInput.value = this.theInput.value.replace(/<[^ >]+:[^>]*>/g, "");
		this.theInput.value = this.theInput.value.replace(/<\/[^ >]+:[^>]*>/g, "");

		this.refreshDisplay();
		
		/* Convert semantics to spans in Mozilla */
		if (!this.IE)
		{
			this.convertSPANs();
		}
	}
	
	return true;
}




/* Clean the HTML code of the content area */
widgEditor.prototype.cleanSource = function()
{
	var theHTML = "";
	
	if (this.wysiwyg)
	{
		theHTML = this.theIframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML;
	}
	else
	{
		theHTML = this.theTextarea.value;
	}

	theHTML = theHTML.validTags();
	
	/* Remove leading and trailing whitespace */
	theHTML = theHTML.replace(/^\s+/, "");
	theHTML = theHTML.replace(/\s+$/, "");
	
	/* Remove style attribute inside any tag */
	theHTML = theHTML.replace(/ style="[^"]*"/g, "");

	/* Replace improper BRs */
	theHTML = theHTML.replace(/<br>/g, "<br />");
	
	/* Remove BRs right before the end of blocks */
	theHTML = theHTML.replace(/<br \/>\s*<\/(h1|h2|h3|h4|h5|h6|li|p)/g, "</$1");
	
	/* Replace improper IMGs */
	theHTML = theHTML.replace(/(<img [^>]+[^\/])>/g, "$1 />");
	
	/* Remove empty tags */
	theHTML = theHTML.replace(/(<[^\/]>|<[^\/][^>]*[^\/]>)\s*<\/[^>]*>/g, "");
	
	if (this.wysiwyg)
	{
		this.theIframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML = theHTML;
	}
	else
	{
		this.theTextarea.value = theHTML;
	}
	
	this.theInput.value = theHTML;
	
	return true;
}




widgEditor.prototype.convertSPANs = function(theSwitch)
{
	if (theSwitch)
	{
		/* Replace styled spans with their semantic equivalent */
		var theSPANs = this.theIframe.contentWindow.document.getElementsByTagName("span");
	
		while(theSPANs.length > 0)
		{
			var theChildren = new Array();
			var theReplacementElement = null;
			var theParentElement = null;
			
			for (var j = 0; j < theSPANs[0].childNodes.length; j++)
			{
				theChildren.push(theSPANs[0].childNodes[j].cloneNode(true));
			}
			
			/* Detect type of span style */
			switch (theSPANs[0].getAttribute("style"))
			{
				case "font-weight: bold;":
					theReplacementElement = this.theIframe.contentWindow.document.createElement("strong");
					theParentElement = theReplacementElement;
					
					break;
				
				case "font-style: italic;":
					theReplacementElement = this.theIframe.contentWindow.document.createElement("em");
					theParentElement = theReplacementElement;
					
					break;
					
				case "font-weight: bold; font-style: italic;":
					theParentElement = this.theIframe.contentWindow.document.createElement("em");
					theReplacementElement = this.theIframe.contentWindow.document.createElement("strong");
					theReplacementElement.appendChild(theParentElement);
					
					break;
					
				case "font-style: italic; font-weight: bold;":
					theParentElement = this.theIframe.contentWindow.document.createElement("strong");
					theReplacementElement = this.theIframe.contentWindow.document.createElement("em");
					theReplacementElement.appendChild(theParentElement);
					
					break;
					
				default:
					replaceNodeWithChildren(theSPANs[0]);
				
					break;
			}
			
			if (theReplacementElement != null)
			{
				for (var j = 0; j < theChildren.length; j++)
				{
					theParentElement.appendChild(theChildren[j]);
				}

				theSPANs[0].parentNode.replaceChild(theReplacementElement, theSPANs[0]);
			}
			
			theSPANs = this.theIframe.contentWindow.document.getElementsByTagName("span");
		}
	}
	else
	{
		/* Replace em and strong tags with styled spans */
		var theEMs = this.theIframe.contentWindow.document.getElementsByTagName("em");
		
		while(theEMs.length > 0)
		{
			var theChildren = new Array();
			var theSpan = this.theIframe.contentWindow.document.createElement("span");
			
			theSpan.setAttribute("style", "font-style: italic;");
			
			for (var j = 0; j < theEMs[0].childNodes.length; j++)
			{
				theChildren.push(theEMs[0].childNodes[j].cloneNode(true));
			}
			
			for (var j = 0; j < theChildren.length; j++)
			{
				theSpan.appendChild(theChildren[j]);
			}

			theEMs[0].parentNode.replaceChild(theSpan, theEMs[0]);
			theEMs = this.theIframe.contentWindow.document.getElementsByTagName("em");
		}
		
		var theSTRONGs = this.theIframe.contentWindow.document.getElementsByTagName("strong");
		
		while(theSTRONGs.length > 0)
		{
			var theChildren = new Array();
			var theSpan = this.theIframe.contentWindow.document.createElement("span");
			
			theSpan.setAttribute("style", "font-weight: bold;");
			
			for (var j = 0; j < theSTRONGs[0].childNodes.length; j++)
			{
				theChildren.push(theSTRONGs[0].childNodes[j].cloneNode(true));
			}
			
			for (var j = 0; j < theChildren.length; j++)
			{
				theSpan.appendChild(theChildren[j]);
			}

			theSTRONGs[0].parentNode.replaceChild(theSpan, theSTRONGs[0]);
			theSTRONGs = this.theIframe.contentWindow.document.getElementsByTagName("strong");
		}
	}
	
	return true;
}




/* Check for pasted content */
widgEditor.prototype.detectPaste = function(e)
{
	var keyPressed = null;
	var theEvent = null;
	
	if (e)
	{
		theEvent = e;
	}
	else
	{
		theEvent = event;
	}
	
	if (theEvent.ctrlKey && theEvent.keyCode == 86 && this.wysiwyg)
	{
		var self = this;
		
		this.pasteCache = this.theIframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML;

		/* Because Mozilla can't access the clipboard directly, must rely on timeout to check pasted differences in main content */
		setTimeout(function(){self.cleanPaste(); return true;}, 100);
	}

	return true;
}




/* Turn on document editing */
widgEditor.prototype.initEdit = function()
{
	var self = this;
	
	try
	{
		this.theIframe.contentWindow.document.designMode = "on";
	}
	catch (e)
	{
		/* setTimeout needed to counteract Mozilla bug whereby you can't immediately change designMode on newly created iframes */
		setTimeout(function(){self.initEdit()}, 250);
			
		return false;
	}
	
	if (!this.IE)
	{
		this.convertSPANs(false);
	}
	
	this.theContainer.style.visibility = "visible";
	this.theTextarea.style.visibility = "visible";
	
	/* Mozilla event capturing */
	if (typeof document.addEventListener == "function")
	{
		this.theIframe.contentWindow.document.addEventListener("mouseup", function(){widgToolbarCheckState(self); return true;}, false);
		this.theIframe.contentWindow.document.addEventListener("keyup", function(){widgToolbarCheckState(self); return true;}, false);
		this.theIframe.contentWindow.document.addEventListener("keydown", function(e){self.detectPaste(e); return true;}, false);
	}
	/* IE event capturing */
	else
	{
		this.theIframe.contentWindow.document.attachEvent("onmouseup", function(){widgToolbarCheckState(self); return true;});
		this.theIframe.contentWindow.document.attachEvent("onkeyup", function(){widgToolbarCheckState(self); return true;});
		this.theIframe.contentWindow.document.attachEvent("onkeydown", function(e){self.detectPaste(e); return true;}, false);
	}
	
	this.locked = false;

	return true;	
}




/* Add elements to a paragraph and inserts the paragraph before a given element in the body */
widgEditor.prototype.insertNewParagraph = function(elementArray, succeedingElement)
{
	var theBody = this.theIframe.contentWindow.document.getElementsByTagName("body")[0];
	var theParagraph = this.theIframe.contentWindow.document.createElement("p");
	
	for (var i = 0; i < elementArray.length; i++)
	{
		theParagraph.appendChild(elementArray[i]);
	}
	
	if (typeof(succeedingElement) != "undefined")
	{
		theBody.insertBefore(theParagraph, succeedingElement);
	}
	else
	{
		theBody.appendChild(theParagraph);
	}
	
	return true;
}




/* Add submit listener to parent form */
widgEditor.prototype.modifyFormSubmit = function()
{
	var self = this;
	var theForm = this.theContainer.parentNode;
	var oldOnsubmit = null;
	
	/* Find the parent form element */
	while (theForm.nodeName.toLowerCase() != "form")
	{
		theForm = theForm.parentNode;
	}

	/* Add onsubmit without overwriting existing function calls */
	oldOnsubmit = theForm.onsubmit;

	if (typeof theForm.onsubmit != "function")
	{
		theForm.onsubmit = function()
		{
			return self.updateWidgInput();
		}
	}
	else
	{
		theForm.onsubmit = function()
		{
			self.updateWidgInput();

			return oldOnsubmit();			
		}
	}

	return true;
}




/* Format the HTML with paragraphs. Any parentless text is enclosed in a paragraph, double breaks are paragraph markers */
widgEditor.prototype.paragraphise = function()
{
	if (widgInsertParagraphs && this.wysiwyg)
	{
		var theBody = this.theIframe.contentWindow.document.getElementsByTagName("body")[0];

		/* Remove all text nodes containing just whitespace */
		for (var i = 0; i < theBody.childNodes.length; i++)
		{
			if (theBody.childNodes[i].nodeName.toLowerCase() == "#text" &&
				theBody.childNodes[i].data.search(/^\s*$/) != -1)
			{
				theBody.removeChild(theBody.childNodes[i]);

				i--;
			}
		}

		var removedElements = new Array();

		for (var i = 0; i < theBody.childNodes.length; i++)
		{
			if (theBody.childNodes[i].nodeName.isInlineName())
			{
				removedElements.push(theBody.childNodes[i].cloneNode(true));

				theBody.removeChild(theBody.childNodes[i]);

				i--;
			}
			else if (theBody.childNodes[i].nodeName.toLowerCase() == "br")
			{
				if (i + 1 < theBody.childNodes.length)
				{
					/* If the current break tag is followed by another break tag */
					if (theBody.childNodes[i + 1].nodeName.toLowerCase() == "br")
					{
						/* Remove consecutive break tags */
						while (i < theBody.childNodes.length && theBody.childNodes[i].nodeName.toLowerCase() == "br")
						{
							theBody.removeChild(theBody.childNodes[i]);
						}

						if (removedElements.length > 0)
						{
							this.insertNewParagraph(removedElements, theBody.childNodes[i]);

							removedElements = new Array();
						}
					}
					/* If the break tag appears before a block element */
					else if (!theBody.childNodes[i + 1].nodeName.isInlineName())
					{
						theBody.removeChild(theBody.childNodes[i]);
					}
					else if (removedElements.length > 0)
					{
						removedElements.push(theBody.childNodes[i].cloneNode(true));

						theBody.removeChild(theBody.childNodes[i]);
					}
					else
					{
						theBody.removeChild(theBody.childNodes[i]);
					}

					i--;
				}
				else
				{
					theBody.removeChild(theBody.childNodes[i]);
				}
			}
			else if (removedElements.length > 0)
			{
				this.insertNewParagraph(removedElements, theBody.childNodes[i]);

				removedElements = new Array();
			}
		}

		if (removedElements.length > 0)
		{
			this.insertNewParagraph(removedElements);
		}
	}
	
	return true;
}




/* Update hidden input to reflect editor contents, for submission */
widgEditor.prototype.refreshDisplay = function()
{
	if (this.wysiwyg)
	{
		this.theIframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML	= this.theInput.value;
	}
	else
	{
		this.theTextarea.value = this.theInput.value;
	}

	return true;
}




/* Switch between WYSIWYG and HTML source */
widgEditor.prototype.switchMode = function()
{
	if (!this.locked)
	{
		this.locked = true;
		
		/* Switch to HTML source */
		if (this.wysiwyg)
		{
			this.updateWidgInput();
			this.theTextarea.value = this.theInput.value;	
			this.theContainer.replaceChild(this.theTextarea, this.theIframe);
			this.theToolbar.disable();
			this.wysiwyg = false;
			this.locked = false;
		}
		/* Switch to WYSIWYG */
		else
		{
			this.updateWidgInput();
			this.theContainer.replaceChild(this.theIframe, this.theTextarea);
			this.writeDocument(this.theInput.value);
			this.theToolbar.enable();
			this.initEdit();
			this.wysiwyg = true;
		}
	}
			
	return true;
}




/* Update hidden input to reflect editor contents, for submission */
widgEditor.prototype.updateWidgInput = function()
{
	if (this.wysiwyg)
	{
		/* Convert spans to semantics in Mozilla */
		if (!this.IE)
		{
			this.convertSPANs(true);
		}
		
		this.paragraphise();		
		this.cleanSource();
	}
	else
	{
		this.theInput.value = this.theTextarea.value;
	}

	return true;
}




/* Write initial content to editor */
widgEditor.prototype.writeDocument = function(documentContent)
{
	/* HTML template into which the HTML Editor content is inserted */
	var documentTemplate = "\
		<html>\
			<head>\
				<style type=\"text/css\">@import url(\"INSERT:STYLESHEET:END\");</style>\
				<!--[if lt IE 7]><style type=\"text/css\">body{behavior:url(behavior/csshover.htc)}</style><link rel=\"stylesheet\" type=\"text/css\" href=\"style/ie6.css\"><![endif]-->\
				<!--[if lt IE 6]><link rel=\"stylesheet\" type=\"text/css\" href=\"style/ie5.css\"><![endif]-->\
			</head>\
			<body id=\"iframeBody\">\
				INSERT:CONTENT:END\
			</body>\
		</html>\
	";
	
	/* Insert dynamic variables/content into document */
	documentTemplate = documentTemplate.replace(/INSERT:STYLESHEET:END/, widgStylesheet);
	documentTemplate = documentTemplate.replace(/INSERT:CONTENT:END/, documentContent);
	
	this.theIframe.contentWindow.document.open();
	this.theIframe.contentWindow.document.write(documentTemplate);
	this.theIframe.contentWindow.document.close();
	
	return true;
}




/* Toolbar items */
function widgToolbar(theEditor)
{
	var self = this;
	
	this.widgEditorObject = theEditor;
	
	/* Create toolbar ul element */
	this.theList = document.createElement("ul");
	this.theList.id = this.widgEditorObject.theInput.id + "WidgToolbar";
	this.theList.className = "widgToolbar";
	this.theList.widgToolbarObject = this;

	/* Create toolbar items */
	for (var i = 0; i < widgToolbarItems.length; i++)
	{
		switch (widgToolbarItems[i])
		{
			case "bold":
				this.addButton(this.theList.id + "ButtonBold", "widgButtonBold", "Negrito", "bold");
				
				break;
				
			case "italic":
				this.addButton(this.theList.id + "ButtonItalic", "widgButtonItalic", "Itálico", "italic");
				
				break;
				
			case "hyperlink":
				this.addButton(this.theList.id + "ButtonLink", "widgButtonLink", "Link", "link");
				
				break;
				
			case "unorderedlist":
				this.addButton(this.theList.id + "ButtonUnordered", "widgButtonUnordered", "Lista", "insertunorderedlist");
				
				break;
				
			case "orderedlist":
				this.addButton(this.theList.id + "ButtonOrdered", "widgButtonOrdered", "Lista Ordenada", "insertorderedlist");
				
				break;
				
			case "image":
				this.addButton(this.theList.id + "ButtonImage", "widgButtonImage", "Imagem", "image");
				
				break;
				
			case "htmlsource":
				this.addButton(this.theList.id + "ButtonHTML", "widgButtonHTML", "Código", "html");
				
				break;
				
			case "blockformat":
				this.addSelect(this.theList.id + "SelectBlock", "widgSelectBlock", widgSelectBlockOptions, "formatblock");
				
				break;
		}
	}

	return true;
}





/* Add button to toolbar */
widgToolbar.prototype.addButton = function(theID, theClass, theLabel, theAction)
{
	var menuItem = document.createElement("li");
	var theLink = document.createElement("a");
	var theText = document.createTextNode(theLabel);
	
	menuItem.id = theID;
	menuItem.className = "widgEditButton";

	theLink.href = "#";
	theLink.title = theLabel;
	theLink.className = theClass;
	theLink.action = theAction;
	theLink.onclick = widgToolbarAction;
	theLink.onmouseover = widgToolbarMouseover;

	theLink.appendChild(theText);
	menuItem.appendChild(theLink);
	this.theList.appendChild(menuItem);

	return true;
}




/* Add select box to toolbar. theContentArray is an array of string pairs (option value, option label) */
widgToolbar.prototype.addSelect = function(theID, theClass, theContentArray, theAction)
{
	var menuItem = document.createElement("li");
	var theSelect = document.createElement("select");
	
	menuItem.className = "widgEditSelect";
	
	theSelect.id = theID;
	theSelect.name = theID;
	theSelect.className = theClass;
	theSelect.action = theAction;
	theSelect.onchange = widgToolbarAction;

	for (var i = 0; i < theContentArray.length; i += 2)
	{
		var theOption = document.createElement("option");
		var theText = document.createTextNode(theContentArray[i + 1]);
		
		theOption.value = theContentArray[i];

		theOption.appendChild(theText);
		theSelect.appendChild(theOption);
	}
	
	menuItem.appendChild(theSelect);
	this.theList.appendChild(menuItem);

	return true;
}




/* Turn off toolbar items */
widgToolbar.prototype.disable = function()
{
	/* Change class to disable buttons using CSS */
	this.theList.className += " widgSource";

	/* Loop through lis */
	for (var i = 0; i < this.theList.childNodes.length; i++)
	{
		var theChild = this.theList.childNodes[i];
		
		if (theChild.nodeName.toLowerCase() == "li" && theChild.className == "widgEditSelect")
		{
			/* Loop through li children to find select */
			for (j = 0; j < theChild.childNodes.length; j++)
			{
				if (theChild.childNodes[j].nodeName.toLowerCase() == "select")
				{
					theChild.childNodes[j].disabled = "disabled";
					
					break;
				}
			}
		}
	}
	
	return true;
}




/* Turn on toolbar items */
widgToolbar.prototype.enable = function()
{
	/* Change class to enable buttons using CSS */
	this.theList.className = this.theList.className.replace(/ widgSource/, "");
	
	/* Loop through lis */
	for (var i = 0; i < this.theList.childNodes.length; i++)
	{
		var theChild = this.theList.childNodes[i];
		
		if (theChild.nodeName.toLowerCase() == "li" && theChild.className == "widgEditSelect")
		{
			/* Loop through li children to find select */
			for (j = 0; j < theChild.childNodes.length; j++)
			{
				if (theChild.childNodes[j].nodeName.toLowerCase() == "select")
				{
					theChild.childNodes[j].disabled = "";
					
					break;
				}
			}
		}
	}
	
	return true;
}




/* Change the status of the selected toolbar item */
widgToolbar.prototype.setState = function(theState, theStatus)
{
	if (theState != "SelectBlock")
	{
		var theButton = document.getElementById(this.theList.id + "Button" + theState);
	
		if (theButton != null)
		{
			if (theStatus == "on")
			{
				theButton.className = theButton.className.addClass("on");
			}
			else
			{
				theButton.className = theButton.className.removeClass("on");
			}
		}
	}
	else
	{
		var theSelect = document.getElementById(this.theList.id + "SelectBlock");
		
		if (theSelect != null)
		{
			theSelect.value = "";
			theSelect.value = theStatus;
		}
	}
			
	return true;	
}





/* Action taken when toolbar item activated */
function widgToolbarAction()
{
	var theToolbar = this.parentNode.parentNode.widgToolbarObject;
	var theWidgEditor = theToolbar.widgEditorObject;
	var theIframe = theWidgEditor.theIframe;
	var theSelection = "";

	/* If somehow a button other than "HTML source" is clicked while viewing HTML source, ignore click */	
	if (!theWidgEditor.wysiwyg && this.action != "html")
	{
		return false;
	}
	
	switch (this.action)
	{
		case "formatblock":
			theIframe.contentWindow.document.execCommand(this.action, false, this.value);

			theWidgEditor.theToolbar.setState("SelectBlock", this.value);
			
			break;
			
		case "html":
			theWidgEditor.switchMode();
			
			break;
			
		case "link":
			if (this.parentNode.className.classExists("on"))
			{
				theIframe.contentWindow.document.execCommand("Unlink", false, null);
				theWidgEditor.theToolbar.setState("Link", "off");
			}
			else
			{
				if (theIframe.contentWindow.document.selection)
				{
					theSelection = theIframe.contentWindow.document.selection.createRange().text;

					if (theSelection == "")
					{
						alert("Selecione o texto que deseja tornar um link.");

						break;
					}
				}
				else
				{
					theSelection = theIframe.contentWindow.getSelection();

					if (theSelection == "")
					{
						alert("Selecione o texto que deseja tornar um link.");

						break;
					}
				}

				var theURL = prompt("Digite o Endereço do Link desejado:", "http://");

				if (theURL != null)
				{			
					theIframe.contentWindow.document.execCommand("CreateLink", false, theURL);
					theWidgEditor.theToolbar.setState("Link", "on");
				}
			}
			
			break;
			
		case "image":
			var theImage = prompt("Digite o local da imagem que deseja exibir:", "");
			
			if (theImage != null && theImage != "")
			{
				var theAlt = prompt("Digite o texto alternativo para essa imagem:", "");
				var theSelection = null;
				var theRange = null;
				
				/* IE selections */
				if (theIframe.contentWindow.document.selection)
				{
					/* Escape quotes in alt text */
					theAlt = theAlt.replace(/"/g, "'");
			
					theSelection = theIframe.contentWindow.document.selection;
					theRange = theSelection.createRange();
					theRange.collapse(false);
					theRange.pasteHTML("<img alt=\"" + theAlt + "\" src=\"" + theImage + "\" />");
					
					break;
				}
				/* Mozilla selections */
				else
				{
					try
					{
						theSelection = theIframe.contentWindow.getSelection();
					}
					catch (e)
					{
						return false;
					}

					theRange = theSelection.getRangeAt(0);
					theRange.collapse(false);
					
					var theImageNode = theIframe.contentWindow.document.createElement("img");
					
					theImageNode.src = theImage;
					theImageNode.alt = theAlt;
					
					theRange.insertNode(theImageNode);
					
					break;
				}
			}
			else
			{
				return false;
			}
		
		default:
			theIframe.contentWindow.document.execCommand(this.action, false, null);
			
			var theAction = this.action.replace(/^./, function(match){return match.toUpperCase();});

			/* Turn off unordered toolbar item if ordered toolbar item was activated */	
			if (this.action == "insertorderedlist")
			{
				theAction = "Ordered";
				theWidgEditor.theToolbar.setState("Unordered", "off");
			}
			
			/* Turn off ordered toolbar item if unordered toolbar item was activated */	
			if (this.action == "insertunorderedlist")
			{
				theAction = "Unordered";
				theWidgEditor.theToolbar.setState("Ordered", "off");
			}
			
			/* If toolbar item was turned on */
			if (theIframe.contentWindow.document.queryCommandState(this.action, false, null))
			{
				theWidgEditor.theToolbar.setState(theAction, "on");
			}
			else
			{
				theWidgEditor.theToolbar.setState(theAction, "off");
			}
	}
	
	if (theWidgEditor.wysiwyg == true)
	{
		theIframe.contentWindow.focus();
	}
	else
	{
		theWidgEditor.theTextarea.focus();
	}
	
	return false;	
}




/* Check the nesting of the current cursor position/selection */
function widgToolbarCheckState(theWidgEditor, resubmit)
{
	if (!resubmit)
	{
		/* Allow browser to update selection before using the selection */
		setTimeout(function(){widgToolbarCheckState(theWidgEditor, true); return true;}, 500);
	}
	
	var theSelection = null;
	var theRange = null;
	var theParentNode = null;
	var theLevel = 0;
	
	/* Turn off all the buttons */
	var menuListItems = theWidgEditor.theToolbar.theList.childNodes;
	for (var i = 0; i < menuListItems.length; i++)
	{
		menuListItems[i].className = menuListItems[i].className.removeClass("on");
	}
	
	/* IE selections */
	if (theWidgEditor.theIframe.contentWindow.document.selection)
	{
		theSelection = theWidgEditor.theIframe.contentWindow.document.selection;
		theRange = theSelection.createRange();
		try
		{
			theParentNode = theRange.parentElement();
		}
		catch (e)
		{
			return false;
		}
	}
	/* Mozilla selections */
	else
	{
		try
		{
			theSelection = theWidgEditor.theIframe.contentWindow.getSelection();
		}
		catch (e)
		{
			return false;
		}
		
		theRange = theSelection.getRangeAt(0);
		theParentNode = theRange.commonAncestorContainer;
	}
	
	while (theParentNode.nodeType == 3)
	{
		theParentNode = theParentNode.parentNode;
	}
	
	while (theParentNode.nodeName.toLowerCase() != "body")
	{
		switch (theParentNode.nodeName.toLowerCase())
		{
			case "a":
				theWidgEditor.theToolbar.setState("Link", "on");
				
				break;
				
			case "em":
				theWidgEditor.theToolbar.setState("Italic", "on");
				
				break;
				
			case "li":
			
				break;
				
			case "ol":
				theWidgEditor.theToolbar.setState("Ordered", "on");
				theWidgEditor.theToolbar.setState("Unordered", "off");
				
				break;
				
			case "span":
				if (theParentNode.getAttribute("style") == "font-weight: bold;")
				{
					theWidgEditor.theToolbar.setState("Bold", "on");
				}
				else if (theParentNode.getAttribute("style") == "font-style: italic;")
				{
					theWidgEditor.theToolbar.setState("Italic", "on");
				}
				else if (theParentNode.getAttribute("style") == "font-weight: bold; font-style: italic;")
				{
					theWidgEditor.theToolbar.setState("Bold", "on");
					theWidgEditor.theToolbar.setState("Italic", "on");
				}
				else if (theParentNode.getAttribute("style") == "font-style: italic; font-weight: bold;")
				{
					theWidgEditor.theToolbar.setState("Bold", "on");
					theWidgEditor.theToolbar.setState("Italic", "on");
				}
				
				break;
			
			case "strong":
				theWidgEditor.theToolbar.setState("Bold", "on");
				
				break;
			
			case "ul":
				theWidgEditor.theToolbar.setState("Unordered", "on");
				theWidgEditor.theToolbar.setState("Ordered", "off");
				
				break;
			
			default:
				theWidgEditor.theToolbar.setState("SelectBlock", "<" + theParentNode.nodeName.toLowerCase() + ">");
			
				break;
		}
		
		theParentNode = theParentNode.parentNode;
		theLevel++;
	}
	
	return true;			
}




/* Turn off browser status display for toolbar items */
function widgToolbarMouseover()
{
	window.status = "";
	
	return true;
}




function acceptableChildren(theNode)
{
	var theChildren = theNode.childNodes;
	
	for (var i = 0; i < theChildren.length; i++)
	{
		if (!theChildren[i].nodeName.isAcceptedElementName())
		{
			if (!theChildren[i].nodeName.isInlineName())
			{
				if (theNode.nodeName.toLowerCase() == "p")
				{
					acceptableChildren(replaceNodeWithChildren(theNode));
					
					return true;
				}
				
				changeNodeType(theChildren[i], "p");
			}
			else
			{
				replaceNodeWithChildren(theChildren[i]);
			}
				
			i = -1;
		}
	}
	
	for (var i = 0; i < theChildren.length; i++)
	{
		acceptableChildren(theChildren[i]);
	}
	
	return true;
}




/* Change the type of a node, e.g. h3 to p */
function changeNodeType(theNode, nodeType)
{
	var theChildren = new Array();
	var theNewNode = document.createElement(nodeType);
	var theParent = theNode.parentNode;
	
	if (theParent != null)
	{
		for (var i = 0; i < theNode.childNodes.length; i++)
		{
			theChildren.push(theNode.childNodes[i].cloneNode(true));
		}
		
		for (var i = 0; i < theChildren.length; i++)
		{
			theNewNode.appendChild(theChildren[i]);
		}
		
		theParent.replaceChild(theNewNode, theNode);
	}
	
	return true;
}




/* Replace a node with its children -- delete the item and move its children up one level in the hierarchy */
function replaceNodeWithChildren(theNode)
{
	var theChildren = new Array();
	var theParent = theNode.parentNode;
	
	if (theParent != null)
	{
		for (var i = 0; i < theNode.childNodes.length; i++)
		{
			theChildren.push(theNode.childNodes[i].cloneNode(true));
		}
		
		for (var i = 0; i < theChildren.length; i++)
		{
			theParent.insertBefore(theChildren[i], theNode);
		}
		
		theParent.removeChild(theNode);
		
		return theParent;
	}
	
	return true;
}




/* Add a class to a string */
String.prototype.addClass = function(theClass)
{
	if (this != "")
	{
		if (!this.classExists(theClass))
		{
			return this + " " + theClass;
		}
	}
	else
	{
		return theClass;
	}
	
	return this;
}




/* Check if a class exists in a string */
String.prototype.classExists = function(theClass)
{
	var regString = "(^| )" + theClass + "\W*";
	var regExpression = new RegExp(regString);
	
	if (regExpression.test(this))
	{
		return true;
	}
	
	return false;
}




/* Check if a string is the nodeName of an accepted element */
String.prototype.isAcceptedElementName = function()
{
	var elementList = new Array("#text", "a", "em", "h1", "h2", "h3", "h4", "h5", "h6", "img", "li", "ol", "p", "strong", "ul");
	var theName = this.toLowerCase();
	
	for (var i = 0; i < elementList.length; i++)
	{
		if (theName == elementList[i])
		{
			return true;
		}
	}
	
	return false;
}




/* Check if a string is the nodeName of an inline element */
String.prototype.isInlineName = function()
{
	var inlineList = new Array("#text", "a", "em", "font", "span", "strong", "u");
	var theName = this.toLowerCase();
	
	for (var i = 0; i < inlineList.length; i++)
	{
		if (theName == inlineList[i])
		{
			return true;
		}
	}
	
	return false;
}




/* Remove a class from a string */
String.prototype.removeClass = function(theClass)
{
	var regString = "(^| )" + theClass + "\W*";
	var regExpression = new RegExp(regString);
	
	return this.replace(regExpression, "");
}




/* Reverse a string */
String.prototype.reverse = function()
{
	var theString = "";
	
	for (var i = this.length - 1; i >= 0; i--)
	{
		theString += this.charAt(i);
	}
	
	return theString;
}




/* Make tags valid by converting uppercase element and attribute names to lowercase and quoting attributes */
String.prototype.validTags = function()
{
	var theString = this;
	
	/* Replace uppercase element names with lowercase */
	theString = theString.replace(/<[^> ]*/g, function(match){return match.toLowerCase();});
	
	/* Replace uppercase attribute names with lowercase */
	theString = theString.replace(/<[^>]*>/g, function(match)
		{
			match = match.replace(/ [^=]+=/g, function(match2){return match2.toLowerCase();});

			return match;
		});
			
	/* Put quotes around unquoted attributes */
	theString = theString.replace(/<[^>]*>/g, function(match)
		{
			match = match.replace(/( [^=]+=)([^"][^ >]*)/g, "$1\"$2\"");
			
			return match;
		});
		
	return theString;
}
