
stylePath = "/skins/ace/";
_skin_path = "/skins/";
_script_path = "/";

baseHref = "http://www.elene-tlc.net";

_editor_url = "/editor/";
_editor_lang = "en"; 
_editor_skin = ""; 
_editor_styles_path = "/skins/ace/_editor.css";
_editor_dream_enabled = false;

/*
 * MindTouch DekiWiki - a commercial grade open source wiki
 *  derived from MediaWiki (www.mediawiki.org)
 * Copyright (C) 2006 MindTouch, Inc.
 * www.mindtouch.com  oss@mindtouch.com
 *
 * For community documentation and downloads visit www.opengarden.org;
 *  please review the licensing section.
 *
 * 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.
 * http://www.gnu.org/copyleft/gpl.html
 */

function BrowserVersion(){
    BrowserVersion.minInternetExplorerVersion = 6.0;
    BrowserVersion.minFirefoxVersion = 1.5;
    BrowserVersion.minCaminoVersion = "1.0";
    BrowserVersion.minFlockVersion = "0.5";
    
    this.isIE = false;
    this.isFF = false;
    this.isNS = true;
    this.isCamino = false;
    this.isSafari = false;
    this.isFlock = false;
    this.version = null;
    this.isSupported = false;
    
    var browserApp = navigator.userAgent;
    var s = "MSIE";
    var i;
    if((i = browserApp.indexOf(s)) >= 0){
        this.isIE = true;
        this.isNS = false;
        this.version = parseFloat(browserApp.substr(i+s.length));
        if(this.version >= BrowserVersion.minInternetExplorerVersion){
            this.isSupported = true;
        }
        return;
    }
    s = "Firefox/";
    if((i = browserApp.indexOf(s)) >= 0){
        this.isFF = true;
        this.version = parseFloat(browserApp.substr(i+s.length));
        if(this.version >= BrowserVersion.minFirefoxVersion){
            this.isSupported = true;
        }
        return;
    }
    s = "Safari/";
    if((i = browserApp.indexOf(s)) >= 0){
        this.isSafari = true;
        this.isSupported = false;
        return;
    }
    s = "Camino/";
    if((i = browserApp.indexOf(s)) >= 0){
        this.isCamino = true;
        this.version = browserApp.substr(i+s.length);
        if(this.version >= BrowserVersion.minCaminoVersion){
            this.isSupported = false;
        }
        return;
    }
    s = "Flock/";
    if((i = browserApp.indexOf(s)) >= 0){
        this.isFlock = true;
        this.version = browserApp.substr(i+s.length);
        if(this.version >= BrowserVersion.minFlockVersion){
            this.isSupported = true;
        }
        return;
    }
    s = "Netscape6/";
    if((i = browserApp.indexOf(s)) >= 0){
        this.isNS = true;
        this.version = parseFloat(browserApp.substr(i+s.length));
        return;
    }
    s = "Gecko";
    if((i = browserApp.indexOf(s)) >= 0){
        this.isNS = true;
        this.version = 6.1;
    }
};
/***
 * hooks an onclick to all links in the table of contents dropdown which closes the window
 */
function hookTOCLinks() {
	var elt = document.getElementById('menuPageContent');
	if (!elt) return;
	var a_ = elt.getElementsByTagName('a');	
	for (var i = 0; i < a_.length; i++)
		a_[i].onclick = function () { menuBodyClick() };
};

function breadcrumbLoad(z) {
	document.getElementById('breadcrumb').innerHTML = z;
};

function doClosePopupMessage(divid, clearInnerHtml) {
    parent.hidePopWin(false);
	return false;
};

function doHidePopupMessage() {
   return doClosePopupMessage();
};

/***
 * this function will take all external link icons from topic
 * and append a child span that contains the link icon
 * this is to correct IE's behaviour of handling links that break cross mult lines
 */
function fixLinkIcons() {
	var browser = new BrowserVersion();
	if (clientBrowser.isIe && browser.version < 7) {
		var elt = document.getElementById('topic');
		var a = elt.getElementsByTagName('a');
		var j = a.length;
		for (var i = 0; i < j; i++) {
			var rel = a[i].getAttribute('rel');
			if (rel && typeof(rel) == 'string' && rel != '') {
				var icona = a[i].cloneNode(true);
				var texta = a[i].cloneNode(true);
				icona.innerHTML = '&nbsp;';
				icona.style.textDecoration = 'none';
				icona.removeAttribute('rel');
				texta.removeAttribute('rel');
				texta.removeAttribute('className');
				if (a[i].className == 'link-user') {
					icona.style.padding = '0 3px 0 6px';
				} else if (rel != 'internal') {
					icona.style.padding = a[i].className == 'link-mailto' ? '0 12px 0 0' : '0 9px 0 0';
					texta.style.paddingRight = '0';
					texta.style.background = '';
				} else {
					icona.style.padding = '0 0 0 14px';
				}
				var span = document.createElement('span');
				if (rel == 'internal') {
					span.appendChild(icona);
					span.appendChild(texta);	
				}
				else{
					span.appendChild(texta);
					span.appendChild(icona);	
				}
				var parent = a[i].parentNode;
				parent.replaceChild(span, a[i]);
			}
		}
	}
};

function createFullHtml(title, body, head, _lang) {
    var html = "<html>\n";
    html += "<head>\n";
    html += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + (HTMLArea.is_gecko ? document.characterSet : document.charset) + "\">\n";
    html += "<title>" + title + "</title>\n";
    html += "<link rel=\"stylesheet\" type=\"text/css\" href=\"/editor/popups/popup.css\" />\n";
    html += "<link rel=\"stylesheet\" type=\"text/css\" href=\"/skins/ace/_icons.css\" />\n";
    html += "<link rel=\"stylesheet\" type=\"text/css\" href=\"/skins/ace/__icons.css\" />\n";
    html += "<link rel=\"stylesheet\" type=\"text/css\" href=\"/editor/popups/selectTopic.css\" />\n";
    html += "<script type=\"text/javascript\" src=\"/editor/popups/popup.js\"></script>\n";
    html += "<script type=\"text/javascript\">function Init() {};\n";
    for (var i in _lang)
    	html += "var "+i+" = '"+_lang[i]+"';\n";
    html += "</script>\n";
    if (head) html += head;
    html += "</head>\n";
    html += "<body onload='Init()'><div class=\"wrap\">\n";
    html += body;
    html += "</div></body>\n";
    html += "</html>";
    return html;
};

function doPopupAttach() {
	if (document.getElementById('editarea'))
		{
		alert("Sorry, you can't attach files while editing a page. Please close the editor first.");
		return false;
		}
    showPopWin('/editor/popups/loading.html', 650, 134);
    var lang = new Object();
    lang['_lang_removeattach'] = _lang_removeattach;
    lang['_lang_fileattach'] = _lang_fileattach;
    setPopWinHTML(createFullHtml('Attach File', 
    	'<div id="attachFileForm">'+document.getElementById('attachFileForm').innerHTML+'</div>',
        "<script src=\"/skins/ace/attach.js\"></script>\n" +
        "<script type=\"text/javascript\">function Init() { __dlg_sizeToContent(); };</script>\n", lang
    ));
    return false;
};

function doPopupAttachNotification() {
	gPopupDoc.getElementById('form').style.display = "none";
	gPopupDoc.getElementById('waiting').style.display = "inline";
};
function doPopupRename(titleID) {
	showPopWin('/skins/ace/popup-rename.php?titleID=' + titleID + '&userName=' + _userName, 570, 530);
	return false;
};
function doPopupInvite(titleID) {
	showPopWin('/skins/ace/popup-invite.php?titleID=' + titleID + '&userName=' + _userName, 470, 300);
	return false;
};
function doPopupMoveAttach(titleID, attachID) {
	showPopWin('/skins/ace/popup-move-attach.php?titleID=' + titleID +'&attachID=' +  attachID + '&userName=' + _userName, 570, 459);
	return false;
};
function doPopupEditAttach(attachID) {
	showPopWin('/skins/ace/popup-attach.php?attachID=' + attachID, 380, 206);
	return false;
};
function doPopupRestrict(titleID) {
	showPopWin('/skins/ace/popup-restrict.php?titleID=' + titleID + '&userName=' + _userName, 380, 315);
	return false;
};
function doPopupViewRestrict(titleID) {
	showPopWin('/skins/ace/popup-viewrestrict.php?titleID=' + titleID, 380, 320);
	return false;
};

function doPopupUnsupported() {
	showPopWin('/skins/ace/popup-unsupported.php', 380, 320);
	return false;
};
function doPopupDelete(titleID) {
	showPopWin('/skins/ace/popup-delete.php?titleID=' + titleID + '&userName=' + _userName, 400, 224);
	return false;
};

function hookEditIcons() {
	function showEditIcon(e) {
		var aTags = this.getElementsByTagName('a');
		if (aTags.length >= 1)
			aTags[0].style.visibility = 'visible';
	};
	function hideEditIcon(e) {
		var aTags = this.getElementsByTagName('a');
		if (aTags.length >= 1)
			aTags[0].style.visibility = 'hidden';
	};
	var elt = document.getElementById('topic');
	for (var i = 2; i < 7; i++) {
		var headers = elt.getElementsByTagName('h'+i);
		for (var j = 0;j<headers.length;j++) {
			var h = headers[j];
			h.onmouseover = showEditIcon;
			h.onmouseout = hideEditIcon;
		}
	}
};

var fps = 500;
function doFade(elt, duration, _fade) {
	if (elt.fadeTimer) 
		clearInterval(elt.fadeTimer);

	elt.fadeOps = new Array();

	elt.fadeFrames = Math.round(fps * duration / 1000);
	elt.fadeInterval = 1000 / fps;
	for (var i = 0; i < _fade.length; i++) {
		var op = {};
		op.param = _fade[i].param;
		op.from = _fade[i].from;
		op.to = _fade[i].to;
		elt.fadeOps[elt.fadeOps.length]= op;
	}
	
	elt.fadeFrame = 0;
	elt.fadeTimer = setInterval ("doStep ('" + elt.id + "')", elt.fadeInterval);
};
	
function doStep(divid) {
	var elt = document.getElementById (divid);

	var completed = elt.fadeFrame / elt.fadeFrames;
	var inverseCompleted = (elt.fadeFrames - elt.fadeFrame) / elt.fadeFrames;

	for (var i = 0; i < elt.fadeOps.length; i ++) {
		var op = elt.fadeOps[i];
		elt.style[op.param] = Number (op.from) * inverseCompleted + Number (op.to) * completed;
	}

	elt.fadeFrame++;

	if (elt.fadeFrame > elt.fadeFrames) {
		clearInterval (elt.fadeTimer);
		elt.fadeTimer = null;
	}
};

function displayInlineMsg(div) {
	var elt = document.getElementById(div);
	
	//page offset from top
	var yOffset = getPageYOffset();
	elt.style.display = 'block';
	var itemHeight = getItemHeight(elt);
	var itemWidth = getItemWidth(elt);
	var eltXOffset = (winX/2) - (itemWidth/2);
	var eltYOffset = (winY/2) - (itemHeight/2) + yOffset;
	
	//set the props of the elt
	elt.style.position = 'absolute';
	elt.style.left = Math.round(eltXOffset) + 'px';
	elt.style.top = Math.round(eltYOffset) + 'px';
	elt.zIndex = 9999;
	
	//hide the message after a few minutes
    window.setTimeout("hideInlineMsg('"+div+"')", 3000);
    
    //IE doesn't support opacity
    if (!ie6 && !ie5) {
		doFade (elt, 650, [{param: "opacity", from: 1.0, to: 0.0}]);
	}
};

function hideInlineMsg(div) {
	document.getElementById(div).style.display = 'none';
};

function fixTables() {
	if (!clientBrowser.isIe)
		return;
	var content = document.getElementById('topic');
	var _tables = content.getElementsByTagName('table');
	if (_tables.length == 0)
		return false;
		
	for (var i = 0; i < _tables.length; i++ ) {		
		var table = _tables[i].cloneNode(true);
		var divTag = document.createElement('div');
		divTag.className = 'wrap_tbl';
		divTag.appendChild(table);
		if (is_gecko) {
			var parentNode = _tables[i].parentNode;
			parentNode.replaceChild(divTag, _tables[i]);
		}
		else {
			_tables[i].replaceNode(divTag);
		}
	}
	
};
function doToggleLayer(elt, setClass, toggleClass) {
	if (!setClass)
		setClass = 'show-no';
		
	if (elt.className == setClass) {
		elt.className = toggleClass;
		return;
	}
	
	if (elt.className == toggleClass) {
		elt.className = setClass;
		return;
	}
		
	var cssClass = elt.className.split(' ');
	if (searchKey = array_search(setClass, cssClass)) 
		cssClass[searchKey] = toggleClass;
	
	else
		cssClass.push(setClass);
		
	elt.className = cssClass.join(' ');
};
function array_search(needle, haystack) {
	for (var i = 0; i < haystack.length; i++ ) {
		if (haystack[i] == needle)
			return i;	
	}	
	return false;
};

function doSectionEditRedirect() {
	var icon = this.getElementsByTagName('span');
	if (icon.length == 0)
		return false;
	for (var i = 0; i < icon.length; i++) {
		if (icon[i].className == 'editsection') {	
			var link = this.getElementsByTagName('a');
			top.location.href = link[0].getAttribute('href');
		}
	}
};

function setHiddenSubmit(divid) {
	document.getElementById(divid).value = '1';
};

// toggles between image description/image form
function fileDesc(divid, type) {
	if (type == 'hide') {
		setDisplayMode('fileDescForm_'+divid, 'hide');
		setDisplayMode('fileDescDisplay_'+divid, 'show');
	}
	else {
		setDisplayMode('fileDescForm_'+divid, 'show');
		setDisplayMode('fileDescDisplay_'+divid, 'hide');
		document.getElementById('fileDescElement_'+divid).focus();
	}	
	imageCellHeights.resize();
	return false;
};

var imageCellHeights = {
	x : null, //total width of the gallery
	cellWidth : 200, //width of each image cell
	cellMinHeight : 235, //minimum cell height
	resize : function ()  {
		var elt = document.getElementById('imageGallery');
		if (!elt) 
			return;
			
		this.x = getItemWidth(elt);
		var imagesPerRow = Math.floor(this.x / this.cellWidth);
		var i = 0; //current number of images in the row
		var curRowHeight = 0;
		var cellHeight = 0;
		var list = elt.getElementsByTagName('li');
		for (var j = 0; j < list.length; j++) {
			list[j].style.height = '';
			list[j].style.minHeight = '';
			cellHeight = getItemHeight(list[j]);
			if (cellHeight > curRowHeight) 
				curRowHeight = cellHeight;
			if (i < (imagesPerRow - 1))
				i++;
			else {
				i = 0;
				curRowHeight = curRowHeight < this.cellMinHeight ? this.cellMinHeight: curRowHeight;
				
				//reset all items in this row to the greatest height
				for (k = 0; k < imagesPerRow; k++) {
					if (ie6 == 1)
						list[j-k].style.height = curRowHeight+'px';
					else
						list[j-k].style.minHeight = curRowHeight+'px';
				}
				curRowHeight = 0;
			}
		}
	}
};

function setDisplayMode(divid, type) {
	if (divLayer = document.getElementById(divid)) {
		if (type == 'show')
			divLayer.style.display = 'block';
		if (type == 'hide')
			divLayer.style.display = 'none';
	}
};

function toggleVisi(divid) {
 	if (myselect = document.getElementById(divid)) {
	 	if (myselect.style.visibility != 'hidden')
		 	myselect.style.visibility = "hidden";
	 	else 
		 	myselect.style.visibility = "visible";
 	}
};

// Wikipedia JavaScript support functions
// if this is true, the toolbar will no longer overwrite the infobox when you move the mouse over individual items
var noOverwrite=false;
var alertText;
var clientPC = navigator.userAgent.toLowerCase(); // Get client info
var is_gecko = ((clientPC.indexOf('gecko')!=-1) && (clientPC.indexOf('spoofer')==-1)
                && (clientPC.indexOf('khtml') == -1) && (clientPC.indexOf('netscape/7.0')==-1));
var is_safari = ((clientPC.indexOf('AppleWebKit')!=-1) && (clientPC.indexOf('spoofer')==-1));
var is_khtml = (navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled ));
if (clientPC.indexOf('opera')!=-1) {
    var is_opera = true;
    var is_opera_preseven = (window.opera && !document.childNodes);
    var is_opera_seven = (window.opera && document.childNodes);
}

// add any onload functions in this hook (please don't hard-code any events in the xhtml source)
function onloadhook () {
    // don't run anything below this for non-dom browsers
    if(!(document.getElementById && document.getElementsByTagName)) return;
    histrowinit();
    unhidetzbutton();
    akeytt();
};

if (window.addEventListener) window.addEventListener("load",onloadhook,false);
else if (window.attachEvent) window.attachEvent("onload",onloadhook);


// document.write special stylesheet links
if(typeof stylepath != 'undefined' && typeof skin != 'undefined') {
    if (is_opera_preseven) {
        document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/Opera6Fixes.css" />');
    } else if (is_opera_seven) {
        document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/Opera7Fixes.css" />');
    } else if (is_khtml) {
        document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/KHTMLFixes.css" />');
    }
}
// for enhanced RecentChanges
function toggleVisibility( _levelId, _otherId, _linkId) {
	var thisLevel = document.getElementById( _levelId );
	var otherLevel = document.getElementById( _otherId );
	var linkLevel = document.getElementById( _linkId );
	if ( thisLevel.style.display == 'none' ) {
		thisLevel.style.display = 'block';
		otherLevel.style.display = 'none';
		linkLevel.style.display = 'inline';
	} else {
		thisLevel.style.display = 'none';
		otherLevel.style.display = 'inline';
		linkLevel.style.display = 'none';
		}
};

// page history stuff
// attach event handlers to the input elements on history page
function histrowinit () {
    hf = document.getElementById('pagehistory');
    if(!hf) return;
    lis = hf.getElementsByTagName('td');
    for (i=0;i<lis.length;i++) {
        inputs=lis[i].getElementsByTagName('input');
        if(inputs[0] && inputs[1]) {
                inputs[0].onclick = diffcheck;
                inputs[1].onclick = diffcheck;
        }
    }
    diffcheck();
};

// check selection and tweak visibility/class onclick
function diffcheck() { 
    var dli = false; // the li where the diff radio is checked
    var oli = false; // the li where the oldid radio is checked
    hf = document.getElementById('pagehistory');
    if(!hf) return;
    lis = hf.getElementsByTagName('td');
    for (i=0;i<lis.length;i++) {
        inputs=lis[i].getElementsByTagName('input');
        if(inputs[1] && inputs[0]) {
            if(inputs[1].checked || inputs[0].checked) { // this row has a checked radio button
                if(inputs[1].checked && inputs[0].checked && inputs[0].value == inputs[1].value) return false;
                if(oli) { // it's the second checked radio
                    if(inputs[1].checked) {
                    oli.className = "selected";
                    return false 
                    }
                } else if (inputs[0].checked) {
                    return false;
                }
                if(inputs[0].checked) dli = lis[i];
                if(!oli) inputs[0].style.visibility = 'hidden';
                if(dli) inputs[1].style.visibility = 'hidden';
                lis[i].className = "selected";
                oli = lis[i];
            }  else { // no radio is checked in this row
                if(!oli) inputs[0].style.visibility = 'hidden';
                else inputs[0].style.visibility = 'visible';
                if(dli) inputs[1].style.visibility = 'hidden';
                else inputs[1].style.visibility = 'visible';
                lis[i].className = "";
            }
        }
    }
};


// Timezone stuff
// tz in format [+-]HHMM
function checkTimezone( tz, msg ) {
	var localclock = new Date();
	// returns negative offset from GMT in minutes
	var tzRaw = localclock.getTimezoneOffset();
	var tzHour = Math.floor( Math.abs(tzRaw) / 60);
	var tzMin = Math.abs(tzRaw) % 60;
	var tzString = ((tzRaw >= 0) ? "-" : "+") + ((tzHour < 10) ? "0" : "") + tzHour + ((tzMin < 10) ? "0" : "") + tzMin;
	if( tz != tzString ) {
		var junk = msg.split( '$1' );
		document.write( junk[0] + "UTC" + tzString + junk[1] );
	}
};
function unhidetzbutton() {
    tzb = document.getElementById('guesstimezonebutton')
    if(tzb) tzb.style.display = 'inline';
};

// in [-]HH:MM format...
// won't yet work with non-even tzs
function fetchTimezone() {
	// FIXME: work around Safari bug
	var localclock = new Date();
	// returns negative offset from GMT in minutes
	var tzRaw = localclock.getTimezoneOffset();
	return formatTimezone(tzRaw);
};

function formatTimezone(tzSecs) {
	var tzHour = Math.floor( Math.abs(tzSecs) / 60);
	var tzMin = Math.abs(tzSecs) % 60;
	return  ((tzSecs >= 0) ? "-" : "") + ((tzHour < 10) ? "0" : "") + tzHour +
		":" + ((tzMin < 10) ? "0" : "") + tzMin;
};

function checkTimezone() {
	var currentTZ = fetchTimezone();
	if (_cur_TZ != currentTZ) {
		x_doSetTimezone(currentTZ, cb_blank);
	}
};

function guessTimezone() {
    var wpHourDiff = document.getElementById('wpHourDiff');
	if (wpHourDiff) wpHourDiff.value = fetchTimezone();
};

function toggleItem(toggleid, contentid) {
	var toc = document.getElementById(toggleid);
	var content = document.getElementById(contentid);
	var spans = toc.getElementsByTagName('span');
	var showlink = spans[0];
	var hidelink = spans[1];
	
	//if we are showing the content
	if (content.style.display == 'none') {
		content.style.display = 'block';
		showlink.style.display = 'none';
		hidelink.style.display = 'block';
	}
	else {
		content.style.display = 'none';
		showlink.style.display = 'block';
		hidelink.style.display = 'none';
	}
};

function openWindow(href,menu) {
	window.open(href, 'popupwindow', 'width='+(winX - 100)+',height='+(winY - 100)+',scrollbars,resizable' + (menu ? ',menubar=yes' : ''));
	return false;
};

function addInfobox(infoText,text_alert) {
	alertText=text_alert;
	var clientPC = navigator.userAgent.toLowerCase(); // Get client info

	var re=new RegExp("\\\\n","g");
	alertText=alertText.replace(re,"\n");

	// if no support for changing selection, add a small copy & paste field
	// document.selection is an IE-only property. The full toolbar works in IE and
	// Gecko-based browsers.
	if(!document.selection && !is_gecko) {
 		infoText=escapeQuotesHTML(infoText);
	 	document.write("<form name='infoform' id='infoform'>"+
			"<input size=80 id='infobox' name='infobox' value=\""+
			infoText+"\" readonly='readonly'></form>");
 	}
};

function escapeQuotes(text) {
	var re=new RegExp("'","g");
	text=text.replace(re,"\\'");
	re=new RegExp('"',"g");
	text=text.replace(re,'&quot;');
	re=new RegExp("\\n","g");
	text=text.replace(re,"\\n");
	return text;
};

function escapeQuotesHTML(text) {
	var re=new RegExp('"',"g");
	text=text.replace(re,"&quot;");
	return text;
};

function akeytt() {
    if(typeof ta == "undefined" || !ta) return;
    pref = 'alt-';
    if(is_safari || navigator.userAgent.toLowerCase().indexOf( 'mac' ) + 1 ) pref = 'control-';
    if(is_opera) pref = 'shift-esc-';
    for(id in ta) {
        n = document.getElementById(id);
        if(n){
            a = n.childNodes[0];
            if(a){
                if(ta[id][0].length > 0) {
                    a.accessKey = ta[id][0];
                    ak = ' ['+pref+ta[id][0]+']';
                } else {
                    ak = '';
                }
                a.title = ta[id][1]+ak;
            } else {
                if(ta[id][0].length > 0) {
                    n.accessKey = ta[id][0];
                    ak = ' ['+pref+ta[id][0]+']';
                } else {
                    ak = '';
                }
                n.title = ta[id][1]+ak;
            }
        }
    }
};

function toggleTable(divid) {
	//change icon
 	var showlink = document.getElementById('showlink-'+divid);
 	var hidelink = document.getElementById('hidelink-'+divid);
 	
 	if( showlink.style.display == 'none') {
		hidelink.style.display='none';
		showlink.style.display='block';
	} else {
		hidelink.style.display='block';
		showlink.style.display='none';
	}	
	
	//loop through table	
	var cells = document.getElementsByTagName('tr');
	var numCells = cells.length;
	var i;
	
	for (i = 0; i < numCells; ++i) {
		// If cell should be changed (matching class)...
		if (divid+' show-no' == cells[i].className)
			cells[i].className = divid + ' display';
		else if (divid+' display' == cells[i].className)
			cells[i].className = divid + ' show-no';
	}
	return false;
};

/* blank function for sajax callback */
function cb_blank() {};

/* function for sajax; persistent addtl nav */
function do_context(z) {
	x_wfStoreContextStatus(z, cb_blank);
};

//MT: royk search toggling
function toggleSearchTabs() {
	var titleContent = document.getElementById('search-title');
	var pageContent = document.getElementById('search-page');
	var tabTitle = document.getElementById('search-title-tab');
	var tabPage = document.getElementById('search-page-tab');
	
	if (titleContent.style.display == 'none') {
		titleContent.style.display = 'block';
		pageContent.style.display = 'none';
		tabTitle.className = 'selected';
		tabPage.className = '';
		var page = 'title';
	}
	else {
		titleContent.style.display = 'none';
		pageContent.style.display = 'block';
		tabTitle.className = '';
		tabPage.className = 'selected';
		var page = 'page';
	}	
	x_wfStoreSearchStatus(page, cb_blank);
};

function createCookie(name,value,days) { 
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else {
		var expires = "";
	}
	document.cookie = name+"="+value+expires+"; path=/";
};

function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') 
			c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) 
			return c.substring(nameEQ.length,c.length);
	}
	return null;
};

function eraseCookie(name) {
	createCookie(name,"",-1);
};
function doRestrictAccess(titleID, userName, protectType, userIds) {
	x_wfRestrictTopic(titleID, userName, protectType, userIds, function (data) { 
		hidePopWin (false); 
		window.location.reload(); 
	});
};

function doDeleteAction (titleID, includingChildren) {
	x_wfDeleteTopic(titleID, includingChildren, _userName, function (data) {
		var status = data.charAt(0);
		if (status == '<') {
			data = data.replace(/<br\s*\/?>/ig, "\n");
		}
		if (status == '+') {
			data = data.substring(1);
			hidePopWin (false);
			window.location = data;
		} else {
			if (status == '-')
				data = data.substring (1);
			hidePopWin (false);
		}
	});
};

/*
 * MindTouch DekiWiki - a commercial grade open source wiki
 *  derived from MediaWiki (www.mediawiki.org)
 * Copyright (C) 2006 MindTouch, Inc.
 * www.mindtouch.com  oss@mindtouch.com
 *
 * For community documentation and downloads visit www.opengarden.org;
 *  please review the licensing section.
 *
 * 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.
 * http://www.gnu.org/copyleft/gpl.html
 */

var row_count = 3;
function addRow() {
	var tbl = document.getElementById('attachFiles');
	var maxNum = document.getElementById('maxNum');
	
	var newRow = tbl.insertRow(tbl.rows.length);
	++row_count;
	newRow.insertCell(0).innerHTML = '<a href="#" onclick="return addRow()" title="'+_lang_fileattach+'"><span class="icon"><img src="/skins/ace/icon-trans.gif" class="attach-add" alt=""></span></a><a href="#" onclick="return delRow(this.parentNode.parentNode.rowIndex)" title="'+_lang_removeattach+'"><span class="icon"><img src="/skins/ace/icon-trans.gif" class="attach-remove"></span></a>';
	newRow.insertCell(1).innerHTML = '<input name="file_'+row_count+'" id="file_'+row_count+'" size="40" type="file"/>';	
	newRow.insertCell(2).innerHTML = '<input type="text" name="filedesc_'+row_count+'" style="width:100%"/>';
	if (row_count > maxNum.value)
		maxNum.value = row_count;
	__dlg_sizeToContent();
	return false;
};
function delRow(indexKey) {
	var tbl = document.getElementById('attachFiles');
	if (tbl.rows.length > 2) {
		tbl.deleteRow(indexKey);
		for (var j = indexKey + 1; j < tbl.rows.length; j++)
			if (tbl.rows[j] && typeof(tbl.moveRow) == 'function') 
				tbl.moveRow(j, j - 1);	
	} else
		parent.doClosePopupMessage();
	__dlg_sizeToContent();
	return false;
};

function doEditAttachDescription(attachID, attachDesc) {
	x_attachEdit(attachID, attachDesc, function(returnValue) {
		hidePopWin (false); 
    	if (returnValue == 'failed') {
	    	return;
    	}
		var elt = document.getElementById('fileDescDisplay_'+attachID);
    	var returnValues = returnValue.split('|');
    	var html = '';
    	if (returnValues.length > 3) {
    		for (var i=2;i<returnValues.length;i++)
    			html += returnValues[i];
    	}
    	else
    		html = returnValues[2];	

    	if (returnValues[0] == 'success')
    		elt.innerHTML = html == '' ? '<span class="nodescription">No description</span>' : html;
    		
        imageCellHeights.resize();
	});
};
/*
 * MindTouch DekiWiki - a commercial grade open source wiki
 *  derived from MediaWiki (www.mediawiki.org)
 * Copyright (C) 2006 MindTouch, Inc.
 * www.mindtouch.com  oss@mindtouch.com
 *
 * For community documentation and downloads visit www.opengarden.org;
 *  please review the licensing section.
 *
 * 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.
 * http://www.gnu.org/copyleft/gpl.html
 */

var menuBubble = false;
var menuOpened = false;
var menuJustOpened = false;
var menuSelect = false;

menuLinkClick = function(divid, offsetX) {
	if (menuOpened && menuOpened != divid)
		menuToggle(menuOpened, offsetX);
	menuToggle(divid, offsetX);
};

menuToggle = function(navid, offsetX) {
	var node = document.getElementById(navid);
	if (!node) return false;
	if (node.style.display == 'block') {
		node.style.display = 'none';	
		menuOpened = false;
	}
	else {
		node.style.visibility = 'hidden';
		node.style.display = 'block';
		var dimensions = Element.getDimensions(node);
		var position = Position.cumulativeOffset(node);
		if (typeof(winX) != 'null') {
			if ((position[0] + dimensions.width) > (winX - 36)) {
				if (typeof(offsetX) == 'undefined') offsetX = 0;
				node.style.left = (position[0] - dimensions.width + offsetX + 5)+'px';
			}
		}
		node.style.visibility = '';
		menuOpened = navid;
		menuJustOpened = true;
	}
};

menuPosition = function (navid, elt, offsetX, offsetY) {
	var x = findPosX(elt);
	var y = findPosY(elt);
	var dimension = Element.getDimensions(elt);
	offsetY = offsetY + dimension.height;
	if (typeof(offsetX) == 'number') x = x + offsetX;
	if (typeof(offsetY) == 'number') y = y + offsetY;
	var node = dojo.byId(navid);
	if (!node) return false;
	node.style.left = x+'px';
	node.style.top = y+'px';
	menuLinkClick(navid, dimension.width);
	return false;
};

menuOff = function(navid) {
	var node = document.getElementById(navid);
	if (!node)
		return false;
	if (node.style.display == 'block') {
		node.style.display = 'none';	
		menuOpened = false;
	}
};

menuBodyClick = function() {
	if (!menuJustOpened && !menuBubble && menuOpened) {
		if (menuSelect) {
			selectToggle(menuOpened);
		}
		else {
			menuToggle(menuOpened);
		}
	}
	if (menuBubble)
		menuBubble = false;	
	if (menuJustOpened)
		menuJustOpened = false;	
};

// select stuff
function selectClick(divid) {
	if (menuOpened && menuOpened != divid)
		selectToggle(menuOpened);	
	selectToggle(divid);
}

function selectToggle(divid) {
	var elt = document.getElementById(divid);
	if (!elt) {
		return false;
	}
	var ul_ = document.getElementsByTagName('ul');
	for ( var i = 0 ; i < ul_.length ; i++) {
		if (ul_[i].className == 'fauxOptions') {
			if (ul_[i].style.display == 'block') {
				ul_[i].style.display = 'none';
				doSetSelectClasses(divid, true);
				menuOpened = false;
				menuSelect = false;
			}
			else {
				ul_[i].style.display = 'block';
				menuOpened = divid;
				menuJustOpened = true;
				menuSelect = true;
			}
		}
	}		
}
 function selectBodyClick() {
  if (!menuJustOpened && !menuBubble && menuOpened)
	selectToggle(menuOpened);
  menuBubble = false;  
  menuJustOpened = false;  
};

function selectClick(node) {
  if (menuOpened && menuOpened != node)
	selectToggle(menuOpened);  
  selectToggle(node);
};

function selectToggle(node) {
  var fauxOptions = node.mt_select.fauxOptions;
  if (fauxOptions.style.display == 'block') {
	fauxOptions.style.display = 'none';
	node.mt_select.options[node.mt_select.selected].node.className = "selected";
	menuOpened = false;
	menuSelect = false;
  } else {
	fauxOptions.style.display = 'block';
	var selNode = node.mt_select.curSelectVal.parentNode;
	fauxOptions.style.left = MT.getOffsetLeft(selNode) + "px";
	fauxOptions.style.top = MT.getOffsetTop(selNode) + selNode.offsetHeight - 1 + "px";
	menuOpened = node;
	menuJustOpened = true;
	menuSelect = true;
  }
};

var NavMenu = { 
	lastOpened : null, //the last opened menu id
	isOpening : null,
	openMenu : false,
	justClosed : false,
	maxHeight: 132, //max height of the menu
	minHeight: 1, //min height of the menu; keep at least 1px for IE
	
	bodyClick : function() {
		if (this.isOpening) {
			this.isOpening = null;
			return;
		}
		if(this.lastOpened) {
			this.hide();
		}
		return false;
	},
	/*** 
	 * 
	 */
	show : function(contextNode, titleID, title, isWatching, isBookmarked, isLoggedIn, canMove, canDelete, isRestricted) {
		this.menuBubble = true;
		this.isOpening = true;
		var divFiller = 'npdFiller_' + titleID;
		var divMenu = 'npdmenu_' + titleID;
		var divContainer = 'container_' + titleID;
		var eltContainer = document.getElementById(divContainer);
		addCSSClass(eltContainer, 'force');
		
		if (this.lastOpened && '_' + titleID != this.lastOpened) {
			this.hide();
		}
		else if (this.lastOpened) {
			this.hide();
			this.justClosed = true;
			return;
		}
		this.lastOpened = '_' + titleID;
		
		var eltFiller = document.getElementById(divFiller);
		var dimensions = Element.getDimensions(contextNode);
		var position = Position.cumulativeOffset(contextNode);
		eltFiller.style.position = 'absolute';
		eltFiller.style.left = (position[0])+'px';
		eltFiller.style.top = (position[1] + dimensions.height) + 'px';
		
		//for IE
		eltFiller.style.display = '';		
		//first, generate the new menu
		eltFiller.appendChild(this.generateMenu(contextNode, titleID, title, isWatching, isBookmarked, isLoggedIn, canMove, canDelete, isRestricted));
		eltFiller.style.display = 'block';
		menuLinkClick(divMenu);
	},
	hide: function () {
		if (this.lastOpened) {
			var divContainer = 'container' +this.lastOpened;
			var eltContainer = document.getElementById(divContainer);
			removeCSSClass(eltContainer, 'force');
			removeCSSClass(eltContainer, 'container-hover');
			removeCSSClass(eltContainer, 'default');
			addCSSClass(eltContainer, 'container');
			var eltMenu = 'npdmenu' + this.lastOpened;	
			var trielt = document.getElementById('expNode'+this.lastOpened);
			if (trielt) trielt.style.visibility = 'hidden';
			var elt = document.getElementById(eltMenu);
			elt.parentNode.removeChild(elt);
			menuLinkClick(eltMenu);	
		}
		this.lastOpened = null;
	},
	
	generateMenu : function (contextNode, titleID, title, isWatching, isBookmarked, isLoggedIn, canMove, canDelete, isRestricted) {
		function createColor(color, title, divid) {	
			var colorNode = document.createElement('a');
			colorNode.href = '#';
			colorNode.setAttribute('stat', 102/*MKS_STAT_MENU_HIGHLIGHT*/);
			if (color == 'cancel') {
				colorNode.className = 'block';
				colorNode.appendChild(iconify('cancel', 'icon-s'));	
			}
			else {
				colorNode.className = 'block '+color;
			}
			colorNode.onclick = function() {
				setColor(title, color);
				return false;
			}
			return colorNode;
		};
		
		function addMenuItem(action, icon, text, onclick, stat) {
			var item = document.createElement('li');
			var a = document.createElement('a');
			
			a.href = action && isLoggedIn ? url+action : "#";
			a.className = 'mlink';
			a.setAttribute('stat', stat);
			a.appendChild(iconify(icon));
						
			var span = document.createElement('span');
			span.innerHTML = text;
			span.className = 'text';
			a.appendChild(span);
			
			if (onclick && isLoggedIn)
			  a.onclick = onclick;
			item.appendChild(a);
			menuList.appendChild(item);
		};

		function addDisabledMenuItem(icon,text) {
			var item = document.createElement('li');
			var a = document.createElement('a');
			a.className = 'mlink disabled';
			a.href = "#";
			a.onclick = function() { return false; }
			a.appendChild(iconify(icon));

			var span = document.createElement('span');
			span.innerHTML = text;
			span.className = 'text';
			a.appendChild(span);

			item.appendChild(a);
			menuList.appendChild(item);
		};

		var divid = 'npdmenu_' + titleID;
		var url = mt_gen.getUrlFromName(title);

		var divMain = document.createElement('div');
		divMain.onclick = function () {
			menuBubble = true;	
		};
		divMain.className = 'dmenu';

		var divWrap = document.createElement('div');
		divWrap.id = divid;
		divWrap.className = 'dmenu-wrap';

		var divTop = document.createElement('div');
		divTop.className = 'dmenu-top';

		var divBottom = document.createElement('div');
		divBottom.className = 'dmenu-bottom';

		var divBody = document.createElement('div');
		divBody.className = 'dmenu-body';

		var menuList = document.createElement('ul');
		
		if (isLoggedIn) {
			addMenuItem('&action=addsubpage','addSubpage', _lang_addSubpage, false, 98/*MKS_STAT_MENU_NEW_SUBPAGE*/);
		}
		else {
			addDisabledMenuItem('addSubpage-disabled', _lang_addSubpage);
		}

		if (!_isGuest) {
    		if (isLoggedIn && canMove) {
    			addMenuItem(null,'move',_lang_move,function () {
    				NavMenu.hide();
    				doPopupRename(titleID, title);
    				return false;
    			}, 101/*MKS_STAT_MENU_MOVE*/);
    		}
    		else if (isRestricted) {
    			addMenuItem(null,'move',_lang_move,function () {
    				NavMenu.hide();
    				doPopupViewRestrict(titleID);
    				return false;
    			});
    		}
    		else {
    			addDisabledMenuItem('move-disabled', _lang_move);
    		}
    		if (isLoggedIn && canDelete) {
    			addMenuItem(null,'delete',_lang_delete,function () {
    				NavMenu.hide();
    				doPopupDelete(titleID, title);
    				return false;
    			}, 70/*MKS_STAT_MENU_DELETE*/);
    		}
    		else if (isRestricted) {
    			addMenuItem(null,'delete',_lang_delete,function () {
    				NavMenu.hide();
    				doPopupViewRestrict(titleID);
    				return false;
    			});
    		}
    		else {
    			addDisabledMenuItem('delete-disabled', _lang_delete);
    		}
		}

		var separator = document.createElement('li');
		separator.className = 'separator';
		menuList.appendChild(separator);

		//highlighting
		var item = document.createElement('li');
		var span = document.createElement('div');
		span.className = 'option';
		var ispan = document.createElement('span');
		ispan.innerHTML = _lang_hilite;
		var breaker = document.createElement('div');
		breaker.className = 'br';

		var divColors = document.createElement('div');
		divColors.className = 'colors';
		divColors.appendChild(createColor('cancel', titleID, divid));
		divColors.appendChild(createColor('red', titleID, divid));
		divColors.appendChild(createColor('green', titleID, divid));
		divColors.appendChild(createColor('blue', titleID, divid));
		divColors.appendChild(createColor('yellow', titleID, divid));

		span.appendChild(divColors);
		span.appendChild(ispan);
		span.appendChild(breaker);

		item.appendChild(span);
		menuList.appendChild(item);

		divBody.appendChild(menuList);

		divWrap.appendChild(divTop);
		divWrap.appendChild(divBody);
		divWrap.appendChild(divBottom);

		divMain.appendChild(divWrap);
		
		return divMain;
	}
};

var FileMenu = { 
	lastOpened : null, //the last opened menu id
	isOpening : null,
	openMenu : false,
	justClosed : false,
	maxHeight: 132, //max height of the menu
	minHeight: 1, //min height of the menu; keep at least 1px for IE
	
	bodyClick : function() {
		if (this.isOpening) {
			this.isOpening = null;
			return;
		}
		if(this.lastOpened) {
			this.hide();
		}
		return false;
	},
	/*** 
	 * 
	 */
	show : function(node, titleID, attachID, title, isLoggedIn, showRevisions, areRevisions, reviseURL, isRestricted) {
		
		this.menuBubble = true;
		this.isOpening = true;
		var divFiller = 'menuFiller'; //filler div for filling the menu
		var divMenu = 'npdmenu_' + titleID; //menu generated by generateMenu()
		
		if (this.lastOpened && '_' + titleID != this.lastOpened) {
			this.hide();
		}
		else if (this.lastOpened) {
			this.hide();
			this.justClosed = true;
			return false;
		}
		this.lastOpened = '_' + titleID;
		
		var eltFiller = document.getElementById(divFiller);
		eltFiller.style.position = 'absolute';
		eltFiller.style.left = (findPosX(node))+'px';
		eltFiller.style.top = (findPosY(node) + 16) + 'px';
		
		//for IE
		eltFiller.style.display = '';		
		//first, generate the new menu
		eltFiller.appendChild(this.generateMenu(titleID, attachID, title, isLoggedIn, showRevisions, areRevisions, reviseURL, isRestricted));
		eltFiller.style.display = 'block';
		
		var dimensions = Element.getDimensions(dojo.byId(divMenu));
		var linkDimensions = Element.getDimensions(node);
		var position = Position.cumulativeOffset(eltFiller);
		if (typeof(winX) != 'null' && typeof(winY) != 'null') {
			var pageDimensions = Position.cumulativeOffset(dojo.byId('bodyHeight'));
			var pageHeight = pageDimensions[1];
			var extendsRight = (position[0] + dimensions.width) > (winX - 36);
			var extendsBottom = (position[1] + dimensions.height) > pageHeight;
			var horizOffset = position[0] - dimensions.width + linkDimensions.width + 5;
			if (extendsRight) {
				if (typeof(offsetX) == 'undefined') offsetX = 0;
				eltFiller.style.left = horizOffset+'px';
			}
			if (extendsBottom) {
				var vertOffset = position[1] - ((position[1] + dimensions.height) - pageHeight);
				eltFiller.style.top = vertOffset + 'px';
				horizOffset = position[0] + linkDimensions.width;
				eltFiller.style.left = horizOffset+'px';
			}
		}
		menuLinkClick(divMenu, dimensions.width);
		return false;
	},
	hide: function () {
		if (this.lastOpened) {
			var eltMenu = 'npdmenu' + this.lastOpened;	
			var elt = document.getElementById(eltMenu);
			elt.parentNode.removeChild(elt);
			menuLinkClick(eltMenu);	
		}
		this.lastOpened = null;
	},
	
	generateMenu : function (titleID, attachID, url, isLoggedIn, showRevisions, areRevisions, reviseURL, isRestricted) {
		function addMenuItem(icon, text, href, onclick, cssClass, stat) {
			var item = document.createElement('li');
			var a = document.createElement('a');
			
			a.href = href;
			a.setAttribute('stat', stat);
			a.className = 'mlink'+(cssClass && cssClass != '' ? ' '+cssClass: '');
			a.appendChild(iconify(icon+(cssClass && cssClass != '' ? '-'+cssClass: '')));
						
			var span = document.createElement('span');
			span.innerHTML = text;
			span.className = 'text';			
			a.appendChild(span);
			
			if (onclick && isLoggedIn)
			  a.onclick = onclick;
			item.appendChild(a);
			menuList.appendChild(item);
		};
		var divid = 'npdmenu_' + titleID;

		var divMain = document.createElement('div');
		divMain.onclick = function () {
			menuBubble = true;	
		};
		divMain.className = 'dmenu';

		var divWrap = document.createElement('div');
		divWrap.id = divid;
		divWrap.className = 'dmenu-wrap';

		var divTop = document.createElement('div');
		divTop.className = 'dmenu-top';

		var divBottom = document.createElement('div');
		divBottom.className = 'dmenu-bottom';

		var divBody = document.createElement('div');
		divBody.className = 'dmenu-body';

		var menuList = document.createElement('ul');
		
		if (isLoggedIn) {
			addMenuItem('attachedit', 'Edit description', '#', function () { 
				if (isRestricted) {
					return doPopupViewRestrict(_page_ID);
				}
				else {
					return doPopupEditAttach(attachID);
				}
			}, false, 107/*MKS_STAT_FILE_DESC*/);
			addMenuItem('attachmove', 'Move', '#', function () { 
				if (isRestricted) {
					return doPopupViewRestrict(_page_ID);
				}
				else {
					return doPopupMoveAttach(_page_ID, attachID);	
				}
			}, false, 108/*MKS_STAT_FILE_MOVE*/);
			addMenuItem('attachdel', 'Delete', url+'&oldid='+attachID+'&action=remove', function() {
				if (isRestricted) {
					return doPopupViewRestrict(_page_ID);
				}
				else {
					return confirm(_lang_removeconfirm);
				}
			}, false, 109/*MKS_STAT_FILE_DELETE*/);
		}
		else {
			addMenuItem('attachedit', 'Edit description', '#', function () { return false; }, 'disabled');
			addMenuItem('attachmove', 'Move', '#', function () { return false; }, 'disabled');
			addMenuItem('attachdel', 'Delete', '#', function() { return false; }, 'disabled');
		}
		if (showRevisions) {
			if (areRevisions) {
				addMenuItem('attachhist', _lang_galleryhist, reviseURL, false, false, 110/*MKS_STAT_FILE_HISTORY*/);
			}
			else {
				addMenuItem('attachhist', _lang_galleryhist, '#', function () { return false;}, 'disabled');
			}
		}
		divBody.appendChild(menuList);

		divWrap.appendChild(divTop);
		divWrap.appendChild(divBody);
		divWrap.appendChild(divBottom);

		divMain.appendChild(divWrap);
		
		return divMain;
	}
};

function setColor(titleID, color) {
	if (color == 'cancel') color = '';
	var elt = document.getElementById('container_' + titleID);
	if (elt) {
		if (!inCSSClass(elt, 'container-current')) {
			elt.className = 'container';
			addCSSClass(elt, color);
			elt.onmouseover = function () {
				NavPane.showBorder(this, color != '' ? ' '+color: '');
			}
			elt.onmouseout = function() {
				NavPane.hideBorder(this, color != '' ? ' '+color: '');
			}
		}
	}
	x_wfStoreHighlights(titleID, color, cb_blank);
};

var NavPane = { 
	lastOpened: null, 
	showBorder : function (elt, hilite) {
		if (inCSSClass(elt, 'force')) {
			return;
		}
		elt.className = hilite != '' ? 'container-hover'+hilite: 'container-hover default';
	}, 
	hideBorder : function (elt, hilite) {
		if (inCSSClass(elt, 'force')) {
			return;
		}
		elt.className = 'container'+hilite;
	},
	boxClick : function (elt) {
		if (NavMenu.menuBubble && (NavMenu.justClosed || NavMenu.lastOpened)) {
			NavMenu.justClosed = null;
			NavMenu.menuBubble = null;
			return;
		}
		var tags = elt.getElementsByTagName('div');
		for (var i = 0; i<tags.length;  i++) {
			if (tags[i].className == 'innerPadding') {
				document.location = tags[i].childNodes[0].href;
			}
		}
	},
	itemClick : function() {
		if (NavMenu.openMenu) return;
	},
	onHover : function (_titleID) {	
		var elt = document.getElementById('expNode' + _titleID);
		if (!elt) return;
		elt.style.visibility = 'visible';
		if (this.lastOpened && this.lastOpened != _titleID) {
			this.onUnhover(this.lastOpened);
			this.lastOpened = null;	
		}
		this.lastOpened = _titleID;
		return true;
	}, 
	
	onUnhover : function (_titleID) {
		if (NavMenu.lastOpened && NavMenu.lastOpened == _titleID) {
			return;
		}
		var elt = document.getElementById('expNode'+_titleID);
		if (!elt) return;
		elt.style.visibility = 'hidden';
		return true;
	}
};


var EditorMenu = { 
	lastOpened : null, //the last opened menu id
	isOpening : null,
	openMenu : false,
	justClosed : false,
	maxHeight: 132, //max height of the menu
	minHeight: 1, //min height of the menu; keep at least 1px for IE
	
	bodyClick : function() {
		if (this.isOpening) {
			this.isOpening = null;
			return;
		}
		if(this.lastOpened) {
			this.hide();
		}
		return false;
	},
	
	bodyClickPtr : function() { EditorMenu.bodyClick(); },

	show : function(menuType) {
		var node;
		var titleID;
		
		switch (menuType) {
			case 'font':
				node = document.getElementById('ebi_Font');
				titleID = 1;
				break;
			case 'fontsize':
				node = document.getElementById('ebi_FontSize');
				titleID = 2;
				break;
			case 'align':
				node = document.getElementById('ebi_Align');
				titleID = 3;
				break;
			case 'fontcolor':
				node = document.getElementById('ebi_FontColor');
				titleID = 4;
				break;
			case 'backcolor':
				node = document.getElementById('ebi_BackgroundColor');
				titleID = 5;
				break;
		}

		this.menuBubble = true;
		this.isOpening = true;
		var divFiller = 'menuFiller'; //filler div for filling the menu
		var divMenu = 'npdmenu_' + titleID; //menu generated by generateMenu()
		
		if (this.lastOpened && '_' + titleID != this.lastOpened) {
			this.hide();
		}
		else if (this.lastOpened) {
			this.hide();
			this.justClosed = true;
			return false;
		}
		this.lastOpened = '_' + titleID;

		var eltFiller = document.getElementById(divFiller);
		eltFiller.style.position = 'absolute';
		xOffset = 0;
		yOffset = 22;
		eltFiller.style.left = (findPosX(node) + xOffset) + 'px';
		eltFiller.style.top = (findPosY(node) + yOffset) + 'px';

		//for IE
		eltFiller.style.display = '';		
		//first, generate the new menu
		eltFiller.appendChild(this.generateMenu(titleID));
		eltFiller.style.display = 'block';

		HTMLArea._addEvent(document, "mousedown", EditorMenu.bodyClickPtr );
		HTMLArea._addEvent(cur_editor._doc, "mousedown", EditorMenu.bodyClickPtr );

		menuLinkClick(divMenu);
		return false;
	},
	
	hide: function () {
		if (this.lastOpened) {
			var eltMenu = 'npdmenu' + this.lastOpened;	
			var elt = document.getElementById(eltMenu);
			elt.parentNode.removeChild(elt);
			menuLinkClick(eltMenu);

			HTMLArea._removeEvent(document, "mousedown", EditorMenu.bodyClickPtr );
			HTMLArea._removeEvent(cur_editor._doc, "mousedown", EditorMenu.bodyClickPtr );
		}
		this.lastOpened = null;
	},
	
	generateMenu : function (titleID) {
		var divid = 'npdmenu_' + titleID;

		var divMain = document.createElement('div');
		divMain.onclick = function () {
			menuBubble = true;	
		};
		divMain.className = 'dmenu';

		var divWrap = document.createElement('div');
		divWrap.id = divid;
		divWrap.className = 'dmenu-wrap';

		var divTop = document.createElement('div');
		divTop.className = 'dmenu-top';

		var divBottom = document.createElement('div');
		divBottom.className = 'dmenu-bottom';

		var divBody = document.createElement('div');
		divBody.className = 'dmenu-body';
		
		var menuList;
		switch (titleID) {
			case 1:
				menuList = this.generateFontMenu();
				break;
			case 2:
				menuList = this.generateFontSizeMenu();
				break;
			case 3:
				menuList = this.generateAlignMenu();
				break;
			case 4:
				menuList = this.generateFontColorMenu();
				break;
			case 5:
				menuList = this.generateBackColorMenu();
				break;
		}

		divBody.appendChild(menuList);

		divWrap.appendChild(divTop);
		divWrap.appendChild(divBody);
		divWrap.appendChild(divBottom);

		divMain.appendChild(divWrap);
		
		return divMain;
	},
	
	generateFontMenu : function () {
		var menuList = document.createElement('ul');
		
		function addFontMenuItem(fontLabel, fontHTML) {
			var item = document.createElement('li');
			var a = document.createElement('a');

			a.className = 'mlink';
			a.href = '#';
			a.onclick = function() { cur_editor.dropdownCommand('fontname', fontHTML); return false; };

			var span = document.createElement('span');
			span.innerHTML = fontLabel;
			span.style.fontFamily = fontHTML;
			span.style.fontSize = '16px';
			a.appendChild(span);

			item.appendChild(a);
			menuList.appendChild(item);
		};
		
		addFontMenuItem("Courier New", 'courier new,courier,monospace');
		addFontMenuItem("Times New Roman", 'times new roman,georgia,times,serif');
		addFontMenuItem("Verdana", 'verdana,arial,helvetica,sans-serif');
		return menuList;
	},

	generateFontSizeMenu : function () {
		var menuList = document.createElement('ul');

		function addFontSizeMenuItem(sizeName, relSize) {
			var item = document.createElement('li');
			var a = document.createElement('a');
			
			a.className = 'mlink';
			a.href = '#';
			a.onclick = function() { cur_editor.dropdownCommand('fontsize', relSize); return false; };
			
			var span = document.createElement('span');
			span.innerHTML = sizeName;
			a.appendChild(span);
			
			item.appendChild(a);
			menuList.appendChild(item);
		};
		
		addFontSizeMenuItem('8 pt', '-2');
		addFontSizeMenuItem('10 pt (normal)', '0');
		addFontSizeMenuItem('14 pt', '+2');
		addFontSizeMenuItem('18 pt', '+3');
		return menuList;
	},
	
	generateAlignMenu : function () {
		var menuList = document.createElement('ul');
		
		function addAlignMenuItem(label, icon, command) {
			var item = document.createElement('li');
			var a = document.createElement('a');
			
			a.className = 'mlink';
			a.href = '#';
			a.onclick = function() { cur_editor.dropdownCommand(command, null); return false; };
			
			a.appendChild(iconify(icon));
			var span = document.createElement('span');
			span.innerHTML = label;
			span.className = 'text';
			a.appendChild(span);
			
			item.appendChild(a);
			menuList.appendChild(item);
		};

		// todo tomk: use the same list as in the editor
		addAlignMenuItem('Left justify', 'justifyleft', 'justifyleft');
		addAlignMenuItem('Center', 'justifycenter', 'justifycenter');
		addAlignMenuItem('Right justify', 'justifyright', 'justifyright');
		addAlignMenuItem('Full justify', 'justifyfull', 'justifyfull');
		return menuList;
	},
	
	generateFontColorMenu : function () {
		var menuList = document.createElement('ul');
		
		function addFontColorMenuItem(label, color) {
			var item = document.createElement('li');
			var a = document.createElement('a');

			a.className = 'mlink';
			a.href = '#';
			a.onclick = function() { cur_editor.dropdownCommand('forecolor', color); return false; };

			var span = document.createElement('span');
			span.innerHTML = label;
			if (color != '#FFFFFF') {
				span.style.color = color;
				span.style.fontWeight = 'bold';
			}
			a.appendChild(span);

			item.appendChild(a);
			menuList.appendChild(item);
		};

		addFontColorMenuItem('Black', '#000000');
		addFontColorMenuItem('Gray', '#999999');
		addFontColorMenuItem('Green', '#598527');
		addFontColorMenuItem('Blue', '#004A80');
		addFontColorMenuItem('Red', '#9E0B0E');
		addFontColorMenuItem('Purple', '#8D258A');
		addFontColorMenuItem('Yellow', '#E6DA00');
		addFontColorMenuItem('Brown', '#736357');
		return menuList;
	},
	
	generateBackColorMenu : function () {
		var menuList = document.createElement('ul');
		
		function addBackColorMenuItem(label, color) {
			var item = document.createElement('li');
			var a = document.createElement('a');
			
			a.className = 'mlink';
			a.href = '#';
			a.onclick = function() { cur_editor.dropdownCommand('backcolor', color); return false; };
			
			var span = document.createElement('span');
			span.innerHTML = '&nbsp;&nbsp;' + label + '&nbsp;&nbsp;';
			span.style.backgroundColor = color;
			a.appendChild(span);
			
			item.appendChild(a);
			menuList.appendChild(item);
		};

		addBackColorMenuItem('White', '#FFFFFF');
		addBackColorMenuItem('Gray', '#EAEAEA');
		addBackColorMenuItem('Green', '#DDF0D3');
		addBackColorMenuItem('Blue', '#C7ECF5');
		addBackColorMenuItem('Red', '#FCE2DB');
		addBackColorMenuItem('Purple', '#D5CAE7');
		addBackColorMenuItem('Yellow', '#FFF7D3');
		addBackColorMenuItem('Brown', '#E5D5C5');
		return menuList;
	}
};

/*
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for more info.
 */

/*
 * Configurable variables. You may need to tweak these to be compatible with
 * the server-side, but the defaults work in most cases.
 */
var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

/*
 * These are the functions you'll usually want to call
 * They take string arguments and return either hex or base-64 encoded strings
 */
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }

/*
 * Calculate the MD5 of an array of little-endian words, and a bit length
 */
function core_md5(x, len)
{
  /* append padding */
  x[len >> 5] |= 0x80 << ((len) % 32);
  x[(((len + 64) >>> 9) << 4) + 14] = len;

  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;

  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;

    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);

    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

    a = safe_add(a, olda);
    b = safe_add(b, oldb);
    c = safe_add(c, oldc);
    d = safe_add(d, oldd);
  }
  return Array(a, b, c, d);

}

/*
 * These functions implement the four basic operations the algorithm uses.
 */
function md5_cmn(q, a, b, x, s, t)
{
  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}

/*
 * Calculate the HMAC-MD5, of a key and some data
 */
function core_hmac_md5(key, data)
{
  var bkey = str2binl(key);
  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);

  var ipad = Array(16), opad = Array(16);
  for(var i = 0; i < 16; i++)
  {
    ipad[i] = bkey[i] ^ 0x36363636;
    opad[i] = bkey[i] ^ 0x5C5C5C5C;
  }

  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
  return core_md5(opad.concat(hash), 512 + 128);
}

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
function safe_add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}

/*
 * Bitwise rotate a 32-bit number to the left.
 */
function bit_rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

/*
 * Convert a string to an array of little-endian words
 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
 */
function str2binl(str)
{
  var bin = Array();
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < str.length * chrsz; i += chrsz)
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
  return bin;
}

/*
 * Convert an array of little-endian words to a string
 */
function binl2str(bin)
{
  var str = "";
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < bin.length * 32; i += chrsz)
    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
  return str;
}

/*
 * Convert an array of little-endian words to a hex string.
 */
function binl2hex(binarray)
{
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i++)
  {
    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
  }
  return str;
}

/*
 * Convert an array of little-endian words to a base-64 string
 */
function binl2b64(binarray)
{
  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i += 3)
  {
    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
    for(var j = 0; j < 4; j++)
    {
      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
    }
  }
  return str;
}

/*
 * MindTouch DekiWiki - a commercial grade open source wiki
 *  derived from MediaWiki (www.mediawiki.org)
 * Copyright (C) 2006 MindTouch, Inc.
 * www.mindtouch.com  oss@mindtouch.com
 *
 * For community documentation and downloads visit www.opengarden.org;
 *  please review the licensing section.
 *
 * 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.
 * http://www.gnu.org/copyleft/gpl.html
 */

var Print = { 
	open : function(href, menu) {
		window.open(href, 'popupwindow', 'width='+(winX - 100)+',height='+winY+',scrollbars,resizable' + (menu ? ',menubar=yes' : ''));
		return false;
	}, 
	doPrint : function () {
		parent.topic.focus();
		parent.topic.print();
		// the first time you print in firefox (or mozilla), immediately executing parent.close() will 
		// result in the page just closing with no print; oddly, if you open the print dialogue again, 
		// the document will print then close the window correctly
		// setting a timeout on the close allows the browser to popup the "print" dialogue before parent.close()
		window.setTimeout("Print.doClose()", 2000);
	},
	doClose : function () {
		parent.close();	
	},
	createEndnotes : function () {
		var elt = document.getElementById('topic');
		var endnotes = '';
		var j = 0;
		var links = elt.getElementsByTagName('a');
		for (i = 0; i < links.length; i++ ) {
			if (links[i].getAttribute('href')) {
				j++;
				var sup = document.createElement('sup');
				sup.className = 'endnotes';
				sup.innerHTML = j;
				links[i].appendChild(sup);
				endnotes += '<sup>'+(j)+'</sup> '+links[i].getAttribute('href')+'<br/>';
			}
		}	
		var div = document.createElement('div');
		div.setAttribute('id', 'endnotes');
		div.setAttribute('class', 'print-toc');
		elt.appendChild(div);
		div.innerHTML = '<h5>Endnotes</h5><div><small>'+endnotes+'</small></div>';
	},
	showEndnotes : function (displayType) {
		var endnotes = parent.topic.document.getElementsByTagName('sup');
		for (i = 0; i < endnotes.length; i++ ) {
			if (endnotes[i].className == 'endnotes') {
				endnotes[i].style.display = displayType == 'show' ? 'inline': 'none';
			}	
		}
		var endnotesBody = parent.topic.document.getElementById('endnotes');
		if (endnotesBody) {
			endnotesBody.style.display = displayType == 'show' ? 'block' : 'none';
		}
	}, 
	onBodyLoad : function () {		
	    Print.createEndnotes();	    
	    if (readCookie('printlinks') == 0) {
	   	 	Print.showEndnotes('none');
		}
	    if (readCookie('printtoc') == 0) {
		   document.getElementById('content-toc').style.display = 'none';
	    }
	    if (readCookie('printfooter') == 0) {
		    document.getElementById('printfooter').style.display = 'none';
	    }	
	}, 
	options : function () {	
		var frameset = parent.topic;
		var printtoc = document.getElementById('print-toc');
		var toc = frameset.document.getElementById('content-toc');
		var printfooter = document.getElementById('print-footer');
		var footer = frameset.document.getElementById('printfooter');
		var printlinks = document.getElementById('print-links');
		
		createCookie('printtoc', (printtoc.checked) ? 1: 0, 365);
		createCookie('printfooter', (printfooter.checked) ? 1: 0, 365);
		createCookie('printlinks', (printlinks.checked) ? 1: 0, 365);
		
		if (printtoc && toc)
			toc.style.display = (printtoc.checked) ? 'block': 'none';
		if (printfooter && footer)
			footer.style.display = (printfooter.checked) ? 'block': 'none';
		if (printlinks) {
			if (printlinks.checked) {
				Print.showEndnotes('show');
			}	
			else {
				Print.showEndnotes('hide');
			}
		}	
	}
};

function saveToPDF (page) {
	var tm = document.getElementById ('tmargin');
	var rm = document.getElementById ('rmargin');
	var bm = document.getElementById ('bmargin');
	var lm = document.getElementById ('lmargin');
	var ls = document.getElementById ('landscape');

	var args = "&action=export&type=pdf";
	
	if (ls.checked) 
		args += "&landscape=true"; 
	
	if (tm.value != null && tm.value != "")
		args += "&tm=" + tm.value; 
	if (rm.value != null && rm.value != "")
		args += "&rm=" + rm.value; 
	if (bm.value != null && bm.value != "")
		args += "&bm=" + bm.value; 
	if (lm.value != null && lm.value != "")
		args += "&lm=" + lm.value; 

	parent.topic.location = page + '&action=export&type=pdf' + args;
}

prefsShow = function (divid) {
	var arrow = document.getElementById('prefs-'+divid+'_button');
	var content = document.getElementById('prefs-'+divid+'_content');
	
	if (content.style.display == 'none') {
		content.style.display = 'block';
		var atype = 'show';
	}
	else {
		content.style.display = 'none';
		var atype = 'hide';	
	}
	arrow.className = (arrow.className == 'buttonify show') ? 'buttonify hide': 'buttonify show';
	x_wfStorePrefsStatus(divid, atype, cb_blank);
};

prefsInfo = function (divid, subdivid, type) {
	if (subdiv = document.getElementById(divid+'-'+subdivid)) {
		var div = document.getElementById(divid+'-msg');
		if (type == 'show') {
			div.style.display = 'block';
			subdiv.style.display = 'block';	
		}
		else {
			div.style.display = 'none';
			subdiv.style.display = 'none';	
		}
	}
};
/*
 * MindTouch DekiWiki - a commercial grade open source wiki
 *  derived from MediaWiki (www.mediawiki.org)
 * Copyright (C) 2006 MindTouch, Inc.
 * www.mindtouch.com  oss@mindtouch.com
 *
 * For community documentation and downloads visit www.opengarden.org;
 *  please review the licensing section.
 *
 * 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.
 * http://www.gnu.org/copyleft/gpl.html
 */

var ttTimeout = null;
var _ttwidth = 300; //width of the topic tip (set in CSS)
var curTT = null;

ttOn = function(obj, lyr) {
	if (ttTimeout)
		clearTimeout(ttTimeout);
	var dimensions = Element.getDimensions(obj);
	ttTimeout = window.setTimeout("ttDisplay('"+lyr+"', "+findPosY(obj)+", "+findPosX(obj)+", "+dimensions.height+", "+dimensions.width+")", 400);
};

ttDisplay = function(lyr, vertOffset, horizOffset, linkHeight, linkWidth) {
	var tt = document.getElementById(lyr);
	
	var pageOffset = 0;
	if (!tt) return false;
	if (ttTimeout != null)	window.clearTimeout(ttTimeout);
	ttTimeout = null;
	curTT = tt;
	
	var dimensions = Element.getDimensions(tt);
	var ttWidth = dimensions.width;
	var ttHeight = dimensions.height;
	
	//do horizontal flipping
	if (typeof(winX) != 'object' && (horizOffset + ttWidth) > winX) {
		horizOffset = horizOffset - ttWidth;
	} 	
	pageOffset = getPageYOffset();
	
	//do vertical flipping
	var vertOffset = ((vertOffset + ttHeight) > (pageOffset + winY)) ? vertOffset - ttHeight : vertOffset + linkHeight;
	
	tt.width = dimensions.width + 'px';
	tt.style.position = 'absolute';
	tt.style.top = vertOffset + 'px';
	tt.style.left = horizOffset + 'px';
	tt.style.display = 'block';
	
};

function clearTT() {
    if (ttTimeout)
        clearTimeout(ttTimeout);
    ttTimeout = null;
    if (curTT) {
        curTT.style.display = 'none';
    }
    curTT = null;
};

ttOff = function(lyr) {
	if (ttTimeout)
		clearTimeout(ttTimeout);
	ttTimeout = null;
	if (tt = document.getElementById(lyr)) {
	    if (curTT == tt)
	       curTT = null;
		tt.style.display = 'none';
	}
};

var imageTT = null;
var imageTTDont = false;

function imageOptions_cb(content) {
    if (content == "")
        return;
    imageOption_hide();
    if (imageTTDont)
        return;
    // $at_id."\n".$timestamp."\n".$file->at_user_text."\n".$file->at_name.".".$file->at_extension."\n".$file->at_filesize
    var fields = content.split("\n");
    var at_id = fields[0];
    var at_timestamp = fields[1];
    var at_user_text = fields[2];
    var at_name = fields[3];
    var at_filesize = fields[4];
    var imageEl = document.getElementById("imgSrc" + at_id);

    imageTT = document.createElement('div');
	imageTT.style.display = 'block';
	imageTT.style.position = 'absolute';
	var top = findPosY(imageEl) + imageEl.offsetHeight;
	var left = findPosX(imageEl) - 27;
	imageTT.style.top = top + 'px';
	imageTT.style.zIndex = 999;
	imageTT.style.left = left + 'px';
	imageTT.innerHTML = "<div class='ttshadow'><div class='tt_top'></div><div class='tt_content'><div><table><tbody>"+
	   "<tr><td><strong>Name:</strong></td><td>"+at_name+"</td></tr>"+
	   "<tr><td><strong>Size:</strong></td><td>"+at_filesize+"</td></tr>"+
	   "<tr><td><strong>Date:</strong></td><td>"+at_timestamp+"</td></tr>"+
	   "<tr><td><strong>Added by:</strong></td><td>"+at_user_text+"</td></tr>"+
	   "</tbody></table></div></div><div class='tt_bottom'></div></div>";
    imageEl.parentNode.appendChild(imageTT);
}

function imageOption_hide() {
    if (imageTT != null) {
        imageTT.parentNode.removeChild(imageTT);
        imageTT = null;
    }
}

function imageOptions(action, at_id) {
    if (action == 'show') {
        imageTTDont = false;
        x_wfGetImageDescription(at_id, imageOptions_cb)
    } else {
        imageTTDont = true;
        imageOption_hide();
    }
}

// Browser detection
var nav = navigator.userAgent.toLowerCase();
var ie6=0; ie5=0; moz5=0; moz0=0; opera=0; needConfirm=0; confirmFlag = 1;
if (nav.indexOf("win") != -1) {
	var pos = nav.indexOf("msie");
	var v = nav.charAt(pos + 5);
	if (pos != -1) {
		if (v >= 6) {
			ie6 = 1;
			ie5 = 1;

		}

		else if (v >= 5)
			ie5 = 1;
	}
}
if (nav.indexOf("compatible") == -1) {
	if (nav.charAt(8) >= 5 && nav.indexOf("7.02") == -1) {
		moz5 = 1;
		moz0 = 1;
	}
}
if (nav.indexOf("opera") != -1) opera=1;
/**
 * COMMON DHTML FUNCTIONS
 * These are handy functions I use all the time.
 *
 * By Seth Banks (webmaster at subimage dot com)
 * http://www.subimage.com/
 *
 * Up to date code can be found at http://www.subimage.com/dhtml/
 *
 * This code is free for you to use anywhere, just keep this comment block.
 */

/**
 * X-browser event handler attachment and detachment
 *
 * @argument obj - the object to attach event to
 * @argument evType - name of the event - DONT ADD "on", pass only "mouseover", etc
 * @argument fn - function to call
 */
function addEvent(obj, evType, fn){
 if (obj.addEventListener){
    obj.addEventListener(evType, fn, true);
    return true;
 } else if (obj.attachEvent){
    var r = obj.attachEvent("on"+evType, fn);
    return r;
 } else {
    return false;
 }
}
function removeEvent(obj, evType, fn, useCapture){
  if (obj.removeEventListener){
    obj.removeEventListener(evType, fn, useCapture);
    return true;
  } else if (obj.detachEvent){
    var r = obj.detachEvent("on"+evType, fn);
    return r;
  } else {
    alert("Handler could not be removed");
  }
}

/**
 * Code below taken from - http://www.evolt.org/article/document_body_doctype_switching_and_more/17/30655/
 *
 * Modified 4/22/04 to work with Opera/Moz (by webmaster at subimage dot com)
 *
 * Gets the full width/height because it's different for most browsers.
 */
function getViewportHeight() {
	if (window.innerHeight!=window.undefined) return window.innerHeight;
	if (document.compatMode=='CSS1Compat') return document.documentElement.clientHeight;
	if (document.body) return document.body.clientHeight; 
	return window.undefined; 
}
function getViewportWidth() {
	if (window.innerWidth!=window.undefined) return window.innerWidth; 
	if (document.compatMode=='CSS1Compat') return document.documentElement.clientWidth; 
	if (document.body) return document.body.clientWidth; 
	return window.undefined; 
}
/*
 * MindTouch DekiWiki - a commercial grade open source wiki
 *  derived from MediaWiki (www.mediawiki.org)
 * Copyright (C) 2006 MindTouch, Inc.
 * www.mindtouch.com  oss@mindtouch.com
 *
 * For community documentation and downloads visit www.opengarden.org;
 *  please review the licensing section.
 *
 * 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.
 * http://www.gnu.org/copyleft/gpl.html
 */

/**
 * POPUP WINDOW CODE v1.1
 * Used for displaying DHTML only popups instead of using buggy modal windows.
 *
 * By Seth Banks (webmaster at subimage dot com)
 * http://www.subimage.com/
 *
 * Contributions by Eric Angel (tab index code) and Scott (hiding/showing selects for IE users)
 *
 * Up to date code can be found at http://www.subimage.com/dhtml/subModal
 *
 * This code is free for you to use anywhere, just keep this comment block.
 */

// Popup code
var gPopupMask = null;
var gPopupContainer = null;
var gPopFrame = null;
var gPopupDoc = null;
var gReturnFunc;
var gPopupIsShown = false;

var gHideSelects = false;


var gTabIndexes = new Array();
// Pre-defined list of tags we want to disable/enable tabbing into
var gTabbableTags = new Array("A","BUTTON","TEXTAREA","INPUT","IFRAME");	

// If using Mozilla or Firefox, use Tab-key trap.
if (!document.all) {
	document.onkeypress = keyDownHandler;
}

/**
 * Initializes popup code on load.	
 */
function initPopUp() {
	gPopupMask = document.getElementById("popupMask");
	gPopupContainer = document.getElementById("popupContainer");
	gPopFrame = document.getElementById("popupFrame");
	
	// check to see if this is IE version 6 or lower. hide select boxes if so
	// maybe they'll fix this in version 7?
	var brsVersion = parseInt(window.navigator.appVersion.charAt(0), 10);
	if (brsVersion <= 6 && window.navigator.userAgent.indexOf("MSIE") > -1) {
		gHideSelects = true;
	}
};
//addEvent(window, "load", initPopUp);

 /**
	* @argument width - int in pixels
	* @argument height - int in pixels
	* @argument url - url to display
	* @argument returnFunc - function to call when returning true from the window.
	*/

function showPopWin(url, width, height, returnFunc) {
	// >MT: tomk: force some padding to the right of the content for non-IE
	if (!HTMLArea.is_ie)
		width += 10;
	// <MT

	if (!gPopupMask) initPopUp();
	if (!gPopupMask) {
		return;
	}
	gPopupIsShown = true;
//	disableTabIndexes();
	gPopupMask.style.display = "block";
	gPopupContainer.style.display = "block";
	// calculate where to place the window on screen
	centerPopWin(width, height);

	var titleBarHeight = parseInt(document.getElementById("popupTitleBar").offsetHeight, 10);
	
	gPopupContainer.style.width = width + "px";
	gPopupContainer.style.height = (height+titleBarHeight) + "px";
	// need to set the width of the iframe to the title bar width because of the dropshadow
	// some oddness was occuring and causing the frame to poke outside the border in IE6

	// >MT: tomk: force some padding to the right of the content for non-IE
	frameWidth = parseInt(document.getElementById("popupTitleBar").offsetWidth, 10) - 12;
	if (!HTMLArea.is_ie)
		frameWidth -= 10;
	gPopFrame.style.width = frameWidth + "px";
	// <MT
	gPopFrame.style.height = (height) + "px";
	
	// set the url
	gPopFrame.src = url;

	gReturnFunc = returnFunc;
	// for IE
	if (gHideSelects)
		hideSelectBoxes();
	
  document.getElementById("popupTitle").innerHTML = "";
	window.setTimeout(function () { setPopTitle(); }, 600);
};

function setPopWinHTML(html) {
    try {
        gPopupDoc = gPopFrame.contentDocument ? gPopFrame.contentDocument : gPopFrame.contentWindow.document;
        if (!gPopupDoc) { // try later
            if (HTMLArea.is_gecko) {
                setTimeout(function() { setPopWinHTML(html) }, 50);
                return false;
            } else
                alert("ERROR: IFRAME can't be initialized.");
        }
    } catch(e) {
        setTimeout(function() { setPopWinHTML(html) }, 50);
        return false;
    }

    gPopupDoc.write(html);
    gPopupDoc.close();
    return true;
};

//
var gi = 0;
function centerPopWin(width, height) {
	if (gPopupIsShown) {
		if (width == null || isNaN(width)) {
			width = gPopupContainer.offsetWidth;
		}
		if (height == null) {
			height = gPopupContainer.offsetHeight;
		}
		
		var fullHeight = getViewportHeight();
		var fullWidth = getViewportWidth();
		
		var theBody = document.documentElement;
		if (!theBody.scrollTop && document.body)
			theBody = document.body;
		
		var scTop = parseInt(theBody.scrollTop,10);
		var scLeft = parseInt(theBody.scrollLeft,10);
		
		gPopupMask.style.height = fullHeight + "px";
		gPopupMask.style.width = fullWidth + "px";
		gPopupMask.style.top = scTop + "px";
		gPopupMask.style.left = scLeft + "px";
		
		window.status = gPopupMask.style.top + " " + gPopupMask.style.left + " " + gi++;
		
		var titleBarHeight = parseInt(document.getElementById("popupTitleBar").offsetHeight, 10);
		
		gPopupContainer.style.top = (scTop + ((fullHeight - (height+titleBarHeight)) / 2)) + "px";
		gPopupContainer.style.left =  (scLeft + ((fullWidth - width) / 2)) + "px";
		//alert(fullWidth + " " + width + " " + gPopupContainer.style.left);
	}
}
addEvent(window, "resize", centerPopWin);
//addEvent(window, "scroll", centerPopWin);
window.onscroll = centerPopWin;

/**
 * @argument callReturnFunc - bool - determines if we call the return function specified
 * @argument returnVal - anything - return value 
 */
function hidePopWin(callReturnFunc) {
	gPopupIsShown = false;
	restoreTabIndexes();
	if (!gPopupMask)
		return;
    gPopupMask.style.display = "none";
	gPopupContainer.style.display = "none";
	document.getElementById("popupTitle").innerHTML = "";
	if (callReturnFunc && gReturnFunc != null)
		gReturnFunc(gPopFrame.returnVal);
	gPopFrame.src = '/editor/popups/loading.html';
	// display all select boxes
	if (gHideSelects)
		displaySelectBoxes();
};

/**
 * Sets the popup title based on the title of the html document it contains.
 * Uses a timeout to keep checking until the title is valid.
 */
function setPopTitle() {
    try {
        gPopupDoc = gPopFrame.contentDocument ? gPopFrame.contentDocument : gPopFrame.contentWindow.document;
        if (gPopupDoc && gPopupDoc.title)
            document.getElementById("popupTitle").innerHTML = gPopupDoc.title;
        else
            window.setTimeout(function() { setPopTitle(); }, 100);
    } catch (e) {
        window.setTimeout(function() { setPopTitle(); }, 100);
    }
};

// Tab key trap. iff popup is shown and key was [TAB], suppress it.
// @argument e - event - keyboard event that caused this function to be called.
function keyDownHandler(e) {
    if (gPopupIsShown && e.keyCode == 9)  return false;
};

// For IE.  Go through predefined tags and disable tabbing into them.
function disableTabIndexes() {
	if (document.all) {
		var i = 0;
		for (var j = 0; j < gTabbableTags.length; j++) {
			var tagElements = document.getElementsByTagName(gTabbableTags[j]);
			for (var k = 0 ; k < tagElements.length; k++) {
				gTabIndexes[i] = tagElements[k].tabIndex;
				tagElements[k].tabIndex="-1";
				i++;
			}
		}
	}
};

// For IE. Restore tab-indexes.
function restoreTabIndexes() {
	if (document.all) {
		var i = 0;
		for (var j = 0; j < gTabbableTags.length; j++) {
			var tagElements = document.getElementsByTagName(gTabbableTags[j]);
			for (var k = 0 ; k < tagElements.length; k++) {
				tagElements[k].tabIndex = gTabIndexes[i];
				tagElements[k].tabEnabled = true;
				i++;
			}
		}
	}
};

/**
* Hides all drop down form select boxes on the screen so they do not appear above the mask layer.
* IE has a problem with wanted select form tags to always be the topmost z-index or layer
*
* Thanks for the code Scott!
*/
function hideSelectBoxes() {
	for(var i = 0; i < document.forms.length; i++) {
		for(var e = 0; e < document.forms[i].length; e++){
			if(document.forms[i].elements[e].tagName == "SELECT") {
				document.forms[i].elements[e].style.visibility="hidden";
			}
		}
	}
};

/**
* Makes all drop down form select boxes on the screen visible so they do not reappear after the dialog is closed.
* IE has a problem with wanted select form tags to always be the topmost z-index or layer
*/
function displaySelectBoxes() {
	for(var i = 0; i < document.forms.length; i++) {
		for(var e = 0; e < document.forms[i].length; e++){
			if(document.forms[i].elements[e].tagName == "SELECT") {
			document.forms[i].elements[e].style.visibility="visible";
			}
		}
	}
};

/*
 * MindTouch DekiWiki - a commercial grade open source wiki
 *  derived from MediaWiki (www.mediawiki.org)
 * Copyright (C) 2006 MindTouch, Inc.
 * www.mindtouch.com  oss@mindtouch.com
 *
 * For community documentation and downloads visit www.opengarden.org;
 *  please review the licensing section.
 *
 * 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.
 * http://www.gnu.org/copyleft/gpl.html
 */

if (typeof _script_path == "undefined") _script_path = "/";
if (typeof _page_titleName == "undefined") _page_titleName = "Sandbox";
if (typeof _page_titlePath == "undefined") _page_titlePath = "/";
if (typeof _path_skin == "undefined") _path_skin = "/skin/ace";

xinha_editors = null;
xinha_init = null;
xinha_init_adv = null;
xinha_init_simple = null;
xinha_config = null;
xinha_plugins = null;
start_editor  = false;
content_editors = null;
title = null;
sectiontoedit = null;
oldcontent = null;
cur_section = null;
cur_editor = null;
did_quicksave = false;

var width = null;
var height = '';
var prevHTML = '';
var saveFlag = false;

var useMTDialogs = true;

function getWindowSize() {
  if (parseInt(navigator.appVersion)>3) {
    // Can't use HTMLArea.is_ie, not defined yet for some reason
    if (navigator.appName=="Netscape") {
      width = window.innerWidth;
      height = window.innerHeight;
    }
    if (navigator.appName.indexOf("Microsoft")!=-1) {
      width = document.documentElement.offsetWidth;
      height = document.documentElement.offsetHeight;
    }
  }
};
getWindowSize();

xinha_init = xinha_init ? xinha_init : function() {
  //hide the box
  wait = document.getElementById('formLoading');

  if (xinha_config == null) {
    xinha_config = new HTMLArea.Config();
    
    xinha_config.URIs = {
      "blank":        "popups/blank.html",
      "link":         "link.html",
      "insert_image": "insert_image.html",
      "insert_table": "insert_table.html",
      "select_color": "select_color.html",
      "forecolor":    "select_color.php?type=fg",
      "hilitecolor":  "select_color.php?type=bg",
      "mostemplates": "select_template.php",
      "moswidgets":   "/dream/widget/select/",
      "about":        "about.html"
    };
  }

  xinha_config.mozParaHandler = 'built-in'; // set to 'built-in', 'dirty' or 'best'
  xinha_config.stripBaseHref = false;
  xinha_config.baseHref = baseHref;
  xinha_config.formatblock = {
    "Normal" :    "",
    "Title":      "h1",
    "Heading 1":  "h2",
    "Heading 2":  "h3",
    "Heading 3":  "h4",
    "Heading 4":  "h5",
    "Heading 5":  "h6",
    "Normal":     "p",
    "Formatted":  "pre"
  };

  xinha_config.fontsize = {
    "&mdash; size &mdash;"  : "mixed",
    "Small":  "-2",
    "Normal": "0",
    "Big":    "+2",
    "Huge":   "+3"
  };

  xinha_config.fontname = {
    "&mdash; font &mdash;": '',
    "Courier New":      'courier new,courier,monospace',
    "Garamond":         'garamond|small-caps',
    "Impact":           'impact',
    "Times New Roman":  'times new roman,georgia,times,serif',
    "Verdana":          'verdana,arial,helvetica,sans-serif'
  };
  
  xinha_config.fontstyles = {
    "&mdash; styles &mdash;": "mixed",
    "Normal":     "normal",
    "Important":  "edimportant",
    "Highlight":  "edhighlight",
    "Subtle":     "edsubtle", 
    "Code":       "edcode",
    "Plain": "plain"
  };
  
  xinha_config.registerButton(
    "simple", "Simple", _script_path+"editor/images/ed_toggle.gif", false,
    function(editor) { switchToSimple(editor); }
  );

  xinha_config.registerButton(
    "advanced", "Advanced", _script_path+"editor/images/ed_toggle.gif", false,
    function(editor) { switchToAdvanced(editor); }
  );

  xinha_config.registerButton(
    "mostemplates", "Templates", _script_path+"editor/images/ed_template.gif", false,
    function(editor) { popupTemplates(400, 110, editor); }
  );
 
  if (_editor_dream_enabled) {
    xinha_config.registerButton(
      "moswidgets", "Widgets", _script_path+"editor/images/ed_widget.gif", false,
      function(editor) { popupWidgets(400, 110, editor); }
    );
  }
  else {
    
  }
  
  xinha_config.registerButton(
    "mksSave", _lang_tooltip_save, _path_skin+"/save_18.gif", false,
    function(editor) {
      okToLeave();
      doSave();
      document.editform.submit();
    }
  );
  
  xinha_config.registerButton(
    "mksCancel", _lang_tooltip_cancel, _path_skin+"/back_18.gif", false,
    function(editor) {
      if (!doCancelEdit(true))
        return;
      if (typeof _cancel_url != 'undefined')
        window.location = _cancel_url;
      else if (typeof _staticEditor != 'undefined' && _staticEditor)
        window.location = mt_gen.getUrlFromName(document.getElementById('wpOldTitle').value);
	  else if (document.editform)
	    document.editform.submit();
    }
  );
  
  xinha_config.registerButton(
    "mksQuicksave", _lang_tooltip_saveminor, _path_skin+"/save_18.gif", false,
    function(editor) {
      okToLeave();
      doSaveMinor();
    }
  );
  
  xinha_config.registerButton(
    "mksPreview", _lang_tooltip_preview, _path_skin+"/srch_18.gif", false,
    function(editor) {
      okToLeave();
      setHiddenSubmit('wpPreviewH');
      var html = cur_editor.getHTML();
      html = stripTitle(html);
      cur_editor.setHTML(html);
      document.getElementById('editarea').value = html;
      document.editform.submit();
    }
  );
  
  xinha_config.registerButton("mksLink", "Insert/modify link", _path_skin+"/ed_link.gif", false,
    function(editor) { cur_editor._createLinkMT(); }
  );
  
  xinha_config.registerButton("mksInsertImage", "Insert image", _path_skin+"/ed_ins_img.gif", false,
    function(editor) { cur_editor._insertImageMT(); }
  );
  
  xinha_config.registerButton("mksFont", "Font", _path_skin+"/font_18.gif", false,
    function(editor) { EditorMenu.show('font'); }
  );
  
  xinha_config.registerButton("mksSize", "Font Size", _path_skin+"/fontsize_18.gif", false,
    function(editor) { EditorMenu.show('fontsize'); }
  );
  
  xinha_config.registerButton("mksAlign", "Align", _path_skin+"/align_18.gif", false,
    function(editor) { EditorMenu.show('align'); }
  );
  
  xinha_config.registerButton("mksFontColor", "Font Color", _path_skin+"/fontcolor_18.gif", false,
    function(editor) { EditorMenu.show('fontcolor'); }
  );
  
  xinha_config.registerButton("mksBackColor", "Background Color", _path_skin+"/backcolor_18.gif", false,
    function(editor) { EditorMenu.show('backcolor'); }
  );
  
  if (typeof(_editor_styles_path) != 'undefined')
    xinha_config.pageStyleSheets = [_editor_styles_path];

  createConfigToolBar(xinha_config,advancedEditor);

  xinha_config.width = clientBrowser.isIe ? '99%': '100%'; //IE will push the whole editor down otherwise
  xinha_config.height = getEditorHeight(null) + "px";
  function doneLoading() {
    startContentEditor();
    if (wait)
      wait.className = 'show-no';
  };

  if (!createPlugins(advancedEditor, doneLoading))
    return;
  doneLoading();
};

function createPlugins(advancedEditor, callbackIfNotReady) {
  xinha_plugins = xinha_plugins ? xinha_plugins : true ? [
    'MindTouch',
    'ContextMenu',
    'FullScreen',
    'SpellChecker',
    'Stylist',
    'TableOperations',
    'EnterParagraphs' //KA - bugfix #493: hitting enter at the end of a heading line produces two new lines
  ] : [
    'MindTouch',
    'FullScreen',
    'SpellChecker',
    'Stylist'
  ];

  return HTMLArea.loadPlugins(xinha_plugins, callbackIfNotReady);
};

function getOffsetTop(item) {
  return getRecursiveProperty(item,"offsetTop");
};

function getRecursiveProperty(item,prop) {
  var ret = 0;
  while(item) {
    ret += item[prop];
    try {
      item = item.offsetParent;
    } catch (e) { item = null; }
  }
  return ret;
};

function getEditorHeight(editor) {
  getWindowSize();
  if (!editor || document.getElementById('isConflict') || cur_section != null)
    return 400;
  var offsetTop = getOffsetTop(editor._htmlArea);
  var newHeight = height - offsetTop - (HTMLArea.is_ie ? 5 : 12);
  if (newHeight < 400)
    newHeight = 400;
  return newHeight;
};

function switchToSimple(editor) {
  advancedEditor = false;
  if (typeof x_wfSaveEditor != 'undefined') x_wfSaveEditor('0', function() {});
  recreatedToolbar(editor);
};

function switchToAdvanced(editor) {
  advancedEditor = true;
  if (typeof x_wfSaveEditor != 'undefined') x_wfSaveEditor('1', function() {});
  recreatedToolbar(editor);
};

function recreatedToolbar(editor) {
  xinha_plugins = null;
  if (!createPlugins(advancedEditor, function() {recreatedToolbar(editor);}))
    return;
  editor.disableToolbar();
  var tb_cell = editor._framework.tb_cell;
  HTMLArea.removeFromParent(editor._toolBar);
  createConfigToolBar(editor.config,advancedEditor);
  editor.registerPlugins(xinha_plugins);
  for (var i in editor.plugins) {
    var plugin = editor.plugins[i].instance;
    HTMLArea.refreshPlugin(plugin);
  }
  var toolbar = editor._createToolbar();
  editor._framework.tb_cell.appendChild(toolbar);
  editor.enableToolbar();
};

function createConfigToolBar(config,adv) {
  config.toolbar =
  [
    ["mksSave","linebreak","mksCancel"],
    ["separator","undo","redo","removeformat","linebreak","mksQuicksave","htmlmode"],
    ["separator","label:Style:","formatblock","mksFont","mksSize","linebreak","bold","italic","underline","strikethrough","mksFontColor","mksBackColor"],
    ["separator","insertorderedlist","insertunorderedlist","mksAlign","linebreak","outdent","indent"],
    ["separator","mksLink","mksInsertImage","moswidgets","linebreak","inserttable","mostemplates"]
  ];
  
  if (!_editor_dream_enabled)
    config.toolbar[4].splice(3, 1);  // super-hack to remove "moswidgets" from the toolbar
  
  /*if (!adv) {
    config.toolbar =
    [
      ["mksSave","label:mksSave|"+_lang_label_save,"linebreak","mksCancel","label:mksCancel|"+_lang_label_cancel,"linebreak"],
      ["separator","formatblock"],
      ["separator","bold","italic","underline","linebreak","strikethrough"],
      ["separator","createlink","linebreak"],
      ["separator","undo","redo","mksQuicksave","removeformat","linebreak","htmlmode","advanced","mksPreview"]
    ];
  }*/
  
};

function cleanStyles(el,fn) {
  if (fn(el)) {
    HTMLArea.removeTag(el);
    return true;
  }
  var c = el.firstChild;
  while (c != null) {
    var next = c.nextSibling;
    if (c.nodeType == 1 && cleanStyles(c,fn))
      next = el.firstChild;
    c = next;
  }
  return false;
};

var convertStyleToSizeID = {
  normal      : "0",
  edimportant : 2,
  edhighlight : 3,
  edsubtle    : 4,
  edcode      : 5,
  plain       : 6
};

var convertSizeIDToStyle = [
  /*0*/ 'normal',
  /*1*/ 'xxx',
  /*2*/ 'edimportant',
  /*3*/ 'edhighlight',
  /*4*/ 'edsubtle',
  /*5*/ 'edcode',
  /*6*/ 'plain'
];

function doApplyFontStyles(editor, txt, value,isArray, tag, text) {
  if (value == "0") {
    if ((!isArray && editor.getHTMLText(HTMLArea.getOuterHTML(tag)) == editor.getHTMLText(text)) || HTMLArea.is_gecko) 
      editor.execCommand(txt, false, HTMLArea.is_ie ? "<>" : "+0");
    else if (isArray) {
      applyFontSize(editor, txt, value);
      editor.execCommand(txt, false, HTMLArea.is_ie ? "<>" : "+0");
    } else
      editor.splitOutRange(tag, editor._createRange(editor._getSelection()));
  } else
    applyFontSize(editor, txt, value);
};

function updateFontStyles(editor, value) {
  var text = editor.getSelectedHTML();
  var tags = getFontStyleTags(editor);
  if (text == "" && value == "normal") {
    editor.selectWord();
    text = editor.getSelectedHTML();
    tags = getFontSizeTags(editor);
  }
  var r = editor.getRange();
  var isArray = typeof tags.tags != "undefined";
  var root = isArray ? tags.root : tags.tag.parentNode;

  // replace font size into span tags (move away tags to make room)
  HTMLArea.replaceTagsF(root,function (el) {
    if (!/^font$/i.test(el.tagName) || el.size == "")
      return null;
    var ret = editor._doc.createElement("span");
    ret.className = '_font_size|' + el.size;
    if (tags.tag == el)
      tags.tag = ret;
    return HTMLArea.cloneNode(el,ret);
  });
  // replace font styles into font size tags (prepare for native use)
  HTMLArea.replaceTagsF(root,function (el) {
    if (!/^span$/i.test(el.tagName) || !/(edimportant|edhighlight|edsubtle|edcode|plain)/i.test(el.className))
      return null;
    
    var ret = editor._doc.createElement("font");
    ret.size = convertStyleToSizeID[el.className];
    if (tags.tag == el)
      tags.tag = ret;
    return HTMLArea.cloneNode(el,ret);
  });

  editor.setRange(r);
  doApplyFontStyles(editor,"fontsize",convertStyleToSizeID[value],isArray,tags.tag,text);
  
  // replace font size into font style tags (store result of native use into wished tags)
  HTMLArea.replaceTagsF(root,function (el) {
    if (!/^font$/i.test(el.tagName) || el.size == "")
      return null;
    var ret = editor._doc.createElement("span");
    ret.className = convertSizeIDToStyle[el.size];
    return HTMLArea.cloneNode(el,ret);
  });
  // replace span into font size tags (move back from hiding)
  HTMLArea.replaceTagsF(root,function (el) {
    if (!/^span$/i.test(el.tagName) || !/_font_size.+/i.test(el.className))
      return null;
    
    var ret = editor._doc.createElement("font");
    ret.size = el.className.substr('_font_size|'.length);
    return HTMLArea.cloneNode(el,ret);
  });
  editor.setRange(r);
  editor.updateToolbar();
};

function getFontSizeTags(editor) {
  return editor.getSelectionTagsF("font",function(el) { return el.size != ""; });
};

function getFontStyleTags(editor) {
  return editor.getSelectionTagsF("span",function(el) { return el.className != ""; });
};

function fontSizes(editor) {
  var tags = getFontSizeTags(editor);
  if (typeof tags.tags != "undefined") // 'mixed' has a false positive if the same size is applied across multiple blocks
    return tags.tags.length > 0 ? "mixed" : "0";
  return tags.tag.size;
};

function fontStyles(editor) {
  var tags = getFontStyleTags(editor);
  if (typeof tags.tags != "undefined") // 'mixed' has a false positive if the same style is applied across multiple blocks
    return tags.tags.length > 0 ? "mixed" : "normal";
  return tags.tag.className;
};

function applyFontSize(editor, txt, value) {
  editor._doc.execCommand(txt, false, HTMLArea.is_ie ? "1" : value);
  if (HTMLArea.is_ie) {
    var sel = editor._getSelection();
    var range = editor._createRange(sel);
    var rangeEl = editor.getParentElement(sel,range);
    var els = rangeEl.getElementsByTagName('font');
    if (els.length == 0)
      els = [rangeEl];
    for (var i = 0; i < els.length; ++i) {
      var el = els[i];
      if (el.size == 1)
        el.size = value;
    }
  }
};

function updateFontSizes(editor, txt, value) {
  var text = editor.getSelectedHTML();
  var tags = getFontSizeTags(editor);
  if (text == "" && value == "0") {
    editor.selectWord();
    text = editor.getSelectedHTML();
    tags = getFontSizeTags(editor);
  }
  doApplyFontStyles(editor, txt, value, typeof tags.tags != "undefined", tags.tag, text);
  editor.updateToolbar();
};

function popupWidgetForm(node, editor) {
  var widgetID = node.getAttribute('widgetID');
  if (!widgetID) {return;}
  var widget = Widget._getWidgetByID(widgetID);
  var widgetType = widget.type;

  editor._popupDialog(400, 400, "/dream/wiki-data/"+widgetType+"/form/", function(param) {
    if (!param || !param.data) {	// user must have pressed Cancel
      return false;
    }
    Widget.updateWidget(editor, param.data, param.widgetID);
    return true;
  }, {widgetID : widgetID, data: widget.data});
};

function popupWidgets(width, height, editor) {
  var sel = editor._getSelection();
  var range = editor._createRange(sel);
  if (HTMLArea.is_ie) {
    if (sel.type == "Control" && range.length >= 1) {
      var node = range.item(0);
      if (node.tagName.toLowerCase() == "iframe") {
        popupWidgetForm(node, editor);
        return;
      }
    }
  }
  editor._popupDialog(width, height, editor.config.URIs["moswidgets"], function(param) {
    if (!param || !param.widgetHtml) {	// user must have pressed Cancel
      return false;
    }
    Widget.insertWidget(editor, param.widgetHtml);
    return true;
  }, null);
}

function popupTemplates(width, height, editor) {
  var sel = editor._getSelection();
  var range = editor._createRange(sel);
  editor._popupDialog(width, height, editor.config.URIs["mostemplates"], function(param) {
    if (!param || (!param.f_template && !param.f_site)) {	// user must have pressed Cancel
      return false;
    }
    editor.focusEditor();
    var doc = editor._doc;
    var template = param.f_template;
    if (param.f_site) {
      var siteTemplate = param.f_site;
      var siteName = siteTemplate.siteName;
      var tree = siteTemplate.tree;
      function createLink(topic,name) {
        return '<a class="site" href="#" title="'+topic+'" template="Template:'+topic+'">'+name+'</a>';
      }
      function createHtml(node) {
        var itemsHtml = '<ul>';
        for (var itemKey in node) {
          if (itemKey == "__value" || itemKey == "__path") continue;
          var item = node[itemKey];
          itemsHtml += '<li>' + createLink(siteName+'/'+item.__path,item.__value) + createHtml(item) + '</li>';
        }
        return itemsHtml == '<ul>' ? "" : itemsHtml + '</ul>';
      };
      template += createHtml(tree);
    }
    editor.insertHTML(template);
    Widget.initializeEditor(editor._doc, editor);
    if (!HTMLArea.is_ie) {
      // Toggle in and out of htmlmode after inserting a template
      // This works around the FF insert unable to backspace bug
      editor.execCommand("htmlmode");
      editor.execCommand("htmlmode");
    }
    return true;
  }, null);
};

function removeFormat(editor) {
  function checkEmpty(el) {
    if (/^(a|span|b|strong|i|em|font|div)$/i.test(el.tagName) &&
        !el.firstChild)
      HTMLArea.removeFromParent(el);
  };
  function parseTree(root) {
    var tag = root.tagName.toLowerCase(), i, next;
    if (/^(a|span|b|strong|i|em|font|small|big|strike|del)$/i.test(root.tagName)) {
      HTMLArea.removeTag(root);
      return false;
    } else {
      for (i = root.firstChild; i; i = next) {
        next = i.nextSibling;
        if (i.nodeType == 1 && parseTree(i))
          checkEmpty(i);
      }
    }
    return true;
  };

  var html = editor.getSelectedHTML();
  var div = editor._doc.createElement("div");
  div.innerHTML = html;
  parseTree(div);
  if (div.innerHTML == html)
    return;
  html = div.innerHTML;
  var r = editor.getRange();
  HTMLArea.is_ie ? document.execCommand("Delete") : editor._createRange().deleteContents();
  editor.insertHTML(html);
  editor.setRange(r);
  editor.updateToolbar();
};

function getAttachmentUrl(id, aref) {
  if (typeof x_wfGetAttachmentUrl == 'undefined') return;
  x_wfGetAttachmentUrl(id, function(data) {
    if (data == '-' || data == '')
      return;
    MindTouch.setLink(aref, data);
  });
}

function startContentEditor() {
  if (!start_editor)
    return;
  
  content_editors = content_editors ? content_editors :
  [
    'editarea'
  ];
  if (document.getElementById('wpTextbox2'))
    content_editors.push('wpTextbox2');
  for (var i = 0; i < content_editors.length; ++i)
    if (!document.getElementById(content_editors[i]))
      return;
  xinha_config = xinha_config ? xinha_config : new HTMLArea.Config();
  content_editors = HTMLArea.makeEditors(content_editors, xinha_config, xinha_plugins);

  for(var i in content_editors) {
    var e = content_editors[i];
    if (i == 'editarea') cur_editor = e;
    if (typeof contextTopic != 'undefined') {
      e.contextTopic = contextTopic;
      e.contextTopicID = _page_ID;
    }
    if(document.compatMode && document.compatMode != 'BackCompat') {
      HTMLArea._addEvent(window, 'resize', function() {
        e.sizeEditor();
      });
    }
  }

  HTMLArea.startEditors(content_editors);
};

var editorStarting = false;
var wpEditTimeValue = null;
var wpSectionValue = null;

function doCheckChanges(editor) {
  if (editorStarting) {
    if (typeof clearTT == 'function') clearTT();

    if (cur_editor != editor)
      return;
    var wpEditTime = document.getElementById('wpEditTime');
    if (wpEditTime) wpEditTime.value = wpEditTimeValue;
    var wpSection = document.getElementById('wpSection');
    if (wpSection) wpSection.value = wpSectionValue;
    wpEditTimeValue = null;
    wpSectionValue = null;
    editorStarting = false;
  }
  if (!editor) 
    return false;
  if (typeof hex_md5 != 'function')
    return false;
  var cur = hex_md5(editor.getHTML());
  if (!saveFlag) {
    saveFlag = true;
    prevHTML = cur;
  }
  else if (prevHTML == cur)
    return true;
  return false;
};

function handleEdit_cb(responseContent) {
  oldcontent = sectiontoedit.innerHTML;
  var r = responseContent.indexOf('|');
  sectiontoedit.innerHTML = responseContent.substring(r+1);

  editorStarting = true;
  wpEditTimeValue = responseContent.substring(0,r);
  wpSectionValue = cur_section != null ? cur_section : '';

  cur_editor = null; content_editors = null; xinha_config = null; xinha_plugins = null;
  start_editor = true;
  new xinha_init;
};

function doSectionEdit_cb(responseContent) {
  if (typeof (sectiontoedit) != 'undefined') {
    handleEdit_cb(responseContent);
  }
};

function doLoadEditor_cb(responseContent) {
  sectiontoedit = document.getElementById("articleText");
  var title = dojo.byId('title');
  title.style.display = 'none';
  handleEdit_cb(responseContent);
};

function doCancelEdit(check) {
  if (check) {
    var display = checkForChanges();
    if (display != null) {
      if (!confirm("Are you sure you want to navigate away from the editor?\n\n" + display + "\n\nPress OK to continue, or Cancel to stay on the current editor."))
        return false;
    }
  } else {
    x_wfStatistics('', 'edit-cancel', function(data) {});
  }
  if (sectiontoedit != null) {
    sectiontoedit.innerHTML = oldcontent;
    hookEditIcons();
    sectiontoedit = null;
  }
  saveFlag = false;
  var title = dojo.byId('title');
  if (title) { //if we're editing an existing page
	  if (title.style.display == 'none') 
	  	title.style.display = 'block';
	  if (did_quicksave)
	    window.location.reload();
  }
  return true;
};

// Public entry point
function doLoadEditor() {
  var browser = new BrowserVersion();
  if (!browser.isSupported) {
	doPopupUnsupported();
	return false;	  
  }
  cur_section = null;
  if (sectiontoedit != null)
    if (!doCancelEdit(true))
      return;
  title = contextTopic;
  x_loadInplaceEditor(contextTopic,doLoadEditor_cb);
};

// Public entry point
function doEditSection (page, section, sectionDivID, sectionAnchor) {
  cur_section = section;
  var newSection = document.getElementById(sectionDivID);
  if (sectiontoedit == newSection)
    return;
  if (sectiontoedit != null)
    if (!doCancelEdit(true))
      return;
  oldcontent = document.getElementById("articleText").innerHTML;
  title = page;
  sectiontoedit = newSection;
  x_doSectionEdit(section, page, doSectionEdit_cb);
};

function isNameChanged() {
  var html = HTMLArea.getHTML(cur_editor._doc.getElementsByTagName('body')[0], false, cur_editor);
  html = stripTitle(html);  // sets wpNewTitle based on page content

  var wpNewTitleName = document.getElementById('wpNewTitle').value;
  var wpOldTitleName = _page_titleName;
  return wpNewTitleName != wpOldTitleName;
};

function saveEntryInline() {
  if (doCheckChanges(cur_editor))
    return;
  var html = HTMLArea.getHTML(cur_editor._doc.getElementsByTagName('body')[0], false, cur_editor);
  html = stripTitle(html);
  var title = contextTopic;
  var time = document.getElementById('wpEditTime').value;
  var section = document.getElementById('wpSection').value;
  html = escape(html);
  var r = new RegExp("\\+","g");
  html = html.replace(r,'%2B');
  x_wfSaveEdit(title, html, time, section, cb_saveEntryInline);
};

function cb_saveEntryInline(responseContent) {
  if (responseContent == '') {
    document.getElementById('quicksavewait').style.display = 'none';
    alert('An unknown error has occured, quick save failed.');
    return;
  }
  var r = responseContent.split('|');
  var wpEditTime = document.getElementById('wpEditTime');
  if (wpEditTime) wpEditTime.value = r[0];
  document.getElementById('quicksavewait').style.display = 'none';
  if (r[1] != '1') {
    // Only show the fading text at bottom of editor, if the action succeeded, otherwise show the alert
    alert(r[2]);
  } else {
    displayInlineMsg('saveMsgSuccess');
    saveFlag = false;
    did_quicksave = true;
    doCheckChanges(cur_editor);
  }
};

function stripTitle(html) {
  if (cur_section != null)
    return html;
  var titleStart = html.indexOf('<h1>');
  var firstTag = html.indexOf('<');
  if (titleStart != firstTag)
    return html;
  var titleStop = html.indexOf('</h1>');
  if (titleStart == -1 || titleStop == -1 || titleStop - titleStart <= 0)
    return html;
  var title = html.substring(titleStart + 4, titleStop);
  var node = document.createElement('div');
  node.innerHTML = title;
  title = HTMLArea.getInnerText(node);
  document.getElementById('wpNewTitle').value = title;
  html = html.substring(titleStop + 5);
  return html;
};

function doSave() {
  setHiddenSubmit('wpSaveH');
  doShowSaveMessage();
  var html = cur_editor.getHTML();
  html = stripTitle(html);
  cur_editor.setHTML(html);
  document.getElementById('editarea').value = html;
};

function doSaveMinor() {
  if (isNameChanged()) {
      alert('Unable to quicksave because you have renamed the page.  You must Save.');
      return;
  }
  setHiddenSubmit('wpSaveMinorH');
  doShowSaveMessage();
  saveEntryInline();
  return false;
};

function okToLeave() {
  saveFlag = false;
};

function doShowSaveMessage() {
  document.getElementById('quicksavewait').style.display = 'block';
};

function doHideSaveMessage() {
  document.getElementById('quicksavedone').style.display = 'none';
};

function prependHTMLToToolbar(editor) {
  if (cur_editor != editor)
    return null;
  
  var sectionAndEditTime;
  if (document.getElementById('wpEditTime') == null)
    sectionAndEditTime = '<input type="hidden" name="wpSection" value="" id="wpSection" />'+
      '<input type="hidden" name="wpEdittime" value="" id="wpEditTime" />';
  else
    sectionAndEditTime = '';
  
  return _prependHTMLToToolbar() + sectionAndEditTime;
};

function addClick(a,stat) {
  HTMLArea.addDom0Event(a, 'click', function() {
    x_wfStatistics(a.href, stat, function(data) {
//      debugger;
        //KA - bugfix 700
        //window.location = a.href;
    });
    //KA - bugfix 700 - commented lines are not required because
    // "leave editor" handler already installed on body
    //return false;
  });
};

function hookClicks() {
  var as = document.getElementsByTagName("a");
  for (var i = as.length; i > 0; ) {
    var a = as[--i];
    if (a.href == "")
      continue;
    var stat = a.getAttribute('stat');
    if (stat)
      addClick(a,stat)
    //else
    //  debugger;
  }
};

/*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:--
--  Xinha (is not htmlArea) - http://xinha.gogo.co.nz/
--
--  Use of Xinha is granted by the terms of the htmlArea License (based on
--  BSD license)  please read license.txt in this package for details.
--
--  Copyright (c) 2006 MindTouch, Inc.
--
--  Xinha was originally based on work by Mihai Bazon which is:
--      Copyright (c) 2003-2004 dynarch.com.
--      Copyright (c) 2002-2003 interactivetools.com, inc.
--      This copyright notice MUST stay intact for use.
--
--  Developers - Coding Style:
--   For the sake of not committing needlessly conflicting changes,
--
--   * New code to be indented with 2 spaces ("soft tab").
--   * New code preferably uses BSD-Style Bracing
--      if(foo)
--      {
--        bar();
--      }
--   * Don't change brace styles unless you're working on the non BSD-Style
--     area (so we don't get spurious changes in line numbering).
--   * Don't change indentation unless you're working on the badly indented
--     area (so we don't get spurious changes of large blocks of code).
--   * Jedit is the recommended editor, a comment of this format should be
--     included in the top 10 lines of the file (see the embedded edit mode)
--
--  $HeadURL: http://svn.xinha.python-hosting.com/trunk/htmlarea.js $
--  $LastChangedDate: 2005-10-02 04:58:27 -0600 (Sun, 02 Oct 2005) $
--  $LastChangedRevision: 377 $
--  $LastChangedBy: kimss $
--------------------------------------------------------------------------*/

HTMLArea.version =
{
'Release'   : 'Trunk',
'Head'      : '$HeadURL: http://svn.xinha.python-hosting.com/trunk/htmlarea.js $'.replace(/^[^:]*: (.*) \$$/, '$1'),
'Date'      : '$LastChangedDate: 2005-10-02 04:58:27 -0600 (Sun, 02 Oct 2005) $'.replace(/^[^:]*: ([0-9-]*) ([0-9:]*) ([+0-9]*) \((.*)\) \$/, '$4 $2 $3'),
'Revision'  : '$LastChangedRevision: 377 $'.replace(/^[^:]*: (.*) \$$/, '$1'),
'RevisionBy': '$LastChangedBy: kimss $'.replace(/^[^:]*: (.*) \$$/, '$1')
};

if (typeof _editor_url == "string") {
    // Leave exactly one backslash at the end of _editor_url
    _editor_url = _editor_url.replace(/\x2f*$/, '/');
} else {
    alert("WARNING: _editor_url is not set!  You should set this variable to the editor files path; it should preferably be an absolute path, like in '/htmlarea/', but it can be relative if you prefer.  Further we will try to load the editor files correctly but we'll probably fail.");
    _editor_url = '';
}

// make sure we have a language
if (typeof _editor_lang == "string") {
    _editor_lang = _editor_lang.toLowerCase();
} else {
    _editor_lang = "en";
}

// skin stylesheet to load
if (!(typeof _editor_skin == "string")) {
    _editor_skin = "";
}

var __htmlareas = [ ];

// enable experimental opera support
HTMLArea.enable_opera = false; 
// browser identification
HTMLArea.agt = navigator.userAgent.toLowerCase();
HTMLArea.is_ie     = ((HTMLArea.agt.indexOf("msie") != -1) && (HTMLArea.agt.indexOf("opera") == -1));
HTMLArea.is_opera  = (HTMLArea.agt.indexOf("opera") != -1);
HTMLArea.is_safari    = (HTMLArea.agt.indexOf("safari") != -1);
HTMLArea.is_mac    = (HTMLArea.agt.indexOf("mac") != -1);
HTMLArea.is_mac_ie = (HTMLArea.is_ie && HTMLArea.is_mac);
HTMLArea.is_win_ie = (HTMLArea.is_ie && !HTMLArea.is_mac);
HTMLArea.is_gecko  = (navigator.product == "Gecko");

// Creates a new HTMLArea object.  Tries to replace the textarea with the given
// ID with it.
function HTMLArea(textarea, config)
{
    if(!textarea) throw("Tried to create HTMLArea without textarea specified.");

    if (HTMLArea.checkSupportedBrowser()) {
        if (typeof config == "undefined") {
            this.config = new HTMLArea.Config();
        } else {
            this.config = config;
        }
        this._htmlArea = null;

        if(typeof textarea != 'object')
        {
            textarea = HTMLArea.getElementById('textarea', textarea);
        }
        this._textArea = textarea;

        // Before we modify anything, get the initial textarea size
        this._initial_ta_size =
        {
            w: textarea.style.width ? textarea.style.width   : (textarea.offsetWidth + 'px'),
            h: textarea.style.height ? textarea.style.height : (textarea.offsetHeight + 'px')
        };

        this._editMode = "wysiwyg";
        this.plugins = {};
        this._timerToolbar = null;
        this._timerUndo = null;
        this._undoQueue = new Array(this.config.undoSteps);
        this._undoPos = -1;
        this._customUndo = true;
        this._mdoc = document; // cache the document, we need it in plugins
        this.doctype = '';
        this.__htmlarea_id_num = __htmlareas.length;
        __htmlareas[this.__htmlarea_id_num] = this;

        this._notifyListeners = { };

        // Panels
        var panels = this._panels =
        {
            right:
            {
                on: true,
                container:    document.createElement('td'),
                panels: [ ]
            },
            left:
            {
                on: true,
                container:    document.createElement('td'),
                panels: [ ]
            },
            top:
            {
                on: true,
                container:    document.createElement('td'),
                panels: [ ]
            },
            bottom:
            {
                on: true,
                container:    document.createElement('td'),
                panels: [ ]
            }
        };

        for(var i in panels)
        {
            panels[i].div = panels[i].container; // legacy
            panels[i].container.className = 'panels ' + i;
            HTMLArea.freeLater(panels[i], 'container');
            HTMLArea.freeLater(panels[i], 'div');
        }
        HTMLArea.freeLater(this, '_textArea');
    }
};

HTMLArea.onload = function(){};
HTMLArea.init = function() {
    HTMLArea.onload();
};


// cache some regexps
HTMLArea.RE_tagName = /(<\/|<)\s*([^ \t\n>]+)/ig;
HTMLArea.RE_doctype = /(<!doctype((.|\n)*?)>)\n?/i;
HTMLArea.RE_head    = /<head>((.|\n)*?)<\/head>/i;
HTMLArea.RE_body    = /<body[^>]*>((.|\n|\r|\t)*?)<\/body>/i;
HTMLArea.RE_Specials = /([\/\^$*+?.()|{}[\]])/g;
HTMLArea.RE_email    = /[a-z0-9_]{3,}@[a-z0-9_-]{2,}(\.[a-z0-9_-]{2,})+/i;
HTMLArea.RE_url      = /(https?:\/\/)?(([a-z0-9_]+:[a-z0-9_]+@)?[a-z0-9_-]{2,}(\.[a-z0-9_-]{2,}){2,}(:[0-9]+)?(\/\S+)*)/i;

HTMLArea.compileRegex = function(str, format) {
    // safari doesn't support compiled regexps
    if (HTMLArea.is_safari) {
        if (typeof format != "undefined") {
            return new RegExp(str, format);
	} else {
            return new RegExp(str);
        }
    }
    if (typeof format != "undefined") {
        return new RegExp().compile(str, format);
    } else {
        return new RegExp().compile(str);
    }
}

HTMLArea.Config = function () {
    var cfg = this;
    this.version = HTMLArea.version.Revision;

    // Width and Height
    //  you may set these as follows
    //  width = 'auto'      -- the width of the original textarea will be used
    //  width = 'toolbar'   -- the width of the toolbar will be used
    //  width = '<css measure>' -- use any css measurement, eg width = '75%'
    //
    //  height = 'auto'     -- the height of the original textarea
    //  height = '<css measure>' -- any css measurement, eg height = '480px'
    this.width  = "auto";
    this.height = "auto";

    // the next parameter specifies whether the toolbar should be included
    // in the size above, or are extra to it.  If false then it's recommended
    // to have explicit pixel sizes above (or on your textarea and have auto above)
    this.sizeIncludesBars = true;

    // the next parameter specifies whether the panels should be included
    // in the size above, or are extra to it.  If false then it's recommended
    // to have explicit pixel sizes above (or on your textarea and have auto above)
    this.sizeIncludesPanels = true;

    // each of the panels has a dimension, for the left/right it's the width
    // for the top/bottom it's the height.
    //
    // WARNING: PANEL DIMENSIONS MUST BE SPECIFIED AS PIXEL WIDTHS
    this.panel_dimensions =
    {
        left:   '200px', // Width
        right:  '200px',
        top:    '100px', // Height
        bottom: '100px'
    };

    // enable creation of a status bar?
    // >MT: doesn't help our users and takes up screen real estate
    this.statusBar = false;
    // <MT

    // intercept ^V and use the HTMLArea paste command
    // If false, then passes ^V through to browser editor widget
    this.htmlareaPaste = false;

    this.mozParaHandler = 'best'; // set to 'built-in', 'dirty' or 'best'
    // built-in: will (may) use 'br' instead of 'p' tags
    // dirty   : will use p and work good enough for the majority of cases,
    // best    : works the best, but it's about 12kb worth of javascript
    //   and will probably be slower than 'dirty'.  This is the "EnterParagraphs"
    //   plugin from "hipikat", rolled in to be part of the core code

    // maximum size of the undo queue
    this.undoSteps = 20;

    // the time interval at which undo samples are taken
    this.undoTimeout = 500; // 1/2 sec.

    // if true then HTMLArea will retrieve the full HTML, starting with the
    // <HTML> tag.
    this.fullPage = false;

    // style included in the iframe document
    this.pageStyle = "";

    // external stylesheets to load (REFERENCE THESE ABSOLUTELY)
    this.pageStyleSheets = [ ];

    // specify a base href for relative links
    this.baseHref  = null;

    // we can strip the base href out of relative links to leave them relative, reason for this
    //   especially if you don't specify a baseHref is that mozilla at least (& IE ?) will prefix
    //   the baseHref to any relative links to make them absolute, which isn't what you want most the time.
    this.stripBaseHref = true;

    // and we can strip the url of the editor page from named links (eg <a href="#top">...</a>)
    //  reason for this is that mozilla at least (and IE ?) prefixes location.href to any
    //  that don't have a url prefixing them
    this.stripSelfNamedAnchors = true;

    // sometimes high-ascii in links can cause problems for servers (basically they don't recognise them)
    //  so you can use this flag to ensure that all characters other than the normal ascii set (actually
    //  only ! through ~) are escaped in URLs to % codes
    this.only7BitPrintablesInURLs = true;

    // if you are putting the HTML written in Xinha into an email you might want it to be 7-bit
    //  characters only.  This config option (off by default) will convert all characters consuming
    //  more than 7bits into UNICODE decimal entity references (actually it will convert anything
    //  below <space> (chr 20) except cr, lf and tab and above <tilde> (~, chr 7E))
    this.sevenBitClean  = false;

    // sometimes we want to be able to replace some string in the html comng in and going out
    //  so that in the editor we use the "internal" string, and outside and in the source view
    //  we use the "external" string  this is useful for say making special codes for
    //  your absolute links, your external string might be some special code, say "{server_url}"
    //  an you say that the internal represenattion of that should be http://your.server/
    this.specialReplacements = { }; // { 'external_string' : 'internal_string' }

    // set to true if you want Word code to be cleaned upon Paste
    this.killWordOnPaste = true;

    // enable the 'Target' field in the Make Link dialog
    this.makeLinkShowsTarget = true;

    // CharSet of the iframe, default is the charset of the document
    this.charSet = HTMLArea.is_gecko ? document.characterSet : document.charset;

    // URL-s
    this.imgURL = "images/";
    this.popupURL = "popups/";

    // remove tags (these have to be a regexp, or null if this functionality is not desired)
    this.htmlRemoveTags = null;

    // Turning this on will turn all "linebreak" and "separator" items in your toolbar into soft-breaks,
    // this means that if the items between that item and the next linebreak/separator can
    // fit on the same line as that which came before then they will, otherwise they will
    // float down to the next line.

    // If you put a linebreak and separator next to each other, only the separator will
    // take effect, this allows you to have one toolbar that works for both flowToolbars = true and false
    // infact the toolbar below has been designed in this way, if flowToolbars is false then it will
    // create explictly two lines (plus any others made by plugins) breaking at justifyleft, however if
    // flowToolbars is false and your window is narrow enough then it will create more than one line
    // even neater, if you resize the window the toolbars will reflow.  Niiiice.

    this.flowToolbars = true;

    /** CUSTOMIZING THE TOOLBAR
    * -------------------------
    *
    * It is recommended that you customize the toolbar contents in an
    * external file (i.e. the one calling HTMLArea) and leave this one
    * unchanged.  That's because when we (InteractiveTools.com) release a
    * new official version, it's less likely that you will have problems
    * upgrading HTMLArea.
    */
    this.toolbar =
    [
    ["popupeditor"],
    ["separator","formatblock","fontname","fontsize","bold","italic","underline","strikethrough"],
    ["separator","forecolor","hilitecolor","textindicator"],
    ["separator","subscript","superscript"],
    ["linebreak","separator","justifyleft","justifycenter","justifyright","justifyfull"],
    ["separator","insertorderedlist","insertunorderedlist","outdent","indent"],
    ["separator","inserthorizontalrule","createlink","insertimage","inserttable"],
    ["separator","undo","redo","selectall","print"], (HTMLArea.is_gecko ? [] : ["cut","copy","paste","overwrite","saveas"]),
    ["separator","killword","clearfonts","removeformat","toggleborders","splitblock","lefttoright", "righttoleft"],
    ["separator","htmlmode","showhelp","about"]
    ];


    this.fontname = {
    "&mdash; font &mdash;":         '',
    "Arial":            'arial,helvetica,sans-serif',
    "Courier New":      'courier new,courier,monospace',
    "Georgia":          'georgia,times new roman,times,serif',
    "Tahoma":           'tahoma,arial,helvetica,sans-serif',
    "Times New Roman":  'times new roman,times,serif',
    "Verdana":          'verdana,arial,helvetica,sans-serif',
    "impact":           'impact',
    "WingDings":        'wingdings'
    };

    this.fontsize = {
    "&mdash; size &mdash;"  : "",
    "1 (8 pt)" : "1",
    "2 (10 pt)": "2",
    "3 (12 pt)": "3",
    "4 (14 pt)": "4",
    "5 (18 pt)": "5",
    "6 (24 pt)": "6",
    "7 (36 pt)": "7"
    };

    this.formatblock = {
    "&mdash; format &mdash;"  : "",
    "Heading 1": "h1",
    "Heading 2": "h2",
    "Heading 3": "h3",
    "Heading 4": "h4",
    "Heading 5": "h5",
    "Heading 6": "h6",
    "Normal"   : "p",
    "Address"  : "address",
    "Formatted": "pre"
    };

    this.customSelects = {};

    function cut_copy_paste(e, cmd, obj) {
        e.execCommand(cmd);
    };

    this.debug = true;

    this.URIs = {
    "blank": "popups/blank.html",
    "link": "link.html",
    "insert_image": "insert_image.html",
    "insert_table": "insert_table.html",
    "select_color": "select_color.html",
    // <MT
	"forecolor":    "select_color.php?type=fg",
	"hilitecolor":  "select_color.php?type=bg",
	// MT> 
    "about": "about.html",
    "help": "editor_help.html"
    };


    // ADDING CUSTOM BUTTONS: please read below!
    // format of the btnList elements is "ID: [ ToolTip, Icon, Enabled in text mode?, ACTION ]"
    //    - ID: unique ID for the button.  If the button calls document.execCommand
    //      it's wise to give it the same name as the called command.
    //    - ACTION: function that gets called when the button is clicked.
    //              it has the following prototype:
    //                 function(editor, buttonName)
    //              - editor is the HTMLArea object that triggered the call
    //              - buttonName is the ID of the clicked button
    //              These 2 parameters makes it possible for you to use the same
    //              handler for more HTMLArea objects or for more different buttons.
    //    - ToolTip: tooltip, will be translated below
    //    - Icon: path to an icon image file for the button
    //            OR; you can use an 18x18 block of a larger image by supllying an array
    //            that has three elemtents, the first is the larger image, the second is the column
    //            the third is the row.  The ros and columns numbering starts at 0 but there is
    //            a header row and header column which have numbering to make life easier.
    //            See images/buttons_main.gif to see how it's done.
    //    - Enabled in text mode: if false the button gets disabled for text-only mode; otherwise enabled all the time.
    this.btnList = {
        bold:          [ "Bold",   HTMLArea._lc({key: 'button_bold', string: ["ed_buttons_main.gif",3,2]}, 'HTMLArea'), false, function(e) {e.execCommand("bold");} ],
        italic:        [ "Italic", HTMLArea._lc({key: 'button_italic', string: ["ed_buttons_main.gif",2,2]}, 'HTMLArea'), false, function(e) {e.execCommand("italic");} ],
        underline:     [ "Underline", HTMLArea._lc({key: 'button_underline', string: ["ed_buttons_main.gif",2,0]}, 'HTMLArea'), false, function(e) {e.execCommand("underline");} ],
        strikethrough: [ "Strikethrough", HTMLArea._lc({key: 'button_strikethrough', string: ["ed_buttons_main.gif",3,0]}, 'HTMLArea'), false, function(e) {e.execCommand("strikethrough");} ],
        subscript:     [ "Subscript", HTMLArea._lc({key: 'button_subscript', string: ["ed_buttons_main.gif",3,1]}, 'HTMLArea'), false, function(e) {e.execCommand("subscript");} ],
        superscript:   [ "Superscript", HTMLArea._lc({key: 'button_superscript', string: ["ed_buttons_main.gif",2,1]}, 'HTMLArea'), false, function(e) {e.execCommand("superscript");} ],

        justifyleft:   [ "Justify left", ["ed_buttons_main.gif",0,0], false, function(e) {e.execCommand("justifyleft");} ],
        justifycenter: [ "Justify center", ["ed_buttons_main.gif",1,1], false, function(e){e.execCommand("justifycenter");}],
        justifyright:  [ "Justify right", ["ed_buttons_main.gif",1,0], false, function(e) {e.execCommand("justifyright");} ],
        justifyfull:   [ "Justify full", ["ed_buttons_main.gif",0,1], false, function(e) {e.execCommand("justifyfull");} ],

        orderedlist:         [ "Ordered list", ["ed_buttons_main.gif",0,3], false, function(e) {e.execCommand("insertorderedlist");} ],
        unorderedlist:       [ "Bulleted list", ["ed_buttons_main.gif",1,3], false, function(e) {e.execCommand("insertunorderedlist");} ],
        insertorderedlist:   [ "Ordered list", ["ed_buttons_main.gif",0,3], false, function(e) {e.execCommand("insertorderedlist");} ],
        insertunorderedlist: [ "Bulleted list", ["ed_buttons_main.gif",1,3], false, function(e) {e.execCommand("insertunorderedlist");} ],

        outdent:     [ "Decrease indent", ["ed_buttons_main.gif",1,2], false, function(e) {e.execCommand("outdent");} ],
        indent:      [ "Increase indent",["ed_buttons_main.gif",0,2], false, function(e) {e.execCommand("indent");} ],
        // >MT: Change "Font color" to "Text color"
        forecolor:   [ "Text color", ["ed_buttons_main.gif",3,3], false, function(e) {e.execCommand("forecolor");} ],
        // <MT
        hilitecolor: [ "Background color", ["ed_buttons_main.gif",2,3], false, function(e) {e.execCommand("hilitecolor");} ],

        // >MT: Clean up the wordsmithing of "Undo", "Redo", "Cut", "Copy", and "Paste"
        undo: [ "Undo last action", ["ed_buttons_main.gif",4,2], false, function(e) {e.execCommand("undo");} ],
        redo: [ "Redo last action", ["ed_buttons_main.gif",5,2], false, function(e) {e.execCommand("redo");} ],
        cut:       [ "Cut", ["ed_buttons_main.gif",5,0], false, cut_copy_paste ],
        copy:      [ "Copy", ["ed_buttons_main.gif",4,0], false, cut_copy_paste ],
        paste:     [ "Paste", ["ed_buttons_main.gif",4,1], false, cut_copy_paste ],
        // <MT
        selectall: [ "Select all", "ed_selectall.gif", false, function(e) {e.execCommand("selectall");} ],

        inserthorizontalrule: [ "Horizontal rule", ["ed_buttons_main.gif",6,0], false, function(e) {e.execCommand("inserthorizontalrule");} ],
        // >MT: use standard createlink, so that param is passed, also change "Insert web link" to "Insert/modify link"
        createlink:           [ "Edit link", ["ed_buttons_main.gif",6,1], false, function(e) {e.execCommand("createlink");} ],
        // <MT
        insertimage:          [ "Insert/modify image", ["ed_buttons_main.gif",6,3], false, function(e) {e.execCommand("insertimage");} ],
        inserttable:          [ "Insert table", ["ed_buttons_main.gif",6,2], false, function(e) {e.execCommand("inserttable");} ],

        htmlmode:      [ "Toggle HTML source", ["ed_buttons_main.gif",7,0], true, function(e) {e.execCommand("htmlmode");} ],
        toggleborders: [ "Toggle borders", ["ed_buttons_main.gif",7,2], false, function(e) { e._toggleBorders() } ],
        print:         [ "Print document", ["ed_buttons_main.gif",8,1], false, function(e) {e._iframe.contentWindow.print();} ],
        saveas:        [ "Save as", "ed_saveas.gif", false, function(e) {e.execCommand("saveas",false,"noname.htm");} ],
        about:         [ "About this editor", ["ed_buttons_main.gif",8,2], true, function(e) {e.execCommand("about");} ],
        showhelp:      [ "Help using editor", ["ed_buttons_main.gif",9,2], true, function(e) {e.execCommand("showhelp");} ],

        splitblock:   [ "Split block", "ed_splitblock.gif", false, function(e) {e._splitBlock();} ],
        lefttoright:  [ "Direction left to right", ["ed_buttons_main.gif",0,4], false, function(e) {e.execCommand("lefttoright");} ],
        righttoleft:  [ "Direction right to left", ["ed_buttons_main.gif",1,4], false, function(e) {e.execCommand("righttoleft");} ],
        overwrite:    [ "Insert/overwrite", "ed_overwrite.gif", false, function(e) {e.execCommand("overwrite");} ],

        // >MT: Clean up the capitalization of "MS word cleaner"
        wordclean:     [ "MS Word cleaner", ["ed_buttons_main.gif",5,3], false, function(e) {e._wordClean();} ],
        // <MT
        clearfonts:    [ "Clear inline font specifications", ["ed_buttons_main.gif",5,4], true, function(e) {e._clearFonts();} ],
        // >MT: "Clear" is being used instead of "Remove"
        removeformat:  [ "Clear formatting", ["ed_buttons_main.gif",4,4], false, function(e) {e.execCommand("removeformat");} ],
        // <MT
        killword:      [ "Clear MS Office tags", ["ed_buttons_main.gif",4,3], false, function(e) {e.execCommand("killword");} ]

    };
    /* ADDING CUSTOM BUTTONS
    * ---------------------
    *
    * It is recommended that you add the custom buttons in an external
    * file and leave this one unchanged.  That's because when we
    * (InteractiveTools.com) release a new official version, it's less
    * likely that you will have problems upgrading HTMLArea.
    *
    * Example on how to add a custom button when you construct the HTMLArea:
    *
    *   var editor = new HTMLArea("your_text_area_id");
    *   var cfg = editor.config; // this is the default configuration
    *   cfg.btnList["my-hilite"] =
    *  [ function(editor) { editor.surroundHTML('<span style="background:yellow">', '</span>'); }, // action
    *    "Highlight selection", // tooltip
    *    "my_hilite.gif", // image
    *    false // disabled in text mode
    *  ];
    *   cfg.toolbar.push(["linebreak", "my-hilite"]); // add the new button to the toolbar
    *
    * An alternate (also more convenient and recommended) way to
    * accomplish this is to use the registerButton function below.
    */
    // initialize tooltips from the I18N module and generate correct image path
    for (var i in this.btnList) {
        var btn = this.btnList[i];
        if(typeof btn[1] != 'string')
        {
            btn[1][0] = _editor_url + this.imgURL + btn[1][0];
        }
        else
        {
            btn[1] = _editor_url + this.imgURL + btn[1];
        }
        btn[0] = HTMLArea._lc(btn[0]); //initialize tooltip
    }

};

/** Helper function: register a new button with the configuration.  It can be
* called with all 5 arguments, or with only one (first one).  When called with
* only one argument it must be an object with the following properties: id,
* tooltip, image, textMode, action.  Examples:
*
* 1. config.registerButton("my-hilite", "Hilite text", "my-hilite.gif", false, function(editor) {...});
* 2. config.registerButton({
*      id       : "my-hilite",      // the ID of your button
*      tooltip  : "Hilite text",    // the tooltip
*      image    : "my-hilite.gif",  // image to be displayed in the toolbar
*      textMode : false,            // disabled in text mode
*      action   : function(editor) { // called when the button is clicked
*                   editor.surroundHTML('<span class="hilite">', '</span>');
*                 },
*      context  : "p"               // will be disabled if outside a <p> element
*    });
*/
HTMLArea.Config.prototype.registerButton = function(id, tooltip, image, textMode, action, context) {
    var the_id;
    if (typeof id == "string") {
        the_id = id;
    } else if (typeof id == "object") {
        the_id = id.id;
    } else {
        alert("ERROR [HTMLArea.Config::registerButton]:\ninvalid arguments");
        return false;
    }
    // check for existing id
    if (typeof this.customSelects[the_id] != "undefined") {
        // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown with the same ID already exists.");
    }
    if (typeof this.btnList[the_id] != "undefined") {
        // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button with the same ID already exists.");
    }
    switch (typeof id) {
        case "string": this.btnList[id] = [ tooltip, image, textMode, action, context ]; break;
        case "object": this.btnList[id.id] = [ id.tooltip, id.image, id.textMode, id.action, id.context ]; break;
    }
};

HTMLArea.prototype.registerPanel = function(side, object)
{
    if(!side) side = 'right';
    var panel = this.addPanel(side);
    if(object)
    {
        object.drawPanelIn(panel);
    }
};

/** The following helper function registers a dropdown box with the editor
* configuration.  You still have to add it to the toolbar, same as with the
* buttons.  Call it like this:
*
* FIXME: add example
*/
HTMLArea.Config.prototype.registerDropdown = function(object) {
    // check for existing id
    if (typeof this.customSelects[object.id] != "undefined") {
        // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown with the same ID already exists.");
    }
    if (typeof this.btnList[object.id] != "undefined") {
        // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button with the same ID already exists.");
    }
    this.customSelects[object.id] = object;
};

/** Call this function to remove some buttons/drop-down boxes from the toolbar.
* Pass as the only parameter a string containing button/drop-down names
* delimited by spaces.  Note that the string should also begin with a space
* and end with a space.  Example:
*
*   config.hideSomeButtons(" fontname fontsize textindicator ");
*
* It's useful because it's easier to remove stuff from the defaul toolbar than
* create a brand new toolbar ;-)
*/
HTMLArea.Config.prototype.hideSomeButtons = function(remove) {
    var toolbar = this.toolbar;
    for (var i = toolbar.length; --i >= 0;) {
        var line = toolbar[i];
        for (var j = line.length; --j >= 0; ) {
            if (remove.indexOf(" " + line[j] + " ") >= 0) {
                var len = 1;
                if (/separator|space/.test(line[j + 1])) {
                    len = 2;
                }
                line.splice(j, len);
            }
        }
    }
};

/** Helper Function: add buttons/drop-downs boxes with title or separator to the toolbar
* if the buttons/drop-downs boxes doesn't allready exists.
* id: button or selectbox (as array with separator or title)
* where: button or selectbox (as array if the first is not found take the second and so on)
* position:
* -1 = insert button (id) one position before the button (where)
* 0 = replace button (where) by button (id)
* +1 = insert button (id) one position after button (where)
*
* cfg.addToolbarElement(["T[title]", "button_id", "separator"] , ["first_id","second_id"], -1);
*/

HTMLArea.Config.prototype.addToolbarElement = function(id, where, position) {
    var toolbar = this.toolbar;
    var a, i, j, o, sid;
    var idIsArray = false;
    var whereIsArray = false;
    var whereLength = 0;
    var whereJ = 0;
    var whereI = 0;
    var exists = false;
    var found = false;
    // check if id and where are arrys
    if ((id && typeof id == "object") && (id.constructor == Array)) {
        idIsArray = true;
    }
    if ((where && typeof where == "object") && (where.constructor == Array)) {
        whereIsArray = true;
        whereLength = where.length;
    }

    if (idIsArray) { //find the button/select box in input array
        for (i = 0; i < id.length; ++i) {
            if ((id[i] != "separator") && (id[i].indexOf("T[") != 0)) {
                sid = id[i];
            }
        }
    } else {
        sid = id;
    }

    for (var i = 0; !exists && !found && i < toolbar.length; ++i) {
        a = toolbar[i]
        for (j = 0; !found && j < a.length; ++j) {
            if (a[i] == sid) { // check if button/select box exists
                exists = true;
                break;
            }
            if (whereIsArray) {
                for (o = 0; o < whereLength; ++o) {
                    if(a[j] == where[o]) {
                        if (o == 0) {
                            found = true;
                            j--;
                            break;
                        } else {
                            whereI = i;
                            whereJ = j;
                            whereLength = o;
                        }
                    }
                }
            } else {
                if (a[j] == where) { // find the position to insert
                    found = true;
                    break;
                }
            }
        }
    }

    if (!exists) {
        if (!found && whereIsArray) { //if check found any other as the first button
            if (where.length != whereLength) {
                j = whereJ;
                a = toolbar[whereI];
                found = true;
            }
        }
        if (found) {
            if (position == 0) { // replace the found button
                if (idIsArray) {
                    a[j] = id[id.length-1];
                    for (i = id.length-1; --i >= 0;) {
                        a.splice(j, 0, id[i]);
                    }
                } else {
                    a[j] = id;
                }
            } else { // insert before/after the found button
                if (position < 0) {
                    j = j + position + 1; //correct position before
                } else if (position > 0) {
                    j = j + position; //correct posion after
                }
                if (idIsArray) {
                    for (i = id.length; --i >= 0;) {
                        a.splice(j, 0, id[i]);
                    }
                } else {
                    a.splice(j, 0, id);
                }
            }
        } else { // no button found
            toolbar[0].splice(0, 0, "separator");
            if (idIsArray) {
                for (i = id.length; --i >= 0;) {
                    toolbar[0].splice(0, 0, id[i]);
                }
            } else {
                toolbar[0].splice(0, 0, id);
            }
        }
    }
};

/** Helper function: replace all TEXTAREA-s in the document with HTMLArea-s. */
HTMLArea.replaceAll = function(config) {
    var tas = document.getElementsByTagName("textarea");
    for (var i = tas.length; i > 0; (new HTMLArea(tas[--i], config)).generate());
};

/** Helper function: replaces the TEXTAREA with the given ID with HTMLArea. */
HTMLArea.replace = function(id, config)
{
    var ta = HTMLArea.getElementById("textarea", id);
    return ta ? (new HTMLArea(ta, config)).generate() : null;;
};

// Creates the toolbar and appends it to the _htmlarea
HTMLArea.prototype._createToolbar = function () {
    var editor = this;  // to access this in nested functions

    var toolbar = document.createElement("div");
    // ._toolbar is for legacy, ._toolBar is better thanks.
    this._toolBar = this._toolbar = toolbar;
    toolbar.className = "toolbar";
    toolbar.unselectable = "1";

    HTMLArea.freeLater(this, '_toolBar');
    HTMLArea.freeLater(this, '_toolbar');

    var tb_row = null;
    var tb_objects = new Object();
    this._toolbarObjects = tb_objects;
    this._createToolbar1(editor, toolbar, tb_objects);
    this._htmlArea.appendChild(toolbar);

    return toolbar;
};


HTMLArea.prototype._setConfig = function(config) {
    this.config = config;
};

HTMLArea.prototype._addToolbar = function() {
    this._createToolbar1(this, this._toolbar, this._toolbarObjects);
};

// separate from previous createToolBar to allow dynamic change of toolbar
HTMLArea.prototype._createToolbar1 = function(editor, toolbar, tb_objects) {
    var tb_row = null;
    // This shouldn't be necessary, but IE seems to float outside of the container
    // when we float toolbar sections, so we have to clear:both here as well
    // as at the end (which we do have to do).
    if(editor.config.flowToolbars)
    {
        var brk = document.createElement('div');
        brk.style.height =
        brk.style.width =
        brk.style.lineHeight =
        brk.style.fontSize = '1px';
        brk.style.clear = 'both';
        toolbar.appendChild(brk);
    }

    // creates a new line in the toolbar
    function newLine() {
        if(tb_row != null && tb_row.childNodes.length == 0) return;

        var table = document.createElement("table");
        table.border = "0px";
        table.cellSpacing = "0px";
        table.cellPadding = "0px";
        if(editor.config.flowToolbars)
        {
            if(HTMLArea.is_ie)
            {
                table.style.styleFloat = "left";
            }
            else
            {
                table.style.cssFloat = "left";
            }
            // >MT: fix flow issue, each newLine is otherwise on a new line
            table.style.width = "auto";
            // <MT
        }

        toolbar.appendChild(table);
        // TBODY is required for IE, otherwise you don't see anything
        // in the TABLE.
        var tb_body = document.createElement("tbody");
        table.appendChild(tb_body);
        tb_row = document.createElement("tr");
        tb_body.appendChild(tb_row);

        table.className = 'toolbarRow'; // meh, kinda.
    }; // END of function: newLine

    // init first line
    newLine();

    // updates the state of a toolbar element.  This function is member of
    // a toolbar element object (unnamed objects created by createButton or
    // createSelect functions below).
    function setButtonStatus(id, newval) {
        var oldval = this[id];
        var el = this.element;
        if (oldval != newval) {
            switch (id) {
                case "enabled":
                if (newval) {
                    HTMLArea._removeClass(el, "buttonDisabled");
                    el.disabled = false;
                } else {
                    HTMLArea._addClass(el, "buttonDisabled");
                    el.disabled = true;
                }
                break;
                case "active":
                if (newval) {
                    HTMLArea._addClass(el, "buttonPressed");
                } else {
                    HTMLArea._removeClass(el, "buttonPressed");
                }
                break;
            }
            this[id] = newval;
        }
    }; // END of function: setButtonStatus

    // this function will handle creation of combo boxes.  Receives as
    // parameter the name of a button as defined in the toolBar config.
    // This function is called from createButton, above, if the given "txt"
    // doesn't match a button.
    function createSelect(txt) {
        var options = null;
        var el = null;
        var cmd = null;
        var customSelects = editor.config.customSelects;
        var context = null;
        var tooltip = "";
        switch (txt) {
            case "fontsize":
            case "fontname":
            case "formatblock":
            // >MT: fontstyles
            case "fontstyles":
            // <MT
            // the following line retrieves the correct
            // configuration option because the variable name
            // inside the Config object is named the same as the
            // button/select in the toolbar.  For instance, if txt
            // == "formatblock" we retrieve config.formatblock (or
            // a different way to write it in JS is
            // config["formatblock"].
            options = editor.config[txt];
            cmd = txt;
            break;
            default:
            // try to fetch it from the list of registered selects
            cmd = txt;
            var dropdown = customSelects[cmd];
            if (typeof dropdown != "undefined") {
                options = dropdown.options;
                context = dropdown.context;
                if (typeof dropdown.tooltip != "undefined") {
                    tooltip = dropdown.tooltip;
                }
            } else {
                alert("ERROR [createSelect]:\nCan't find the requested dropdown definition");
            }
            break;
        }
        if (options) {
            el = document.createElement("select");
            el.title = tooltip;
            var obj = {
                name    : txt,    // field name
                element : el,     // the UI element (SELECT)
                enabled : true,   // is it enabled?
                text    : false,  // enabled in text mode?
                cmd     : cmd,    // command ID
                state   : setButtonStatus, // for changing state
                context : context
            };

            HTMLArea.freeLater(obj);

            tb_objects[txt] = obj;

            for (var i in options) {
                var op = document.createElement("option");
                op.innerHTML = HTMLArea._lc(i);
                op.value = options[i];
                el.appendChild(op);
            }
            HTMLArea._addEvent(el, "change", function () {
                editor._comboSelected(el, txt);
            });
        }
        return el;
    }; // END of function: createSelect

    // appends a new button to toolbar
    function createButton(txt) {
        // >MT: handle 'showbutton'
        var btn = editor.config.btnList[txt];
        if (btn && btn[5] == false) {
            return -1;
        }
        // <MT
        // the element that will be created
        var el = null;
        var btn = null;
        switch (txt) {
            case "separator":
            if(editor.config.flowToolbars) newLine();
            el = document.createElement("div");
            el.className = "separator";
            break;
            case "space":
            el = document.createElement("div");
            el.className = "space";
            break;
            case "linebreak":
            newLine();
            return false;
            case "textindicator":
            el = document.createElement("div");
            el.appendChild(document.createTextNode("A"));
            el.className = "indicator";
            el.title = HTMLArea._lc("Current style");
            var obj = {
                name  : txt, // the button name (i.e. 'bold')
                element : el, // the UI element (DIV)
                enabled : true, // is it enabled?
                active  : false, // is it pressed?
                text  : false, // enabled in text mode?
                cmd      : "textindicator", // the command ID
                state  : setButtonStatus // for changing state
            };

            HTMLArea.freeLater(obj);

            tb_objects[txt] = obj;
            break;
            default:
            btn = editor.config.btnList[txt];
        }
        if (!el && btn) {
            el = document.createElement("a");
            el.style.display = 'block';
            el.href = 'javascript:void(0)';
            el.style.textDecoration = 'none';
            el.title = btn[0];
            el.className = "button";
            // let's just pretend we have a button object, and
            // assign all the needed information to it.
            var obj = {
                name  : txt, // the button name (i.e. 'bold')
                element : el, // the UI element (DIV)
                enabled : true, // is it enabled?
                active  : false, // is it pressed?
                text  : btn[2], // enabled in text mode?
                cmd      : btn[3], // the command ID
                state  : setButtonStatus, // for changing state
                context : btn[4] || null // enabled in a certain context?
            };

            HTMLArea.freeLater(obj);

            tb_objects[txt] = obj;
            // handlers to emulate nice flat toolbar buttons
            HTMLArea._addEvent(el, "mouseout", function () {
                if (obj.enabled) with (HTMLArea) {
                    //_removeClass(el, "buttonHover");
                    _removeClass(el, "buttonActive");
                    (obj.active) && _addClass(el, "buttonPressed");
                }
            });

            HTMLArea._addEvent(el, "mousedown", function (ev) {
                if (obj.enabled) with (HTMLArea) {
                    _addClass(el, "buttonActive");
                    _removeClass(el, "buttonPressed");
                    _stopEvent(is_ie ? window.event : ev);
                }
            });
            // when clicked, do the following:
            HTMLArea._addEvent(el, "click", function (ev) {
                if (obj.enabled) with (HTMLArea) {
                    _removeClass(el, "buttonActive");
                    //_removeClass(el, "buttonHover");
                    if(HTMLArea.is_gecko)
                    {
                        editor.activateEditor();
                    }
                    obj.cmd(editor, obj.name, obj);
                    _stopEvent(is_ie ? window.event : ev);
                }
            });

            var i_contain = HTMLArea.makeBtnImg(btn[1]);
            var img = i_contain.firstChild;
            el.appendChild(i_contain);

            obj.imgel = img;
            obj.swapImage = function(newimg)
            {
                if(typeof newimg != 'string')
                {
                    img.src = newimg[0];
                    img.style.position = 'relative';
                    img.style.top  = newimg[2] ? ('-' + (18 * (newimg[2] + 1)) + 'px') : '-18px';
                    img.style.left = newimg[1] ? ('-' + (18 * (newimg[1] + 1)) + 'px') : '-18px';
                }
                else
                {
                    obj.imgel.src = newimg;
                    img.style.top = '0px';
                    img.style.left = '0px';
                }
            }

        } else if (!el) {
            el = createSelect(txt);
        }

        return el;
    };

    var first = true;
    for (var i = 0; i < this.config.toolbar.length; ++i) {
        if (!first) {
            // createButton("linebreak");
        } else {
            first = false;
        }
        if(this.config.toolbar[i] == null) this.config.toolbar[i] = ['separator'];
        var group = this.config.toolbar[i];

        for (var j = 0; j < group.length; ++j)
        {
            var code = group[j];
            if (/^([IT])\[(.*?)\]/.test(code))
            {
                // special case, create text label
                var l7ed = RegExp.$1 == "I"; // localized?
                var label = RegExp.$2;
                if (l7ed) {
                    label = HTMLArea._lc(label);
                }
                var tb_cell = document.createElement("td");
                tb_row.appendChild(tb_cell);
                tb_cell.className = "label";
                tb_cell.innerHTML = label;
            }
            else if(typeof code != 'function')
            {
                var tb_element = createButton(code);

                // >MT: handle hidden buttons
                if (tb_element && tb_element != -1)
                // <MT
                {
                    var tb_cell = document.createElement("td");
                    tb_cell.className = 'toolbarElement';
                    tb_row.appendChild(tb_cell);
                    tb_cell.appendChild(tb_element);
                }
                else if (tb_element == null)
                {
                    alert("FIXME: Unknown toolbar item: " + code);
                }
            }
        }
    }

    if(editor.config.flowToolbars)
    {
        var brk = document.createElement('div');
        brk.style.height =
        brk.style.width =
        brk.style.lineHeight =
        brk.style.fontSize = '1px';
        brk.style.clear = 'both';
        toolbar.appendChild(brk);
    }

    return toolbar;
};

use_clone_img = false;
HTMLArea.makeBtnImg = function(imgDef, doc)
{
    if(!doc) doc = document;

    if(!doc._htmlareaImgCache)
    {
        doc._htmlareaImgCache = { };
        HTMLArea.freeLater(doc._htmlareaImgCache);
    }

    var i_contain = null;
    if(HTMLArea.is_ie && ((!doc.compatMode) || (doc.compatMode && doc.compatMode == "BackCompat")))
    {
        i_contain = doc.createElement('span');
    }
    else
    {
        i_contain = doc.createElement('div');
        i_contain.style.position = 'relative';
    }

    i_contain.style.overflow = 'hidden';
    i_contain.style.width = "18px";
    i_contain.style.height = "18px";
    i_contain.className    = 'buttonImageContainer';

    var img = null;
    if(typeof imgDef == 'string')
    {
        if(doc._htmlareaImgCache[imgDef])
        {
            // >MT: fix cloneNode takes an argument
            img = doc._htmlareaImgCache[imgDef].cloneNode(false);
            // <MT
        }
        else
        {
            img = doc.createElement("img");
            img.src = imgDef;
            img.style.width = "18px";
            img.style.height = "18px";
            if(use_clone_img)
            // >MT: fix cloneNode takes an argument
            doc._htmlareaImgCache[imgDef] = img.cloneNode(false);
            // <MT
        }
    }
    else
    {
        if(doc._htmlareaImgCache[imgDef[0]])
        {
            // >MT: fix cloneNode takes an argument
            img = doc._htmlareaImgCache[imgDef[0]].cloneNode(false);
            // <MT
        }
        else
        {
            img = doc.createElement("img");
            img.src = imgDef[0];
            img.style.position = 'relative';
            if(use_clone_img)
            // >MT: fix cloneNode takes an argument
            doc._htmlareaImgCache[imgDef[0]] = img.cloneNode(false);
            // <MT
        }
        img.style.top  = imgDef[2] ? ('-' + (18 * (imgDef[2] + 1)) + 'px') : '-18px';
        img.style.left = imgDef[1] ? ('-' + (18 * (imgDef[1] + 1)) + 'px') : '-18px';
    }
    i_contain.appendChild(img);
    return i_contain;
};


HTMLArea.prototype._createStatusBar = function() {
    var statusbar = document.createElement("div");
    statusbar.className = "statusBar";
    this._statusBar = statusbar;
    HTMLArea.freeLater(this, '_statusBar');

    // statusbar.appendChild(document.createTextNode(HTMLArea._lc("Path") + ": "));
    // creates a holder for the path view
    div = document.createElement("span");
    div.className = "statusBarTree";
    div.innerHTML = HTMLArea._lc("Path") + ": ";
    this._statusBarTree = div;
    HTMLArea.freeLater(this, '_statusBarTree');
    this._statusBar.appendChild(div);

    div = document.createElement("span");
    div.innerHTML = HTMLArea._lc("You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.");
    div.style.display = "none";
    this._statusBarTextMode = div;
    HTMLArea.freeLater(this, '_statusBarTextMode');
    this._statusBar.appendChild(div);

    if (!this.config.statusBar)
    {
        // disable it...
        statusbar.style.display = "none";
    }

    return statusbar;
};

// Creates the HTMLArea object and replaces the textarea with it.
HTMLArea.prototype.generate = function ()
{
    var editor = this;  // we'll need "this" in some nested functions

    if(typeof Dialog == 'undefined')
    {
        HTMLArea._loadback
        (_editor_url + 'dialog.js', function() { editor.generate(); } );
        return false;
    }

    if(typeof HTMLArea.Dialog == 'undefined')
    {
        HTMLArea._loadback
        (_editor_url + 'inline-dialog.js', function() { editor.generate(); } );
        return false;
    }

    // >MT: use popupdiv instead of popupwin
    if(typeof PopupDiv == 'undefined')
    {
        HTMLArea._loadback
        (_editor_url + 'popupdiv.js', function() { editor.generate(); } );
        return false;
    }
    /*
    if(typeof PopupWin == 'undefined')
    {
    HTMLArea._loadback
    (_editor_url + 'popupwin.js', function() { editor.generate(); } );
    return false;
    }
    */
    // <MT

    if(_editor_skin != "") {
        var found=false;
        var head = document.getElementsByTagName("head")[0];
        var links = document.getElementsByTagName("link");
        for(var i = 0; i<links.length; i++) {
            if((links[i].rel == "stylesheet")&&(links[i].href == _editor_url + 'skins/' + _editor_skin + '/skin.css'))
            found = true;
        }
        if(!found) {
            var link = document.createElement("link");
            link.type = "text/css";
            link.href = _editor_url + 'skins/' + _editor_skin + '/skin.css';
            link.rel = "stylesheet"
            head.appendChild(link);
        }
    }

    //backwards-compatibility: load FullScreen-Plugin if we find a "popupeditor"-button in the toolbar
    var toolbar = editor.config.toolbar;
    for (var i = toolbar.length; --i >= 0;) {
        for (var j = toolbar[i].length; --j >= 0; ) {
            if (toolbar[i][j]=="popupeditor") {
                if(typeof FullScreen == "undefined") {
                    HTMLArea.loadPlugin("FullScreen", function() { editor.generate(); } );
                    return false;
                }
                editor.registerPlugin('FullScreen');
            }
        }
    }

    // If this is gecko, set up the paragraph handling now
    if(HTMLArea.is_gecko)
    {
        switch(editor.config.mozParaHandler)
        {
            case 'best':
            {
                if(typeof EnterParagraphs == 'undefined')
                {
                    HTMLArea.loadPlugin("EnterParagraphs", function() { editor.generate(); } );
                    return false;
                }
                editor.registerPlugin('EnterParagraphs');
            }
            break;

            case 'dirty'   :
            case 'built-in':
            default        :
            {
                // See _editorEvent
            }
            break;
        }
    }

    // create the editor framework, yah, table layout I know, but much easier
    // to get it working correctly this way, sorry about that, patches welcome.

    this._framework =
    {
    'table'     :document.createElement('table'),
    'tbody'     :document.createElement('tbody'), // IE will not show the table if it doesn't have a tbody!
    'tb_row'    :document.createElement('tr'),
    'tb_cell'   :document.createElement('td'), // Toolbar

    'tp_row'    :document.createElement('tr'),
    'tp_cell'   :this._panels.top.container,   // top panel

    'ler_row'   :document.createElement('tr'),
    'lp_cell'   :this._panels.left.container,  // left panel
    'ed_cell'   :document.createElement('td'), // editor
    'rp_cell'   :this._panels.right.container, // right panel

    'bp_row'    :document.createElement('tr'),
    'bp_cell'   :this._panels.bottom.container,// bottom panel

    'sb_row'    :document.createElement('tr'),
    'sb_cell'   :document.createElement('td')  // status bar

    };

    HTMLArea.freeLater(this._framework);

    var fw = this._framework;
    fw.table.border="0";
    fw.table.cellPadding="0";
    fw.table.cellSpacing="0";

    fw.tb_row.style.verticalAlign = 'top';
    fw.tp_row.style.verticalAlign = 'top';
    fw.ler_row.style.verticalAlign= 'top';
    fw.bp_row.style.verticalAlign = 'top';
    fw.sb_row.style.verticalAlign = 'top';
    fw.ed_cell.style.position     = 'relative';

    // Put the cells in the rows        set col & rowspans
    // note that I've set all these so that all panels are showing
    // but they will be redone in sizeEditor() depending on which
    // panels are shown.  It's just here to clarify how the thing
    // is put togethor.
    fw.tb_row.appendChild(fw.tb_cell);  fw.tb_cell.colSpan = 3;

    fw.tp_row.appendChild(fw.tp_cell);  fw.tp_cell.colSpan = 3;

    fw.ler_row.appendChild(fw.lp_cell);
    fw.ler_row.appendChild(fw.ed_cell);
    fw.ler_row.appendChild(fw.rp_cell);

    fw.bp_row.appendChild(fw.bp_cell);  fw.bp_cell.colSpan = 3;

    fw.sb_row.appendChild(fw.sb_cell);  fw.sb_cell.colSpan = 3;

    // Put the rows in the table body
    fw.tbody.appendChild(fw.tb_row);  // Toolbar
    fw.tbody.appendChild(fw.tp_row); // Left, Top, Right panels
    fw.tbody.appendChild(fw.ler_row);  // Editor/Textarea
    fw.tbody.appendChild(fw.bp_row);  // Bottom panel
    fw.tbody.appendChild(fw.sb_row);  // Statusbar

    // and body in the table
    fw.table.appendChild(fw.tbody);

    var htmlarea = this._framework.table;
    this._htmlArea = htmlarea;
    HTMLArea.freeLater(this, '_htmlArea');
    htmlarea.className = "htmlarea";

    // create the toolbar and put in the area
    var toolbar = this._createToolbar();
    // >MT: add this._readOnly
    if (!this._readOnly)
    // <MT
    this._framework.tb_cell.appendChild(toolbar);

    // create the IFRAME & add to container
    var iframe = document.createElement("iframe");
    iframe.src = _editor_url + editor.config.URIs["blank"];
    this._framework.ed_cell.appendChild(iframe);
    this._iframe = iframe;
    this._iframe.className = 'xinha_iframe';
    HTMLArea.freeLater(this, '_iframe');

    // creates & appends the status bar
    var statusbar = this._createStatusBar();
    this._framework.sb_cell.appendChild(statusbar);

    // insert Xinha before the textarea.
    var textarea = this._textArea;
    textarea.parentNode.insertBefore(htmlarea, textarea);
    textarea.className = 'xinha_textarea';

    // extract the textarea and insert it into the htmlarea
    HTMLArea.removeFromParent(textarea);
    this._framework.ed_cell.appendChild(textarea);

    // Set up event listeners for saving the iframe content to the textarea
    if (textarea.form)
    {
        // onsubmit get the HTMLArea content and update original textarea.
        HTMLArea.prependDom0Event
        (
        this._textArea.form,
        'submit',
        function() {editor._textArea.value = editor.outwardHtml(editor.getHTML()); return true;}
        );

        var initialTAContent = textarea.value;

        // onreset revert the HTMLArea content to the textarea content
        HTMLArea.prependDom0Event
        (
        this._textArea.form,
        'reset',
        function() { editor.setHTML(editor.inwardHtml(initialTAContent)); editor.updateToolbar(); return true; }
        );
    }

    // add a handler for the "back/forward" case -- on body.unload we save
    // the HTML content into the original textarea.
    HTMLArea.prependDom0Event(window, 'unload', function() {textarea.value = editor.outwardHtml(editor.getHTML()); return true; });

    // Hide textarea
    textarea.style.display = "none";

    // Initalize size
    editor.initSize();

    // Add an event to initialize the iframe once loaded.
    editor._iframeLoadDone = false;
    HTMLArea._addEvent
    (
    this._iframe,
    'load',
    function(e)
    {
        if(! editor._iframeLoadDone)
        {
            editor._iframeLoadDone = true;
            editor.initIframe();
        }
        return true;
    }
    );

};

/**
* Size the editor according to the INITIAL sizing information.
* config.width
*    The width may be set via three ways
*    auto    = the width is inherited from the original textarea
*    toolbar = the width is set to be the same size as the toolbar
*    <set size> = the width is an explicit size (any CSS measurement, eg 100em should be fine)
*
* config.height
*    auto    = the height is inherited from the original textarea
*    <set size> = an explicit size measurement (again, CSS measurements)
*
* config.sizeIncludesBars
*    true    = the tool & status bars will appear inside the width & height confines
*    false   = the tool & status bars will appear outside the width & height confines
*
*/

HTMLArea.prototype.initSize = function()
{
    var editor = this;

    var width  = null;
    var height = null;
    switch(this.config.width)
    {
        case 'auto':
        {
            width = this._initial_ta_size.w;
        }
        break;

        case 'toolbar':
        {
            width = this._toolBar.offsetWidth;
        }
        break;

        default :
        {
            width = this.config.width;
        }
        break;
    }

    switch(this.config.height)
    {
        case 'auto':
        {
            height = this._initial_ta_size.h;
        }
        break;

        default :
        {
            height = this.config.height;
        }
        break;
    }

    this.sizeEditor(width, height, this.config.sizeIncludesBars, this.config.sizeIncludesPanels);

    HTMLArea.addDom0Event(window, 'resize', function(e) { editor.sizeEditor(); });

    this.notifyOn('panel_change',function(){editor.sizeEditor();});
};

/**
*  Size the editor to a specific size, or just refresh the size (when window resizes for example)
*  @param width optional width (CSS specification)
*  @param height optional height (CSS specification)
*  @param includingBars optional boolean to indicate if the size should include or exclude tool & status bars
*/

HTMLArea.prototype.sizeEditor = function(width, height, includingBars, includingPanels)
{

    // We need to set the iframe & textarea to 100% height so that the htmlarea
    // isn't "pushed out" when we get it's height, so we can change them later.
    this._iframe.style.height   = '100%';
    this._textArea.style.height = '100%';
    this._iframe.style.width    = '';
    this._textArea.style.width  = '';

    if(includingBars != null)     this._htmlArea.sizeIncludesToolbars = includingBars;
    if(includingPanels != null)   this._htmlArea.sizeIncludesPanels   = includingPanels;

    if(width != null)
    {
        this._htmlArea.style.width          = width;
        if(!this._htmlArea.sizeIncludesPanels)
        {
            // Need to add some for l & r panels
            var panel = this._panels.right;
            if(panel.on && panel.panels.length && HTMLArea.hasDisplayedChildren(panel.div))
            {
                this._htmlArea.style.width = this._htmlArea.offsetWidth + parseInt(this.config.panel_dimensions.right);
            }

            var panel = this._panels.left;
            if(panel.on && panel.panels.length && HTMLArea.hasDisplayedChildren(panel.div))
            {
                this._htmlArea.style.width = this._htmlArea.offsetWidth + parseInt(this.config.panel_dimensions.left);
            }
        }
    }

    if(height != null)
    {
        this._htmlArea.style.height         = height;
        if(!this._htmlArea.sizeIncludesToolbars)
        {
            // Need to add some for toolbars
            this._htmlArea.style.height         = this._htmlArea.offsetHeight + this._toolbar.offsetHeight + this._statusBar.offsetHeight;
        }

        if(!this._htmlArea.sizeIncludesPanels)
        {
            // Need to add some for l & r panels
            var panel = this._panels.top;
            if(panel.on && panel.panels.length && HTMLArea.hasDisplayedChildren(panel.div))
            {
                this._htmlArea.style.height = this._htmlArea.offsetHeight + parseInt(this.config.panel_dimensions.top);
            }

            var panel = this._panels.bottom;
            if(panel.on && panel.panels.length && HTMLArea.hasDisplayedChildren(panel.div))
            {
                this._htmlArea.style.height = this._htmlArea.offsetHeight + parseInt(this.config.panel_dimensions.bottom);
            }
        }
    }

    // >MT: add this._OnResize
    if (typeof this._OnResize == 'function' && width == null && height == null)
    this._OnResize();
    // <MT
    // At this point we have this._htmlArea.style.width & this._htmlArea.style.height
    // which are the size for the OUTER editor area, including toolbars and panels
    // now we size the INNER area and position stuff in the right places.
    width  = this._htmlArea.offsetWidth;
    height = this._htmlArea.offsetHeight;

    // Set colspan for toolbar, and statusbar, rowspan for left & right panels, and insert panels to be displayed
    // into thier rows
    var panels = this._panels;
    var editor = this;
    var col_span = 1;

    function panel_is_alive(pan)
    {
        if(panels[pan].on && panels[pan].panels.length && HTMLArea.hasDisplayedChildren(panels[pan].container))
        {
            panels[pan].container.style.display = '';
            return true;
        }

        // Otherwise make sure it's been removed from the framework
        else
        {
            panels[pan].container.style.display='none';
            return false;
        }
    }

    if(panel_is_alive('left'))
    {
        col_span += 1;
    }

    if(panel_is_alive('top'))
    {
        // NOP
    }

    if(panel_is_alive('right'))
    {
        col_span += 1;
    }

    if(panel_is_alive('bottom'))
    {
        // NOP
    }

    this._framework.tb_cell.colSpan = col_span;
    this._framework.tp_cell.colSpan = col_span;
    this._framework.bp_cell.colSpan = col_span;
    this._framework.sb_cell.colSpan = col_span;

    // Put in the panel rows, top panel goes above editor row
    if(!this._framework.tp_row.childNodes.length)
    {
        HTMLArea.removeFromParent(this._framework.tp_row);
    }
    else
    {
        if(!HTMLArea.hasParentNode(this._framework.tp_row))
        {
            this._framework.tbody.insertBefore(this._framework.tp_row, this._framework.ler_row);
        }
    }

    // bp goes after the editor
    if(!this._framework.bp_row.childNodes.length)
    {
        HTMLArea.removeFromParent(this._framework.bp_row);
    }
    else
    {
        if(!HTMLArea.hasParentNode(this._framework.bp_row))
        {
            this._framework.tbody.insertBefore(this._framework.bp_row, this._framework.ler_row.nextSibling);
        }
    }

    // finally if the statusbar is on, insert it
    if(!this.config.statusBar)
    {
        HTMLArea.removeFromParent(this._framework.sb_row);
    }
    else
    {
        if(!HTMLArea.hasParentNode(this._framework.sb_row))
        {
            this._framework.table.appendChild(this._framework.sb_row);
        }
    }

    // Size and set colspans, link up the framework
    this._framework.lp_cell.style.width  = this.config.panel_dimensions.left;
    this._framework.rp_cell.style.width  = this.config.panel_dimensions.right;
    this._framework.tp_cell.style.height = this.config.panel_dimensions.top;
    this._framework.bp_cell.style.height = this.config.panel_dimensions.bottom;
    this._framework.tb_cell.style.height = this._toolBar.offsetHeight   + 'px';
    this._framework.sb_cell.style.height = this._statusBar.offsetHeight + 'px';

    var edcellheight = height - this._toolBar.offsetHeight - this._statusBar.offsetHeight;
    if(panel_is_alive('top'))    edcellheight  -= parseInt(this.config.panel_dimensions.top);
    if(panel_is_alive('bottom')) edcellheight  -= parseInt(this.config.panel_dimensions.bottom);;
    this._iframe.style.height    = edcellheight + 'px';

    var edcellwidth = width;
    if(panel_is_alive('left'))  edcellwidth -= parseInt(this.config.panel_dimensions.left);
    if(panel_is_alive('right')) edcellwidth -= parseInt(this.config.panel_dimensions.right);
    this._iframe.style.width     =  edcellwidth + 'px';

    this._textArea.style.height = this._iframe.style.height;
    this._textArea.style.width  = this._iframe.style.width;

    this.notifyOf('resize', {width:this._htmlArea.offsetWidth, height:this._htmlArea.offsetHeight});
    // >MT: redraw after resize, to remove artifacts
    this.forceRedraw();
    // <MT
};

HTMLArea.prototype.addPanel = function(side)
{
    var div = document.createElement('div');
    div.side = side;
    if(side == 'left' || side == 'right')
    {
        div.style.width = this.config.panel_dimensions[side];
    }
    HTMLArea.addClasses(div, 'panel');
    this._panels[side].panels.push(div);
    this._panels[side].div.appendChild(div);

    this.notifyOf('panel_change', {'action':'add','panel':div});

    return div;
};

HTMLArea.prototype.removePanel = function(panel)
{
    this._panels[panel.side].div.removeChild(panel);
    var clean = [ ];
    for(var i = 0; i < this._panels[panel.side].panels.length; i++)
    {
        if(this._panels[panel.side].panels[i] != panel)
        {
            clean.push(this._panels[panel.side].panels[i]);
        }
    }
    this._panels[panel.side].panels = clean;
    this.notifyOf('panel_change', {'action':'remove','panel':panel});
};

HTMLArea.prototype.hidePanel = function(panel)
{
    if(panel)
    {
        panel.style.display = 'none';
        this.notifyOf('panel_change', {'action':'hide','panel':panel});
    }
};

HTMLArea.prototype.showPanel = function(panel)
{
    if(panel)
    {
        panel.style.display = '';
        this.notifyOf('panel_change', {'action':'show','panel':panel});
    }
};

HTMLArea.prototype.hidePanels = function(sides)
{
    if(typeof sides == 'undefined')
    {
        sides = ['left','right','top','bottom'];
    }

    var reShow = [];
    for(var i = 0; i < sides.length;i++)
    {
        if(this._panels[sides[i]].on)
        {
            reShow.push(sides[i]);
            this._panels[sides[i]].on = false;
        }
    }
    this.notifyOf('panel_change', {'action':'multi_hide','sides':sides});
};

HTMLArea.prototype.showPanels = function(sides)
{
    if(typeof sides == 'undefined')
    {
        sides = ['left','right','top','bottom'];
    }

    var reHide = [];
    for(var i = 0; i < sides.length;i++)
    {
        if(!this._panels[sides[i]].on)
        {
            reHide.push(sides[i]);
            this._panels[sides[i]].on = true;
        }
    }
    this.notifyOf('panel_change', {'action':'multi_show','sides':sides});
};

HTMLArea.objectProperties = function(obj)
{
    var props = [ ];
    for(var x in obj)
    {
        props[props.length] = x;
    }
    return props;
};

/*
* EDITOR ACTIVATION NOTES:
*  when a page has multiple Xinha editors, ONLY ONE should be activated at any time (this is mostly to
*  work around a bug in Mozilla, but also makes some sense).  No editor should be activated or focused
*  automatically until at least one editor has been activated through user action (by mouse-clicking in
*  the editor).
*/

HTMLArea.prototype.editorIsActivated = function() {
    try {
        if (HTMLArea.is_gecko) return (this._doc.designMode == 'on');
        else return (this._doc.body.contentEditable);
    } catch (e)
    {
        return false;
    }
};

HTMLArea._someEditorHasBeenActivated = false;
HTMLArea._currentlyActiveEditor      = false;
HTMLArea.prototype.activateEditor = function()
{
    // We only want ONE editor at a time to be active
    if(HTMLArea._currentlyActiveEditor)
    {
        if(HTMLArea._currentlyActiveEditor == this) return true;
        HTMLArea._currentlyActiveEditor.deactivateEditor();
    }

    if (HTMLArea.is_gecko && this._doc.designMode != 'on')
    {
        try
        {
            // cannot set design mode if no display
            if (this._iframe.style.display == 'none')
            {
                this._iframe.style.display = '';
                this._doc.designMode = 'on';
                this._iframe.style.display = 'none';
            }
            else
            {
                this._doc.designMode = 'on';
            }
        } catch (e) {}
    }
    else if(!HTMLArea.is_gecko && this._doc.body.contentEditable != true)
    {
        this._doc.body.contentEditable = true;
    }

    // We need to know that at least one editor on the page has been activated
    // this is because we will not focus any editor until an editor has been activated
    HTMLArea._someEditorHasBeenActivated = true;
    HTMLArea._currentlyActiveEditor      = this;

    var editor = this;
    this.enableToolbar();
};

HTMLArea.prototype.deactivateEditor = function()
{
    // If the editor isn't active then the user shouldn't use the toolbar
    this.disableToolbar();

    if (HTMLArea.is_gecko && this._doc.designMode != 'off')
    {
        try {this._doc.designMode = 'off';} catch (e) {}
    }
    else if(!HTMLArea.is_gecko && this._doc.body.contentEditable != false)
    {
        this._doc.body.contentEditable = false;
    }

    if(HTMLArea._currentlyActiveEditor != this)
    {
        // We just deactivated an editor that wasn't marked as the currentlyActiveEditor

        return; // I think this should really be an error, there shouldn't be a situation where
        // an editor is deactivated without first being activated.  but it probably won't
        // hurt anything.
    }

    HTMLArea._currentlyActiveEditor = false;
};

HTMLArea.prototype.initIframe = function()
{
    this.disableToolbar();
    var doc = null;
    var editor = this;
    try
    {
        if (editor._iframe.contentDocument)
        {
            this._doc = editor._iframe.contentDocument;
        }
        else
        {
            this._doc = editor._iframe.contentWindow.document;
        }
        doc = this._doc;
        if (!doc) { // try later
            if (HTMLArea.is_gecko) {
                setTimeout(function() { editor.initIframe()}, 50);
                return false;
            } else {
                alert("ERROR: IFRAME can't be initialized.");
            }
        }
        // >MT: redraw after load is complete to remove redraw artifacts
        else
        setTimeout(function() { editor.forceRedraw()}, 50);
        // <MT
    }
    catch(e)
    { // try later
        setTimeout(function() { editor.initIframe()}, 50);
        // >MT: return on failure
        return false;
        // <MT
    }

    HTMLArea.freeLater(this, '_doc');
    // MT: doc.open() removed
    if (!editor.config.fullPage) {
        var html = "<html>\n";
        html += "<head>\n";
        html += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + editor.config.charSet + "\">\n";
        if(typeof editor.config.baseHref != 'undefined' && editor.config.baseHref != null)
        {
            html += "<base href=\"" + editor.config.baseHref + "\"/>\n";
        }
        html += "<style title=\"table borders\">"
        + ".htmtableborders, .htmtableborders td, .htmtableborders th {border : 1px dashed lightgrey ! important;} \n"
        + "</style>\n";
        html += "<style type=\"text/css\">"
        + "html, body { border: 0px; } \n"
        + "span.macro, span.macro ul, span.macro div, span.macro p {background : #CCCCCC;}\n"
        + "</style>\n";

        if(editor.config.pageStyle)
        {
            html += "<style type=\"text/css\">\n" + editor.config.pageStyle + "\n</style>";
        }

        if(typeof editor.config.pageStyleSheets !== 'undefined')
        {
            for(style_i = 0; style_i < editor.config.pageStyleSheets.length; style_i++)
            {
                if(editor.config.pageStyleSheets[style_i].length > 0)
                html += "<link rel=\"stylesheet\" type=\"text/css\" href=\"" + editor.config.pageStyleSheets[style_i] + "\">";
                //html += "<style> @import url('" + editor.config.pageStyleSheets[style_i] + "'); </style>\n";
            }
        }
        html += "</head>\n";
        html += "<body id='topic'>\n";
        html +=   editor.inwardHtml(editor._textArea.value);
        html += "</body>\n";
        html += "</html>";
    } else {
        var html = editor.inwardHtml(editor._textArea.value);
        if (html.match(HTMLArea.RE_doctype)) {
            editor.setDoctype(RegExp.$1);
            html = html.replace(HTMLArea.RE_doctype, "");
        }
    }
    doc.write(html);
    doc.close();

    // if we have multiple editors some bug in Mozilla makes some lose editing ability
    HTMLArea._addEvents
    (
    doc,
    ["mousedown"],
    function() { editor.activateEditor(); return true; }
    );


    // intercept some events; for updating the toolbar & keyboard handlers
    HTMLArea._addEvents
    (doc, ["keydown", "keypress", "mousedown", "mouseup", "drag"],
    function (event) {
        return editor._editorEvent(HTMLArea.is_ie ? editor._iframe.contentWindow.event : event);
    });

    // check if any plugins have registered refresh handlers
    for (var i in editor.plugins) {
        var plugin = editor.plugins[i].instance;
        HTMLArea.refreshPlugin(plugin);
    }

    // specific editor initialization
    if(typeof editor._onGenerate == "function") {
        editor._onGenerate();
    }

    // >MT: add this.editorLoaded
    if (typeof editor.editorLoaded == 'function')
    editor.editorLoaded();
    // <MT
};

// Switches editor mode; parameter can be "textmode" or "wysiwyg".  If no
// parameter was passed this function toggles between modes.
HTMLArea.prototype.setMode = function(mode) {
    if (typeof mode == "undefined") {
        mode = ((this._editMode == "textmode") ? "wysiwyg" : "textmode");
    }

    switch (mode) {
        case "textmode":
        {
            // >MT: use XHTML
            var html = this.outwardHtml(this.getXHTML());
            // <MT
            this.setHTML(html);

            // Hide the iframe
            this.deactivateEditor();
            this._iframe.style.display   = 'none';
            this._textArea.style.display = '';

            if (this.config.statusBar)
            {
                this._statusBarTree.style.display = "none";
                this._statusBarTextMode.style.display = "";
            }

            this.notifyOf('modechange', {'mode':'text'});
            break;
        }

        case "wysiwyg":
        {
            var html = this.inwardHtml(this.getHTML());
            this.deactivateEditor();
            this.setHTML(html);
            // >MT: use XHTML
            HTMLArea.makeXHTML(null, this.makeXHTMLContext(false));
            if (window.Widget)
                Widget.initializeEditor(this._doc, this);
            // <MT
            this._iframe.style.display   = '';
            this._textArea.style.display = "none";
            this.activateEditor();
            if (this.config.statusBar)
            {
                this._statusBarTree.style.display = "";
                this._statusBarTextMode.style.display = "none";
            }

            this.notifyOf('modechange', {'mode':'wysiwyg'});
            break;
        }

        default:
        {
            alert("Mode <" + mode + "> not defined!");
            return false;
        }
    }
    this._editMode = mode;
    // >MT: add this._OnMode
    if (typeof this._OnMode == "function")
    this._OnMode(mode);
    // <MT

    for (var i in this.plugins) {
        var plugin = this.plugins[i].instance;
        if (typeof plugin.onMode == "function") plugin.onMode(mode);
    }
};

HTMLArea.prototype.setFullHTML = function(html) {
    var save_multiline = RegExp.multiline;
    RegExp.multiline = true;
    if (html.match(HTMLArea.RE_doctype)) {
        this.setDoctype(RegExp.$1);
        html = html.replace(HTMLArea.RE_doctype, "");
    }
    RegExp.multiline = save_multiline;
    if (!HTMLArea.is_ie) {
        if (html.match(HTMLArea.RE_head))
        this._doc.getElementsByTagName("head")[0].innerHTML = RegExp.$1;
        if (html.match(HTMLArea.RE_body))
        this._doc.getElementsByTagName("body")[0].innerHTML = RegExp.$1;
    } else {
        var reac = this.editorIsActivated();
        if(reac) this.deactivateEditor();
        var html_re = /<html>((.|\n)*?)<\/html>/i;
        html = html.replace(html_re, "$1");
        this._doc.open();
        this._doc.write(html);
        // >MT: add topic ID
        this._doc.body.id = "topic";
        // <MT
        this._doc.close();
        if(reac) this.activateEditor();
        return true;
    }
};

/***************************************************
*  Category: PLUGINS
***************************************************/

// Create the specified plugin and register it with this HTMLArea
// return the plugin created to allow refresh when necessary
HTMLArea.prototype.registerPlugin = function() {
    var plugin = arguments[0];

    // We can only register plugins that have been succesfully loaded
    if
    (
    plugin == null
    || typeof plugin == 'undefined'
    || (typeof plugin == 'string' && eval('typeof ' + plugin) == 'undefined')
    ) return false;

    var args = [];
    for (var i = 1; i < arguments.length; ++i)
    args.push(arguments[i]);
    return this.registerPlugin2(plugin, args);
};

// this is the variant of the function above where the plugin arguments are
// already packed in an array.  Externally, it should be only used in the
// full-screen editor code, in order to initialize plugins with the same
// parameters as in the opener window.
HTMLArea.prototype.registerPlugin2 = function(plugin, args) {
    if (typeof plugin == "string")
    plugin = eval(plugin);
    if (typeof plugin == "undefined") {
        /* FIXME: This should never happen. But why does it do? */
        return false;
    }
    var obj = new plugin(this, args);
    if (obj) {
        var clone = {};
        var info = plugin._pluginInfo;
        for (var i in info)
        clone[i] = info[i];
        clone.instance = obj;
        clone.args = args;
        this.plugins[plugin._pluginInfo.name] = clone;
        return obj;
    } else
        alert("Can't register plugin " + plugin.toString() + ".");
};

// static function that loads the required plugin and lang file, based on the
// language loaded already for HTMLArea.  You better make sure that the plugin
// _has_ that language, otherwise shit might happen ;-)
HTMLArea.getPluginDir = function(pluginName) {
    return _editor_url + "plugins/" + pluginName;
};

HTMLArea.loadPlugin = function(pluginName, callback) {
    // Might already be loaded
    if(eval('typeof ' + pluginName) != 'undefined')
    {
        if(callback)
        {
            callback(pluginName);
        }
        return true;
    }

    var dir = this.getPluginDir(pluginName);
    var plugin = pluginName.replace(/([a-z])([A-Z])([a-z])/g,
    function (str, l1, l2, l3) {
        return l1 + "-" + l2.toLowerCase() + l3;
    }).toLowerCase() + ".js";
    var plugin_file = dir + "/" + plugin;

    if(callback)
    {
        HTMLArea._loadback(plugin_file, function() { callback(pluginName); });
    }
    else
    {
        document.write("<script type='text/javascript' src='" + plugin_file + "'></script>");
    }
    return false;
};

HTMLArea._pluginLoadStatus = { };
HTMLArea.loadPlugins = function(plugins, callbackIfNotReady)
{
    // Rip the ones that are loaded and look for ones that have failed
    var retVal = true;
    var nuPlugins = HTMLArea.cloneObject(plugins);
    while(nuPlugins.length)
    {
        var p = nuPlugins.pop();
        if(typeof HTMLArea._pluginLoadStatus[p] == 'undefined')
        {
            // Load it
            HTMLArea._pluginLoadStatus[p] = 'loading';
            HTMLArea.loadPlugin(p,
            function(plugin)
            {
                if(eval('typeof ' + plugin) != 'undefined')
                {
                    HTMLArea._pluginLoadStatus[plugin] = 'ready';
                }
                else
                {
                    // Actually, this won't happen, because if the script fails
                    // it will throw an exception preventing the callback from
                    // running.  This will leave it always in the "loading" state
                    // unfortunatly that means we can't fail plugins gracefully
                    // by just skipping them.
                    HTMLArea._pluginLoadStatus[plugin] = 'failed';
                }
            }
            );
            retVal = false;
        }
        else
        {
            switch(HTMLArea._pluginLoadStatus[p])
            {
                case 'failed':
                case 'ready' :
                break;

                case 'loading':
                default       :
                retVal = false;
                break;
            }
        }
    }

    if(retVal) return true; // All done, just return

    // Waiting on plugins to load, return false now and come back a bit later
    // if we have to callback
    if(callbackIfNotReady)
    {
        setTimeout(function() { if(HTMLArea.loadPlugins(plugins, callbackIfNotReady)) callbackIfNotReady(); }, 150);
    }
    return retVal;
};

// refresh plugin by calling onGenerate or onGenerateOnce method.
HTMLArea.refreshPlugin = function(plugin) {
    if (typeof plugin.onGenerate == "function")
    plugin.onGenerate();
    if (typeof plugin.onGenerateOnce == "function") {
        plugin.onGenerateOnce();
        plugin.onGenerateOnce = null;
    }
};

HTMLArea.loadStyle = function(style, plugin) {
    var url = _editor_url || '';
    if (typeof plugin != "undefined") {
        url += "plugins/" + plugin + "/";
    }
    url += style;
    if (/^\//.test(style))
    url = style;
    var head = document.getElementsByTagName("head")[0];
    var link = document.createElement("link");
    link.rel = "stylesheet";
    link.href = url;
    head.appendChild(link);
    //document.write("<style type='text/css'>@import url(" + url + ");</style>");
};
HTMLArea.loadStyle(typeof _editor_css == "string" ? _editor_css : "htmlarea.css");

/***************************************************
*  Category: EDITOR UTILITIES
***************************************************/

HTMLArea.prototype.debugTree = function() {
    var ta = document.createElement("textarea");
    ta.style.width = "100%";
    ta.style.height = "20em";
    ta.value = "";
    function debug(indent, str) {
        for (; --indent >= 0;)
        ta.value += " ";
        ta.value += str + "\n";
    };
    function _dt(root, level) {
        var tag = root.tagName.toLowerCase(), i;
        var ns = HTMLArea.is_ie ? root.scopeName : root.prefix;
        debug(level, "- " + tag + " [" + ns + "]");
        for (i = root.firstChild; i; i = i.nextSibling)
        if (i.nodeType == 1)
        _dt(i, level + 2);
    };
    _dt(this._doc.body, 0);
    document.body.appendChild(ta);
};

HTMLArea.getInnerText = function(el) {
    // >MT: use faster native function
    if (HTMLArea.is_ie)
    return el.nodeType == 3 ? el.nodeValue : el.innerText;
    // >MT: This crashes FF 1.0.x
    // else if (HTMLArea.is_gecko)
    //   return el.textContent;
    // <MT
    // <MT
    // >MT: handle text nodes
    var txt = el.nodeType == 3 ? el.data : '', i;
    // <MT
    for (i = el.firstChild; i; i = i.nextSibling) {
        if (i.nodeType == 3)
        txt += i.data;
        else if (i.nodeType == 1)
        txt += HTMLArea.getInnerText(i);
    }
    return txt;
};

HTMLArea.prototype._wordClean = function() {
    var
    editor = this,
    stats = {
        empty_tags : 0,
        mso_class  : 0,
        mso_style  : 0,
        mso_xmlel  : 0,
        orig_len   : this._doc.body.innerHTML.length,
        T          : (new Date()).getTime()
    },
    stats_txt = {
        empty_tags : "Empty tags removed: ",
        mso_class  : "MSO class names removed: ",
        mso_style  : "MSO inline style removed: ",
        mso_xmlel  : "MSO XML elements stripped: "
    };
    function showStats() {
        var txt = "HTMLArea word cleaner stats: \n\n";
        for (var i in stats)
        if (stats_txt[i])
        txt += stats_txt[i] + stats[i] + "\n";
        txt += "\nInitial document length: " + stats.orig_len + "\n";
        txt += "Final document length: " + editor._doc.body.innerHTML.length + "\n";
        txt += "Clean-up took " + (((new Date()).getTime() - stats.T) / 1000) + " seconds";
        alert(txt);
    };
    function clearClass(node) {
        var newc = node.className.replace(/(^|\s)mso.*?(\s|$)/ig, ' ');
        if (newc != node.className) {
            node.className = newc;
            if (!/\S/.test(node.className)) {
                node.removeAttribute("className");
                ++stats.mso_class;
            }
        }
    };
    function clearStyle(node) {
        var declarations = node.style.cssText.split(/\s*;\s*/);
        for (var i = declarations.length; --i >= 0;)
        if (/^mso|^tab-stops/i.test(declarations[i]) ||
        /^margin\s*:\s*0..\s+0..\s+0../i.test(declarations[i])) {
            ++stats.mso_style;
            declarations.splice(i, 1);
        }
        node.style.cssText = declarations.join("; ");
    };
    function stripTag(el) {
        if (HTMLArea.is_ie)
        el.outerHTML = HTMLArea.htmlEncode(el.innerText);
        else {
            var txt = document.createTextNode(HTMLArea.getInnerText(el));
            el.parentNode.insertBefore(txt, el);
            HTMLArea.removeFromParent(el);
        }
        ++stats.mso_xmlel;
    };
    function checkEmpty(el) {
        if (/^(a|span|b|strong|i|em|font)$/i.test(el.tagName) &&
        !el.firstChild) {
            HTMLArea.removeFromParent(el);
            ++stats.empty_tags;
        }
    };
    function parseTree(root) {
        var tag = root.tagName.toLowerCase(), i, next;
        if ((HTMLArea.is_ie && root.scopeName != 'HTML') || (!HTMLArea.is_ie && /:/.test(tag))) {
            stripTag(root);
            return false;
        } else {
            clearClass(root);
            clearStyle(root);
            for (i = root.firstChild; i; i = next) {
                next = i.nextSibling;
                if (i.nodeType == 1 && parseTree(i))
                checkEmpty(i);
            }
        }
        return true;
    };
    parseTree(this._doc.body);
    // showStats();
    // this.debugTree();
    // this.setHTML(this.getHTML());
    // this.setHTML(this.getInnerHTML());
    // this.forceRedraw();
    this.updateToolbar();
};

HTMLArea.prototype._clearFonts = function() {
    var D = this.getInnerHTML();

    if(confirm(HTMLArea._lc("Would you like to clear font typefaces?")))
    {
        D = D.replace(/face="[^"]*"/gi, '');
    D = D.replace(/font-family:[^;}"']+;?/gi, '');
  }

  if(confirm(HTMLArea._lc("Would you like to clear font sizes?")))
  {
    D = D.replace(/size="[^"]*"/gi, '');
    D = D.replace(/font-size:[^;}"']+;?/gi, '');
    }

    if(confirm(HTMLArea._lc("Would you like to clear font colours?")))
    {
        D = D.replace(/color="[^"]*"/gi, '');
    D = D.replace(/([^-])color:[^;}"']+;?/gi, '$1');
  }

  D = D.replace(/(style|class)="\s*"/gi, '');
  D = D.replace(/<(font|span)\s*>/gi, '');
  this.setHTML(D);
  this.updateToolbar();
};

HTMLArea.prototype._splitBlock = function()
{
  this._doc.execCommand('formatblock', false, 'div');
};

HTMLArea.prototype.forceRedraw = function() {
  // >MT: handle if called before body is loaded
  if (this._doc == null || this._doc.body == null)
    return;
  // <MT
  this._doc.body.style.visibility = "hidden";
  this._doc.body.style.visibility = "visible";
  // this._doc.body.innerHTML = this.getInnerHTML();
};

// focuses the iframe window.  returns a reference to the editor document.
HTMLArea.prototype.focusEditor = function() {
  switch (this._editMode) {
    // notice the try { ... } catch block to avoid some rare exceptions in FireFox
    // (perhaps also in other Gecko browsers). Manual focus by user is required in
      // case of an error. Somebody has an idea?
    case "wysiwyg" :
    try
    {
      // We don't want to focus the field unless at least one field has been activated.
        if(HTMLArea._someEditorHasBeenActivated)
        {
            this.activateEditor(); // Ensure *this* editor is activated
            this._iframe.contentWindow.focus(); // and focus it
        }
    } catch (e) {} break;
    case "textmode": try { this._textArea.focus() } catch (e) {} break;
    default: alert("ERROR: mode " + this._editMode + " is not defined");
}
return this._doc;
};

// takes a snapshot of the current text (for undo)
HTMLArea.prototype._undoTakeSnapshot = function() {
    ++this._undoPos;
    if (this._undoPos >= this.config.undoSteps) {
        // remove the first element
        this._undoQueue.shift();
        --this._undoPos;
    }
    // use the fasted method (getInnerHTML);
    var take = true;
    var txt = this.getInnerHTML();
    if (this._undoPos > 0)
    take = (this._undoQueue[this._undoPos - 1] != txt);
    if (take) {
        this._undoQueue[this._undoPos] = txt;
    } else {
        this._undoPos--;
    }
};

HTMLArea.prototype.undo = function() {
    if (this._undoPos > 0) {
        var txt = this._undoQueue[--this._undoPos];
        if (txt) this.setHTML(txt);
        else ++this._undoPos;
    }
};

HTMLArea.prototype.redo = function() {
    if (this._undoPos < this._undoQueue.length - 1) {
        var txt = this._undoQueue[++this._undoPos];
        if (txt) this.setHTML(txt);
        else --this._undoPos;
    }
};

HTMLArea.prototype.disableToolbar = function(except)
{
    if(this._timerToolbar) clearTimeout(this._timerToolbar);
    if(typeof except == 'undefined')
    {
        except = [ ];
    }
    else if(typeof except != 'object')
    {
        except = [except];
    }

    for (var i in this._toolbarObjects)
    {
        var btn = this._toolbarObjects[i];
        if(except.contains(i))
        {
            continue;
        }
        btn.state("enabled", false);
    }
};

HTMLArea.prototype.enableToolbar = function()
{
    this.updateToolbar();
};

if(!Array.prototype.contains)
{
    Array.prototype.contains = function(needle)
    {
        var haystack = this;
        for(var i = 0; i < haystack.length; i++)
        {
            if(needle == haystack[i]) return true;
        }

        return false;
    };
}

if(!Array.prototype.indexOf)
{
    Array.prototype.indexOf = function(needle)
    {
        var haystack = this;
        for(var i = 0; i < haystack.length; i++)
        {
            if(needle == haystack[i]) return i;
        }

        return null;
    };
}


// updates enabled/disable/active state of the toolbar elements
HTMLArea.prototype.updateToolbar = function(noStatus) {
    var doc = this._doc;
    var text = (this._editMode == "textmode");
    var ancestors = null;
    if (!text) {
        ancestors = this.getAllAncestors();
        if (this.config.statusBar && !noStatus) {
            this._statusBarTree.innerHTML = HTMLArea._lc("Path") + ": "; // clear
            for (var i = ancestors.length; --i >= 0;) {
                var el = ancestors[i];
                if (!el) {
                    // hell knows why we get here; this
                    // could be a classic example of why
                    // it's good to check for conditions
                    // that are impossible to happen ;-)
                    continue;
                }
                var a = document.createElement("a");
                a.href = "javascript:void(0)";
                a.el = el;
                a.editor = this;
                HTMLArea.addDom0Event(a, 'click', function() {
                    this.blur();
                    this.editor.selectNodeContents(this.el);
                    this.editor.updateToolbar(true);
                    return false;
                });
                HTMLArea.addDom0Event(a, 'contextmenu',  function() {
                    // TODO: add context menu here
                    this.blur();
                    // >MT: show HTML instead of CSS on status right click
                    var info = "HTML:\n";
                    /* DEBUG
                    info += HTMLArea.getOuterHTML(this.el);
                    info += "\ngetHTML:\n";
                    /**/
                    info += HTMLArea.getHTMLWrapper(this.el,true,editor ? editor : this.editor);
                    // <MT
                    alert(info);
                    return false;
                });
                var txt = el.tagName.toLowerCase();
                a.title = el.style.cssText;
                if (el.id) {
                    txt += "#" + el.id;
                }
                if (el.className) {
                    txt += "." + el.className;
                }
                a.appendChild(document.createTextNode(txt));
                this._statusBarTree.appendChild(a);
                if (i != 0) {
                    this._statusBarTree.appendChild(document.createTextNode(String.fromCharCode(0xbb)));
                }
            }
        }
    }

    for (var i in this._toolbarObjects) {
        var btn = this._toolbarObjects[i];
        var cmd = i;
        var inContext = true;
        if (btn.context && !text) {
            inContext = false;
            var context = btn.context;
            var attrs = [];
            if (/(.*)\[(.*?)\]/.test(context)) {
                context = RegExp.$1;
                attrs = RegExp.$2.split(",");
            }
            context = context.toLowerCase();
            var match = (context == "*");
            for (var k = 0; k < ancestors.length; ++k) {
                if (!ancestors[k]) {
                    // the impossible really happens.
                    continue;
                }
                if (match || (ancestors[k].tagName.toLowerCase() == context)) {
                    inContext = true;
                    for (var ka = 0; ka < attrs.length; ++ka) {
                        if (!eval("ancestors[k]." + attrs[ka])) {
                            inContext = false;
                            break;
                        }
                    }
                    if (inContext) {
                        break;
                    }
                }
            }
        }
        btn.state("enabled", (!text || btn.text) && inContext);
        if (typeof cmd == "function") {
            continue;
        }
        // look-it-up in the custom dropdown boxes
        var dropdown = this.config.customSelects[cmd];
        // >MT: disallow formatting in header tags
        var isInHeader = this._isInAny(ancestors,["h1","h2","h3","h4","h5","h6"]);
        // <MT
        if ((!text || btn.text) && (typeof dropdown != "undefined")) {
            dropdown.refresh(this);
            continue;
        }
        switch (cmd)
        {
            case "fontname":
            case "fontsize":
            // >MT: add fontstyles
            case "fontstyles":
            // <MT
            {
                // >MT: add relative font sizes and font styles
                if (!text) if (isInHeader) btn.state("enabled", false);
                else {
                    if (cmd == 'fontstyles' && typeof fontStyles != 'undefined')
                    var value = fontStyles(this);
                    else if (cmd == 'fontsize' && typeof fontSizes != 'undefined')
                    var value = fontSizes(this);
                    else
                    // <MT
                    var value = ("" + doc.queryCommandValue(cmd)).toLowerCase();

                    if (!value) {
                        btn.element.selectedIndex = 0;
                        break;
                    }

                    // HACK -- retrieve the config option for this
                    // combo box.  We rely on the fact that the
                    // variable in config has the same name as
                    // button name in the toolbar.
                    var options = this.config[cmd];
                    var k = 0;
                    // >MT: don't use exception handling
                    var found = false;
                    // <MT
                    for (var j in options)
                    {
                        // FIXME: the following line is scary.
                        if ((j.toLowerCase() == value) || (options[j].substr(0, value.length).toLowerCase() == value))
                        {
                            btn.element.selectedIndex = k;
                            // >MT: don't use exception handling
                            found = true;
                            break;
                            // <MT
                        }
                        ++k;
                    }
                    // >MT: don't use exception handling
                    if (!found)
                    // <MT
                    btn.element.selectedIndex = 0;
                    // >MT: don't use exception handling
                }
                // <MT
            }
            break;

            // It's better to search for the format block by tag name from the
            //  current selection upwards, because IE has a tendancy to return
            //  things like 'heading 1' for 'h1', which breaks things if you want
            //  to call your heading blocks 'header 1'.  Stupid MS.
            case "formatblock"  :
            {
                // >MT: disallow blockformat in lists and tables
                if (this._isInAny(ancestors,["ul","ol","table"])) {
                    //btn.state("enabled", false);
                    for (var i = 0; i < ancestors.length; ++i) {
                        var a = ancestors[i];
                        if (!a)
                            continue;
                        var tag = a.tagName.toLowerCase();
                        if (/ul|ol|table/i.test(tag))
                            break;
                        if (tag == 'span' && /header_/i.test(a.className)) {
                            var level = parseInt(a.className.substring(7));
                            btn.element.selectedIndex = level;
                            break;
                        }
                    }
                } else {
                    // <MT
                    var blocks = [ ];
                    // >MT: fix <p> case
                    var hasP = 0;
                    // <MT
                    for(var i in this.config['formatblock'])
                    {
                        // >MT: fix <p> case
                        var b = this.config['formatblock'][i];
                        if (b.toLowerCase() != "p")
                        blocks[blocks.length] = b;
                        else {
                            hasP = blocks.length;
                            blocks[blocks.length] = '-p-';
                        }
                        // <MT
                    }

                    // >MT: fix <p> case
                    var sel = this._getSelection();
                    var deepestAncestor = this._getFirstAncestor(sel, blocks);
                    if(!deepestAncestor && hasP) {
                        blocks[hasP] = "p";
                        deepestAncestor = this._getFirstAncestor(sel, ["p"]);
                    }
                    // <MT
                    if(deepestAncestor)
                    {
                        for(var x= 0; x < blocks.length; x++)
                        {
                            if(blocks[x].toLowerCase() == deepestAncestor.tagName.toLowerCase())
                            {
                                btn.element.selectedIndex = x;
                            }
                        }
                    }
                    else
                    {
                        btn.element.selectedIndex = 0;
                    }
                }
                // >MT: disallow blockformat in lists and tables
            }
            // <MT
            break;

            case "textindicator":
            if (!text) {
                try {with (btn.element.style) {
                    backgroundColor = HTMLArea._makeColor(
                    doc.queryCommandValue(HTMLArea.is_ie ? "backcolor" : "hilitecolor"));
                    if (/transparent/i.test(backgroundColor)) {
                        // Mozilla
                        backgroundColor = HTMLArea._makeColor(doc.queryCommandValue("backcolor"));
                    }
                    color = HTMLArea._makeColor(doc.queryCommandValue("forecolor"));
                    fontFamily = doc.queryCommandValue("fontname");
                    fontWeight = doc.queryCommandState("bold") ? "bold" : "normal";
                    fontStyle = doc.queryCommandState("italic") ? "italic" : "normal";
                }} catch (e) {
                    // alert(e + "\n\n" + cmd);
                }
            }
            break;
            case "htmlmode": btn.state("active", text); break;
            case "lefttoright":
            case "righttoleft":
            var el = this.getParentElement();
            while (el && !HTMLArea.isBlockElement(el))
            el = el.parentNode;
            if (el)
            btn.state("active", (el.style.direction == ((cmd == "righttoleft") ? "rtl" : "ltr")));
            break;
            default:
            // >MT: improve performance
            if (cmd.indexOf('insert') < 0)
            // <MT
            cmd = cmd.replace(/(un)?orderedlist/i, "insert$1orderedlist");

            // >MT: disallow formating in headers
            if (isInHeader && typeof HTMLArea.RE_noHeaderCmd != "undefined" && HTMLArea.RE_noHeaderCmd.test(cmd))
            btn.state("enabled", false);
            // <MT

            // >MT: remove exceptions in FF
            var check = HTMLArea.is_ie || /^(bold|italic|underline|strikethrough|subscript|superscript|justify.*|insert(un)?orderedlist|overwrite)$/.test(cmd);
            // <MT
            try {
                // >MT: remove exceptions in FF
                if (check || text)
                // <MT
                btn.state("active", (!text && doc.queryCommandState(cmd)));
            } catch (e) {}
        }
    }
    // take undo snapshots
    if (this._customUndo && !this._timerUndo) {
        this._undoTakeSnapshot();
        var editor = this;
        this._timerUndo = setTimeout(function() {
            editor._timerUndo = null;
        }, this.config.undoTimeout);
    }

    // Insert a space in certain locations, this is just to make editing a little
    // easier (to "get out of" tags), it's not essential.
    // TODO: Make this work for IE?
    // TODO: Perhaps should use a plain space character, I'm not sure.
    //  OK, I've disabled this temporarily, to be honest, I can't rightly remember what the
    //  original problem was I was trying to solve with it.  I think perhaps that EnterParagraphs
    //  might solve the problem, whatever the hell it was.  I'm going senile, I'm sure.
    if(0 && HTMLArea.is_gecko)
    {
        var s = this._getSelection();
        // If the last character in the last text node of the parent tag
        // and the parent tag is not a block tag
        if(s && s.isCollapsed && s.anchorNode
        && s.anchorNode.parentNode.tagName.toLowerCase() != 'body'
        && s.anchorNode.nodeType == 3 && s.anchorOffset == s.anchorNode.length
        && !
        (   s.anchorNode.parentNode.nextSibling
        && s.anchorNode.parentNode.nextSibling.nodeType == 3
        )
        && !HTMLArea.isBlockElement(s.anchorNode.parentNode)
        )
        {
            // Insert hair-width-space after the close tag if there isn't another text node on the other side
            // It could also work with zero-width-space (\u200B) but I don't like it so much.
            // Perhaps this won't work well in various character sets and we should use plain space (20)?
            try
            {
                s.anchorNode.parentNode.parentNode.insertBefore
                (this._doc.createTextNode('\t'), s.anchorNode.parentNode.nextSibling);
            }
            catch(e)
            {
                // Disregard
            }
        }
    }

    // check if any plugins have registered refresh handlers
    for (var i in this.plugins) {
        var plugin = this.plugins[i].instance;
        if (typeof plugin.onUpdateToolbar == "function")
        plugin.onUpdateToolbar();
    }


};

/** Returns a node after which we can insert other nodes, in the current
* selection.  The selection is removed.  It splits a text node, if needed.
*/
HTMLArea.prototype.insertNodeAtSelection = function(toBeInserted) {
    if (!HTMLArea.is_ie) {
        var sel = this._getSelection();
        var range = this._createRange(sel);
        // remove the current selection
        sel.removeAllRanges();
        range.deleteContents();
        var node = range.startContainer;
        var pos = range.startOffset;
        switch (node.nodeType) {
            case 3: // Node.TEXT_NODE
            // we have to split it at the caret position.
            if (toBeInserted.nodeType == 3) {
                // do optimized insertion
                node.insertData(pos, toBeInserted.data);
                range = this._createRange();
                range.setEnd(node, pos + toBeInserted.length);
                range.setStart(node, pos + toBeInserted.length);
                sel.addRange(range);
            } else {
                node = node.splitText(pos);
                var selnode = toBeInserted;
                if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
                    selnode = selnode.firstChild;
                }
                node.parentNode.insertBefore(toBeInserted, node);
                this.selectNodeContents(selnode);
                this.updateToolbar();
            }
            break;
            case 1: // Node.ELEMENT_NODE
            var selnode = toBeInserted;
            if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
                selnode = selnode.firstChild;
            }
            node.insertBefore(toBeInserted, node.childNodes[pos]);
            this.selectNodeContents(selnode);
            this.updateToolbar();
            break;
        }
    } else {
        return null;  // this function not yet used for IE <FIXME>
    }
};

// Returns the deepest node that contains both endpoints of the selection.
// >MT: add range argument
HTMLArea.prototype.getParentElement = function(sel,range) {
    // <MT
    if(typeof sel == 'undefined')
    {
        sel = this._getSelection();
    }
    // >MT: add range argument
    if(typeof range == 'undefined') {
        range = this._createRange(sel);
    }
    // <MT
    if (HTMLArea.is_ie) {
        switch (sel.type) {
            case "Text":
            case "None":
            // It seems that even for selection of type "None",
            // there _is_ a parent element and it's value is not
            // only correct, but very important to us.  MSIE is
            // certainly the buggiest browser in the world and I
            // wonder, God, how can Earth stand it?
                return range ? range.parentElement() : this._doc.body;
            case "Control":
                return range.item(0);
            default:
                return this._doc.body;
        }
    } else try {
        var p = range.commonAncestorContainer;
        if (!range.collapsed && range.startContainer == range.endContainer &&
        range.startOffset - range.endOffset <= 1 && range.startContainer.hasChildNodes())
        p = range.startContainer.childNodes[range.startOffset];
        /*
        alert(range.startContainer + ":" + range.startOffset + "\n" +
        range.endContainer + ":" + range.endOffset);
        */
        while (p.nodeType == 3) {
            p = p.parentNode;
        }
        return p;
    } catch (e) {
        return null;
    }
};

// Returns an array with all the ancestor nodes of the selection.
HTMLArea.prototype.getAllAncestors = function() {
    var p = this.getParentElement();
    var a = [];
    while (p && (p.nodeType == 1) && (p.tagName.toLowerCase() != 'body')) {
        a.push(p);
        p = p.parentNode;
    }
    a.push(this._doc.body);
    return a;
};

// Returns the deepest ancestor of the selection that is of the current type
HTMLArea.prototype._getFirstAncestor = function(sel, types)
{
    var prnt = this._activeElement(sel);
    if(prnt == null)
    {
        try
        {
            prnt = (HTMLArea.is_ie ? this._createRange(sel).parentElement() : this._createRange(sel).commonAncestorContainer);
        }
        catch(e)
        {
            return null;
        }
    }

    if(typeof types == 'string')
    {
        types = [types];
    }

    while(prnt)
    {
        if(prnt.nodeType == 1)
        {
            if(types == null) return prnt;
            if(types.contains(prnt.tagName.toLowerCase()))
            {

                return prnt;
            }
            if(prnt.tagName.toLowerCase() == 'body') break;
            if(prnt.tagName.toLowerCase() == 'table') break;
        }
        prnt = prnt.parentNode;
    }

    return null;
};

/**
* Returns the selected element, if any.  That is,
* the element that you have last selected in the "path"
* at the bottom of the editor, or a "control" (eg image)
*
* @returns null | element
*/
HTMLArea.prototype._activeElement = function(sel)
{
    if(sel == null) return null;
    if(this._selectionEmpty(sel)) return null;

    if(HTMLArea.is_ie)
    {
        if(sel.type.toLowerCase() == "control")
        {
            return sel.createRange().item(0);
        }
        else
        {

            // If it's not a control, then we need to see if
            // the selection is the _entire_ text of a parent node
            // (this happens when a node is clicked in the tree)
            var range = sel.createRange();
            // >MT: add range argument
            var p_elm = this.getParentElement(sel,range);
            // <MT
            if(p_elm.innerHTML == range.htmlText)
            {
                return p_elm;
            }
            /*
            if(p_elm)
            {
            var p_rng = this._doc.body.createTextRange();
            p_rng.moveToElementText(p_elm);
            if(p_rng.isEqual(range))
            {
            return p_elm;
            }
            }

            if(range.parentElement())
            {
            var prnt_range = this._doc.body.createTextRange();
            prnt_range.moveToElementText(range.parentElement());
            if(prnt_range.isEqual(range))
            {
            return range.parentElement();
            }
            }
            */
            return null;
        }
    }
    else
    {
        // For Mozilla we just see if the selection is not collapsed (something is selected)
        // and that the anchor (start of selection) is an element.  This might not be totally
        // correct, we possibly should do a simlar check to IE?
        if(! sel.isCollapsed)
        {
            if(sel.anchorNode.childNodes.length > sel.anchorOffset && sel.anchorNode.childNodes[sel.anchorOffset].nodeType == 1)
            {
                return sel.anchorNode.childNodes[sel.anchorOffset];
            }
            else if(sel.anchorNode.nodeType == 1)
            {
                return sel.anchorNode;
            }
            else
            {
                return sel.anchorNode.parentNode;
            }
        }
        return null;
    }
};


HTMLArea.prototype._selectionEmpty = function(sel)
{
    if(!sel) return true;

    if(HTMLArea.is_ie)
    {
        var range = this._createRange(sel);
        return range ? range.htmlText == '' : true;
    }
    else if(typeof sel.isCollapsed != 'undefined')
    {
        return sel.isCollapsed;
    }

    return true;
};

HTMLArea.prototype._getAncestorBlock = function(sel)
{
    // Scan upwards to find a block level element that we can change or apply to
    var prnt = (HTMLArea.is_ie ? this._createRange(sel).parentElement : this._createRange(sel).commonAncestorContainer);

    while(prnt && (prnt.nodeType == 1))
    {
        switch(prnt.tagName.toLowerCase())
        {
            case 'div' :
            case 'p'   :
            case 'address'    :
            case 'blockquote' :
            case 'center'  :
            case 'del'     :
            case 'ins'     :
            case 'pre'     :
            case 'h1'      :
            case 'h2'      :
            case 'h3'      :
            case 'h4'      :
            case 'h5'      :
            case 'h6'      :
            case 'h7'      :
            // Block Element
            return prnt;

            case 'body'     :
            case 'noframes' :
            case 'dd'  :
            case 'li'  :
            case 'th'  :
            case 'td'  :
            case 'noscript' :
            // Halting element (stop searching)
            return null;

            default :
            // Keep lookin
            break;
        }
    }

    return null;
};

HTMLArea.prototype._createImplicitBlock = function(type)
{
    // expand it until we reach a block element in either direction
    // then wrap the selection in a block and return
    var sel = this._getSelection();
    if(HTMLArea.is_ie)
    {
        sel.empty();
    }
    else
    {
        sel.collapseToStart();
    }

    var rng = this._createRange(sel);

    // Expand UP

    // Expand DN
};

HTMLArea.prototype._formatBlock = function(block_format)
{
    var ancestors = this.getAllAncestors();
    var apply_to = null;

    // Block format can be a tag followed with class defs
    //  eg div.blue.left
    var target_tag = null;
    var target_classNames = [ ];

    if(block_format.indexOf('.') >= 0)
    {
        target_tag = block_format.substr(0, block_format.indexOf('.')).toLowerCase();;

        target_classNames = block_format.substr(block_format.indexOf('.'), block_format.length - block_format.indexOf('.')).replace(/\./g, '').replace(/^\s*/, '').replace(/\s*$/, '').split(' ');
    }
    else
    {
        target_tag = block_format.toLowerCase();
    }

    var sel = this._getSelection();
    var rng = this._createRange(sel);
    var apply_to = null;

    if(HTMLArea.is_gecko)
    {
        if(sel.isCollapsed)
        {
            // With no selection we want to apply to the whole contents of the ancestor block
            apply_to = this._getAncestorBlock(sel);
            if(apply_to == null)
            {
                // If there wasn't an ancestor, make one.
                apply_to = this._createImplicitBlock(sel, target_tag);
            }
        }
        else
        {
            // With a selection it's more tricky
            switch(target_tag)
            {

                case 'h1'      :
                case 'h2'      :
                case 'h3'      :
                case 'h4'      :
                case 'h5'      :
                case 'h6'      :
                case 'h7'      :
                apply_to = [ ];
                var search_tags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7'];
                for(var y = 0; y < search_tags.length; y++)
                {
                    var headers = this._doc.getElementsByTagName(search_tag[y]);
                    for(var x = 0; x < headers.length; x++)
                    {
                        if(sel.containsNode(headers[x]))
                        {
                            apply_to[apply_to.length] = headers[x];
                        }
                    }
                }
                if(apply_to.length > 0) break;
                // If there wern't any in the selection drop through
                case 'div' :
                apply_to = this._doc.createElement(target_tag);
                apply_to.appendChild(rng.extractContents());
                rng.insertNode(apply_to);
                break;

                case 'p'   :
                case 'center'  :
                case 'pre' :
                case 'ins' :
                case 'del' :
                case 'blockquote' :
                case 'address'    :
                apply_to = [ ];
                var paras = this._doc.getElementsByTagName(target_tag);
                for(var x = 0; x < paras.length; x++)
                {
                    if(sel.containsNode(paras[x]))
                    {
                        apply_to[apply_to.length] = paras[x];
                    }
                }

                if(apply_to.length == 0)
                {
                    sel.collapseToStart();
                    return this._formatBlock(block_format);
                }
                break;
            }
        }
    }

};

// Selects the contents inside the given node
HTMLArea.prototype.selectNodeContents = function(node, pos) {
    this.focusEditor();
    this.forceRedraw();
    var range;
    var collapsed = typeof pos == "undefined" ? true : false;
    if (HTMLArea.is_ie) {
        // Tables and Images get selected as "objects" rather than the text contents
        if(collapsed && node.tagName && node.tagName.toLowerCase().match(/table|img|input|select|textarea/))
        {
            range = this._doc.body.createControlRange();
            range.add(node);
        }
        else
        {
            range = this._doc.body.createTextRange();
            range.moveToElementText(node);
            //(collapsed) && range.collapse(pos);
        }
        range.select();
    } else {
        var sel = this._getSelection();
        range = this._doc.createRange();
        // Tables and Images get selected as "objects" rather than the text contents
        if(collapsed && node.tagName && node.tagName.toLowerCase().match(/table|img|input|textarea|select/))
        {
            range.selectNode(node);
        }
        else
        {
            range.selectNodeContents(node);
            //(collapsed) && range.collapse(pos);
        }
        sel.removeAllRanges();
        sel.addRange(range);
    }
};

/** Call this function to insert HTML code at the current position.  It deletes
* the selection, if any.
*/
HTMLArea.prototype.insertHTML = function(html) {
    var sel = this._getSelection();
    var range = this._createRange(sel);
    if (HTMLArea.is_ie) {
        // >MT: add error handling
        if (range.parentElement().document != this._doc) {
            alert('Insertion point was not detected within the editor. Please try again and ensure your cursors insertion point remains within the editable region.');
            return;
        }
        // <MT
        range.pasteHTML(html);
    } else {
        // construct a new document fragment with the given HTML
        var fragment = this._doc.createDocumentFragment();
        var div = this._doc.createElement("div");
        div.innerHTML = html;
        while (div.firstChild) {
            // the following call also removes the node from div
            fragment.appendChild(div.firstChild);
        }
        // this also removes the selection
        var node = this.insertNodeAtSelection(fragment);
    }
};

/**
*  Call this function to surround the existing HTML code in the selection with
*  your tags.  FIXME: buggy!  This function will be deprecated "soon".
*/
HTMLArea.prototype.surroundHTML = function(startTag, endTag) {
    var html = this.getSelectedHTML();
    // the following also deletes the selection
    this.insertHTML(startTag + html + endTag);
};

/// Retrieve the selected block
HTMLArea.prototype.getSelectedHTML = function() {
    var sel = this._getSelection();
    var range = this._createRange(sel);
    var existing = null;
    if (HTMLArea.is_ie) {
        existing = range.htmlText;
    } else {
        existing = HTMLArea.getHTML(range.cloneContents(), false, this);
    }
    return existing;
};

/// Return true if we have some selection
HTMLArea.prototype.hasSelectedText = function() {
    // FIXME: come _on_ mishoo, you can do better than this ;-)
    return this.getSelectedHTML() != '';
};

HTMLArea.prototype._createLink = function(link) {
    var editor = this;
    var outparam = null;
    editor.focusEditor();
    if (typeof link == "undefined") {
        link = this.getParentElement();
        if (link) {
            while (link && !/^a$/i.test(link.tagName))
            link = link.parentNode;
        }
    }
    if (!link) {
        var sel = editor._getSelection();
        var range = editor._createRange(sel);
        var compare = 0;
        if (HTMLArea.is_ie) {
            if(sel.type == "Control")
            {
                compare = range.length;
            }
            else
            {
                compare = range.compareEndPoints("StartToEnd", range);
            }
        } else {
            compare = range.compareBoundaryPoints(range.START_TO_END, range);
        }
        if (compare == 0) {
            alert(HTMLArea._lc("You need to select some text before creating a link"));
            return;
        }
        outparam = {
            f_href : '',
            f_title : '',
            f_target : '',
            f_usetarget : editor.config.makeLinkShowsTarget
        };
    } else
    outparam = {
        f_href   : HTMLArea.is_ie ? editor.stripBaseURL(link.href) : link.getAttribute("href"),
        f_title  : link.title,
        f_target : link.target,
        f_usetarget : editor.config.makeLinkShowsTarget
    };
    this._popupDialog(600, 451, editor.config.URIs["link"], function(param) {
        if (!param)
        return false;
        var a = link;
        if (!a) try {
            editor._doc.execCommand("createlink", false, param.f_href);
            a = editor.getParentElement();
            var sel = editor._getSelection();
            var range = editor._createRange(sel);
            if (!HTMLArea.is_ie) {
                a = range.startContainer;
                if (!/^a$/i.test(a.tagName)) {
                    a = a.nextSibling;
                    if (a == null)
                        a = range.startContainer.parentNode;
                }
            }
        } catch(e) {}
        else {
            var href = param.f_href.trim();
            editor.selectNodeContents(a);
            if (href == "") {
                editor._doc.execCommand("unlink", false, null);
                editor.updateToolbar();
                return false;
            }
            else {
                a.href = href;
            }
        }
        if (!(a && /^a$/i.test(a.tagName)))
            return false;
        a.target = param.f_target.trim();
        a.title = param.f_title.trim();
        editor.selectNodeContents(a);
        editor.updateToolbar();
    }, outparam);
};

// Called when the user clicks on "InsertImage" button.  If an image is already
// there, it will just modify it's properties.
HTMLArea.prototype._insertImage = function(image) {
	// >MT: use the MT image dialog
	if (typeof useMTDialogs != "undefined" && useMTDialogs == true) {
		this._insertImageMT(image);
		return;
	}
	// <MT

    var editor = this;  // for nested functions
    var outparam = null;
    if (typeof image == "undefined") {
        image = this.getParentElement();
        if (image && !/^img$/i.test(image.tagName))
        image = null;
    }
    if (image) outparam = {
        f_base   : editor.config.baseHref,
        f_url    : HTMLArea.is_ie ? editor.stripBaseURL(image.src) : image.getAttribute("src"),
        f_alt    : image.alt,
        f_border : image.border,
        f_align  : image.align,
        f_vert   : image.vspace,
        f_horiz  : image.hspace
    };
    this._popupDialog(400, 200, editor.config.URIs["insert_image"], function(param) {
        if (!param) {  // user must have pressed Cancel
            return false;
        }
        var img = image;
        if (!img) {
            var sel = editor._getSelection();
            var range = editor._createRange(sel);
            editor._doc.execCommand("insertimage", false, param.f_url);
            if (HTMLArea.is_ie) {
                img = range.parentElement();
                // wonder if this works...
                if (img.tagName.toLowerCase() != "img") {
                    img = img.previousSibling;
                }
            } else {
                img = range.startContainer.previousSibling;
                if (!img.tagName) {
                    // if the cursor is at the beginning of the document
                    img = range.startContainer.firstChild;
                }
            }
        } else {
            img.src = param.f_url;
        }

        for (var field in param) {
            var value = param[field];
            switch (field) {
                case "f_alt"    : img.alt    = value; break;
                case "f_border" : img.border = parseInt(value || "0"); break;
                case "f_align"  : img.align  = value; break;
                case "f_vert"   : img.vspace = parseInt(value || "0"); break;
                case "f_horiz"  : img.hspace = parseInt(value || "0"); break;
            }
        }
    }, outparam);
};

// Called when the user clicks the Insert Table button
HTMLArea.prototype._insertTable = function() {
    var sel = this._getSelection();
    var range = this._createRange(sel);
    var editor = this;  // for nested functions
    this._popupDialog(400, 205, editor.config.URIs["insert_table"], function(param) {
        if (!param) {  // user must have pressed Cancel
            return false;
        }
        var doc = editor._doc;
        // create the table element
        var table = doc.createElement("table");
        // assign the given arguments

        for (var field in param) {
            var value = param[field];
            if (!value) {
                continue;
            }
            switch (field) {
                case "f_width"   : table.style.width = value + param["f_unit"]; break;
                case "f_align"   : table.align   = value; break;
                case "f_border"  : table.border  = parseInt(value); break;
                case "f_spacing" : table.cellSpacing = parseInt(value); break;
                case "f_padding" : table.cellPadding = parseInt(value); break;
            }
        }
        var cellwidth = 0;
        if (param.f_fixed)
        cellwidth = Math.floor(100 / parseInt(param.f_cols));
        var tbody = doc.createElement("tbody");
        // >MT: align new table 'top'
        tbody.style.verticalAlign = "top";
        // <MT
        table.appendChild(tbody);
        for (var i = 0; i < param["f_rows"]; ++i) {
            var tr = doc.createElement("tr");
            tbody.appendChild(tr);
            for (var j = 0; j < param["f_cols"]; ++j) {
                var td = doc.createElement("td");
                if (cellwidth)
                td.style.width = cellwidth + "%";
                tr.appendChild(td);
                // >MT: use '&nbsp;' which is cross-platform
                td.innerHTML = HTMLArea.is_ie ? '&nbsp;' : '<br>';
                // <MT
            }
        }
        // >MT: use XHTML
        var parent = editor.getParentElement();
        // <MT
        if (HTMLArea.is_ie) {
            range.pasteHTML(table.outerHTML);
        } else {
            // insert the table
            editor.insertNodeAtSelection(table);
        }
        // >MT: use XHTML
        HTMLArea.makeXHTML(parent, editor.makeXHTMLContext(false));
        // <MT
        return true;
    }, null);
};

/***************************************************
*  Category: EVENT HANDLERS
***************************************************/

// el is reference to the SELECT object
// txt is the name of the select field, as in config.toolbar
HTMLArea.prototype._comboSelected = function(el, txt) {
    this.focusEditor();
    var value = el.options[el.selectedIndex].value;
    switch (txt) {
        // >MT: add fontstyles
    case "fontstyles":
        if (typeof updateFontStyles != "undefined")
        updateFontStyles(this, value);
        else
        this.surroundHTML('<span class="'+value+'">', '</span>');
        break;
        // <MT
        // >MT: use relative font sizes
    case "fontsize":
        if (typeof updateFontSizes != "undefined")
        updateFontSizes(this, txt, value);
        else
        this.execCommand(txt, false, value);
        break;
        // <MT
    case "fontname":
    case "fontsize": this.execCommand(txt, false, value); break;
    case "formatblock":
        // (HTMLArea.is_ie) && (value = "<" + value + ">");
        value = "<" + value + ">"
        this.execCommand(txt, false, value);
        break;
    default:
        // try to look it up in the registered dropdowns
        var dropdown = this.config.customSelects[txt];
        if (typeof dropdown != "undefined") {
            dropdown.action(this);
        } else {
            alert("FIXME: combo box " + txt + " not implemented");
        }
    }
};

// the execCommand function (intercepts some commands and replaces them with
// our own implementation)
HTMLArea.prototype.execCommand = function(cmdID, UI, param) {
    // >MT: add this.preExecCommand
    var p = {cmdID: cmdID, UI: UI, param: param};
    if (typeof this.preExecCommand == 'function' && !this.preExecCommand(p))
        return false;
    cmdID = p.cmdID; UI = p.UI; param = p.param;
    // <MT

    var editor = this;  // for nested functions
    this.focusEditor();
    cmdID = cmdID.toLowerCase();
    // >MT: take an undo snapshot before any user action
    this._undoTakeSnapshot();
    // <MT
    if (HTMLArea.is_gecko) try { this._doc.execCommand('useCSS', false, true); } catch (e) {}; //switch useCSS off (true=off)
    switch (cmdID) {
    case "htmlmode" : this.setMode(); break;
    case "hilitecolor":
        (HTMLArea.is_ie) && (cmdID = "backcolor");
        if (HTMLArea.is_gecko) try { editor._doc.execCommand('useCSS', false, false); } catch (e) {};//switch on useCSS (mozilla bug #279330)
    case "forecolor":
       this._popupDialog(400, 206, editor.config.URIs[cmdID == 'forecolor' ? 'forecolor': 'hilitecolor'], function(color) {
            if (color) { // selection not canceled
                // >MT: add this._onColorChange
                editor.focusEditor();
                if (typeof editor._onColorChange == 'function')
                    editor._onColorChange(cmdID, color);
                else
                // <MT
                    editor._doc.execCommand(cmdID, false, "#" + color);
            }
        }, HTMLArea._colorToRgb(this._doc.queryCommandValue(cmdID)));
        break;
    case "createlink":
		// >MT: use MT-specific dialogs
		if (typeof useMTDialogs != "undefined" && useMTDialogs == true)
			this._createLinkMT(param);
		else
		// <MT
			this._createLink();
	    break;
    case "undo":
    case "redo":
        if (this._customUndo)
            this[cmdID]();
        else
            this._doc.execCommand(cmdID, UI, param);
        break;
    case "inserttable": this._insertTable(); break;
    case "insertimage": this._insertImage(); break;
    case "about":       this._popupDialog(400, 200, editor.config.URIs["about"], null, this); break;
    case "showhelp" :   this._popupDialog(400, 200, editor.config.URIs["help"], null, this); break;
    case "killword":    this._wordClean(); break;
        // >MT: handle removeFormat externally
    case "removeformat":
        this._doc.execCommand(cmdID, UI, param);
        if (typeof removeFormat != "undefined")
            removeFormat(this);
        break;
        // <MT

    case "cut":
    case "copy":
    case "paste":
        try {
            this._doc.execCommand(cmdID, UI, param);
        } catch (e) {
            if (HTMLArea.is_gecko) {
                alert(HTMLArea._lc("The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly."));
            }
        }
        // >MT: move out of exception handling
        if (cmdID == "paste") {
            if (this.config.killWordOnPaste)
            this._wordClean();
        }
        // <MT
        break;
    case "lefttoright":
    case "righttoleft":
        var dir = (cmdID == "righttoleft") ? "rtl" : "ltr";
        var el = this.getParentElement();
        while (el && !HTMLArea.isBlockElement(el))
            el = el.parentNode;
        if (el) {
            if (el.style.direction == dir)
                el.style.direction = "";
            else
                el.style.direction = dir;
        }
        break;
    default: try { this._doc.execCommand(cmdID, UI, param); }
        catch(e) { if (this.config.debug) { alert(e + "\n\nby execCommand(" + cmdID + ");"); } }
    }

    // >MT: add this.postExecCommand
    if (typeof this.postExecCommand == 'function' && !this.postExecCommand(cmdID, UI, param))
        return false;
    // <MT
    this.updateToolbar();
    return false;
};

/** A generic event handler for things that happen in the IFRAME's document.
* This function also handles key bindings. */
HTMLArea.prototype._editorEvent = function(ev) {
    var editor = this;
    var keyEvent = (HTMLArea.is_ie && ev.type == "keydown") || (!HTMLArea.is_ie && ev.type == "keypress");

    //call events of textarea
    if(typeof editor._textArea['on'+ev.type] == "function") {
        editor._textArea['on'+ev.type]();
    }

    if(HTMLArea.is_gecko && keyEvent && ev.ctrlKey &&  this._unLink && this._unlinkOnUndo)
    {
        if(String.fromCharCode(ev.charCode).toLowerCase() == 'z')
        {
            HTMLArea._stopEvent(ev);
            this._unLink();
            editor.updateToolbar();
            return;
        }
    }

    if (keyEvent)
    {
        for (var i in editor.plugins)
        {
            var plugin = editor.plugins[i].instance;
            if (typeof plugin.onKeyPress == "function")
            if (plugin.onKeyPress(ev))
            return false;
        }
    }

    if (keyEvent && ev.ctrlKey && !ev.altKey)
    {
        var sel = null;
        var range = null;
        var key = String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : ev.charCode).toLowerCase();
        var cmd = null;
        var value = null;
        switch (key) {
        case 'a':
            if (!HTMLArea.is_ie) {
                // KEY select all
                sel = this._getSelection();
                sel.removeAllRanges();
                range = this._createRange();
                range.selectNodeContents(this._doc.body);
                sel.addRange(range);
                HTMLArea._stopEvent(ev);
            }
            break;

            // simple key commands follow
        case 'b': cmd = "bold"; break;
        case 'i': cmd = "italic"; break;
        case 'u': cmd = "underline"; break;
            // >MT: add quick-save
        case 'q':
            if (typeof(saveEntryInline) != 'undefined')
            saveEntryInline();
            break;
            // <MT
            /* >MT: Disabled
        case 's': cmd = "strikethrough"; break;
        case 'l': cmd = "justifyleft"; break;
        case 'e': cmd = "justifycenter"; break;
        case 'r': cmd = "justifyright"; break;
        case 'j': cmd = "justifyfull"; break;
            <MT */
        case 'z': cmd = "undo"; break;
        case 'y': cmd = "redo"; break;
            // >MT: spal handling of 'v', 'n', '0', 'w', 'k', and 'l'
        case 'n':
            // magic insert for demo fall
            HTMLArea._stopEvent(ev);
            Widget.magicInsert(this);
            break;
        case 'v':
            var sel = editor._getSelection();
            var hx = this._getFirstAncestor(sel, ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']);
            if (hx) {
                /* splitting heading
                var evt = document.createEventObject();
                evt.keyCode = 13; // Enter
                document.fireEvent("onkeydown",evt);
                document.fireEvent("onkeydown",evt);
                var r = editor._createRange(sel);
                r.moveToElementText(hx.nextSibling);
                editor.execCommand("formatblock", false, "<p>");
                */
                var p = hx.ownerDocument.createElement('p');
                p.innerHTML = "<br />";
                hx.parentNode.insertBefore(p, hx.nextSibling);
                if (HTMLArea.is_ie) {
                    var r = editor._createRange(sel);
                    r.moveToElementText(p);
                    r.select();
                } else {
                    sel.removeAllRanges();
                    var r = editor._createRange(sel);
                    r.selectNodeContents(p);
                    sel.addRange(r);
                }
            }
            if (HTMLArea.is_ie || editor.config.htmlareaPaste)
                cmd = "paste";
            else
            if (HTMLArea.is_gecko) 
            {
            /* >MT: not yet:
                var r = editor._createRange(sel);
                sel.removeAllRanges();
                r.deleteContents();
                r.collapse(true);
                if (r.startOffset > 0) {
                    r.setStart(r.startContainer, r.startOffset-1);
                    r.collapse(true);
                }
                MindTouch.insertHTML(r, "<span class='pasteTag start'>|</span>");
                var n = r.startContainer;
                r.selectNode(n.nextSibling.nextSibling);
                var c = r.startContainer.childNodes[r.startOffset];
                while (c.nodeType == 1)
                    c = c.firstChild;
                r.setStart(c, 2);
                r.collapse(true);
                MindTouch.insertHTML(r, "<span class='pasteTag end'>|</span>");
                r.setStart(c, 1);
                r.collapse(true);
                sel.addRange(r);
            /* <MT */
                setTimeout(function() { editor._wordClean(); }, 50);
            }
            break;
        // turned off for demo fall: case 'n':
        case '0':
            cmd = "formatblock";
            value = HTMLArea.is_ie ? "<p>" : "p";
            break;
        case 'w':
            value = 'no-popup';
        case 'k':
            cmd = "createlink";
            break;
        case 'l':
            if (this._doc.queryCommandState("insertunorderedlist"))
                cmd = "insertorderedlist";
            else if (this._doc.queryCommandState("insertorderedlist")) {
                var ancestors = this.getAllAncestors();
                var count = 0;
                for (var i = 0; i < ancestors.length; ++i) {
                    if (/^(ul|ol)$/i.test(ancestors[i].tagName))
                    ++count;
                }
                cmd = count >= 2 ? "insertunorderedlist" : "outdent";
            } else
                cmd = "insertunorderedlist";
            break;
            // <MT

            // headings
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
            cmd = "formatblock";
            // >MT: offset <h> tags
            value = "h" + (parseInt(key)+1);
            // <MT
            if (HTMLArea.is_ie)
            value = "<" + value + ">";
            break;
        }
        if (cmd) {
            // execute simple command
            this.execCommand(cmd, false, value);
            HTMLArea._stopEvent(ev);
        }
    }
    else if (keyEvent)
    {
        // >MT: add this.handleTab
        if (ev.keyCode == 9 && typeof this.handleTab == 'function' && !this.handleTab(ev))
        return;
        // <MT

        // IE's textRange and selection object is woefully inadequate,
        // which means this fancy stuff is gecko only sorry :-|
        // Die Bill, Die.  (IE supports it somewhat nativly though)
        if(HTMLArea.is_gecko)
        {
            var s = editor._getSelection()
            var autoWrap = function (textNode, tag)
            {
                var rightText = textNode.nextSibling;
                if(typeof tag == 'string') tag = editor._doc.createElement(tag);
                var a = textNode.parentNode.insertBefore(tag, rightText);
                HTMLArea.removeFromParent(textNode);
                a.appendChild(textNode);
                rightText.data = ' ' + rightText.data;

                if(HTMLArea.is_ie)
                {
                    var r = editor._createRange(s);
                    s.moveToElementText(rightText);
                    s.move('character', 1);
                }
                else
                {
                    s.collapse(rightText, 1);
                }
                HTMLArea._stopEvent(ev);

                editor._unLink = function()
                {
                    var t = a.firstChild;
                    a.removeChild(t);
                    a.parentNode.insertBefore(t, a);
                    HTMLArea.removeFromParent(a);
                    editor._unLink = null;
                    editor._unlinkOnUndo = false;
                }
                editor._unlinkOnUndo = true;

                return a;
            };

            switch(ev.which)
            {
                // Space, see if the text just typed looks like a URL, or email address
                // and link it appropriatly
                case 32:
                {
                    if(s && s.isCollapsed && s.anchorNode.nodeType == 3 && s.anchorNode.data.length > 3 && s.anchorNode.data.indexOf('.') >= 0)
                    {
                        var midStart = s.anchorNode.data.substring(0,s.anchorOffset).search(/\S{4,}$/);
                        if(midStart == -1) break;

                        if(this._getFirstAncestor(s, 'a'))
                        {
                            break; // already in an anchor
                        }

                        var matchData = s.anchorNode.data.substring(0,s.anchorOffset).replace(/^.*?(\S*)$/, '$1');
                        var m        = matchData.match(HTMLArea.RE_email);
                        if(m)
                        {
                            var leftText  = s.anchorNode;
                            var rightText = leftText.splitText(s.anchorOffset);
                            var midText   = leftText.splitText(midStart);

                            autoWrap(midText, 'a').href = 'mailto:' + m[0];
                            break;
                        }

                        var m = matchData.match(HTMLArea.RE_url);
                        if(m)
                        {
                            var leftText  = s.anchorNode;
                            var rightText = leftText.splitText(s.anchorOffset);
                            var midText   = leftText.splitText(midStart);
                            autoWrap(midText, 'a').href = (m[1] ? m[1] : 'http://') + m[2];
                            break;
                        }
                    }

                }
                break;

                default :
                {
                    if(ev.keyCode == 27 || (this._unlinkOnUndo && ev.ctrlKey && ev.which == 122) )
                    {
                        if(this._unLink)
                        {
                            this._unLink();
                            HTMLArea._stopEvent(ev);
                        }
                        break;
                    }
                    else if(ev.which || ev.keyCode == 8 || ev.keyCode == 46)
                    {
                        this._unlinkOnUndo = false;

                        if(s.anchorNode && s.anchorNode.nodeType == 3)
                        {
                            // See if we might be changing a link
                            var a = this._getFirstAncestor(s, 'a');
                            if(!a) break; // not an anchor
                            if(!a._updateAnchTimeout)
                            {
                                if(   s.anchorNode.data.match(HTMLArea.RE_email)
                                && (a.href.match('mailto:' + s.anchorNode.data.trim()))
                                )
                                {
                                    var textNode = s.anchorNode;
                                    var fn = function()
                                    {
                                        a.href = 'mailto:' + textNode.data.trim();
                                        a._updateAnchTimeout = setTimeout(fn, 250);
                                    }
                                    a._updateAnchTimeout = setTimeout(fn, 250);
                                    break;
                                }

                                var m = s.anchorNode.data.match(HTMLArea.RE_url);
                                if(m &&  a.href.match(s.anchorNode.data.trim()) )
                                {
                                    var textNode = s.anchorNode;
                                    var fn = function()
                                    {
                                        var m = textNode.data.match(HTMLArea.RE_url);
                                        a.href = (m[1] ? m[1] : 'http://') + m[2];
                                        a._updateAnchTimeout = setTimeout(fn, 250);
                                    }
                                    a._updateAnchTimeout = setTimeout(fn, 250);
                                }
                            }
                        }

                    }
                }
                break;
            }
        }

        // other keys here
        switch (ev.keyCode)
        {
            case 13: // KEY enter
            if (HTMLArea.is_gecko && !ev.shiftKey && this.config.mozParaHandler == 'dirty' )
            {
                this.dom_checkInsertP();
                HTMLArea._stopEvent(ev);
            }
            break;
            case 8: // KEY backspace
            case 46: // KEY delete
            if (HTMLArea.is_gecko && !ev.shiftKey) {
                if (this.dom_checkBackspace())
                HTMLArea._stopEvent(ev);
            } else if (HTMLArea.is_ie) {
                // >MT: add param
                if (this.ie_checkBackspace(ev))
                // <MT
                HTMLArea._stopEvent(ev);
            }
            break;
        }
    }

    // update the toolbar state after some time
    if (editor._timerToolbar) {
        clearTimeout(editor._timerToolbar);
    }
    editor._timerToolbar = setTimeout(function() {
        editor.updateToolbar();
        editor._timerToolbar = null;
        // >MT: fix issue with Mac FF and slowdown on typing
    }, 750);
    // <MT
};

HTMLArea.prototype.convertNode = function(el, newTagName) {
    var newel = this._doc.createElement(newTagName);
    while (el.firstChild)
    newel.appendChild(el.firstChild);
    return newel;
};

// >MT: add param
HTMLArea.prototype.ie_checkBackspace = function(ev) {
    // <MT
    var sel = this._getSelection();
    if(sel.type == 'Control')
    {
        var elm = this._activeElement(sel);
        HTMLArea.removeFromParent(elm);
        return true;
    }

    // This bit of code preseves links when you backspace over the
    // endpoint of the link in IE.  Without it, if you have something like
    //    link_here |
    // where | is the cursor, and backspace over the last e, then the link
    // will de-link, which is a bit tedious
    // >MT: add this.handleTab
    if (typeof this.handleTab == 'function' && this.handleTab(ev))
		return true;
    // <MT
    var range = this._createRange(sel);
    if (!range)
		return false;
    var r2 = range.duplicate();
    r2.moveStart("character", -1);
    var a = r2.parentElement();
    if (a != range.parentElement() &&
		/^a$/i.test(a.tagName)) {
        r2.collapse(true);
        r2.moveEnd("character", 1);
        r2.pasteHTML('');
        r2.select();
        return true;
    }
};

HTMLArea.prototype.dom_checkBackspace = function() {
    var self = this;
    var sel = self._getSelection();
    var range = self._createRange(sel);
    var SC = range.startContainer;
    var SO = range.startOffset;

    // >MT: don't merge to <a> tags following eachother
    var el = SC.nodeType == 1 ? SC : SC.parentNode;
    var pn = el.parentNode;
    var ppn = pn ? pn.previousSibling : null;
    if (ppn && ppn.nodeType == 3 && ppn.textContent.trim().length == 0)
        ppn = ppn.previousSibling;
    var lc = ppn ? ppn.lastChild : null;
    if (SO == 0 && /^a$/i.test(el.tagName) && pn && /^p$/i.test(pn.tagName) && ppn && /^p$/i.test(ppn.tagName) && lc && /^a$/i.test(lc.tagName)) {
        ppn.appendChild(this._doc.createElement('BR'));
        return false;
    }
    // <MT

    setTimeout(function() {
        var SC = range.startContainer;
        var SO = range.startOffset;
        var EC = range.endContainer;
        var EO = range.endOffset;
        var newr = SC.nextSibling;
        if (SC.nodeType == 3)
            SC = SC.parentNode;
        if (!/\S/.test(SC.tagName)) {
            var p = document.createElement("p");
            while (SC.firstChild)
                p.appendChild(SC.firstChild);
            SC.parentNode.insertBefore(p, SC);
            HTMLArea.removeFromParent(SC);
            var r = range.cloneRange();
            r.setStartBefore(newr);
            r.setEndAfter(newr);
            r.extractContents();
            sel.removeAllRanges();
            sel.addRange(r);
        }
    }, 10);
    // >MT: proper return value
    return false;
    // <MT
};

/** The idea here is
* 1. See if we are in a block element
* 2. If we are not, then wrap the current "block" of text into a paragraph
* 3. Now that we have a block element, select all the text between the insertion point
*    and just AFTER the end of the block
*    eg <p>The quick |brown fox jumped over the lazy dog.</p>|
*                     ---------------------------------------
* 4. Extract that from the document, making
*       <p>The quick </p>
*    and a document fragment with
*       <p>brown fox jumped over the lazy dog.</p>
* 5. Reinsert it just after the block element
*       <p>The quick </p><p>brown fox jumped over the lazy dog.</p>
*
* Along the way, allow inserting blank paragraphs, which will look like <p><br/></p>
*/

HTMLArea.prototype.dom_checkInsertP = function() {

    // Get the insertion point, we'll scrub any highlighted text the user wants rid of while we are there.
    var sel = this._getSelection();
    var range = this._createRange(sel);
    if (!range.collapsed)
    {
        range.deleteContents();
    }
    this.deactivateEditor();
    //sel.removeAllRanges();
    //sel.addRange(range);

    var SC = range.startContainer;
    var SO = range.startOffset;
    var EC = range.endContainer;
    var EO = range.endOffset;

    // If the insertion point is character 0 of the
    // document, then insert a space character that we will wrap into a paragraph
    // in a bit.
    if (SC == EC && SC == body && !SO && !EO)
    {
        p = this._doc.createTextNode(" ");
        body.insertBefore(p, body.firstChild);
        range.selectNodeContents(p);
        SC = range.startContainer;
        SO = range.startOffset;
        EC = range.endContainer;
        EO = range.endOffset;
    }

    // See if we are in a block element, if so, great.
    var p     = this.getAllAncestors();

    var block = null;
    var body = this._doc.body;
    for (var i = 0; i < p.length; ++i)
    {
        if(HTMLArea.isParaContainer(p[i]))
        {
            break;
        }
        else if (HTMLArea.isBlockElement(p[i]) && !/body|html/i.test(p[i].tagName))
        {
            block = p[i];
            break;
        }
    }

    // If not in a block element, we'll have to turn some stuff into a paragraph
    if (!block)
    {
        // We want to wrap as much stuff as possible into the paragraph in both directions
        // from the insertion point.  We start with the start container and walk back up to the
        // node just before any of the paragraph containers.
        var wrap = range.startContainer;
        while(wrap.parentNode && !HTMLArea.isParaContainer(wrap.parentNode))
        {
            wrap = wrap.parentNode;
        }
        var start = wrap;
        var end   = wrap;

        // Now we walk up the sibling list until we hit the top of the document
        // or an element that we shouldn't put in a p (eg other p, div, ul, ol, table)
        while(start.previousSibling)
        {
            if(start.previousSibling.tagName)
            {
                if(!HTMLArea.isBlockElement(start.previousSibling))
                {
                    start = start.previousSibling;
                }
                else
                {
                    break;
                }
            }
            else
            {
                start = start.previousSibling;
            }
        }

        // Same down the list
        while(end.nextSibling)
        {
            if(end.nextSibling.tagName)
            {
                if(!HTMLArea.isBlockElement(end.nextSibling))
                {
                    end = end.nextSibling;
                }
                else
                {
                    break;
                }
            }
            else
            {
                end = end.nextSibling;
            }
        }

        // Select the entire block
        range.setStartBefore(start);
        range.setEndAfter(end);

        // Make it a paragraph
        range.surroundContents(this._doc.createElement('p'));

        // Which becomes the block element
        block = range.startContainer.firstChild;

        // And finally reset the insertion point to where it was originally
        range.setStart(SC, SO);
    }

    // The start point is the insertion point, so just move the end point to immediatly
    // after the block
    range.setEndAfter(block);

    // Extract the range, to split the block
    // If we just did range.extractContents() then Mozilla does wierd stuff
    // with selections, but if we clone, then remove the original range and extract
    // the clone, it's quite happy.
    var r2 = range.cloneRange();
    sel.removeRange(range);
    var df = r2.extractContents();

    if(df.childNodes.length == 0)
    {
        df.appendChild(this._doc.createElement('p'));
        df.firstChild.appendChild(this._doc.createElement('br'));
    }

    if(df.childNodes.length > 1)
    {
        var nb = this._doc.createElement('p');
        while(df.firstChild)
        {
            var s = df.firstChild;
            df.removeChild(s);
            nb.appendChild(s);
        }
        df.appendChild(nb);
    }

    // If the original block is empty, put a nsbp in it.
    if (!/\S/.test(block.innerHTML))
    block.innerHTML = "&nbsp;";

    p = df.firstChild;
    if (!/\S/.test(p.innerHTML))
    p.innerHTML = "<br />";

    // If the new block is empty and it's a heading, make it a paragraph
    // note, the new block is empty when you are hitting enter at the end of the existing block
    if (/^\s*<br\s*\/?>\s*$/.test(p.innerHTML) && /^h[1-6]$/i.test(p.tagName))
    {
        df.appendChild(this.convertNode(p, "p"));
        df.removeChild(p);
    }

    var newblock = block.parentNode.insertBefore(df.firstChild, block.nextSibling);

    // Select the range (to set the insertion)
    // collapse to the start of the new block
    //  (remember the block might be <p><br/></p>, so if we collapsed to the end the <br/> would be noticable)

    //range.selectNode(newblock.firstChild);
    //range.collapse(true);

    this.activateEditor();

    var sel = this._getSelection();
    sel.removeAllRanges();
    sel.collapse(newblock,0);

    // scroll into view
    this.scrollToElement(newblock);

    //this.forceRedraw();

};

HTMLArea.prototype.scrollToElement = function(e)
{
    if(HTMLArea.is_gecko)
    {
        var top  = 0;
        var left = 0;
        while(e)
        {
            top  += e.offsetTop;
            left += e.offsetLeft;
            if(e.offsetParent && e.offsetParent.tagName.toLowerCase() != 'body')
            {
                e = e.offsetParent;
            }
            else
            {
                e = null;
            }
        }
        this._iframe.contentWindow.scrollTo(left, top);
    }
};

// retrieve the HTML
HTMLArea.prototype.getHTML = function() {
    var html = '';
    switch (this._editMode) {
        case "wysiwyg"  :
        {
            if (!this.config.fullPage)
            html = HTMLArea.getHTML(this._doc.body, false, this);
            else
            html = this.doctype + "\n" + HTMLArea.getHTML(this._doc.documentElement, true, this);
            break;
        }
        case "textmode" :
        {
            html = this._textArea.value;
            break;
        }
        default:
        {
            alert("Mode <" + mode + "> not defined!");
            return false;
        }
    }
    return html;
};

HTMLArea.prototype.outwardHtml = function(html)
{
    html = html.replace(/<(\/?)b(\s|>|\/)/ig, "<$1strong$2");
    html = html.replace(/<(\/?)i(\s|>|\/)/ig, "<$1em$2");
    html = html.replace(/<(\/?)strike(\s|>|\/)/ig, "<$1del$2");
    // >MT: also handle <u> as <ins>
    html = html.replace(/<(\/?)u(\s|>|\/)/ig, "<$1ins$2");
    // <MT

    // replace window.open to that any clicks won't open a popup in designMode
    html = html.replace("onclick=\"try{if(document.designMode &amp;&amp; document.designMode == 'on') return false;}catch(e){} window.open(", "onclick=\"window.open(");

    // Figure out what our server name is, and how it's referenced
    var serverBase = location.href.replace(/(https?:\/\/[^\/]*)\/.*/, '$1') + '/';

    // IE puts this in can't figure out why
    html = html.replace(/https?:\/\/null\//g, serverBase);

    // Make semi-absolute links to be truely absolute
    //  we do this just to standardize so that special replacements knows what
    //  to expect
    html = html.replace(/((href|src|background)=[\'\"])\/+/ig, '$1' + serverBase);

    html = this.outwardSpecialReplacements(html);

    html = this.fixRelativeLinks(html);

    if(this.config.sevenBitClean)
    {
        html = html.replace(/[^ -~\r\n\t]/g, function(c){ return '&#'+c.charCodeAt(0)+';';});
    }

    // ticket:56, the "greesemonkey" plugin for Firefox adds this junk,
    // so we strip it out.  Original submitter gave a plugin, but that's
    // a bit much just for this IMHO - james
    if(HTMLArea.is_gecko)
    {
        html = html.replace(/<script[\s]*src[\s]*=[\s]*['"]chrome:\/\/.*?["']>[\s]*<\/script>/ig, '');
    }

    return html;
};

HTMLArea.prototype.inwardHtml = function(html)
{
    // Midas uses b and i instead of strong and em, um, hello,
    // mozilla, this is the 21st century calling!
    if (HTMLArea.is_gecko) {
        html = html.replace(/<(\/?)strong(\s|>|\/)/ig, "<$1b$2");
        html = html.replace(/<(\/?)em(\s|>|\/)/ig, "<$1i$2");
        html = html.replace(/<\/a>\s*<\/(li|td|th|p|blockquote|dl|pre)>/ig, "</a>&nbsp;</$1>");
    }
    // >MT: also handle <u> as <ins>, and <strike> as <del>
    html = html.replace(/<(\/?)del(\s|>|\/)/ig, "<$1strike$2");
    html = html.replace(/<(\/?)ins(\s|>|\/)/ig, "<$1u$2");
    // <MT

    // replace window.open to that any clicks won't open a popup in designMode
    html = html.replace("onclick=\"window.open(", "onclick=\"try{if(document.designMode &amp;&amp; document.designMode == 'on') return false;}catch(e){} window.open(");

    html = this.inwardSpecialReplacements(html);

    // For IE's sake, make any URLs that are semi-absolute (="/....") to be
    // truely absolute
    var nullRE = new RegExp('((href|src|background)=[\'"])/+', 'gi');
    html = html.replace(nullRE, '$1' + location.href.replace(/(https?:\/\/[^\/]*)\/.*/, '$1') + '/');

    html = this.fixRelativeLinks(html);
    return html;
};

HTMLArea.prototype.outwardSpecialReplacements = function(html)
{
    for(var i in this.config.specialReplacements)
    {
        var from = this.config.specialReplacements[i];
        var to   = i;
        // alert('out : ' + from + '=>' + to);
        var reg = new RegExp(from.replace(HTMLArea.RE_Specials, '\\$1'), 'g');
        html = html.replace(reg, to.replace(/\$/g, '$$$$'));
        //html = html.replace(from, to);
    }
    return html;
};

HTMLArea.prototype.inwardSpecialReplacements = function(html)
{
    // alert("inward");
    for(var i in this.config.specialReplacements)
    {
        var from = i;
        var to   = this.config.specialReplacements[i];
        // alert('in : ' + from + '=>' + to);
        //
        // html = html.replace(reg, to);
        // html = html.replace(from, to);
        var reg = new RegExp(from.replace(HTMLArea.RE_Specials, '\\$1'), 'g');
        html = html.replace(reg, to.replace(/\$/g, '$$$$')); // IE uses doubled dollar signs to escape backrefs, also beware that IE also implements $& $_ and $' like perl.
    }
    return html;
};


HTMLArea.prototype.fixRelativeLinks = function(html)
{

    if(typeof this.config.stripSelfNamedAnchors != 'undefined' && this.config.stripSelfNamedAnchors)
    {
        var stripRe = new RegExp(document.location.href.replace(HTMLArea.RE_Specials, '\\$1') + '(#[^\'" ]*)', 'g');
        html = html.replace(stripRe, '$1');
    }


    if(typeof this.config.stripBaseHref != 'undefined' && this.config.stripBaseHref)
    {
        var baseRe = null
        if(typeof this.config.baseHref != 'undefined' && this.config.baseHref != null)
        {
            baseRe = new RegExp(this.config.baseHref.replace(HTMLArea.RE_Specials, '\\$1'), 'g');
        }
        else
        {
            baseRe = new RegExp(document.location.href.replace(/([^\/]*\/?)$/, '').replace(HTMLArea.RE_Specials, '\\$1'), 'g');
        }

        html = html.replace(baseRe, '');
    }

    if(HTMLArea.is_ie)
    {
        // This is now done in inward & outward
        // Don't know why but IE is doing this (putting http://null/ on links?!
        // alert(html);
        // var nullRE = new RegExp('https?:\/\/null\/', 'g');
        // html = html.replace(nullRE, location.href.replace(/(https?:\/\/[^\/]*\/).*/, '$1'));
        // alert(html);
    }

    return html;
};

// retrieve the HTML (fastest version, but uses innerHTML)
HTMLArea.prototype.getInnerHTML = function() {
    if(!this._doc.body) return '';
    switch (this._editMode) {
      case "wysiwyg"  :
        if (!this.config.fullPage)
        // return this._doc.body.innerHTML;
          html = this._doc.body.innerHTML;
        else
          html = this.doctype + "\n" + this._doc.documentElement.innerHTML;
        break;
      case "textmode" :
        html = this._textArea.value;
        break;
      default:
        alert("Mode <" + mode + "> not defined!");
        return false;
    }

    return html;
};

// completely change the HTML inside
HTMLArea.prototype.setHTML = function(html) {
    if (!this.config.fullPage)
    {
        this._doc.body.innerHTML = html;
    }
    else
    {
        this.setFullHTML(html);
    }
    this._textArea.value = html;
};

// sets the given doctype (useful when config.fullPage is true)
HTMLArea.prototype.setDoctype = function(doctype) {
    this.doctype = doctype;
};

/***************************************************
*  Category: UTILITY FUNCTIONS
***************************************************/

// variable used to pass the object to the popup editor window.
HTMLArea._object = null;

// function that returns a clone of the given object
HTMLArea.cloneObject = function(obj) {
    if (!obj) return null;
    var newObj = new Object;

    // check for array objects
    // >MT: fix FF 1.5 issue
    if (obj.constructor.toString().indexOf("function Array(") >= 0) {
        // <MT
        newObj = obj.constructor();
    }

    // check for function objects (as usual, IE is fucked up)
    // >MT: fix FF 1.5 issue
    if (obj.constructor.toString().indexOf("function Function(") >= 0) {
        // <MT
        newObj = obj; // just copy reference to it
    } else for (var n in obj) {
        var node = obj[n];
        if (typeof node == 'object') { newObj[n] = HTMLArea.cloneObject(node); }
        else                         { newObj[n] = node; }
    }

    return newObj;
};

// FIXME!!! this should return false for IE < 5.5
HTMLArea.checkSupportedBrowser = function() {
    if (HTMLArea.is_gecko) {
        if (navigator.productSub < 20021201) {
            alert(_lang_browsernotsupported);
            return false;
        }
        if (navigator.productSub < 20030210) {
            alert(_lang_browsernotsupported);
        }
    }
    var ret = HTMLArea.is_gecko || HTMLArea.is_ie || (HTMLArea.enable_opera && HTMLArea.is_opera);
    if (!ret) alert(_lang_browsernotsupported);
    return ret;
};

// selection & ranges

// >MT: Restore a cached selection
HTMLArea.prototype._selectRange = function(rng) {
    if (HTMLArea.is_ie) {
        rng.select();
    } else {
        alert ('setSelection is unsupported on firefox.');
    }
}
// <MT

// returns the current selection object
HTMLArea.prototype._getSelection = function() {
    if (HTMLArea.is_ie) {
        return this._doc.selection;
    } else {
        return this._iframe.contentWindow.getSelection();
    }
};

// returns a range for the current selection
HTMLArea.prototype._createRange = function(sel) {
    if (HTMLArea.is_ie) {
        // >MT: allow empty argument
        if (typeof sel == "undefined")
            sel = this._getSelection();
        // <MT
        try {return sel.createRange();} catch(e) {return null;}
    } else {
        this.activateEditor();
        // >MT: allow empty argument
        if (sel == null || typeof sel == "undefined")
            sel = this._getSelection();
        // <MT
        // >MT: handle exception different
        try {
            if (sel != null)
                return sel.getRangeAt(0);
        } catch(e) {}
        // <MT
        return this._doc.createRange();
    }
};

// event handling

/** Event Flushing
*  To try and work around memory leaks in the rather broken
*  garbage collector in IE, HTMLArea.flushEvents can be called
*  onunload, it will remove any event listeners (that were added
*  through _addEvent(s)) and clear any DOM-0 events.
*/
HTMLArea._eventFlushers = [ ];
HTMLArea.flushEvents = function()
{
    var x = 0;
    var e = null;
    while(e = HTMLArea._eventFlushers.pop())
    {
        if(e.length == 3)
        {
            HTMLArea._removeEvent(e[0], e[1], e[2]);
            x++;
        }
        else if (e.length == 2)
        {
            try {
                e[0]['on' + e[1]] = null;
                e[0]._xinha_dom0Events[e[1]] = null;
            } catch (ex) {}
            x++;
        }
    }

    /*
    // This code is very agressive, and incredibly slow in IE, so I've disabled it.

    if(document.all)
    {
    for(var i = 0; i < document.all.length; i++)
    {
    for(var j in document.all[i])
    {
    if(/^on/.test(j) && typeof document.all[i][j] == 'function')
    {
    document.all[i][j] = null;
    x++;
    }
    }
    }
    }
    */

    // alert('Flushed ' + x + ' events.');
};

HTMLArea._addEvent = function(el, evname, func) {
    if (HTMLArea.is_ie || HTMLArea.is_opera) {
        el.attachEvent("on" + evname, func);
    } else {
        el.addEventListener(evname, func, true);
    }
    HTMLArea._eventFlushers.push([el, evname, func]);
};

HTMLArea._addEvents = function(el, evs, func) {
    for (var i = evs.length; --i >= 0;) {
        HTMLArea._addEvent(el, evs[i], func);
    }
};

HTMLArea._removeEvent = function(el, evname, func) {
    if (HTMLArea.is_ie) {
        el.detachEvent("on" + evname, func);
    } else {
        el.removeEventListener(evname, func, true);
    }
};

HTMLArea._removeEvents = function(el, evs, func) {
    for (var i = evs.length; --i >= 0;) {
        HTMLArea._removeEvent(el, evs[i], func);
    }
};

HTMLArea._stopEvent = function(ev) {
    if (HTMLArea.is_ie) {
        ev.cancelBubble = true;
        ev.returnValue = false;
    } else {
        ev.preventDefault();
        ev.stopPropagation();
    }
};

/**
* Adds a standard "DOM-0" event listener to an element.
* The DOM-0 events are those applied directly as attributes to
* an element - eg element.onclick = stuff;
*
* By using this function instead of simply overwriting any existing
* DOM-0 event by the same name on the element it will trigger as well
* as the existing ones.  Handlers are triggered one after the other
* in the order they are added.
*
* Remember to return true/false from your handler, this will determine
* whether subsequent handlers will be triggered (ie that the event will
* continue or be canceled).
*
*/

HTMLArea.addDom0Event = function(el, ev, fn)
{
    HTMLArea._prepareForDom0Events(el, ev);
    el._xinha_dom0Events[ev].unshift(fn);
};


/**
* See addDom0Event, the difference is that handlers registered using
* prependDom0Event will be triggered before existing DOM-0 events of the
* same name on the same element.
*/

HTMLArea.prependDom0Event = function(el, ev, fn)
{
    HTMLArea._prepareForDom0Events(el, ev);
    el._xinha_dom0Events[ev].push(fn);
};

/**
* Prepares an element to receive more than one DOM-0 event handler
* when handlers are added via addDom0Event and prependDom0Event.
*/
HTMLArea._prepareForDom0Events = function(el, ev)
{
    // Create a structure to hold our lists of event handlers
    if(typeof el._xinha_dom0Events == 'undefined')
    {
        el._xinha_dom0Events = { };
        HTMLArea.freeLater(el, '_xinha_dom0Events');
    }

    // Create a list of handlers for this event type
    if(typeof el._xinha_dom0Events[ev] == 'undefined')
    {
        el._xinha_dom0Events[ev] = [ ];
        if(typeof el['on'+ev] == 'function')
        {
            el._xinha_dom0Events[ev].push(el['on'+ev]);
        }

        // Make the actual event handler, which runs through
        // each of the handlers in the list and executes them
        // in the correct context.
        el['on'+ev] = function(event)
        {
            var a = el._xinha_dom0Events[ev];
            // call previous submit methods if they were there.
            var allOK = true;
            for (var i = a.length; --i >= 0;)
            {
                // We want the handler to be a member of the form, not the array, so that "this" will work correctly
                el._xinha_tempEventHandler = a[i];
                if(el._xinha_tempEventHandler(event) == false)
                {
                    el._xinha_tempEventHandler = null;
                    allOK = false;
                    break;
                }
                el._xinha_tempEventHandler = null;
            }
            return allOK;
        };

        HTMLArea._eventFlushers.push([el, ev]);
    }
};

HTMLArea.prototype.notifyOn = function(ev, fn)
{
    if(typeof this._notifyListeners[ev] == 'undefined')
    {
        this._notifyListeners[ev] = [ ];
        HTMLArea.freeLater(this, '_notifyListeners');
    }

    this._notifyListeners[ev].push(fn);
};

HTMLArea.prototype.notifyOf = function(ev, args)
{

    if(this._notifyListeners[ev])
    {
        for(var i = 0; i < this._notifyListeners[ev].length; i++)
        {
            this._notifyListeners[ev][i](ev, args);
        }
    }
};


HTMLArea._removeClass = function(el, className) {
    if (!(el && el.className)) {
        return;
    }
    var cls = el.className.split(" ");
    var ar = new Array();
    for (var i = cls.length; i > 0;) {
        if (cls[--i] != className) {
            ar[ar.length] = cls[i];
        }
    }
    el.className = ar.join(" ");
};

HTMLArea._addClass = function(el, className) {
    // remove the class first, if already there
    HTMLArea._removeClass(el, className);
    el.className += " " + className;
};

HTMLArea._hasClass = function(el, className) {
    if (!(el && el.className)) {
        return false;
    }
    var cls = el.className.split(" ");
    for (var i = cls.length; i > 0;) {
        if (cls[--i] == className) {
            return true;
        }
    }
    return false;
};

HTMLArea._blockTags = " body form textarea fieldset ul ol dl li div " +
"p h1 h2 h3 h4 h5 h6 quote pre table thead " +
"tbody tfoot tr td th iframe address blockquote";
HTMLArea.isBlockElement = function(el) {
    return el && el.nodeType == 1 && (HTMLArea._blockTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
};

HTMLArea._paraContainerTags = " body td th caption fieldset div ";
HTMLArea.isParaContainer = function(el)
{
    return el && el.nodeType == 1 && (HTMLArea._paraContainerTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
};

HTMLArea._closingTags = " head script style div span tr td tbody table em strong b i strike code cite dfn abbr acronym font a title textarea select form iframe ";
HTMLArea.needsClosingTag = function(el) {
    return el && el.nodeType == 1 && (HTMLArea._closingTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
};

// performs HTML encoding of some given string
// >MT: use compiled regex
HTMLArea.htmlEncode_regEx = HTMLArea.compileRegex(/[&<>\x22\u0080-\uFFFF]/g);
// <MT
HTMLArea.htmlEncode = function(str) {
    if(typeof str.replace == 'undefined') str = str.toString();
    // >MT: use compiled regex
    return str.replace(HTMLArea.htmlEncode_regEx, function(s,b) {
        switch (s) {
        case '&': return "&amp;";
        case '<': return "&lt;";
        case '>': return "&gt;";
        case "\xA0": return "&nbsp;";
        case '"': return "&quot;";
        default: return "&#"+s.charCodeAt(0)+";";
        }
    });
    // <MT
};

// Retrieves the HTML code from the given node.   This is a replacement for
// getting innerHTML, using standard DOM calls.
// Wrapper catch a Mozilla-Exception with non well formed html source code
HTMLArea.getHTML = function(root, outputRoot, editor) {
    try {
        return HTMLArea.getHTMLWrapper(root,outputRoot,editor).trim();
    }
    catch(e){
        alert(HTMLArea._lc('Your Document is not well formed. Check JavaScript console for details.'));
        return editor._iframe.contentWindow.document.body.innerHTML;
    }
};

HTMLArea.getHTMLWrapper = function(root, outputRoot, editor, indent, isPre) {
    var html = "";
    if(!indent) indent = '';

    // >MT: fix just in case
    if (root == null)
        return html;
    // <MT

    switch (root.nodeType) {
    case 10:// Node.DOCUMENT_TYPE_NODE
    case 6: // Node.ENTITY_NODE
    case 12:// Node.NOTATION_NODE
        // this all are for the document type, probably not necessary
        break;

    case 2: // Node.ATTRIBUTE_NODE
        // Never get here, this has to be handled in the ELEMENT case because
        // of IE crapness requring that some attributes are grabbed directly from
        // the attribute (nodeValue doesn't return correct values), see
        //http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&selm=3porgu4mc4ofcoa1uqkf7u8kvv064kjjb4%404ax.com
        // for information
        break;

    case 4: // Node.CDATA_SECTION_NODE
        // Mozilla seems to convert CDATA into a comment when going into wysiwyg mode,
        //  don't know about IE
        html += (HTMLArea.is_ie ? ('\n' + indent) : '') + '<![CDATA[' + root.data + ']]>' ;
        break;

    case 5: // Node.ENTITY_REFERENCE_NODE
        html += '&' + root.nodeValue + ';';
        break;

    case 7: // Node.PROCESSING_INSTRUCTION_NODE
        // PI's don't seem to survive going into the wysiwyg mode, (at least in moz)
        // so this is purely academic
        // >MT: don't use ? and > together otherwise PHP will not like it
        html += (HTMLArea.is_ie ? ('\n' + indent) : '') + '<'+'?' + root.target + ' ' + root.data + ' ?>';
        // <MT
        break;


    case 1: // Node.ELEMENT_NODE
    case 11: // Node.DOCUMENT_FRAGMENT_NODE
    case 9: // Node.DOCUMENT_NODE
    {
        var closed;
        var i;
        var root_tag = (root.nodeType == 1) ? root.tagName.toLowerCase() : '';
        isPre = isPre || root_tag == "pre";
        if (outputRoot)
            outputRoot = !(editor.config.htmlRemoveTags && editor.config.htmlRemoveTags.test(root_tag));
        if (HTMLArea.is_ie && root_tag == "head") {
            if (outputRoot)
                html += (HTMLArea.is_ie ? ('\n' + indent) : '') + "<head>";
            // lowercasize
            var save_multiline = RegExp.multiline;
            RegExp.multiline = true;
            var txt = root.innerHTML.replace(HTMLArea.RE_tagName, function(str, p1, p2) {
                return p1 + p2.toLowerCase();
            });
            RegExp.multiline = save_multiline;
            html += txt + '\n';
            if (outputRoot)
                html += (HTMLArea.is_ie ? ('\n' + indent) : '') + "</head>";
            break;
        }
        if (root_tag == "iframe" && window.Widget) {
            var widget = Widget.getWidget(root);
            if (widget)
                return widget.toHtml();
        }
        if (outputRoot) {
            closed = (!(root.hasChildNodes() || HTMLArea.needsClosingTag(root)));
            // >MT: Ignore <br /> when with <li> and at end of the line or followed by <ul>
            if (root_tag=="br" && root.parentNode.nodeType == 1 && root.parentNode.tagName.toLowerCase() == "li") {
                var n = root.nextSibling;
                if (!n)
                    return "";
                if (n.nodeType == 3 && n.data.trim().length == 0) {
                    n = n.nextSibling;
                    if (!n) return "";
                }
                if (n.nodeType == 1 && /^ul|ol$/i.test(n.tagName))
                    return "";
            }
            html += (HTMLArea.isBlockElement(root) && !isPre ? ('\n' + indent) : '') + "<" + root.tagName.toLowerCase();
            // <MT
            // >MT: speed increase
            var tag = root.tagName.toLowerCase();
            var hasAttrs = HTMLArea.is_ie ? root.outerHTML.trim().length - root.innerHTML.length > 2*tag.length + 5 : true;
            if (hasAttrs) {
                // <MT
                var attrs = root.attributes;
                for (i = 0; i < attrs.length; ++i) {
                    var a = attrs.item(i);
                    // >MT: speed increase
                    if (!a.specified) continue;
                    // <MT
                    var name = a.nodeName.toLowerCase();
                    // >MT: speed increase
                    if (name == 'value' && !/input|option/.test(tag)) continue;
                    // <MT
                    if (/_moz_editor_bogus_node/.test(name)) {
                        html = "";
                        break;
                    }
                    if (/(_moz)|(contenteditable)|(_msh)/.test(name)) {
                        // avoid certain attributes
                        continue;
                    }
                    var value;
                    if (name != "style") {
                        // IE5.5 reports 25 when cellSpacing is
                        // 1; other values might be doomed too.
                        // For this reason we extract the
                        // values directly from the root node.
                        // I'm starting to HATE JavaScript
                        // development.  Browser differences
                        // suck.
                        //
                        // Using Gecko the values of href and src are converted to absolute links
                        // unless we get them using nodeValue()
                        if (typeof root[a.nodeName] != "undefined" && name != "href" && name != "src" && !/^on/.test(name)) {
                            value = root[a.nodeName];
                        } else {
                            value = a.nodeValue;
                            // IE seems not willing to return the original values - it converts to absolute
                            // links using a.nodeValue, a.value, a.stringValue, root.getAttribute("href")
                            // So we have to strip the baseurl manually :-/
                            if (HTMLArea.is_ie && (name == "href" || name == "src")) {
                                value = editor.stripBaseURL(value);
                            }

                            // High-ascii (8bit) characters in links seem to cause problems for some sites,
                            // while this seems to be consistent with RFC 3986 Section 2.4
                            // because these are not "reserved" characters, it does seem to
                            // cause links to international resources not to work.  See ticket:167

                            // IE always returns high-ascii characters un-encoded in links even if they
                            // were supplied as % codes (it unescapes them when we pul the value from the link).

                            // Hmmm, very strange if we use encodeURI here, or encodeURIComponent in place
                            // of escape below, then the encoding is wrong.  I mean, completely.
                            // Nothing like it should be at all.  Using escape seems to work though.
                            // It's in both browsers too, so either I'm doing something wrong, or
                            // something else is going on?

                            if(editor.config.only7BitPrintablesInURLs && (name == "href" || name == "src"))
                            {
                                value = value.replace(/([^!-~]+)/g, function(match) { return escape(match); });
                            }
                        }
                    } else { // IE fails to put style in attributes list
                        // FIXME: cssText reported by IE is UPPERCASE
                        value = root.style.cssText;
                    }
                    if (/^(_moz)?$/.test(value)) {
                        // Mozilla reports some special tags
                        // here; we don't need them.
                        continue;
                    }
                    html += " " + name + '="' + HTMLArea.htmlEncode(value) + '"';
                }
                // >MT: speed increase
            }
            // <MT
            if (html != "") {
              // >MT: extend to td, th, li
                if(closed && (root_tag=="p" || root_tag=="td" || root_tag=="th" || root_tag=="li")) {
                    //never use <p /> as empty paragraphs won't be visible
                    html += "><br /></"+root_tag+">";
                // <MT
                } else if(closed) {
                    html += " />";
                    // >MT: add newline after <BR />
                    if (root_tag=="br" && (root.nextSibling && root.nextSibling.nodeType == 1) && !isPre) {
                        html += '\n' + (root.nextSibling ? indent : '');
                    }
                    // <MT
                } else {
                    html += ">";
                }
            }
        }
        var containsBlock = false;
        // >MT: don't indent body
        var newIndent = root_tag == "body" ? "" : indent + '  ';
        var innerHTML = '';
        // <MT
        for (i = root.firstChild; i; i = i.nextSibling) {
            if(!containsBlock && i.nodeType == 1 && HTMLArea.isBlockElement(i)) containsBlock = true;
            // >MT: don't indent body
            innerHTML += HTMLArea.getHTMLWrapper(i, true, editor, newIndent, isPre);
            // <MT
        }
        if (outputRoot && !closed) {
            // >MT: extend to gecko
            if ((root_tag=="p" || root_tag=="td" || root_tag=="th" || root_tag=="li") && innerHTML.replace(/([\s\xA0]|&nbsp;)/g, '').length == 0) {
                html += "<br /></"+root_tag+">";
            } else html += innerHTML + (HTMLArea.isBlockElement(root) && containsBlock && !isPre ? ('\n' + indent) : '') + "</" + root_tag + ">";
            // <MT
        } else html += innerHTML;
        break;
    }
    case 3: // Node.TEXT_NODE
        // >MT: don't output empty text after element
        if (root.data.length != 0 && root.data.trim().length == 0)
            html = " ";
        else
            html = /^script|style$/i.test(root.parentNode.tagName) ? root.data : HTMLArea.htmlEncode(root.data.replace(/(\s|&nbsp;)+$/,' '));
        // <MT
        break;

    case 8: // Node.COMMENT_NODE
        if (/^\[if .+\]$/.test(root.data) || root.data == '[endif]') return ''; 
        html = "<!--" + root.data + "-->";
        break;
    }
    return html;
};

/** @see getHTMLWrapper (search for "value = a.nodeValue;") */

HTMLArea.prototype.stripBaseURL = function(string)
{
    if(this.config.baseHref==null || !this.config.stripBaseHref)
    {
        return(string);
    }
    var baseurl = this.config.baseHref;

    // strip host-part of URL which is added by MSIE to links relative to server root
    baseurl = baseurl.replace(/^(https?:\/\/[^\/]+)(.*)$/, '$1');
    basere = new RegExp(baseurl);
    return string.replace(basere, "");
};


String.prototype.trim = function() {
    return this.replace(/^\s+/, '').replace(/\s+$/, '');
};

// creates a rgb-style color from a number
HTMLArea._makeColor = function(v) {
    if (typeof v != "number") {
        // already in rgb (hopefully); IE doesn't get here.
        return v;
    }
    // IE sends number; convert to rgb.
    var r = v & 0xFF;
    var g = (v >> 8) & 0xFF;
    var b = (v >> 16) & 0xFF;
    return "rgb(" + r + "," + g + "," + b + ")";
};

// returns hexadecimal color representation from a number or a rgb-style color.
HTMLArea._colorToRgb = function(v) {
    if (!v)
    return '';

    // returns the hex representation of one byte (2 digits)
    function hex(d) {
        return (d < 16) ? ("0" + d.toString(16)) : d.toString(16);
    };

    if (typeof v == "number") {
        // we're talking to IE here
        var r = v & 0xFF;
        var g = (v >> 8) & 0xFF;
        var b = (v >> 16) & 0xFF;
        return "#" + hex(r) + hex(g) + hex(b);
    }

    if (v.substr(0, 3) == "rgb") {
        // in rgb(...) form -- Mozilla
        var re = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/;
        if (v.match(re)) {
            var r = parseInt(RegExp.$1);
            var g = parseInt(RegExp.$2);
            var b = parseInt(RegExp.$3);
            return "#" + hex(r) + hex(g) + hex(b);
        }
        // doesn't match RE?!  maybe uses percentages or float numbers
        // -- FIXME: not yet implemented.
        return null;
    }

    if (v.substr(0, 1) == "#") {
        // already hex rgb (hopefully :D )
        return v;
    }

    // >MT: add 16 known colors
    switch (v.toLowerCase())
    {
        case "green": return "#008000";
        case "lime": return "#00ff00";
        case "teal": return "#008080";
        case "aqua": return "#00ffff";
        case "navy": return "#000080";
        case "blue": return "#0000ff";
        case "purple": return "#800080";
        case "fuchsia": return "#ff00ff";
        case "maroon": return "#800000";
        case "red": return "#ff0000";
        case "olive": return "#808000";
        case "yellow": return "#ffff00";
        case "white": return "#ffffff";
        case "silver": return "#c0c0c0";
        case "gray": return "#808080";
        case "black": return "#000000";
    }

    // if everything else fails ;)
    return v;
    // <MT
};

// modal dialogs for Mozilla (for IE we're using the showModalDialog() call).

// receives an URL to the popup dialog and a function that receives one value;
// this function will get called after the dialog is closed, with the return
// value of the dialog.
HTMLArea.prototype._popupDialog = function(width, height, url, action, init) {
    Dialog(width, height, this.popupURL(url), action, init, this);
};

// paths

HTMLArea.prototype.imgURL = function(file, plugin) {
    if (typeof plugin == "undefined")
    return _editor_url + file;
    else
    return _editor_url + "plugins/" + plugin + "/img/" + file;
};

HTMLArea.prototype.popupURL = function(file) {
    var url = "";
    if (file.match(/^plugin:\/\/(.*?)\/(.*)/)) {
        var plugin = RegExp.$1;
        var popup = RegExp.$2;
        if (!/\.html$/.test(popup))
        popup += ".html";
        url = _editor_url + "plugins/" + plugin + "/popups/" + popup;
        // >MT: also allow external popups
    } else if(/^\/.*/.test(file) || /^http/.test(file))
    // <MT
    url = file;
    else
    url = _editor_url + this.config.popupURL + file;
    return url;
};

/**
* FIX: Internet Explorer returns an item having the _name_ equal to the given
* id, even if it's not having any id.  This way it can return a different form
* field even if it's not a textarea.  This workarounds the problem by
* specifically looking to search only elements having a certain tag name.
*/
HTMLArea.getElementById = function(tag, id) {
    var el, i, objs = document.getElementsByTagName(tag);
    for (i = objs.length; --i >= 0 && (el = objs[i]);)
    if (el.id == id)
    return el;
    return null;
};


/** Use some CSS trickery to toggle borders on tables */

HTMLArea.prototype._toggleBorders = function()
{
    tables = this._doc.getElementsByTagName('TABLE');
    if(tables.length != 0)
    {
        if(!this.borders)
        {
            name = "bordered";
            this.borders = true;
        }
        else
        {
            name = "";
            this.borders = false;
        }

        for (var ix=0;ix < tables.length;ix++)
        {
            if(this.borders)
            {
                // flashing the display forces moz to listen (JB:18-04-2005) - #102
                if(HTMLArea.is_gecko)
                {
                    tables[ix].style.display="none";
                    tables[ix].style.display="table";
                }
                HTMLArea._addClass(tables[ix], 'htmtableborders');
            }
            else
            {
                HTMLArea._removeClass(tables[ix], 'htmtableborders');
            }
        }
    }
    return true;
};


HTMLArea.addClasses = function(el, classes)
{
    if(el != null)
    {
        var thiers = el.className.trim().split(' ');
        var ours   = classes.split(' ');
        for(var x = 0; x < ours.length; x++)
        {
            var exists = false;
            for(var i = 0; exists == false && i < thiers.length; i++)
            {
                if(thiers[i] == ours[x])
                {
                    exists = true;
                }
            }
            if(exists == false)
            {
                thiers[thiers.length] = ours[x];
            }
        }
        el.className = thiers.join(' ').trim();
    }
};

HTMLArea.removeClasses = function(el, classes)
{
    var existing    = el.className.trim().split();
    var new_classes = [ ];
    var remove      = classes.trim().split();

    for(var i = 0; i < existing.length; i++)
    {
        var found = false;
        for(var x = 0; x < remove.length && !found; x++)
        {
            if(existing[i] == remove[x])
            {
                found = true;
            }
        }
        if(!found)
        {
            new_classes[new_classes.length] = existing[i];
        }
    }
    return new_classes.join(' ');
};

/** Alias these for convenience */
HTMLArea.addClass       = HTMLArea._addClass;
HTMLArea.removeClass    = HTMLArea._removeClass;
HTMLArea._addClasses    = HTMLArea.addClasses;
HTMLArea._removeClasses = HTMLArea.removeClasses;

/** Use XML HTTPRequest to post some data back to the server and do something
* with the response (asyncronously!), this is used by such things as the tidy functions
*/
HTMLArea._postback = function(url, data, handler)
{
    var req = window.XMLHttpRequest ? new XMLHttpRequest() : window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : null;

    var content = '';
    for(var i in data)
    {
        content += (content.length ? '&' : '') + i + '=' + encodeURIComponent(data[i]);
    }

    function callBack()
    {
        if(req.readyState == 4)
        {
            if(req.status == 200)
            {
                if(typeof handler == 'function')
                handler(req.responseText, req);
            }
            else
            {
                alert('An error has occurred: ' + req.statusText);
            }
        }
    };

    req.onreadystatechange = callBack;

    req.open('POST', url, true);
    req.setRequestHeader
    (
    'Content-Type',
    'application/x-www-form-urlencoded; charset=UTF-8'
    );
    //alert(content);
    req.send(content);
};

HTMLArea._getback = function(url, handler)
{
    var req = window.XMLHttpRequest ? new XMLHttpRequest() : window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : null;

    function callBack()
    {
        if(req.readyState == 4)
        {
            if(req.status == 200)
            {
                handler(req.responseText, req);
            }
            else
            {
                alert('An error has occurred: ' + req.statusText);
            }
        }
    };

    req.onreadystatechange = callBack;
    req.open('GET', url, true);
    req.send(null);
};

HTMLArea._geturlcontent = function(url)
{
    var req = window.XMLHttpRequest ? new XMLHttpRequest() : window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : null;

    // Synchronous!
    req.open('GET', url, false);
    req.send(null);
    if(req.status == 200)
    {
        return req.responseText;
    }
    else
    {
        return '';
    }

};

/**
* Unless somebody already has, make a little function to debug things
*/
if(typeof dump == 'undefined')
{
    function dump(o) {
        var s = '';
        for (var prop in o) {
            s += prop + ' = ' + o[prop] + '\n';
        }

        x = window.open("", "debugger");
        x.document.write('<pre>' + s + '</pre>');
    }
}


HTMLArea.arrayContainsArray = function(a1, a2)
{
    var all_found = true;
    for(var x = 0; x < a2.length; x++)
    {
        var found = false;
        for(var i = 0; i < a1.length; i++)
        {
            if(a1[i] == a2[x])
            {
                found = true;
                break;
            }
        }
        if(!found)
        {
            all_found = false;
            break;
        }
    }
    return all_found;
};

HTMLArea.arrayFilter = function(a1, filterfn)
{
    var new_a = [ ];
    for(var x = 0; x < a1.length; x++)
    {
        if(filterfn(a1[x]))
        new_a[new_a.length] = a1[x];
    }

    return new_a;
};

HTMLArea.uniq_count = 0;
HTMLArea.uniq = function(prefix)
{
    return prefix + HTMLArea.uniq_count++;
};

/** New language handling functions **/


/** Load a language file.
*  This function should not be used directly, HTMLArea._lc will use it when necessary.
* @param context Case sensitive context name, eg 'HTMLArea', 'TableOperations', ...
*/
HTMLArea._loadlang = function(context)
{
    if(typeof _editor_lcbackend == "string")
    {
        //use backend
        var url = _editor_lcbackend;
        url = url.replace(/%lang%/, _editor_lang);
        url = url.replace(/%context%/, context);
    }
    else
    {
        //use internal files
        if(context != 'HTMLArea') {
            var url = _editor_url+"plugins/"+context+"/lang/"+_editor_lang+".js";
        } else {
            var url = _editor_url+"lang/"+_editor_lang+".js";
        }
    }

    var lang;
    var langData = HTMLArea._geturlcontent(url);
    if(langData != "") {
        try {
            eval('lang = ' + langData);
        } catch(Error) {
            alert('Error reading Language-File ('+url+'):\n'+Error.toString());
            lang = { }
        }
    } else {
        lang = { };
    }

    return lang;
};

/** Return a localised string.
* @param string    English language string
* @param context   Case sensitive context name, eg 'HTMLArea' (default), 'TableOperations'...
* @param replace   Replace $variables in String, eg {foo: 'replaceText'} ($foo in string will be replaced)
*/
HTMLArea._lc = function(string, context, replace)
{
    var ret;
    if(_editor_lang == "en")
    {
        if(typeof string == 'object' && string.string) {
            ret = string.string;
        } else {
            ret = string;
        }
    }
    else
    {
        if(typeof HTMLArea._lc_catalog == 'undefined')
        {
            HTMLArea._lc_catalog = [ ];
        }

        if(typeof context == 'undefined')
        {
            context = 'HTMLArea';
        }

        if(typeof HTMLArea._lc_catalog[context] == 'undefined')
        {
            HTMLArea._lc_catalog[context] = HTMLArea._loadlang(context);
        }

        var key;
        if(typeof string == 'object' && string.key)
        {
            key = string.key;
        }
        else if(typeof string == 'object' && string.string)
        {
            key = string.string;
        }
        else
        {
            key = string;
        }

        if(typeof HTMLArea._lc_catalog[context][key] == 'undefined')
        {
            if(context=='HTMLArea')
            {
                // Indicate it's untranslated
                if(typeof string == 'object' && string.string) {
                    ret = string.string;
                } else {
                    ret = string;
                }
            }
            else
            {
                //if string is not found and context is not HTMLArea try if it is in HTMLArea
                return HTMLArea._lc(string, 'HTMLArea', replace);
            }
        }
        else
        {
            ret = HTMLArea._lc_catalog[context][key];
        }
    }

    if(typeof string == 'object' && string.replace)
    {
        replace = string.replace;
    }
    if(typeof replace != "undefined")
    {
        for(var i in replace)
        {
            ret = ret.replace('$'+i, replace[i]);
        }
    }

    return ret;
};

HTMLArea.hasDisplayedChildren = function(el)
{
    var children = el.childNodes;
    for(var i =0; i < children.length;i++)
    {
        if(children[i].tagName)
        {
            if(children[i].style.display != 'none')
            {
                return true;
            }
        }
    }
    return false;
};


HTMLArea._loadback = function(src, callback)
{
    var head = document.getElementsByTagName("head")[0];
    var evt = HTMLArea.is_ie ? "onreadystatechange" : "onload";

    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = src;
    script[evt] = function()
    {
        if(HTMLArea.is_ie && !/loaded|complete/.test(window.event.srcElement.readyState))  return;
        callback();
    }
    head.appendChild(script);
};

HTMLArea.collectionToArray = function(collection)
{
    var array = [ ];
    for(var i = 0; i < collection.length; i++)
    {
        array.push(collection.item(i));
    }
    return array;
};

if(!Array.prototype.append)
{
    Array.prototype.append  = function(a)
    {
        for(var i = 0; i<a.length;i++)
        {
            this.push(a[i]);
        }
        return this;
    };
}

HTMLArea.makeEditors = function(editor_names, default_config, plugin_names)
{
    if(typeof default_config == 'function')
    {
        default_config = default_config();
    }

    var editors = { };
    for(var x = 0; x < editor_names.length; x++)
    {
        var editor = new HTMLArea(editor_names[x], HTMLArea.cloneObject(default_config));
        editor.registerPlugins(plugin_names);
        editors[editor_names[x]] = editor;
    }
    return editors;
};

HTMLArea.startEditors = function(editors)
{
    for(var i in editors)
    {
        if(editors[i].generate) editors[i].generate();
    }
};

HTMLArea.prototype.registerPlugins = function(plugin_names) {
    if(plugin_names)
    {
        for(var i = 0; i < plugin_names.length; i++)
        {
            this.registerPlugin(eval(plugin_names[i]));
        }
    }
};

/** Utility function to base64_encode some arbitrary data, uses the builtin btoa() if it exists (Moz) */

HTMLArea.base64_encode =  function(input)
{
    var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var output = "";
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    do {
        chr1 = input.charCodeAt(i++);
        chr2 = input.charCodeAt(i++);
        chr3 = input.charCodeAt(i++);

        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;

        if (isNaN(chr2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
            enc4 = 64;
        }

        output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) +
        keyStr.charAt(enc3) + keyStr.charAt(enc4);
    } while (i < input.length);

    return output;
};

/** Utility function to base64_decode some arbitrary data, uses the builtin atob() if it exists (Moz) */

HTMLArea.base64_decode =function(input)
{
    var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var output = "";
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    do {
        enc1 = keyStr.indexOf(input.charAt(i++));
        enc2 = keyStr.indexOf(input.charAt(i++));
        enc3 = keyStr.indexOf(input.charAt(i++));
        enc4 = keyStr.indexOf(input.charAt(i++));

        chr1 = (enc1 << 2) | (enc2 >> 4);
        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
        chr3 = ((enc3 & 3) << 6) | enc4;

        output = output + String.fromCharCode(chr1);

        if (enc3 != 64) {
            output = output + String.fromCharCode(chr2);
        }
        if (enc4 != 64) {
            output = output + String.fromCharCode(chr3);
        }
    } while (i < input.length);

    return output;
};

HTMLArea.removeFromParent = function(el)
{
    if(!el.parentNode) return;
    var pN = el.parentNode;
    pN.removeChild(el);
    return el;
};

HTMLArea.hasParentNode = function(el)
{
    if(el.parentNode)
    {
        // When you remove an element from the parent in IE it makes the parent
        // of the element a document fragment.  Moz doesn't.
        if(el.parentNode.nodeType == 11)
        {
            return false;
        }
        return true;
    }

    return false;
};

HTMLArea.getOuterHTML = function(element)
{
    if(HTMLArea.is_ie)
    {
        return element.outerHTML;
    }
    else
    {
        return (new XMLSerializer()).serializeToString(element);
    }
};

HTMLArea.toFree = [ ];
HTMLArea.freeLater = function(obj,prop)
{
    HTMLArea.toFree.push({o:obj,p:prop});
};

HTMLArea.free = function(obj, prop)
{
    if(obj && !prop)
    {
        for(var p in obj)
        {
            HTMLArea.free(obj, p);
        }
    }
    // >MT: fix
    else if (obj && typeof obj[prop] != 'unknown')
    // <MT
    {
        obj[prop] = null;
    }
};

/** IE's Garbage Collector is broken very badly.  We will do our best to
*   do it's job for it, but we can't be perfect.
*/

HTMLArea.collectGarbageForIE = function()
{
    HTMLArea.flushEvents();
    for(var x = 0; x < HTMLArea.toFree.length; x++)
    {
        if(!HTMLArea.toFree[x].o) alert("What is " + x + ' ' + HTMLArea.toFree[x].o);
        HTMLArea.free(HTMLArea.toFree[x].o, HTMLArea.toFree[x].p);
    }
};

HTMLArea.init();
HTMLArea.addDom0Event(window,'unload',HTMLArea.collectGarbageForIE);

String.prototype.utf8ToCodepoint = function() {
  var z = this.charCodeAt(0), length;
  if (z & 0x80) {
    length = 0;
    while (z & 0x80) {
      length++;
      z <<= 1;
    }
  } else
    length = 1;

  if (length != this.length) return false;
  if (length == 1) return z;

  // Mask off the length-determining bits and shift back to the original location
  z &= 0xff;
  z >>= length;

  // Add in the free bits from subsequent bytes
  for ( var i=1; i < length; i++ ) {
    z <<= 6;
    z |= this.charCodeAt(i) & 0x3f;
  }
  return z;
};

String.prototype.utf8ToString = function() {
  var val = this.replace(/[\xc0-\xfd][\x80-\xbf]*/g, function(s) {
    return String.fromCharCode(s.utf8ToCodepoint());
  });;
  return val;
};

String.prototype.utf8URL = function() {
  var val = this.replace(/[ \?%\+&=#\.\u0080-\uFFFF]/g, function(s) {
    switch (s) {
    case ' ': return '_';
    case '+': return '%2B';
    default:
      return escape(String.charToUtf8(s.charCodeAt(0)));
    }
  });
  return val;
};

String.prototype.utf8 = function() {
  var val = this.replace(/[\u0080-\uFFFF]/g, function(s) {
    return String.charToUtf8(s.charCodeAt(0));
  });
  return val;
};

String.charToUtf8 = function(codepoint) {
  if(codepoint < 0x80) return String.fromCharCode(codepoint);
  if(codepoint < 0x800) return String.fromCharCode(
    codepoint >> 6 & 0x3f | 0xc0, 
    codepoint & 0x3f | 0x80);
  if(codepoint < 0x10000) return String.fromCharCode(
    codepoint >> 12 & 0x0f | 0xe0, 
    codepoint >> 6 & 0x3f | 0x80, 
    codepoint & 0x3f | 0x80);
  if(codepoint < 0x110000) return String.fromCharCode(
    codepoint >> 18 & 0x07 | 0xf0, 
    codepoint >> 12 & 0x3f | 0x80, 
    codepoint >> 6 & 0x3f | 0x80, 
    codepoint & 0x3f | 0x80);

  // There should be no assigned code points outside this range, but
  return String.fromCharCode(codepoint);
};

var winX = null;
var winY = null;

clientWindow = function () {
	if (self.innerHeight) {
		winX = self.innerWidth;
		winY = self.innerHeight;
	}
	else if (document.documentElement && document.documentElement.clientHeight)	{
		winX = document.documentElement.clientWidth;
		winY = document.documentElement.clientHeight;
	}
	else if (document.body) {
		winX = document.body.clientWidth;
		winY = document.body.clientHeight;
	}
};

getItemHeight = function (elt) {
	return elt.offsetHeight;
};

getItemWidth = function (elt) {
	return elt.offsetWidth;
};

//returns the Y offset of a page
getPageYOffset = function() {
	return (window.pageYOffset > 0) ? window.pageYOffset: document.body.scrollTop;
};

//returns the X offset of a page
getPageXOffset = function() {
	return (window.pageXOffset > 0) ? window.pageXOffset: document.body.scrollLeft;
};

findPosX = function (obj) {
	return getRecursiveProperty(obj, "offsetLeft");
};

findPosY = function (obj) {
	return getRecursiveProperty(obj, "offsetTop");
};

findPosScrollY = function () {	
	var sTop = 0;
	if (document.body.scrollTop > 0) {
		sTop = document.body.scrollTop;
	}
	else if (document.body.parentNode.scrollTop > 0) {
		sTop = document.body.parentNode.scrollTop;	
	}
	return sTop;	
};

findPosScrollX = function () {	
	var sLeft = 0;
	if (document.body.scrollLeft > 0) {
		sLeft = document.body.scrollLeft;
	}
	else if (document.body.parentNode.scrollLeft > 0) {
		sLeft = document.body.parentNode.scrollLeft;	
	}
	return sLeft;	
};

getRecursiveProperty = function (obj, property) {
	var ret = 0;
	while (obj) {
		ret += obj[property];
		obj = obj.offsetParent;
	}
	return ret;	
};

//adds a css class
addCSSClass = function (elt, newClass) {
	var class_ = elt.className.split(' ');
	for ( var i = 0; i < class_.length; i++ ) {
		if (class_[i] == newClass) { 
			return;
		}
	}
	elt.className = elt.className+' '+newClass;
	return true;
};
replaceCSSClass = function (elt, newClass) {
	elt.className = newClass;
	return true;
};
removeCSSClass = function (elt, className) {
	var new_ = new Array;
	var class_ = elt.className.split(' ');
	for ( var i = 0; i < class_.length; i++ ) {
		if (class_[i] != className) { 
			new_[i] = class_[i];
		}
	}
	elt.className = new_.join(' ');
};
inCSSClass = function(elt, className) {
	var new_ = new Array;
	var class_ = elt.className.split(' ');
	for ( var i = 0; i < class_.length; i++ ) {
		if (class_[i] == className) { 
			return true;
		}
	}	
	return false;
};
function mt_gen() {
	
}

/***  
 * takes a string and escapes single quotes and encodes html
 */
mt_gen.htmlspecialchars = function(str) {	
	// performs HTML encoding of some given string
	mt_gen.htmlEncode_regEx = [
		new RegExp().compile(/&/ig),
		new RegExp().compile(/</ig),
		new RegExp().compile(/>/ig),
		new RegExp().compile(/'/ig),
		new RegExp().compile(/\xA0/g),
	    // \x22 means '"' -- we use hex reprezentation so that we don't disturb
	    // JS compressors (well, at least mine fails.. ;)
		new RegExp().compile(/\x22/g),
		// special encode none-ASCII
		new RegExp().compile(/[\x80-\xFF]/g)
	];
	mt_gen.htmlEncode_regExR = [
		"&amp;",
		"&lt;",
		"&gt;",
		"\\'",
		"&nbsp;",
		"&quot;",
		function(s,b){return "&#"+s.charCodeAt(0)+";";}
	];
	
    if(typeof str.replace == 'undefined') str = str.toString();
    for (var i = 0; i < mt_gen.htmlEncode_regEx.length; ++i)
    	str = str.replace(mt_gen.htmlEncode_regEx[i], mt_gen.htmlEncode_regExR[i]);
    return str;
};

mt_gen.getUrlFromName = function(href) {
	href = mt_gen.extractName(href).replace(/ /g,'_');
    if (href.indexOf('&') > 0 || href.indexOf('?') > 0 || href.indexOf('+') > 0 || href.indexOf('#') > 0 || 
        href.indexOf('\\') > 0 || href.indexOf('//') > 0 || href.indexOf('%') > 0
    )
        href = 'index.php?title=' + encodeURIComponent(href);
    return '/' + href;
};

mt_gen.extractName = function(href) {
    if (href.charAt(0) == '/') href = href.substr(1);
    if (href.indexOf('index.php?title=') == 0)
        href = href.substr('index.php?title='.length);
    href = href.replace(/&action=.+$/i, '');
    try { href = unescape(href); } catch (e) {}
    return href;
};


var clientBrowser = { 
	isIe : false, 
	isMoz : false,
	isOpera : false,
	detect : function () { 
		var nav = navigator.userAgent.toLowerCase();
		if (nav.indexOf('msie') >= 0) {
			clientBrowser.isIe = true;
		}
		else if (nav.indexOf('mozilla') >= 0)  {
			clientBrowser.isMoz = true;
		}
		else if (nav.indexOf('opera') >= 0) {
			clientBrowser.isOpera = true;	
		}
	}
};

function iconify(icon_class, parentClass) {
	if (!parentClass) parentClass = 'icon';
	var span = document.createElement('span');
	span.className = parentClass;
	var img = document.createElement('img');
	img.src = '/skins/ace/icon-trans.gif';
	if (typeof(icon_class) != 'undefined' && icon_class != '') {
		img.className = icon_class;	
	}
	span.appendChild(img);
	return span;
};

var Element = {};
Element.getDimensions = function(element) {
	if (dojo.style.isDisplayed(element))
		return { width : dojo.style.getBorderBoxWidth(element), height: dojo.style.getBorderBoxHeight(element) };
	// All *Width and *Height properties give 0 on elements with display none,
	// so enable the element temporarily
	var els = element.style;
	var originalVisibility = els.visibility;
	var originalPosition = els.position;
	els.visibility = 'hidden';
	els.position = 'absolute';
	els.display = '';
	var originalWidth = element.clientWidth;
	var originalHeight = element.clientHeight;
	els.display = 'none';
	els.position = originalPosition;
	els.visibility = originalVisibility;
	return { width: originalWidth, height: originalHeight };
};

var Position = {}
Position.cumulativeOffset = function(element) {
	var valueT = 0, valueL = 0;
	do {
		valueT += element.offsetTop  || 0;
		valueL += element.offsetLeft || 0;
		element = element.offsetParent;
	} while (element);
	return [valueL, valueT];
};

/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

/*
	This is a compiled version of Dojo, built for deployment and not for
	development. To get an editable version, please visit:

		http://dojotoolkit.org

	for documentation and information on getting the source.
*/

var dj_global=this;
function dj_undef(_1,_2){
if(!_2){
_2=dj_global;
}
return (typeof _2[_1]=="undefined");
}
if(dj_undef("djConfig")){
var djConfig={};
}
if(dj_undef("dojo")){
var dojo={};
}
dojo.version={major:0,minor:2,patch:2,flag:"+",revision:Number("$Rev: 3802 $".match(/[0-9]+/)[0]),toString:function(){
with(dojo.version){
return major+"."+minor+"."+patch+flag+" ("+revision+")";
}
}};
dojo.evalProp=function(_3,_4,_5){
return (_4&&!dj_undef(_3,_4)?_4[_3]:(_5?(_4[_3]={}):undefined));
};
dojo.parseObjPath=function(_6,_7,_8){
var _9=(_7?_7:dj_global);
var _a=_6.split(".");
var _b=_a.pop();
for(var i=0,l=_a.length;i<l&&_9;i++){
_9=dojo.evalProp(_a[i],_9,_8);
}
return {obj:_9,prop:_b};
};
dojo.evalObjPath=function(_d,_e){
if(typeof _d!="string"){
return dj_global;
}
if(_d.indexOf(".")==-1){
return dojo.evalProp(_d,dj_global,_e);
}
with(dojo.parseObjPath(_d,dj_global,_e)){
return dojo.evalProp(prop,obj,_e);
}
};
dojo.errorToString=function(_f){
return ((!dj_undef("message",_f))?_f.message:(dj_undef("description",_f)?_f:_f.description));
};
dojo.raise=function(_10,_11){
if(_11){
_10=_10+": "+dojo.errorToString(_11);
}
var he=dojo.hostenv;
if((!dj_undef("hostenv",dojo))&&(!dj_undef("println",dojo.hostenv))){
dojo.hostenv.println("FATAL: "+_10);
}
throw Error(_10);
};
dojo.debug=function(){
};
dojo.debugShallow=function(obj){
};
dojo.profile={start:function(){
},end:function(){
},stop:function(){
},dump:function(){
}};
function dj_eval(s){
return dj_global.eval?dj_global.eval(s):eval(s);
}
dojo.unimplemented=function(_15,_16){
var _17="'"+_15+"' not implemented";
if((!dj_undef(_16))&&(_16)){
_17+=" "+_16;
}
dojo.raise(_17);
};
dojo.deprecated=function(_18,_19,_1a){
var _1b="DEPRECATED: "+_18;
if(_19){
_1b+=" "+_19;
}
if(_1a){
_1b+=" -- will be removed in version: "+_1a;
}
dojo.debug(_1b);
};
dojo.inherits=function(_1c,_1d){
if(typeof _1d!="function"){
dojo.raise("dojo.inherits: superclass argument ["+_1d+"] must be a function (subclass: ["+_1c+"']");
}
_1c.prototype=new _1d();
_1c.prototype.constructor=_1c;
_1c.superclass=_1d.prototype;
_1c["super"]=_1d.prototype;
};
dojo.render=(function(){
function vscaffold(_1e,_1f){
var tmp={capable:false,support:{builtin:false,plugin:false},prefixes:_1e};
for(var x in _1f){
tmp[x]=false;
}
return tmp;
}
return {name:"",ver:dojo.version,os:{win:false,linux:false,osx:false},html:vscaffold(["html"],["ie","opera","khtml","safari","moz"]),svg:vscaffold(["svg"],["corel","adobe","batik"]),vml:vscaffold(["vml"],["ie"]),swf:vscaffold(["Swf","Flash","Mm"],["mm"]),swt:vscaffold(["Swt"],["ibm"])};
})();
dojo.hostenv=(function(){
var _22={isDebug:false,allowQueryConfig:false,baseScriptUri:"",baseRelativePath:"",libraryScriptUri:"",iePreventClobber:false,ieClobberMinimal:true,preventBackButtonFix:true,searchIds:[],parseWidgets:true};
if(typeof djConfig=="undefined"){
djConfig=_22;
}else{
for(var _23 in _22){
if(typeof djConfig[_23]=="undefined"){
djConfig[_23]=_22[_23];
}
}
}
return {name_:"(unset)",version_:"(unset)",getName:function(){
return this.name_;
},getVersion:function(){
return this.version_;
},getText:function(uri){
dojo.unimplemented("getText","uri="+uri);
}};
})();
dojo.hostenv.getBaseScriptUri=function(){
if(djConfig.baseScriptUri.length){
return djConfig.baseScriptUri;
}
var uri=new String(djConfig.libraryScriptUri||djConfig.baseRelativePath);
if(!uri){
dojo.raise("Nothing returned by getLibraryScriptUri(): "+uri);
}
var _26=uri.lastIndexOf("/");
djConfig.baseScriptUri=djConfig.baseRelativePath;
return djConfig.baseScriptUri;
};
(function(){
var _27={pkgFileName:"__package__",loading_modules_:{},loaded_modules_:{},addedToLoadingCount:[],removedFromLoadingCount:[],inFlightCount:0,modulePrefixes_:{dojo:{name:"dojo",value:"src"}},setModulePrefix:function(_28,_29){
this.modulePrefixes_[_28]={name:_28,value:_29};
},getModulePrefix:function(_2a){
var mp=this.modulePrefixes_;
if((mp[_2a])&&(mp[_2a]["name"])){
return mp[_2a].value;
}
return _2a;
},getTextStack:[],loadUriStack:[],loadedUris:[],post_load_:false,modulesLoadedListeners:[]};
for(var _2c in _27){
dojo.hostenv[_2c]=_27[_2c];
}
})();
dojo.hostenv.loadPath=function(_2d,_2e,cb){
if((_2d.charAt(0)=="/")||(_2d.match(/^\w+:/))){
dojo.raise("relpath '"+_2d+"'; must be relative");
}
var uri=this.getBaseScriptUri()+_2d;
if(djConfig.cacheBust&&dojo.render.html.capable){
uri+="?"+String(djConfig.cacheBust).replace(/\W+/g,"");
}
try{
return ((!_2e)?this.loadUri(uri,cb):this.loadUriAndCheck(uri,_2e,cb));
}
catch(e){
dojo.debug(e);
return false;
}
};
dojo.hostenv.loadUri=function(uri,cb){
if(this.loadedUris[uri]){
return;
}
var _33=this.getText(uri,null,true);
if(_33==null){
return 0;
}
this.loadedUris[uri]=true;
var _34=dj_eval(_33);
return 1;
};
dojo.hostenv.loadUriAndCheck=function(uri,_36,cb){
var ok=true;
try{
ok=this.loadUri(uri,cb);
}
catch(e){
dojo.debug("failed loading ",uri," with error: ",e);
}
return ((ok)&&(this.findModule(_36,false)))?true:false;
};
dojo.loaded=function(){
};
dojo.hostenv.loaded=function(){
this.post_load_=true;
var mll=this.modulesLoadedListeners;
this.modulesLoadedListeners=[];
for(var x=0;x<mll.length;x++){
mll[x]();
}
dojo.loaded();
};
dojo.addOnLoad=function(obj,_3c){
var dh=dojo.hostenv;
if(arguments.length==1){
dh.modulesLoadedListeners.push(obj);
}else{
if(arguments.length>1){
dh.modulesLoadedListeners.push(function(){
obj[_3c]();
});
}
}
if(dh.post_load_&&dh.inFlightCount==0){
dh.callLoaded();
}
};
dojo.hostenv.modulesLoaded=function(){
if(this.post_load_){
return;
}
if((this.loadUriStack.length==0)&&(this.getTextStack.length==0)){
if(this.inFlightCount>0){
dojo.debug("files still in flight!");
return;
}
dojo.hostenv.callLoaded();
}
};
dojo.hostenv.callLoaded=function(){
if(typeof setTimeout=="object"){
setTimeout("dojo.hostenv.loaded();",0);
}else{
dojo.hostenv.loaded();
}
};
dojo.hostenv._global_omit_module_check=false;
dojo.hostenv.loadModule=function(_3e,_3f,_40){
if(!_3e){
return;
}
_40=this._global_omit_module_check||_40;
var _41=this.findModule(_3e,false);
if(_41){
return _41;
}
if(dj_undef(_3e,this.loading_modules_)){
this.addedToLoadingCount.push(_3e);
}
this.loading_modules_[_3e]=1;
var _42=_3e.replace(/\./g,"/")+".js";
var _43=_3e.split(".");
var _44=_3e.split(".");
for(var i=_43.length-1;i>0;i--){
var _46=_43.slice(0,i).join(".");
var _47=this.getModulePrefix(_46);
if(_47!=_46){
_43.splice(0,i,_47);
break;
}
}
var _48=_43[_43.length-1];
if(_48=="*"){
_3e=(_44.slice(0,-1)).join(".");
while(_43.length){
_43.pop();
_43.push(this.pkgFileName);
_42=_43.join("/")+".js";
if(_42.charAt(0)=="/"){
_42=_42.slice(1);
}
ok=this.loadPath(_42,((!_40)?_3e:null));
if(ok){
break;
}
_43.pop();
}
}else{
_42=_43.join("/")+".js";
_3e=_44.join(".");
var ok=this.loadPath(_42,((!_40)?_3e:null));
if((!ok)&&(!_3f)){
_43.pop();
while(_43.length){
_42=_43.join("/")+".js";
ok=this.loadPath(_42,((!_40)?_3e:null));
if(ok){
break;
}
_43.pop();
_42=_43.join("/")+"/"+this.pkgFileName+".js";
if(_42.charAt(0)=="/"){
_42=_42.slice(1);
}
ok=this.loadPath(_42,((!_40)?_3e:null));
if(ok){
break;
}
}
}
if((!ok)&&(!_40)){
dojo.raise("Could not load '"+_3e+"'; last tried '"+_42+"'");
}
}
if(!_40&&!this["isXDomain"]){
_41=this.findModule(_3e,false);
if(!_41){
dojo.raise("symbol '"+_3e+"' is not defined after loading '"+_42+"'");
}
}
return _41;
};
dojo.hostenv.startPackage=function(_4a){
var _4b=dojo.evalObjPath((_4a.split(".").slice(0,-1)).join("."));
this.loaded_modules_[(new String(_4a)).toLowerCase()]=_4b;
var _4c=_4a.split(/\./);
if(_4c[_4c.length-1]=="*"){
_4c.pop();
}
return dojo.evalObjPath(_4c.join("."),true);
};
dojo.hostenv.findModule=function(_4d,_4e){
var lmn=(new String(_4d)).toLowerCase();
if(this.loaded_modules_[lmn]){
return this.loaded_modules_[lmn];
}
var _50=dojo.evalObjPath(_4d);
if((_4d)&&(typeof _50!="undefined")&&(_50)){
this.loaded_modules_[lmn]=_50;
return _50;
}
if(_4e){
dojo.raise("no loaded module named '"+_4d+"'");
}
return null;
};
dojo.kwCompoundRequire=function(_51){
var _52=_51["common"]||[];
var _53=(_51[dojo.hostenv.name_])?_52.concat(_51[dojo.hostenv.name_]||[]):_52.concat(_51["default"]||[]);
for(var x=0;x<_53.length;x++){
var _55=_53[x];
if(_55.constructor==Array){
dojo.hostenv.loadModule.apply(dojo.hostenv,_55);
}else{
dojo.hostenv.loadModule(_55);
}
}
};
dojo.require=function(){
dojo.hostenv.loadModule.apply(dojo.hostenv,arguments);
};
dojo.requireIf=function(){
if((arguments[0]===true)||(arguments[0]=="common")||(arguments[0]&&dojo.render[arguments[0]].capable)){
var _56=[];
for(var i=1;i<arguments.length;i++){
_56.push(arguments[i]);
}
dojo.require.apply(dojo,_56);
}
};
dojo.requireAfterIf=dojo.requireIf;
dojo.provide=function(){
return dojo.hostenv.startPackage.apply(dojo.hostenv,arguments);
};
dojo.setModulePrefix=function(_58,_59){
return dojo.hostenv.setModulePrefix(_58,_59);
};
dojo.exists=function(obj,_5b){
var p=_5b.split(".");
for(var i=0;i<p.length;i++){
if(!(obj[p[i]])){
return false;
}
obj=obj[p[i]];
}
return true;
};
if(typeof window=="undefined"){
dojo.raise("no window object");
}
(function(){
if(djConfig.allowQueryConfig){
var _5e=document.location.toString();
var _5f=_5e.split("?",2);
if(_5f.length>1){
var _60=_5f[1];
var _61=_60.split("&");
for(var x in _61){
var sp=_61[x].split("=");
if((sp[0].length>9)&&(sp[0].substr(0,9)=="djConfig.")){
var opt=sp[0].substr(9);
try{
djConfig[opt]=eval(sp[1]);
}
catch(e){
djConfig[opt]=sp[1];
}
}
}
}
}
if(((djConfig["baseScriptUri"]=="")||(djConfig["baseRelativePath"]==""))&&(document&&document.getElementsByTagName)){
var _65=document.getElementsByTagName("script");
var _66=/(__package__|dojo|bootstrap1)\.js([\?\.]|$)/i;
for(var i=0;i<_65.length;i++){
var src=_65[i].getAttribute("src");
if(!src){
continue;
}
var m=src.match(_66);
if(m){
root=src.substring(0,m.index);
if(src.indexOf("bootstrap1")>-1){
root+="../";
}
if(!this["djConfig"]){
djConfig={};
}
if(djConfig["baseScriptUri"]==""){
djConfig["baseScriptUri"]=root;
}
if(djConfig["baseRelativePath"]==""){
djConfig["baseRelativePath"]=root;
}
break;
}
}
}
var dr=dojo.render;
var drh=dojo.render.html;
var drs=dojo.render.svg;
var dua=drh.UA=navigator.userAgent;
var dav=drh.AV=navigator.appVersion;
var t=true;
var f=false;
drh.capable=t;
drh.support.builtin=t;
dr.ver=parseFloat(drh.AV);
dr.os.mac=dav.indexOf("Macintosh")>=0;
dr.os.win=dav.indexOf("Windows")>=0;
dr.os.linux=dav.indexOf("X11")>=0;
drh.opera=dua.indexOf("Opera")>=0;
drh.khtml=(dav.indexOf("Konqueror")>=0)||(dav.indexOf("Safari")>=0);
drh.safari=dav.indexOf("Safari")>=0;
var _71=dua.indexOf("Gecko");
drh.mozilla=drh.moz=(_71>=0)&&(!drh.khtml);
if(drh.mozilla){
drh.geckoVersion=dua.substring(_71+6,_71+14);
}
drh.ie=(document.all)&&(!drh.opera);
drh.ie50=drh.ie&&dav.indexOf("MSIE 5.0")>=0;
drh.ie55=drh.ie&&dav.indexOf("MSIE 5.5")>=0;
drh.ie60=drh.ie&&dav.indexOf("MSIE 6.0")>=0;
dr.vml.capable=drh.ie;
drs.capable=f;
drs.support.plugin=f;
drs.support.builtin=f;
if(document.implementation&&document.implementation.hasFeature&&document.implementation.hasFeature("org.w3c.dom.svg","1.0")){
drs.capable=t;
drs.support.builtin=t;
drs.support.plugin=f;
}
})();
dojo.hostenv.startPackage("dojo.hostenv");
dojo.render.name=dojo.hostenv.name_="browser";
dojo.hostenv.searchIds=[];
var DJ_XMLHTTP_PROGIDS=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"];
dojo.hostenv.getXmlhttpObject=function(){
var _72=null;
var _73=null;
try{
_72=new XMLHttpRequest();
}
catch(e){
}
if(!_72){
for(var i=0;i<3;++i){
var _75=DJ_XMLHTTP_PROGIDS[i];
try{
_72=new ActiveXObject(_75);
}
catch(e){
_73=e;
}
if(_72){
DJ_XMLHTTP_PROGIDS=[_75];
break;
}
}
}
if(!_72){
return dojo.raise("XMLHTTP not available",_73);
}
return _72;
};
dojo.hostenv.getText=function(uri,_77,_78){
var _79=this.getXmlhttpObject();
if(_77){
_79.onreadystatechange=function(){
if((4==_79.readyState)&&(_79["status"])){
if(_79.status==200){
_77(_79.responseText);
}
}
};
}
_79.open("GET",uri,_77?true:false);
try{
_79.send(null);
}
catch(e){
if(_78&&!_77){
return null;
}else{
throw e;
}
}
if(_77){
return null;
}
return _79.responseText;
};
dojo.hostenv.defaultDebugContainerId="dojoDebug";
dojo.hostenv._println_buffer=[];
dojo.hostenv._println_safe=false;
dojo.hostenv.println=function(_7a){
if(!dojo.hostenv._println_safe){
dojo.hostenv._println_buffer.push(_7a);
}else{
try{
var _7b=document.getElementById(djConfig.debugContainerId?djConfig.debugContainerId:dojo.hostenv.defaultDebugContainerId);
if(!_7b){
_7b=document.getElementsByTagName("body")[0]||document.body;
}
var div=document.createElement("div");
div.appendChild(document.createTextNode(_7a));
_7b.appendChild(div);
}
catch(e){
try{
document.write("<div>"+_7a+"</div>");
}
catch(e2){
window.status=_7a;
}
}
}
};
dojo.addOnLoad(function(){
dojo.hostenv._println_safe=true;
while(dojo.hostenv._println_buffer.length>0){
dojo.hostenv.println(dojo.hostenv._println_buffer.shift());
}
});
function dj_addNodeEvtHdlr(_7d,_7e,fp,_80){
var _81=_7d["on"+_7e]||function(){
};
_7d["on"+_7e]=function(){
fp.apply(_7d,arguments);
_81.apply(_7d,arguments);
};
return true;
}
dj_addNodeEvtHdlr(window,"load",function(){
if(arguments.callee.initialized){
return;
}
arguments.callee.initialized=true;
var _82=function(){
if(dojo.render.html.ie){
dojo.hostenv.makeWidgets();
}
};
if(dojo.hostenv.inFlightCount==0){
_82();
dojo.hostenv.modulesLoaded();
}else{
dojo.addOnLoad(_82);
}
});
dojo.hostenv.makeWidgets=function(){
var _83=[];
if(djConfig.searchIds&&djConfig.searchIds.length>0){
_83=_83.concat(djConfig.searchIds);
}
if(dojo.hostenv.searchIds&&dojo.hostenv.searchIds.length>0){
_83=_83.concat(dojo.hostenv.searchIds);
}
if((djConfig.parseWidgets)||(_83.length>0)){
if(dojo.evalObjPath("dojo.widget.Parse")){
try{
var _84=new dojo.xml.Parse();
if(_83.length>0){
for(var x=0;x<_83.length;x++){
var _86=document.getElementById(_83[x]);
if(!_86){
continue;
}
var _87=_84.parseElement(_86,null,true);
dojo.widget.getParser().createComponents(_87);
}
}else{
if(djConfig.parseWidgets){
var _87=_84.parseElement(document.getElementsByTagName("body")[0]||document.body,null,true);
dojo.widget.getParser().createComponents(_87);
}
}
}
catch(e){
dojo.debug("auto-build-widgets error:",e);
}
}
}
};
dojo.addOnLoad(function(){
if(!dojo.render.html.ie){
dojo.hostenv.makeWidgets();
}
});
try{
if(dojo.render.html.ie){
document.namespaces.add("v","urn:schemas-microsoft-com:vml");
document.createStyleSheet().addRule("v\\:*","behavior:url(#default#VML)");
}
}
catch(e){
}
dojo.hostenv.writeIncludes=function(){
};
dojo.byId=function(id,doc){
if(id&&(typeof id=="string"||id instanceof String)){
if(!doc){
doc=document;
}
return doc.getElementById(id);
}
return id;
};
(function(){
if(typeof dj_usingBootstrap!="undefined"){
return;
}
var _8a=false;
var _8b=false;
var _8c=false;
if((typeof this["load"]=="function")&&(typeof this["Packages"]=="function")){
_8a=true;
}else{
if(typeof this["load"]=="function"){
_8b=true;
}else{
if(window.widget){
_8c=true;
}
}
}
var _8d=[];
if((this["djConfig"])&&((djConfig["isDebug"])||(djConfig["debugAtAllCosts"]))){
_8d.push("debug.js");
}
if((this["djConfig"])&&(djConfig["debugAtAllCosts"])&&(!_8a)&&(!_8c)){
_8d.push("browser_debug.js");
}
if((this["djConfig"])&&(djConfig["compat"])){
_8d.push("compat/"+djConfig["compat"]+".js");
}
var _8e=djConfig["baseScriptUri"];
if((this["djConfig"])&&(djConfig["baseLoaderUri"])){
_8e=djConfig["baseLoaderUri"];
}
for(var x=0;x<_8d.length;x++){
var _90=_8e+"src/"+_8d[x];
if(_8a||_8b){
load(_90);
}else{
try{
document.write("<scr"+"ipt type='text/javascript' src='"+_90+"'></scr"+"ipt>");
}
catch(e){
var _91=document.createElement("script");
_91.src=_90;
document.getElementsByTagName("head")[0].appendChild(_91);
}
}
}
})();
dojo.provide("dojo.lang.common");
dojo.require("dojo.lang");
dojo.lang.mixin=function(obj,_93){
var _94={};
for(var x in _93){
if(typeof _94[x]=="undefined"||_94[x]!=_93[x]){
obj[x]=_93[x];
}
}
if(dojo.render.html.ie&&dojo.lang.isFunction(_93["toString"])&&_93["toString"]!=obj["toString"]){
obj.toString=_93.toString;
}
return obj;
};
dojo.lang.extend=function(_96,_97){
this.mixin(_96.prototype,_97);
};
dojo.lang.find=function(arr,val,_9a,_9b){
if(!dojo.lang.isArrayLike(arr)&&dojo.lang.isArrayLike(val)){
var a=arr;
arr=val;
val=a;
}
var _9d=dojo.lang.isString(arr);
if(_9d){
arr=arr.split("");
}
if(_9b){
var _9e=-1;
var i=arr.length-1;
var end=-1;
}else{
var _9e=1;
var i=0;
var end=arr.length;
}
if(_9a){
while(i!=end){
if(arr[i]===val){
return i;
}
i+=_9e;
}
}else{
while(i!=end){
if(arr[i]==val){
return i;
}
i+=_9e;
}
}
return -1;
};
dojo.lang.indexOf=dojo.lang.find;
dojo.lang.findLast=function(arr,val,_a3){
return dojo.lang.find(arr,val,_a3,true);
};
dojo.lang.lastIndexOf=dojo.lang.findLast;
dojo.lang.inArray=function(arr,val){
return dojo.lang.find(arr,val)>-1;
};
dojo.lang.isObject=function(wh){
return typeof wh=="object"||dojo.lang.isArray(wh)||dojo.lang.isFunction(wh);
};
dojo.lang.isArray=function(wh){
return (wh instanceof Array||typeof wh=="array");
};
dojo.lang.isArrayLike=function(wh){
if(dojo.lang.isString(wh)){
return false;
}
if(dojo.lang.isFunction(wh)){
return false;
}
if(dojo.lang.isArray(wh)){
return true;
}
if(typeof wh!="undefined"&&wh&&dojo.lang.isNumber(wh.length)&&isFinite(wh.length)){
return true;
}
return false;
};
dojo.lang.isFunction=function(wh){
return (wh instanceof Function||typeof wh=="function");
};
dojo.lang.isString=function(wh){
return (wh instanceof String||typeof wh=="string");
};
dojo.lang.isAlien=function(wh){
return !dojo.lang.isFunction()&&/\{\s*\[native code\]\s*\}/.test(String(wh));
};
dojo.lang.isBoolean=function(wh){
return (wh instanceof Boolean||typeof wh=="boolean");
};
dojo.lang.isNumber=function(wh){
return (wh instanceof Number||typeof wh=="number");
};
dojo.lang.isUndefined=function(wh){
return ((wh==undefined)&&(typeof wh=="undefined"));
};
dojo.provide("dojo.lang");
dojo.provide("dojo.lang.Lang");
dojo.require("dojo.lang.common");
dojo.provide("dojo.lang.func");
dojo.require("dojo.lang.common");
dojo.lang.hitch=function(_af,_b0){
if(dojo.lang.isString(_b0)){
var fcn=_af[_b0];
}else{
var fcn=_b0;
}
return function(){
return fcn.apply(_af,arguments);
};
};
dojo.lang.anonCtr=0;
dojo.lang.anon={};
dojo.lang.nameAnonFunc=function(_b2,_b3){
var nso=(_b3||dojo.lang.anon);
if((dj_global["djConfig"])&&(djConfig["slowAnonFuncLookups"]==true)){
for(var x in nso){
if(nso[x]===_b2){
return x;
}
}
}
var ret="__"+dojo.lang.anonCtr++;
while(typeof nso[ret]!="undefined"){
ret="__"+dojo.lang.anonCtr++;
}
nso[ret]=_b2;
return ret;
};
dojo.lang.forward=function(_b7){
return function(){
return this[_b7].apply(this,arguments);
};
};
dojo.lang.curry=function(ns,_b9){
var _ba=[];
ns=ns||dj_global;
if(dojo.lang.isString(_b9)){
_b9=ns[_b9];
}
for(var x=2;x<arguments.length;x++){
_ba.push(arguments[x]);
}
var _bc=(_b9["__preJoinArity"]||_b9.length)-_ba.length;
function gather(_bd,_be,_bf){
var _c0=_bf;
var _c1=_be.slice(0);
for(var x=0;x<_bd.length;x++){
_c1.push(_bd[x]);
}
_bf=_bf-_bd.length;
if(_bf<=0){
var res=_b9.apply(ns,_c1);
_bf=_c0;
return res;
}else{
return function(){
return gather(arguments,_c1,_bf);
};
}
}
return gather([],_ba,_bc);
};
dojo.lang.curryArguments=function(ns,_c5,_c6,_c7){
var _c8=[];
var x=_c7||0;
for(x=_c7;x<_c6.length;x++){
_c8.push(_c6[x]);
}
return dojo.lang.curry.apply(dojo.lang,[ns,_c5].concat(_c8));
};
dojo.lang.tryThese=function(){
for(var x=0;x<arguments.length;x++){
try{
if(typeof arguments[x]=="function"){
var ret=(arguments[x]());
if(ret){
return ret;
}
}
}
catch(e){
dojo.debug(e);
}
}
};
dojo.lang.delayThese=function(_cc,cb,_ce,_cf){
if(!_cc.length){
if(typeof _cf=="function"){
_cf();
}
return;
}
if((typeof _ce=="undefined")&&(typeof cb=="number")){
_ce=cb;
cb=function(){
};
}else{
if(!cb){
cb=function(){
};
if(!_ce){
_ce=0;
}
}
}
setTimeout(function(){
(_cc.shift())();
cb();
dojo.lang.delayThese(_cc,cb,_ce,_cf);
},_ce);
};
dojo.provide("dojo.lang.array");
dojo.require("dojo.lang.common");
dojo.lang.has=function(obj,_d1){
try{
return (typeof obj[_d1]!="undefined");
}
catch(e){
return false;
}
};
dojo.lang.isEmpty=function(obj){
if(dojo.lang.isObject(obj)){
var tmp={};
var _d4=0;
for(var x in obj){
if(obj[x]&&(!tmp[x])){
_d4++;
break;
}
}
return (_d4==0);
}else{
if(dojo.lang.isArrayLike(obj)||dojo.lang.isString(obj)){
return obj.length==0;
}
}
};
dojo.lang.map=function(arr,obj,_d8){
var _d9=dojo.lang.isString(arr);
if(_d9){
arr=arr.split("");
}
if(dojo.lang.isFunction(obj)&&(!_d8)){
_d8=obj;
obj=dj_global;
}else{
if(dojo.lang.isFunction(obj)&&_d8){
var _da=obj;
obj=_d8;
_d8=_da;
}
}
if(Array.map){
var _db=Array.map(arr,_d8,obj);
}else{
var _db=[];
for(var i=0;i<arr.length;++i){
_db.push(_d8.call(obj,arr[i]));
}
}
if(_d9){
return _db.join("");
}else{
return _db;
}
};
dojo.lang.forEach=function(_dd,_de,_df){
if(dojo.lang.isString(_dd)){
_dd=_dd.split("");
}
if(Array.forEach){
Array.forEach(_dd,_de,_df);
}else{
if(!_df){
_df=dj_global;
}
for(var i=0,l=_dd.length;i<l;i++){
_de.call(_df,_dd[i],i,_dd);
}
}
};
dojo.lang._everyOrSome=function(_e1,arr,_e3,_e4){
if(dojo.lang.isString(arr)){
arr=arr.split("");
}
if(Array.every){
return Array[(_e1)?"every":"some"](arr,_e3,_e4);
}else{
if(!_e4){
_e4=dj_global;
}
for(var i=0,l=arr.length;i<l;i++){
var _e6=_e3.call(_e4,arr[i],i,arr);
if((_e1)&&(!_e6)){
return false;
}else{
if((!_e1)&&(_e6)){
return true;
}
}
}
return (_e1)?true:false;
}
};
dojo.lang.every=function(arr,_e8,_e9){
return this._everyOrSome(true,arr,_e8,_e9);
};
dojo.lang.some=function(arr,_eb,_ec){
return this._everyOrSome(false,arr,_eb,_ec);
};
dojo.lang.filter=function(arr,_ee,_ef){
var _f0=dojo.lang.isString(arr);
if(_f0){
arr=arr.split("");
}
if(Array.filter){
var _f1=Array.filter(arr,_ee,_ef);
}else{
if(!_ef){
if(arguments.length>=3){
dojo.raise("thisObject doesn't exist!");
}
_ef=dj_global;
}
var _f1=[];
for(var i=0;i<arr.length;i++){
if(_ee.call(_ef,arr[i],i,arr)){
_f1.push(arr[i]);
}
}
}
if(_f0){
return _f1.join("");
}else{
return _f1;
}
};
dojo.lang.unnest=function(){
var out=[];
for(var i=0;i<arguments.length;i++){
if(dojo.lang.isArrayLike(arguments[i])){
var add=dojo.lang.unnest.apply(this,arguments[i]);
out=out.concat(add);
}else{
out.push(arguments[i]);
}
}
return out;
};
dojo.lang.toArray=function(_f6,_f7){
var _f8=[];
for(var i=_f7||0;i<_f6.length;i++){
_f8.push(_f6[i]);
}
return _f8;
};
dojo.provide("dojo.dom");
dojo.require("dojo.lang.array");
dojo.dom.ELEMENT_NODE=1;
dojo.dom.ATTRIBUTE_NODE=2;
dojo.dom.TEXT_NODE=3;
dojo.dom.CDATA_SECTION_NODE=4;
dojo.dom.ENTITY_REFERENCE_NODE=5;
dojo.dom.ENTITY_NODE=6;
dojo.dom.PROCESSING_INSTRUCTION_NODE=7;
dojo.dom.COMMENT_NODE=8;
dojo.dom.DOCUMENT_NODE=9;
dojo.dom.DOCUMENT_TYPE_NODE=10;
dojo.dom.DOCUMENT_FRAGMENT_NODE=11;
dojo.dom.NOTATION_NODE=12;
dojo.dom.dojoml="http://www.dojotoolkit.org/2004/dojoml";
dojo.dom.xmlns={svg:"http://www.w3.org/2000/svg",smil:"http://www.w3.org/2001/SMIL20/",mml:"http://www.w3.org/1998/Math/MathML",cml:"http://www.xml-cml.org",xlink:"http://www.w3.org/1999/xlink",xhtml:"http://www.w3.org/1999/xhtml",xul:"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",xbl:"http://www.mozilla.org/xbl",fo:"http://www.w3.org/1999/XSL/Format",xsl:"http://www.w3.org/1999/XSL/Transform",xslt:"http://www.w3.org/1999/XSL/Transform",xi:"http://www.w3.org/2001/XInclude",xforms:"http://www.w3.org/2002/01/xforms",saxon:"http://icl.com/saxon",xalan:"http://xml.apache.org/xslt",xsd:"http://www.w3.org/2001/XMLSchema",dt:"http://www.w3.org/2001/XMLSchema-datatypes",xsi:"http://www.w3.org/2001/XMLSchema-instance",rdf:"http://www.w3.org/1999/02/22-rdf-syntax-ns#",rdfs:"http://www.w3.org/2000/01/rdf-schema#",dc:"http://purl.org/dc/elements/1.1/",dcq:"http://purl.org/dc/qualifiers/1.0","soap-env":"http://schemas.xmlsoap.org/soap/envelope/",wsdl:"http://schemas.xmlsoap.org/wsdl/",AdobeExtensions:"http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"};
dojo.dom.isNode=function(wh){
if(typeof Element=="object"){
try{
return wh instanceof Element;
}
catch(E){
}
}else{
return wh&&!isNaN(wh.nodeType);
}
};
dojo.dom.getTagName=function(_fb){
dojo.deprecated("dojo.dom.getTagName","use node.tagName instead","0.4");
var _fc=_fb.tagName;
if(_fc.substr(0,5).toLowerCase()!="dojo:"){
if(_fc.substr(0,4).toLowerCase()=="dojo"){
return "dojo:"+_fc.substring(4).toLowerCase();
}
var djt=_fb.getAttribute("dojoType")||_fb.getAttribute("dojotype");
if(djt){
return "dojo:"+djt.toLowerCase();
}
if((_fb.getAttributeNS)&&(_fb.getAttributeNS(this.dojoml,"type"))){
return "dojo:"+_fb.getAttributeNS(this.dojoml,"type").toLowerCase();
}
try{
djt=_fb.getAttribute("dojo:type");
}
catch(e){
}
if(djt){
return "dojo:"+djt.toLowerCase();
}
if((!dj_global["djConfig"])||(!djConfig["ignoreClassNames"])){
var _fe=_fb.className||_fb.getAttribute("class");
if((_fe)&&(_fe.indexOf)&&(_fe.indexOf("dojo-")!=-1)){
var _ff=_fe.split(" ");
for(var x=0;x<_ff.length;x++){
if((_ff[x].length>5)&&(_ff[x].indexOf("dojo-")>=0)){
return "dojo:"+_ff[x].substr(5).toLowerCase();
}
}
}
}
}
return _fc.toLowerCase();
};
dojo.dom.getUniqueId=function(){
do{
var id="dj_unique_"+(++arguments.callee._idIncrement);
}while(document.getElementById(id));
return id;
};
dojo.dom.getUniqueId._idIncrement=0;
dojo.dom.firstElement=dojo.dom.getFirstChildElement=function(_102,_103){
var node=_102.firstChild;
while(node&&node.nodeType!=dojo.dom.ELEMENT_NODE){
node=node.nextSibling;
}
if(_103&&node&&node.tagName&&node.tagName.toLowerCase()!=_103.toLowerCase()){
node=dojo.dom.nextElement(node,_103);
}
return node;
};
dojo.dom.lastElement=dojo.dom.getLastChildElement=function(_105,_106){
var node=_105.lastChild;
while(node&&node.nodeType!=dojo.dom.ELEMENT_NODE){
node=node.previousSibling;
}
if(_106&&node&&node.tagName&&node.tagName.toLowerCase()!=_106.toLowerCase()){
node=dojo.dom.prevElement(node,_106);
}
return node;
};
dojo.dom.nextElement=dojo.dom.getNextSiblingElement=function(node,_109){
if(!node){
return null;
}
do{
node=node.nextSibling;
}while(node&&node.nodeType!=dojo.dom.ELEMENT_NODE);
if(node&&_109&&_109.toLowerCase()!=node.tagName.toLowerCase()){
return dojo.dom.nextElement(node,_109);
}
return node;
};
dojo.dom.prevElement=dojo.dom.getPreviousSiblingElement=function(node,_10b){
if(!node){
return null;
}
if(_10b){
_10b=_10b.toLowerCase();
}
do{
node=node.previousSibling;
}while(node&&node.nodeType!=dojo.dom.ELEMENT_NODE);
if(node&&_10b&&_10b.toLowerCase()!=node.tagName.toLowerCase()){
return dojo.dom.prevElement(node,_10b);
}
return node;
};
dojo.dom.moveChildren=function(_10c,_10d,trim){
var _10f=0;
if(trim){
while(_10c.hasChildNodes()&&_10c.firstChild.nodeType==dojo.dom.TEXT_NODE){
_10c.removeChild(_10c.firstChild);
}
while(_10c.hasChildNodes()&&_10c.lastChild.nodeType==dojo.dom.TEXT_NODE){
_10c.removeChild(_10c.lastChild);
}
}
while(_10c.hasChildNodes()){
_10d.appendChild(_10c.firstChild);
_10f++;
}
return _10f;
};
dojo.dom.copyChildren=function(_110,_111,trim){
var _113=_110.cloneNode(true);
return this.moveChildren(_113,_111,trim);
};
dojo.dom.removeChildren=function(node){
var _115=node.childNodes.length;
while(node.hasChildNodes()){
node.removeChild(node.firstChild);
}
return _115;
};
dojo.dom.replaceChildren=function(node,_117){
dojo.dom.removeChildren(node);
node.appendChild(_117);
};
dojo.dom.removeNode=function(node){
if(node&&node.parentNode){
return node.parentNode.removeChild(node);
}
};
dojo.dom.getAncestors=function(node,_11a,_11b){
var _11c=[];
var _11d=dojo.lang.isFunction(_11a);
while(node){
if(!_11d||_11a(node)){
_11c.push(node);
}
if(_11b&&_11c.length>0){
return _11c[0];
}
node=node.parentNode;
}
if(_11b){
return null;
}
return _11c;
};
dojo.dom.getAncestorsByTag=function(node,tag,_120){
tag=tag.toLowerCase();
return dojo.dom.getAncestors(node,function(el){
return ((el.tagName)&&(el.tagName.toLowerCase()==tag));
},_120);
};
dojo.dom.getFirstAncestorByTag=function(node,tag){
return dojo.dom.getAncestorsByTag(node,tag,true);
};
dojo.dom.isDescendantOf=function(node,_125,_126){
if(_126&&node){
node=node.parentNode;
}
while(node){
if(node==_125){
return true;
}
node=node.parentNode;
}
return false;
};
dojo.dom.innerXML=function(node){
if(node.innerXML){
return node.innerXML;
}else{
if(typeof XMLSerializer!="undefined"){
return (new XMLSerializer()).serializeToString(node);
}
}
};
dojo.dom.createDocumentFromText=function(str,_129){
if(!_129){
_129="text/xml";
}
if(typeof DOMParser!="undefined"){
var _12a=new DOMParser();
return _12a.parseFromString(str,_129);
}else{
if(typeof ActiveXObject!="undefined"){
var _12b=new ActiveXObject("Microsoft.XMLDOM");
if(_12b){
_12b.async=false;
_12b.loadXML(str);
return _12b;
}else{
dojo.debug("toXml didn't work?");
}
}else{
if(document.createElement){
var tmp=document.createElement("xml");
tmp.innerHTML=str;
if(document.implementation&&document.implementation.createDocument){
var _12d=document.implementation.createDocument("foo","",null);
for(var i=0;i<tmp.childNodes.length;i++){
_12d.importNode(tmp.childNodes.item(i),true);
}
return _12d;
}
return tmp.document&&tmp.document.firstChild?tmp.document.firstChild:tmp;
}
}
}
return null;
};
dojo.dom.prependChild=function(node,_130){
if(_130.firstChild){
_130.insertBefore(node,_130.firstChild);
}else{
_130.appendChild(node);
}
return true;
};
dojo.dom.insertBefore=function(node,ref,_133){
if(_133!=true&&(node===ref||node.nextSibling===ref)){
return false;
}
var _134=ref.parentNode;
_134.insertBefore(node,ref);
return true;
};
dojo.dom.insertAfter=function(node,ref,_137){
var pn=ref.parentNode;
if(ref==pn.lastChild){
if((_137!=true)&&(node===ref)){
return false;
}
pn.appendChild(node);
}else{
return this.insertBefore(node,ref.nextSibling,_137);
}
return true;
};
dojo.dom.insertAtPosition=function(node,ref,_13b){
if((!node)||(!ref)||(!_13b)){
return false;
}
switch(_13b.toLowerCase()){
case "before":
return dojo.dom.insertBefore(node,ref);
case "after":
return dojo.dom.insertAfter(node,ref);
case "first":
if(ref.firstChild){
return dojo.dom.insertBefore(node,ref.firstChild);
}else{
ref.appendChild(node);
return true;
}
break;
default:
ref.appendChild(node);
return true;
}
};
dojo.dom.insertAtIndex=function(node,_13d,_13e){
var _13f=_13d.childNodes;
if(!_13f.length){
_13d.appendChild(node);
return true;
}
var _140=null;
for(var i=0;i<_13f.length;i++){
var _142=_13f.item(i)["getAttribute"]?parseInt(_13f.item(i).getAttribute("dojoinsertionindex")):-1;
if(_142<_13e){
_140=_13f.item(i);
}
}
if(_140){
return dojo.dom.insertAfter(node,_140);
}else{
return dojo.dom.insertBefore(node,_13f.item(0));
}
};
dojo.dom.textContent=function(node,text){
if(text){
dojo.dom.replaceChildren(node,document.createTextNode(text));
return text;
}else{
var _145="";
if(node==null){
return _145;
}
for(var i=0;i<node.childNodes.length;i++){
switch(node.childNodes[i].nodeType){
case 1:
case 5:
_145+=dojo.dom.textContent(node.childNodes[i]);
break;
case 3:
case 2:
case 4:
_145+=node.childNodes[i].nodeValue;
break;
default:
break;
}
}
return _145;
}
};
dojo.dom.collectionToArray=function(_147){
dojo.deprecated("dojo.dom.collectionToArray","use dojo.lang.toArray instead","0.4");
return dojo.lang.toArray(_147);
};
dojo.dom.hasParent=function(node){
return node&&node.parentNode&&dojo.dom.isNode(node.parentNode);
};
dojo.dom.isTag=function(node){
if(node&&node.tagName){
var arr=dojo.lang.toArray(arguments,1);
return arr[dojo.lang.find(node.tagName,arr)]||"";
}
return "";
};
dojo.provide("dojo.graphics.color");
dojo.require("dojo.lang.array");
dojo.graphics.color.Color=function(r,g,b,a){
if(dojo.lang.isArray(r)){
this.r=r[0];
this.g=r[1];
this.b=r[2];
this.a=r[3]||1;
}else{
if(dojo.lang.isString(r)){
var rgb=dojo.graphics.color.extractRGB(r);
this.r=rgb[0];
this.g=rgb[1];
this.b=rgb[2];
this.a=g||1;
}else{
if(r instanceof dojo.graphics.color.Color){
this.r=r.r;
this.b=r.b;
this.g=r.g;
this.a=r.a;
}else{
this.r=r;
this.g=g;
this.b=b;
this.a=a;
}
}
}
};
dojo.graphics.color.Color.fromArray=function(arr){
return new dojo.graphics.color.Color(arr[0],arr[1],arr[2],arr[3]);
};
dojo.lang.extend(dojo.graphics.color.Color,{toRgb:function(_151){
if(_151){
return this.toRgba();
}else{
return [this.r,this.g,this.b];
}
},toRgba:function(){
return [this.r,this.g,this.b,this.a];
},toHex:function(){
return dojo.graphics.color.rgb2hex(this.toRgb());
},toCss:function(){
return "rgb("+this.toRgb().join()+")";
},toString:function(){
return this.toHex();
},blend:function(_152,_153){
return dojo.graphics.color.blend(this.toRgb(),new Color(_152).toRgb(),_153);
}});
dojo.graphics.color.named={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],blue:[0,0,255],navy:[0,0,128],gray:[128,128,128],silver:[192,192,192]};
dojo.graphics.color.blend=function(a,b,_156){
if(typeof a=="string"){
return dojo.graphics.color.blendHex(a,b,_156);
}
if(!_156){
_156=0;
}else{
if(_156>1){
_156=1;
}else{
if(_156<-1){
_156=-1;
}
}
}
var c=new Array(3);
for(var i=0;i<3;i++){
var half=Math.abs(a[i]-b[i])/2;
c[i]=Math.floor(Math.min(a[i],b[i])+half+(half*_156));
}
return c;
};
dojo.graphics.color.blendHex=function(a,b,_15c){
return dojo.graphics.color.rgb2hex(dojo.graphics.color.blend(dojo.graphics.color.hex2rgb(a),dojo.graphics.color.hex2rgb(b),_15c));
};
dojo.graphics.color.extractRGB=function(_15d){
var hex="0123456789abcdef";
_15d=_15d.toLowerCase();
if(_15d.indexOf("rgb")==0){
var _15f=_15d.match(/rgba*\((\d+), *(\d+), *(\d+)/i);
var ret=_15f.splice(1,3);
return ret;
}else{
var _161=dojo.graphics.color.hex2rgb(_15d);
if(_161){
return _161;
}else{
return dojo.graphics.color.named[_15d]||[255,255,255];
}
}
};
dojo.graphics.color.hex2rgb=function(hex){
var _163="0123456789ABCDEF";
var rgb=new Array(3);
if(hex.indexOf("#")==0){
hex=hex.substring(1);
}
hex=hex.toUpperCase();
if(hex.replace(new RegExp("["+_163+"]","g"),"")!=""){
return null;
}
if(hex.length==3){
rgb[0]=hex.charAt(0)+hex.charAt(0);
rgb[1]=hex.charAt(1)+hex.charAt(1);
rgb[2]=hex.charAt(2)+hex.charAt(2);
}else{
rgb[0]=hex.substring(0,2);
rgb[1]=hex.substring(2,4);
rgb[2]=hex.substring(4);
}
for(var i=0;i<rgb.length;i++){
rgb[i]=_163.indexOf(rgb[i].charAt(0))*16+_163.indexOf(rgb[i].charAt(1));
}
return rgb;
};
dojo.graphics.color.rgb2hex=function(r,g,b){
if(dojo.lang.isArray(r)){
g=r[1]||0;
b=r[2]||0;
r=r[0]||0;
}
var ret=dojo.lang.map([r,g,b],function(x){
x=new Number(x);
var s=x.toString(16);
while(s.length<2){
s="0"+s;
}
return s;
});
ret.unshift("#");
return ret.join("");
};
dojo.provide("dojo.uri.Uri");
dojo.uri=new function(){
this.joinPath=function(){
var arr=[];
for(var i=0;i<arguments.length;i++){
arr.push(arguments[i]);
}
return arr.join("/").replace(/\/{2,}/g,"/").replace(/((https*|ftps*):)/i,"$1/");
};
this.dojoUri=function(uri){
return new dojo.uri.Uri(dojo.hostenv.getBaseScriptUri(),uri);
};
this.Uri=function(){
var uri=arguments[0];
for(var i=1;i<arguments.length;i++){
if(!arguments[i]){
continue;
}
var _171=new dojo.uri.Uri(arguments[i].toString());
var _172=new dojo.uri.Uri(uri.toString());
if(_171.path==""&&_171.scheme==null&&_171.authority==null&&_171.query==null){
if(_171.fragment!=null){
_172.fragment=_171.fragment;
}
_171=_172;
}else{
if(_171.scheme==null){
_171.scheme=_172.scheme;
if(_171.authority==null){
_171.authority=_172.authority;
if(_171.path.charAt(0)!="/"){
var path=_172.path.substring(0,_172.path.lastIndexOf("/")+1)+_171.path;
var segs=path.split("/");
for(var j=0;j<segs.length;j++){
if(segs[j]=="."){
if(j==segs.length-1){
segs[j]="";
}else{
segs.splice(j,1);
j--;
}
}else{
if(j>0&&!(j==1&&segs[0]=="")&&segs[j]==".."&&segs[j-1]!=".."){
if(j==segs.length-1){
segs.splice(j,1);
segs[j-1]="";
}else{
segs.splice(j-1,2);
j-=2;
}
}
}
}
_171.path=segs.join("/");
}
}
}
}
uri="";
if(_171.scheme!=null){
uri+=_171.scheme+":";
}
if(_171.authority!=null){
uri+="//"+_171.authority;
}
uri+=_171.path;
if(_171.query!=null){
uri+="?"+_171.query;
}
if(_171.fragment!=null){
uri+="#"+_171.fragment;
}
}
this.uri=uri.toString();
var _176="^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$";
var r=this.uri.match(new RegExp(_176));
this.scheme=r[2]||(r[1]?"":null);
this.authority=r[4]||(r[3]?"":null);
this.path=r[5];
this.query=r[7]||(r[6]?"":null);
this.fragment=r[9]||(r[8]?"":null);
if(this.authority!=null){
_176="^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$";
r=this.authority.match(new RegExp(_176));
this.user=r[3]||null;
this.password=r[4]||null;
this.host=r[5];
this.port=r[7]||null;
}
this.toString=function(){
return this.uri;
};
};
};
dojo.provide("dojo.style");
dojo.require("dojo.graphics.color");
dojo.require("dojo.uri.Uri");
dojo.require("dojo.lang.common");
(function(){
var h=dojo.render.html;
var ds=dojo.style;
var db=document["body"]||document["documentElement"];
ds.boxSizing={MARGIN_BOX:"margin-box",BORDER_BOX:"border-box",PADDING_BOX:"padding-box",CONTENT_BOX:"content-box"};
var bs=ds.boxSizing;
ds.getBoxSizing=function(node){
if((h.ie)||(h.opera)){
var cm=document["compatMode"];
if((cm=="BackCompat")||(cm=="QuirksMode")){
return bs.BORDER_BOX;
}else{
return bs.CONTENT_BOX;
}
}else{
if(arguments.length==0){
node=document.documentElement;
}
var _17e=ds.getStyle(node,"-moz-box-sizing");
if(!_17e){
_17e=ds.getStyle(node,"box-sizing");
}
return (_17e?_17e:bs.CONTENT_BOX);
}
};
ds.isBorderBox=function(node){
return (ds.getBoxSizing(node)==bs.BORDER_BOX);
};
ds.getUnitValue=function(node,_181,_182){
var s=ds.getComputedStyle(node,_181);
if((!s)||((s=="auto")&&(_182))){
return {value:0,units:"px"};
}
if(dojo.lang.isUndefined(s)){
return ds.getUnitValue.bad;
}
var _184=s.match(/(\-?[\d.]+)([a-z%]*)/i);
if(!_184){
return ds.getUnitValue.bad;
}
return {value:Number(_184[1]),units:_184[2].toLowerCase()};
};
ds.getUnitValue.bad={value:NaN,units:""};
ds.getPixelValue=function(node,_186,_187){
var _188=ds.getUnitValue(node,_186,_187);
if(isNaN(_188.value)){
return 0;
}
if((_188.value)&&(_188.units!="px")){
return NaN;
}
return _188.value;
};
ds.getNumericStyle=function(){
dojo.deprecated("dojo.(style|html).getNumericStyle","in favor of dojo.(style|html).getPixelValue","0.4");
return ds.getPixelValue.apply(this,arguments);
};
ds.setPositivePixelValue=function(node,_18a,_18b){
if(isNaN(_18b)){
return false;
}
node.style[_18a]=Math.max(0,_18b)+"px";
return true;
};
ds._sumPixelValues=function(node,_18d,_18e){
var _18f=0;
for(x=0;x<_18d.length;x++){
_18f+=ds.getPixelValue(node,_18d[x],_18e);
}
return _18f;
};
ds.isPositionAbsolute=function(node){
return (ds.getComputedStyle(node,"position")=="absolute");
};
ds.getBorderExtent=function(node,side){
return (ds.getStyle(node,"border-"+side+"-style")=="none"?0:ds.getPixelValue(node,"border-"+side+"-width"));
};
ds.getMarginWidth=function(node){
return ds._sumPixelValues(node,["margin-left","margin-right"],ds.isPositionAbsolute(node));
};
ds.getBorderWidth=function(node){
return ds.getBorderExtent(node,"left")+ds.getBorderExtent(node,"right");
};
ds.getPaddingWidth=function(node){
return ds._sumPixelValues(node,["padding-left","padding-right"],true);
};
ds.getPadBorderWidth=function(node){
return ds.getPaddingWidth(node)+ds.getBorderWidth(node);
};
ds.getContentBoxWidth=function(node){
node=dojo.byId(node);
return node.offsetWidth-ds.getPadBorderWidth(node);
};
ds.getBorderBoxWidth=function(node){
node=dojo.byId(node);
return node.offsetWidth;
};
ds.getMarginBoxWidth=function(node){
return ds.getInnerWidth(node)+ds.getMarginWidth(node);
};
ds.setContentBoxWidth=function(node,_19b){
node=dojo.byId(node);
if(ds.isBorderBox(node)){
_19b+=ds.getPadBorderWidth(node);
}
return ds.setPositivePixelValue(node,"width",_19b);
};
ds.setMarginBoxWidth=function(node,_19d){
node=dojo.byId(node);
if(!ds.isBorderBox(node)){
_19d-=ds.getPadBorderWidth(node);
}
_19d-=ds.getMarginWidth(node);
return ds.setPositivePixelValue(node,"width",_19d);
};
ds.getContentWidth=ds.getContentBoxWidth;
ds.getInnerWidth=ds.getBorderBoxWidth;
ds.getOuterWidth=ds.getMarginBoxWidth;
ds.setContentWidth=ds.setContentBoxWidth;
ds.setOuterWidth=ds.setMarginBoxWidth;
ds.getMarginHeight=function(node){
return ds._sumPixelValues(node,["margin-top","margin-bottom"],ds.isPositionAbsolute(node));
};
ds.getBorderHeight=function(node){
return ds.getBorderExtent(node,"top")+ds.getBorderExtent(node,"bottom");
};
ds.getPaddingHeight=function(node){
return ds._sumPixelValues(node,["padding-top","padding-bottom"],true);
};
ds.getPadBorderHeight=function(node){
return ds.getPaddingHeight(node)+ds.getBorderHeight(node);
};
ds.getContentBoxHeight=function(node){
node=dojo.byId(node);
return node.offsetHeight-ds.getPadBorderHeight(node);
};
ds.getBorderBoxHeight=function(node){
node=dojo.byId(node);
return node.offsetHeight;
};
ds.getMarginBoxHeight=function(node){
return ds.getInnerHeight(node)+ds.getMarginHeight(node);
};
ds.setContentBoxHeight=function(node,_1a6){
node=dojo.byId(node);
if(ds.isBorderBox(node)){
_1a6+=ds.getPadBorderHeight(node);
}
return ds.setPositivePixelValue(node,"height",_1a6);
};
ds.setMarginBoxHeight=function(node,_1a8){
node=dojo.byId(node);
if(!ds.isBorderBox(node)){
_1a8-=ds.getPadBorderHeight(node);
}
_1a8-=ds.getMarginHeight(node);
return ds.setPositivePixelValue(node,"height",_1a8);
};
ds.getContentHeight=ds.getContentBoxHeight;
ds.getInnerHeight=ds.getBorderBoxHeight;
ds.getOuterHeight=ds.getMarginBoxHeight;
ds.setContentHeight=ds.setContentBoxHeight;
ds.setOuterHeight=ds.setMarginBoxHeight;
ds.getAbsolutePosition=ds.abs=function(node,_1aa){
var ret=[];
ret.x=ret.y=0;
var st=dojo.html.getScrollTop();
var sl=dojo.html.getScrollLeft();
if(h.ie){
with(node.getBoundingClientRect()){
ret.x=left-2;
ret.y=top-2;
}
}else{
if(node["offsetParent"]){
var _1ae;
if((h.safari)&&(node.style.getPropertyValue("position")=="absolute")&&(node.parentNode==db)){
_1ae=db;
}else{
_1ae=db.parentNode;
}
if(node.parentNode!=db){
ret.x-=ds.sumAncestorProperties(node,"scrollLeft");
ret.y-=ds.sumAncestorProperties(node,"scrollTop");
}
do{
var n=node["offsetLeft"];
ret.x+=isNaN(n)?0:n;
var m=node["offsetTop"];
ret.y+=isNaN(m)?0:m;
node=node.offsetParent;
}while((node!=_1ae)&&(node!=null));
}else{
if(node["x"]&&node["y"]){
ret.x+=isNaN(node.x)?0:node.x;
ret.y+=isNaN(node.y)?0:node.y;
}
}
}
if(_1aa){
ret.y+=st;
ret.x+=sl;
}
ret[0]=ret.x;
ret[1]=ret.y;
return ret;
};
ds.sumAncestorProperties=function(node,prop){
node=dojo.byId(node);
if(!node){
return 0;
}
var _1b3=0;
while(node){
var val=node[prop];
if(val){
_1b3+=val-0;
}
node=node.parentNode;
}
return _1b3;
};
ds.getTotalOffset=function(node,type,_1b7){
node=dojo.byId(node);
return ds.abs(node,_1b7)[(type=="top")?"y":"x"];
};
ds.getAbsoluteX=ds.totalOffsetLeft=function(node,_1b9){
return ds.getTotalOffset(node,"left",_1b9);
};
ds.getAbsoluteY=ds.totalOffsetTop=function(node,_1bb){
return ds.getTotalOffset(node,"top",_1bb);
};
ds.styleSheet=null;
ds.insertCssRule=function(_1bc,_1bd,_1be){
if(!ds.styleSheet){
if(document.createStyleSheet){
ds.styleSheet=document.createStyleSheet();
}else{
if(document.styleSheets[0]){
ds.styleSheet=document.styleSheets[0];
}else{
return null;
}
}
}
if(arguments.length<3){
if(ds.styleSheet.cssRules){
_1be=ds.styleSheet.cssRules.length;
}else{
if(ds.styleSheet.rules){
_1be=ds.styleSheet.rules.length;
}else{
return null;
}
}
}
if(ds.styleSheet.insertRule){
var rule=_1bc+" { "+_1bd+" }";
return ds.styleSheet.insertRule(rule,_1be);
}else{
if(ds.styleSheet.addRule){
return ds.styleSheet.addRule(_1bc,_1bd,_1be);
}else{
return null;
}
}
};
ds.removeCssRule=function(_1c0){
if(!ds.styleSheet){
dojo.debug("no stylesheet defined for removing rules");
return false;
}
if(h.ie){
if(!_1c0){
_1c0=ds.styleSheet.rules.length;
ds.styleSheet.removeRule(_1c0);
}
}else{
if(document.styleSheets[0]){
if(!_1c0){
_1c0=ds.styleSheet.cssRules.length;
}
ds.styleSheet.deleteRule(_1c0);
}
}
return true;
};
ds.insertCssFile=function(URI,doc,_1c3){
if(!URI){
return;
}
if(!doc){
doc=document;
}
var _1c4=dojo.hostenv.getText(URI);
_1c4=ds.fixPathsInCssText(_1c4,URI);
if(_1c3){
var _1c5=doc.getElementsByTagName("style");
var _1c6="";
for(var i=0;i<_1c5.length;i++){
_1c6=(_1c5[i].styleSheet&&_1c5[i].styleSheet.cssText)?_1c5[i].styleSheet.cssText:_1c5[i].innerHTML;
if(_1c4==_1c6){
return;
}
}
}
var _1c8=ds.insertCssText(_1c4);
if(_1c8&&djConfig.isDebug){
_1c8.setAttribute("dbgHref",URI);
}
return _1c8;
};
ds.insertCssText=function(_1c9,doc,URI){
if(!_1c9){
return;
}
if(!doc){
doc=document;
}
if(URI){
_1c9=ds.fixPathsInCssText(_1c9,URI);
}
var _1cc=doc.createElement("style");
_1cc.setAttribute("type","text/css");
if(_1cc.styleSheet){
_1cc.styleSheet.cssText=_1c9;
}else{
var _1cd=doc.createTextNode(_1c9);
_1cc.appendChild(_1cd);
}
var head=doc.getElementsByTagName("head")[0];
if(!head){
dojo.debug("No head tag in document, aborting styles");
}else{
head.appendChild(_1cc);
}
return _1cc;
};
ds.fixPathsInCssText=function(_1cf,URI){
if(!_1cf||!URI){
return;
}
var pos=0;
var str="";
var url="";
while(pos!=-1){
pos=0;
url="";
pos=_1cf.indexOf("url(",pos);
if(pos<0){
break;
}
str+=_1cf.slice(0,pos+4);
_1cf=_1cf.substring(pos+4,_1cf.length);
url+=_1cf.match(/^[\t\s\w()\/.\\'"-:#=&?]*\)/)[0];
_1cf=_1cf.substring(url.length-1,_1cf.length);
url=url.replace(/^[\s\t]*(['"]?)([\w()\/.\\'"-:#=&?]*)\1[\s\t]*?\)/,"$2");
if(url.search(/(file|https?|ftps?):\/\//)==-1){
url=(new dojo.uri.Uri(URI,url).toString());
}
str+=url;
}
return str+_1cf;
};
ds.getBackgroundColor=function(node){
node=dojo.byId(node);
var _1d5;
do{
_1d5=ds.getStyle(node,"background-color");
if(_1d5.toLowerCase()=="rgba(0, 0, 0, 0)"){
_1d5="transparent";
}
if(node==document.getElementsByTagName("body")[0]){
node=null;
break;
}
node=node.parentNode;
}while(node&&dojo.lang.inArray(_1d5,["transparent",""]));
if(_1d5=="transparent"){
_1d5=[255,255,255,0];
}else{
_1d5=dojo.graphics.color.extractRGB(_1d5);
}
return _1d5;
};
ds.getComputedStyle=function(node,_1d7,_1d8){
node=dojo.byId(node);
var _1d7=ds.toSelectorCase(_1d7);
var _1d9=ds.toCamelCase(_1d7);
if(!node||!node.style){
return _1d8;
}else{
if(document.defaultView){
try{
var cs=document.defaultView.getComputedStyle(node,"");
if(cs){
return cs.getPropertyValue(_1d7);
}
}
catch(e){
if(node.style.getPropertyValue){
return node.style.getPropertyValue(_1d7);
}else{
return _1d8;
}
}
}else{
if(node.currentStyle){
return node.currentStyle[_1d9];
}
}
}
if(node.style.getPropertyValue){
return node.style.getPropertyValue(_1d7);
}else{
return _1d8;
}
};
ds.getStyleProperty=function(node,_1dc){
node=dojo.byId(node);
return (node&&node.style?node.style[ds.toCamelCase(_1dc)]:undefined);
};
ds.getStyle=function(node,_1de){
var _1df=ds.getStyleProperty(node,_1de);
return (_1df?_1df:ds.getComputedStyle(node,_1de));
};
ds.setStyle=function(node,_1e1,_1e2){
node=dojo.byId(node);
if(node&&node.style){
var _1e3=ds.toCamelCase(_1e1);
node.style[_1e3]=_1e2;
}
};
ds.toCamelCase=function(_1e4){
var arr=_1e4.split("-"),cc=arr[0];
for(var i=1;i<arr.length;i++){
cc+=arr[i].charAt(0).toUpperCase()+arr[i].substring(1);
}
return cc;
};
ds.toSelectorCase=function(_1e7){
return _1e7.replace(/([A-Z])/g,"-$1").toLowerCase();
};
ds.setOpacity=function setOpacity(node,_1e9,_1ea){
node=dojo.byId(node);
if(!_1ea){
if(_1e9>=1){
if(h.ie){
ds.clearOpacity(node);
return;
}else{
_1e9=0.999999;
}
}else{
if(_1e9<0){
_1e9=0;
}
}
}
if(h.ie){
if(node.nodeName.toLowerCase()=="tr"){
var tds=node.getElementsByTagName("td");
for(var x=0;x<tds.length;x++){
tds[x].style.filter="Alpha(Opacity="+_1e9*100+")";
}
}
node.style.filter="Alpha(Opacity="+_1e9*100+")";
}else{
if(h.moz){
node.style.opacity=_1e9;
node.style.MozOpacity=_1e9;
}else{
if(h.safari){
node.style.opacity=_1e9;
node.style.KhtmlOpacity=_1e9;
}else{
node.style.opacity=_1e9;
}
}
}
};
ds.getOpacity=function getOpacity(node){
node=dojo.byId(node);
if(h.ie){
var opac=(node.filters&&node.filters.alpha&&typeof node.filters.alpha.opacity=="number"?node.filters.alpha.opacity:100)/100;
}else{
var opac=node.style.opacity||node.style.MozOpacity||node.style.KhtmlOpacity||1;
}
return opac>=0.999999?1:Number(opac);
};
ds.clearOpacity=function clearOpacity(node){
node=dojo.byId(node);
var ns=node.style;
if(h.ie){
try{
if(node.filters&&node.filters.alpha){
ns.filter="";
}
}
catch(e){
}
}else{
if(h.moz){
ns.opacity=1;
ns.MozOpacity=1;
}else{
if(h.safari){
ns.opacity=1;
ns.KhtmlOpacity=1;
}else{
ns.opacity=1;
}
}
}
};
ds._toggle=function(node,_1f2,_1f3){
node=dojo.byId(node);
_1f3(node,!_1f2(node));
return _1f2(node);
};
ds.show=function(node){
node=dojo.byId(node);
if(ds.getStyleProperty(node,"display")=="none"){
ds.setStyle(node,"display",(node.dojoDisplayCache||""));
node.dojoDisplayCache=undefined;
}
};
ds.hide=function(node){
node=dojo.byId(node);
if(typeof node["dojoDisplayCache"]=="undefined"){
var d=ds.getStyleProperty(node,"display");
if(d!="none"){
node.dojoDisplayCache=d;
}
}
ds.setStyle(node,"display","none");
};
ds.setShowing=function(node,_1f8){
ds[(_1f8?"show":"hide")](node);
};
ds.isShowing=function(node){
return (ds.getStyleProperty(node,"display")!="none");
};
ds.toggleShowing=function(node){
return ds._toggle(node,ds.isShowing,ds.setShowing);
};
ds.displayMap={tr:"",td:"",th:"",img:"inline",span:"inline",input:"inline",button:"inline"};
ds.suggestDisplayByTagName=function(node){
node=dojo.byId(node);
if(node&&node.tagName){
var tag=node.tagName.toLowerCase();
return (tag in ds.displayMap?ds.displayMap[tag]:"block");
}
};
ds.setDisplay=function(node,_1fe){
ds.setStyle(node,"display",(dojo.lang.isString(_1fe)?_1fe:(_1fe?ds.suggestDisplayByTagName(node):"none")));
};
ds.isDisplayed=function(node){
return (ds.getComputedStyle(node,"display")!="none");
};
ds.toggleDisplay=function(node){
return ds._toggle(node,ds.isDisplayed,ds.setDisplay);
};
ds.setVisibility=function(node,_202){
ds.setStyle(node,"visibility",(dojo.lang.isString(_202)?_202:(_202?"visible":"hidden")));
};
ds.isVisible=function(node){
return (ds.getComputedStyle(node,"visibility")!="hidden");
};
ds.toggleVisibility=function(node){
return ds._toggle(node,ds.isVisible,ds.setVisibility);
};
ds.toCoordinateArray=function(_205,_206){
if(dojo.lang.isArray(_205)){
while(_205.length<4){
_205.push(0);
}
while(_205.length>4){
_205.pop();
}
var ret=_205;
}else{
var node=dojo.byId(_205);
var pos=ds.getAbsolutePosition(node,_206);
var ret=[pos.x,pos.y,ds.getBorderBoxWidth(node),ds.getBorderBoxHeight(node)];
}
ret.x=ret[0];
ret.y=ret[1];
ret.w=ret[2];
ret.h=ret[3];
return ret;
};
})();
dojo.provide("dojo.string.common");
dojo.require("dojo.string");
dojo.string.trim=function(str,wh){
if(!str.replace){
return str;
}
if(!str.length){
return str;
}
var re=(wh>0)?(/^\s+/):(wh<0)?(/\s+$/):(/^\s+|\s+$/g);
return str.replace(re,"");
};
dojo.string.trimStart=function(str){
return dojo.string.trim(str,1);
};
dojo.string.trimEnd=function(str){
return dojo.string.trim(str,-1);
};
dojo.string.repeat=function(str,_210,_211){
var out="";
for(var i=0;i<_210;i++){
out+=str;
if(_211&&i<_210-1){
out+=_211;
}
}
return out;
};
dojo.string.pad=function(str,len,c,dir){
var out=String(str);
if(!c){
c="0";
}
if(!dir){
dir=1;
}
while(out.length<len){
if(dir>0){
out=c+out;
}else{
out+=c;
}
}
return out;
};
dojo.string.padLeft=function(str,len,c){
return dojo.string.pad(str,len,c,1);
};
dojo.string.padRight=function(str,len,c){
return dojo.string.pad(str,len,c,-1);
};
dojo.provide("dojo.string");
dojo.require("dojo.string.common");
dojo.provide("dojo.html");
dojo.require("dojo.lang.func");
dojo.require("dojo.dom");
dojo.require("dojo.style");
dojo.require("dojo.string");
dojo.lang.mixin(dojo.html,dojo.dom);
dojo.lang.mixin(dojo.html,dojo.style);
dojo.html.clearSelection=function(){
try{
if(window["getSelection"]){
if(dojo.render.html.safari){
window.getSelection().collapse();
}else{
window.getSelection().removeAllRanges();
}
}else{
if(document.selection){
if(document.selection.empty){
document.selection.empty();
}else{
if(document.selection.clear){
document.selection.clear();
}
}
}
}
return true;
}
catch(e){
dojo.debug(e);
return false;
}
};
dojo.html.disableSelection=function(_21f){
_21f=dojo.byId(_21f)||document.body;
var h=dojo.render.html;
if(h.mozilla){
_21f.style.MozUserSelect="none";
}else{
if(h.safari){
_21f.style.KhtmlUserSelect="none";
}else{
if(h.ie){
_21f.unselectable="on";
}else{
return false;
}
}
}
return true;
};
dojo.html.enableSelection=function(_221){
_221=dojo.byId(_221)||document.body;
var h=dojo.render.html;
if(h.mozilla){
_221.style.MozUserSelect="";
}else{
if(h.safari){
_221.style.KhtmlUserSelect="";
}else{
if(h.ie){
_221.unselectable="off";
}else{
return false;
}
}
}
return true;
};
dojo.html.selectElement=function(_223){
_223=dojo.byId(_223);
if(document.selection&&document.body.createTextRange){
var _224=document.body.createTextRange();
_224.moveToElementText(_223);
_224.select();
}else{
if(window["getSelection"]){
var _225=window.getSelection();
if(_225["selectAllChildren"]){
_225.selectAllChildren(_223);
}
}
}
};
dojo.html.selectInputText=function(_226){
_226=dojo.byId(_226);
if(document.selection&&document.body.createTextRange){
var _227=_226.createTextRange();
_227.moveStart("character",0);
_227.moveEnd("character",_226.value.length);
_227.select();
}else{
if(window["getSelection"]){
var _228=window.getSelection();
_226.setSelectionRange(0,_226.value.length);
}
}
_226.focus();
};
dojo.html.isSelectionCollapsed=function(){
if(document["selection"]){
return document.selection.createRange().text=="";
}else{
if(window["getSelection"]){
var _229=window.getSelection();
if(dojo.lang.isString(_229)){
return _229=="";
}else{
return _229.isCollapsed;
}
}
}
};
dojo.html.getEventTarget=function(evt){
if(!evt){
evt=window.event||{};
}
var t=(evt.srcElement?evt.srcElement:(evt.target?evt.target:null));
while((t)&&(t.nodeType!=1)){
t=t.parentNode;
}
return t;
};
dojo.html.getDocumentWidth=function(){
dojo.deprecated("dojo.html.getDocument* has been deprecated in favor of dojo.html.getViewport*");
return dojo.html.getViewportWidth();
};
dojo.html.getDocumentHeight=function(){
dojo.deprecated("dojo.html.getDocument* has been deprecated in favor of dojo.html.getViewport*");
return dojo.html.getViewportHeight();
};
dojo.html.getDocumentSize=function(){
dojo.deprecated("dojo.html.getDocument* has been deprecated in favor of dojo.html.getViewport*");
return dojo.html.getViewportSize();
};
dojo.html.getViewportWidth=function(){
var w=0;
if(window.innerWidth){
w=window.innerWidth;
}
if(dojo.exists(document,"documentElement.clientWidth")){
var w2=document.documentElement.clientWidth;
if(!w||w2&&w2<w){
w=w2;
}
return w;
}
if(document.body){
return document.body.clientWidth;
}
return 0;
};
dojo.html.getViewportHeight=function(){
if(window.innerHeight){
return window.innerHeight;
}
if(dojo.exists(document,"documentElement.clientHeight")){
return document.documentElement.clientHeight;
}
if(document.body){
return document.body.clientHeight;
}
return 0;
};
dojo.html.getViewportSize=function(){
var ret=[dojo.html.getViewportWidth(),dojo.html.getViewportHeight()];
ret.w=ret[0];
ret.h=ret[1];
return ret;
};
dojo.html.getScrollTop=function(){
return window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;
};
dojo.html.getScrollLeft=function(){
return window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;
};
dojo.html.getScrollOffset=function(){
var off=[dojo.html.getScrollLeft(),dojo.html.getScrollTop()];
off.x=off[0];
off.y=off[1];
return off;
};
dojo.html.getParentOfType=function(node,type){
dojo.deprecated("dojo.html.getParentOfType has been deprecated in favor of dojo.html.getParentByType*");
return dojo.html.getParentByType(node,type);
};
dojo.html.getParentByType=function(node,type){
var _234=dojo.byId(node);
type=type.toLowerCase();
while((_234)&&(_234.nodeName.toLowerCase()!=type)){
if(_234==(document["body"]||document["documentElement"])){
return null;
}
_234=_234.parentNode;
}
return _234;
};
dojo.html.getAttribute=function(node,attr){
node=dojo.byId(node);
if((!node)||(!node.getAttribute)){
return null;
}
var ta=typeof attr=="string"?attr:new String(attr);
var v=node.getAttribute(ta.toUpperCase());
if((v)&&(typeof v=="string")&&(v!="")){
return v;
}
if(v&&v.value){
return v.value;
}
if((node.getAttributeNode)&&(node.getAttributeNode(ta))){
return (node.getAttributeNode(ta)).value;
}else{
if(node.getAttribute(ta)){
return node.getAttribute(ta);
}else{
if(node.getAttribute(ta.toLowerCase())){
return node.getAttribute(ta.toLowerCase());
}
}
}
return null;
};
dojo.html.hasAttribute=function(node,attr){
node=dojo.byId(node);
return dojo.html.getAttribute(node,attr)?true:false;
};
dojo.html.getClass=function(node){
node=dojo.byId(node);
if(!node){
return "";
}
var cs="";
if(node.className){
cs=node.className;
}else{
if(dojo.html.hasAttribute(node,"class")){
cs=dojo.html.getAttribute(node,"class");
}
}
return dojo.string.trim(cs);
};
dojo.html.getClasses=function(node){
var c=dojo.html.getClass(node);
return (c=="")?[]:c.split(/\s+/g);
};
dojo.html.hasClass=function(node,_240){
return dojo.lang.inArray(dojo.html.getClasses(node),_240);
};
dojo.html.prependClass=function(node,_242){
_242+=" "+dojo.html.getClass(node);
return dojo.html.setClass(node,_242);
};
dojo.html.addClass=function(node,_244){
if(dojo.html.hasClass(node,_244)){
return false;
}
_244=dojo.string.trim(dojo.html.getClass(node)+" "+_244);
return dojo.html.setClass(node,_244);
};
dojo.html.setClass=function(node,_246){
node=dojo.byId(node);
var cs=new String(_246);
try{
if(typeof node.className=="string"){
node.className=cs;
}else{
if(node.setAttribute){
node.setAttribute("class",_246);
node.className=cs;
}else{
return false;
}
}
}
catch(e){
dojo.debug("dojo.html.setClass() failed",e);
}
return true;
};
dojo.html.removeClass=function(node,_249,_24a){
var _249=dojo.string.trim(new String(_249));
try{
var cs=dojo.html.getClasses(node);
var nca=[];
if(_24a){
for(var i=0;i<cs.length;i++){
if(cs[i].indexOf(_249)==-1){
nca.push(cs[i]);
}
}
}else{
for(var i=0;i<cs.length;i++){
if(cs[i]!=_249){
nca.push(cs[i]);
}
}
}
dojo.html.setClass(node,nca.join(" "));
}
catch(e){
dojo.debug("dojo.html.removeClass() failed",e);
}
return true;
};
dojo.html.replaceClass=function(node,_24f,_250){
dojo.html.removeClass(node,_250);
dojo.html.addClass(node,_24f);
};
dojo.html.classMatchType={ContainsAll:0,ContainsAny:1,IsOnly:2};
dojo.html.getElementsByClass=function(_251,_252,_253,_254){
_252=dojo.byId(_252)||document;
var _255=_251.split(/\s+/g);
var _256=[];
if(_254!=1&&_254!=2){
_254=0;
}
var _257=new RegExp("(\\s|^)(("+_255.join(")|(")+"))(\\s|$)");
if(!_253){
_253="*";
}
var _258=_252.getElementsByTagName(_253);
var node,i=0;
outer:
while(node=_258[i++]){
var _25a=dojo.html.getClasses(node);
if(_25a.length==0){
continue outer;
}
var _25b=0;
for(var j=0;j<_25a.length;j++){
if(_257.test(_25a[j])){
if(_254==dojo.html.classMatchType.ContainsAny){
_256.push(node);
continue outer;
}else{
_25b++;
}
}else{
if(_254==dojo.html.classMatchType.IsOnly){
continue outer;
}
}
}
if(_25b==_255.length){
if(_254==dojo.html.classMatchType.IsOnly&&_25b==_25a.length){
_256.push(node);
}else{
if(_254==dojo.html.classMatchType.ContainsAll){
_256.push(node);
}
}
}
}
return _256;
};
dojo.html.getElementsByClassName=dojo.html.getElementsByClass;
dojo.html.getCursorPosition=function(e){
e=e||window.event;
var _25e={x:0,y:0};
if(e.pageX||e.pageY){
_25e.x=e.pageX;
_25e.y=e.pageY;
}else{
var de=document.documentElement;
var db=document.body;
_25e.x=e.clientX+((de||db)["scrollLeft"])-((de||db)["clientLeft"]);
_25e.y=e.clientY+((de||db)["scrollTop"])-((de||db)["clientTop"]);
}
return _25e;
};
dojo.html.overElement=function(_261,e){
_261=dojo.byId(_261);
var _263=dojo.html.getCursorPosition(e);
with(dojo.html){
var top=getAbsoluteY(_261,true);
var _265=top+getInnerHeight(_261);
var left=getAbsoluteX(_261,true);
var _267=left+getInnerWidth(_261);
}
return (_263.x>=left&&_263.x<=_267&&_263.y>=top&&_263.y<=_265);
};
dojo.html.setActiveStyleSheet=function(_268){
var i=0,a,els=document.getElementsByTagName("link");
while(a=els[i++]){
if(a.getAttribute("rel").indexOf("style")!=-1&&a.getAttribute("title")){
a.disabled=true;
if(a.getAttribute("title")==_268){
a.disabled=false;
}
}
}
};
dojo.html.getActiveStyleSheet=function(){
var i=0,a,els=document.getElementsByTagName("link");
while(a=els[i++]){
if(a.getAttribute("rel").indexOf("style")!=-1&&a.getAttribute("title")&&!a.disabled){
return a.getAttribute("title");
}
}
return null;
};
dojo.html.getPreferredStyleSheet=function(){
var i=0,a,els=document.getElementsByTagName("link");
while(a=els[i++]){
if(a.getAttribute("rel").indexOf("style")!=-1&&a.getAttribute("rel").indexOf("alt")==-1&&a.getAttribute("title")){
return a.getAttribute("title");
}
}
return null;
};
dojo.html.body=function(){
dojo.deprecated("dojo.html.body","use document.body instead");
return document.body||document.getElementsByTagName("body")[0];
};
dojo.html.isTag=function(node){
node=dojo.byId(node);
if(node&&node.tagName){
var arr=dojo.lang.map(dojo.lang.toArray(arguments,1),function(a){
return String(a).toLowerCase();
});
return arr[dojo.lang.find(node.tagName.toLowerCase(),arr)]||"";
}
return "";
};
dojo.html._callExtrasDeprecated=function(_26f,args){
var _271="dojo.html.extras";
dojo.deprecated("dojo.html."+_26f+" has been moved to "+_271);
dojo["require"](_271);
return dojo.html[_26f].apply(dojo.html,args);
};
dojo.html.createNodesFromText=function(){
return dojo.html._callExtrasDeprecated("createNodesFromText",arguments);
};
dojo.html.gravity=function(){
return dojo.html._callExtrasDeprecated("gravity",arguments);
};
dojo.html.placeOnScreen=function(){
return dojo.html._callExtrasDeprecated("placeOnScreen",arguments);
};
dojo.html.placeOnScreenPoint=function(){
return dojo.html._callExtrasDeprecated("placeOnScreenPoint",arguments);
};
dojo.html.renderedTextContent=function(){
return dojo.html._callExtrasDeprecated("renderedTextContent",arguments);
};
dojo.html.BackgroundIframe=function(){
return dojo.html._callExtrasDeprecated("BackgroundIframe",arguments);
};
dojo.provide("dojo.lfx.Animation");
dojo.provide("dojo.lfx.Line");
dojo.require("dojo.lang.func");
dojo.lfx.Line=function(_272,end){
this.start=_272;
this.end=end;
if(dojo.lang.isArray(_272)){
var diff=[];
dojo.lang.forEach(this.start,function(s,i){
diff[i]=this.end[i]-s;
},this);
this.getValue=function(n){
var res=[];
dojo.lang.forEach(this.start,function(s,i){
res[i]=(diff[i]*n)+s;
},this);
return res;
};
}else{
var diff=end-_272;
this.getValue=function(n){
return (diff*n)+this.start;
};
}
};
dojo.lfx.easeIn=function(n){
return Math.pow(n,3);
};
dojo.lfx.easeOut=function(n){
return (1-Math.pow(1-n,3));
};
dojo.lfx.easeInOut=function(n){
return ((3*Math.pow(n,2))-(2*Math.pow(n,3)));
};
dojo.lfx.IAnimation=function(){
};
dojo.lang.extend(dojo.lfx.IAnimation,{curve:null,duration:1000,easing:null,repeatCount:0,rate:25,handler:null,beforeBegin:null,onBegin:null,onAnimate:null,onEnd:null,onPlay:null,onPause:null,onStop:null,play:null,pause:null,stop:null,fire:function(evt,args){
if(this[evt]){
if(args){
this[evt].apply(this,args);
}else{
this[evt].apply(this);
}
}
},_active:false,_paused:false});
dojo.lfx.Animation=function(_281,_282,_283,_284,_285,rate){
dojo.lfx.IAnimation.call(this);
if(dojo.lang.isNumber(_281)||(!_281&&_282.getValue)){
rate=_285;
_285=_284;
_284=_283;
_283=_282;
_282=_281;
_281=null;
}else{
if(_281.getValue||dojo.lang.isArray(_281)){
rate=_284;
_285=_283;
_284=_282;
_283=_281;
_282=null;
_281=null;
}
}
if(dojo.lang.isArray(_283)){
this.curve=new dojo.lfx.Line(_283[0],_283[1]);
}else{
this.curve=_283;
}
if(_282!=null&&_282>0){
this.duration=_282;
}
if(_285){
this.repeatCount=_285;
}
if(rate){
this.rate=rate;
}
if(_281){
this.handler=_281.handler;
this.beforeBegin=_281.beforeBegin;
this.onBegin=_281.onBegin;
this.onEnd=_281.onEnd;
this.onPlay=_281.onPlay;
this.onPause=_281.onPause;
this.onStop=_281.onStop;
this.onAnimate=_281.onAnimate;
}
if(_284&&dojo.lang.isFunction(_284)){
this.easing=_284;
}
};
dojo.inherits(dojo.lfx.Animation,dojo.lfx.IAnimation);
dojo.lang.extend(dojo.lfx.Animation,{_startTime:null,_endTime:null,_timer:null,_percent:0,_startRepeatCount:0,play:function(_287,_288){
if(_288){
clearTimeout(this._timer);
this._active=false;
this._paused=false;
this._percent=0;
}else{
if(this._active&&!this._paused){
return;
}
}
this.fire("beforeBegin");
if(_287>0){
setTimeout(dojo.lang.hitch(this,function(){
this.play(null,_288);
}),_287);
return;
}
this._startTime=new Date().valueOf();
if(this._paused){
this._startTime-=(this.duration*this._percent/100);
}
this._endTime=this._startTime+this.duration;
this._active=true;
this._paused=false;
var step=this._percent/100;
var _28a=this.curve.getValue(step);
if(this._percent==0){
if(!this._startRepeatCount){
this._startRepeatCount=this.repeatCount;
}
this.fire("handler",["begin",_28a]);
this.fire("onBegin",[_28a]);
}
this.fire("handler",["play",_28a]);
this.fire("onPlay",[_28a]);
this._cycle();
},pause:function(){
clearTimeout(this._timer);
if(!this._active){
return;
}
this._paused=true;
var _28b=this.curve.getValue(this._percent/100);
this.fire("handler",["pause",_28b]);
this.fire("onPause",[_28b]);
},gotoPercent:function(pct,_28d){
clearTimeout(this._timer);
this._active=true;
this._paused=true;
this._percent=pct;
if(_28d){
this.play();
}
},stop:function(_28e){
clearTimeout(this._timer);
var step=this._percent/100;
if(_28e){
step=1;
}
var _290=this.curve.getValue(step);
this.fire("handler",["stop",_290]);
this.fire("onStop",[_290]);
this._active=false;
this._paused=false;
},status:function(){
if(this._active){
return this._paused?"paused":"playing";
}else{
return "stopped";
}
},_cycle:function(){
clearTimeout(this._timer);
if(this._active){
var curr=new Date().valueOf();
var step=(curr-this._startTime)/(this._endTime-this._startTime);
if(step>=1){
step=1;
this._percent=100;
}else{
this._percent=step*100;
}
if(this.easing&&dojo.lang.isFunction(this.easing)){
step=this.easing(step);
}
var _293=this.curve.getValue(step);
this.fire("handler",["animate",_293]);
this.fire("onAnimate",[_293]);
if(step<1){
this._timer=setTimeout(dojo.lang.hitch(this,"_cycle"),this.rate);
}else{
this._active=false;
this.fire("handler",["end"]);
this.fire("onEnd");
if(this.repeatCount>0){
this.repeatCount--;
this.play(null,true);
}else{
if(this.repeatCount==-1){
this.play(null,true);
}else{
if(this._startRepeatCount){
this.repeatCount=this._startRepeatCount;
this._startRepeatCount=0;
}
}
}
}
}
}});
dojo.lfx.Combine=function(){
dojo.lfx.IAnimation.call(this);
this._anims=[];
this._animsEnded=0;
var _294=arguments;
if(_294.length==1&&(dojo.lang.isArray(_294[0])||dojo.lang.isArrayLike(_294[0]))){
_294=_294[0];
}
var _295=this;
dojo.lang.forEach(_294,function(anim){
_295._anims.push(anim);
dojo.event.connect(anim,"onEnd",function(){
_295._onAnimsEnded();
});
});
};
dojo.inherits(dojo.lfx.Combine,dojo.lfx.IAnimation);
dojo.lang.extend(dojo.lfx.Combine,{_animsEnded:0,play:function(_297,_298){
if(!this._anims.length){
return;
}
this.fire("beforeBegin");
if(_297>0){
setTimeout(dojo.lang.hitch(this,function(){
this.play(null,_298);
}),_297);
return;
}
if(_298||this._anims[0].percent==0){
this.fire("onBegin");
}
this.fire("onPlay");
this._animsCall("play",null,_298);
},pause:function(){
this.fire("onPause");
this._animsCall("pause");
},stop:function(_299){
this.fire("onStop");
this._animsCall("stop",_299);
},_onAnimsEnded:function(){
this._animsEnded++;
if(this._animsEnded>=this._anims.length){
this.fire("onEnd");
}
},_animsCall:function(_29a){
var args=[];
if(arguments.length>1){
for(var i=1;i<arguments.length;i++){
args.push(arguments[i]);
}
}
var _29d=this;
dojo.lang.forEach(this._anims,function(anim){
anim[_29a](args);
},_29d);
}});
dojo.lfx.Chain=function(){
dojo.lfx.IAnimation.call(this);
this._anims=[];
this._currAnim=-1;
var _29f=arguments;
if(_29f.length==1&&(dojo.lang.isArray(_29f[0])||dojo.lang.isArrayLike(_29f[0]))){
_29f=_29f[0];
}
var _2a0=this;
dojo.lang.forEach(_29f,function(anim,i,_2a3){
_2a0._anims.push(anim);
if(i<_2a3.length-1){
dojo.event.connect(anim,"onEnd",function(){
_2a0._playNext();
});
}else{
dojo.event.connect(anim,"onEnd",function(){
_2a0.fire("onEnd");
});
}
},_2a0);
};
dojo.inherits(dojo.lfx.Chain,dojo.lfx.IAnimation);
dojo.lang.extend(dojo.lfx.Chain,{_currAnim:-1,play:function(_2a4,_2a5){
if(!this._anims.length){
return;
}
if(_2a5||!this._anims[this._currAnim]){
this._currAnim=0;
}
this.fire("beforeBegin");
if(_2a4>0){
setTimeout(dojo.lang.hitch(this,function(){
this.play(null,_2a5);
}),_2a4);
return;
}
if(this._anims[this._currAnim]){
if(this._currAnim==0){
this.fire("handler",["begin",this._currAnim]);
this.fire("onBegin",[this._currAnim]);
}
this.fire("onPlay",[this._currAnim]);
this._anims[this._currAnim].play(null,_2a5);
}
},pause:function(){
if(this._anims[this._currAnim]){
this._anims[this._currAnim].pause();
this.fire("onPause",[this._currAnim]);
}
},playPause:function(){
if(this._anims.length==0){
return;
}
if(this._currAnim==-1){
this._currAnim=0;
}
var _2a6=this._anims[this._currAnim];
if(_2a6){
if(!_2a6._active||_2a6._paused){
this.play();
}else{
this.pause();
}
}
},stop:function(){
if(this._anims[this._currAnim]){
this._anims[this._currAnim].stop();
this.fire("onStop",[this._currAnim]);
}
},_playNext:function(){
if(this._currAnim==-1||this._anims.length==0){
return;
}
this._currAnim++;
if(this._anims[this._currAnim]){
this._anims[this._currAnim].play(null,true);
}
}});
dojo.lfx.combine=function(){
var _2a7=arguments;
if(dojo.lang.isArray(arguments[0])){
_2a7=arguments[0];
}
return new dojo.lfx.Combine(_2a7);
};
dojo.lfx.chain=function(){
var _2a8=arguments;
if(dojo.lang.isArray(arguments[0])){
_2a8=arguments[0];
}
return new dojo.lfx.Chain(_2a8);
};
dojo.provide("dojo.lang.extras");
dojo.require("dojo.lang.common");
dojo.lang.setTimeout=function(func,_2aa){
var _2ab=window,argsStart=2;
if(!dojo.lang.isFunction(func)){
_2ab=func;
func=_2aa;
_2aa=arguments[2];
argsStart++;
}
if(dojo.lang.isString(func)){
func=_2ab[func];
}
var args=[];
for(var i=argsStart;i<arguments.length;i++){
args.push(arguments[i]);
}
return setTimeout(function(){
func.apply(_2ab,args);
},_2aa);
};
dojo.lang.getNameInObj=function(ns,item){
if(!ns){
ns=dj_global;
}
for(var x in ns){
if(ns[x]===item){
return new String(x);
}
}
return null;
};
dojo.lang.shallowCopy=function(obj){
var ret={},key;
for(key in obj){
if(dojo.lang.isUndefined(ret[key])){
ret[key]=obj[key];
}
}
return ret;
};
dojo.lang.firstValued=function(){
for(var i=0;i<arguments.length;i++){
if(typeof arguments[i]!="undefined"){
return arguments[i];
}
}
return undefined;
};
dojo.lang.getObjPathValue=function(_2b4,_2b5,_2b6){
with(dojo.parseObjPath(_2b4,_2b5,_2b6)){
return dojo.evalProp(prop,obj,_2b6);
}
};
dojo.lang.setObjPathValue=function(_2b7,_2b8,_2b9,_2ba){
if(arguments.length<4){
_2ba=true;
}
with(dojo.parseObjPath(_2b7,_2b9,_2ba)){
if(obj&&(_2ba||(prop in obj))){
obj[prop]=_2b8;
}
}
};
dojo.provide("dojo.event");
dojo.require("dojo.lang.array");
dojo.require("dojo.lang.extras");
dojo.require("dojo.lang.func");
dojo.event=new function(){
this.canTimeout=dojo.lang.isFunction(dj_global["setTimeout"])||dojo.lang.isAlien(dj_global["setTimeout"]);
function interpolateArgs(args){
var dl=dojo.lang;
var ao={srcObj:dj_global,srcFunc:null,adviceObj:dj_global,adviceFunc:null,aroundObj:null,aroundFunc:null,adviceType:(args.length>2)?args[0]:"after",precedence:"last",once:false,delay:null,rate:0,adviceMsg:false};
switch(args.length){
case 0:
return;
case 1:
return;
case 2:
ao.srcFunc=args[0];
ao.adviceFunc=args[1];
break;
case 3:
if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isString(args[2]))){
ao.adviceType="after";
ao.srcObj=args[0];
ao.srcFunc=args[1];
ao.adviceFunc=args[2];
}else{
if((dl.isString(args[1]))&&(dl.isString(args[2]))){
ao.srcFunc=args[1];
ao.adviceFunc=args[2];
}else{
if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isFunction(args[2]))){
ao.adviceType="after";
ao.srcObj=args[0];
ao.srcFunc=args[1];
var _2be=dojo.lang.nameAnonFunc(args[2],ao.adviceObj);
ao.adviceFunc=_2be;
}else{
if((dl.isFunction(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))){
ao.adviceType="after";
ao.srcObj=dj_global;
var _2be=dojo.lang.nameAnonFunc(args[0],ao.srcObj);
ao.srcFunc=_2be;
ao.adviceObj=args[1];
ao.adviceFunc=args[2];
}
}
}
}
break;
case 4:
if((dl.isObject(args[0]))&&(dl.isObject(args[2]))){
ao.adviceType="after";
ao.srcObj=args[0];
ao.srcFunc=args[1];
ao.adviceObj=args[2];
ao.adviceFunc=args[3];
}else{
if((dl.isString(args[0]))&&(dl.isString(args[1]))&&(dl.isObject(args[2]))){
ao.adviceType=args[0];
ao.srcObj=dj_global;
ao.srcFunc=args[1];
ao.adviceObj=args[2];
ao.adviceFunc=args[3];
}else{
if((dl.isString(args[0]))&&(dl.isFunction(args[1]))&&(dl.isObject(args[2]))){
ao.adviceType=args[0];
ao.srcObj=dj_global;
var _2be=dojo.lang.nameAnonFunc(args[1],dj_global);
ao.srcFunc=_2be;
ao.adviceObj=args[2];
ao.adviceFunc=args[3];
}else{
if((dl.isString(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))&&(dl.isFunction(args[3]))){
ao.srcObj=args[1];
ao.srcFunc=args[2];
var _2be=dojo.lang.nameAnonFunc(args[3],dj_global);
ao.adviceObj=dj_global;
ao.adviceFunc=_2be;
}else{
if(dl.isObject(args[1])){
ao.srcObj=args[1];
ao.srcFunc=args[2];
ao.adviceObj=dj_global;
ao.adviceFunc=args[3];
}else{
if(dl.isObject(args[2])){
ao.srcObj=dj_global;
ao.srcFunc=args[1];
ao.adviceObj=args[2];
ao.adviceFunc=args[3];
}else{
ao.srcObj=ao.adviceObj=ao.aroundObj=dj_global;
ao.srcFunc=args[1];
ao.adviceFunc=args[2];
ao.aroundFunc=args[3];
}
}
}
}
}
}
break;
case 6:
ao.srcObj=args[1];
ao.srcFunc=args[2];
ao.adviceObj=args[3];
ao.adviceFunc=args[4];
ao.aroundFunc=args[5];
ao.aroundObj=dj_global;
break;
default:
ao.srcObj=args[1];
ao.srcFunc=args[2];
ao.adviceObj=args[3];
ao.adviceFunc=args[4];
ao.aroundObj=args[5];
ao.aroundFunc=args[6];
ao.once=args[7];
ao.delay=args[8];
ao.rate=args[9];
ao.adviceMsg=args[10];
break;
}
if(dl.isFunction(ao.aroundFunc)){
var _2be=dojo.lang.nameAnonFunc(ao.aroundFunc,ao.aroundObj);
ao.aroundFunc=_2be;
}
if(!dl.isString(ao.srcFunc)){
ao.srcFunc=dojo.lang.getNameInObj(ao.srcObj,ao.srcFunc);
}
if(!dl.isString(ao.adviceFunc)){
ao.adviceFunc=dojo.lang.getNameInObj(ao.adviceObj,ao.adviceFunc);
}
if((ao.aroundObj)&&(!dl.isString(ao.aroundFunc))){
ao.aroundFunc=dojo.lang.getNameInObj(ao.aroundObj,ao.aroundFunc);
}
if(!ao.srcObj){
dojo.raise("bad srcObj for srcFunc: "+ao.srcFunc);
}
if(!ao.adviceObj){
dojo.raise("bad adviceObj for adviceFunc: "+ao.adviceFunc);
}
return ao;
}
this.connect=function(){
if(arguments.length==1){
var ao=arguments[0];
}else{
var ao=interpolateArgs(arguments);
}
if(dojo.lang.isArray(ao.srcObj)&&ao.srcObj!=""){
var _2c0={};
for(var x in ao){
_2c0[x]=ao[x];
}
var mjps=[];
dojo.lang.forEach(ao.srcObj,function(src){
if((dojo.render.html.capable)&&(dojo.lang.isString(src))){
src=dojo.byId(src);
}
_2c0.srcObj=src;
mjps.push(dojo.event.connect.call(dojo.event,_2c0));
});
return mjps;
}
var mjp=dojo.event.MethodJoinPoint.getForMethod(ao.srcObj,ao.srcFunc);
if(ao.adviceFunc){
var mjp2=dojo.event.MethodJoinPoint.getForMethod(ao.adviceObj,ao.adviceFunc);
}
mjp.kwAddAdvice(ao);
return mjp;
};
this.log=function(a1,a2){
var _2c8;
if((arguments.length==1)&&(typeof a1=="object")){
_2c8=a1;
}else{
_2c8={srcObj:a1,srcFunc:a2};
}
_2c8.adviceFunc=function(){
var _2c9=[];
for(var x=0;x<arguments.length;x++){
_2c9.push(arguments[x]);
}
dojo.debug("("+_2c8.srcObj+")."+_2c8.srcFunc,":",_2c9.join(", "));
};
this.kwConnect(_2c8);
};
this.connectBefore=function(){
var args=["before"];
for(var i=0;i<arguments.length;i++){
args.push(arguments[i]);
}
return this.connect.apply(this,args);
};
this.connectAround=function(){
var args=["around"];
for(var i=0;i<arguments.length;i++){
args.push(arguments[i]);
}
return this.connect.apply(this,args);
};
this.connectOnce=function(){
var ao=interpolateArgs(arguments);
ao.once=true;
return this.connect(ao);
};
this._kwConnectImpl=function(_2d0,_2d1){
var fn=(_2d1)?"disconnect":"connect";
if(typeof _2d0["srcFunc"]=="function"){
_2d0.srcObj=_2d0["srcObj"]||dj_global;
var _2d3=dojo.lang.nameAnonFunc(_2d0.srcFunc,_2d0.srcObj);
_2d0.srcFunc=_2d3;
}
if(typeof _2d0["adviceFunc"]=="function"){
_2d0.adviceObj=_2d0["adviceObj"]||dj_global;
var _2d3=dojo.lang.nameAnonFunc(_2d0.adviceFunc,_2d0.adviceObj);
_2d0.adviceFunc=_2d3;
}
return dojo.event[fn]((_2d0["type"]||_2d0["adviceType"]||"after"),_2d0["srcObj"]||dj_global,_2d0["srcFunc"],_2d0["adviceObj"]||_2d0["targetObj"]||dj_global,_2d0["adviceFunc"]||_2d0["targetFunc"],_2d0["aroundObj"],_2d0["aroundFunc"],_2d0["once"],_2d0["delay"],_2d0["rate"],_2d0["adviceMsg"]||false);
};
this.kwConnect=function(_2d4){
return this._kwConnectImpl(_2d4,false);
};
this.disconnect=function(){
var ao=interpolateArgs(arguments);
if(!ao.adviceFunc){
return;
}
var mjp=dojo.event.MethodJoinPoint.getForMethod(ao.srcObj,ao.srcFunc);
return mjp.removeAdvice(ao.adviceObj,ao.adviceFunc,ao.adviceType,ao.once);
};
this.kwDisconnect=function(_2d7){
return this._kwConnectImpl(_2d7,true);
};
};
dojo.event.MethodInvocation=function(_2d8,obj,args){
this.jp_=_2d8;
this.object=obj;
this.args=[];
for(var x=0;x<args.length;x++){
this.args[x]=args[x];
}
this.around_index=-1;
};
dojo.event.MethodInvocation.prototype.proceed=function(){
this.around_index++;
if(this.around_index>=this.jp_.around.length){
return this.jp_.object[this.jp_.methodname].apply(this.jp_.object,this.args);
}else{
var ti=this.jp_.around[this.around_index];
var mobj=ti[0]||dj_global;
var meth=ti[1];
return mobj[meth].call(mobj,this);
}
};
dojo.event.MethodJoinPoint=function(obj,_2e0){
this.object=obj||dj_global;
this.methodname=_2e0;
this.methodfunc=this.object[_2e0];
this.before=[];
this.after=[];
this.around=[];
};
dojo.event.MethodJoinPoint.getForMethod=function(obj,_2e2){
if(!obj){
obj=dj_global;
}
if(!obj[_2e2]){
obj[_2e2]=function(){
};
}else{
if((!dojo.lang.isFunction(obj[_2e2]))&&(!dojo.lang.isAlien(obj[_2e2]))){
return null;
}
}
var _2e3=_2e2+"$joinpoint";
var _2e4=_2e2+"$joinpoint$method";
var _2e5=obj[_2e3];
if(!_2e5){
var _2e6=false;
if(dojo.event["browser"]){
if((obj["attachEvent"])||(obj["nodeType"])||(obj["addEventListener"])){
_2e6=true;
dojo.event.browser.addClobberNodeAttrs(obj,[_2e3,_2e4,_2e2]);
}
}
var _2e7=obj[_2e2].length;
obj[_2e4]=obj[_2e2];
_2e5=obj[_2e3]=new dojo.event.MethodJoinPoint(obj,_2e4);
obj[_2e2]=function(){
var args=[];
if((_2e6)&&(!arguments.length)){
var evt=null;
try{
if(obj.ownerDocument){
evt=obj.ownerDocument.parentWindow.event;
}else{
if(obj.documentElement){
evt=obj.documentElement.ownerDocument.parentWindow.event;
}else{
evt=window.event;
}
}
}
catch(e){
evt=window.event;
}
if(evt){
args.push(dojo.event.browser.fixEvent(evt,this));
}
}else{
for(var x=0;x<arguments.length;x++){
if((x==0)&&(_2e6)&&(dojo.event.browser.isEvent(arguments[x]))){
args.push(dojo.event.browser.fixEvent(arguments[x],this));
}else{
args.push(arguments[x]);
}
}
}
return _2e5.run.apply(_2e5,args);
};
obj[_2e2].__preJoinArity=_2e7;
}
return _2e5;
};
dojo.lang.extend(dojo.event.MethodJoinPoint,{unintercept:function(){
this.object[this.methodname]=this.methodfunc;
this.before=[];
this.after=[];
this.around=[];
},disconnect:dojo.lang.forward("unintercept"),run:function(){
var obj=this.object||dj_global;
var args=arguments;
var _2ed=[];
for(var x=0;x<args.length;x++){
_2ed[x]=args[x];
}
var _2ef=function(marr){
if(!marr){
dojo.debug("Null argument to unrollAdvice()");
return;
}
var _2f1=marr[0]||dj_global;
var _2f2=marr[1];
if(!_2f1[_2f2]){
dojo.raise("function \""+_2f2+"\" does not exist on \""+_2f1+"\"");
}
var _2f3=marr[2]||dj_global;
var _2f4=marr[3];
var msg=marr[6];
var _2f6;
var to={args:[],jp_:this,object:obj,proceed:function(){
return _2f1[_2f2].apply(_2f1,to.args);
}};
to.args=_2ed;
var _2f8=parseInt(marr[4]);
var _2f9=((!isNaN(_2f8))&&(marr[4]!==null)&&(typeof marr[4]!="undefined"));
if(marr[5]){
var rate=parseInt(marr[5]);
var cur=new Date();
var _2fc=false;
if((marr["last"])&&((cur-marr.last)<=rate)){
if(dojo.event.canTimeout){
if(marr["delayTimer"]){
clearTimeout(marr.delayTimer);
}
var tod=parseInt(rate*2);
var mcpy=dojo.lang.shallowCopy(marr);
marr.delayTimer=setTimeout(function(){
mcpy[5]=0;
_2ef(mcpy);
},tod);
}
return;
}else{
marr.last=cur;
}
}
if(_2f4){
_2f3[_2f4].call(_2f3,to);
}else{
if((_2f9)&&((dojo.render.html)||(dojo.render.svg))){
dj_global["setTimeout"](function(){
if(msg){
_2f1[_2f2].call(_2f1,to);
}else{
_2f1[_2f2].apply(_2f1,args);
}
},_2f8);
}else{
if(msg){
_2f1[_2f2].call(_2f1,to);
}else{
_2f1[_2f2].apply(_2f1,args);
}
}
}
};
if(this.before.length>0){
dojo.lang.forEach(this.before,_2ef);
}
var _2ff;
if(this.around.length>0){
var mi=new dojo.event.MethodInvocation(this,obj,args);
_2ff=mi.proceed();
}else{
if(this.methodfunc){
_2ff=this.object[this.methodname].apply(this.object,args);
}
}
if(this.after.length>0){
dojo.lang.forEach(this.after,_2ef);
}
return (this.methodfunc)?_2ff:null;
},getArr:function(kind){
var arr=this.after;
if((typeof kind=="string")&&(kind.indexOf("before")!=-1)){
arr=this.before;
}else{
if(kind=="around"){
arr=this.around;
}
}
return arr;
},kwAddAdvice:function(args){
this.addAdvice(args["adviceObj"],args["adviceFunc"],args["aroundObj"],args["aroundFunc"],args["adviceType"],args["precedence"],args["once"],args["delay"],args["rate"],args["adviceMsg"]);
},addAdvice:function(_304,_305,_306,_307,_308,_309,once,_30b,rate,_30d){
var arr=this.getArr(_308);
if(!arr){
dojo.raise("bad this: "+this);
}
var ao=[_304,_305,_306,_307,_30b,rate,_30d];
if(once){
if(this.hasAdvice(_304,_305,_308,arr)>=0){
return;
}
}
if(_309=="first"){
arr.unshift(ao);
}else{
arr.push(ao);
}
},hasAdvice:function(_310,_311,_312,arr){
if(!arr){
arr=this.getArr(_312);
}
var ind=-1;
for(var x=0;x<arr.length;x++){
if((arr[x][0]==_310)&&(arr[x][1]==_311)){
ind=x;
}
}
return ind;
},removeAdvice:function(_316,_317,_318,once){
var arr=this.getArr(_318);
var ind=this.hasAdvice(_316,_317,_318,arr);
if(ind==-1){
return false;
}
while(ind!=-1){
arr.splice(ind,1);
if(once){
break;
}
ind=this.hasAdvice(_316,_317,_318,arr);
}
return true;
}});
dojo.provide("dojo.lfx.html");
dojo.require("dojo.lfx.Animation");
dojo.require("dojo.html");
dojo.require("dojo.event");
dojo.require("dojo.lang.func");
dojo.lfx.html._byId=function(_31c){
if(dojo.lang.isArrayLike(_31c)){
if(!_31c.alreadyChecked){
var n=[];
dojo.lang.forEach(_31c,function(node){
n.push(dojo.byId(node));
});
n.alreadyChecked=true;
return n;
}else{
return _31c;
}
}else{
return [dojo.byId(_31c)];
}
};
dojo.lfx.html.propertyAnimation=function(_31f,_320,_321,_322){
_31f=dojo.lfx.html._byId(_31f);
if(_31f.length==1){
dojo.lang.forEach(_320,function(prop){
if(typeof prop["start"]=="undefined"){
prop.start=parseInt(dojo.style.getComputedStyle(_31f[0],prop.property));
if(isNaN(prop.start)&&(prop.property=="opacity")){
prop.start=1;
}
}
});
}
var _324=function(_325){
var _326=new Array(_325.length);
for(var i=0;i<_325.length;i++){
_326[i]=Math.round(_325[i]);
}
return _326;
};
var _328=function(n,_32a){
n=dojo.byId(n);
if(!n||!n.style){
return;
}
for(s in _32a){
if(s=="opacity"){
dojo.style.setOpacity(n,_32a[s]);
}else{
n.style[dojo.style.toCamelCase(s)]=_32a[s];
}
}
};
var _32b=function(_32c){
this._properties=_32c;
this.diffs=new Array(_32c.length);
dojo.lang.forEach(_32c,function(prop,i){
if(dojo.lang.isArray(prop.start)){
this.diffs[i]=null;
}else{
this.diffs[i]=prop.end-prop.start;
}
},this);
this.getValue=function(n){
var ret={};
dojo.lang.forEach(this._properties,function(prop,i){
var _333=null;
if(dojo.lang.isArray(prop.start)){
_333=(prop.units||"rgb")+"(";
for(var j=0;j<prop.start.length;j++){
_333+=Math.round(((prop.end[j]-prop.start[j])*n)+prop.start[j])+(j<prop.start.length-1?",":"");
}
_333+=")";
}else{
_333=((this.diffs[i])*n)+prop.start+(prop.property!="opacity"?prop.units||"px":"");
}
ret[prop.property]=_333;
},this);
return ret;
};
};
var anim=new dojo.lfx.Animation(_321,new _32b(_320),_322);
dojo.event.connect(anim,"onAnimate",function(_336){
dojo.lang.forEach(_31f,function(node){
_328(node,_336);
});
});
return anim;
};
dojo.lfx.html._makeFadeable=function(_338){
var _339=function(node){
if(dojo.render.html.ie){
if((node.style.zoom.length==0)&&(dojo.style.getStyle(node,"zoom")=="normal")){
node.style.zoom="1";
}
if((node.style.width.length==0)&&(dojo.style.getStyle(node,"width")=="auto")){
node.style.width="auto";
}
}
};
if(dojo.lang.isArrayLike(_338)){
dojo.lang.forEach(_338,_339);
}else{
_339(_338);
}
};
dojo.lfx.html.fadeIn=function(_33b,_33c,_33d,_33e){
_33b=dojo.lfx.html._byId(_33b);
dojo.lfx.html._makeFadeable(_33b);
var anim=dojo.lfx.propertyAnimation(_33b,[{property:"opacity",start:dojo.style.getOpacity(_33b[0]),end:1}],_33c,_33d);
if(_33e){
dojo.event.connect(anim,"onEnd",function(){
_33e(_33b,anim);
});
}
return anim;
};
dojo.lfx.html.fadeOut=function(_340,_341,_342,_343){
_340=dojo.lfx.html._byId(_340);
dojo.lfx.html._makeFadeable(_340);
var anim=dojo.lfx.propertyAnimation(_340,[{property:"opacity",start:dojo.style.getOpacity(_340[0]),end:0}],_341,_342);
if(_343){
dojo.event.connect(anim,"onEnd",function(){
_343(_340,anim);
});
}
return anim;
};
dojo.lfx.html.fadeShow=function(_345,_346,_347,_348){
var anim=dojo.lfx.html.fadeIn(_345,_346,_347,_348);
dojo.event.connect(anim,"beforeBegin",function(){
if(dojo.lang.isArrayLike(_345)){
dojo.lang.forEach(_345,dojo.style.show);
}else{
dojo.style.show(_345);
}
});
return anim;
};
dojo.lfx.html.fadeHide=function(_34a,_34b,_34c,_34d){
var anim=dojo.lfx.html.fadeOut(_34a,_34b,_34c,function(){
if(dojo.lang.isArrayLike(_34a)){
dojo.lang.forEach(_34a,dojo.style.hide);
}else{
dojo.style.hide(_34a);
}
if(_34d){
_34d(_34a,anim);
}
});
return anim;
};
dojo.lfx.html.wipeIn=function(_34f,_350,_351,_352){
_34f=dojo.lfx.html._byId(_34f);
var _353=[];
var init=function(node,_356){
if(_356=="visible"){
node.style.overflow="hidden";
}
dojo.style.show(node);
node.style.height=0;
};
dojo.lang.forEach(_34f,function(node){
var _358=dojo.style.getStyle(node,"overflow");
var _359=function(){
init(node,_358);
};
_359();
var anim=dojo.lfx.propertyAnimation(node,[{property:"height",start:0,end:node.scrollHeight}],_350,_351);
dojo.event.connect(anim,"beforeBegin",_359);
dojo.event.connect(anim,"onEnd",function(){
node.style.overflow=_358;
node.style.height="auto";
if(_352){
_352(node,anim);
}
});
_353.push(anim);
});
if(_34f.length>1){
return dojo.lfx.combine(_353);
}else{
return _353[0];
}
};
dojo.lfx.html.wipeOut=function(_35b,_35c,_35d,_35e){
_35b=dojo.lfx.html._byId(_35b);
var _35f=[];
var init=function(node,_362){
dojo.style.show(node);
if(_362=="visible"){
node.style.overflow="hidden";
}
};
dojo.lang.forEach(_35b,function(node){
var _364=dojo.style.getStyle(node,"overflow");
var _365=function(){
init(node,_364);
};
_365();
var anim=dojo.lfx.propertyAnimation(node,[{property:"height",start:node.offsetHeight,end:0}],_35c,_35d);
dojo.event.connect(anim,"beforeBegin",_365);
dojo.event.connect(anim,"onEnd",function(){
dojo.style.hide(node);
node.style.overflow=_364;
if(_35e){
_35e(node,anim);
}
});
_35f.push(anim);
});
if(_35b.length>1){
return dojo.lfx.combine(_35f);
}else{
return _35f[0];
}
};
dojo.lfx.html.slideTo=function(_367,_368,_369,_36a,_36b){
_367=dojo.lfx.html._byId(_367);
var _36c=[];
dojo.lang.forEach(_367,function(node){
var top=null;
var left=null;
var pos=null;
var init=(function(){
var _372=node;
return function(){
top=node.offsetTop;
left=node.offsetLeft;
pos=dojo.style.getComputedStyle(node,"position");
if(pos=="relative"||pos=="static"){
top=parseInt(dojo.style.getComputedStyle(node,"top"))||0;
left=parseInt(dojo.style.getComputedStyle(node,"left"))||0;
}
};
})();
init();
var anim=dojo.lfx.propertyAnimation(node,[{property:"top",start:top,end:_368[0]},{property:"left",start:left,end:_368[1]}],_369,_36a);
dojo.event.connect(anim,"beforeBegin",init);
if(_36b){
dojo.event.connect(anim,"onEnd",function(){
_36b(node,anim);
});
}
_36c.push(anim);
});
if(_367.length>1){
return dojo.lfx.combine(_36c);
}else{
return _36c[0];
}
};
dojo.lfx.html.explode=function(_374,_375,_376,_377,_378){
var _379=dojo.style.toCoordinateArray(_374);
var _37a=document.createElement("div");
with(_37a.style){
position="absolute";
border="1px solid black";
display="none";
}
document.body.appendChild(_37a);
_375=dojo.byId(_375);
with(_375.style){
visibility="hidden";
display="block";
}
var _37b=dojo.style.toCoordinateArray(_375);
with(_375.style){
display="none";
visibility="visible";
}
var anim=new dojo.lfx.Animation({beforeBegin:function(){
dojo.style.show(_37a);
},onAnimate:function(_37d){
with(_37a.style){
left=_37d[0]+"px";
top=_37d[1]+"px";
width=_37d[2]+"px";
height=_37d[3]+"px";
}
},onEnd:function(){
dojo.style.show(_375);
_37a.parentNode.removeChild(_37a);
}},_376,new dojo.lfx.Line(_379,_37b),_377);
if(_378){
dojo.event.connect(anim,"onEnd",function(){
_378(_375,anim);
});
}
return anim;
};
dojo.lfx.html.implode=function(_37e,end,_380,_381,_382){
var _383=dojo.style.toCoordinateArray(_37e);
var _384=dojo.style.toCoordinateArray(end);
_37e=dojo.byId(_37e);
var _385=document.createElement("div");
with(_385.style){
position="absolute";
border="1px solid black";
display="none";
}
document.body.appendChild(_385);
var anim=new dojo.lfx.Animation({beforeBegin:function(){
dojo.style.hide(_37e);
dojo.style.show(_385);
},onAnimate:function(_387){
with(_385.style){
left=_387[0]+"px";
top=_387[1]+"px";
width=_387[2]+"px";
height=_387[3]+"px";
}
},onEnd:function(){
_385.parentNode.removeChild(_385);
}},_380,new dojo.lfx.Line(_383,_384),_381);
if(_382){
dojo.event.connect(anim,"onEnd",function(){
_382(_37e,anim);
});
}
return anim;
};
dojo.lfx.html.highlight=function(_388,_389,_38a,_38b,_38c){
_388=dojo.lfx.html._byId(_388);
var _38d=[];
dojo.lang.forEach(_388,function(node){
var _38f=dojo.style.getBackgroundColor(node);
var bg=dojo.style.getStyle(node,"background-color").toLowerCase();
var _391=(bg=="transparent"||bg=="rgba(0, 0, 0, 0)");
while(_38f.length>3){
_38f.pop();
}
var rgb=new dojo.graphics.color.Color(_389).toRgb();
var _393=new dojo.graphics.color.Color(_38f).toRgb();
var anim=dojo.lfx.propertyAnimation(node,[{property:"background-color",start:rgb,end:_393}],_38a,_38b);
dojo.event.connect(anim,"beforeBegin",function(){
node.style.backgroundColor="rgb("+rgb.join(",")+")";
});
dojo.event.connect(anim,"onEnd",function(){
if(_391){
node.style.backgroundColor="transparent";
}
if(_38c){
_38c(node,anim);
}
});
_38d.push(anim);
});
if(_388.length>1){
return dojo.lfx.combine(_38d);
}else{
return _38d[0];
}
};
dojo.lfx.html.unhighlight=function(_395,_396,_397,_398,_399){
_395=dojo.lfx.html._byId(_395);
var _39a=[];
dojo.lang.forEach(_395,function(node){
var _39c=new dojo.graphics.color.Color(dojo.style.getBackgroundColor(node)).toRgb();
var rgb=new dojo.graphics.color.Color(_396).toRgb();
var anim=dojo.lfx.propertyAnimation(node,[{property:"background-color",start:_39c,end:rgb}],_397,_398);
dojo.event.connect(anim,"beforeBegin",function(){
node.style.backgroundColor="rgb("+_39c.join(",")+")";
});
if(_399){
dojo.event.connect(anim,"onEnd",function(){
_399(node,anim);
});
}
_39a.push(anim);
});
if(_395.length>1){
return dojo.lfx.combine(_39a);
}else{
return _39a[0];
}
};
dojo.lang.mixin(dojo.lfx,dojo.lfx.html);
dojo.kwCompoundRequire({browser:["dojo.lfx.html"],dashboard:["dojo.lfx.html"]});
dojo.provide("dojo.lfx.*");
dojo.require("dojo.event");
dojo.provide("dojo.event.topic");
dojo.event.topic=new function(){
this.topics={};
this.getTopic=function(_39f){
if(!this.topics[_39f]){
this.topics[_39f]=new this.TopicImpl(_39f);
}
return this.topics[_39f];
};
this.registerPublisher=function(_3a0,obj,_3a2){
var _3a0=this.getTopic(_3a0);
_3a0.registerPublisher(obj,_3a2);
};
this.subscribe=function(_3a3,obj,_3a5){
var _3a3=this.getTopic(_3a3);
_3a3.subscribe(obj,_3a5);
};
this.unsubscribe=function(_3a6,obj,_3a8){
var _3a6=this.getTopic(_3a6);
_3a6.unsubscribe(obj,_3a8);
};
this.destroy=function(_3a9){
this.getTopic(_3a9).destroy();
delete this.topics[_3a9];
};
this.publish=function(_3aa,_3ab){
var _3aa=this.getTopic(_3aa);
var args=[];
if(arguments.length==2&&(dojo.lang.isArray(_3ab)||_3ab.callee)){
args=_3ab;
}else{
var args=[];
for(var x=1;x<arguments.length;x++){
args.push(arguments[x]);
}
}
_3aa.sendMessage.apply(_3aa,args);
};
};
dojo.event.topic.TopicImpl=function(_3ae){
this.topicName=_3ae;
this.subscribe=function(_3af,_3b0){
var tf=_3b0||_3af;
var to=(!_3b0)?dj_global:_3af;
dojo.event.kwConnect({srcObj:this,srcFunc:"sendMessage",adviceObj:to,adviceFunc:tf});
};
this.unsubscribe=function(_3b3,_3b4){
var tf=(!_3b4)?_3b3:_3b4;
var to=(!_3b4)?null:_3b3;
dojo.event.kwDisconnect({srcObj:this,srcFunc:"sendMessage",adviceObj:to,adviceFunc:tf});
};
this.destroy=function(){
dojo.event.MethodJoinPoint.getForMethod(this,"sendMessage").disconnect();
};
this.registerPublisher=function(_3b7,_3b8){
dojo.event.connect(_3b7,_3b8,this,"sendMessage");
};
this.sendMessage=function(_3b9){
};
};
dojo.provide("dojo.event.browser");
dojo.require("dojo.event");
dojo_ie_clobber=new function(){
this.clobberNodes=[];
function nukeProp(node,prop){
try{
node[prop]=null;
}
catch(e){
}
try{
delete node[prop];
}
catch(e){
}
try{
node.removeAttribute(prop);
}
catch(e){
}
}
this.clobber=function(_3bc){
var na;
var tna;
if(_3bc){
tna=_3bc.all||_3bc.getElementsByTagName("*");
na=[_3bc];
for(var x=0;x<tna.length;x++){
if(tna[x]["__doClobber__"]){
na.push(tna[x]);
}
}
}else{
try{
window.onload=null;
}
catch(e){
}
na=(this.clobberNodes.length)?this.clobberNodes:document.all;
}
tna=null;
var _3c0={};
for(var i=na.length-1;i>=0;i=i-1){
var el=na[i];
if(el["__clobberAttrs__"]){
for(var j=0;j<el.__clobberAttrs__.length;j++){
nukeProp(el,el.__clobberAttrs__[j]);
}
nukeProp(el,"__clobberAttrs__");
nukeProp(el,"__doClobber__");
}
}
na=null;
};
};
if(dojo.render.html.ie){
window.onunload=function(){
dojo_ie_clobber.clobber();
try{
if((dojo["widget"])&&(dojo.widget["manager"])){
dojo.widget.manager.destroyAll();
}
}
catch(e){
}
try{
window.onload=null;
}
catch(e){
}
try{
window.onunload=null;
}
catch(e){
}
dojo_ie_clobber.clobberNodes=[];
};
}
dojo.event.browser=new function(){
var _3c4=0;
this.clean=function(node){
if(dojo.render.html.ie){
dojo_ie_clobber.clobber(node);
}
};
this.addClobberNode=function(node){
if(!node["__doClobber__"]){
node.__doClobber__=true;
dojo_ie_clobber.clobberNodes.push(node);
node.__clobberAttrs__=[];
}
};
this.addClobberNodeAttrs=function(node,_3c8){
this.addClobberNode(node);
for(var x=0;x<_3c8.length;x++){
node.__clobberAttrs__.push(_3c8[x]);
}
};
this.removeListener=function(node,_3cb,fp,_3cd){
if(!_3cd){
var _3cd=false;
}
_3cb=_3cb.toLowerCase();
if(_3cb.substr(0,2)=="on"){
_3cb=_3cb.substr(2);
}
if(node.removeEventListener){
node.removeEventListener(_3cb,fp,_3cd);
}
};
this.addListener=function(node,_3cf,fp,_3d1,_3d2){
if(!node){
return;
}
if(!_3d1){
var _3d1=false;
}
_3cf=_3cf.toLowerCase();
if(_3cf.substr(0,2)!="on"){
_3cf="on"+_3cf;
}
if(!_3d2){
var _3d3=function(evt){
if(!evt){
evt=window.event;
}
var ret=fp(dojo.event.browser.fixEvent(evt,this));
if(_3d1){
dojo.event.browser.stopEvent(evt);
}
return ret;
};
}else{
_3d3=fp;
}
if(node.addEventListener){
node.addEventListener(_3cf.substr(2),_3d3,_3d1);
return _3d3;
}else{
if(typeof node[_3cf]=="function"){
var _3d6=node[_3cf];
node[_3cf]=function(e){
_3d6(e);
return _3d3(e);
};
}else{
node[_3cf]=_3d3;
}
if(dojo.render.html.ie){
this.addClobberNodeAttrs(node,[_3cf]);
}
return _3d3;
}
};
this.isEvent=function(obj){
return (typeof obj!="undefined")&&(typeof Event!="undefined")&&(obj.eventPhase);
};
this.currentEvent=null;
this.callListener=function(_3d9,_3da){
if(typeof _3d9!="function"){
dojo.raise("listener not a function: "+_3d9);
}
dojo.event.browser.currentEvent.currentTarget=_3da;
return _3d9.call(_3da,dojo.event.browser.currentEvent);
};
this.stopPropagation=function(){
dojo.event.browser.currentEvent.cancelBubble=true;
};
this.preventDefault=function(){
dojo.event.browser.currentEvent.returnValue=false;
};
this.keys={KEY_BACKSPACE:8,KEY_TAB:9,KEY_ENTER:13,KEY_SHIFT:16,KEY_CTRL:17,KEY_ALT:18,KEY_PAUSE:19,KEY_CAPS_LOCK:20,KEY_ESCAPE:27,KEY_SPACE:32,KEY_PAGE_UP:33,KEY_PAGE_DOWN:34,KEY_END:35,KEY_HOME:36,KEY_LEFT_ARROW:37,KEY_UP_ARROW:38,KEY_RIGHT_ARROW:39,KEY_DOWN_ARROW:40,KEY_INSERT:45,KEY_DELETE:46,KEY_LEFT_WINDOW:91,KEY_RIGHT_WINDOW:92,KEY_SELECT:93,KEY_F1:112,KEY_F2:113,KEY_F3:114,KEY_F4:115,KEY_F5:116,KEY_F6:117,KEY_F7:118,KEY_F8:119,KEY_F9:120,KEY_F10:121,KEY_F11:122,KEY_F12:123,KEY_NUM_LOCK:144,KEY_SCROLL_LOCK:145};
this.revKeys=[];
for(var key in this.keys){
this.revKeys[this.keys[key]]=key;
}
this.fixEvent=function(evt,_3dd){
if((!evt)&&(window["event"])){
var evt=window.event;
}
if((evt["type"])&&(evt["type"].indexOf("key")==0)){
evt.keys=this.revKeys;
for(var key in this.keys){
evt[key]=this.keys[key];
}
if((dojo.render.html.ie)&&(evt["type"]=="keypress")){
evt.charCode=evt.keyCode;
}
}
if(dojo.render.html.ie){
if(!evt.target){
evt.target=evt.srcElement;
}
if(!evt.currentTarget){
evt.currentTarget=(_3dd?_3dd:evt.srcElement);
}
if(!evt.layerX){
evt.layerX=evt.offsetX;
}
if(!evt.layerY){
evt.layerY=evt.offsetY;
}
if(!evt.pageX){
evt.pageX=evt.clientX+(window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0);
}
if(!evt.pageY){
evt.pageY=evt.clientY+(window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0);
}
if(evt.type=="mouseover"){
evt.relatedTarget=evt.fromElement;
}
if(evt.type=="mouseout"){
evt.relatedTarget=evt.toElement;
}
this.currentEvent=evt;
evt.callListener=this.callListener;
evt.stopPropagation=this.stopPropagation;
evt.preventDefault=this.preventDefault;
}
return evt;
};
this.stopEvent=function(ev){
if(window.event){
ev.returnValue=false;
ev.cancelBubble=true;
}else{
ev.preventDefault();
ev.stopPropagation();
}
};
};
dojo.kwCompoundRequire({common:["dojo.event","dojo.event.topic"],browser:["dojo.event.browser"],dashboard:["dojo.event.browser"]});
dojo.provide("dojo.event.*");
dojo.provide("dojo.logging.Logger");
dojo.provide("dojo.log");
dojo.require("dojo.lang");
dojo.logging.Record=function(lvl,msg){
this.level=lvl;
this.message=msg;
this.time=new Date();
};
dojo.logging.LogFilter=function(_3e2){
this.passChain=_3e2||"";
this.filter=function(_3e3){
return true;
};
};
dojo.logging.Logger=function(){
this.cutOffLevel=0;
this.propagate=true;
this.parent=null;
this.data=[];
this.filters=[];
this.handlers=[];
};
dojo.lang.extend(dojo.logging.Logger,{argsToArr:function(args){
var ret=[];
for(var x=0;x<args.length;x++){
ret.push(args[x]);
}
return ret;
},setLevel:function(lvl){
this.cutOffLevel=parseInt(lvl);
},isEnabledFor:function(lvl){
return parseInt(lvl)>=this.cutOffLevel;
},getEffectiveLevel:function(){
if((this.cutOffLevel==0)&&(this.parent)){
return this.parent.getEffectiveLevel();
}
return this.cutOffLevel;
},addFilter:function(flt){
this.filters.push(flt);
return this.filters.length-1;
},removeFilterByIndex:function(_3ea){
if(this.filters[_3ea]){
delete this.filters[_3ea];
return true;
}
return false;
},removeFilter:function(_3eb){
for(var x=0;x<this.filters.length;x++){
if(this.filters[x]===_3eb){
delete this.filters[x];
return true;
}
}
return false;
},removeAllFilters:function(){
this.filters=[];
},filter:function(rec){
for(var x=0;x<this.filters.length;x++){
if((this.filters[x]["filter"])&&(!this.filters[x].filter(rec))||(rec.level<this.cutOffLevel)){
return false;
}
}
return true;
},addHandler:function(hdlr){
this.handlers.push(hdlr);
return this.handlers.length-1;
},handle:function(rec){
if((!this.filter(rec))||(rec.level<this.cutOffLevel)){
return false;
}
for(var x=0;x<this.handlers.length;x++){
if(this.handlers[x]["handle"]){
this.handlers[x].handle(rec);
}
}
return true;
},log:function(lvl,msg){
if((this.propagate)&&(this.parent)&&(this.parent.rec.level>=this.cutOffLevel)){
this.parent.log(lvl,msg);
return false;
}
this.handle(new dojo.logging.Record(lvl,msg));
return true;
},debug:function(msg){
return this.logType("DEBUG",this.argsToArr(arguments));
},info:function(msg){
return this.logType("INFO",this.argsToArr(arguments));
},warning:function(msg){
return this.logType("WARNING",this.argsToArr(arguments));
},error:function(msg){
return this.logType("ERROR",this.argsToArr(arguments));
},critical:function(msg){
return this.logType("CRITICAL",this.argsToArr(arguments));
},exception:function(msg,e,_3fb){
if(e){
var _3fc=[e.name,(e.description||e.message)];
if(e.fileName){
_3fc.push(e.fileName);
_3fc.push("line "+e.lineNumber);
}
msg+=" "+_3fc.join(" : ");
}
this.logType("ERROR",msg);
if(!_3fb){
throw e;
}
},logType:function(type,args){
var na=[dojo.logging.log.getLevel(type)];
if(typeof args=="array"){
na=na.concat(args);
}else{
if((typeof args=="object")&&(args["length"])){
na=na.concat(this.argsToArr(args));
}else{
na=na.concat(this.argsToArr(arguments).slice(1));
}
}
return this.log.apply(this,na);
}});
void (function(){
var _400=dojo.logging.Logger.prototype;
_400.warn=_400.warning;
_400.err=_400.error;
_400.crit=_400.critical;
})();
dojo.logging.LogHandler=function(_401){
this.cutOffLevel=(_401)?_401:0;
this.formatter=null;
this.data=[];
this.filters=[];
};
dojo.logging.LogHandler.prototype.setFormatter=function(fmtr){
dojo.unimplemented("setFormatter");
};
dojo.logging.LogHandler.prototype.flush=function(){
dojo.unimplemented("flush");
};
dojo.logging.LogHandler.prototype.close=function(){
dojo.unimplemented("close");
};
dojo.logging.LogHandler.prototype.handleError=function(){
dojo.unimplemented("handleError");
};
dojo.logging.LogHandler.prototype.handle=function(_403){
if((this.filter(_403))&&(_403.level>=this.cutOffLevel)){
this.emit(_403);
}
};
dojo.logging.LogHandler.prototype.emit=function(_404){
dojo.unimplemented("emit");
};
void (function(){
var _405=["setLevel","addFilter","removeFilterByIndex","removeFilter","removeAllFilters","filter"];
var tgt=dojo.logging.LogHandler.prototype;
var src=dojo.logging.Logger.prototype;
for(var x=0;x<_405.length;x++){
tgt[_405[x]]=src[_405[x]];
}
})();
dojo.logging.log=new dojo.logging.Logger();
dojo.logging.log.levels=[{"name":"DEBUG","level":1},{"name":"INFO","level":2},{"name":"WARNING","level":3},{"name":"ERROR","level":4},{"name":"CRITICAL","level":5}];
dojo.logging.log.loggers={};
dojo.logging.log.getLogger=function(name){
if(!this.loggers[name]){
this.loggers[name]=new dojo.logging.Logger();
this.loggers[name].parent=this;
}
return this.loggers[name];
};
dojo.logging.log.getLevelName=function(lvl){
for(var x=0;x<this.levels.length;x++){
if(this.levels[x].level==lvl){
return this.levels[x].name;
}
}
return null;
};
dojo.logging.log.addLevelName=function(name,lvl){
if(this.getLevelName(name)){
this.err("could not add log level "+name+" because a level with that name already exists");
return false;
}
this.levels.append({"name":name,"level":parseInt(lvl)});
return true;
};
dojo.logging.log.getLevel=function(name){
for(var x=0;x<this.levels.length;x++){
if(this.levels[x].name.toUpperCase()==name.toUpperCase()){
return this.levels[x].level;
}
}
return null;
};
dojo.logging.MemoryLogHandler=function(_410,_411,_412,_413){
dojo.logging.LogHandler.call(this,_410);
this.numRecords=(typeof djConfig["loggingNumRecords"]!="undefined")?djConfig["loggingNumRecords"]:((_411)?_411:-1);
this.postType=(typeof djConfig["loggingPostType"]!="undefined")?djConfig["loggingPostType"]:(_412||-1);
this.postInterval=(typeof djConfig["loggingPostInterval"]!="undefined")?djConfig["loggingPostInterval"]:(_412||-1);
};
dojo.logging.MemoryLogHandler.prototype=new dojo.logging.LogHandler();
dojo.logging.MemoryLogHandler.prototype.emit=function(_414){
this.data.push(_414);
if(this.numRecords!=-1){
while(this.data.length>this.numRecords){
this.data.shift();
}
}
};
dojo.logging.logQueueHandler=new dojo.logging.MemoryLogHandler(0,50,0,10000);
dojo.logging.logQueueHandler.emit=function(_415){
var _416=String(dojo.log.getLevelName(_415.level)+": "+_415.time.toLocaleTimeString())+": "+_415.message;
if(!dj_undef("debug",dj_global)){
dojo.debug(_416);
}else{
if((typeof dj_global["print"]=="function")&&(!dojo.render.html.capable)){
print(_416);
}
}
this.data.push(_415);
if(this.numRecords!=-1){
while(this.data.length>this.numRecords){
this.data.shift();
}
}
};
dojo.logging.log.addHandler(dojo.logging.logQueueHandler);
dojo.log=dojo.logging.log;
dojo.kwCompoundRequire({common:["dojo.logging.Logger",false,false],rhino:["dojo.logging.RhinoLogger"]});
dojo.provide("dojo.logging.*");
dojo.provide("dojo.io.IO");
dojo.require("dojo.string");
dojo.require("dojo.lang.extras");
dojo.io.transports=[];
dojo.io.hdlrFuncNames=["load","error","timeout"];
dojo.io.Request=function(url,_418,_419,_41a){
if((arguments.length==1)&&(arguments[0].constructor==Object)){
this.fromKwArgs(arguments[0]);
}else{
this.url=url;
if(_418){
this.mimetype=_418;
}
if(_419){
this.transport=_419;
}
if(arguments.length>=4){
this.changeUrl=_41a;
}
}
};
dojo.lang.extend(dojo.io.Request,{url:"",mimetype:"text/plain",method:"GET",content:undefined,transport:undefined,changeUrl:undefined,formNode:undefined,sync:false,bindSuccess:false,useCache:false,preventCache:false,load:function(type,data,evt){
},error:function(type,_41f){
},timeout:function(type){
},handle:function(){
},timeoutSeconds:0,abort:function(){
},fromKwArgs:function(_421){
if(_421["url"]){
_421.url=_421.url.toString();
}
if(_421["formNode"]){
_421.formNode=dojo.byId(_421.formNode);
}
if(!_421["method"]&&_421["formNode"]&&_421["formNode"].method){
_421.method=_421["formNode"].method;
}
if(!_421["handle"]&&_421["handler"]){
_421.handle=_421.handler;
}
if(!_421["load"]&&_421["loaded"]){
_421.load=_421.loaded;
}
if(!_421["changeUrl"]&&_421["changeURL"]){
_421.changeUrl=_421.changeURL;
}
_421.encoding=dojo.lang.firstValued(_421["encoding"],djConfig["bindEncoding"],"");
_421.sendTransport=dojo.lang.firstValued(_421["sendTransport"],djConfig["ioSendTransport"],false);
var _422=dojo.lang.isFunction;
for(var x=0;x<dojo.io.hdlrFuncNames.length;x++){
var fn=dojo.io.hdlrFuncNames[x];
if(_422(_421[fn])){
continue;
}
if(_422(_421["handle"])){
_421[fn]=_421.handle;
}
}
dojo.lang.mixin(this,_421);
}});
dojo.io.Error=function(msg,type,num){
this.message=msg;
this.type=type||"unknown";
this.number=num||0;
};
dojo.io.transports.addTransport=function(name){
this.push(name);
this[name]=dojo.io[name];
};
dojo.io.bind=function(_429){
if(!(_429 instanceof dojo.io.Request)){
try{
_429=new dojo.io.Request(_429);
}
catch(e){
dojo.debug(e);
}
}
var _42a="";
if(_429["transport"]){
_42a=_429["transport"];
if(!this[_42a]){
return _429;
}
}else{
for(var x=0;x<dojo.io.transports.length;x++){
var tmp=dojo.io.transports[x];
if((this[tmp])&&(this[tmp].canHandle(_429))){
_42a=tmp;
}
}
if(_42a==""){
return _429;
}
}
this[_42a].bind(_429);
_429.bindSuccess=true;
return _429;
};
dojo.io.queueBind=function(_42d){
if(!(_42d instanceof dojo.io.Request)){
try{
_42d=new dojo.io.Request(_42d);
}
catch(e){
dojo.debug(e);
}
}
var _42e=_42d.load;
_42d.load=function(){
dojo.io._queueBindInFlight=false;
var ret=_42e.apply(this,arguments);
dojo.io._dispatchNextQueueBind();
return ret;
};
var _430=_42d.error;
_42d.error=function(){
dojo.io._queueBindInFlight=false;
var ret=_430.apply(this,arguments);
dojo.io._dispatchNextQueueBind();
return ret;
};
dojo.io._bindQueue.push(_42d);
dojo.io._dispatchNextQueueBind();
return _42d;
};
dojo.io._dispatchNextQueueBind=function(){
if(!dojo.io._queueBindInFlight){
dojo.io._queueBindInFlight=true;
if(dojo.io._bindQueue.length>0){
dojo.io.bind(dojo.io._bindQueue.shift());
}else{
dojo.io._queueBindInFlight=false;
}
}
};
dojo.io._bindQueue=[];
dojo.io._queueBindInFlight=false;
dojo.io.argsFromMap=function(map,_433,last){
var enc=/utf/i.test(_433||"")?encodeURIComponent:dojo.string.encodeAscii;
var _436=[];
var _437=new Object();
for(var name in map){
var _439=function(elt){
var val=enc(name)+"="+enc(elt);
_436[(last==name)?"push":"unshift"](val);
};
if(!_437[name]){
var _43c=map[name];
if(dojo.lang.isArray(_43c)){
dojo.lang.forEach(_43c,_439);
}else{
_439(_43c);
}
}
}
return _436.join("&");
};
dojo.io.setIFrameSrc=function(_43d,src,_43f){
try{
var r=dojo.render.html;
if(!_43f){
if(r.safari){
_43d.location=src;
}else{
frames[_43d.name].location=src;
}
}else{
var idoc;
if(r.ie){
idoc=_43d.contentWindow.document;
}else{
if(r.safari){
idoc=_43d.document;
}else{
idoc=_43d.contentWindow;
}
}
idoc.location.replace(src);
}
}
catch(e){
dojo.debug(e);
dojo.debug("setIFrameSrc: "+e);
}
};
dojo.provide("dojo.string.extras");
dojo.require("dojo.string.common");
dojo.require("dojo.lang");
dojo.string.paramString=function(str,_443,_444){
for(var name in _443){
var re=new RegExp("\\%\\{"+name+"\\}","g");
str=str.replace(re,_443[name]);
}
if(_444){
str=str.replace(/%\{([^\}\s]+)\}/g,"");
}
return str;
};
dojo.string.capitalize=function(str){
if(!dojo.lang.isString(str)){
return "";
}
if(arguments.length==0){
str=this;
}
var _448=str.split(" ");
var _449="";
var len=_448.length;
for(var i=0;i<len;i++){
var word=_448[i];
word=word.charAt(0).toUpperCase()+word.substring(1,word.length);
_449+=word;
if(i<len-1){
_449+=" ";
}
}
return new String(_449);
};
dojo.string.isBlank=function(str){
if(!dojo.lang.isString(str)){
return true;
}
return (dojo.string.trim(str).length==0);
};
dojo.string.encodeAscii=function(str){
if(!dojo.lang.isString(str)){
return str;
}
var ret="";
var _450=escape(str);
var _451,re=/%u([0-9A-F]{4})/i;
while((_451=_450.match(re))){
var num=Number("0x"+_451[1]);
var _453=escape("&#"+num+";");
ret+=_450.substring(0,_451.index)+_453;
_450=_450.substring(_451.index+_451[0].length);
}
ret+=_450.replace(/\+/g,"%2B");
return ret;
};
dojo.string.escape=function(type,str){
var args=[];
for(var i=1;i<arguments.length;i++){
args.push(arguments[i]);
}
switch(type.toLowerCase()){
case "xml":
case "html":
case "xhtml":
return dojo.string.escapeXml.apply(this,args);
case "sql":
return dojo.string.escapeSql.apply(this,args);
case "regexp":
case "regex":
return dojo.string.escapeRegExp.apply(this,args);
case "javascript":
case "jscript":
case "js":
return dojo.string.escapeJavaScript.apply(this,args);
case "ascii":
return dojo.string.encodeAscii.apply(this,args);
default:
return str;
}
};
dojo.string.escapeXml=function(str,_459){
str=str.replace(/&/gm,"&amp;").replace(/</gm,"&lt;").replace(/>/gm,"&gt;").replace(/"/gm,"&quot;");
if(!_459){
str=str.replace(/'/gm,"&#39;");
}
return str;
};
dojo.string.escapeSql=function(str){
return str.replace(/'/gm,"''");
};
dojo.string.escapeRegExp=function(str){
return str.replace(/\\/gm,"\\\\").replace(/([\f\b\n\t\r[\^$|?*+(){}])/gm,"\\$1");
};
dojo.string.escapeJavaScript=function(str){
return str.replace(/(["'\f\b\n\t\r])/gm,"\\$1");
};
dojo.string.escapeString=function(str){
return ("\""+str.replace(/(["\\])/g,"\\$1")+"\"").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\r]/g,"\\r");
};
dojo.string.summary=function(str,len){
if(!len||str.length<=len){
return str;
}else{
return str.substring(0,len).replace(/\.+$/,"")+"...";
}
};
dojo.string.endsWith=function(str,end,_462){
if(_462){
str=str.toLowerCase();
end=end.toLowerCase();
}
if((str.length-end.length)<0){
return false;
}
return str.lastIndexOf(end)==str.length-end.length;
};
dojo.string.endsWithAny=function(str){
for(var i=1;i<arguments.length;i++){
if(dojo.string.endsWith(str,arguments[i])){
return true;
}
}
return false;
};
dojo.string.startsWith=function(str,_466,_467){
if(_467){
str=str.toLowerCase();
_466=_466.toLowerCase();
}
return str.indexOf(_466)==0;
};
dojo.string.startsWithAny=function(str){
for(var i=1;i<arguments.length;i++){
if(dojo.string.startsWith(str,arguments[i])){
return true;
}
}
return false;
};
dojo.string.has=function(str){
for(var i=1;i<arguments.length;i++){
if(str.indexOf(arguments[i])>-1){
return true;
}
}
return false;
};
dojo.string.normalizeNewlines=function(text,_46d){
if(_46d=="\n"){
text=text.replace(/\r\n/g,"\n");
text=text.replace(/\r/g,"\n");
}else{
if(_46d=="\r"){
text=text.replace(/\r\n/g,"\r");
text=text.replace(/\n/g,"\r");
}else{
text=text.replace(/([^\r])\n/g,"$1\r\n");
text=text.replace(/\r([^\n])/g,"\r\n$1");
}
}
return text;
};
dojo.string.splitEscaped=function(str,_46f){
var _470=[];
for(var i=0,prevcomma=0;i<str.length;i++){
if(str.charAt(i)=="\\"){
i++;
continue;
}
if(str.charAt(i)==_46f){
_470.push(str.substring(prevcomma,i));
prevcomma=i+1;
}
}
_470.push(str.substr(prevcomma));
return _470;
};
dojo.provide("dojo.undo.browser");
dojo.require("dojo.io");
try{
if((!djConfig["preventBackButtonFix"])&&(!dojo.hostenv.post_load_)){
document.write("<iframe style='border: 0px; width: 1px; height: 1px; position: absolute; bottom: 0px; right: 0px; visibility: visible;' name='djhistory' id='djhistory' src='"+(dojo.hostenv.getBaseScriptUri()+"iframe_history.html")+"'></iframe>");
}
}
catch(e){
}
dojo.undo.browser={initialHref:window.location.href,initialHash:window.location.hash,moveForward:false,historyStack:[],forwardStack:[],historyIframe:null,bookmarkAnchor:null,locationTimer:null,setInitialState:function(args){
this.initialState={"url":this.initialHref,"kwArgs":args,"urlHash":this.initialHash};
},addToHistory:function(args){
var hash=null;
if(!this.historyIframe){
this.historyIframe=window.frames["djhistory"];
}
if(!this.bookmarkAnchor){
this.bookmarkAnchor=document.createElement("a");
(document.body||document.getElementsByTagName("body")[0]).appendChild(this.bookmarkAnchor);
this.bookmarkAnchor.style.display="none";
}
if((!args["changeUrl"])||(dojo.render.html.ie)){
var url=dojo.hostenv.getBaseScriptUri()+"iframe_history.html?"+(new Date()).getTime();
this.moveForward=true;
dojo.io.setIFrameSrc(this.historyIframe,url,false);
}
if(args["changeUrl"]){
this.changingUrl=true;
hash="#"+((args["changeUrl"]!==true)?args["changeUrl"]:(new Date()).getTime());
setTimeout("window.location.href = '"+hash+"'; dojo.undo.browser.changingUrl = false;",1);
this.bookmarkAnchor.href=hash;
if(dojo.render.html.ie){
var _476=args["back"]||args["backButton"]||args["handle"];
var tcb=function(_478){
if(window.location.hash!=""){
setTimeout("window.location.href = '"+hash+"';",1);
}
_476.apply(this,[_478]);
};
if(args["back"]){
args.back=tcb;
}else{
if(args["backButton"]){
args.backButton=tcb;
}else{
if(args["handle"]){
args.handle=tcb;
}
}
}
this.forwardStack=[];
var _479=args["forward"]||args["forwardButton"]||args["handle"];
var tfw=function(_47b){
if(window.location.hash!=""){
window.location.href=hash;
}
if(_479){
_479.apply(this,[_47b]);
}
};
if(args["forward"]){
args.forward=tfw;
}else{
if(args["forwardButton"]){
args.forwardButton=tfw;
}else{
if(args["handle"]){
args.handle=tfw;
}
}
}
}else{
if(dojo.render.html.moz){
if(!this.locationTimer){
this.locationTimer=setInterval("dojo.undo.browser.checkLocation();",200);
}
}
}
}
this.historyStack.push({"url":url,"kwArgs":args,"urlHash":hash});
},checkLocation:function(){
if(!this.changingUrl){
var hsl=this.historyStack.length;
if((window.location.hash==this.initialHash)||(window.location.href==this.initialHref)&&(hsl==1)){
this.handleBackButton();
return;
}
if(this.forwardStack.length>0){
if(this.forwardStack[this.forwardStack.length-1].urlHash==window.location.hash){
this.handleForwardButton();
return;
}
}
if((hsl>=2)&&(this.historyStack[hsl-2])){
if(this.historyStack[hsl-2].urlHash==window.location.hash){
this.handleBackButton();
return;
}
}
}
},iframeLoaded:function(evt,_47e){
var _47f=this._getUrlQuery(_47e.href);
if(_47f==null){
if(this.historyStack.length==1){
this.handleBackButton();
}
return;
}
if(this.moveForward){
this.moveForward=false;
return;
}
if(this.historyStack.length>=2&&_47f==this._getUrlQuery(this.historyStack[this.historyStack.length-2].url)){
this.handleBackButton();
}else{
if(this.forwardStack.length>0&&_47f==this._getUrlQuery(this.forwardStack[this.forwardStack.length-1].url)){
this.handleForwardButton();
}
}
},handleBackButton:function(){
var _480=this.historyStack.pop();
if(!_480){
return;
}
var last=this.historyStack[this.historyStack.length-1];
if(!last&&this.historyStack.length==0){
last=this.initialState;
}
if(last){
if(last.kwArgs["back"]){
last.kwArgs["back"]();
}else{
if(last.kwArgs["backButton"]){
last.kwArgs["backButton"]();
}else{
if(last.kwArgs["handle"]){
last.kwArgs.handle("back");
}
}
}
}
this.forwardStack.push(_480);
},handleForwardButton:function(){
var last=this.forwardStack.pop();
if(!last){
return;
}
if(last.kwArgs["forward"]){
last.kwArgs.forward();
}else{
if(last.kwArgs["forwardButton"]){
last.kwArgs.forwardButton();
}else{
if(last.kwArgs["handle"]){
last.kwArgs.handle("forward");
}
}
}
this.historyStack.push(last);
},_getUrlQuery:function(url){
var _484=url.split("?");
if(_484.length<2){
return null;
}else{
return _484[1];
}
}};
dojo.provide("dojo.io.BrowserIO");
dojo.require("dojo.io");
dojo.require("dojo.lang.array");
dojo.require("dojo.lang.func");
dojo.require("dojo.string.extras");
dojo.require("dojo.dom");
dojo.require("dojo.undo.browser");
dojo.io.checkChildrenForFile=function(node){
var _486=false;
var _487=node.getElementsByTagName("input");
dojo.lang.forEach(_487,function(_488){
if(_486){
return;
}
if(_488.getAttribute("type")=="file"){
_486=true;
}
});
return _486;
};
dojo.io.formHasFile=function(_489){
return dojo.io.checkChildrenForFile(_489);
};
dojo.io.updateNode=function(node,_48b){
node=dojo.byId(node);
var args=_48b;
if(dojo.lang.isString(_48b)){
args={url:_48b};
}
args.mimetype="text/html";
args.load=function(t,d,e){
while(node.firstChild){
if(dojo["event"]){
try{
dojo.event.browser.clean(node.firstChild);
}
catch(e){
}
}
node.removeChild(node.firstChild);
}
node.innerHTML=d;
};
dojo.io.bind(args);
};
dojo.io.formFilter=function(node){
var type=(node.type||"").toLowerCase();
return !node.disabled&&node.name&&!dojo.lang.inArray(type,["file","submit","image","reset","button"]);
};
dojo.io.encodeForm=function(_492,_493,_494){
if((!_492)||(!_492.tagName)||(!_492.tagName.toLowerCase()=="form")){
dojo.raise("Attempted to encode a non-form element.");
}
if(!_494){
_494=dojo.io.formFilter;
}
var enc=/utf/i.test(_493||"")?encodeURIComponent:dojo.string.encodeAscii;
var _496=[];
for(var i=0;i<_492.elements.length;i++){
var elm=_492.elements[i];
if(!elm||elm.tagName.toLowerCase()=="fieldset"||!_494(elm)){
continue;
}
var name=enc(elm.name);
var type=elm.type.toLowerCase();
if(type=="select-multiple"){
for(var j=0;j<elm.options.length;j++){
if(elm.options[j].selected){
_496.push(name+"="+enc(elm.options[j].value));
}
}
}else{
if(dojo.lang.inArray(type,["radio","checkbox"])){
if(elm.checked){
_496.push(name+"="+enc(elm.value));
}
}else{
_496.push(name+"="+enc(elm.value));
}
}
}
var _49c=_492.getElementsByTagName("input");
for(var i=0;i<_49c.length;i++){
var _49d=_49c[i];
if(_49d.type.toLowerCase()=="image"&&_49d.form==_492&&_494(_49d)){
var name=enc(_49d.name);
_496.push(name+"="+enc(_49d.value));
_496.push(name+".x=0");
_496.push(name+".y=0");
}
}
return _496.join("&")+"&";
};
dojo.io.FormBind=function(args){
this.bindArgs={};
if(args&&args.formNode){
this.init(args);
}else{
if(args){
this.init({formNode:args});
}
}
};
dojo.lang.extend(dojo.io.FormBind,{form:null,bindArgs:null,clickedButton:null,init:function(args){
var form=dojo.byId(args.formNode);
if(!form||!form.tagName||form.tagName.toLowerCase()!="form"){
throw new Error("FormBind: Couldn't apply, invalid form");
}else{
if(this.form==form){
return;
}else{
if(this.form){
throw new Error("FormBind: Already applied to a form");
}
}
}
dojo.lang.mixin(this.bindArgs,args);
this.form=form;
this.connect(form,"onsubmit","submit");
for(var i=0;i<form.elements.length;i++){
var node=form.elements[i];
if(node&&node.type&&dojo.lang.inArray(node.type.toLowerCase(),["submit","button"])){
this.connect(node,"onclick","click");
}
}
var _4a3=form.getElementsByTagName("input");
for(var i=0;i<_4a3.length;i++){
var _4a4=_4a3[i];
if(_4a4.type.toLowerCase()=="image"&&_4a4.form==form){
this.connect(_4a4,"onclick","click");
}
}
},onSubmit:function(form){
return true;
},submit:function(e){
e.preventDefault();
if(this.onSubmit(this.form)){
dojo.io.bind(dojo.lang.mixin(this.bindArgs,{formFilter:dojo.lang.hitch(this,"formFilter")}));
}
},click:function(e){
var node=e.currentTarget;
if(node.disabled){
return;
}
this.clickedButton=node;
},formFilter:function(node){
var type=(node.type||"").toLowerCase();
var _4ab=false;
if(node.disabled||!node.name){
_4ab=false;
}else{
if(dojo.lang.inArray(type,["submit","button","image"])){
if(!this.clickedButton){
this.clickedButton=node;
}
_4ab=node==this.clickedButton;
}else{
_4ab=!dojo.lang.inArray(type,["file","submit","reset","button"]);
}
}
return _4ab;
},connect:function(_4ac,_4ad,_4ae){
if(dojo.evalObjPath("dojo.event.connect")){
dojo.event.connect(_4ac,_4ad,this,_4ae);
}else{
var fcn=dojo.lang.hitch(this,_4ae);
_4ac[_4ad]=function(e){
if(!e){
e=window.event;
}
if(!e.currentTarget){
e.currentTarget=e.srcElement;
}
if(!e.preventDefault){
e.preventDefault=function(){
window.event.returnValue=false;
};
}
fcn(e);
};
}
}});
dojo.io.XMLHTTPTransport=new function(){
var _4b1=this;
var _4b2={};
this.useCache=false;
this.preventCache=false;
function getCacheKey(url,_4b4,_4b5){
return url+"|"+_4b4+"|"+_4b5.toLowerCase();
}
function addToCache(url,_4b7,_4b8,http){
_4b2[getCacheKey(url,_4b7,_4b8)]=http;
}
function getFromCache(url,_4bb,_4bc){
return _4b2[getCacheKey(url,_4bb,_4bc)];
}
this.clearCache=function(){
_4b2={};
};
function doLoad(_4bd,http,url,_4c0,_4c1){
if((http.status==200)||(http.status==304)||(http.status==204)||(location.protocol=="file:"&&(http.status==0||http.status==undefined))||(location.protocol=="chrome:"&&(http.status==0||http.status==undefined))){
var ret;
if(_4bd.method.toLowerCase()=="head"){
var _4c3=http.getAllResponseHeaders();
ret={};
ret.toString=function(){
return _4c3;
};
var _4c4=_4c3.split(/[\r\n]+/g);
for(var i=0;i<_4c4.length;i++){
var pair=_4c4[i].match(/^([^:]+)\s*:\s*(.+)$/i);
if(pair){
ret[pair[1]]=pair[2];
}
}
}else{
if(_4bd.mimetype=="text/javascript"){
try{
ret=dj_eval(http.responseText);
}
catch(e){
dojo.debug(e);
dojo.debug(http.responseText);
ret=null;
}
}else{
if(_4bd.mimetype=="text/json"){
try{
ret=dj_eval("("+http.responseText+")");
}
catch(e){
dojo.debug(e);
dojo.debug(http.responseText);
ret=false;
}
}else{
if((_4bd.mimetype=="application/xml")||(_4bd.mimetype=="text/xml")){
ret=http.responseXML;
if(!ret||typeof ret=="string"){
ret=dojo.dom.createDocumentFromText(http.responseText);
}
}else{
ret=http.responseText;
}
}
}
}
if(_4c1){
addToCache(url,_4c0,_4bd.method,http);
}
_4bd[(typeof _4bd.load=="function")?"load":"handle"]("load",ret,http,_4bd);
}else{
var _4c7=new dojo.io.Error("XMLHttpTransport Error: "+http.status+" "+http.statusText);
_4bd[(typeof _4bd.error=="function")?"error":"handle"]("error",_4c7,http,_4bd);
}
}
function setHeaders(http,_4c9){
if(_4c9["headers"]){
for(var _4ca in _4c9["headers"]){
if(_4ca.toLowerCase()=="content-type"&&!_4c9["contentType"]){
_4c9["contentType"]=_4c9["headers"][_4ca];
}else{
http.setRequestHeader(_4ca,_4c9["headers"][_4ca]);
}
}
}
}
this.inFlight=[];
this.inFlightTimer=null;
this.startWatchingInFlight=function(){
if(!this.inFlightTimer){
this.inFlightTimer=setInterval("dojo.io.XMLHTTPTransport.watchInFlight();",10);
}
};
this.watchInFlight=function(){
var now=null;
for(var x=this.inFlight.length-1;x>=0;x--){
var tif=this.inFlight[x];
if(!tif){
this.inFlight.splice(x,1);
continue;
}
if(4==tif.http.readyState){
this.inFlight.splice(x,1);
doLoad(tif.req,tif.http,tif.url,tif.query,tif.useCache);
}else{
if(tif.startTime){
if(!now){
now=(new Date()).getTime();
}
if(tif.startTime+(tif.req.timeoutSeconds*1000)<now){
if(typeof tif.http.abort=="function"){
tif.http.abort();
}
this.inFlight.splice(x,1);
tif.req[(typeof tif.req.timeout=="function")?"timeout":"handle"]("timeout",null,tif.http,tif.req);
}
}
}
}
if(this.inFlight.length==0){
clearInterval(this.inFlightTimer);
this.inFlightTimer=null;
}
};
var _4ce=dojo.hostenv.getXmlhttpObject()?true:false;
this.canHandle=function(_4cf){
return _4ce&&dojo.lang.inArray((_4cf["mimetype"].toLowerCase()||""),["text/plain","text/html","application/xml","text/xml","text/javascript","text/json"])&&!(_4cf["formNode"]&&dojo.io.formHasFile(_4cf["formNode"]));
};
this.multipartBoundary="45309FFF-BD65-4d50-99C9-36986896A96F";
this.bind=function(_4d0){
if(!_4d0["url"]){
if(!_4d0["formNode"]&&(_4d0["backButton"]||_4d0["back"]||_4d0["changeUrl"]||_4d0["watchForURL"])&&(!djConfig.preventBackButtonFix)){
dojo.deprecated("Using dojo.io.XMLHTTPTransport.bind() to add to browser history without doing an IO request is deprecated. Use dojo.undo.browser.addToHistory() instead.");
dojo.undo.browser.addToHistory(_4d0);
return true;
}
}
var url=_4d0.url;
var _4d2="";
if(_4d0["formNode"]){
var ta=_4d0.formNode.getAttribute("action");
if((ta)&&(!_4d0["url"])){
url=ta;
}
var tp=_4d0.formNode.getAttribute("method");
if((tp)&&(!_4d0["method"])){
_4d0.method=tp;
}
_4d2+=dojo.io.encodeForm(_4d0.formNode,_4d0.encoding,_4d0["formFilter"]);
}
if(url.indexOf("#")>-1){
dojo.debug("Warning: dojo.io.bind: stripping hash values from url:",url);
url=url.split("#")[0];
}
if(_4d0["file"]){
_4d0.method="post";
}
if(!_4d0["method"]){
_4d0.method="get";
}
if(_4d0.method.toLowerCase()=="get"){
_4d0.multipart=false;
}else{
if(_4d0["file"]){
_4d0.multipart=true;
}else{
if(!_4d0["multipart"]){
_4d0.multipart=false;
}
}
}
if(_4d0["backButton"]||_4d0["back"]||_4d0["changeUrl"]){
dojo.undo.browser.addToHistory(_4d0);
}
var _4d5=_4d0["content"]||{};
if(_4d0.sendTransport){
_4d5["dojo.transport"]="xmlhttp";
}
do{
if(_4d0.postContent){
_4d2=_4d0.postContent;
break;
}
if(_4d5){
_4d2+=dojo.io.argsFromMap(_4d5,_4d0.encoding);
}
if(_4d0.method.toLowerCase()=="get"||!_4d0.multipart){
break;
}
var t=[];
if(_4d2.length){
var q=_4d2.split("&");
for(var i=0;i<q.length;++i){
if(q[i].length){
var p=q[i].split("=");
t.push("--"+this.multipartBoundary,"Content-Disposition: form-data; name=\""+p[0]+"\"","",p[1]);
}
}
}
if(_4d0.file){
if(dojo.lang.isArray(_4d0.file)){
for(var i=0;i<_4d0.file.length;++i){
var o=_4d0.file[i];
t.push("--"+this.multipartBoundary,"Content-Disposition: form-data; name=\""+o.name+"\"; filename=\""+("fileName" in o?o.fileName:o.name)+"\"","Content-Type: "+("contentType" in o?o.contentType:"application/octet-stream"),"",o.content);
}
}else{
var o=_4d0.file;
t.push("--"+this.multipartBoundary,"Content-Disposition: form-data; name=\""+o.name+"\"; filename=\""+("fileName" in o?o.fileName:o.name)+"\"","Content-Type: "+("contentType" in o?o.contentType:"application/octet-stream"),"",o.content);
}
}
if(t.length){
t.push("--"+this.multipartBoundary+"--","");
_4d2=t.join("\r\n");
}
}while(false);
var _4db=_4d0["sync"]?false:true;
var _4dc=_4d0["preventCache"]||(this.preventCache==true&&_4d0["preventCache"]!=false);
var _4dd=_4d0["useCache"]==true||(this.useCache==true&&_4d0["useCache"]!=false);
if(!_4dc&&_4dd){
var _4de=getFromCache(url,_4d2,_4d0.method);
if(_4de){
doLoad(_4d0,_4de,url,_4d2,false);
return;
}
}
var http=dojo.hostenv.getXmlhttpObject(_4d0);
var _4e0=false;
if(_4db){
var _4e1=this.inFlight.push({"req":_4d0,"http":http,"url":url,"query":_4d2,"useCache":_4dd,"startTime":_4d0.timeoutSeconds?(new Date()).getTime():0});
this.startWatchingInFlight();
}
if(_4d0.method.toLowerCase()=="post"){
http.open("POST",url,_4db);
setHeaders(http,_4d0);
http.setRequestHeader("Content-Type",_4d0.multipart?("multipart/form-data; boundary="+this.multipartBoundary):(_4d0.contentType||"application/x-www-form-urlencoded"));
try{
http.send(_4d2);
}
catch(e){
if(typeof http.abort=="function"){
http.abort();
}
doLoad(_4d0,{status:404},url,_4d2,_4dd);
}
}else{
var _4e2=url;
if(_4d2!=""){
_4e2+=(_4e2.indexOf("?")>-1?"&":"?")+_4d2;
}
if(_4dc){
_4e2+=(dojo.string.endsWithAny(_4e2,"?","&")?"":(_4e2.indexOf("?")>-1?"&":"?"))+"dojo.preventCache="+new Date().valueOf();
}
http.open(_4d0.method.toUpperCase(),_4e2,_4db);
setHeaders(http,_4d0);
try{
http.send(null);
}
catch(e){
if(typeof http.abort=="function"){
http.abort();
}
doLoad(_4d0,{status:404},url,_4d2,_4dd);
}
}
if(!_4db){
doLoad(_4d0,http,url,_4d2,_4dd);
}
_4d0.abort=function(){
return http.abort();
};
return;
};
dojo.io.transports.addTransport("XMLHTTPTransport");
};
dojo.provide("dojo.io.cookie");
dojo.io.cookie.setCookie=function(name,_4e4,days,path,_4e7,_4e8){
var _4e9=-1;
if(typeof days=="number"&&days>=0){
var d=new Date();
d.setTime(d.getTime()+(days*24*60*60*1000));
_4e9=d.toGMTString();
}
_4e4=escape(_4e4);
document.cookie=name+"="+_4e4+";"+(_4e9!=-1?" expires="+_4e9+";":"")+(path?"path="+path:"")+(_4e7?"; domain="+_4e7:"")+(_4e8?"; secure":"");
};
dojo.io.cookie.set=dojo.io.cookie.setCookie;
dojo.io.cookie.getCookie=function(name){
var idx=document.cookie.lastIndexOf(name+"=");
if(idx==-1){
return null;
}
value=document.cookie.substring(idx+name.length+1);
var end=value.indexOf(";");
if(end==-1){
end=value.length;
}
value=value.substring(0,end);
value=unescape(value);
return value;
};
dojo.io.cookie.get=dojo.io.cookie.getCookie;
dojo.io.cookie.deleteCookie=function(name){
dojo.io.cookie.setCookie(name,"-",0);
};
dojo.io.cookie.setObjectCookie=function(name,obj,days,path,_4f3,_4f4,_4f5){
if(arguments.length==5){
_4f5=_4f3;
_4f3=null;
_4f4=null;
}
var _4f6=[],cookie,value="";
if(!_4f5){
cookie=dojo.io.cookie.getObjectCookie(name);
}
if(days>=0){
if(!cookie){
cookie={};
}
for(var prop in obj){
if(prop==null){
delete cookie[prop];
}else{
if(typeof obj[prop]=="string"||typeof obj[prop]=="number"){
cookie[prop]=obj[prop];
}
}
}
prop=null;
for(var prop in cookie){
_4f6.push(escape(prop)+"="+escape(cookie[prop]));
}
value=_4f6.join("&");
}
dojo.io.cookie.setCookie(name,value,days,path,_4f3,_4f4);
};
dojo.io.cookie.getObjectCookie=function(name){
var _4f9=null,cookie=dojo.io.cookie.getCookie(name);
if(cookie){
_4f9={};
var _4fa=cookie.split("&");
for(var i=0;i<_4fa.length;i++){
var pair=_4fa[i].split("=");
var _4fd=pair[1];
if(isNaN(_4fd)){
_4fd=unescape(pair[1]);
}
_4f9[unescape(pair[0])]=_4fd;
}
}
return _4f9;
};
dojo.io.cookie.isSupported=function(){
if(typeof navigator.cookieEnabled!="boolean"){
dojo.io.cookie.setCookie("__TestingYourBrowserForCookieSupport__","CookiesAllowed",90,null);
var _4fe=dojo.io.cookie.getCookie("__TestingYourBrowserForCookieSupport__");
navigator.cookieEnabled=(_4fe=="CookiesAllowed");
if(navigator.cookieEnabled){
this.deleteCookie("__TestingYourBrowserForCookieSupport__");
}
}
return navigator.cookieEnabled;
};
if(!dojo.io.cookies){
dojo.io.cookies=dojo.io.cookie;
}
dojo.kwCompoundRequire({common:["dojo.io"],rhino:["dojo.io.RhinoIO"],browser:["dojo.io.BrowserIO","dojo.io.cookie"],dashboard:["dojo.io.BrowserIO","dojo.io.cookie"]});
dojo.provide("dojo.io.*");
dojo.kwCompoundRequire({common:["dojo.uri.Uri",false,false]});
dojo.provide("dojo.uri.*");
dojo.provide("dojo.io.IframeIO");
dojo.require("dojo.io.BrowserIO");
dojo.require("dojo.uri.*");
dojo.io.createIFrame=function(_4ff,_500){
if(window[_4ff]){
return window[_4ff];
}
if(window.frames[_4ff]){
return window.frames[_4ff];
}
var r=dojo.render.html;
var _502=null;
var turi=dojo.uri.dojoUri("iframe_history.html?noInit=true");
var _504=((r.ie)&&(dojo.render.os.win))?"<iframe name='"+_4ff+"' src='"+turi+"' onload='"+_500+"'>":"iframe";
_502=document.createElement(_504);
with(_502){
name=_4ff;
setAttribute("name",_4ff);
id=_4ff;
}
(document.body||document.getElementsByTagName("body")[0]).appendChild(_502);
window[_4ff]=_502;
with(_502.style){
position="absolute";
left=top="0px";
height=width="1px";
visibility="hidden";
}
if(!r.ie){
dojo.io.setIFrameSrc(_502,turi,true);
_502.onload=new Function(_500);
}
return _502;
};
dojo.io.iframeContentWindow=function(_505){
var win=_505.contentWindow||dojo.io.iframeContentDocument(_505).defaultView||dojo.io.iframeContentDocument(_505).__parent__||(_505.name&&document.frames[_505.name])||null;
return win;
};
dojo.io.iframeContentDocument=function(_507){
var doc=_507.contentDocument||((_507.contentWindow)&&(_507.contentWindow.document))||((_507.name)&&(document.frames[_507.name])&&(document.frames[_507.name].document))||null;
return doc;
};
dojo.io.IframeTransport=new function(){
var _509=this;
this.currentRequest=null;
this.requestQueue=[];
this.iframeName="dojoIoIframe";
this.fireNextRequest=function(){
if((this.currentRequest)||(this.requestQueue.length==0)){
return;
}
var cr=this.currentRequest=this.requestQueue.shift();
cr._contentToClean=[];
var fn=cr["formNode"];
var _50c=cr["content"]||{};
if(cr.sendTransport){
_50c["dojo.transport"]="iframe";
}
if(fn){
if(_50c){
for(var x in _50c){
if(!fn[x]){
var tn;
if(dojo.render.html.ie){
tn=document.createElement("<input type='hidden' name='"+x+"' value='"+_50c[x]+"'>");
fn.appendChild(tn);
}else{
tn=document.createElement("input");
fn.appendChild(tn);
tn.type="hidden";
tn.name=x;
tn.value=_50c[x];
}
cr._contentToClean.push(x);
}else{
fn[x].value=_50c[x];
}
}
}
if(cr["url"]){
cr._originalAction=fn.getAttribute("action");
fn.setAttribute("action",cr.url);
}
if(!fn.getAttribute("method")){
fn.setAttribute("method",(cr["method"])?cr["method"]:"post");
}
cr._originalTarget=fn.getAttribute("target");
fn.setAttribute("target",this.iframeName);
fn.target=this.iframeName;
fn.submit();
}else{
var _50f=dojo.io.argsFromMap(this.currentRequest.content);
var _510=(cr.url.indexOf("?")>-1?"&":"?")+_50f;
dojo.io.setIFrameSrc(this.iframe,_510,true);
}
};
this.canHandle=function(_511){
return ((dojo.lang.inArray(_511["mimetype"],["text/plain","text/html","application/xml","text/xml","text/javascript","text/json"]))&&((_511["formNode"])&&(dojo.io.checkChildrenForFile(_511["formNode"])))&&(dojo.lang.inArray(_511["method"].toLowerCase(),["post","get"]))&&(!((_511["sync"])&&(_511["sync"]==true))));
};
this.bind=function(_512){
if(!this["iframe"]){
this.setUpIframe();
}
this.requestQueue.push(_512);
this.fireNextRequest();
return;
};
this.setUpIframe=function(){
this.iframe=dojo.io.createIFrame(this.iframeName,"dojo.io.IframeTransport.iframeOnload();");
};
this.iframeOnload=function(){
if(!_509.currentRequest){
_509.fireNextRequest();
return;
}
var req=_509.currentRequest;
var _514=req._contentToClean;
for(var i=0;i<_514.length;i++){
var key=_514[i];
var _517=req.formNode[key];
req.formNode.removeChild(_517);
req.formNode[key]=null;
}
if(req["_originalAction"]){
req.formNode.setAttribute("action",req._originalAction);
}
req.formNode.setAttribute("target",req._originalTarget);
req.formNode.target=req._originalTarget;
var ifr=_509.iframe;
var ifw=dojo.io.iframeContentWindow(ifr);
var _51a;
var _51b=false;
try{
var cmt=req.mimetype;
if((cmt=="text/javascript")||(cmt=="text/json")){
var cd=dojo.io.iframeContentDocument(_509.iframe);
var js=cd.getElementsByTagName("textarea")[0].value;
if(cmt=="text/json"){
js="("+js+")";
}
_51a=dj_eval(js);
}else{
if((cmt=="application/xml")||(cmt=="text/xml")){
_51a=dojo.io.iframeContentDocument(_509.iframe);
}else{
_51a=ifw.innerHTML;
}
}
_51b=true;
}
catch(e){
var _51f=new dojo.io.Error("IframeTransport Error");
if(dojo.lang.isFunction(req["error"])){
req.error("error",_51f,req);
}
}
try{
if(_51b&&dojo.lang.isFunction(req["load"])){
req.load("load",_51a,req);
}
}
catch(e){
throw e;
}
finally{
_509.currentRequest=null;
_509.fireNextRequest();
}
};
dojo.io.transports.addTransport("IframeTransport");
};
dojo.provide("dojo.date");
dojo.date.setDayOfYear=function(_520,_521){
_520.setMonth(0);
_520.setDate(_521);
return _520;
};
dojo.date.getDayOfYear=function(_522){
var _523=new Date(_522.getFullYear(),0,1);
return Math.floor((_522.getTime()-_523.getTime())/86400000);
};
dojo.date.setWeekOfYear=function(_524,week,_526){
if(arguments.length==1){
_526=0;
}
dojo.unimplemented("dojo.date.setWeekOfYear");
};
dojo.date.getWeekOfYear=function(_527,_528){
if(arguments.length==1){
_528=0;
}
var _529=new Date(_527.getFullYear(),0,1);
var day=_529.getDay();
_529.setDate(_529.getDate()-day+_528-(day>_528?7:0));
return Math.floor((_527.getTime()-_529.getTime())/604800000);
};
dojo.date.setIsoWeekOfYear=function(_52b,week,_52d){
if(arguments.length==1){
_52d=1;
}
dojo.unimplemented("dojo.date.setIsoWeekOfYear");
};
dojo.date.getIsoWeekOfYear=function(_52e,_52f){
if(arguments.length==1){
_52f=1;
}
dojo.unimplemented("dojo.date.getIsoWeekOfYear");
};
dojo.date.setIso8601=function(_530,_531){
var _532=(_531.indexOf("T")==-1)?_531.split(" "):_531.split("T");
dojo.date.setIso8601Date(_530,_532[0]);
if(_532.length==2){
dojo.date.setIso8601Time(_530,_532[1]);
}
return _530;
};
dojo.date.fromIso8601=function(_533){
return dojo.date.setIso8601(new Date(0,0),_533);
};
dojo.date.setIso8601Date=function(_534,_535){
var _536="^([0-9]{4})((-?([0-9]{2})(-?([0-9]{2}))?)|"+"(-?([0-9]{3}))|(-?W([0-9]{2})(-?([1-7]))?))?$";
var d=_535.match(new RegExp(_536));
if(!d){
dojo.debug("invalid date string: "+_535);
return false;
}
var year=d[1];
var _539=d[4];
var date=d[6];
var _53b=d[8];
var week=d[10];
var _53d=(d[12])?d[12]:1;
_534.setYear(year);
if(_53b){
dojo.date.setDayOfYear(_534,Number(_53b));
}else{
if(week){
_534.setMonth(0);
_534.setDate(1);
var gd=_534.getDay();
var day=(gd)?gd:7;
var _540=Number(_53d)+(7*Number(week));
if(day<=4){
_534.setDate(_540+1-day);
}else{
_534.setDate(_540+8-day);
}
}else{
if(_539){
_534.setDate(1);
_534.setMonth(_539-1);
}
if(date){
_534.setDate(date);
}
}
}
return _534;
};
dojo.date.fromIso8601Date=function(_541){
return dojo.date.setIso8601Date(new Date(0,0),_541);
};
dojo.date.setIso8601Time=function(_542,_543){
var _544="Z|(([-+])([0-9]{2})(:?([0-9]{2}))?)$";
var d=_543.match(new RegExp(_544));
var _546=0;
if(d){
if(d[0]!="Z"){
_546=(Number(d[3])*60)+Number(d[5]);
_546*=((d[2]=="-")?1:-1);
}
_546-=_542.getTimezoneOffset();
_543=_543.substr(0,_543.length-d[0].length);
}
var _547="^([0-9]{2})(:?([0-9]{2})(:?([0-9]{2})(.([0-9]+))?)?)?$";
var d=_543.match(new RegExp(_547));
if(!d){
dojo.debug("invalid time string: "+_543);
return false;
}
var _548=d[1];
var mins=Number((d[3])?d[3]:0);
var secs=(d[5])?d[5]:0;
var ms=d[7]?(Number("0."+d[7])*1000):0;
_542.setHours(_548);
_542.setMinutes(mins);
_542.setSeconds(secs);
_542.setMilliseconds(ms);
return _542;
};
dojo.date.fromIso8601Time=function(_54c){
return dojo.date.setIso8601Time(new Date(0,0),_54c);
};
dojo.date.shortTimezones=["IDLW","BET","HST","MART","AKST","PST","MST","CST","EST","AST","NFT","BST","FST","AT","GMT","CET","EET","MSK","IRT","GST","AFT","AGTT","IST","NPT","ALMT","MMT","JT","AWST","JST","ACST","AEST","LHST","VUT","NFT","NZT","CHAST","PHOT","LINT"];
dojo.date.timezoneOffsets=[-720,-660,-600,-570,-540,-480,-420,-360,-300,-240,-210,-180,-120,-60,0,60,120,180,210,240,270,300,330,345,360,390,420,480,540,570,600,630,660,690,720,765,780,840];
dojo.date.months=["January","February","March","April","May","June","July","August","September","October","November","December"];
dojo.date.shortMonths=["Jan","Feb","Mar","Apr","May","June","July","Aug","Sep","Oct","Nov","Dec"];
dojo.date.days=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
dojo.date.shortDays=["Sun","Mon","Tues","Wed","Thur","Fri","Sat"];
dojo.date.getDaysInMonth=function(_54d){
var _54e=_54d.getMonth();
var days=[31,28,31,30,31,30,31,31,30,31,30,31];
if(_54e==1&&dojo.date.isLeapYear(_54d)){
return 29;
}else{
return days[_54e];
}
};
dojo.date.isLeapYear=function(_550){
var year=_550.getFullYear();
return (year%400==0)?true:(year%100==0)?false:(year%4==0)?true:false;
};
dojo.date.getDayName=function(_552){
return dojo.date.days[_552.getDay()];
};
dojo.date.getDayShortName=function(_553){
return dojo.date.shortDays[_553.getDay()];
};
dojo.date.getMonthName=function(_554){
return dojo.date.months[_554.getMonth()];
};
dojo.date.getMonthShortName=function(_555){
return dojo.date.shortMonths[_555.getMonth()];
};
dojo.date.getTimezoneName=function(_556){
var _557=-(_556.getTimezoneOffset());
for(var i=0;i<dojo.date.timezoneOffsets.length;i++){
if(dojo.date.timezoneOffsets[i]==_557){
return dojo.date.shortTimezones[i];
}
}
function $(s){
s=String(s);
while(s.length<2){
s="0"+s;
}
return s;
}
return (_557<0?"-":"+")+$(Math.floor(Math.abs(_557)/60))+":"+$(Math.abs(_557)%60);
};
dojo.date.getOrdinal=function(_55a){
var date=_55a.getDate();
if(date%100!=11&&date%10==1){
return "st";
}else{
if(date%100!=12&&date%10==2){
return "nd";
}else{
if(date%100!=13&&date%10==3){
return "rd";
}else{
return "th";
}
}
}
};
dojo.date.format=dojo.date.strftime=function(_55c,_55d){
var _55e=null;
function _(s,n){
s=String(s);
n=(n||2)-s.length;
while(n-->0){
s=(_55e==null?"0":_55e)+s;
}
return s;
}
function $(_561){
switch(_561){
case "a":
return dojo.date.getDayShortName(_55c);
break;
case "A":
return dojo.date.getDayName(_55c);
break;
case "b":
case "h":
return dojo.date.getMonthShortName(_55c);
break;
case "B":
return dojo.date.getMonthName(_55c);
break;
case "c":
return _55c.toLocaleString();
break;
case "C":
return _(Math.floor(_55c.getFullYear()/100));
break;
case "d":
return _(_55c.getDate());
break;
case "D":
return $("m")+"/"+$("d")+"/"+$("y");
break;
case "e":
if(_55e==null){
_55e=" ";
}
return _(_55c.getDate(),2);
break;
case "g":
break;
case "G":
break;
case "F":
return $("Y")+"-"+$("m")+"-"+$("d");
break;
case "H":
return _(_55c.getHours());
break;
case "I":
return _(_55c.getHours()%12||12);
break;
case "j":
return _(dojo.date.getDayOfYear(_55c),3);
break;
case "m":
return _(_55c.getMonth()+1);
break;
case "M":
return _(_55c.getMinutes());
break;
case "n":
return "\n";
break;
case "p":
return _55c.getHours()<12?"am":"pm";
break;
case "r":
return $("I")+":"+$("M")+":"+$("S")+" "+$("p");
break;
case "R":
return $("H")+":"+$("M");
break;
case "S":
return _(_55c.getSeconds());
break;
case "t":
return "\t";
break;
case "T":
return $("H")+":"+$("M")+":"+$("S");
break;
case "u":
return String(_55c.getDay()||7);
break;
case "U":
return _(dojo.date.getWeekOfYear(_55c));
break;
case "V":
return _(dojo.date.getIsoWeekOfYear(_55c));
break;
case "W":
return _(dojo.date.getWeekOfYear(_55c,1));
break;
case "w":
return String(_55c.getDay());
break;
case "x":
break;
case "X":
break;
case "y":
return _(_55c.getFullYear()%100);
break;
case "Y":
return String(_55c.getFullYear());
break;
case "z":
var _562=_55c.getTimezoneOffset();
return (_562<0?"-":"+")+_(Math.floor(Math.abs(_562)/60))+":"+_(Math.abs(_562)%60);
break;
case "Z":
return dojo.date.getTimezoneName(_55c);
break;
case "%":
return "%";
break;
}
}
var _563="";
var i=0,index=0,switchCase;
while((index=_55d.indexOf("%",i))!=-1){
_563+=_55d.substring(i,index++);
switch(_55d.charAt(index++)){
case "_":
_55e=" ";
break;
case "-":
_55e="";
break;
case "0":
_55e="0";
break;
case "^":
switchCase="upper";
break;
case "#":
switchCase="swap";
break;
default:
_55e=null;
index--;
break;
}
property=$(_55d.charAt(index++));
if(switchCase=="upper"||(switchCase=="swap"&&/[a-z]/.test(property))){
property=property.toUpperCase();
}else{
if(switchCase=="swap"&&!/[a-z]/.test(property)){
property=property.toLowerCase();
}
}
swicthCase=null;
_563+=property;
i=index;
}
_563+=_55d.substring(i);
return _563;
};
dojo.date.compareTypes={DATE:1,TIME:2};
dojo.date.compare=function(_565,_566,_567){
var dA=_565;
var dB=_566||new Date();
var now=new Date();
var opt=_567||(dojo.date.compareTypes.DATE|dojo.date.compareTypes.TIME);
var d1=new Date(((opt&dojo.date.compareTypes.DATE)?(dA.getFullYear()):now.getFullYear()),((opt&dojo.date.compareTypes.DATE)?(dA.getMonth()):now.getMonth()),((opt&dojo.date.compareTypes.DATE)?(dA.getDate()):now.getDate()),((opt&dojo.date.compareTypes.TIME)?(dA.getHours()):0),((opt&dojo.date.compareTypes.TIME)?(dA.getMinutes()):0),((opt&dojo.date.compareTypes.TIME)?(dA.getSeconds()):0));
var d2=new Date(((opt&dojo.date.compareTypes.DATE)?(dB.getFullYear()):now.getFullYear()),((opt&dojo.date.compareTypes.DATE)?(dB.getMonth()):now.getMonth()),((opt&dojo.date.compareTypes.DATE)?(dB.getDate()):now.getDate()),((opt&dojo.date.compareTypes.TIME)?(dB.getHours()):0),((opt&dojo.date.compareTypes.TIME)?(dB.getMinutes()):0),((opt&dojo.date.compareTypes.TIME)?(dB.getSeconds()):0));
if(d1.valueOf()>d2.valueOf()){
return 1;
}
if(d1.valueOf()<d2.valueOf()){
return -1;
}
return 0;
};
dojo.date.dateParts={YEAR:0,MONTH:1,DAY:2,HOUR:3,MINUTE:4,SECOND:5,MILLISECOND:6};
dojo.date.add=function(d,unit,_570){
var n=(_570)?_570:1;
var v;
switch(unit){
case dojo.date.dateParts.YEAR:
v=new Date(d.getFullYear()+n,d.getMonth(),d.getDate(),d.getHours(),d.getMinutes(),d.getSeconds(),d.getMilliseconds());
break;
case dojo.date.dateParts.MONTH:
v=new Date(d.getFullYear(),d.getMonth()+n,d.getDate(),d.getHours(),d.getMinutes(),d.getSeconds(),d.getMilliseconds());
break;
case dojo.date.dateParts.HOUR:
v=new Date(d.getFullYear(),d.getMonth(),d.getDate(),d.getHours()+n,d.getMinutes(),d.getSeconds(),d.getMilliseconds());
break;
case dojo.date.dateParts.MINUTE:
v=new Date(d.getFullYear(),d.getMonth(),d.getDate(),d.getHours(),d.getMinutes()+n,d.getSeconds(),d.getMilliseconds());
break;
case dojo.date.dateParts.SECOND:
v=new Date(d.getFullYear(),d.getMonth(),d.getDate(),d.getHours(),d.getMinutes(),d.getSeconds()+n,d.getMilliseconds());
break;
case dojo.date.dateParts.MILLISECOND:
v=new Date(d.getFullYear(),d.getMonth(),d.getDate(),d.getHours(),d.getMinutes(),d.getSeconds(),d.getMilliseconds()+n);
break;
default:
v=new Date(d.getFullYear(),d.getMonth(),d.getDate()+n,d.getHours(),d.getMinutes(),d.getSeconds(),d.getMilliseconds());
}
return v;
};
dojo.date.toString=function(date,_574){
dojo.deprecated("dojo.date.toString","use dojo.date.format instead","0.4");
if(_574.indexOf("#d")>-1){
_574=_574.replace(/#dddd/g,dojo.date.getDayOfWeekName(date));
_574=_574.replace(/#ddd/g,dojo.date.getShortDayOfWeekName(date));
_574=_574.replace(/#dd/g,(date.getDate().toString().length==1?"0":"")+date.getDate());
_574=_574.replace(/#d/g,date.getDate());
}
if(_574.indexOf("#M")>-1){
_574=_574.replace(/#MMMM/g,dojo.date.getMonthName(date));
_574=_574.replace(/#MMM/g,dojo.date.getShortMonthName(date));
_574=_574.replace(/#MM/g,((date.getMonth()+1).toString().length==1?"0":"")+(date.getMonth()+1));
_574=_574.replace(/#M/g,date.getMonth()+1);
}
if(_574.indexOf("#y")>-1){
var _575=date.getFullYear().toString();
_574=_574.replace(/#yyyy/g,_575);
_574=_574.replace(/#yy/g,_575.substring(2));
_574=_574.replace(/#y/g,_575.substring(3));
}
if(_574.indexOf("#")==-1){
return _574;
}
if(_574.indexOf("#h")>-1){
var _576=date.getHours();
_576=(_576>12?_576-12:(_576==0)?12:_576);
_574=_574.replace(/#hh/g,(_576.toString().length==1?"0":"")+_576);
_574=_574.replace(/#h/g,_576);
}
if(_574.indexOf("#H")>-1){
_574=_574.replace(/#HH/g,(date.getHours().toString().length==1?"0":"")+date.getHours());
_574=_574.replace(/#H/g,date.getHours());
}
if(_574.indexOf("#m")>-1){
_574=_574.replace(/#mm/g,(date.getMinutes().toString().length==1?"0":"")+date.getMinutes());
_574=_574.replace(/#m/g,date.getMinutes());
}
if(_574.indexOf("#s")>-1){
_574=_574.replace(/#ss/g,(date.getSeconds().toString().length==1?"0":"")+date.getSeconds());
_574=_574.replace(/#s/g,date.getSeconds());
}
if(_574.indexOf("#T")>-1){
_574=_574.replace(/#TT/g,date.getHours()>=12?"PM":"AM");
_574=_574.replace(/#T/g,date.getHours()>=12?"P":"A");
}
if(_574.indexOf("#t")>-1){
_574=_574.replace(/#tt/g,date.getHours()>=12?"pm":"am");
_574=_574.replace(/#t/g,date.getHours()>=12?"p":"a");
}
return _574;
};
dojo.date.daysInMonth=function(_577,year){
dojo.deprecated("daysInMonth(month, year)","replaced by getDaysInMonth(dateObject)","0.4");
return dojo.date.getDaysInMonth(new Date(year,_577,1));
};
dojo.date.toLongDateString=function(date){
dojo.deprecated("dojo.date.toLongDateString","use dojo.date.format(date, \"%B %e, %Y\") instead","0.4");
return dojo.date.format(date,"%B %e, %Y");
};
dojo.date.toShortDateString=function(date){
dojo.deprecated("dojo.date.toShortDateString","use dojo.date.format(date, \"%b %e, %Y\") instead","0.4");
return dojo.date.format(date,"%b %e, %Y");
};
dojo.date.toMilitaryTimeString=function(date){
dojo.deprecated("dojo.date.toMilitaryTimeString","use dojo.date.format(date, \"%T\")","0.4");
return dojo.date.format(date,"%T");
};
dojo.date.toRelativeString=function(date){
var now=new Date();
var diff=(now-date)/1000;
var end=" ago";
var _580=false;
if(diff<0){
_580=true;
end=" from now";
diff=-diff;
}
if(diff<60){
diff=Math.round(diff);
return diff+" second"+(diff==1?"":"s")+end;
}else{
if(diff<3600){
diff=Math.round(diff/60);
return diff+" minute"+(diff==1?"":"s")+end;
}else{
if(diff<3600*24&&date.getDay()==now.getDay()){
diff=Math.round(diff/3600);
return diff+" hour"+(diff==1?"":"s")+end;
}else{
if(diff<3600*24*7){
diff=Math.round(diff/(3600*24));
if(diff==1){
return _580?"Tomorrow":"Yesterday";
}else{
return diff+" days"+end;
}
}else{
return dojo.date.toShortDateString(date);
}
}
}
}
};
dojo.date.getDayOfWeekName=function(date){
dojo.deprecated("dojo.date.getDayOfWeekName","use dojo.date.getDayName instead","0.4");
return dojo.date.days[date.getDay()];
};
dojo.date.getShortDayOfWeekName=function(date){
dojo.deprecated("dojo.date.getShortDayOfWeekName","use dojo.date.getDayShortName instead","0.4");
return dojo.date.shortDays[date.getDay()];
};
dojo.date.getShortMonthName=function(date){
dojo.deprecated("dojo.date.getShortMonthName","use dojo.date.getMonthShortName instead","0.4");
return dojo.date.shortMonths[date.getMonth()];
};
dojo.date.toSql=function(date,_585){
return dojo.date.format(date,"%F"+!_585?" %T":"");
};
dojo.date.fromSql=function(_586){
var _587=_586.split(/[\- :]/g);
while(_587.length<6){
_587.push(0);
}
return new Date(_587[0],(parseInt(_587[1],10)-1),_587[2],_587[3],_587[4],_587[5]);
};
dojo.provide("dojo.string.Builder");
dojo.require("dojo.string");
dojo.string.Builder=function(str){
this.arrConcat=(dojo.render.html.capable&&dojo.render.html["ie"]);
var a=[];
var b=str||"";
var _58b=this.length=b.length;
if(this.arrConcat){
if(b.length>0){
a.push(b);
}
b="";
}
this.toString=this.valueOf=function(){
return (this.arrConcat)?a.join(""):b;
};
this.append=function(s){
if(this.arrConcat){
a.push(s);
}else{
b+=s;
}
_58b+=s.length;
this.length=_58b;
return this;
};
this.clear=function(){
a=[];
b="";
_58b=this.length=0;
return this;
};
this.remove=function(f,l){
var s="";
if(this.arrConcat){
b=a.join("");
}
a=[];
if(f>0){
s=b.substring(0,(f-1));
}
b=s+b.substring(f+l);
_58b=this.length=b.length;
if(this.arrConcat){
a.push(b);
b="";
}
return this;
};
this.replace=function(o,n){
if(this.arrConcat){
b=a.join("");
}
a=[];
b=b.replace(o,n);
_58b=this.length=b.length;
if(this.arrConcat){
a.push(b);
b="";
}
return this;
};
this.insert=function(idx,s){
if(this.arrConcat){
b=a.join("");
}
a=[];
if(idx==0){
b=s+b;
}else{
var t=b.split("");
t.splice(idx,0,s);
b=t.join("");
}
_58b=this.length=b.length;
if(this.arrConcat){
a.push(b);
b="";
}
return this;
};
};
dojo.kwCompoundRequire({common:["dojo.string","dojo.string.common","dojo.string.extras","dojo.string.Builder"]});
dojo.provide("dojo.string.*");
if(!this["dojo"]){
alert("\"dojo/__package__.js\" is now located at \"dojo/dojo.js\". Please update your includes accordingly");
}
dojo.provide("dojo.AdapterRegistry");
dojo.require("dojo.lang.func");
dojo.AdapterRegistry=function(){
this.pairs=[];
};
dojo.lang.extend(dojo.AdapterRegistry,{register:function(name,_596,wrap,_598){
if(_598){
this.pairs.unshift([name,_596,wrap]);
}else{
this.pairs.push([name,_596,wrap]);
}
},match:function(){
for(var i=0;i<this.pairs.length;i++){
var pair=this.pairs[i];
if(pair[1].apply(this,arguments)){
return pair[2].apply(this,arguments);
}
}
throw new Error("No match found");
},unregister:function(name){
for(var i=0;i<this.pairs.length;i++){
var pair=this.pairs[i];
if(pair[0]==name){
this.pairs.splice(i,1);
return true;
}
}
return false;
}});
dojo.provide("dojo.json");
dojo.require("dojo.lang.func");
dojo.require("dojo.string.extras");
dojo.require("dojo.AdapterRegistry");
dojo.json={jsonRegistry:new dojo.AdapterRegistry(),register:function(name,_59f,wrap,_5a1){
dojo.json.jsonRegistry.register(name,_59f,wrap,_5a1);
},evalJson:function(json){
try{
return eval("("+json+")");
}
catch(e){
dojo.debug(e);
return json;
}
},evalJSON:function(json){
dojo.deprecated("dojo.json.evalJSON","use dojo.json.evalJson","0.4");
return this.evalJson(json);
},serialize:function(o){
var _5a5=typeof (o);
if(_5a5=="undefined"){
return "undefined";
}else{
if((_5a5=="number")||(_5a5=="boolean")){
return o+"";
}else{
if(o===null){
return "null";
}
}
}
if(_5a5=="string"){
return dojo.string.escapeString(o);
}
var me=arguments.callee;
var _5a7;
if(typeof (o.__json__)=="function"){
_5a7=o.__json__();
if(o!==_5a7){
return me(_5a7);
}
}
if(typeof (o.json)=="function"){
_5a7=o.json();
if(o!==_5a7){
return me(_5a7);
}
}
if(_5a5!="function"&&typeof (o.length)=="number"){
var res=[];
for(var i=0;i<o.length;i++){
var val=me(o[i]);
if(typeof (val)!="string"){
val="undefined";
}
res.push(val);
}
return "["+res.join(",")+"]";
}
try{
window.o=o;
_5a7=dojo.json.jsonRegistry.match(o);
return me(_5a7);
}
catch(e){
}
if(_5a5=="function"){
return null;
}
res=[];
for(var k in o){
var _5ac;
if(typeof (k)=="number"){
_5ac="\""+k+"\"";
}else{
if(typeof (k)=="string"){
_5ac=dojo.string.escapeString(k);
}else{
continue;
}
}
val=me(o[k]);
if(typeof (val)!="string"){
continue;
}
res.push(_5ac+":"+val);
}
return "{"+res.join(",")+"}";
}};
dojo.provide("dojo.Deferred");
dojo.require("dojo.lang.func");
dojo.Deferred=function(_5ad){
this.chain=[];
this.id=this._nextId();
this.fired=-1;
this.paused=0;
this.results=[null,null];
this.canceller=_5ad;
this.silentlyCancelled=false;
};
dojo.lang.extend(dojo.Deferred,{getFunctionFromArgs:function(){
var a=arguments;
if((a[0])&&(!a[1])){
if(dojo.lang.isFunction(a[0])){
return a[0];
}else{
if(dojo.lang.isString(a[0])){
return dj_global[a[0]];
}
}
}else{
if((a[0])&&(a[1])){
return dojo.lang.hitch(a[0],a[1]);
}
}
return null;
},repr:function(){
var _5af;
if(this.fired==-1){
_5af="unfired";
}else{
if(this.fired==0){
_5af="success";
}else{
_5af="error";
}
}
return "Deferred("+this.id+", "+_5af+")";
},toString:dojo.lang.forward("repr"),_nextId:(function(){
var n=1;
return function(){
return n++;
};
})(),cancel:function(){
if(this.fired==-1){
if(this.canceller){
this.canceller(this);
}else{
this.silentlyCancelled=true;
}
if(this.fired==-1){
this.errback(new Error(this.repr()));
}
}else{
if((this.fired==0)&&(this.results[0] instanceof dojo.Deferred)){
this.results[0].cancel();
}
}
},_pause:function(){
this.paused++;
},_unpause:function(){
this.paused--;
if((this.paused==0)&&(this.fired>=0)){
this._fire();
}
},_continue:function(res){
this._resback(res);
this._unpause();
},_resback:function(res){
this.fired=((res instanceof Error)?1:0);
this.results[this.fired]=res;
this._fire();
},_check:function(){
if(this.fired!=-1){
if(!this.silentlyCancelled){
dojo.raise("already called!");
}
this.silentlyCancelled=false;
return;
}
},callback:function(res){
this._check();
this._resback(res);
},errback:function(res){
this._check();
if(!(res instanceof Error)){
res=new Error(res);
}
this._resback(res);
},addBoth:function(cb,cbfn){
var _5b7=this.getFunctionFromArgs(cb,cbfn);
if(arguments.length>2){
_5b7=dojo.lang.curryArguments(null,_5b7,arguments,2);
}
return this.addCallbacks(_5b7,_5b7);
},addCallback:function(cb,cbfn){
var _5ba=this.getFunctionFromArgs(cb,cbfn);
if(arguments.length>2){
_5ba=dojo.lang.curryArguments(null,_5ba,arguments,2);
}
return this.addCallbacks(_5ba,null);
},addErrback:function(cb,cbfn){
var _5bd=this.getFunctionFromArgs(cb,cbfn);
if(arguments.length>2){
_5bd=dojo.lang.curryArguments(null,_5bd,arguments,2);
}
return this.addCallbacks(null,_5bd);
return this.addCallbacks(null,fn);
},addCallbacks:function(cb,eb){
this.chain.push([cb,eb]);
if(this.fired>=0){
this._fire();
}
return this;
},_fire:function(){
var _5c0=this.chain;
var _5c1=this.fired;
var res=this.results[_5c1];
var self=this;
var cb=null;
while(_5c0.length>0&&this.paused==0){
var pair=_5c0.shift();
var f=pair[_5c1];
if(f==null){
continue;
}
try{
res=f(res);
_5c1=((res instanceof Error)?1:0);
if(res instanceof dojo.Deferred){
cb=function(res){
self._continue(res);
};
this._pause();
}
}
catch(err){
_5c1=1;
res=err;
}
}
this.fired=_5c1;
this.results[_5c1]=res;
if((cb)&&(this.paused)){
res.addBoth(cb);
}
}});
dojo.provide("dojo.rpc.Deferred");
dojo.require("dojo.Deferred");
dojo.rpc.Deferred=dojo.Deferred;
dojo.rpc.Deferred.prototype=dojo.Deferred.prototype;
dojo.provide("dojo.rpc.RpcService");
dojo.require("dojo.io.*");
dojo.require("dojo.json");
dojo.require("dojo.lang.func");
dojo.require("dojo.rpc.Deferred");
dojo.rpc.RpcService=function(url){
if(url){
this.connect(url);
}
};
dojo.lang.extend(dojo.rpc.RpcService,{strictArgChecks:true,serviceUrl:"",parseResults:function(obj){
return obj;
},errorCallback:function(_5ca){
return function(type,obj,e){
_5ca.errback(e);
};
},resultCallback:function(_5ce){
var tf=dojo.lang.hitch(this,function(type,obj,e){
var _5d3=this.parseResults(obj||e);
_5ce.callback(_5d3);
});
return tf;
},generateMethod:function(_5d4,_5d5,url){
return dojo.lang.hitch(this,function(){
var _5d7=new dojo.rpc.Deferred();
if((this.strictArgChecks)&&(_5d5!=null)&&(arguments.length!=_5d5.length)){
dojo.raise("Invalid number of parameters for remote method.");
}else{
this.bind(_5d4,arguments,_5d7,url);
}
return _5d7;
});
},processSmd:function(_5d8){
dojo.debug("RpcService: Processing returned SMD.");
if(_5d8.methods){
dojo.lang.forEach(_5d8.methods,function(m){
if(m&&m["name"]){
dojo.debug("RpcService: Creating Method: this.",m.name,"()");
this[m.name]=this.generateMethod(m.name,m.parameters,m["url"]||m["serviceUrl"]||m["serviceURL"]);
if(dojo.lang.isFunction(this[m.name])){
dojo.debug("RpcService: Successfully created",m.name,"()");
}else{
dojo.debug("RpcService: Failed to create",m.name,"()");
}
}
},this);
}
this.serviceUrl=_5d8.serviceUrl||_5d8.serviceURL;
dojo.debug("RpcService: Dojo RpcService is ready for use.");
},connect:function(_5da){
dojo.debug("RpcService: Attempting to load SMD document from:",_5da);
dojo.io.bind({url:_5da,mimetype:"text/json",load:dojo.lang.hitch(this,function(type,_5dc,e){
return this.processSmd(_5dc);
}),sync:true});
}});
dojo.provide("dojo.rpc.JsonService");
dojo.require("dojo.rpc.RpcService");
dojo.require("dojo.io.*");
dojo.require("dojo.json");
dojo.require("dojo.lang");
dojo.rpc.JsonService=function(args){
if(args){
if(dojo.lang.isString(args)){
this.connect(args);
}else{
if(args["smdUrl"]){
this.connect(args.smdUrl);
}
if(args["smdStr"]){
this.processSmd(dj_eval("("+args.smdStr+")"));
}
if(args["smdObj"]){
this.processSmd(args.smdObj);
}
if(args["serviceUrl"]){
this.serviceUrl=args.serviceUrl;
}
if(typeof args["strictArgChecks"]!="undefined"){
this.strictArgChecks=args.strictArgChecks;
}
}
}
};
dojo.inherits(dojo.rpc.JsonService,dojo.rpc.RpcService);
dojo.lang.extend(dojo.rpc.JsonService,{bustCache:false,contentType:"application/json-rpc",lastSubmissionId:0,callRemote:function(_5df,_5e0){
var _5e1=new dojo.rpc.Deferred();
this.bind(_5df,_5e0,_5e1);
return _5e1;
},bind:function(_5e2,_5e3,_5e4,url){
dojo.io.bind({url:url||this.serviceUrl,postContent:this.createRequest(_5e2,_5e3),method:"POST",contentType:this.contentType,mimetype:"text/json",load:this.resultCallback(_5e4),preventCache:this.bustCache});
},createRequest:function(_5e6,_5e7){
var req={"params":_5e7,"method":_5e6,"id":++this.lastSubmissionId};
var data=dojo.json.serialize(req);
dojo.debug("JsonService: JSON-RPC Request: "+data);
return data;
},parseResults:function(obj){
if(!obj){
return;
}
if(obj["Result"]||obj["result"]){
return obj["result"]||obj["Result"];
}else{
if(obj["ResultSet"]){
return obj["ResultSet"];
}else{
return obj;
}
}
}});
dojo.kwCompoundRequire({common:["dojo.rpc.JsonService",false,false]});
dojo.provide("dojo.rpc.*");
dojo.provide("dojo.xml.Parse");
dojo.require("dojo.dom");
dojo.xml.Parse=function(){
function getDojoTagName(node){
var _5ec=node.tagName;
if(_5ec.substr(0,5).toLowerCase()!="dojo:"){
if(_5ec.substr(0,4).toLowerCase()=="dojo"){
return "dojo:"+_5ec.substring(4).toLowerCase();
}
var djt=node.getAttribute("dojoType")||node.getAttribute("dojotype");
if(djt){
return "dojo:"+djt.toLowerCase();
}
if(node.getAttributeNS&&node.getAttributeNS(dojo.dom.dojoml,"type")){
return "dojo:"+node.getAttributeNS(dojo.dom.dojoml,"type").toLowerCase();
}
try{
djt=node.getAttribute("dojo:type");
}
catch(e){
}
if(djt){
return "dojo:"+djt.toLowerCase();
}
if(!dj_global["djConfig"]||!djConfig["ignoreClassNames"]){
var _5ee=node.className||node.getAttribute("class");
if(_5ee&&_5ee.indexOf&&_5ee.indexOf("dojo-")!=-1){
var _5ef=_5ee.split(" ");
for(var x=0;x<_5ef.length;x++){
if(_5ef[x].length>5&&_5ef[x].indexOf("dojo-")>=0){
return "dojo:"+_5ef[x].substr(5).toLowerCase();
}
}
}
}
}
return _5ec.toLowerCase();
}
this.parseElement=function(node,_5f2,_5f3,_5f4){
if(node.getAttribute("parseWidgets")=="false"){
return {};
}
var _5f5={};
var _5f6=getDojoTagName(node);
_5f5[_5f6]=[];
if((!_5f3)||(_5f6.substr(0,4).toLowerCase()=="dojo")){
var _5f7=parseAttributes(node);
for(var attr in _5f7){
if((!_5f5[_5f6][attr])||(typeof _5f5[_5f6][attr]!="array")){
_5f5[_5f6][attr]=[];
}
_5f5[_5f6][attr].push(_5f7[attr]);
}
_5f5[_5f6].nodeRef=node;
_5f5.tagName=_5f6;
_5f5.index=_5f4||0;
}
var _5f9=0;
var tcn,i=0,nodes=node.childNodes;
while(tcn=nodes[i++]){
switch(tcn.nodeType){
case dojo.dom.ELEMENT_NODE:
_5f9++;
var ctn=getDojoTagName(tcn);
if(!_5f5[ctn]){
_5f5[ctn]=[];
}
_5f5[ctn].push(this.parseElement(tcn,true,_5f3,_5f9));
if((tcn.childNodes.length==1)&&(tcn.childNodes.item(0).nodeType==dojo.dom.TEXT_NODE)){
_5f5[ctn][_5f5[ctn].length-1].value=tcn.childNodes.item(0).nodeValue;
}
break;
case dojo.dom.TEXT_NODE:
if(node.childNodes.length==1){
_5f5[_5f6].push({value:node.childNodes.item(0).nodeValue});
}
break;
default:
break;
}
}
return _5f5;
};
function parseAttributes(node){
var _5fd={};
var atts=node.attributes;
var _5ff,i=0;
while(_5ff=atts[i++]){
if((dojo.render.html.capable)&&(dojo.render.html.ie)){
if(!_5ff){
continue;
}
if((typeof _5ff=="object")&&(typeof _5ff.nodeValue=="undefined")||(_5ff.nodeValue==null)||(_5ff.nodeValue=="")){
continue;
}
}
var nn=(_5ff.nodeName.indexOf("dojo:")==-1)?_5ff.nodeName:_5ff.nodeName.split("dojo:")[1];
_5fd[nn]={value:_5ff.nodeValue};
}
return _5fd;
}
};
dojo.provide("dojo.xml.domUtil");
dojo.require("dojo.graphics.color");
dojo.require("dojo.dom");
dojo.require("dojo.style");
dojo.deprecated("dojo.xml.domUtil is deprecated, use dojo.dom instead");
dojo.xml.domUtil=new function(){
this.nodeTypes={ELEMENT_NODE:1,ATTRIBUTE_NODE:2,TEXT_NODE:3,CDATA_SECTION_NODE:4,ENTITY_REFERENCE_NODE:5,ENTITY_NODE:6,PROCESSING_INSTRUCTION_NODE:7,COMMENT_NODE:8,DOCUMENT_NODE:9,DOCUMENT_TYPE_NODE:10,DOCUMENT_FRAGMENT_NODE:11,NOTATION_NODE:12};
this.dojoml="http://www.dojotoolkit.org/2004/dojoml";
this.idIncrement=0;
this.getTagName=function(){
return dojo.dom.getTagName.apply(dojo.dom,arguments);
};
this.getUniqueId=function(){
return dojo.dom.getUniqueId.apply(dojo.dom,arguments);
};
this.getFirstChildTag=function(){
return dojo.dom.getFirstChildElement.apply(dojo.dom,arguments);
};
this.getLastChildTag=function(){
return dojo.dom.getLastChildElement.apply(dojo.dom,arguments);
};
this.getNextSiblingTag=function(){
return dojo.dom.getNextSiblingElement.apply(dojo.dom,arguments);
};
this.getPreviousSiblingTag=function(){
return dojo.dom.getPreviousSiblingElement.apply(dojo.dom,arguments);
};
this.forEachChildTag=function(node,_602){
var _603=this.getFirstChildTag(node);
while(_603){
if(_602(_603)=="break"){
break;
}
_603=this.getNextSiblingTag(_603);
}
};
this.moveChildren=function(){
return dojo.dom.moveChildren.apply(dojo.dom,arguments);
};
this.copyChildren=function(){
return dojo.dom.copyChildren.apply(dojo.dom,arguments);
};
this.clearChildren=function(){
return dojo.dom.removeChildren.apply(dojo.dom,arguments);
};
this.replaceChildren=function(){
return dojo.dom.replaceChildren.apply(dojo.dom,arguments);
};
this.getStyle=function(){
return dojo.style.getStyle.apply(dojo.style,arguments);
};
this.toCamelCase=function(){
return dojo.style.toCamelCase.apply(dojo.style,arguments);
};
this.toSelectorCase=function(){
return dojo.style.toSelectorCase.apply(dojo.style,arguments);
};
this.getAncestors=function(){
return dojo.dom.getAncestors.apply(dojo.dom,arguments);
};
this.isChildOf=function(){
return dojo.dom.isDescendantOf.apply(dojo.dom,arguments);
};
this.createDocumentFromText=function(){
return dojo.dom.createDocumentFromText.apply(dojo.dom,arguments);
};
if(dojo.render.html.capable||dojo.render.svg.capable){
this.createNodesFromText=function(txt,wrap){
return dojo.dom.createNodesFromText.apply(dojo.dom,arguments);
};
}
this.extractRGB=function(_606){
return dojo.graphics.color.extractRGB(_606);
};
this.hex2rgb=function(hex){
return dojo.graphics.color.hex2rgb(hex);
};
this.rgb2hex=function(r,g,b){
return dojo.graphics.color.rgb2hex(r,g,b);
};
this.insertBefore=function(){
return dojo.dom.insertBefore.apply(dojo.dom,arguments);
};
this.before=this.insertBefore;
this.insertAfter=function(){
return dojo.dom.insertAfter.apply(dojo.dom,arguments);
};
this.after=this.insertAfter;
this.insert=function(){
return dojo.dom.insertAtPosition.apply(dojo.dom,arguments);
};
this.insertAtIndex=function(){
return dojo.dom.insertAtIndex.apply(dojo.dom,arguments);
};
this.textContent=function(){
return dojo.dom.textContent.apply(dojo.dom,arguments);
};
this.renderedTextContent=function(){
return dojo.dom.renderedTextContent.apply(dojo.dom,arguments);
};
this.remove=function(node){
return dojo.dom.removeNode.apply(dojo.dom,arguments);
};
};
dojo.provide("dojo.xml.htmlUtil");
dojo.require("dojo.html");
dojo.require("dojo.style");
dojo.require("dojo.dom");
dojo.deprecated("dojo.xml.htmlUtil is deprecated, use dojo.html instead");
dojo.xml.htmlUtil=new function(){
this.styleSheet=dojo.style.styleSheet;
this._clobberSelection=function(){
return dojo.html.clearSelection.apply(dojo.html,arguments);
};
this.disableSelect=function(){
return dojo.html.disableSelection.apply(dojo.html,arguments);
};
this.enableSelect=function(){
return dojo.html.enableSelection.apply(dojo.html,arguments);
};
this.getInnerWidth=function(){
return dojo.style.getInnerWidth.apply(dojo.style,arguments);
};
this.getOuterWidth=function(node){
dojo.unimplemented("dojo.xml.htmlUtil.getOuterWidth");
};
this.getInnerHeight=function(){
return dojo.style.getInnerHeight.apply(dojo.style,arguments);
};
this.getOuterHeight=function(node){
dojo.unimplemented("dojo.xml.htmlUtil.getOuterHeight");
};
this.getTotalOffset=function(){
return dojo.style.getTotalOffset.apply(dojo.style,arguments);
};
this.totalOffsetLeft=function(){
return dojo.style.totalOffsetLeft.apply(dojo.style,arguments);
};
this.getAbsoluteX=this.totalOffsetLeft;
this.totalOffsetTop=function(){
return dojo.style.totalOffsetTop.apply(dojo.style,arguments);
};
this.getAbsoluteY=this.totalOffsetTop;
this.getEventTarget=function(){
return dojo.html.getEventTarget.apply(dojo.html,arguments);
};
this.getScrollTop=function(){
return dojo.html.getScrollTop.apply(dojo.html,arguments);
};
this.getScrollLeft=function(){
return dojo.html.getScrollLeft.apply(dojo.html,arguments);
};
this.evtTgt=this.getEventTarget;
this.getParentOfType=function(){
return dojo.html.getParentOfType.apply(dojo.html,arguments);
};
this.getAttribute=function(){
return dojo.html.getAttribute.apply(dojo.html,arguments);
};
this.getAttr=function(node,attr){
dojo.deprecated("dojo.xml.htmlUtil.getAttr is deprecated, use dojo.xml.htmlUtil.getAttribute instead");
return dojo.xml.htmlUtil.getAttribute(node,attr);
};
this.hasAttribute=function(){
return dojo.html.hasAttribute.apply(dojo.html,arguments);
};
this.hasAttr=function(node,attr){
dojo.deprecated("dojo.xml.htmlUtil.hasAttr is deprecated, use dojo.xml.htmlUtil.hasAttribute instead");
return dojo.xml.htmlUtil.hasAttribute(node,attr);
};
this.getClass=function(){
return dojo.html.getClass.apply(dojo.html,arguments);
};
this.hasClass=function(){
return dojo.html.hasClass.apply(dojo.html,arguments);
};
this.prependClass=function(){
return dojo.html.prependClass.apply(dojo.html,arguments);
};
this.addClass=function(){
return dojo.html.addClass.apply(dojo.html,arguments);
};
this.setClass=function(){
return dojo.html.setClass.apply(dojo.html,arguments);
};
this.removeClass=function(){
return dojo.html.removeClass.apply(dojo.html,arguments);
};
this.classMatchType={ContainsAll:0,ContainsAny:1,IsOnly:2};
this.getElementsByClass=function(){
return dojo.html.getElementsByClass.apply(dojo.html,arguments);
};
this.getElementsByClassName=this.getElementsByClass;
this.setOpacity=function(){
return dojo.style.setOpacity.apply(dojo.style,arguments);
};
this.getOpacity=function(){
return dojo.style.getOpacity.apply(dojo.style,arguments);
};
this.clearOpacity=function(){
return dojo.style.clearOpacity.apply(dojo.style,arguments);
};
this.gravity=function(){
return dojo.html.gravity.apply(dojo.html,arguments);
};
this.gravity.NORTH=1;
this.gravity.SOUTH=1<<1;
this.gravity.EAST=1<<2;
this.gravity.WEST=1<<3;
this.overElement=function(){
return dojo.html.overElement.apply(dojo.html,arguments);
};
this.insertCssRule=function(){
return dojo.style.insertCssRule.apply(dojo.style,arguments);
};
this.insertCSSRule=function(_612,_613,_614){
dojo.deprecated("dojo.xml.htmlUtil.insertCSSRule is deprecated, use dojo.xml.htmlUtil.insertCssRule instead");
return dojo.xml.htmlUtil.insertCssRule(_612,_613,_614);
};
this.removeCssRule=function(){
return dojo.style.removeCssRule.apply(dojo.style,arguments);
};
this.removeCSSRule=function(_615){
dojo.deprecated("dojo.xml.htmlUtil.removeCSSRule is deprecated, use dojo.xml.htmlUtil.removeCssRule instead");
return dojo.xml.htmlUtil.removeCssRule(_615);
};
this.insertCssFile=function(){
return dojo.style.insertCssFile.apply(dojo.style,arguments);
};
this.insertCSSFile=function(URI,doc,_618){
dojo.deprecated("dojo.xml.htmlUtil.insertCSSFile is deprecated, use dojo.xml.htmlUtil.insertCssFile instead");
return dojo.xml.htmlUtil.insertCssFile(URI,doc,_618);
};
this.getBackgroundColor=function(){
return dojo.style.getBackgroundColor.apply(dojo.style,arguments);
};
this.getUniqueId=function(){
return dojo.dom.getUniqueId();
};
this.getStyle=function(){
return dojo.style.getStyle.apply(dojo.style,arguments);
};
};
dojo.require("dojo.xml.Parse");
dojo.kwCompoundRequire({common:["dojo.xml.domUtil"],browser:["dojo.xml.htmlUtil"],dashboard:["dojo.xml.htmlUtil"],svg:["dojo.xml.svgUtil"]});
dojo.provide("dojo.xml.*");
dojo.provide("dojo.lang.type");
dojo.require("dojo.lang.common");
dojo.lang.whatAmI=function(wh){
try{
if(dojo.lang.isArray(wh)){
return "array";
}
if(dojo.lang.isFunction(wh)){
return "function";
}
if(dojo.lang.isString(wh)){
return "string";
}
if(dojo.lang.isNumber(wh)){
return "number";
}
if(dojo.lang.isBoolean(wh)){
return "boolean";
}
if(dojo.lang.isAlien(wh)){
return "alien";
}
if(dojo.lang.isUndefined(wh)){
return "undefined";
}
for(var name in dojo.lang.whatAmI.custom){
if(dojo.lang.whatAmI.custom[name](wh)){
return name;
}
}
if(dojo.lang.isObject(wh)){
return "object";
}
}
catch(E){
}
return "unknown";
};
dojo.lang.whatAmI.custom={};
dojo.lang.isNumeric=function(wh){
return (!isNaN(wh)&&isFinite(wh)&&(wh!=null)&&!dojo.lang.isBoolean(wh)&&!dojo.lang.isArray(wh));
};
dojo.lang.isBuiltIn=function(wh){
return (dojo.lang.isArray(wh)||dojo.lang.isFunction(wh)||dojo.lang.isString(wh)||dojo.lang.isNumber(wh)||dojo.lang.isBoolean(wh)||(wh==null)||(wh instanceof Error)||(typeof wh=="error"));
};
dojo.lang.isPureObject=function(wh){
return ((wh!=null)&&dojo.lang.isObject(wh)&&wh.constructor==Object);
};
dojo.lang.isOfType=function(_61e,type){
if(dojo.lang.isArray(type)){
var _620=type;
for(var i in _620){
var _622=_620[i];
if(dojo.lang.isOfType(_61e,_622)){
return true;
}
}
return false;
}else{
if(dojo.lang.isString(type)){
type=type.toLowerCase();
}
switch(type){
case Array:
case "array":
return dojo.lang.isArray(_61e);
break;
case Function:
case "function":
return dojo.lang.isFunction(_61e);
break;
case String:
case "string":
return dojo.lang.isString(_61e);
break;
case Number:
case "number":
return dojo.lang.isNumber(_61e);
break;
case "numeric":
return dojo.lang.isNumeric(_61e);
break;
case Boolean:
case "boolean":
return dojo.lang.isBoolean(_61e);
break;
case Object:
case "object":
return dojo.lang.isObject(_61e);
break;
case "pureobject":
return dojo.lang.isPureObject(_61e);
break;
case "builtin":
return dojo.lang.isBuiltIn(_61e);
break;
case "alien":
return dojo.lang.isAlien(_61e);
break;
case "undefined":
return dojo.lang.isUndefined(_61e);
break;
case null:
case "null":
return (_61e===null);
break;
case "optional":
return ((_61e===null)||dojo.lang.isUndefined(_61e));
break;
default:
if(dojo.lang.isFunction(type)){
return (_61e instanceof type);
}else{
dojo.raise("dojo.lang.isOfType() was passed an invalid type");
}
break;
}
}
dojo.raise("If we get here, it means a bug was introduced above.");
};
dojo.lang.getObject=function(str){
var _624=str.split("."),i=0,obj=dj_global;
do{
obj=obj[_624[i++]];
}while(i<_624.length&&obj);
return (obj!=dj_global)?obj:null;
};
dojo.lang.doesObjectExist=function(str){
var _626=str.split("."),i=0,obj=dj_global;
do{
obj=obj[_626[i++]];
}while(i<_626.length&&obj);
return (obj&&obj!=dj_global);
};
dojo.provide("dojo.lang.assert");
dojo.require("dojo.lang.common");
dojo.require("dojo.lang.array");
dojo.require("dojo.lang.type");
dojo.lang.assert=function(_627,_628){
if(!_627){
var _629="An assert statement failed.\n"+"The method dojo.lang.assert() was called with a 'false' value.\n";
if(_628){
_629+="Here's the assert message:\n"+_628+"\n";
}
throw new Error(_629);
}
};
dojo.lang.assertType=function(_62a,type,_62c){
if(!dojo.lang.isOfType(_62a,type)){
if(!_62c){
if(!dojo.lang.assertType._errorMessage){
dojo.lang.assertType._errorMessage="Type mismatch: dojo.lang.assertType() failed.";
}
_62c=dojo.lang.assertType._errorMessage;
}
dojo.lang.assert(false,_62c);
}
};
dojo.lang.assertValidKeywords=function(_62d,_62e,_62f){
var key;
if(!_62f){
if(!dojo.lang.assertValidKeywords._errorMessage){
dojo.lang.assertValidKeywords._errorMessage="In dojo.lang.assertValidKeywords(), found invalid keyword:";
}
_62f=dojo.lang.assertValidKeywords._errorMessage;
}
if(dojo.lang.isArray(_62e)){
for(key in _62d){
if(!dojo.lang.inArray(_62e,key)){
dojo.lang.assert(false,_62f+" "+key);
}
}
}else{
for(key in _62d){
if(!(key in _62e)){
dojo.lang.assert(false,_62f+" "+key);
}
}
}
};
dojo.provide("dojo.lang.repr");
dojo.require("dojo.lang.common");
dojo.require("dojo.AdapterRegistry");
dojo.require("dojo.string.extras");
dojo.lang.reprRegistry=new dojo.AdapterRegistry();
dojo.lang.registerRepr=function(name,_632,wrap,_634){
dojo.lang.reprRegistry.register(name,_632,wrap,_634);
};
dojo.lang.repr=function(obj){
if(typeof (obj)=="undefined"){
return "undefined";
}else{
if(obj===null){
return "null";
}
}
try{
if(typeof (obj["__repr__"])=="function"){
return obj["__repr__"]();
}else{
if((typeof (obj["repr"])=="function")&&(obj.repr!=arguments.callee)){
return obj["repr"]();
}
}
return dojo.lang.reprRegistry.match(obj);
}
catch(e){
if(typeof (obj.NAME)=="string"&&(obj.toString==Function.prototype.toString||obj.toString==Object.prototype.toString)){
return o.NAME;
}
}
if(typeof (obj)=="function"){
obj=(obj+"").replace(/^\s+/,"");
var idx=obj.indexOf("{");
if(idx!=-1){
obj=obj.substr(0,idx)+"{...}";
}
}
return obj+"";
};
dojo.lang.reprArrayLike=function(arr){
try{
var na=dojo.lang.map(arr,dojo.lang.repr);
return "["+na.join(", ")+"]";
}
catch(e){
}
};
dojo.lang.reprString=function(str){
dojo.deprecated("dojo.lang.reprNumber","use `String(num)` instead","0.4");
return dojo.string.escapeString(str);
};
dojo.lang.reprNumber=function(num){
dojo.deprecated("dojo.lang.reprNumber","use `String(num)` instead","0.4");
return num+"";
};
(function(){
var m=dojo.lang;
m.registerRepr("arrayLike",m.isArrayLike,m.reprArrayLike);
m.registerRepr("string",m.isString,m.reprString);
m.registerRepr("numbers",m.isNumber,m.reprNumber);
m.registerRepr("boolean",m.isBoolean,m.reprNumber);
})();
dojo.provide("dojo.lang.declare");
dojo.require("dojo.lang.common");
dojo.require("dojo.lang.extras");
dojo.lang.declare=function(_63c,_63d,_63e,init){
var ctor=function(){
var self=this._getPropContext();
var s=self.constructor.superclass;
if((s)&&(s.constructor)){
if(s.constructor==arguments.callee){
this.inherited("constructor",arguments);
}else{
this._inherited(s,"constructor",arguments);
}
}
if((!this.prototyping)&&(self.initializer)){
self.initializer.apply(this,arguments);
}
};
var scp=(_63d?_63d.prototype:null);
if(scp){
scp.prototyping=true;
ctor.prototype=new _63d();
scp.prototyping=false;
}
ctor.prototype.constructor=ctor;
ctor.superclass=scp;
dojo.lang.extend(ctor,dojo.lang.declare.base);
_63e=(_63e||{});
_63e.initializer=(_63e.initializer)||(init)||(function(){
});
_63e.className=_63c;
dojo.lang.extend(ctor,_63e);
dojo.lang.setObjPathValue(_63c,ctor,null,true);
};
dojo.lang.declare.base={_getPropContext:function(){
return (this.___proto||this);
},_inherited:function(_644,_645,args){
var _647=this.___proto;
this.___proto=_644;
var _648=_644[_645].apply(this,(args||[]));
this.___proto=_647;
return _648;
},inherited:function(prop,args){
var p=this._getPropContext();
do{
if((!p.constructor)||(!p.constructor.superclass)){
return;
}
p=p.constructor.superclass;
}while(!(prop in p));
return (typeof p[prop]=="function"?this._inherited(p,prop,args):p[prop]);
}};
dojo.declare=dojo.lang.declare;
dojo.kwCompoundRequire({common:["dojo.lang","dojo.lang.common","dojo.lang.assert","dojo.lang.array","dojo.lang.type","dojo.lang.func","dojo.lang.extras","dojo.lang.repr","dojo.lang.declare"]});
dojo.provide("dojo.lang.*");
dojo.provide("dojo.storage");
dojo.provide("dojo.storage.StorageProvider");
dojo.require("dojo.lang.*");
dojo.require("dojo.event.*");
dojo.storage=function(){
};
dojo.lang.extend(dojo.storage,{SUCCESS:"success",FAILED:"failed",PENDING:"pending",SIZE_NOT_AVAILABLE:"Size not available",SIZE_NO_LIMIT:"No size limit",namespace:"dojoStorage",onHideSettingsUI:null,initialize:function(){
dojo.unimplemented("dojo.storage.initialize");
},isAvailable:function(){
dojo.unimplemented("dojo.storage.isAvailable");
},put:function(key,_64d,_64e){
dojo.unimplemented("dojo.storage.put");
},get:function(key){
dojo.unimplemented("dojo.storage.get");
},hasKey:function(key){
if(this.get(key)!=null){
return true;
}else{
return false;
}
},getKeys:function(){
dojo.unimplemented("dojo.storage.getKeys");
},clear:function(){
dojo.unimplemented("dojo.storage.clear");
},remove:function(key){
dojo.unimplemented("dojo.storage.remove");
},isPermanent:function(){
dojo.unimplemented("dojo.storage.isPermanent");
},getMaximumSize:function(){
dojo.unimplemented("dojo.storage.getMaximumSize");
},hasSettingsUI:function(){
return false;
},showSettingsUI:function(){
dojo.unimplemented("dojo.storage.showSettingsUI");
},hideSettingsUI:function(){
dojo.unimplemented("dojo.storage.hideSettingsUI");
},getType:function(){
dojo.unimplemented("dojo.storage.getType");
},isValidKey:function(_652){
if(_652==null||typeof _652=="undefined"){
return false;
}
return /^[0-9A-Za-z_]*$/.test(_652);
}});
dojo.storage.manager=new function(){
this.currentProvider=null;
this.available=false;
this.initialized=false;
this.providers=new Array();
this.namespace="dojo.storage";
this.initialize=function(){
this.autodetect();
};
this.register=function(name,_654){
this.providers[this.providers.length]=_654;
this.providers[name]=_654;
};
this.setProvider=function(_655){
};
this.autodetect=function(){
if(this.initialized==true){
return;
}
var _656=null;
for(var i=0;i<this.providers.length;i++){
_656=this.providers[i];
if(_656.isAvailable()){
break;
}
}
if(_656==null){
this.initialized=true;
this.available=false;
this.currentProvider=null;
dojo.raise("No storage provider found for this platform");
}
this.currentProvider=_656;
for(var i in _656){
dojo.storage[i]=_656[i];
}
dojo.storage.manager=this;
dojo.storage.initialize();
this.initialized=true;
this.available=true;
};
this.isAvailable=function(){
return this.available;
};
this.isInitialized=function(){
if(dojo.flash.ready==false){
return false;
}else{
return this.initialized;
}
};
this.supportsProvider=function(_658){
try{
var _659=eval("new "+_658+"()");
var _65a=_659.isAvailable();
if(_65a==null||typeof _65a=="undefined"){
return false;
}
return _65a;
}
catch(exception){
dojo.debug("exception="+exception);
return false;
}
};
this.getProvider=function(){
return this.currentProvider;
};
this.loaded=function(){
};
};
dojo.provide("dojo.flash");
dojo.require("dojo.string.*");
dojo.require("dojo.uri.*");
dojo.flash={flash6_version:null,flash8_version:null,ready:false,_visible:true,_loadedListeners:new Array(),_installingListeners:new Array(),setSwf:function(_65b){
if(_65b==null||dojo.lang.isUndefined(_65b)){
return;
}
if(_65b.flash6!=null&&!dojo.lang.isUndefined(_65b.flash6)){
this.flash6_version=_65b.flash6;
}
if(_65b.flash8!=null&&!dojo.lang.isUndefined(_65b.flash8)){
this.flash8_version=_65b.flash8;
}
if(!dojo.lang.isUndefined(_65b.visible)){
this._visible=_65b.visible;
}
this._initialize();
},useFlash6:function(){
if(this.flash6_version==null){
return false;
}else{
if(this.flash6_version!=null&&dojo.flash.info.commVersion==6){
return true;
}else{
return false;
}
}
},useFlash8:function(){
if(this.flash8_version==null){
return false;
}else{
if(this.flash8_version!=null&&dojo.flash.info.commVersion==8){
return true;
}else{
return false;
}
}
},addLoadedListener:function(_65c){
this._loadedListeners.push(_65c);
},addInstallingListener:function(_65d){
this._installingListeners.push(_65d);
},loaded:function(){
dojo.flash.ready=true;
if(dojo.flash._loadedListeners.length>0){
for(var i=0;i<dojo.flash._loadedListeners.length;i++){
dojo.flash._loadedListeners[i].call(null);
}
}
},installing:function(){
if(dojo.flash._installingListeners.length>0){
for(var i=0;i<dojo.flash._installingListeners.length;i++){
dojo.flash._installingListeners[i].call(null);
}
}
},_initialize:function(){
var _660=new dojo.flash.Install();
dojo.flash.installer=_660;
if(_660.needed()==true){
_660.install();
}else{
dojo.flash.obj=new dojo.flash.Embed(this._visible);
dojo.flash.obj.write(dojo.flash.info.commVersion);
dojo.flash.comm=new dojo.flash.Communicator();
}
}};
dojo.flash.Info=function(){
if(dojo.render.html.ie){
document.writeln("<script language=\"VBScript\" type=\"text/vbscript\">");
document.writeln("Function VBGetSwfVer(i)");
document.writeln("  on error resume next");
document.writeln("  Dim swControl, swVersion");
document.writeln("  swVersion = 0");
document.writeln("  set swControl = CreateObject(\"ShockwaveFlash.ShockwaveFlash.\" + CStr(i))");
document.writeln("  if (IsObject(swControl)) then");
document.writeln("    swVersion = swControl.GetVariable(\"$version\")");
document.writeln("  end if");
document.writeln("  VBGetSwfVer = swVersion");
document.writeln("End Function");
document.writeln("</script>");
}
this._detectVersion();
this._detectCommunicationVersion();
};
dojo.flash.Info.prototype={version:-1,versionMajor:-1,versionMinor:-1,versionRevision:-1,capable:false,commVersion:6,installing:false,isVersionOrAbove:function(_661,_662,_663){
_663=parseFloat("."+_663);
if(this.versionMajor>=_661&&this.versionMinor>=_662&&this.versionRevision>=_663){
return true;
}else{
return false;
}
},_detectVersion:function(){
var _664;
for(var _665=25;_665>0;_665--){
if(dojo.render.html.ie){
_664=VBGetSwfVer(_665);
}else{
_664=this._JSFlashInfo(_665);
}
if(_664==-1){
this.capable=false;
return;
}else{
if(_664!=0){
var _666;
if(dojo.render.html.ie){
var _667=_664.split(" ");
var _668=_667[1];
_666=_668.split(",");
}else{
_666=_664.split(".");
}
this.versionMajor=_666[0];
this.versionMinor=_666[1];
this.versionRevision=_666[2];
versionString=this.versionMajor+"."+this.versionRevision;
this.version=parseFloat(versionString);
this.capable=true;
break;
}
}
}
},_JSFlashInfo:function(_669){
if(navigator.plugins!=null&&navigator.plugins.length>0){
if(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]){
var _66a=navigator.plugins["Shockwave Flash 2.0"]?" 2.0":"";
var _66b=navigator.plugins["Shockwave Flash"+_66a].description;
var _66c=_66b.split(" ");
var _66d=_66c[2].split(".");
var _66e=_66d[0];
var _66f=_66d[1];
if(_66c[3]!=""){
tempArrayMinor=_66c[3].split("r");
}else{
tempArrayMinor=_66c[4].split("r");
}
var _670=tempArrayMinor[1]>0?tempArrayMinor[1]:0;
var _671=_66e+"."+_66f+"."+_670;
return _671;
}
}
return -1;
},_detectCommunicationVersion:function(){
if(this.capable==false){
this.commVersion=null;
return;
}
if(typeof djConfig["forceFlashComm"]!="undefined"&&typeof djConfig["forceFlashComm"]!=null){
this.commVersion=djConfig["forceFlashComm"];
return;
}
if(dojo.render.html.safari==true||dojo.render.html.opera==true){
this.commVersion=8;
}else{
this.commVersion=6;
}
}};
dojo.flash.Embed=function(_672){
this._visible=_672;
};
dojo.flash.Embed.prototype={width:215,height:138,id:"flashObject",_visible:true,write:function(_673,_674){
if(dojo.lang.isUndefined(_674)){
_674=false;
}
var _675=new dojo.string.Builder();
_675.append("width: "+this.width+"px; ");
_675.append("height: "+this.height+"px; ");
if(this._visible==false){
_675.append("position: absolute; ");
_675.append("z-index: 10000; ");
_675.append("top: -1000px; ");
_675.append("left: -1000px; ");
}
_675=_675.toString();
var _676;
var _677;
if(_673==6){
_677=dojo.flash.flash6_version;
var _678=djConfig.baseRelativePath;
_677=_677+"?baseRelativePath="+escape(_678);
_676="<embed id=\""+this.id+"\" src=\""+_677+"\" "+"    quality=\"high\" bgcolor=\"#ffffff\" "+"    width=\""+this.width+"\" height=\""+this.height+"\" "+"    name=\""+this.id+"\" "+"    align=\"middle\" allowScriptAccess=\"sameDomain\" "+"    type=\"application/x-shockwave-flash\" swLiveConnect=\"true\" "+"    pluginspage=\"http://www.macromedia.com/go/getflashplayer\">";
}else{
_677=dojo.flash.flash8_version;
var _679=_677,swflocEmbed=_677;
if(_674){
var _67a=escape(window.location);
document.title=document.title.slice(0,47)+" - Flash Player Installation";
var _67b=escape(document.title);
_679+="?MMredirectURL="+_67a+"&MMplayerType=ActiveX"+"&MMdoctitle="+_67b;
swflocEmbed+="?MMredirectURL="+_67a+"&MMplayerType=PlugIn";
}
_676="<object classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" "+"codebase=\"http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0\" "+"width=\""+this.width+"\" "+"height=\""+this.height+"\" "+"id=\""+this.id+"\" "+"align=\"middle\"> "+"<param name=\"allowScriptAccess\" value=\"sameDomain\" /> "+"<param name=\"movie\" value=\""+_679+"\" /> "+"<param name=\"quality\" value=\"high\" /> "+"<param name=\"bgcolor\" value=\"#ffffff\" /> "+"<embed src=\""+swflocEmbed+"\" "+"quality=\"high\" "+"bgcolor=\"#ffffff\" "+"width=\""+this.width+"\" "+"height=\""+this.height+"\" "+"id=\""+this.id+"\" "+"name=\""+this.id+"\" "+"swLiveConnect=\"true\" "+"align=\"middle\" "+"allowScriptAccess=\"sameDomain\" "+"type=\"application/x-shockwave-flash\" "+"pluginspage=\"http://www.macromedia.com/go/getflashplayer\" />"+"</object>";
}
_676="<div id=\""+this.id+"Container\" style=\""+_675+"\"> "+_676+"</div>";
document.writeln(_676);
},get:function(){
return document.getElementById(this.id);
},setVisible:function(_67c){
var _67d=dojo.byId(this.id+"Container");
if(_67c==true){
_67d.style.visibility="visible";
}else{
_67d.style.position="absolute";
_67d.style.x="-1000px";
_67d.style.y="-1000px";
_67d.style.visibility="hidden";
}
},center:function(){
var _67e=this.width;
var _67f=this.height;
var _680=document.body.clientWidth;
var _681=document.body.clientHeight;
if(!dojo.render.html.ie&&document.compatMode=="CSS1Compat"){
_680=document.body.parentNode.clientWidth;
_681=document.body.parentNode.clientHeight;
}else{
if(dojo.render.html.ie&&document.compatMode=="CSS1Compat"){
_680=document.documentElement.clientWidth;
_681=document.documentElement.clientHeight;
}else{
if(dojo.render.html.safari){
_681=self.innerHeight;
}
}
}
var _682=window.scrollX;
var _683=window.scrollY;
if(typeof _682=="undefined"){
if(document.compatMode=="CSS1Compat"){
_682=document.documentElement.scrollLeft;
_683=document.documentElement.scrollTop;
}else{
_682=document.body.scrollLeft;
_683=document.body.scrollTop;
}
}
var x=_682+(_680-_67e)/2;
var y=_683+(_681-_67f)/2;
var _686=dojo.byId(this.id+"Container");
_686.style.top=y+"px";
_686.style.left=x+"px";
}};
dojo.flash.Communicator=function(){
if(dojo.flash.useFlash6()){
this._writeFlash6();
}else{
if(dojo.flash.useFlash8()){
this._writeFlash8();
}
}
};
dojo.flash.Communicator.prototype={_writeFlash6:function(){
var id=dojo.flash.obj.id;
document.writeln("<script language=\"JavaScript\">");
document.writeln("  function "+id+"_DoFSCommand(command, args){ ");
document.writeln("    dojo.flash.comm._handleFSCommand(command, args); ");
document.writeln("}");
document.writeln("</script>");
if(dojo.render.html.ie){
document.writeln("<SCRIPT LANGUAGE=VBScript> ");
document.writeln("on error resume next ");
document.writeln("Sub "+id+"_FSCommand(ByVal command, ByVal args)");
document.writeln(" call "+id+"_DoFSCommand(command, args)");
document.writeln("end sub");
document.writeln("</SCRIPT> ");
}
},_writeFlash8:function(){
},_handleFSCommand:function(_688,args){
if(_688!=null&&!dojo.lang.isUndefined(_688)&&/^FSCommand:(.*)/.test(_688)==true){
_688=_688.match(/^FSCommand:(.*)/)[1];
}
if(_688=="addCallback"){
this._fscommandAddCallback(_688,args);
}else{
if(_688=="call"){
this._fscommandCall(_688,args);
}else{
if(_688=="fscommandReady"){
this._fscommandReady();
}
}
}
},_fscommandAddCallback:function(_68a,args){
var _68c=args;
var _68d=function(){
return dojo.flash.comm._call(_68c,arguments);
};
dojo.flash.comm[_68c]=_68d;
dojo.flash.obj.get().SetVariable("_succeeded",true);
},_fscommandCall:function(_68e,args){
var _690=dojo.flash.obj.get();
var _691=args;
var _692=parseInt(_690.GetVariable("_numArgs"));
var _693=new Array();
for(var i=0;i<_692;i++){
var _695=_690.GetVariable("_"+i);
_693.push(_695);
}
var _696;
if(_691.indexOf(".")==-1){
_696=window[_691];
}else{
_696=eval(_691);
}
var _697=null;
if(!dojo.lang.isUndefined(_696)&&_696!=null){
_697=_696.apply(null,_693);
}
_690.SetVariable("_returnResult",_697);
},_fscommandReady:function(){
var _698=dojo.flash.obj.get();
_698.SetVariable("fscommandReady","true");
},_call:function(_699,args){
var _69b=dojo.flash.obj.get();
_69b.SetVariable("_functionName",_699);
_69b.SetVariable("_numArgs",args.length);
for(var i=0;i<args.length;i++){
var _69d=args[i];
_69d=_69d.replace(/\0/g,"\\0");
_69b.SetVariable("_"+i,_69d);
}
_69b.TCallLabel("/_flashRunner","execute");
var _69e=_69b.GetVariable("_returnResult");
_69e=_69e.replace(/\\0/g,"\x00");
return _69e;
},_addExternalInterfaceCallback:function(_69f){
var _6a0=function(){
var _6a1=new Array(arguments.length);
for(var i=0;i<arguments.length;i++){
_6a1[i]=arguments[i];
}
return dojo.flash.comm._execFlash(_69f,_6a1);
};
dojo.flash.comm[_69f]=_6a0;
},_encodeData:function(data){
var _6a4=/\&([^;]*)\;/g;
data=data.replace(_6a4,"&amp;$1;");
data=data.replace(/</g,"&lt;");
data=data.replace(/>/g,"&gt;");
data=data.replace("\\","&custom_backslash;&custom_backslash;");
data=data.replace(/\n/g,"\\n");
data=data.replace(/\r/g,"\\r");
data=data.replace(/\f/g,"\\f");
data=data.replace(/\0/g,"\\0");
data=data.replace(/\'/g,"\\'");
data=data.replace(/\"/g,"\\\"");
return data;
},_decodeData:function(data){
if(data==null||typeof data=="undefined"){
return data;
}
data=data.replace(/\&custom_lt\;/g,"<");
data=data.replace(/\&custom_gt\;/g,">");
data=eval("\""+data+"\"");
return data;
},_chunkArgumentData:function(_6a6,_6a7){
var _6a8=dojo.flash.obj.get();
var _6a9=Math.ceil(_6a6.length/1024);
for(var i=0;i<_6a9;i++){
var _6ab=i*1024;
var _6ac=i*1024+1024;
if(i==(_6a9-1)){
_6ac=i*1024+_6a6.length;
}
var _6ad=_6a6.substring(_6ab,_6ac);
_6ad=this._encodeData(_6ad);
_6a8.CallFunction("<invoke name=\"chunkArgumentData\" "+"returntype=\"javascript\">"+"<arguments>"+"<string>"+_6ad+"</string>"+"<number>"+_6a7+"</number>"+"</arguments>"+"</invoke>");
}
},_chunkReturnData:function(){
var _6ae=dojo.flash.obj.get();
var _6af=_6ae.getReturnLength();
var _6b0=new Array();
for(var i=0;i<_6af;i++){
var _6b2=_6ae.CallFunction("<invoke name=\"chunkReturnData\" "+"returntype=\"javascript\">"+"<arguments>"+"<number>"+i+"</number>"+"</arguments>"+"</invoke>");
if(_6b2=="\"\""||_6b2=="''"){
_6b2="";
}else{
_6b2=_6b2.substring(1,_6b2.length-1);
}
_6b0.push(_6b2);
}
var _6b3=_6b0.join("");
return _6b3;
},_execFlash:function(_6b4,_6b5){
var _6b6=dojo.flash.obj.get();
_6b6.startExec();
_6b6.setNumberArguments(_6b5.length);
for(var i=0;i<_6b5.length;i++){
this._chunkArgumentData(_6b5[i],i);
}
_6b6.exec(_6b4);
var _6b8=this._chunkReturnData();
_6b8=this._decodeData(_6b8);
_6b6.endExec();
return _6b8;
}};
dojo.flash.Install=function(){
};
dojo.flash.Install.prototype={needed:function(){
if(dojo.flash.info.capable==false){
return true;
}
if(dojo.render.os.mac==true&&!dojo.flash.info.isVersionOrAbove(8,0,0)){
return true;
}
if(!dojo.flash.info.isVersionOrAbove(6,0,0)){
return true;
}
return false;
},install:function(){
dojo.flash.info.installing=true;
dojo.flash.installing();
if(dojo.flash.info.capable==false){
var _6b9=new dojo.flash.Embed(false);
_6b9.write(8);
}else{
if(dojo.flash.info.isVersionOrAbove(6,0,65)){
var _6b9=new dojo.flash.Embed(false);
_6b9.write(8,true);
_6b9.setVisible(true);
_6b9.center();
}else{
alert("This content requires a more recent version of the Macromedia "+" Flash Player.");
window.location.href="http://www.macromedia.com/go/getflashplayer";
}
}
},_onInstallStatus:function(msg){
if(msg=="Download.Complete"){
dojo.flash._initialize();
}else{
if(msg=="Download.Cancelled"){
alert("This content requires a more recent version of the Macromedia "+" Flash Player.");
window.location.href="http://www.macromedia.com/go/getflashplayer";
}else{
if(msg=="Download.Failed"){
alert("There was an error downloading the Flash Player update. "+"Please try again later, or visit macromedia.com to download "+"the latest version of the Flash plugin.");
}
}
}
}};
dojo.flash.info=new dojo.flash.Info();
dojo.provide("dojo.storage.browser");
dojo.provide("dojo.storage.browser.FlashStorageProvider");
dojo.require("dojo.storage");
dojo.require("dojo.flash");
dojo.require("dojo.json");
dojo.require("dojo.uri.*");
dojo.storage.browser.FlashStorageProvider=function(){
};
dojo.inherits(dojo.storage.browser.FlashStorageProvider,dojo.storage);
dojo.lang.extend(dojo.storage.browser.FlashStorageProvider,{namespace:"default",initialized:false,_available:null,_statusHandler:null,initialize:function(){
var _6bb=function(){
dojo.storage._flashLoaded();
};
dojo.flash.addLoadedListener(_6bb);
var _6bc=dojo.uri.dojoUri("Storage_version6.swf").toString();
var _6bd=dojo.uri.dojoUri("Storage_version8.swf").toString();
dojo.flash.setSwf({flash6:_6bc,flash8:_6bd,visible:false});
},isAvailable:function(){
if(djConfig["disableFlashStorage"]==true){
this._available=false;
}
return this._available;
},setNamespace:function(_6be){
this.namespace=_6be;
},put:function(key,_6c0,_6c1){
if(this.isValidKey(key)==false){
dojo.raise("Invalid key given: "+key);
}
this._statusHandler=_6c1;
if(dojo.lang.isString(_6c0)){
_6c0="string:"+_6c0;
}else{
_6c0=dojo.json.serialize(_6c0);
}
dojo.flash.comm.put(key,_6c0,this.namespace);
},get:function(key){
if(this.isValidKey(key)==false){
dojo.raise("Invalid key given: "+key);
}
var _6c3=dojo.flash.comm.get(key,this.namespace);
if(_6c3==""){
return null;
}
if(!dojo.lang.isUndefined(_6c3)&&_6c3!=null&&/^string:/.test(_6c3)){
_6c3=_6c3.substring("string:".length);
}else{
_6c3=dojo.json.evalJson(_6c3);
}
return _6c3;
},getKeys:function(){
var _6c4=dojo.flash.comm.getKeys(this.namespace);
if(_6c4==""){
return new Array();
}
_6c4=_6c4.split(",");
return _6c4;
},clear:function(){
dojo.flash.comm.clear(this.namespace);
},remove:function(key){
},isPermanent:function(){
return true;
},getMaximumSize:function(){
return dojo.storage.SIZE_NO_LIMIT;
},hasSettingsUI:function(){
return true;
},showSettingsUI:function(){
dojo.flash.comm.showSettings();
dojo.flash.obj.setVisible(true);
dojo.flash.obj.center();
},hideSettingsUI:function(){
dojo.flash.obj.setVisible(false);
if(dojo.storage.onHideSettingsUI!=null&&!dojo.lang.isUndefined(dojo.storage.onHideSettingsUI)){
dojo.storage.onHideSettingsUI.call(null);
}
},getType:function(){
return "dojo.storage.FlashStorageProvider";
},_flashLoaded:function(){
this.initialized=true;
dojo.storage.manager.loaded();
},_onStatus:function(_6c6,key){
if(_6c6==dojo.storage.PENDING){
dojo.flash.obj.center();
dojo.flash.obj.setVisible(true);
}else{
dojo.flash.obj.setVisible(false);
}
if(!dojo.lang.isUndefined(dojo.storage._statusHandler)&&dojo.storage._statusHandler!=null){
dojo.storage._statusHandler.call(null,_6c6,key);
}
}});
dojo.storage.manager.register("dojo.storage.browser.FlashStorageProvider",new dojo.storage.browser.FlashStorageProvider());
dojo.storage.manager.initialize();
dojo.kwCompoundRequire({common:["dojo.storage"],browser:["dojo.storage.browser"],dashboard:["dojo.storage.dashboard"]});
dojo.provide("dojo.storage.*");
dojo.provide("dojo.undo.Manager");
dojo.require("dojo.lang");
dojo.undo.Manager=function(_6c8){
this.clear();
this._parent=_6c8;
};
dojo.lang.extend(dojo.undo.Manager,{_parent:null,_undoStack:null,_redoStack:null,_currentManager:null,canUndo:false,canRedo:false,isUndoing:false,isRedoing:false,onUndo:function(_6c9,item){
},onRedo:function(_6cb,item){
},onUndoAny:function(_6cd,item){
},onRedoAny:function(_6cf,item){
},_updateStatus:function(){
this.canUndo=this._undoStack.length>0;
this.canRedo=this._redoStack.length>0;
},clear:function(){
this._undoStack=[];
this._redoStack=[];
this._currentManager=this;
this.isUndoing=false;
this.isRedoing=false;
this._updateStatus();
},undo:function(){
if(!this.canUndo){
return false;
}
this.endAllTransactions();
this.isUndoing=true;
var top=this._undoStack.pop();
if(top instanceof this.constructor){
top.undoAll();
}else{
top.undo();
}
if(top.redo){
this._redoStack.push(top);
}
this.isUndoing=false;
this._updateStatus();
this.onUndo(this,top);
if(!(top instanceof this.constructor)){
this.getTop().onUndoAny(this,top);
}
return true;
},redo:function(){
if(!this.canRedo){
return false;
}
this.isRedoing=true;
var top=this._redoStack.pop();
if(top instanceof this.constructor){
top.redoAll();
}else{
top.redo();
}
this._undoStack.push(top);
this.isRedoing=false;
this._updateStatus();
this.onRedo(this,top);
if(!(top instanceof this.constructor)){
this.getTop().onRedoAny(this,top);
}
return true;
},undoAll:function(){
while(this._undoStack.length>0){
this.undo();
}
},redoAll:function(){
while(this._redoStack.length>0){
this.redo();
}
},push:function(undo,redo,_6d5){
if(!undo){
return;
}
if(this._currentManager==this){
this._undoStack.push({undo:undo,redo:redo,description:_6d5});
}else{
this._currentManager.push.apply(this._currentManager,arguments);
}
this._redoStack=[];
this._updateStatus();
},concat:function(_6d6){
if(!_6d6){
return;
}
if(this._currentManager==this){
for(var x=0;x<_6d6._undoStack.length;x++){
this._undoStack.push(_6d6._undoStack[x]);
}
this._updateStatus();
}else{
this._currentManager.concat.apply(this._currentManager,arguments);
}
},beginTransaction:function(_6d8){
if(this._currentManager==this){
var mgr=new dojo.undo.Manager(this);
mgr.description=_6d8?_6d8:"";
this._undoStack.push(mgr);
this._currentManager=mgr;
return mgr;
}else{
this._currentManager=this._currentManager.beginTransaction.apply(this._currentManager,arguments);
}
},endTransaction:function(_6da){
if(this._currentManager==this){
if(this._parent){
this._parent._currentManager=this._parent;
if(this._undoStack.length==0||_6da){
var idx=dojo.lang.find(this._parent._undoStack,this);
if(idx>=0){
this._parent._undoStack.splice(idx,1);
if(_6da){
for(var x=0;x<this._undoStack.length;x++){
this._parent._undoStack.splice(idx++,0,this._undoStack[x]);
}
this._updateStatus();
}
}
}
return this._parent;
}
}else{
this._currentManager=this._currentManager.endTransaction.apply(this._currentManager,arguments);
}
},endAllTransactions:function(){
while(this._currentManager!=this){
this.endTransaction();
}
},getTop:function(){
if(this._parent){
return this._parent.getTop();
}else{
return this;
}
}});
dojo.require("dojo.undo.Manager");
dojo.provide("dojo.undo.*");
dojo.provide("dojo.crypto");
dojo.crypto.cipherModes={ECB:0,CBC:1,PCBC:2,CFB:3,OFB:4,CTR:5};
dojo.crypto.outputTypes={Base64:0,Hex:1,String:2,Raw:3};
dojo.require("dojo.crypto");
dojo.provide("dojo.crypto.MD5");
dojo.crypto.MD5=new function(){
var _6dd=8;
var mask=(1<<_6dd)-1;
function toWord(s){
var wa=[];
for(var i=0;i<s.length*_6dd;i+=_6dd){
wa[i>>5]|=(s.charCodeAt(i/_6dd)&mask)<<(i%32);
}
return wa;
}
function toString(wa){
var s=[];
for(var i=0;i<wa.length*32;i+=_6dd){
s.push(String.fromCharCode((wa[i>>5]>>>(i%32))&mask));
}
return s.join("");
}
function toHex(wa){
var h="0123456789abcdef";
var s=[];
for(var i=0;i<wa.length*4;i++){
s.push(h.charAt((wa[i>>2]>>((i%4)*8+4))&15)+h.charAt((wa[i>>2]>>((i%4)*8))&15));
}
return s.join("");
}
function toBase64(wa){
var p="=";
var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var s=[];
for(var i=0;i<wa.length*4;i+=3){
var t=(((wa[i>>2]>>8*(i%4))&255)<<16)|(((wa[i+1>>2]>>8*((i+1)%4))&255)<<8)|((wa[i+2>>2]>>8*((i+2)%4))&255);
for(var j=0;j<4;j++){
if(i*8+j*6>wa.length*32){
s.push(p);
}else{
s.push(tab.charAt((t>>6*(3-j))&63));
}
}
}
return s.join("");
}
function add(x,y){
var l=(x&65535)+(y&65535);
var m=(x>>16)+(y>>16)+(l>>16);
return (m<<16)|(l&65535);
}
function R(n,c){
return (n<<c)|(n>>>(32-c));
}
function C(q,a,b,x,s,t){
return add(R(add(add(a,q),add(x,t)),s),b);
}
function FF(a,b,c,d,x,s,t){
return C((b&c)|((~b)&d),a,b,x,s,t);
}
function GG(a,b,c,d,x,s,t){
return C((b&d)|(c&(~d)),a,b,x,s,t);
}
function HH(a,b,c,d,x,s,t){
return C(b^c^d,a,b,x,s,t);
}
function II(a,b,c,d,x,s,t){
return C(c^(b|(~d)),a,b,x,s,t);
}
function core(x,len){
x[len>>5]|=128<<((len)%32);
x[(((len+64)>>>9)<<4)+14]=len;
var a=1732584193;
var b=-271733879;
var c=-1732584194;
var d=271733878;
for(var i=0;i<x.length;i+=16){
var olda=a;
var oldb=b;
var oldc=c;
var oldd=d;
a=FF(a,b,c,d,x[i+0],7,-680876936);
d=FF(d,a,b,c,x[i+1],12,-389564586);
c=FF(c,d,a,b,x[i+2],17,606105819);
b=FF(b,c,d,a,x[i+3],22,-1044525330);
a=FF(a,b,c,d,x[i+4],7,-176418897);
d=FF(d,a,b,c,x[i+5],12,1200080426);
c=FF(c,d,a,b,x[i+6],17,-1473231341);
b=FF(b,c,d,a,x[i+7],22,-45705983);
a=FF(a,b,c,d,x[i+8],7,1770035416);
d=FF(d,a,b,c,x[i+9],12,-1958414417);
c=FF(c,d,a,b,x[i+10],17,-42063);
b=FF(b,c,d,a,x[i+11],22,-1990404162);
a=FF(a,b,c,d,x[i+12],7,1804603682);
d=FF(d,a,b,c,x[i+13],12,-40341101);
c=FF(c,d,a,b,x[i+14],17,-1502002290);
b=FF(b,c,d,a,x[i+15],22,1236535329);
a=GG(a,b,c,d,x[i+1],5,-165796510);
d=GG(d,a,b,c,x[i+6],9,-1069501632);
c=GG(c,d,a,b,x[i+11],14,643717713);
b=GG(b,c,d,a,x[i+0],20,-373897302);
a=GG(a,b,c,d,x[i+5],5,-701558691);
d=GG(d,a,b,c,x[i+10],9,38016083);
c=GG(c,d,a,b,x[i+15],14,-660478335);
b=GG(b,c,d,a,x[i+4],20,-405537848);
a=GG(a,b,c,d,x[i+9],5,568446438);
d=GG(d,a,b,c,x[i+14],9,-1019803690);
c=GG(c,d,a,b,x[i+3],14,-187363961);
b=GG(b,c,d,a,x[i+8],20,1163531501);
a=GG(a,b,c,d,x[i+13],5,-1444681467);
d=GG(d,a,b,c,x[i+2],9,-51403784);
c=GG(c,d,a,b,x[i+7],14,1735328473);
b=GG(b,c,d,a,x[i+12],20,-1926607734);
a=HH(a,b,c,d,x[i+5],4,-378558);
d=HH(d,a,b,c,x[i+8],11,-2022574463);
c=HH(c,d,a,b,x[i+11],16,1839030562);
b=HH(b,c,d,a,x[i+14],23,-35309556);
a=HH(a,b,c,d,x[i+1],4,-1530992060);
d=HH(d,a,b,c,x[i+4],11,1272893353);
c=HH(c,d,a,b,x[i+7],16,-155497632);
b=HH(b,c,d,a,x[i+10],23,-1094730640);
a=HH(a,b,c,d,x[i+13],4,681279174);
d=HH(d,a,b,c,x[i+0],11,-358537222);
c=HH(c,d,a,b,x[i+3],16,-722521979);
b=HH(b,c,d,a,x[i+6],23,76029189);
a=HH(a,b,c,d,x[i+9],4,-640364487);
d=HH(d,a,b,c,x[i+12],11,-421815835);
c=HH(c,d,a,b,x[i+15],16,530742520);
b=HH(b,c,d,a,x[i+2],23,-995338651);
a=II(a,b,c,d,x[i+0],6,-198630844);
d=II(d,a,b,c,x[i+7],10,1126891415);
c=II(c,d,a,b,x[i+14],15,-1416354905);
b=II(b,c,d,a,x[i+5],21,-57434055);
a=II(a,b,c,d,x[i+12],6,1700485571);
d=II(d,a,b,c,x[i+3],10,-1894986606);
c=II(c,d,a,b,x[i+10],15,-1051523);
b=II(b,c,d,a,x[i+1],21,-2054922799);
a=II(a,b,c,d,x[i+8],6,1873313359);
d=II(d,a,b,c,x[i+15],10,-30611744);
c=II(c,d,a,b,x[i+6],15,-1560198380);
b=II(b,c,d,a,x[i+13],21,1309151649);
a=II(a,b,c,d,x[i+4],6,-145523070);
d=II(d,a,b,c,x[i+11],10,-1120210379);
c=II(c,d,a,b,x[i+2],15,718787259);
b=II(b,c,d,a,x[i+9],21,-343485551);
a=add(a,olda);
b=add(b,oldb);
c=add(c,oldc);
d=add(d,oldd);
}
return [a,b,c,d];
}
function hmac(data,key){
var wa=toWord(key);
if(wa.length>16){
wa=core(wa,key.length*_6dd);
}
var l=[],r=[];
for(var i=0;i<16;i++){
l[i]=wa[i]^909522486;
r[i]=wa[i]^1549556828;
}
var h=core(l.concat(toWord(data)),512+data.length*_6dd);
return core(r.concat(h),640);
}
this.compute=function(data,_72a){
var out=_72a||dojo.crypto.outputTypes.Base64;
switch(out){
case dojo.crypto.outputTypes.Hex:
return toHex(core(toWord(data),data.length*_6dd));
case dojo.crypto.outputTypes.String:
return toString(core(toWord(data),data.length*_6dd));
default:
return toBase64(core(toWord(data),data.length*_6dd));
}
};
this.getHMAC=function(data,key,_72e){
var out=_72e||dojo.crypto.outputTypes.Base64;
switch(out){
case dojo.crypto.outputTypes.Hex:
return toHex(hmac(data,key));
case dojo.crypto.outputTypes.String:
return toString(hmac(data,key));
default:
return toBase64(hmac(data,key));
}
};
}();
dojo.kwCompoundRequire({common:["dojo.crypto","dojo.crypto.MD5"]});
dojo.provide("dojo.crypto.*");
dojo.provide("dojo.collections.Collections");
dojo.collections={Collections:true};
dojo.collections.DictionaryEntry=function(k,v){
this.key=k;
this.value=v;
this.valueOf=function(){
return this.value;
};
this.toString=function(){
return String(this.value);
};
};
dojo.collections.Iterator=function(arr){
var a=arr;
var _734=0;
this.element=a[_734]||null;
this.atEnd=function(){
return (_734>=a.length);
};
this.get=function(){
if(this.atEnd()){
return null;
}
this.element=a[_734++];
return this.element;
};
this.map=function(fn,_736){
var s=_736||dj_global;
if(Array.map){
return Array.map(a,fn,s);
}else{
var arr=[];
for(var i=0;i<a.length;i++){
arr.push(fn.call(s,a[i]));
}
return arr;
}
};
this.reset=function(){
_734=0;
this.element=a[_734];
};
};
dojo.collections.DictionaryIterator=function(obj){
var a=[];
for(var p in obj){
a.push(obj[p]);
}
var _73d=0;
this.element=a[_73d]||null;
this.atEnd=function(){
return (_73d>=a.length);
};
this.get=function(){
if(this.atEnd()){
return null;
}
this.element=a[_73d++];
return this.element;
};
this.map=function(fn,_73f){
var s=_73f||dj_global;
if(Array.map){
return Array.map(a,fn,s);
}else{
var arr=[];
for(var i=0;i<a.length;i++){
arr.push(fn.call(s,a[i]));
}
return arr;
}
};
this.reset=function(){
_73d=0;
this.element=a[_73d];
};
};
dojo.provide("dojo.collections.ArrayList");
dojo.require("dojo.collections.Collections");
dojo.collections.ArrayList=function(arr){
var _744=[];
if(arr){
_744=_744.concat(arr);
}
this.count=_744.length;
this.add=function(obj){
_744.push(obj);
this.count=_744.length;
};
this.addRange=function(a){
if(a.getIterator){
var e=a.getIterator();
while(!e.atEnd()){
this.add(e.get());
}
this.count=_744.length;
}else{
for(var i=0;i<a.length;i++){
_744.push(a[i]);
}
this.count=_744.length;
}
};
this.clear=function(){
_744.splice(0,_744.length);
this.count=0;
};
this.clone=function(){
return new dojo.collections.ArrayList(_744);
};
this.contains=function(obj){
for(var i=0;i<_744.length;i++){
if(_744[i]==obj){
return true;
}
}
return false;
};
this.forEach=function(fn,_74c){
var s=_74c||dj_global;
if(Array.forEach){
Array.forEach(_744,fn,s);
}else{
for(var i=0;i<_744.length;i++){
fn.call(s,_744[i],i,_744);
}
}
};
this.getIterator=function(){
return new dojo.collections.Iterator(_744);
};
this.indexOf=function(obj){
for(var i=0;i<_744.length;i++){
if(_744[i]==obj){
return i;
}
}
return -1;
};
this.insert=function(i,obj){
_744.splice(i,0,obj);
this.count=_744.length;
};
this.item=function(i){
return _744[i];
};
this.remove=function(obj){
var i=this.indexOf(obj);
if(i>=0){
_744.splice(i,1);
}
this.count=_744.length;
};
this.removeAt=function(i){
_744.splice(i,1);
this.count=_744.length;
};
this.reverse=function(){
_744.reverse();
};
this.sort=function(fn){
if(fn){
_744.sort(fn);
}else{
_744.sort();
}
};
this.setByIndex=function(i,obj){
_744[i]=obj;
this.count=_744.length;
};
this.toArray=function(){
return [].concat(_744);
};
this.toString=function(_75a){
return _744.join((_75a||","));
};
};
dojo.provide("dojo.collections.Queue");
dojo.require("dojo.collections.Collections");
dojo.collections.Queue=function(arr){
var q=[];
if(arr){
q=q.concat(arr);
}
this.count=q.length;
this.clear=function(){
q=[];
this.count=q.length;
};
this.clone=function(){
return new dojo.collections.Queue(q);
};
this.contains=function(o){
for(var i=0;i<q.length;i++){
if(q[i]==o){
return true;
}
}
return false;
};
this.copyTo=function(arr,i){
arr.splice(i,0,q);
};
this.dequeue=function(){
var r=q.shift();
this.count=q.length;
return r;
};
this.enqueue=function(o){
this.count=q.push(o);
};
this.forEach=function(fn,_764){
var s=_764||dj_global;
if(Array.forEach){
Array.forEach(q,fn,s);
}else{
for(var i=0;i<items.length;i++){
fn.call(s,q[i],i,q);
}
}
};
this.getIterator=function(){
return new dojo.collections.Iterator(q);
};
this.peek=function(){
return q[0];
};
this.toArray=function(){
return [].concat(q);
};
};
dojo.provide("dojo.collections.Stack");
dojo.require("dojo.collections.Collections");
dojo.collections.Stack=function(arr){
var q=[];
if(arr){
q=q.concat(arr);
}
this.count=q.length;
this.clear=function(){
q=[];
this.count=q.length;
};
this.clone=function(){
return new dojo.collections.Stack(q);
};
this.contains=function(o){
for(var i=0;i<q.length;i++){
if(q[i]==o){
return true;
}
}
return false;
};
this.copyTo=function(arr,i){
arr.splice(i,0,q);
};
this.forEach=function(fn,_76e){
var s=_76e||dj_global;
if(Array.forEach){
Array.forEach(q,fn,s);
}else{
for(var i=0;i<items.length;i++){
fn.call(s,q[i],i,q);
}
}
};
this.getIterator=function(){
return new dojo.collections.Iterator(q);
};
this.peek=function(){
return q[(q.length-1)];
};
this.pop=function(){
var r=q.pop();
this.count=q.length;
return r;
};
this.push=function(o){
this.count=q.push(o);
};
this.toArray=function(){
return [].concat(q);
};
};
dojo.require("dojo.lang");
dojo.provide("dojo.dnd.DragSource");
dojo.provide("dojo.dnd.DropTarget");
dojo.provide("dojo.dnd.DragObject");
dojo.provide("dojo.dnd.DragAndDrop");
dojo.dnd.DragSource=function(){
var dm=dojo.dnd.dragManager;
if(dm["registerDragSource"]){
dm.registerDragSource(this);
}
};
dojo.lang.extend(dojo.dnd.DragSource,{type:"",onDragEnd:function(){
},onDragStart:function(){
},unregister:function(){
dojo.dnd.dragManager.unregisterDragSource(this);
},reregister:function(){
dojo.dnd.dragManager.registerDragSource(this);
}});
dojo.dnd.DragObject=function(){
var dm=dojo.dnd.dragManager;
if(dm["registerDragObject"]){
dm.registerDragObject(this);
}
};
dojo.lang.extend(dojo.dnd.DragObject,{type:"",onDragStart:function(){
},onDragMove:function(){
},onDragOver:function(){
},onDragOut:function(){
},onDragEnd:function(){
},onDragLeave:this.onDragOut,onDragEnter:this.onDragOver,ondragout:this.onDragOut,ondragover:this.onDragOver});
dojo.dnd.DropTarget=function(){
if(this.constructor==dojo.dnd.DropTarget){
return;
}
this.acceptedTypes=[];
dojo.dnd.dragManager.registerDropTarget(this);
};
dojo.lang.extend(dojo.dnd.DropTarget,{acceptsType:function(type){
if(!dojo.lang.inArray(this.acceptedTypes,"*")){
if(!dojo.lang.inArray(this.acceptedTypes,type)){
return false;
}
}
return true;
},accepts:function(_776){
if(!dojo.lang.inArray(this.acceptedTypes,"*")){
for(var i=0;i<_776.length;i++){
if(!dojo.lang.inArray(this.acceptedTypes,_776[i].type)){
return false;
}
}
}
return true;
},onDragOver:function(){
},onDragOut:function(){
},onDragMove:function(){
},onDropStart:function(){
},onDrop:function(){
},onDropEnd:function(){
}});
dojo.dnd.DragEvent=function(){
this.dragSource=null;
this.dragObject=null;
this.target=null;
this.eventStatus="success";
};
dojo.dnd.DragManager=function(){
};
dojo.lang.extend(dojo.dnd.DragManager,{selectedSources:[],dragObjects:[],dragSources:[],registerDragSource:function(){
},dropTargets:[],registerDropTarget:function(){
},lastDragTarget:null,currentDragTarget:null,onKeyDown:function(){
},onMouseOut:function(){
},onMouseMove:function(){
},onMouseUp:function(){
}});
dojo.provide("dojo.dnd.HtmlDragManager");
dojo.require("dojo.dnd.DragAndDrop");
dojo.require("dojo.event.*");
dojo.require("dojo.lang.array");
dojo.require("dojo.html");
dojo.require("dojo.style");
dojo.dnd.HtmlDragManager=function(){
};
dojo.inherits(dojo.dnd.HtmlDragManager,dojo.dnd.DragManager);
dojo.lang.extend(dojo.dnd.HtmlDragManager,{disabled:false,nestedTargets:false,mouseDownTimer:null,dsCounter:0,dsPrefix:"dojoDragSource",dropTargetDimensions:[],currentDropTarget:null,previousDropTarget:null,_dragTriggered:false,selectedSources:[],dragObjects:[],currentX:null,currentY:null,lastX:null,lastY:null,mouseDownX:null,mouseDownY:null,threshold:7,dropAcceptable:false,cancelEvent:function(e){
e.stopPropagation();
e.preventDefault();
},registerDragSource:function(ds){
if(ds["domNode"]){
var dp=this.dsPrefix;
var _77b=dp+"Idx_"+(this.dsCounter++);
ds.dragSourceId=_77b;
this.dragSources[_77b]=ds;
ds.domNode.setAttribute(dp,_77b);
if(dojo.render.html.ie){
dojo.event.connect(ds.domNode,"ondragstart",this.cancelEvent);
}
}
},unregisterDragSource:function(ds){
if(ds["domNode"]){
var dp=this.dsPrefix;
var _77e=ds.dragSourceId;
delete ds.dragSourceId;
delete this.dragSources[_77e];
ds.domNode.setAttribute(dp,null);
}
if(dojo.render.html.ie){
dojo.event.disconnect(ds.domNode,"ondragstart",this.cancelEvent);
}
},registerDropTarget:function(dt){
this.dropTargets.push(dt);
},unregisterDropTarget:function(dt){
var _781=dojo.lang.find(this.dropTargets,dt,true);
if(_781>=0){
this.dropTargets.splice(_781,1);
}
},getDragSource:function(e){
var tn=e.target;
if(tn===document.body){
return;
}
var ta=dojo.html.getAttribute(tn,this.dsPrefix);
while((!ta)&&(tn)){
tn=tn.parentNode;
if((!tn)||(tn===document.body)){
return;
}
ta=dojo.html.getAttribute(tn,this.dsPrefix);
}
return this.dragSources[ta];
},onKeyDown:function(e){
},onMouseDown:function(e){
if(this.disabled){
return;
}
if(dojo.render.html.ie){
if(e.button!=1){
return;
}
}else{
if(e.which!=1){
return;
}
}
var _787=e.target.nodeType==dojo.dom.TEXT_NODE?e.target.parentNode:e.target;
if(dojo.html.isTag(_787,"button","textarea","input","select","option")){
return;
}
var ds=this.getDragSource(e);
if(!ds){
return;
}
if(!dojo.lang.inArray(this.selectedSources,ds)){
this.selectedSources.push(ds);
}
this.mouseDownX=e.pageX;
this.mouseDownY=e.pageY;
e.preventDefault();
dojo.event.connect(document,"onmousemove",this,"onMouseMove");
},onMouseUp:function(e,_78a){
if(this.selectedSources.length==0){
return;
}
this.mouseDownX=null;
this.mouseDownY=null;
this._dragTriggered=false;
e.dragSource=this.dragSource;
if((!e.shiftKey)&&(!e.ctrlKey)){
if(this.currentDropTarget){
this.currentDropTarget.onDropStart();
}
dojo.lang.forEach(this.dragObjects,function(_78b){
var ret=null;
if(!_78b){
return;
}
if(this.currentDropTarget){
e.dragObject=_78b;
var ce=this.currentDropTarget.domNode.childNodes;
if(ce.length>0){
e.dropTarget=ce[0];
while(e.dropTarget==_78b.domNode){
e.dropTarget=e.dropTarget.nextSibling;
}
}else{
e.dropTarget=this.currentDropTarget.domNode;
}
if(this.dropAcceptable){
ret=this.currentDropTarget.onDrop(e);
}else{
this.currentDropTarget.onDragOut(e);
}
}
e.dragStatus=this.dropAcceptable&&ret?"dropSuccess":"dropFailure";
_78b.dragSource.onDragEnd(e);
_78b.onDragEnd(e);
},this);
this.selectedSources=[];
this.dragObjects=[];
this.dragSource=null;
if(this.currentDropTarget){
this.currentDropTarget.onDropEnd();
}
}
dojo.event.disconnect(document,"onmousemove",this,"onMouseMove");
this.currentDropTarget=null;
},onScroll:function(){
for(var i=0;i<this.dragObjects.length;i++){
if(this.dragObjects[i].updateDragOffset){
this.dragObjects[i].updateDragOffset();
}
}
this.cacheTargetLocations();
},_dragStartDistance:function(x,y){
if((!this.mouseDownX)||(!this.mouseDownX)){
return;
}
var dx=Math.abs(x-this.mouseDownX);
var dx2=dx*dx;
var dy=Math.abs(y-this.mouseDownY);
var dy2=dy*dy;
return parseInt(Math.sqrt(dx2+dy2),10);
},cacheTargetLocations:function(){
this.dropTargetDimensions=[];
dojo.lang.forEach(this.dropTargets,function(_795){
var tn=_795.domNode;
if(!tn){
return;
}
var ttx=dojo.style.getAbsoluteX(tn,true);
var tty=dojo.style.getAbsoluteY(tn,true);
this.dropTargetDimensions.push([[ttx,tty],[ttx+dojo.style.getInnerWidth(tn),tty+dojo.style.getInnerHeight(tn)],_795]);
},this);
},onMouseMove:function(e){
if((dojo.render.html.ie)&&(e.button!=1)){
this.currentDropTarget=null;
this.onMouseUp(e,true);
return;
}
if((this.selectedSources.length)&&(!this.dragObjects.length)){
var dx;
var dy;
if(!this._dragTriggered){
this._dragTriggered=(this._dragStartDistance(e.pageX,e.pageY)>this.threshold);
if(!this._dragTriggered){
return;
}
dx=e.pageX-this.mouseDownX;
dy=e.pageY-this.mouseDownY;
}
if(this.selectedSources.length==1){
this.dragSource=this.selectedSources[0];
}
dojo.lang.forEach(this.selectedSources,function(_79c){
if(!_79c){
return;
}
var tdo=_79c.onDragStart(e);
if(tdo){
tdo.onDragStart(e);
tdo.dragOffset.top+=dy;
tdo.dragOffset.left+=dx;
tdo.dragSource=_79c;
this.dragObjects.push(tdo);
}
},this);
this.previousDropTarget=null;
this.cacheTargetLocations();
}
dojo.lang.forEach(this.dragObjects,function(_79e){
if(_79e){
_79e.onDragMove(e);
}
});
if(this.currentDropTarget){
var c=dojo.style.toCoordinateArray(this.currentDropTarget.domNode,true);
var dtp=[[c[0],c[1]],[c[0]+c[2],c[1]+c[3]]];
}
if((!this.nestedTargets)&&(dtp)&&(this.isInsideBox(e,dtp))){
if(this.dropAcceptable){
this.currentDropTarget.onDragMove(e,this.dragObjects);
}
}else{
var _7a1=this.findBestTarget(e);
if(_7a1.target===null){
if(this.currentDropTarget){
this.currentDropTarget.onDragOut(e);
this.previousDropTarget=this.currentDropTarget;
this.currentDropTarget=null;
}
this.dropAcceptable=false;
return;
}
if(this.currentDropTarget!==_7a1.target){
if(this.currentDropTarget){
this.previousDropTarget=this.currentDropTarget;
this.currentDropTarget.onDragOut(e);
}
this.currentDropTarget=_7a1.target;
e.dragObjects=this.dragObjects;
this.dropAcceptable=this.currentDropTarget.onDragOver(e);
}else{
if(this.dropAcceptable){
this.currentDropTarget.onDragMove(e,this.dragObjects);
}
}
}
},findBestTarget:function(e){
var _7a3=this;
var _7a4=new Object();
_7a4.target=null;
_7a4.points=null;
dojo.lang.every(this.dropTargetDimensions,function(_7a5){
if(!_7a3.isInsideBox(e,_7a5)){
return true;
}
_7a4.target=_7a5[2];
_7a4.points=_7a5;
return Boolean(_7a3.nestedTargets);
});
return _7a4;
},isInsideBox:function(e,_7a7){
if((e.pageX>_7a7[0][0])&&(e.pageX<_7a7[1][0])&&(e.pageY>_7a7[0][1])&&(e.pageY<_7a7[1][1])){
return true;
}
return false;
},onMouseOver:function(e){
},onMouseOut:function(e){
}});
dojo.dnd.dragManager=new dojo.dnd.HtmlDragManager();
(function(){
var d=document;
var dm=dojo.dnd.dragManager;
dojo.event.connect(d,"onkeydown",dm,"onKeyDown");
dojo.event.connect(d,"onmouseover",dm,"onMouseOver");
dojo.event.connect(d,"onmouseout",dm,"onMouseOut");
dojo.event.connect(d,"onmousedown",dm,"onMouseDown");
dojo.event.connect(d,"onmouseup",dm,"onMouseUp");
dojo.event.connect(window,"onscroll",dm,"onScroll");
})();
dojo.require("dojo.html");
dojo.provide("dojo.html.extras");
dojo.require("dojo.string.extras");
dojo.html.gravity=function(node,e){
node=dojo.byId(node);
var _7ae=dojo.html.getCursorPosition(e);
with(dojo.html){
var _7af=getAbsoluteX(node,true)+(getInnerWidth(node)/2);
var _7b0=getAbsoluteY(node,true)+(getInnerHeight(node)/2);
}
with(dojo.html.gravity){
return ((_7ae.x<_7af?WEST:EAST)|(_7ae.y<_7b0?NORTH:SOUTH));
}
};
dojo.html.gravity.NORTH=1;
dojo.html.gravity.SOUTH=1<<1;
dojo.html.gravity.EAST=1<<2;
dojo.html.gravity.WEST=1<<3;
dojo.html.renderedTextContent=function(node){
node=dojo.byId(node);
var _7b2="";
if(node==null){
return _7b2;
}
for(var i=0;i<node.childNodes.length;i++){
switch(node.childNodes[i].nodeType){
case 1:
case 5:
var _7b4="unknown";
try{
_7b4=dojo.style.getStyle(node.childNodes[i],"display");
}
catch(E){
}
switch(_7b4){
case "block":
case "list-item":
case "run-in":
case "table":
case "table-row-group":
case "table-header-group":
case "table-footer-group":
case "table-row":
case "table-column-group":
case "table-column":
case "table-cell":
case "table-caption":
_7b2+="\n";
_7b2+=dojo.html.renderedTextContent(node.childNodes[i]);
_7b2+="\n";
break;
case "none":
break;
default:
if(node.childNodes[i].tagName&&node.childNodes[i].tagName.toLowerCase()=="br"){
_7b2+="\n";
}else{
_7b2+=dojo.html.renderedTextContent(node.childNodes[i]);
}
break;
}
break;
case 3:
case 2:
case 4:
var text=node.childNodes[i].nodeValue;
var _7b6="unknown";
try{
_7b6=dojo.style.getStyle(node,"text-transform");
}
catch(E){
}
switch(_7b6){
case "capitalize":
text=dojo.string.capitalize(text);
break;
case "uppercase":
text=text.toUpperCase();
break;
case "lowercase":
text=text.toLowerCase();
break;
default:
break;
}
switch(_7b6){
case "nowrap":
break;
case "pre-wrap":
break;
case "pre-line":
break;
case "pre":
break;
default:
text=text.replace(/\s+/," ");
if(/\s$/.test(_7b2)){
text.replace(/^\s/,"");
}
break;
}
_7b2+=text;
break;
default:
break;
}
}
return _7b2;
};
dojo.html.createNodesFromText=function(txt,trim){
if(trim){
txt=dojo.string.trim(txt);
}
var tn=document.createElement("div");
tn.style.visibility="hidden";
document.body.appendChild(tn);
var _7ba="none";
if((/^<t[dh][\s\r\n>]/i).test(dojo.string.trimStart(txt))){
txt="<table><tbody><tr>"+txt+"</tr></tbody></table>";
_7ba="cell";
}else{
if((/^<tr[\s\r\n>]/i).test(dojo.string.trimStart(txt))){
txt="<table><tbody>"+txt+"</tbody></table>";
_7ba="row";
}else{
if((/^<(thead|tbody|tfoot)[\s\r\n>]/i).test(dojo.string.trimStart(txt))){
txt="<table>"+txt+"</table>";
_7ba="section";
}
}
}
tn.innerHTML=txt;
if(tn["normalize"]){
tn.normalize();
}
var _7bb=null;
switch(_7ba){
case "cell":
_7bb=tn.getElementsByTagName("tr")[0];
break;
case "row":
_7bb=tn.getElementsByTagName("tbody")[0];
break;
case "section":
_7bb=tn.getElementsByTagName("table")[0];
break;
default:
_7bb=tn;
break;
}
var _7bc=[];
for(var x=0;x<_7bb.childNodes.length;x++){
_7bc.push(_7bb.childNodes[x].cloneNode(true));
}
tn.style.display="none";
document.body.removeChild(tn);
return _7bc;
};
dojo.html.placeOnScreen=function(node,_7bf,_7c0,_7c1,_7c2){
if(dojo.lang.isArray(_7bf)){
_7c2=_7c1;
_7c1=_7c0;
_7c0=_7bf[1];
_7bf=_7bf[0];
}
if(!isNaN(_7c1)){
_7c1=[Number(_7c1),Number(_7c1)];
}else{
if(!dojo.lang.isArray(_7c1)){
_7c1=[0,0];
}
}
var _7c3=dojo.html.getScrollOffset();
var view=dojo.html.getViewportSize();
node=dojo.byId(node);
var w=node.offsetWidth+_7c1[0];
var h=node.offsetHeight+_7c1[1];
if(_7c2){
_7bf-=_7c3.x;
_7c0-=_7c3.y;
}
var x=_7bf+w;
if(x>view.w){
x=view.w-w;
}else{
x=_7bf;
}
x=Math.max(_7c1[0],x)+_7c3.x;
var y=_7c0+h;
if(y>view.h){
y=view.h-h;
}else{
y=_7c0;
}
y=Math.max(_7c1[1],y)+_7c3.y;
node.style.left=x+"px";
node.style.top=y+"px";
var ret=[x,y];
ret.x=x;
ret.y=y;
return ret;
};
dojo.html.placeOnScreenPoint=function(node,_7cb,_7cc,_7cd,_7ce){
if(dojo.lang.isArray(_7cb)){
_7ce=_7cd;
_7cd=_7cc;
_7cc=_7cb[1];
_7cb=_7cb[0];
}
if(!isNaN(_7cd)){
_7cd=[Number(_7cd),Number(_7cd)];
}else{
if(!dojo.lang.isArray(_7cd)){
_7cd=[0,0];
}
}
var _7cf=dojo.html.getScrollOffset();
var view=dojo.html.getViewportSize();
node=dojo.byId(node);
var _7d1=node.style.display;
node.style.display="";
var w=dojo.style.getInnerWidth(node);
var h=dojo.style.getInnerHeight(node);
node.style.display=_7d1;
if(_7ce){
_7cb-=_7cf.x;
_7cc-=_7cf.y;
}
var x=-1,y=-1;
if((_7cb+_7cd[0])+w<=view.w&&(_7cc+_7cd[1])+h<=view.h){
x=(_7cb+_7cd[0]);
y=(_7cc+_7cd[1]);
}
if((x<0||y<0)&&(_7cb-_7cd[0])<=view.w&&(_7cc+_7cd[1])+h<=view.h){
x=(_7cb-_7cd[0])-w;
y=(_7cc+_7cd[1]);
}
if((x<0||y<0)&&(_7cb+_7cd[0])+w<=view.w&&(_7cc-_7cd[1])<=view.h){
x=(_7cb+_7cd[0]);
y=(_7cc-_7cd[1])-h;
}
if((x<0||y<0)&&(_7cb-_7cd[0])<=view.w&&(_7cc-_7cd[1])<=view.h){
x=(_7cb-_7cd[0])-w;
y=(_7cc-_7cd[1])-h;
}
if(x<0||y<0||(x+w>view.w)||(y+h>view.h)){
return dojo.html.placeOnScreen(node,_7cb,_7cc,_7cd,_7ce);
}
x+=_7cf.x;
y+=_7cf.y;
node.style.left=x+"px";
node.style.top=y+"px";
var ret=[x,y];
ret.x=x;
ret.y=y;
return ret;
};
dojo.html.BackgroundIframe=function(node){
if(dojo.render.html.ie){
var html="<iframe "+"style='position: absolute; left: 0px; top: 0px; width: 100%; height: 100%;"+"z-index: -1; filter:Alpha(Opacity=\"0\");' "+">";
this.iframe=document.createElement(html);
if(node){
node.appendChild(this.iframe);
this.domNode=node;
}else{
document.body.appendChild(this.iframe);
this.iframe.style.display="none";
}
}
};
dojo.lang.extend(dojo.html.BackgroundIframe,{iframe:null,onResized:function(){
if(this.iframe&&this.domNode){
var w=dojo.style.getOuterWidth(this.domNode);
var h=dojo.style.getOuterHeight(this.domNode);
if(w==0||h==0){
dojo.lang.setTimeout(this,this.onResized,50);
return;
}
var s=this.iframe.style;
s.width=w+"px";
s.height=h+"px";
}
},size:function(node){
if(!this.iframe){
return;
}
coords=dojo.style.toCoordinateArray(node,true);
var s=this.iframe.style;
s.width=coords.w+"px";
s.height=coords.h+"px";
s.left=coords.x+"px";
s.top=coords.y+"px";
},setZIndex:function(node){
if(!this.iframe){
return;
}
if(dojo.dom.isNode(node)){
this.iframe.style.zIndex=dojo.html.getStyle(node,"z-index")-1;
}else{
if(!isNaN(node)){
this.iframe.style.zIndex=node;
}
}
},show:function(){
if(!this.iframe){
return;
}
this.iframe.style.display="block";
},hide:function(){
if(!this.ie){
return;
}
var s=this.iframe.style;
s.display="none";
},remove:function(){
dojo.dom.removeNode(this.iframe);
}});
dojo.provide("dojo.dnd.HtmlDragAndDrop");
dojo.provide("dojo.dnd.HtmlDragSource");
dojo.provide("dojo.dnd.HtmlDropTarget");
dojo.provide("dojo.dnd.HtmlDragObject");
dojo.require("dojo.dnd.HtmlDragManager");
dojo.require("dojo.dnd.DragAndDrop");
dojo.require("dojo.dom");
dojo.require("dojo.style");
dojo.require("dojo.html");
dojo.require("dojo.html.extras");
dojo.require("dojo.lang.extras");
dojo.require("dojo.lfx.*");
dojo.dnd.HtmlDragSource=function(node,type){
node=dojo.byId(node);
this.constrainToContainer=false;
if(node){
this.domNode=node;
this.dragObject=node;
dojo.dnd.DragSource.call(this);
this.type=type||this.domNode.nodeName.toLowerCase();
}
};
dojo.inherits(dojo.dnd.HtmlDragSource,dojo.dnd.DragSource);
dojo.lang.extend(dojo.dnd.HtmlDragSource,{dragClass:"",onDragStart:function(){
var _7e1=new dojo.dnd.HtmlDragObject(this.dragObject,this.type);
if(this.dragClass){
_7e1.dragClass=this.dragClass;
}
if(this.constrainToContainer){
_7e1.constrainTo(this.constrainingContainer||this.domNode.parentNode);
}
return _7e1;
},setDragHandle:function(node){
node=dojo.byId(node);
dojo.dnd.dragManager.unregisterDragSource(this);
this.domNode=node;
dojo.dnd.dragManager.registerDragSource(this);
},setDragTarget:function(node){
this.dragObject=node;
},constrainTo:function(_7e4){
this.constrainToContainer=true;
if(_7e4){
this.constrainingContainer=_7e4;
}
}});
dojo.dnd.HtmlDragObject=function(node,type){
this.domNode=dojo.byId(node);
this.type=type;
this.constrainToContainer=false;
this.dragSource=null;
};
dojo.inherits(dojo.dnd.HtmlDragObject,dojo.dnd.DragObject);
dojo.lang.extend(dojo.dnd.HtmlDragObject,{dragClass:"",opacity:0.5,createIframe:true,disableX:false,disableY:false,createDragNode:function(){
var node=this.domNode.cloneNode(true);
if(this.dragClass){
dojo.html.addClass(node,this.dragClass);
}
if(this.opacity<1){
dojo.style.setOpacity(node,this.opacity);
}
if(dojo.render.html.ie&&this.createIframe){
with(node.style){
top="0px";
left="0px";
}
var _7e8=document.createElement("div");
_7e8.appendChild(node);
this.bgIframe=new dojo.html.BackgroundIframe(_7e8);
_7e8.appendChild(this.bgIframe.iframe);
node=_7e8;
}
node.style.zIndex=999;
return node;
},onDragStart:function(e){
dojo.html.clearSelection();
this.scrollOffset=dojo.html.getScrollOffset();
this.dragStartPosition=dojo.style.getAbsolutePosition(this.domNode,true);
this.dragOffset={y:this.dragStartPosition.y-e.pageY,x:this.dragStartPosition.x-e.pageX};
this.dragClone=this.createDragNode();
if((this.domNode.parentNode.nodeName.toLowerCase()=="body")||(dojo.style.getComputedStyle(this.domNode.parentNode,"position")=="static")){
this.parentPosition={y:0,x:0};
}else{
this.parentPosition=dojo.style.getAbsolutePosition(this.domNode.parentNode,true);
}
if(this.constrainToContainer){
this.constraints=this.getConstraints();
}
with(this.dragClone.style){
position="absolute";
top=this.dragOffset.y+e.pageY+"px";
left=this.dragOffset.x+e.pageX+"px";
}
document.body.appendChild(this.dragClone);
},getConstraints:function(){
if(this.constrainingContainer.nodeName.toLowerCase()=="body"){
width=dojo.html.getViewportWidth();
height=dojo.html.getViewportHeight();
padLeft=0;
padTop=0;
}else{
width=dojo.style.getContentWidth(this.constrainingContainer);
height=dojo.style.getContentHeight(this.constrainingContainer);
padLeft=dojo.style.getPixelValue(this.constrainingContainer,"padding-left",true);
padTop=dojo.style.getPixelValue(this.constrainingContainer,"padding-top",true);
}
return {minX:padLeft,minY:padTop,maxX:padLeft+width-dojo.style.getOuterWidth(this.domNode),maxY:padTop+height-dojo.style.getOuterHeight(this.domNode)};
},updateDragOffset:function(){
var _7ea=dojo.html.getScrollOffset();
if(_7ea.y!=this.scrollOffset.y){
var diff=_7ea.y-this.scrollOffset.y;
this.dragOffset.y+=diff;
this.scrollOffset.y=_7ea.y;
}
if(_7ea.x!=this.scrollOffset.x){
var diff=_7ea.x-this.scrollOffset.x;
this.dragOffset.x+=diff;
this.scrollOffset.x=_7ea.x;
}
},onDragMove:function(e){
this.updateDragOffset();
var x=this.dragOffset.x+e.pageX;
var y=this.dragOffset.y+e.pageY;
if(this.constrainToContainer){
if(x<this.constraints.minX){
x=this.constraints.minX;
}
if(y<this.constraints.minY){
y=this.constraints.minY;
}
if(x>this.constraints.maxX){
x=this.constraints.maxX;
}
if(y>this.constraints.maxY){
y=this.constraints.maxY;
}
}
if(!this.disableY){
this.dragClone.style.top=y+"px";
}
if(!this.disableX){
this.dragClone.style.left=x+"px";
}
},onDragEnd:function(e){
switch(e.dragStatus){
case "dropSuccess":
dojo.dom.removeNode(this.dragClone);
this.dragClone=null;
break;
case "dropFailure":
var _7f0=dojo.style.getAbsolutePosition(this.dragClone,true);
var _7f1=[this.dragStartPosition.x+1,this.dragStartPosition.y+1];
var line=new dojo.lfx.Line(_7f0,_7f1);
var anim=new dojo.lfx.Animation(500,line,dojo.lfx.easeOut);
var _7f4=this;
dojo.event.connect(anim,"onAnimate",function(e){
_7f4.dragClone.style.left=e[0]+"px";
_7f4.dragClone.style.top=e[1]+"px";
});
dojo.event.connect(anim,"onEnd",function(e){
dojo.lang.setTimeout(dojo.dom.removeNode,200,_7f4.dragClone);
});
anim.play();
break;
}
dojo.event.connect(this.domNode,"onclick",this,"squelchOnClick");
},squelchOnClick:function(e){
e.preventDefault();
dojo.event.disconnect(this.domNode,"onclick",this,"squelchOnClick");
},constrainTo:function(_7f8){
this.constrainToContainer=true;
if(_7f8){
this.constrainingContainer=_7f8;
}else{
this.constrainingContainer=this.domNode.parentNode;
}
}});
dojo.dnd.HtmlDropTarget=function(node,_7fa){
if(arguments.length==0){
return;
}
this.domNode=dojo.byId(node);
dojo.dnd.DropTarget.call(this);
if(_7fa&&dojo.lang.isString(_7fa)){
_7fa=[_7fa];
}
this.acceptedTypes=_7fa||[];
};
dojo.inherits(dojo.dnd.HtmlDropTarget,dojo.dnd.DropTarget);
dojo.lang.extend(dojo.dnd.HtmlDropTarget,{onDragOver:function(e){
if(!this.accepts(e.dragObjects)){
return false;
}
this.childBoxes=[];
for(var i=0,child;i<this.domNode.childNodes.length;i++){
child=this.domNode.childNodes[i];
if(child.nodeType!=dojo.dom.ELEMENT_NODE){
continue;
}
var pos=dojo.style.getAbsolutePosition(child,true);
var _7fe=dojo.style.getInnerHeight(child);
var _7ff=dojo.style.getInnerWidth(child);
this.childBoxes.push({top:pos.y,bottom:pos.y+_7fe,left:pos.x,right:pos.x+_7ff,node:child});
}
return true;
},_getNodeUnderMouse:function(e){
for(var i=0,child;i<this.childBoxes.length;i++){
with(this.childBoxes[i]){
if(e.pageX>=left&&e.pageX<=right&&e.pageY>=top&&e.pageY<=bottom){
return i;
}
}
}
return -1;
},createDropIndicator:function(){
this.dropIndicator=document.createElement("div");
with(this.dropIndicator.style){
position="absolute";
zIndex=999;
borderTopWidth="1px";
borderTopColor="black";
borderTopStyle="solid";
width=dojo.style.getInnerWidth(this.domNode)+"px";
left=dojo.style.getAbsoluteX(this.domNode,true)+"px";
}
},onDragMove:function(e,_803){
var i=this._getNodeUnderMouse(e);
if(!this.dropIndicator){
this.createDropIndicator();
}
if(i<0){
if(this.childBoxes.length){
var _805=(dojo.html.gravity(this.childBoxes[0].node,e)&dojo.html.gravity.NORTH);
}else{
var _805=true;
}
}else{
var _806=this.childBoxes[i];
var _805=(dojo.html.gravity(_806.node,e)&dojo.html.gravity.NORTH);
}
this.placeIndicator(e,_803,i,_805);
if(!dojo.html.hasParent(this.dropIndicator)){
document.body.appendChild(this.dropIndicator);
}
},placeIndicator:function(e,_808,_809,_80a){
with(this.dropIndicator.style){
if(_809<0){
if(this.childBoxes.length){
top=(_80a?this.childBoxes[0].top:this.childBoxes[this.childBoxes.length-1].bottom)+"px";
}else{
top=dojo.style.getAbsoluteY(this.domNode,true)+"px";
}
}else{
var _80b=this.childBoxes[_809];
top=(_80a?_80b.top:_80b.bottom)+"px";
}
}
},onDragOut:function(e){
if(this.dropIndicator){
dojo.dom.removeNode(this.dropIndicator);
delete this.dropIndicator;
}
},onDrop:function(e){
this.onDragOut(e);
var i=this._getNodeUnderMouse(e);
if(i<0){
if(this.childBoxes.length){
if(dojo.html.gravity(this.childBoxes[0].node,e)&dojo.html.gravity.NORTH){
return this.insert(e,this.childBoxes[0].node,"before");
}else{
return this.insert(e,this.childBoxes[this.childBoxes.length-1].node,"after");
}
}
return this.insert(e,this.domNode,"append");
}
var _80f=this.childBoxes[i];
if(dojo.html.gravity(_80f.node,e)&dojo.html.gravity.NORTH){
return this.insert(e,_80f.node,"before");
}else{
return this.insert(e,_80f.node,"after");
}
},insert:function(e,_811,_812){
var node=e.dragObject.domNode;
if(_812=="before"){
return dojo.html.insertBefore(node,_811);
}else{
if(_812=="after"){
return dojo.html.insertAfter(node,_811);
}else{
if(_812=="append"){
_811.appendChild(node);
return true;
}
}
}
return false;
}});
dojo.kwCompoundRequire({common:["dojo.dnd.DragAndDrop"],browser:["dojo.dnd.HtmlDragAndDrop"],dashboard:["dojo.dnd.HtmlDragAndDrop"]});
dojo.provide("dojo.dnd.*");
dojo.provide("dojo.widget.Manager");
dojo.require("dojo.lang.array");
dojo.require("dojo.lang.func");
dojo.require("dojo.event.*");
dojo.widget.manager=new function(){
this.widgets=[];
this.widgetIds=[];
this.topWidgets={};
var _814={};
var _815=[];
this.getUniqueId=function(_816){
return _816+"_"+(_814[_816]!=undefined?++_814[_816]:_814[_816]=0);
};
this.add=function(_817){
dojo.profile.start("dojo.widget.manager.add");
this.widgets.push(_817);
if(!_817.extraArgs["id"]){
_817.extraArgs["id"]=_817.extraArgs["ID"];
}
if(_817.widgetId==""){
if(_817["id"]){
_817.widgetId=_817["id"];
}else{
if(_817.extraArgs["id"]){
_817.widgetId=_817.extraArgs["id"];
}else{
_817.widgetId=this.getUniqueId(_817.widgetType);
}
}
}
if(this.widgetIds[_817.widgetId]){
dojo.debug("widget ID collision on ID: "+_817.widgetId);
}
this.widgetIds[_817.widgetId]=_817;
dojo.profile.end("dojo.widget.manager.add");
};
this.destroyAll=function(){
for(var x=this.widgets.length-1;x>=0;x--){
try{
this.widgets[x].destroy(true);
delete this.widgets[x];
}
catch(e){
}
}
};
this.remove=function(_819){
var tw=this.widgets[_819].widgetId;
delete this.widgetIds[tw];
this.widgets.splice(_819,1);
};
this.removeById=function(id){
for(var i=0;i<this.widgets.length;i++){
if(this.widgets[i].widgetId==id){
this.remove(i);
break;
}
}
};
this.getWidgetById=function(id){
return this.widgetIds[id];
};
this.getWidgetsByType=function(type){
var lt=type.toLowerCase();
var ret=[];
dojo.lang.forEach(this.widgets,function(x){
if(x.widgetType.toLowerCase()==lt){
ret.push(x);
}
});
return ret;
};
this.getWidgetsOfType=function(id){
dojo.deprecated("getWidgetsOfType is depecrecated, use getWidgetsByType");
return dojo.widget.manager.getWidgetsByType(id);
};
this.getWidgetsByFilter=function(_823,_824){
var ret=[];
dojo.lang.every(this.widgets,function(x){
if(_823(x)){
ret.push(x);
if(_824){
return false;
}
}
return true;
});
return (_824?ret[0]:ret);
};
this.getAllWidgets=function(){
return this.widgets.concat();
};
this.getWidgetByNode=function(node){
var w=this.getAllWidgets();
for(var i=0;i<w.length;i++){
if(w[i].domNode==node){
return w[i];
}
}
return null;
};
this.byId=this.getWidgetById;
this.byType=this.getWidgetsByType;
this.byFilter=this.getWidgetsByFilter;
this.byNode=this.getWidgetByNode;
var _82a={};
var _82b=["dojo.widget"];
for(var i=0;i<_82b.length;i++){
_82b[_82b[i]]=true;
}
this.registerWidgetPackage=function(_82d){
if(!_82b[_82d]){
_82b[_82d]=true;
_82b.push(_82d);
}
};
this.getWidgetPackageList=function(){
return dojo.lang.map(_82b,function(elt){
return (elt!==true?elt:undefined);
});
};
this.getImplementation=function(_82f,_830,_831){
var impl=this.getImplementationName(_82f);
if(impl){
var ret=new impl(_830);
return ret;
}
};
this.getImplementationName=function(_834){
var _835=_834.toLowerCase();
var impl=_82a[_835];
if(impl){
return impl;
}
if(!_815.length){
for(var _837 in dojo.render){
if(dojo.render[_837]["capable"]===true){
var _838=dojo.render[_837].prefixes;
for(var i=0;i<_838.length;i++){
_815.push(_838[i].toLowerCase());
}
}
}
_815.push("");
}
for(var i=0;i<_82b.length;i++){
var _83a=dojo.evalObjPath(_82b[i]);
if(!_83a){
continue;
}
for(var j=0;j<_815.length;j++){
if(!_83a[_815[j]]){
continue;
}
for(var _83c in _83a[_815[j]]){
if(_83c.toLowerCase()!=_835){
continue;
}
_82a[_835]=_83a[_815[j]][_83c];
return _82a[_835];
}
}
for(var j=0;j<_815.length;j++){
for(var _83c in _83a){
if(_83c.toLowerCase()!=(_815[j]+_835)){
continue;
}
_82a[_835]=_83a[_83c];
return _82a[_835];
}
}
}
throw new Error("Could not locate \""+_834+"\" class");
};
this.resizing=false;
this.onWindowResized=function(){
if(this.resizing){
return;
}
try{
this.resizing=true;
for(var id in this.topWidgets){
var _83e=this.topWidgets[id];
if(_83e.onParentResized){
_83e.onParentResized();
}
}
}
catch(e){
}
finally{
this.resizing=false;
}
};
if(typeof window!="undefined"){
dojo.addOnLoad(this,"onWindowResized");
dojo.event.connect(window,"onresize",this,"onWindowResized");
}
};
(function(){
var dw=dojo.widget;
var dwm=dw.manager;
var h=dojo.lang.curry(dojo.lang,"hitch",dwm);
var g=function(_843,_844){
dw[(_844||_843)]=h(_843);
};
g("add","addWidget");
g("destroyAll","destroyAllWidgets");
g("remove","removeWidget");
g("removeById","removeWidgetById");
g("getWidgetById");
g("getWidgetById","byId");
g("getWidgetsByType");
g("getWidgetsByFilter");
g("getWidgetsByType","byType");
g("getWidgetsByFilter","byFilter");
g("getWidgetByNode","byNode");
dw.all=function(n){
var _846=dwm.getAllWidgets.apply(dwm,arguments);
if(arguments.length>0){
return _846[n];
}
return _846;
};
g("registerWidgetPackage");
g("getImplementation","getWidgetImplementation");
g("getImplementationName","getWidgetImplementationName");
dw.widgets=dwm.widgets;
dw.widgetIds=dwm.widgetIds;
dw.root=dwm.root;
})();
dojo.provide("dojo.widget.Widget");
dojo.provide("dojo.widget.tags");
dojo.require("dojo.lang.func");
dojo.require("dojo.lang.array");
dojo.require("dojo.lang.extras");
dojo.require("dojo.lang.declare");
dojo.require("dojo.widget.Manager");
dojo.require("dojo.event.*");
dojo.declare("dojo.widget.Widget",null,{initializer:function(){
this.children=[];
this.extraArgs={};
},parent:null,isTopLevel:false,isModal:false,isEnabled:true,isHidden:false,isContainer:false,widgetId:"",widgetType:"Widget",toString:function(){
return "[Widget "+this.widgetType+", "+(this.widgetId||"NO ID")+"]";
},repr:function(){
return this.toString();
},enable:function(){
this.isEnabled=true;
},disable:function(){
this.isEnabled=false;
},hide:function(){
this.isHidden=true;
},show:function(){
this.isHidden=false;
},onResized:function(){
this.notifyChildrenOfResize();
},notifyChildrenOfResize:function(){
for(var i=0;i<this.children.length;i++){
var _848=this.children[i];
if(_848.onResized){
_848.onResized();
}
}
},create:function(args,_84a,_84b){
this.satisfyPropertySets(args,_84a,_84b);
this.mixInProperties(args,_84a,_84b);
this.postMixInProperties(args,_84a,_84b);
dojo.widget.manager.add(this);
this.buildRendering(args,_84a,_84b);
this.initialize(args,_84a,_84b);
this.postInitialize(args,_84a,_84b);
this.postCreate(args,_84a,_84b);
return this;
},destroy:function(_84c){
this.destroyChildren();
this.uninitialize();
this.destroyRendering(_84c);
dojo.widget.manager.removeById(this.widgetId);
},destroyChildren:function(){
while(this.children.length>0){
var tc=this.children[0];
this.removeChild(tc);
tc.destroy();
}
},getChildrenOfType:function(type,_84f){
var ret=[];
var _851=dojo.lang.isFunction(type);
if(!_851){
type=type.toLowerCase();
}
for(var x=0;x<this.children.length;x++){
if(_851){
if(this.children[x] instanceof type){
ret.push(this.children[x]);
}
}else{
if(this.children[x].widgetType.toLowerCase()==type){
ret.push(this.children[x]);
}
}
if(_84f){
ret=ret.concat(this.children[x].getChildrenOfType(type,_84f));
}
}
return ret;
},getDescendants:function(){
var _853=[];
var _854=[this];
var elem;
while(elem=_854.pop()){
_853.push(elem);
dojo.lang.forEach(elem.children,function(elem){
_854.push(elem);
});
}
return _853;
},satisfyPropertySets:function(args){
return args;
},mixInProperties:function(args,frag){
if((args["fastMixIn"])||(frag["fastMixIn"])){
for(var x in args){
this[x]=args[x];
}
return;
}
var _85b;
var _85c=dojo.widget.lcArgsCache[this.widgetType];
if(_85c==null){
_85c={};
for(var y in this){
_85c[((new String(y)).toLowerCase())]=y;
}
dojo.widget.lcArgsCache[this.widgetType]=_85c;
}
var _85e={};
for(var x in args){
if(!this[x]){
var y=_85c[(new String(x)).toLowerCase()];
if(y){
args[y]=args[x];
x=y;
}
}
if(_85e[x]){
continue;
}
_85e[x]=true;
if((typeof this[x])!=(typeof _85b)){
if(typeof args[x]!="string"){
this[x]=args[x];
}else{
if(dojo.lang.isString(this[x])){
this[x]=args[x];
}else{
if(dojo.lang.isNumber(this[x])){
this[x]=new Number(args[x]);
}else{
if(dojo.lang.isBoolean(this[x])){
this[x]=(args[x].toLowerCase()=="false")?false:true;
}else{
if(dojo.lang.isFunction(this[x])){
if(args[x].search(/[^\w\.]+/i)==-1){
this[x]=dojo.evalObjPath(args[x],false);
}else{
var tn=dojo.lang.nameAnonFunc(new Function(args[x]),this);
dojo.event.connect(this,x,this,tn);
}
}else{
if(dojo.lang.isArray(this[x])){
this[x]=args[x].split(";");
}else{
if(this[x] instanceof Date){
this[x]=new Date(Number(args[x]));
}else{
if(typeof this[x]=="object"){
if(this[x] instanceof dojo.uri.Uri){
this[x]=args[x];
}else{
var _860=args[x].split(";");
for(var y=0;y<_860.length;y++){
var si=_860[y].indexOf(":");
if((si!=-1)&&(_860[y].length>si)){
this[x][_860[y].substr(0,si).replace(/^\s+|\s+$/g,"")]=_860[y].substr(si+1);
}
}
}
}else{
this[x]=args[x];
}
}
}
}
}
}
}
}
}else{
this.extraArgs[x.toLowerCase()]=args[x];
}
}
},postMixInProperties:function(){
},initialize:function(args,frag){
return false;
},postInitialize:function(args,frag){
return false;
},postCreate:function(args,frag){
return false;
},uninitialize:function(){
return false;
},buildRendering:function(){
dojo.unimplemented("dojo.widget.Widget.buildRendering, on "+this.toString()+", ");
return false;
},destroyRendering:function(){
dojo.unimplemented("dojo.widget.Widget.destroyRendering");
return false;
},cleanUp:function(){
dojo.unimplemented("dojo.widget.Widget.cleanUp");
return false;
},addedTo:function(_868){
},addChild:function(_869){
dojo.unimplemented("dojo.widget.Widget.addChild");
return false;
},removeChild:function(_86a){
for(var x=0;x<this.children.length;x++){
if(this.children[x]===_86a){
this.children.splice(x,1);
break;
}
}
return _86a;
},resize:function(_86c,_86d){
this.setWidth(_86c);
this.setHeight(_86d);
},setWidth:function(_86e){
if((typeof _86e=="string")&&(_86e.substr(-1)=="%")){
this.setPercentageWidth(_86e);
}else{
this.setNativeWidth(_86e);
}
},setHeight:function(_86f){
if((typeof _86f=="string")&&(_86f.substr(-1)=="%")){
this.setPercentageHeight(_86f);
}else{
this.setNativeHeight(_86f);
}
},setPercentageHeight:function(_870){
return false;
},setNativeHeight:function(_871){
return false;
},setPercentageWidth:function(_872){
return false;
},setNativeWidth:function(_873){
return false;
},getPreviousSibling:function(){
var idx=this.getParentIndex();
if(idx<=0){
return null;
}
return this.getSiblings()[idx-1];
},getSiblings:function(){
return this.parent.children;
},getParentIndex:function(){
return dojo.lang.indexOf(this.getSiblings(),this,true);
},getNextSibling:function(){
var idx=this.getParentIndex();
if(idx==this.getSiblings().length-1){
return null;
}
if(idx<0){
return null;
}
return this.getSiblings()[idx+1];
}});
dojo.widget.lcArgsCache={};
dojo.widget.tags={};
dojo.widget.tags.addParseTreeHandler=function(type){
var _877=type.toLowerCase();
this[_877]=function(_878,_879,_87a,_87b,_87c){
return dojo.widget.buildWidgetFromParseTree(_877,_878,_879,_87a,_87b,_87c);
};
};
dojo.widget.tags.addParseTreeHandler("dojo:widget");
dojo.widget.tags["dojo:propertyset"]=function(_87d,_87e,_87f){
var _880=_87e.parseProperties(_87d["dojo:propertyset"]);
};
dojo.widget.tags["dojo:connect"]=function(_881,_882,_883){
var _884=_882.parseProperties(_881["dojo:connect"]);
};
dojo.widget.buildWidgetFromParseTree=function(type,frag,_887,_888,_889,_88a){
var _88b=type.split(":");
_88b=(_88b.length==2)?_88b[1]:type;
var _88c=_88a||_887.parseProperties(frag["dojo:"+_88b]);
var _88d=dojo.widget.manager.getImplementation(_88b);
if(!_88d){
throw new Error("cannot find \""+_88b+"\" widget");
}else{
if(!_88d.create){
throw new Error("\""+_88b+"\" widget object does not appear to implement *Widget");
}
}
_88c["dojoinsertionindex"]=_889;
var ret=_88d.create(_88c,frag,_888);
return ret;
};
dojo.widget.defineWidget=function(_88f,_890,_891,_892,ctor){
var _894=_88f.split(".");
var type=_894.pop();
if(_892){
while((_894.length)&&(_894.pop()!=_892)){
}
}
_894=_894.join(".");
dojo.widget.manager.registerWidgetPackage(_894);
dojo.widget.tags.addParseTreeHandler("dojo:"+type.toLowerCase());
if(!_891){
_891={};
}
_891.widgetType=type;
if((!ctor)&&(_891["classConstructor"])){
ctor=_891.classConstructor;
delete _891.classConstructor;
}
dojo.declare(_88f,_890,_891,ctor);
};
dojo.provide("dojo.widget.Parse");
dojo.require("dojo.widget.Manager");
dojo.require("dojo.dom");
dojo.widget.Parse=function(_896){
this.propertySetsList=[];
this.fragment=_896;
this.createComponents=function(frag,_898){
var _899=[];
var _89a=false;
try{
if((frag)&&(frag["tagName"])&&(frag!=frag["nodeRef"])){
var _89b=dojo.widget.tags;
var tna=String(frag["tagName"]).split(";");
for(var x=0;x<tna.length;x++){
var ltn=(tna[x].replace(/^\s+|\s+$/g,"")).toLowerCase();
if(_89b[ltn]){
_89a=true;
frag.tagName=ltn;
var ret=_89b[ltn](frag,this,_898,frag["index"]);
_899.push(ret);
}else{
if((dojo.lang.isString(ltn))&&(ltn.substr(0,5)=="dojo:")){
dojo.debug("no tag handler registed for type: ",ltn);
}
}
}
}
}
catch(e){
dojo.debug("dojo.widget.Parse: error:",e);
}
if(!_89a){
_899=_899.concat(this.createSubComponents(frag,_898));
}
return _899;
};
this.createSubComponents=function(_8a0,_8a1){
var frag,comps=[];
for(var item in _8a0){
frag=_8a0[item];
if((frag)&&(typeof frag=="object")&&(frag!=_8a0.nodeRef)&&(frag!=_8a0["tagName"])){
comps=comps.concat(this.createComponents(frag,_8a1));
}
}
return comps;
};
this.parsePropertySets=function(_8a4){
return [];
var _8a5=[];
for(var item in _8a4){
if((_8a4[item]["tagName"]=="dojo:propertyset")){
_8a5.push(_8a4[item]);
}
}
this.propertySetsList.push(_8a5);
return _8a5;
};
this.parseProperties=function(_8a7){
var _8a8={};
for(var item in _8a7){
if((_8a7[item]==_8a7["tagName"])||(_8a7[item]==_8a7.nodeRef)){
}else{
if((_8a7[item]["tagName"])&&(dojo.widget.tags[_8a7[item].tagName.toLowerCase()])){
}else{
if((_8a7[item][0])&&(_8a7[item][0].value!="")&&(_8a7[item][0].value!=null)){
try{
if(item.toLowerCase()=="dataprovider"){
var _8aa=this;
this.getDataProvider(_8aa,_8a7[item][0].value);
_8a8.dataProvider=this.dataProvider;
}
_8a8[item]=_8a7[item][0].value;
var _8ab=this.parseProperties(_8a7[item]);
for(var _8ac in _8ab){
_8a8[_8ac]=_8ab[_8ac];
}
}
catch(e){
dojo.debug(e);
}
}
}
}
}
return _8a8;
};
this.getDataProvider=function(_8ad,_8ae){
dojo.io.bind({url:_8ae,load:function(type,_8b0){
if(type=="load"){
_8ad.dataProvider=_8b0;
}
},mimetype:"text/javascript",sync:true});
};
this.getPropertySetById=function(_8b1){
for(var x=0;x<this.propertySetsList.length;x++){
if(_8b1==this.propertySetsList[x]["id"][0].value){
return this.propertySetsList[x];
}
}
return "";
};
this.getPropertySetsByType=function(_8b3){
var _8b4=[];
for(var x=0;x<this.propertySetsList.length;x++){
var cpl=this.propertySetsList[x];
var cpcc=cpl["componentClass"]||cpl["componentType"]||null;
if((cpcc)&&(propertySetId==cpcc[0].value)){
_8b4.push(cpl);
}
}
return _8b4;
};
this.getPropertySets=function(_8b8){
var ppl="dojo:propertyproviderlist";
var _8ba=[];
var _8bb=_8b8["tagName"];
if(_8b8[ppl]){
var _8bc=_8b8[ppl].value.split(" ");
for(propertySetId in _8bc){
if((propertySetId.indexOf("..")==-1)&&(propertySetId.indexOf("://")==-1)){
var _8bd=this.getPropertySetById(propertySetId);
if(_8bd!=""){
_8ba.push(_8bd);
}
}else{
}
}
}
return (this.getPropertySetsByType(_8bb)).concat(_8ba);
};
this.createComponentFromScript=function(_8be,_8bf,_8c0){
var ltn="dojo:"+_8bf.toLowerCase();
if(dojo.widget.tags[ltn]){
_8c0.fastMixIn=true;
return [dojo.widget.tags[ltn](_8c0,this,null,null,_8c0)];
}else{
if(ltn.substr(0,5)=="dojo:"){
dojo.debug("no tag handler registed for type: ",ltn);
}
}
};
};
dojo.widget._parser_collection={"dojo":new dojo.widget.Parse()};
dojo.widget.getParser=function(name){
if(!name){
name="dojo";
}
if(!this._parser_collection[name]){
this._parser_collection[name]=new dojo.widget.Parse();
}
return this._parser_collection[name];
};
dojo.widget.createWidget=function(name,_8c4,_8c5,_8c6){
var _8c7=name.toLowerCase();
var _8c8="dojo:"+_8c7;
var _8c9=(dojo.byId(name)&&(!dojo.widget.tags[_8c8]));
if((arguments.length==1)&&((typeof name!="string")||(_8c9))){
var xp=new dojo.xml.Parse();
var tn=(_8c9)?dojo.byId(name):name;
return dojo.widget.getParser().createComponents(xp.parseElement(tn,null,true))[0];
}
function fromScript(_8cc,name,_8ce){
_8ce[_8c8]={dojotype:[{value:_8c7}],nodeRef:_8cc,fastMixIn:true};
return dojo.widget.getParser().createComponentFromScript(_8cc,name,_8ce,true);
}
if(typeof name!="string"&&typeof _8c4=="string"){
dojo.deprecated("dojo.widget.createWidget","argument order is now of the form "+"dojo.widget.createWidget(NAME, [PROPERTIES, [REFERENCENODE, [POSITION]]])");
return fromScript(name,_8c4,_8c5);
}
_8c4=_8c4||{};
var _8cf=false;
var tn=null;
var h=dojo.render.html.capable;
if(h){
tn=document.createElement("span");
}
if(!_8c5){
_8cf=true;
_8c5=tn;
if(h){
document.body.appendChild(_8c5);
}
}else{
if(_8c6){
dojo.dom.insertAtPosition(tn,_8c5,_8c6);
}else{
tn=_8c5;
}
}
var _8d1=fromScript(tn,name,_8c4);
if(!_8d1[0]||typeof _8d1[0].widgetType=="undefined"){
throw new Error("createWidget: Creation of \""+name+"\" widget failed.");
}
if(_8cf){
if(_8d1[0].domNode.parentNode){
_8d1[0].domNode.parentNode.removeChild(_8d1[0].domNode);
}
}
return _8d1[0];
};
dojo.widget.fromScript=function(name,_8d3,_8d4,_8d5){
dojo.deprecated("dojo.widget.fromScript"," use "+"dojo.widget.createWidget instead");
return dojo.widget.createWidget(name,_8d3,_8d4,_8d5);
};
dojo.provide("dojo.widget.DomWidget");
dojo.require("dojo.event.*");
dojo.require("dojo.widget.Widget");
dojo.require("dojo.dom");
dojo.require("dojo.xml.Parse");
dojo.require("dojo.uri.*");
dojo.require("dojo.lang.func");
dojo.widget._cssFiles={};
dojo.widget._cssStrings={};
dojo.widget._templateCache={};
dojo.widget.defaultStrings={dojoRoot:dojo.hostenv.getBaseScriptUri(),baseScriptUri:dojo.hostenv.getBaseScriptUri()};
dojo.widget.buildFromTemplate=function(){
dojo.lang.forward("fillFromTemplateCache");
};
dojo.widget.fillFromTemplateCache=function(obj,_8d7,_8d8,_8d9,_8da){
var _8db=_8d7||obj.templatePath;
var _8dc=_8d8||obj.templateCssPath;
if(_8db&&!(_8db instanceof dojo.uri.Uri)){
_8db=dojo.uri.dojoUri(_8db);
dojo.deprecated("templatePath should be of type dojo.uri.Uri");
}
if(_8dc&&!(_8dc instanceof dojo.uri.Uri)){
_8dc=dojo.uri.dojoUri(_8dc);
dojo.deprecated("templateCssPath should be of type dojo.uri.Uri");
}
var _8dd=dojo.widget._templateCache;
if(!obj["widgetType"]){
do{
var _8de="__dummyTemplate__"+dojo.widget._templateCache.dummyCount++;
}while(_8dd[_8de]);
obj.widgetType=_8de;
}
var wt=obj.widgetType;
if((!obj.templateCssString)&&(_8dc)&&(!dojo.widget._cssFiles[_8dc])){
obj.templateCssString=dojo.hostenv.getText(_8dc);
obj.templateCssPath=null;
dojo.widget._cssFiles[_8dc]=true;
}
if((obj["templateCssString"])&&(!obj.templateCssString["loaded"])){
dojo.style.insertCssText(obj.templateCssString,null,_8dc);
if(!obj.templateCssString){
obj.templateCssString="";
}
obj.templateCssString.loaded=true;
}
var ts=_8dd[wt];
if(!ts){
_8dd[wt]={"string":null,"node":null};
if(_8da){
ts={};
}else{
ts=_8dd[wt];
}
}
if(!obj.templateString){
obj.templateString=_8d9||ts["string"];
}
if(!obj.templateNode){
obj.templateNode=ts["node"];
}
if((!obj.templateNode)&&(!obj.templateString)&&(_8db)){
var _8e1=dojo.hostenv.getText(_8db);
if(_8e1){
var _8e2=_8e1.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
if(_8e2){
_8e1=_8e2[1];
}
}else{
_8e1="";
}
obj.templateString=_8e1;
if(!_8da){
_8dd[wt]["string"]=_8e1;
}
}
if((!ts["string"])&&(!_8da)){
ts.string=obj.templateString;
}
};
dojo.widget._templateCache.dummyCount=0;
dojo.widget.attachProperties=["dojoAttachPoint","id"];
dojo.widget.eventAttachProperty="dojoAttachEvent";
dojo.widget.onBuildProperty="dojoOnBuild";
dojo.widget.attachTemplateNodes=function(_8e3,_8e4,_8e5){
var _8e6=dojo.dom.ELEMENT_NODE;
function trim(str){
return str.replace(/^\s+|\s+$/g,"");
}
if(!_8e3){
_8e3=_8e4.domNode;
}
if(_8e3.nodeType!=_8e6){
return;
}
var _8e8=_8e3.all||_8e3.getElementsByTagName("*");
var _8e9=_8e4;
for(var x=-1;x<_8e8.length;x++){
var _8eb=(x==-1)?_8e3:_8e8[x];
var _8ec=[];
for(var y=0;y<this.attachProperties.length;y++){
var _8ee=_8eb.getAttribute(this.attachProperties[y]);
if(_8ee){
_8ec=_8ee.split(";");
for(var z=0;z<_8ec.length;z++){
if(dojo.lang.isArray(_8e4[_8ec[z]])){
_8e4[_8ec[z]].push(_8eb);
}else{
_8e4[_8ec[z]]=_8eb;
}
}
break;
}
}
var _8f0=_8eb.getAttribute(this.templateProperty);
if(_8f0){
_8e4[_8f0]=_8eb;
}
var _8f1=_8eb.getAttribute(this.eventAttachProperty);
if(_8f1){
var evts=_8f1.split(";");
for(var y=0;y<evts.length;y++){
if((!evts[y])||(!evts[y].length)){
continue;
}
var _8f3=null;
var tevt=trim(evts[y]);
if(evts[y].indexOf(":")>=0){
var _8f5=tevt.split(":");
tevt=trim(_8f5[0]);
_8f3=trim(_8f5[1]);
}
if(!_8f3){
_8f3=tevt;
}
var tf=function(){
var ntf=new String(_8f3);
return function(evt){
if(_8e9[ntf]){
_8e9[ntf](dojo.event.browser.fixEvent(evt,this));
}
};
}();
dojo.event.browser.addListener(_8eb,tevt,tf,false,true);
}
}
for(var y=0;y<_8e5.length;y++){
var _8f9=_8eb.getAttribute(_8e5[y]);
if((_8f9)&&(_8f9.length)){
var _8f3=null;
var _8fa=_8e5[y].substr(4);
_8f3=trim(_8f9);
var _8fb=[_8f3];
if(_8f3.indexOf(";")>=0){
_8fb=dojo.lang.map(_8f3.split(";"),trim);
}
for(var z=0;z<_8fb.length;z++){
if(!_8fb[z].length){
continue;
}
var tf=function(){
var ntf=new String(_8fb[z]);
return function(evt){
if(_8e9[ntf]){
_8e9[ntf](dojo.event.browser.fixEvent(evt,this));
}
};
}();
dojo.event.browser.addListener(_8eb,_8fa,tf,false,true);
}
}
}
var _8fe=_8eb.getAttribute(this.onBuildProperty);
if(_8fe){
eval("var node = baseNode; var widget = targetObj; "+_8fe);
}
}
};
dojo.widget.getDojoEventsFromStr=function(str){
var re=/(dojoOn([a-z]+)(\s?))=/gi;
var evts=str?str.match(re)||[]:[];
var ret=[];
var lem={};
for(var x=0;x<evts.length;x++){
if(evts[x].legth<1){
continue;
}
var cm=evts[x].replace(/\s/,"");
cm=(cm.slice(0,cm.length-1));
if(!lem[cm]){
lem[cm]=true;
ret.push(cm);
}
}
return ret;
};
dojo.declare("dojo.widget.DomWidget",dojo.widget.Widget,{initializer:function(){
if((arguments.length>0)&&(typeof arguments[0]=="object")){
this.create(arguments[0]);
}
},templateNode:null,templateString:null,templateCssString:null,preventClobber:false,domNode:null,containerNode:null,addChild:function(_906,_907,pos,ref,_90a){
if(!this.isContainer){
dojo.debug("dojo.widget.DomWidget.addChild() attempted on non-container widget");
return null;
}else{
this.addWidgetAsDirectChild(_906,_907,pos,ref,_90a);
this.registerChild(_906,_90a);
}
return _906;
},addWidgetAsDirectChild:function(_90b,_90c,pos,ref,_90f){
if((!this.containerNode)&&(!_90c)){
this.containerNode=this.domNode;
}
var cn=(_90c)?_90c:this.containerNode;
if(!pos){
pos="after";
}
if(!ref){
if(!cn){
cn=document.body;
}
ref=cn.lastChild;
}
if(!_90f){
_90f=0;
}
_90b.domNode.setAttribute("dojoinsertionindex",_90f);
if(!ref){
cn.appendChild(_90b.domNode);
}else{
if(pos=="insertAtIndex"){
dojo.dom.insertAtIndex(_90b.domNode,ref.parentNode,_90f);
}else{
if((pos=="after")&&(ref===cn.lastChild)){
cn.appendChild(_90b.domNode);
}else{
dojo.dom.insertAtPosition(_90b.domNode,cn,pos);
}
}
}
},registerChild:function(_911,_912){
_911.dojoInsertionIndex=_912;
var idx=-1;
for(var i=0;i<this.children.length;i++){
if(this.children[i].dojoInsertionIndex<_912){
idx=i;
}
}
this.children.splice(idx+1,0,_911);
_911.parent=this;
_911.addedTo(this);
delete dojo.widget.manager.topWidgets[_911.widgetId];
},removeChild:function(_915){
dojo.dom.removeNode(_915.domNode);
return dojo.widget.DomWidget.superclass.removeChild.call(this,_915);
},getFragNodeRef:function(frag){
if(!frag||!frag["dojo:"+this.widgetType.toLowerCase()]){
dojo.raise("Error: no frag for widget type "+this.widgetType+", id "+this.widgetId+" (maybe a widget has set it's type incorrectly)");
}
return (frag?frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"]:null);
},postInitialize:function(args,frag,_919){
var _91a=this.getFragNodeRef(frag);
if(_919&&(_919.snarfChildDomOutput||!_91a)){
_919.addWidgetAsDirectChild(this,"","insertAtIndex","",args["dojoinsertionindex"],_91a);
}else{
if(_91a){
if(this.domNode&&(this.domNode!==_91a)){
var _91b=_91a.parentNode.replaceChild(this.domNode,_91a);
}
}
}
if(_919){
_919.registerChild(this,args.dojoinsertionindex);
}else{
dojo.widget.manager.topWidgets[this.widgetId]=this;
}
if(this.isContainer){
var _91c=dojo.widget.getParser();
_91c.createSubComponents(frag,this);
}
},buildRendering:function(args,frag){
var ts=dojo.widget._templateCache[this.widgetType];
if((!this.preventClobber)&&((this.templatePath)||(this.templateNode)||((this["templateString"])&&(this.templateString.length))||((typeof ts!="undefined")&&((ts["string"])||(ts["node"]))))){
this.buildFromTemplate(args,frag);
}else{
this.domNode=this.getFragNodeRef(frag);
}
this.fillInTemplate(args,frag);
},buildFromTemplate:function(args,frag){
var _922=false;
if(args["templatecsspath"]){
args["templateCssPath"]=args["templatecsspath"];
}
if(args["templatepath"]){
_922=true;
args["templatePath"]=args["templatepath"];
}
dojo.widget.fillFromTemplateCache(this,args["templatePath"],args["templateCssPath"],null,_922);
var ts=dojo.widget._templateCache[this.widgetType];
if((ts)&&(!_922)){
if(!this.templateString.length){
this.templateString=ts["string"];
}
if(!this.templateNode){
this.templateNode=ts["node"];
}
}
var _924=false;
var node=null;
var tstr=this.templateString;
if((!this.templateNode)&&(this.templateString)){
_924=this.templateString.match(/\$\{([^\}]+)\}/g);
if(_924){
var hash=this.strings||{};
for(var key in dojo.widget.defaultStrings){
if(dojo.lang.isUndefined(hash[key])){
hash[key]=dojo.widget.defaultStrings[key];
}
}
for(var i=0;i<_924.length;i++){
var key=_924[i];
key=key.substring(2,key.length-1);
var kval=(key.substring(0,5)=="this.")?this[key.substring(5)]:hash[key];
var _92b;
if((kval)||(dojo.lang.isString(kval))){
_92b=(dojo.lang.isFunction(kval))?kval.call(this,key,this.templateString):kval;
tstr=tstr.replace(_924[i],_92b);
}
}
}else{
this.templateNode=this.createNodesFromText(this.templateString,true)[0];
ts.node=this.templateNode;
}
}
if((!this.templateNode)&&(!_924)){
dojo.debug("weren't able to create template!");
return false;
}else{
if(!_924){
node=this.templateNode.cloneNode(true);
if(!node){
return false;
}
}else{
node=this.createNodesFromText(tstr,true)[0];
}
}
this.domNode=node;
this.attachTemplateNodes(this.domNode,this);
if(this.isContainer&&this.containerNode){
var src=this.getFragNodeRef(frag);
if(src){
dojo.dom.moveChildren(src,this.containerNode);
}
}
},attachTemplateNodes:function(_92d,_92e){
if(!_92e){
_92e=this;
}
return dojo.widget.attachTemplateNodes(_92d,_92e,dojo.widget.getDojoEventsFromStr(this.templateString));
},fillInTemplate:function(){
},destroyRendering:function(){
try{
delete this.domNode;
}
catch(e){
}
},cleanUp:function(){
},getContainerHeight:function(){
dojo.unimplemented("dojo.widget.DomWidget.getContainerHeight");
},getContainerWidth:function(){
dojo.unimplemented("dojo.widget.DomWidget.getContainerWidth");
},createNodesFromText:function(){
dojo.unimplemented("dojo.widget.DomWidget.createNodesFromText");
}});
dojo.provide("dojo.lfx.toggle");
dojo.require("dojo.lfx.*");
dojo.lfx.toggle.plain={show:function(node,_930,_931,_932){
dojo.style.show(node);
if(dojo.lang.isFunction(_932)){
_932();
}
},hide:function(node,_934,_935,_936){
dojo.style.hide(node);
if(dojo.lang.isFunction(_936)){
_936();
}
}};
dojo.lfx.toggle.fade={show:function(node,_938,_939,_93a){
dojo.lfx.fadeShow(node,_938,_939,_93a).play();
},hide:function(node,_93c,_93d,_93e){
dojo.lfx.fadeHide(node,_93c,_93d,_93e).play();
}};
dojo.lfx.toggle.wipe={show:function(node,_940,_941,_942){
dojo.lfx.wipeIn(node,_940,_941,_942).play();
},hide:function(node,_944,_945,_946){
dojo.lfx.wipeOut(node,_944,_945,_946).play();
}};
dojo.lfx.toggle.explode={show:function(node,_948,_949,_94a,_94b){
dojo.lfx.explode(_94b||[0,0,0,0],node,_948,_949,_94a).play();
},hide:function(node,_94d,_94e,_94f,_950){
dojo.lfx.implode(node,_950||[0,0,0,0],_94d,_94e,_94f).play();
}};
dojo.provide("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.DomWidget");
dojo.require("dojo.html");
dojo.require("dojo.html.extras");
dojo.require("dojo.lang.extras");
dojo.require("dojo.lang.func");
dojo.require("dojo.lfx.toggle");
dojo.declare("dojo.widget.HtmlWidget",dojo.widget.DomWidget,{widgetType:"HtmlWidget",templateCssPath:null,templatePath:null,toggle:"plain",toggleDuration:150,animationInProgress:false,initialize:function(args,frag){
},postMixInProperties:function(args,frag){
this.toggleObj=dojo.lfx.toggle[this.toggle.toLowerCase()]||dojo.lfx.toggle.plain;
},getContainerHeight:function(){
dojo.unimplemented("dojo.widget.HtmlWidget.getContainerHeight");
},getContainerWidth:function(){
return this.parent.domNode.offsetWidth;
},setNativeHeight:function(_955){
var ch=this.getContainerHeight();
},createNodesFromText:function(txt,wrap){
return dojo.html.createNodesFromText(txt,wrap);
},destroyRendering:function(_959){
try{
if(!_959){
dojo.event.browser.clean(this.domNode);
}
this.domNode.parentNode.removeChild(this.domNode);
delete this.domNode;
}
catch(e){
}
},isShowing:function(){
return dojo.style.isShowing(this.domNode);
},toggleShowing:function(){
if(this.isHidden){
this.show();
}else{
this.hide();
}
},show:function(){
this.animationInProgress=true;
this.isHidden=false;
this.toggleObj.show(this.domNode,this.toggleDuration,null,dojo.lang.hitch(this,this.onShow),this.explodeSrc);
},onShow:function(){
this.animationInProgress=false;
},hide:function(){
this.animationInProgress=true;
this.isHidden=true;
this.toggleObj.hide(this.domNode,this.toggleDuration,null,dojo.lang.hitch(this,this.onHide),this.explodeSrc);
},onHide:function(){
this.animationInProgress=false;
},_isResized:function(w,h){
if(!this.isShowing()){
return false;
}
w=w||dojo.style.getOuterWidth(this.domNode);
h=h||dojo.style.getOuterHeight(this.domNode);
if(this.width==w&&this.height==h){
return false;
}
this.width=w;
this.height=h;
return true;
},onParentResized:function(){
if(!this._isResized()){
return;
}
this.onResized();
},resizeTo:function(w,h){
if(!this._isResized(w,h)){
return;
}
dojo.style.setOuterWidth(this.domNode,w);
dojo.style.setOuterHeight(this.domNode,h);
this.onResized();
},resizeSoon:function(){
if(this.isShowing()){
dojo.lang.setTimeout(this,this.onResized,0);
}
},onResized:function(){
dojo.lang.forEach(this.children,function(_95e){
_95e.onParentResized();
});
}});
dojo.kwCompoundRequire({common:["dojo.xml.Parse","dojo.widget.Widget","dojo.widget.Parse","dojo.widget.Manager"],browser:["dojo.widget.DomWidget","dojo.widget.HtmlWidget"],dashboard:["dojo.widget.DomWidget","dojo.widget.HtmlWidget"],svg:["dojo.widget.SvgWidget"]});
dojo.provide("dojo.widget.*");
dojo.provide("dojo.math");
dojo.math.degToRad=function(x){
return (x*Math.PI)/180;
};
dojo.math.radToDeg=function(x){
return (x*180)/Math.PI;
};
dojo.math.factorial=function(n){
if(n<1){
return 0;
}
var _962=1;
for(var i=1;i<=n;i++){
_962*=i;
}
return _962;
};
dojo.math.permutations=function(n,k){
if(n==0||k==0){
return 1;
}
return (dojo.math.factorial(n)/dojo.math.factorial(n-k));
};
dojo.math.combinations=function(n,r){
if(n==0||r==0){
return 1;
}
return (dojo.math.factorial(n)/(dojo.math.factorial(n-r)*dojo.math.factorial(r)));
};
dojo.math.bernstein=function(t,n,i){
return (dojo.math.combinations(n,i)*Math.pow(t,i)*Math.pow(1-t,n-i));
};
dojo.math.gaussianRandom=function(){
var k=2;
do{
var i=2*Math.random()-1;
var j=2*Math.random()-1;
k=i*i+j*j;
}while(k>=1);
k=Math.sqrt((-2*Math.log(k))/k);
return i*k;
};
dojo.math.mean=function(){
var _96e=dojo.lang.isArray(arguments[0])?arguments[0]:arguments;
var mean=0;
for(var i=0;i<_96e.length;i++){
mean+=_96e[i];
}
return mean/_96e.length;
};
dojo.math.round=function(_971,_972){
if(!_972){
var _973=1;
}else{
var _973=Math.pow(10,_972);
}
return Math.round(_971*_973)/_973;
};
dojo.math.sd=function(){
var _974=dojo.lang.isArray(arguments[0])?arguments[0]:arguments;
return Math.sqrt(dojo.math.variance(_974));
};
dojo.math.variance=function(){
var _975=dojo.lang.isArray(arguments[0])?arguments[0]:arguments;
var mean=0,squares=0;
for(var i=0;i<_975.length;i++){
mean+=_975[i];
squares+=Math.pow(_975[i],2);
}
return (squares/_975.length)-Math.pow(mean/_975.length,2);
};
dojo.math.range=function(a,b,step){
if(arguments.length<2){
b=a;
a=0;
}
if(arguments.length<3){
step=1;
}
var _97b=[];
if(step>0){
for(var i=a;i<b;i+=step){
_97b.push(i);
}
}else{
if(step<0){
for(var i=a;i>b;i+=step){
_97b.push(i);
}
}else{
throw new Error("dojo.math.range: step must be non-zero");
}
}
return _97b;
};
dojo.provide("dojo.math.curves");
dojo.require("dojo.math");
dojo.math.curves={Line:function(_97d,end){
this.start=_97d;
this.end=end;
this.dimensions=_97d.length;
for(var i=0;i<_97d.length;i++){
_97d[i]=Number(_97d[i]);
}
for(var i=0;i<end.length;i++){
end[i]=Number(end[i]);
}
this.getValue=function(n){
var _981=new Array(this.dimensions);
for(var i=0;i<this.dimensions;i++){
_981[i]=((this.end[i]-this.start[i])*n)+this.start[i];
}
return _981;
};
return this;
},Bezier:function(pnts){
this.getValue=function(step){
if(step>=1){
return this.p[this.p.length-1];
}
if(step<=0){
return this.p[0];
}
var _985=new Array(this.p[0].length);
for(var k=0;j<this.p[0].length;k++){
_985[k]=0;
}
for(var j=0;j<this.p[0].length;j++){
var C=0;
var D=0;
for(var i=0;i<this.p.length;i++){
C+=this.p[i][j]*this.p[this.p.length-1][0]*dojo.math.bernstein(step,this.p.length,i);
}
for(var l=0;l<this.p.length;l++){
D+=this.p[this.p.length-1][0]*dojo.math.bernstein(step,this.p.length,l);
}
_985[j]=C/D;
}
return _985;
};
this.p=pnts;
return this;
},CatmullRom:function(pnts,c){
this.getValue=function(step){
var _98f=step*(this.p.length-1);
var node=Math.floor(_98f);
var _991=_98f-node;
var i0=node-1;
if(i0<0){
i0=0;
}
var i=node;
var i1=node+1;
if(i1>=this.p.length){
i1=this.p.length-1;
}
var i2=node+2;
if(i2>=this.p.length){
i2=this.p.length-1;
}
var u=_991;
var u2=_991*_991;
var u3=_991*_991*_991;
var _999=new Array(this.p[0].length);
for(var k=0;k<this.p[0].length;k++){
var x1=(-this.c*this.p[i0][k])+((2-this.c)*this.p[i][k])+((this.c-2)*this.p[i1][k])+(this.c*this.p[i2][k]);
var x2=(2*this.c*this.p[i0][k])+((this.c-3)*this.p[i][k])+((3-2*this.c)*this.p[i1][k])+(-this.c*this.p[i2][k]);
var x3=(-this.c*this.p[i0][k])+(this.c*this.p[i1][k]);
var x4=this.p[i][k];
_999[k]=x1*u3+x2*u2+x3*u+x4;
}
return _999;
};
if(!c){
this.c=0.7;
}else{
this.c=c;
}
this.p=pnts;
return this;
},Arc:function(_99f,end,ccw){
var _9a2=dojo.math.points.midpoint(_99f,end);
var _9a3=dojo.math.points.translate(dojo.math.points.invert(_9a2),_99f);
var rad=Math.sqrt(Math.pow(_9a3[0],2)+Math.pow(_9a3[1],2));
var _9a5=dojo.math.radToDeg(Math.atan(_9a3[1]/_9a3[0]));
if(_9a3[0]<0){
_9a5-=90;
}else{
_9a5+=90;
}
dojo.math.curves.CenteredArc.call(this,_9a2,rad,_9a5,_9a5+(ccw?-180:180));
},CenteredArc:function(_9a6,_9a7,_9a8,end){
this.center=_9a6;
this.radius=_9a7;
this.start=_9a8||0;
this.end=end;
this.getValue=function(n){
var _9ab=new Array(2);
var _9ac=dojo.math.degToRad(this.start+((this.end-this.start)*n));
_9ab[0]=this.center[0]+this.radius*Math.sin(_9ac);
_9ab[1]=this.center[1]-this.radius*Math.cos(_9ac);
return _9ab;
};
return this;
},Circle:function(_9ad,_9ae){
dojo.math.curves.CenteredArc.call(this,_9ad,_9ae,0,360);
return this;
},Path:function(){
var _9af=[];
var _9b0=[];
var _9b1=[];
var _9b2=0;
this.add=function(_9b3,_9b4){
if(_9b4<0){
dojo.raise("dojo.math.curves.Path.add: weight cannot be less than 0");
}
_9af.push(_9b3);
_9b0.push(_9b4);
_9b2+=_9b4;
computeRanges();
};
this.remove=function(_9b5){
for(var i=0;i<_9af.length;i++){
if(_9af[i]==_9b5){
_9af.splice(i,1);
_9b2-=_9b0.splice(i,1)[0];
break;
}
}
computeRanges();
};
this.removeAll=function(){
_9af=[];
_9b0=[];
_9b2=0;
};
this.getValue=function(n){
var _9b8=false,value=0;
for(var i=0;i<_9b1.length;i++){
var r=_9b1[i];
if(n>=r[0]&&n<r[1]){
var subN=(n-r[0])/r[2];
value=_9af[i].getValue(subN);
_9b8=true;
break;
}
}
if(!_9b8){
value=_9af[_9af.length-1].getValue(1);
}
for(j=0;j<i;j++){
value=dojo.math.points.translate(value,_9af[j].getValue(1));
}
return value;
};
function computeRanges(){
var _9bc=0;
for(var i=0;i<_9b0.length;i++){
var end=_9bc+_9b0[i]/_9b2;
var len=end-_9bc;
_9b1[i]=[_9bc,end,len];
_9bc=end;
}
}
return this;
}};
dojo.provide("dojo.math.points");
dojo.require("dojo.math");
dojo.math.points={translate:function(a,b){
if(a.length!=b.length){
dojo.raise("dojo.math.translate: points not same size (a:["+a+"], b:["+b+"])");
}
var c=new Array(a.length);
for(var i=0;i<a.length;i++){
c[i]=a[i]+b[i];
}
return c;
},midpoint:function(a,b){
if(a.length!=b.length){
dojo.raise("dojo.math.midpoint: points not same size (a:["+a+"], b:["+b+"])");
}
var c=new Array(a.length);
for(var i=0;i<a.length;i++){
c[i]=(a[i]+b[i])/2;
}
return c;
},invert:function(a){
var b=new Array(a.length);
for(var i=0;i<a.length;i++){
b[i]=-a[i];
}
return b;
},distance:function(a,b){
return Math.sqrt(Math.pow(b[0]-a[0],2)+Math.pow(b[1]-a[1],2));
}};
dojo.kwCompoundRequire({common:[["dojo.math",false,false],["dojo.math.curves",false,false],["dojo.math.points",false,false]]});
dojo.provide("dojo.math.*");


/**
 * Checks/unchecks all checkboxes
 *
 * @param   string   the form name
 * @param   atring   the name of the array with the checkboxes
 * @param   boolean  whether to check or to uncheck the element
 *
 * @return  boolean  always true
 */
function setBoxes(the_form, the_checkboxes, do_check)
{
    var elts      = (the_checkboxes != '')
                  ? document.forms[the_form].elements[the_checkboxes + '[]']
                  : document.forms[the_form].elements;
    var elts_cnt  = (typeof(elts.length) != 'undefined')
                  ? elts.length
                  : 0;

    if (elts_cnt) {
        for (var i = 0; i < elts_cnt; i++) {
	        
	        if (elts[i].checked == true) {
            	elts[i].checked = false;
	        }
	        else {
            	elts[i].checked = true;
	        }
        } // end for
    } else {
        elts.checked        = do_check;
    } // end if... else

    return true;
} // end of the 'setCheckboxes()' function

function addUser() {
	x_wfAdminUserForm(function (returned) { 
		var cln = document.createElement('div');
		cln.innerHTML = returned;
		var elt = document.getElementById('fillerArea');
		if (!elt) return false;
		elt.appendChild(cln);
	});
	return false;
}
function setUserStatus(div) {
	var cb = document.getElementById('cb_'+div);
	var elt = document.getElementById('hidden_'+div);
	if (!elt || !cb) return;
	elt.value = cb.checked ? 1: 0;
	return true;
}
function addRowToTable(the_element) {
	var tbl = document.getElementById(the_element);
	var lastRow = tbl.rows.length;
	// if there's no header row in the table, then iteration = lastRow + 1
	var iteration = lastRow;
	var row = tbl.insertRow(lastRow - 1);
	
	// left cell
	var cellLeft = row.insertCell(0);
	var el = document.createElement('input');
	el.setAttribute('type', 'text');
	el.setAttribute('name', 'user_name['+iteration+']');
	el.setAttribute('class', 'inputText');
	cellLeft.appendChild(el);
	
	// right cell
	var cellRight = row.insertCell(1);
	var el = document.createElement('input');
	el.setAttribute('type', 'text');
	el.setAttribute('name', 'user_email['+iteration+']');
	el.setAttribute('class', 'inputText');
	cellRight.appendChild(el);
	
	
	var cellRightY = row.insertCell(2);
	var el = document.createElement('input');
	el.setAttribute('type', 'text');
	el.setAttribute('name', 'user_real_name['+iteration+']');
	el.setAttribute('class', 'inputText');
	cellRightY.appendChild(el);
	
	
	var cellRightY = row.insertCell(3);
	var el = document.createElement('input');
	el.setAttribute('type', 'password');
	el.setAttribute('name', 'user_password['+iteration+']');
	el.setAttribute('class', 'inputPassword');
	cellRightY.appendChild(el);
	
	
	var cellRightY = row.insertCell(4);
	var el = document.createElement('input');
	el.setAttribute('type', 'password');
	el.setAttribute('name', 'user_password_verify['+iteration+']');
	el.setAttribute('class', 'inputPassword');
	cellRightY.appendChild(el);
	
	
	var cellRightZ = row.insertCell(5);
	var el = document.createElement('input');
	el.setAttribute('type', 'checkbox');
	el.setAttribute('name', 'user_status['+iteration+']');
	el.setAttribute('id', 'burea' + iteration);
	el.setAttribute('class', 'inputCheckbox');
	var text = document.createTextNode(' Administrator');
	cellRightZ.appendChild(el);
	cellRightZ.appendChild(text);	
}


function disableSubmit(theform) {
	var submitTags = theform.getElementsByTagName('input');
	if (submitTags) {
		var length = submitTags.length;
		for (i = 0; i < length; i++) {
		var tempobj = theform.elements[i];
			var tempobj = submitTags[i].getAttribute('type');
			if (tempobj.toLowerCase() == "submit")
				submitTags[i].disabled = true;
			}
		return true;
	}
	else {
		return false;
	}
}
// Table Operations Plugin for HTMLArea-3.0
// Implementation by Mihai Bazon.  Sponsored by http://www.bloki.com
//
// htmlArea v3.0 - Copyright (c) 2002 interactivetools.com, inc.
// This notice MUST stay intact for use (see license.txt).
//
// A free WYSIWYG editor replacement for <textarea> fields.
// For full source code and docs, visit http://www.interactivetools.com/
//
// Version 3.0 developed by Mihai Bazon for InteractiveTools.
//   http://dynarch.com/mishoo
//
// $Id: table-operations.js 376 2005-10-01 09:23:52Z mokhet $

// Object that will encapsulate all the table operations provided by
// HTMLArea-3.0 (except "insert table" which is included in the main file)
function TableOperations(editor) {
	this.editor = editor;

	var cfg = editor.config;
	var bl = TableOperations.btnList;
	var self = this;

	// register the toolbar buttons provided by this plugin

    
	var toolbar = ["linebreak"];
	for (var i = 0; i < bl.length; ++i) {
		var btn = bl[i];
		if (!btn) {
			/* >MT: don't add separator *
			toolbar.push("separator");
			/* <MT */
		} else {
			var id = "TO-" + btn[0];
			// >MT: don't show buttons on toolbar
			if (typeof HTMLArea.Config.MTregisterButton == 'function')
  				HTMLArea.Config.MTregisterButton(cfg, id, HTMLArea._lc(btn[2], "TableOperations"), editor.imgURL(btn[0] + ".gif", "TableOperations"), false,
					   function(editor, id) {
						   // dispatch button press event
						   self.buttonPress(editor, id);
					   }, btn[1], false);
			else
			// <MT
				cfg.registerButton(id, HTMLArea._lc(btn[2], "TableOperations"), editor.imgURL(btn[0] + ".gif", "TableOperations"), false,
					   function(editor, id) {
						   // dispatch button press event
						   self.buttonPress(editor, id);
					   }, btn[1]);
			toolbar.push(id);
		}
	}

	// add a new line in the toolbar
	cfg.toolbar.push(toolbar);
};

TableOperations._pluginInfo = {
	name          : "TableOperations",
	version       : "1.0",
	developer     : "Mihai Bazon",
	developer_url : "http://dynarch.com/mishoo/",
	c_owner       : "Mihai Bazon",
	sponsor       : "Zapatec Inc.",
	sponsor_url   : "http://www.bloki.com",
	license       : "htmlArea"
};

TableOperations.prototype._lc = function(string) {
    return HTMLArea._lc(string, 'TableOperations');
};

/************************
 * UTILITIES
 ************************/

// retrieves the closest element having the specified tagName in the list of
// ancestors of the current selection/caret.
TableOperations.prototype.getClosest = function(tagName) {
	var editor = this.editor;
	var ancestors = editor.getAllAncestors();
	var ret = null;
	tagName = ("" + tagName).toLowerCase();
	for (var i = 0; i < ancestors.length; ++i) {
		var el = ancestors[i];
		if (el.tagName.toLowerCase() == tagName) {
			ret = el;
			break;
		}
	}
	return ret;
};

// this function requires the file PopupDiv/PopupWin to be loaded from browser
TableOperations.prototype.dialogTableProperties = function() {
	// retrieve existing values
	var table = this.getClosest("table");
	// this.editor.selectNodeContents(table);
	// this.editor.updateToolbar();

    // >MT: Use PopupDiv instead of PopopWin
	var dialog = new PopupDiv(this.editor, HTMLArea._lc("Table Properties", "TableOperations"), function(dialog, params) {
    // <MT
		TableOperations.processStyle(params, table);
		for (var i in params) {
      if(typeof params[i] == 'function') continue;
			var val = params[i];
			switch (i) {
			case "f_caption":
				if (/\S/.test(val)) {
					// contains non white-space characters
					var caption = table.getElementsByTagName("caption")[0];
					if (!caption) {
						caption = dialog.editor._doc.createElement("caption");
						table.insertBefore(caption, table.firstChild);
					}
					caption.innerHTML = val;
				} else {
					// search for caption and delete it if found
					var caption = table.getElementsByTagName("caption")[0];
					if (caption) {
						caption.parentNode.removeChild(caption);
					}
				}
				break;
			case "f_summary":
				table.summary = val;
				break;
			case "f_width":
				table.style.width = ("" + val) + params.f_unit;
				break;
			case "f_align":
				table.align = val;
				break;
			case "f_spacing":
				table.cellSpacing = val;
				break;
			case "f_padding":
				table.cellPadding = val;
				break;
			case "f_borders":
				table.border = val;
				break;
			case "f_frames":
				table.frame = val;
				break;
			case "f_rules":
				table.rules = val;
				break;
			}
		}
		// various workarounds to refresh the table display (Gecko,
		// what's going on?! do not disappoint me!)
		dialog.editor.forceRedraw();
		dialog.editor.focusEditor();
		dialog.editor.updateToolbar();
		var save_collapse = table.style.borderCollapse;
		table.style.borderCollapse = "collapse";
		table.style.borderCollapse = "separate";
		table.style.borderCollapse = save_collapse;
	},

	// this function gets called when the dialog needs to be initialized
	function (dialog) {

		var f_caption = "";
		var capel = table.getElementsByTagName("caption")[0];
		if (capel) {
			f_caption = capel.innerHTML;
		}
		var f_summary = table.summary;
		var f_width = parseInt(table.style.width);
		isNaN(f_width) && (f_width = "");
		var f_unit = /%/.test(table.style.width) ? 'percent' : 'pixels';
		var f_align = table.align;
		var f_spacing = table.cellSpacing;
		var f_padding = table.cellPadding;
		var f_borders = table.border;
		var f_frames = table.frame;
		var f_rules = table.rules;

		function selected(val) {
			return val ? " selected" : "";
		};

		// dialog contents
		dialog.content.style.width = "400px";
		dialog.content.innerHTML = " \
<div class='title'\
 style='background: url(" + dialog.baseURL + dialog.editor.imgURL("table-prop.gif", "TableOperations") + ") #fff 98% 50% no-repeat'>" + HTMLArea._lc("Table Properties", "TableOperations") + "\
</div> \
<table style='width:100%'> \
  <tr> \
    <td> \
      <fieldset><legend>" + HTMLArea._lc("Description", "TableOperations") + "</legend> \
       <table style='width:100%'> \
        <tr> \
          <td class='label'>" + HTMLArea._lc("Caption", "TableOperations") + ":</td> \
          <td class='value'><input type='text' name='f_caption' value='" + f_caption + "'/></td> \
        </tr><tr> \
          <td class='label'>" + HTMLArea._lc("Summary", "TableOperations") + ":</td> \
          <td class='value'><input type='text' name='f_summary' value='" + f_summary + "'/></td> \
        </tr> \
       </table> \
      </fieldset> \
    </td> \
  </tr> \
  <tr><td id='--HA-layout'></td></tr> \
  <tr> \
    <td> \
      <fieldset><legend>" + HTMLArea._lc("Spacing and padding", "TableOperations") + "</legend> \
       <table style='width:100%'> \
"+//        <tr> \
//           <td class='label'>" + HTMLArea._lc("Width", "TableOperations") + ":</td> \
//           <td><input type='text' name='f_width' value='" + f_width + "' size='5' /> \
//             <select name='f_unit'> \
//               <option value='%'" + selected(f_unit == "percent") + ">" + HTMLArea._lc("percent", "TableOperations") + "</option> \
//               <option value='px'" + selected(f_unit == "pixels") + ">" + HTMLArea._lc("pixels", "TableOperations") + "</option> \
//             </select> &nbsp;&nbsp;" + HTMLArea._lc("Align", "TableOperations") + ": \
//             <select name='f_align'> \
//               <option value='left'" + selected(f_align == "left") + ">" + HTMLArea._lc("Left", "TableOperations") + "</option> \
//               <option value='center'" + selected(f_align == "center") + ">" + HTMLArea._lc("Center", "TableOperations") + "</option> \
//               <option value='right'" + selected(f_align == "right") + ">" + HTMLArea._lc("Right", "TableOperations") + "</option> \
//             </select> \
//           </td> \
//         </tr> \
"        <tr> \
          <td class='label'>" + HTMLArea._lc("Spacing", "TableOperations") + ":</td> \
          <td><input type='text' name='f_spacing' size='5' value='" + f_spacing + "' /> &nbsp;" + HTMLArea._lc("Padding", "TableOperations") + ":\
            <input type='text' name='f_padding' size='5' value='" + f_padding + "' /> &nbsp;&nbsp;" + HTMLArea._lc("pixels", "TableOperations") + "\
          </td> \
        </tr> \
       </table> \
      </fieldset> \
    </td> \
  </tr> \
  <tr> \
    <td> \
      <fieldset><legend>Frame and borders</legend> \
        <table width='100%'> \
          <tr> \
            <td class='label'>" + HTMLArea._lc("Borders", "TableOperations") + ":</td> \
            <td><input name='f_borders' type='text' size='5' value='" + f_borders + "' /> &nbsp;&nbsp;" + HTMLArea._lc("pixels", "TableOperations") + "</td> \
          </tr> \
          <tr> \
            <td class='label'>" + HTMLArea._lc("Frames", "TableOperations") + ":</td> \
            <td> \
              <select name='f_frames'> \
                <option value='void'" + selected(f_frames == "void") + ">" + HTMLArea._lc("No sides", "TableOperations") + "</option> \
                <option value='above'" + selected(f_frames == "above") + ">" + HTMLArea._lc("The top side only", "TableOperations") + "</option> \
                <option value='below'" + selected(f_frames == "below") + ">" + HTMLArea._lc("The bottom side only", "TableOperations") + "</option> \
                <option value='hsides'" + selected(f_frames == "hsides") + ">" + HTMLArea._lc("The top and bottom sides only", "TableOperations") + "</option> \
                <option value='vsides'" + selected(f_frames == "vsides") + ">" + HTMLArea._lc("The right and left sides only", "TableOperations") + "</option> \
                <option value='lhs'" + selected(f_frames == "lhs") + ">" + HTMLArea._lc("The left-hand side only", "TableOperations") + "</option> \
                <option value='rhs'" + selected(f_frames == "rhs") + ">" + HTMLArea._lc("The right-hand side only", "TableOperations") + "</option> \
                <option value='box'" + selected(f_frames == "box") + ">" + HTMLArea._lc("All four sides", "TableOperations") + "</option> \
              </select> \
            </td> \
          </tr> \
          <tr> \
            <td class='label'>" + HTMLArea._lc("Rules", "TableOperations") + ":</td> \
            <td> \
              <select name='f_rules'> \
                <option value='none'" + selected(f_rules == "none") + ">" + HTMLArea._lc("No rules", "TableOperations") + "</option> \
                <option value='rows'" + selected(f_rules == "rows") + ">" + HTMLArea._lc("Rules will appear between rows only", "TableOperations") + "</option> \
                <option value='cols'" + selected(f_rules == "cols") + ">" + HTMLArea._lc("Rules will appear between columns only", "TableOperations") + "</option> \
                <option value='all'" + selected(f_rules == "all") + ">" + HTMLArea._lc("Rules will appear between all rows and columns", "TableOperations") + "</option> \
              </select> \
            </td> \
          </tr> \
        </table> \
      </fieldset> \
    </td> \
  </tr> \
  <tr> \
    <td id='--HA-style'></td> \
  </tr> \
</table> \
";
		var st_prop = TableOperations.createStyleFieldset(dialog.doc, dialog.editor, table);
		var p = dialog.doc.getElementById("--HA-style");
		p.appendChild(st_prop);
		var st_layout = TableOperations.createStyleLayoutFieldset(dialog.doc, dialog.editor, table);
		p = dialog.doc.getElementById("--HA-layout");
		p.appendChild(st_layout);
		dialog.modal = true;
		dialog.addButtons("OK", "Cancel");
		dialog.showAtElement(dialog.editor._iframe, "c");
	});
};

// this function requires the file PopupDiv/PopupWin to be loaded from browser
TableOperations.prototype.dialogRowCellProperties = function(cell) {
	// retrieve existing values
	var element = this.getClosest(cell ? "td" : "tr");
	var table = this.getClosest("table");
	// this.editor.selectNodeContents(element);
	// this.editor.updateToolbar();

    // >MT: Use PopupDiv instead of PopopWin
	var dialog = new PopupDiv(this.editor, cell ? HTMLArea._lc("Cell Properties", "TableOperations") : HTMLArea._lc("Row Properties", "TableOperations"), function(dialog, params) {
    // <MT
		TableOperations.processStyle(params, element);
		for (var i in params) {
			if(typeof params[i] == 'function') continue;
			var val = params[i];
			switch (i) {
			case "f_align":
				element.align = val;
				break;
			case "f_char":
				element.ch = val;
				break;
			case "f_valign":
				element.vAlign = val;
				break;
			}
		}
		// various workarounds to refresh the table display (Gecko,
		// what's going on?! do not disappoint me!)
		dialog.editor.forceRedraw();
		dialog.editor.focusEditor();
		dialog.editor.updateToolbar();
		var save_collapse = table.style.borderCollapse;
		table.style.borderCollapse = "collapse";
		table.style.borderCollapse = "separate";
		table.style.borderCollapse = save_collapse;
	},

	// this function gets called when the dialog needs to be initialized
	function (dialog) {

		var f_align = element.align;
		var f_valign = element.vAlign;
		var f_char = element.ch;

		function selected(val) {
			return val ? " selected" : "";
		};

		// dialog contents
		dialog.content.style.width = "400px";
		dialog.content.innerHTML = " \
<div class='title'\
 style='background: url(" + dialog.baseURL + dialog.editor.imgURL(cell ? "cell-prop.gif" : "row-prop.gif", "TableOperations") + ") #fff 98% 50% no-repeat'>" + HTMLArea._lc(cell ? "Cell Properties" : "Row Properties", "TableOperations") + "</div> \
<table style='width:100%'> \
  <tr> \
    <td id='--HA-layout'> \
"+//      <fieldset><legend>" + HTMLArea._lc("Layout", "TableOperations") + "</legend> \
//        <table style='width:100%'> \
//         <tr> \
//           <td class='label'>" + HTMLArea._lc("Align", "TableOperations") + ":</td> \
//           <td> \
//             <select name='f_align'> \
//               <option value='left'" + selected(f_align == "left") + ">" + HTMLArea._lc("Left", "TableOperations") + "</option> \
//               <option value='center'" + selected(f_align == "center") + ">" + HTMLArea._lc("Center", "TableOperations") + "</option> \
//               <option value='right'" + selected(f_align == "right") + ">" + HTMLArea._lc("Right", "TableOperations") + "</option> \
//               <option value='char'" + selected(f_align == "char") + ">" + HTMLArea._lc("Char", "TableOperations") + "</option> \
//             </select> \
//             &nbsp;&nbsp;" + HTMLArea._lc("Char", "TableOperations") + ": \
//             <input type='text' style='font-family: monospace; text-align: center' name='f_char' size='1' value='" + f_char + "' /> \
//           </td> \
//         </tr><tr> \
//           <td class='label'>" + HTMLArea._lc("Vertical align", "TableOperations") + ":</td> \
//           <td> \
//             <select name='f_valign'> \
//               <option value='top'" + selected(f_valign == "top") + ">" + HTMLArea._lc("Top", "TableOperations") + "</option> \
//               <option value='middle'" + selected(f_valign == "middle") + ">" + HTMLArea._lc("Middle", "TableOperations") + "</option> \
//               <option value='bottom'" + selected(f_valign == "bottom") + ">" + HTMLArea._lc("Bottom", "TableOperations") + "</option> \
//               <option value='baseline'" + selected(f_valign == "baseline") + ">" + HTMLArea._lc("Baseline", "TableOperations") + "</option> \
//             </select> \
//           </td> \
//         </tr> \
//        </table> \
//       </fieldset> \
"    </td> \
  </tr> \
  <tr> \
    <td id='--HA-style'></td> \
  </tr> \
</table> \
";
		var st_prop = TableOperations.createStyleFieldset(dialog.doc, dialog.editor, element);
		var p = dialog.doc.getElementById("--HA-style");
		p.appendChild(st_prop);
		var st_layout = TableOperations.createStyleLayoutFieldset(dialog.doc, dialog.editor, element);
		p = dialog.doc.getElementById("--HA-layout");
		p.appendChild(st_layout);
		dialog.modal = true;
		dialog.addButtons("OK", "Cancel");
		dialog.showAtElement(dialog.editor._iframe, "c");
	});
};

// this function gets called when some button from the TableOperations toolbar
// was pressed.
TableOperations.prototype.buttonPress = function(editor, button_id) {
	this.editor = editor;
	var mozbr = HTMLArea.is_gecko ? "<br />" : "";

	// helper function that clears the content in a table row
	function clearRow(tr) {
		var tds = tr.getElementsByTagName("td");
		for (var i = tds.length; --i >= 0;) {
			var td = tds[i];
			td.rowSpan = 1;
			td.innerHTML = mozbr;
		}
	};

	function splitRow(td) {
		var n = parseInt("" + td.rowSpan);
		var nc = parseInt("" + td.colSpan);
		td.rowSpan = 1;
		tr = td.parentNode;
		var itr = tr.rowIndex;
		var trs = tr.parentNode.rows;
		var index = td.cellIndex;
		while (--n > 0) {
			tr = trs[++itr];
			var otd = editor._doc.createElement("td");
			otd.colSpan = td.colSpan;
			otd.innerHTML = mozbr;
			tr.insertBefore(otd, tr.cells[index]);
		}
		editor.forceRedraw();
		editor.updateToolbar();
	};

	function splitCol(td) {
		var nc = parseInt("" + td.colSpan);
		td.colSpan = 1;
		tr = td.parentNode;
		var ref = td.nextSibling;
		while (--nc > 0) {
			var otd = editor._doc.createElement("td");
			otd.rowSpan = td.rowSpan;
			otd.innerHTML = mozbr;
			tr.insertBefore(otd, ref);
		}
		editor.forceRedraw();
		editor.updateToolbar();
	};

	function splitCell(td) {
		var nc = parseInt("" + td.colSpan);
		splitCol(td);
		var items = td.parentNode.cells;
		var index = td.cellIndex;
		while (nc-- > 0) {
			splitRow(items[index++]);
		}
	};

	function selectNextNode(el) {
		var node = el.nextSibling;
		while (node && node.nodeType != 1) {
			node = node.nextSibling;
		}
		if (!node) {
			node = el.previousSibling;
			while (node && node.nodeType != 1) {
				node = node.previousSibling;
			}
		}
		if (!node) {
			node = el.parentNode;
		}
		editor.selectNodeContents(node);
	};

	switch (button_id) {
		// ROWS

	case "TO-row-insert-above":
	case "TO-row-insert-under":
		var tr = this.getClosest("tr");
		if (!tr) {
			break;
		}
		var otr = tr.cloneNode(true);
		clearRow(otr);
		tr.parentNode.insertBefore(otr, /under/.test(button_id) ? tr.nextSibling : tr);
		editor.forceRedraw();
		editor.focusEditor();
		break;
	case "TO-row-delete":
		var tr = this.getClosest("tr");
		if (!tr) {
			break;
		}
		var par = tr.parentNode;
		if (par.rows.length == 1) {
			while (par.tagName.toLowerCase() != 'table')
				par = par.parentNode;
			HTMLArea.removeFromParent(par);
			break;
		}
		// set the caret first to a position that doesn't
		// disappear.
		selectNextNode(tr);
		par.removeChild(tr);
		editor.forceRedraw();
		editor.focusEditor();
		editor.updateToolbar();
		break;
	case "TO-row-split":
		var td = this.getClosest("td");
		if (!td) {
			break;
		}
		splitRow(td);
		break;

		// COLUMNS

	case "TO-col-insert-before":
	case "TO-col-insert-after":
		var td = this.getClosest("td");
		if (!td) {
			break;
		}
		var rows = td.parentNode.parentNode.rows;
		var index = td.cellIndex;
		for (var i = rows.length; --i >= 0;) {
      /*
      var tr = rows;
      var otd = tr.insertCell(index + (/after/.test(button_id) ? 1 : 0));
      otd.innerHTML = mozbr;
      */
			var tr = rows[i];
			var ref = tr.cells[index + (/after/.test(button_id) ? 1 : 0)];
			// >MT: fix issue when accessing out of bounds
			if (typeof ref == "undefined") ref = null;
			// <MT
			var otd = editor._doc.createElement("td");
			otd.innerHTML = mozbr;
			tr.insertBefore(otd, ref);

		}
		editor.focusEditor();
		break;
	case "TO-col-split":
		var td = this.getClosest("td");
		if (!td) {
			break;
		}
		splitCol(td);
		break;
	case "TO-col-delete":
		var td = this.getClosest("td");
		if (!td) {
			break;
		}
		var index = td.cellIndex;
		if (td.parentNode.cells.length == 1) {
			while (td.tagName.toLowerCase() != 'table')
				td = td.parentNode;
			HTMLArea.removeFromParent(td);
			break;
		}
		// set the caret first to a position that doesn't disappear
		selectNextNode(td);
		var rows = td.parentNode.parentNode.rows;
		for (var i = rows.length; --i >= 0;) {
			var tr = rows[i];
			tr.removeChild(tr.cells[index]);
		}
		editor.forceRedraw();
		editor.focusEditor();
		editor.updateToolbar();
		break;

		// CELLS

	case "TO-cell-split":
		var td = this.getClosest("td");
		if (!td) {
			break;
		}
		splitCell(td);
		break;
	case "TO-cell-insert-before":
	case "TO-cell-insert-after":
		var td = this.getClosest("td");
		if (!td) {
			break;
		}
		var tr = td.parentNode;
		var otd = editor._doc.createElement("td");
		otd.innerHTML = mozbr;
		tr.insertBefore(otd, /after/.test(button_id) ? td.nextSibling : td);
		editor.forceRedraw();
		editor.focusEditor();
		break;
	case "TO-cell-delete":
		var td = this.getClosest("td");
		if (!td) {
			break;
		}
		if (td.parentNode.cells.length == 1) {
			while (td.tagName.toLowerCase() != 'table')
				td = td.parentNode;
			HTMLArea.removeFromParent(td);
			break;
		}
		// set the caret first to a position that doesn't disappear
		selectNextNode(td);
		td.parentNode.removeChild(td);
		editor.forceRedraw();
		editor.updateToolbar();
		break;
	case "TO-cell-merge":
		// !! FIXME: Mozilla specific !!
		var sel = editor._getSelection();
		var range, i = 0;
		var rows = [];
		var row = null;
		var cells = null;
		if (!HTMLArea.is_ie) {
			try {
				while (range = sel.getRangeAt(i++)) {
					var td = range.startContainer.childNodes[range.startOffset];
					if (td.parentNode != row) {
						row = td.parentNode;
						(cells) && rows.push(cells);
						cells = [];
					}
					cells.push(td);
				}
			} catch(e) {/* finished walking through selection */}
			rows.push(cells);
		} else {
			// Internet Explorer "browser"
			var td = this.getClosest("td");
			if (!td) {
				alert(HTMLArea._lc("Please click into some cell", "TableOperations"));
				break;
			}
			var tr = td.parentElement;
			var no_cols = prompt(HTMLArea._lc("How many columns would you like to merge?", "TableOperations"), 2);
			if (!no_cols) {
				// cancelled
				break;
			}
			var no_rows = prompt(HTMLArea._lc("How many rows would you like to merge?", "TableOperations"), 2);
			if (!no_rows) {
				// cancelled
				break;
			}
			var cell_index = td.cellIndex;
			while (no_rows-- > 0) {
				td = tr.cells[cell_index];
				cells = [td];
				for (var i = 1; i < no_cols; ++i) {
					td = td.nextSibling;
					if (!td) {
						break;
					}
					cells.push(td);
				}
				rows.push(cells);
				tr = tr.nextSibling;
				if (!tr) {
					break;
				}
			}
		}
		var HTML = "";
		for (i = 0; i < rows.length; ++i) {
			// i && (HTML += "<br />");
			var cells = rows[i];
			for (var j = 0; j < cells.length; ++j) {
				// j && (HTML += "&nbsp;");
				var cell = cells[j];
				HTML += cell.innerHTML;
				(i || j) && (cell.parentNode.removeChild(cell));
			}
		}
		var td = rows[0][0];
		td.innerHTML = HTML;
		td.rowSpan = rows.length;
		td.colSpan = rows[0].length;
		editor.selectNodeContents(td);
		editor.forceRedraw();
		editor.focusEditor();
		break;

		// PROPERTIES

	case "TO-table-prop":
		this.dialogTableProperties();
		break;

	case "TO-row-prop":
		this.dialogRowCellProperties(false);
		break;

	case "TO-cell-prop":
		this.dialogRowCellProperties(true);
		break;

	default:
		alert("Button [" + button_id + "] not yet implemented");
	}
};

// the list of buttons added by this plugin
TableOperations.btnList = [
	// table properties button
    ["table-prop",       "table", "Table properties"],
	null,			// separator

	// ROWS
	["row-prop",         "tr", "Row properties"],
	["row-insert-above", "tr", "Insert row before"],
	["row-insert-under", "tr", "Insert row after"],
	["row-delete",       "tr", "Delete row"],
	["row-split",        "td[rowSpan!=1]", "Split row"],
	null,

	// COLS
	["col-insert-before", "td", "Insert column before"],
	["col-insert-after",  "td", "Insert column after"],
	["col-delete",        "td", "Delete column"],
	["col-split",         "td[colSpan!=1]", "Split column"],
	null,

	// CELLS
	["cell-prop",          "td", "Cell properties"],
	["cell-insert-before", "td", "Insert cell before"],
	["cell-insert-after",  "td", "Insert cell after"],
	["cell-delete",        "td", "Delete cell"],
	["cell-merge",         "tr", "Merge cells"],
	["cell-split",         "td[colSpan!=1,rowSpan!=1]", "Split cell"]
	];



//// GENERIC CODE [style of any element; this should be moved into a separate
//// file as it'll be very useful]
//// BEGIN GENERIC CODE -----------------------------------------------------

TableOperations.getLength = function(value) {
	var len = parseInt(value);
	if (isNaN(len)) {
		len = "";
	}
	return len;
};

// Applies the style found in "params" to the given element.
TableOperations.processStyle = function(params, element) {
	var style = element.style;
	for (var i in params) {
    if(typeof params[i] == 'function') continue;
		var val = params[i];
		switch (i) {
		case "f_st_backgroundColor":
			style.backgroundColor = val;
			break;
		case "f_st_color":
			style.color = val;
			break;
		case "f_st_backgroundImage":
			if (/\S/.test(val)) {
				style.backgroundImage = "url(" + val + ")";
			} else {
				style.backgroundImage = "none";
			}
			break;
		case "f_st_borderWidth":
			style.borderWidth = val;
			break;
		case "f_st_borderStyle":
			style.borderStyle = val;
			break;
		case "f_st_borderColor":
			style.borderColor = val;
			break;
		case "f_st_borderCollapse":
			style.borderCollapse = val ? "collapse" : "separate";
			break;
		case "f_st_width":
			if (/\S/.test(val)) {
				style.width = val + params["f_st_widthUnit"];
			} else {
				style.width = "";
			}
			break;
		case "f_st_height":
			if (/\S/.test(val)) {
				style.height = val + params["f_st_heightUnit"];
			} else {
				style.height = "";
			}
			break;
		case "f_st_textAlign":
			if (val == "char") {
				var ch = params["f_st_textAlignChar"];
				if (ch == '"') {
					ch = '\\"';
				}
				style.textAlign = '"' + ch + '"';
			} else {
				style.textAlign = val;
			}
			break;
		case "f_st_verticalAlign":
			style.verticalAlign = val;
			break;
		case "f_st_float":
			style.cssFloat = val;
			break;
// 		case "f_st_margin":
// 			style.margin = val + "px";
// 			break;
// 		    case "f_st_padding":
// 			style.padding = val + "px";
// 			break;
		}
	}
};

// Returns an HTML element for a widget that allows color selection.  That is,
// a button that contains the given color, if any, and when pressed will popup
// the sooner-or-later-to-be-rewritten select_color.html dialog allowing user
// to select some color.  If a color is selected, an input field with the name
// "f_st_"+name will be updated with the color value in #123456 format.
TableOperations.createColorButton = function(doc, editor, color, name) {
	if (!color) {
		color = "";
	} else if (!/#/.test(color)) {
		color = HTMLArea._colorToRgb(color);
	}

	var df = doc.createElement("span");
 	var field = doc.createElement("input");
	field.type = "hidden";
	df.appendChild(field);
 	field.name = "f_st_" + name;
	field.value = color;
	var button = doc.createElement("span");
	button.className = "buttonColor";
	df.appendChild(button);
	var span = doc.createElement("span");
	span.className = "chooser";
	span.innerHTML = "&nbsp;"; //MT royk: this line is required for IE to render this span correctly
	// >MT: fix for special cases
	try { span.style.backgroundColor = color; } catch (e) {}
	// <MT
	button.appendChild(span);
	button.onmouseover = function() { if (!this.disabled) { this.className += " buttonColor-hilite"; }};
	button.onmouseout = function() { if (!this.disabled) { this.className = "buttonColor"; }};
	span.onclick = function() {
		if (this.parentNode.disabled) {
			return false;
		}
		var dialog = "select_color.php";
		dialog += name == "color" ? "?type=fg" : "?type=bg";
		editor._popupDialog(400, 206, dialog, function(color) {
			if (color) {
				span.style.backgroundColor = "#" + color;
				field.value = "#" + color;
			}
		}, color);
	};
	var span2 = doc.createElement("span");
	span2.innerHTML = "&#x00d7;";
	span2.className = "nocolor";
	span2.title = HTMLArea._lc("Unset color", "TableOperations");
	button.appendChild(span2);
	span2.onmouseover = function() { if (!this.parentNode.disabled) { this.className += " nocolor-hilite"; }};
	span2.onmouseout = function() { if (!this.parentNode.disabled) { this.className = "nocolor"; }};
	span2.onclick = function() {
		span.style.backgroundColor = "";
		field.value = "";
	};
	return df;
};

TableOperations.createStyleLayoutFieldset = function(doc, editor, el) {
	var fieldset = doc.createElement("fieldset");
	var legend = doc.createElement("legend");
	fieldset.appendChild(legend);
	legend.innerHTML = HTMLArea._lc("Layout", "TableOperations");
	var table = doc.createElement("table");
	fieldset.appendChild(table);
	table.style.width = "100%";
	var tbody = doc.createElement("tbody");
	table.appendChild(tbody);

	var tagname = el.tagName.toLowerCase();
	var tr, td, input, select, option, options, i;

	if (tagname != "td" && tagname != "tr" && tagname != "th") {
		tr = doc.createElement("tr");
		tbody.appendChild(tr);
		td = doc.createElement("td");
		td.className = "label";
		tr.appendChild(td);
		td.innerHTML = HTMLArea._lc("Float", "TableOperations") + ":";
		td = doc.createElement("td");
		tr.appendChild(td);
		select = doc.createElement("select");
		td.appendChild(select);
		select.name = "f_st_float";
		options = ["None", "Left", "Right"];
		for (var i = 0; i < options.length; ++i) {
			var Val = options[i];
			var val = options[i].toLowerCase();
			option = doc.createElement("option");
			option.innerHTML = HTMLArea._lc(Val, "TableOperations");
			option.value = val;
			option.selected = (("" + el.style.cssFloat).toLowerCase() == val);
			select.appendChild(option);
		}
	}

	tr = doc.createElement("tr");
	tbody.appendChild(tr);
	td = doc.createElement("td");
	td.className = "label";
	tr.appendChild(td);
	td.innerHTML = HTMLArea._lc("Width", "TableOperations") + ":";
	td = doc.createElement("td");
	tr.appendChild(td);
	input = doc.createElement("input");
	input.type = "text";
	input.value = TableOperations.getLength(el.style.width);
	input.size = "5";
	input.name = "f_st_width";
	input.style.marginRight = "0.5em";
	if (tagname == "tr") {
		input.disabled = true;
	}
	td.appendChild(input);
	select = doc.createElement("select");
	select.name = "f_st_widthUnit";
	option = doc.createElement("option");
	option.innerHTML = HTMLArea._lc("percent", "TableOperations");
	option.value = "%";
	option.selected = /%/.test(el.style.width);
	select.appendChild(option);
	option = doc.createElement("option");
	option.innerHTML = HTMLArea._lc("pixels", "TableOperations");
	option.value = "px";
	option.selected = /px/.test(el.style.width);
	select.appendChild(option);
	if (tagname == "tr") {
		select.disabled = true;
	}
	td.appendChild(select);

	select.style.marginRight = "0.5em";
	td.appendChild(doc.createTextNode(HTMLArea._lc("Text align", "TableOperations") + ":"));
	select = doc.createElement("select");
	select.style.marginLeft = select.style.marginRight = "0.5em";
	td.appendChild(select);
	select.name = "f_st_textAlign";
	options = ["Left", "Center", "Right", "Justify"];
	if (tagname == "td") {
		options.push("Char");
	}
	input = doc.createElement("input");
	input.name = "f_st_textAlignChar";
	input.id = "f_st_textAlignChar";
	input.size = "1";
	input.style.fontFamily = "monospace";
	td.appendChild(input);
	for (var i = 0; i < options.length; ++i) {
		var Val = options[i];
		var val = Val.toLowerCase();
		option = doc.createElement("option");
		option.value = val;
		option.innerHTML = HTMLArea._lc(Val, "TableOperations");
		option.selected = (el.style.textAlign.toLowerCase() == val);
		select.appendChild(option);
	}
	function setCharVisibility(value) {
		// Karen Ananiev
		var inputField = document.getElementsByName("f_st_textAlignChar");
		// inputField.length == 0 when element is being generated and == 1 when event occurs
		var inputChar = (1 == inputField.length) ? inputField[0] : input;
		inputChar.style.visibility = value ? "visible" : "hidden";
		//input.style.visibility = value ? "visible" : "hidden";
		if (value) {
			inputChar.focus();
			inputChar.select();
		}
	};
	select.onchange = function() { setCharVisibility(this.value == "char"); };
	setCharVisibility(select.value == "char");

	tr = doc.createElement("tr");
	tbody.appendChild(tr);
	td = doc.createElement("td");
	td.className = "label";
	tr.appendChild(td);
	td.innerHTML = HTMLArea._lc("Height", "TableOperations") + ":";
	td = doc.createElement("td");
	tr.appendChild(td);
	input = doc.createElement("input");
	input.type = "text";
	input.value = TableOperations.getLength(el.style.height);
	input.size = "5";
	input.name = "f_st_height";
	input.style.marginRight = "0.5em";
	td.appendChild(input);
	select = doc.createElement("select");
	select.name = "f_st_heightUnit";
	option = doc.createElement("option");
	option.innerHTML = HTMLArea._lc("percent", "TableOperations");
	option.value = "%";
	option.selected = /%/.test(el.style.height);
	select.appendChild(option);
	option = doc.createElement("option");
	option.innerHTML = HTMLArea._lc("pixels", "TableOperations");
	option.value = "px";
	option.selected = /px/.test(el.style.height);
	select.appendChild(option);
	td.appendChild(select);

	select.style.marginRight = "0.5em";
	td.appendChild(doc.createTextNode(HTMLArea._lc("Vertical align", "TableOperations") + ":"));
	select = doc.createElement("select");
	select.name = "f_st_verticalAlign";
	select.style.marginLeft = "0.5em";
	td.appendChild(select);
	options = ["Top", "Middle", "Bottom", "Baseline"];
	for (var i = 0; i < options.length; ++i) {
		var Val = options[i];
		var val = Val.toLowerCase();
		option = doc.createElement("option");
		option.value = val;
		option.innerHTML = HTMLArea._lc(Val, "TableOperations");
		option.selected = (el.style.verticalAlign.toLowerCase() == val);
		select.appendChild(option);
	}

	return fieldset;
};

// Returns an HTML element containing the style attributes for the given
// element.  This can be easily embedded into any dialog; the functionality is
// also provided.
TableOperations.createStyleFieldset = function(doc, editor, el) {
	var fieldset = doc.createElement("fieldset");
	var legend = doc.createElement("legend");
	fieldset.appendChild(legend);
	legend.innerHTML = HTMLArea._lc("CSS Style", "TableOperations");
	var table = doc.createElement("table");
	fieldset.appendChild(table);
	table.style.width = "100%";
	var tbody = doc.createElement("tbody");
	table.appendChild(tbody);

	var tr, td, input, select, option, options, i;

	tr = doc.createElement("tr");
	tbody.appendChild(tr);
	td = doc.createElement("td");
	tr.appendChild(td);
	td.className = "label";
	td.innerHTML = HTMLArea._lc("Background", "TableOperations") + ":";
	td = doc.createElement("td");
	tr.appendChild(td);
	var df = TableOperations.createColorButton(doc, editor, el.style.backgroundColor, "backgroundColor");
	df.firstChild.nextSibling.style.marginRight = "0.5em";
	td.appendChild(df);
	td.appendChild(doc.createTextNode(HTMLArea._lc("Image URL", "TableOperations") + ": "));
	input = doc.createElement("input");
	input.type = "text";
	input.name = "f_st_backgroundImage";
	if (el.style.backgroundImage.match(/url\(\s*(.*?)\s*\)/)) {
		input.value = RegExp.$1;
	}
	// input.style.width = "100%";
	td.appendChild(input);

	tr = doc.createElement("tr");
	tbody.appendChild(tr);
	td = doc.createElement("td");
	tr.appendChild(td);
	td.className = "label";
	td.innerHTML = HTMLArea._lc("FG Color", "TableOperations") + ":";
	td = doc.createElement("td");
	tr.appendChild(td);
	td.appendChild(TableOperations.createColorButton(doc, editor, el.style.color, "color"));

	// for better alignment we include an invisible field.
	input = doc.createElement("input");
	input.style.visibility = "hidden";
	input.type = "text";
	td.appendChild(input);

	tr = doc.createElement("tr");
	tbody.appendChild(tr);
	td = doc.createElement("td");
	tr.appendChild(td);
	td.className = "label";
	td.innerHTML = HTMLArea._lc("Border", "TableOperations") + ":";
	td = doc.createElement("td");
	tr.appendChild(td);

	var colorButton = TableOperations.createColorButton(doc, editor, el.style.borderColor, "borderColor");
	var btn = colorButton.firstChild.nextSibling;
	td.appendChild(colorButton);
	// borderFields.push(btn);
	btn.style.marginRight = "0.5em";

	select = doc.createElement("select");
	var borderFields = [];
	td.appendChild(select);
	select.name = "f_st_borderStyle";
	options = ["none", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"];
	var currentBorderStyle = el.style.borderStyle;
	// Gecko reports "solid solid solid solid" for "border-style: solid".
	// That is, "top right bottom left" -- we only consider the first
	// value.
	(currentBorderStyle.match(/([^\s]*)\s/)) && (currentBorderStyle = RegExp.$1);
	for (var i in options) {
    if(typeof options[i] == 'function') continue;
		var val = options[i];
		option = doc.createElement("option");
		option.value = val;
		option.innerHTML = val;
		(val == currentBorderStyle) && (option.selected = true);
		select.appendChild(option);
	}
	select.style.marginRight = "0.5em";
	function setBorderFieldsStatus(value) {
		for (var i = 0; i < borderFields.length; ++i) {
			var el = borderFields[i];
			el.style.visibility = value ? "hidden" : "visible";
			if (!value && (el.tagName.toLowerCase() == "input")) {
				el.focus();
				el.select();
			}
		}
	};
	select.onchange = function() { setBorderFieldsStatus(this.value == "none"); };

	input = doc.createElement("input");
	borderFields.push(input);
	input.type = "text";
	input.name = "f_st_borderWidth";
	input.value = TableOperations.getLength(el.style.borderWidth);
	input.size = "5";
	td.appendChild(input);
	input.style.marginRight = "0.5em";
	var span = doc.createElement("span");
	span.innerHTML = HTMLArea._lc("pixels", "TableOperations");
	td.appendChild(span);
	borderFields.push(span);

	setBorderFieldsStatus(select.value == "none");

	if (el.tagName.toLowerCase() == "table") {
		// the border-collapse style is only for tables
		tr = doc.createElement("tr");
		tbody.appendChild(tr);
		td = doc.createElement("td");
		td.className = "label";
		tr.appendChild(td);
		input = doc.createElement("input");
		input.type = "checkbox";
		input.name = "f_st_borderCollapse";
		input.id = "f_st_borderCollapse";
		var val = (/collapse/i.test(el.style.borderCollapse));
		input.checked = val ? 1 : 0;
		td.appendChild(input);

		td = doc.createElement("td");
		tr.appendChild(td);
		var label = doc.createElement("label");
		label.htmlFor = "f_st_borderCollapse";
		label.innerHTML = HTMLArea._lc("Collapsed borders", "TableOperations");
		td.appendChild(label);
	}

// 	tr = doc.createElement("tr");
// 	tbody.appendChild(tr);
// 	td = doc.createElement("td");
// 	td.className = "label";
// 	tr.appendChild(td);
// 	td.innerHTML = HTMLArea._lc("Margin", "TableOperations") + ":";
// 	td = doc.createElement("td");
// 	tr.appendChild(td);
// 	input = doc.createElement("input");
// 	input.type = "text";
// 	input.size = "5";
// 	input.name = "f_st_margin";
// 	td.appendChild(input);
// 	input.style.marginRight = "0.5em";
// 	td.appendChild(doc.createTextNode(HTMLArea._lc("Padding", "TableOperations") + ":"));

// 	input = doc.createElement("input");
// 	input.type = "text";
// 	input.size = "5";
// 	input.name = "f_st_padding";
// 	td.appendChild(input);
// 	input.style.marginLeft = "0.5em";
// 	input.style.marginRight = "0.5em";
// 	td.appendChild(doc.createTextNode(HTMLArea._lc("pixels", "TableOperations")));

	return fieldset;
};

//// END GENERIC CODE -------------------------------------------------------

/**
 * Add an empty css_style to Config object's prototype
 *  the format is { '.className' : 'Description' }
 */

HTMLArea.Config.prototype.css_style = { };

/**
 * This method loads an external stylesheet and uses it in the stylist
 */
HTMLArea.Config.prototype.stylistLoadStylesheet = function(url, altnames)
{
  if(!altnames) altnames = { };
  var newStyles = HTMLArea.ripStylesFromCSSFile(url);
  for(var i in newStyles)
  {
    if(altnames[i])
    {
      this.css_style[i] = altnames[i];
    }
    else
    {
      this.css_style[i] = newStyles[i];
    }
  }
  this.pageStyleSheets[this.pageStyleSheets.length] = url;
};

/**
 * This method takes raw style definitions and uses them in the stylist
 */
HTMLArea.Config.prototype.stylistLoadStyles = function(styles, altnames)
{
  if(!altnames) altnames = { };
  var newStyles = HTMLArea.ripStylesFromCSSString(styles);
  for(var i in newStyles)
  {
    if(altnames[i])
    {
      this.css_style[i] = altnames[i];
    }
    else
    {
      this.css_style[i] = newStyles[i];
    }
  }
  this.pageStyle += styles;
};



/**
 * Fill the stylist panel with styles that may be applied to the current selection.  Styles
 * are supplied in the css_style property of the HTMLArea.Config object, which is in the format
 * { '.className' : 'Description' }
 * classes that are defined on a specific tag (eg 'a.email_link') are only shown in the panel
 *    when an element of that type is selected.
 * classes that are defined with selectors/psuedoclasses (eg 'a.email_link:hover') are never
 *    shown (if you have an 'a.email_link' without the pseudoclass it will be shown of course)
 * multiple classes (eg 'a.email_link.staff_member') are shown as a single class, and applied
 *    to the element as multiple classes (class="email_link staff_member")
 * you may click a class name in the stylist panel to add it, and click again to remove it
 * you may add multiple classes to any element
 * spans will be added where no single _and_entire_ element is selected
 */
HTMLArea.prototype._fillStylist = function()
{
  if(!this._stylist) return false;
  this._stylist.innerHTML = '<h1>'+HTMLArea._lc('Styles', 'Stylist')+'</h1>';

  var may_apply = true;
  var sel       = this._getSelection();

  // What is applied
  // var applied = this._getAncestorsClassNames(this._getSelection());

  // Get an active element
  var active_elem = this._activeElement(sel);

  for(var x in this.config.css_style)
  {
    var tag   = null;
    var className = x.trim();
    var applicable = true;
    var apply_to   = active_elem;

    if(applicable && /[^a-zA-Z0-9_.-]/.test(className))
    {
      applicable = false; // Only basic classes are accepted, no selectors, etc.. presumed
                          // that if you have a.foo:visited you'll also have a.foo
      // alert('complex');
    }

    if(className.indexOf('.') < 0)
    {
      // No class name, just redefines a tag
      applicable = false;
    }

    if(applicable && (className.indexOf('.') > 0))
    {
      // requires specific html tag
      tag = className.substring(0, className.indexOf('.')).toLowerCase();
      className = className.substring(className.indexOf('.'), className.length);

      // To apply we must have an ancestor tag that is the right type
      if(active_elem != null && active_elem.tagName.toLowerCase() == tag)
      {
        applicable = true;
        apply_to = active_elem;
      }
      else
      {
        if(this._getFirstAncestor(this._getSelection(), [tag]) != null)
        {
          applicable = true;
          apply_to = this._getFirstAncestor(this._getSelection(), [tag]);
        }
        else
        {
          // alert (this._getFirstAncestor(this._getSelection(), tag));
          // If we don't have an ancestor, but it's a div/span/p/hx stle, we can make one
          if(( tag == 'div' || tag == 'span' || tag == 'p'
              || (tag.substr(0,1) == 'h' && tag.length == 2 && tag != 'hr')))
          {
            if(!this._selectionEmpty(this._getSelection()))
            {
              applicable = true;
              apply_to = 'new';
            }
            else
            {
              // See if we can get a paragraph or header that can be converted
              apply_to = this._getFirstAncestor(sel, ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7']);
              if(apply_to != null)
              {
                applicable = true;
              }
            }
          }
          else
          {
            applicable = false;
          }
        }
      }
    }

    if(applicable)
    {
      // Remove the first .
      className = className.substring(className.indexOf('.'), className.length);

      // Replace any futher ones with spaces (for multiple class definitions)
      className = className.replace('.', ' ');

      if(apply_to == null)
      {
        if(this._selectionEmpty(this._getSelection()))
        {
          // Get the previous element and apply to that
          apply_to = this._getFirstAncestor(this._getSelection(), null);
        }
        else
        {
          apply_to = 'new';
          tag      = 'span';
        }
      }
    }

    var applied    = (this._ancestorsWithClasses(sel, tag, className).length > 0 ? true : false);
    var applied_to = this._ancestorsWithClasses(sel, tag, className);

    if(applicable)
    {
      var anch = document.createElement('a');
      anch._stylist_className = className.trim();
      anch._stylist_applied   = applied;
      anch._stylist_appliedTo = applied_to;
      anch._stylist_applyTo = apply_to;
      anch._stylist_applyTag = tag;

      anch.innerHTML = this.config.css_style[x];
      anch.href = 'javascript:void(0)';
      var editor = this;
      anch.onclick = function()
      {
        if(this._stylist_applied == true)
        {
          editor._stylistRemoveClasses(this._stylist_className, this._stylist_appliedTo);
        }
        else
        {
          editor._stylistAddClasses(this._stylist_applyTo, this._stylist_applyTag, this._stylist_className);
        }
        return false;
      }

      anch.style.display = 'block';
      anch.style.paddingLeft = '3px';
      anch.style.paddingTop = '1px';
      anch.style.paddingBottom = '1px';
      anch.style.textDecoration = 'none';

      if(applied)
      {
        anch.style.background = 'Highlight';
        anch.style.color = 'HighlightText';
      }

      this._stylist.appendChild(anch);
    }
  }
};


/**
 * Add the given classes (space seperated list) to the currently selected element
 * (will add a span if none selected)
 */
HTMLArea.prototype._stylistAddClasses = function(el, tag, classes)
  {
    if(el == 'new')
    {
      this.insertHTML('<' + tag + ' class="' + classes + '">' + this.getSelectedHTML() + '</' + tag + '>');
    }
    else
    {
      if(tag != null && el.tagName.toLowerCase() != tag)
      {
        // Have to change the tag!
        var new_el = this.switchElementTag(el, tag);

        if(typeof el._stylist_usedToBe != 'undefined')
        {
          new_el._stylist_usedToBe = el._stylist_usedToBe;
          new_el._stylist_usedToBe[new_el._stylist_usedToBe.length] = {'tagName' : el.tagName, 'className' : el.getAttribute('class')};
        }
        else
        {
          new_el._stylist_usedToBe = [{'tagName' : el.tagName, 'className' : el.getAttribute('class')}];
        }

        HTMLArea.addClasses(new_el, classes);
      }
      else
      {
        HTMLArea._addClasses(el, classes);
      }
    }
    this.focusEditor();
    this.updateToolbar();
  };

/**
 * Remove the given classes (space seperated list) from the given elements (array of elements)
 */
HTMLArea.prototype._stylistRemoveClasses = function(classes, from)
  {
    for(var x = 0; x < from.length; x++)
    {
      this._stylistRemoveClassesFull(from[x], classes);
    }
    this.focusEditor();
    this.updateToolbar();
  };

HTMLArea.prototype._stylistRemoveClassesFull = function(el, classes)
{
  if(el != null)
  {
    var thiers = el.className.trim().split(' ');
    var new_thiers = [ ];
    var ours   = classes.split(' ');
    for(var x = 0; x < thiers.length; x++)
    {
      var exists = false;
      for(var i = 0; exists == false && i < ours.length; i++)
      {
        if(ours[i] == thiers[x])
        {
          exists = true;
        }
      }
      if(exists == false)
      {
        new_thiers[new_thiers.length] = thiers[x];
      }
    }

    if(new_thiers.length == 0 && el._stylist_usedToBe && el._stylist_usedToBe.length > 0 && el._stylist_usedToBe[el._stylist_usedToBe.length - 1].className != null)
    {
      // Revert back to what we were IF the classes are identical
      var last_el = el._stylist_usedToBe[el._stylist_usedToBe.length - 1];
      var last_classes = HTMLArea.arrayFilter(last_el.className.trim().split(' '), function(c) { if (c == null || c.trim() == '') { return false;} return true; });

      if(
        (new_thiers.length == 0)
        ||
        (
        HTMLArea.arrayContainsArray(new_thiers, last_classes)
        && HTMLArea.arrayContainsArray(last_classes, new_thiers)
        )
      )
      {
        el = this.switchElementTag(el, last_el.tagName);
        new_thiers = last_classes;
      }
      else
      {
        // We can't rely on the remembered tags any more
        el._stylist_usedToBe = [ ];
      }
    }

    if(     new_thiers.length > 0
        ||  el.tagName.toLowerCase() != 'span'
        || (el.id && el.id != '')
      )
    {
      el.className = new_thiers.join(' ').trim();
    }
    else
    {
      // Must be a span with no classes and no id, so we can splice it out
      var prnt = el.parentNode;
      var childs = el.childNodes;
      for(var x = 0; x < childs.length; x++)
      {
        prnt.insertBefore(childs[x], el);
      }
      prnt.removeChild(el);
    }
  }
};

/**
 * Change the tag of an element
 */
HTMLArea.prototype.switchElementTag = function(el, tag)
{
  var prnt = el.parentNode;
  var new_el = this._doc.createElement(tag);

  if(HTMLArea.is_ie || el.hasAttribute('id'))    new_el.setAttribute('id', el.getAttribute('id'));
  if(HTMLArea.is_ie || el.hasAttribute('style')) new_el.setAttribute('style', el.getAttribute('style'));

  var childs = el.childNodes;
  for(var x = 0; x < childs.length; x++)
  {
    new_el.appendChild(childs[x].cloneNode(true));
  }

  prnt.insertBefore(new_el, el);
  new_el._stylist_usedToBe = [el.tagName];
  prnt.removeChild(el);
  this.selectNodeContents(new_el);
  return new_el;
};

HTMLArea.prototype._getAncestorsClassNames = function(sel)
{
  // Scan upwards to find a block level element that we can change or apply to
  var prnt = this._activeElement(sel);
  if(prnt == null)
  {
    prnt = (HTMLArea.is_ie ? this._createRange(sel).parentElement() : this._createRange(sel).commonAncestorContainer);
  }

  var classNames = [ ];
  while(prnt)
  {
    if(prnt.nodeType == 1)
    {
      var classes = prnt.className.trim().split(' ');
      for(var x = 0; x < classes.length; x++)
      {
        classNames[classNames.length] = classes[x];
      }

      if(prnt.tagName.toLowerCase() == 'body') break;
      if(prnt.tagName.toLowerCase() == 'table'  ) break;
    }
      prnt = prnt.parentNode;
  }

  return classNames;
};

HTMLArea.prototype._ancestorsWithClasses = function(sel, tag, classes)
{
  var ancestors = [ ];
  var prnt = this._activeElement(sel);
  if(prnt == null)
  {
    try
    {
      prnt = (HTMLArea.is_ie ? this._createRange(sel).parentElement() : this._createRange(sel).commonAncestorContainer);
    }
    catch(e)
    {
      return ancestors;
    }
  }
  var search_classes = classes.trim().split(' ');

  while(prnt)
  {
    if(prnt.nodeType == 1)
    {
      if(tag == null || prnt.tagName.toLowerCase() == tag)
      {
        var classes = prnt.className.trim().split(' ');
        var found_all = true;
        for(var i = 0; i < search_classes.length; i++)
        {
          var found_class = false;
          for(var x = 0; x < classes.length; x++)
          {
            if(search_classes[i] == classes[x])
            {
              found_class = true;
              break;
            }
          }

          if(!found_class)
          {
            found_all = false;
            break;
          }
        }

        if(found_all) ancestors[ancestors.length] = prnt;
      }
      if(prnt.tagName.toLowerCase() == 'body')    break;
      if(prnt.tagName.toLowerCase() == 'table'  ) break;
    }
    prnt = prnt.parentNode;
  }

  return ancestors;
};


HTMLArea.ripStylesFromCSSFile = function(URL)
{
  var css = HTMLArea._geturlcontent(URL);
  return HTMLArea.ripStylesFromCSSString(css);
};

HTMLArea.ripStylesFromCSSString = function(css)
{
  // We are only interested in the selectors, the rules are not important
  //  so we'll drop out all coments and rules
  RE_comment = /\/\*(.|\r|\n)*?\*\//g;
  RE_rule    = /\{(.|\r|\n)*?\}/g;
  css = css.replace(RE_comment, '');
  css = css.replace(RE_rule, ',');

  // And split on commas
  css = css.split(',');

  // And add those into our structure
  var selectors = { };
  for(var x = 0; x < css.length; x++)
  {
    if(css[x].trim())
    {
      selectors[css[x].trim()] = css[x].trim();
    }
  }


  return selectors;
};

// Make our right side panel and insert appropriatly
function Stylist(editor, args)
{
  this.editor = editor;
  // >MT: make sure to remove when recreated
  if (typeof editor._stylist != "undefined" && editor._stylist != null)
    editor.removePanel(editor._stylist);
  // <MT
  editor._stylist = null; // This needs to be changes to be Stylist::_stylist sometime
  editor._stylist = editor.addPanel('right');
  HTMLArea.addClass(editor._stylist, 'stylist');

  var stylist = this;
  editor.notifyOn('modechange',
                  function(e,args)
                  {
                    switch(args.mode)
                    {
                      case 'text':
                      {
                        editor.hidePanel(editor._stylist);
                        break;
                      }
                      case 'wysiwyg':
                      {
                        editor.showPanel(editor._stylist);
                        break;
                      }
                    }
                  }
                  );
};

Stylist._pluginInfo =
{
  name     : "Stylist",
  version  : "1.0",
  developer: "James Sleeman",
  developer_url: "http://www.gogo.co.nz/",
  c_owner      : "Gogo Internet Services",
  license      : "htmlArea",
  sponsor      : "Gogo Internet Services",
  sponsor_url  : "http://www.gogo.co.nz/"
};

Stylist.prototype.onGenerate = function()
{
  var editor = this.editor;
  if(typeof editor.config.css_style == 'undefined' || HTMLArea.objectProperties(editor.config.css_style).length == 0)
  {
    editor.removePanel(editor._stylist);
    editor._stylist = null;
  }
};

Stylist.prototype.onUpdateToolbar = function()
{
  if(this.editor._stylist)
  {
    if(this._timeoutID)
    {
      window.clearTimeout(this._timeoutID);
    }

    var e = this.editor;
    this._timeoutID = window.setTimeout(function() { e._fillStylist(); }, 250);
  }
};

// tabs 2

/**
* @fileoverview By Adam Wright, for The University of Western Australia
*
* Distributed under the same terms as HTMLArea itself.
* This notice MUST stay intact for use (see license.txt).
*
* Heavily modified by Yermo Lamers of DTLink, LLC, College Park, Md., USA.
* For more info see http://www.areaedit.com
*/

/**
* plugin Info
*/

EnterParagraphs._pluginInfo =
	{
  name          : "EnterParagraphs",
  version       : "1.0",
  developer     : "Adam Wright",
  developer_url : "http://www.hipikat.org/",
  sponsor       : "The University of Western Australia",
  sponsor_url   : "http://www.uwa.edu.au/",
  license       : "htmlArea"
	};

// ------------------------------------------------------------------

// "constants"

/**
* Whitespace Regex
*/

EnterParagraphs.prototype._whiteSpace = /^\s*$/;

/**
* The pragmatic list of which elements a paragraph may not contain
*/

EnterParagraphs.prototype._pExclusions = /^(address|blockquote|body|dd|div|dl|dt|fieldset|form|h1|h2|h3|h4|h5|h6|hr|li|noscript|ol|p|pre|table|ul)$/i;

/**
* elements which may contain a paragraph
*/

EnterParagraphs.prototype._pContainers = /^(body|del|div|fieldset|form|ins|map|noscript|object|td|th)$/i;

/**
* Elements which may not contain paragraphs, and would prefer a break to being split
*/

EnterParagraphs.prototype._pBreak = /^(address|pre|blockquote)$/i;

/**
* Elements which may not contain children
*/

EnterParagraphs.prototype._permEmpty = /^(area|base|basefont|br|col|frame|hr|img|input|isindex|link|meta|param)$/i;

/**
* Elements which count as content, as distinct from whitespace or containers
*/

EnterParagraphs.prototype._elemSolid = /^(applet|br|button|hr|img|input|table)$/i;

/**
* Elements which should get a new P, before or after, when enter is pressed at either end
*/

EnterParagraphs.prototype._pifySibling = /^(address|blockquote|del|div|dl|fieldset|form|h1|h2|h3|h4|h5|h6|hr|ins|map|noscript|object|ol|p|pre|table|ul|)$/i;
EnterParagraphs.prototype._pifyForced = /^(ul|ol|dl|table)$/i;

/**
* Elements which should get a new P, before or after a close parent, when enter is pressed at either end
*/

EnterParagraphs.prototype._pifyParent = /^(dd|dt|li|td|th|tr)$/i;

// ---------------------------------------------------------------------

/**
* EnterParagraphs Constructor
*/

function EnterParagraphs(editor)
	{

  this.editor = editor;

	// [STRIP
	// create a ddt debug trace object. There may be multiple editors on
	// the page each EnterParagraphs .. to distinguish which instance
	// is generating the message we tack on the name of the textarea.

	//this.ddt = new DDT( editor._textArea + ":EnterParagraphs Plugin" );

	// uncomment to turn on debugging messages.

	//this.ddt._ddtOn();

	//this.ddt._ddt( "enter-paragraphs.js","23", "EnterParagraphs(): constructor" );

	// STRIP]

  // hook into the event handler to intercept key presses if we are using
	// gecko (Mozilla/FireFox)

  if (HTMLArea.is_gecko)
		{
		//this.ddt._ddt( "enter-paragraphs.js","23", "EnterParagraphs(): we are gecko. Setting event handler." );
    this.onKeyPress = this.__onKeyPress;
		}

	};	// end of constructor.

// ------------------------------------------------------------------

/**
* name member for debugging
*
* This member is used to identify objects of this class in debugging
* messages.
*/

EnterParagraphs.prototype.name = "EnterParagraphs";

/**
* Gecko's a bit lacking in some odd ways...
*/

EnterParagraphs.prototype.insertAdjacentElement = function(ref,pos,el)
	{

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "122", "insertAdjacentElement(): top with pos '" + pos + "' ref:", ref );
	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "122", "insertAdjacentElement(): top with el:", el );

  if ( pos == 'BeforeBegin' )
		{
		ref.parentNode.insertBefore(el,ref);
		}
  else if ( pos == 'AfterEnd' )
		{
		ref.nextSibling ? ref.parentNode.insertBefore(el,ref.nextSibling) : ref.parentNode.appendChild(el);
		}
  else if ( pos == 'AfterBegin' && ref.firstChild )
		{
		ref.insertBefore(el,ref.firstChild);
		}
  else if ( pos == 'BeforeEnd' || pos == 'AfterBegin' )
		{
		ref.appendChild(el);
		}

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "122", "insertAdjacentElement(): bottom with ref:", ref );

	};	// end of insertAdjacentElement()

// ----------------------------------------------------------------

/**
* Passes a global parent node or document fragment to forEachNode
*
* @param root node root node to start search from.
* @param mode string function to apply to each node.
* @param direction string traversal direction "ltr" (left to right) or "rtl" (right_to_left)
* @param init boolean
*/

EnterParagraphs.prototype.forEachNodeUnder = function ( root, mode, direction, init )
	{

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "144", "forEachNodeUnder(): top mode is '" + mode + "' direction is '" + direction + "' starting with root node:", root );

  // Identify the first and last nodes to deal with

  var start, end;

	// nodeType 11 is DOCUMENT_FRAGMENT_NODE which is a container.

  if ( root.nodeType == 11 && root.firstChild )
		{
    start = root.firstChild;
    end = root.lastChild;
	  }
	else
		{
		start = end = root;
		}

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "144", "forEachNodeUnder(): start node is:", start );
	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "144", "forEachNodeUnder(): initial end node is:", end );

	// traverse down the right hand side of the tree getting the last child of the last
	// child in each level until we reach bottom.
  while ( end.lastChild )
		end = end.lastChild;

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "144", "forEachNodeUnder(): end node after descent is:", end );

  return this.forEachNode( start, end, mode, direction, init);

	};	// end of forEachNodeUnder()

// -----------------------------------------------------------------------

/**
* perform a depth first descent in the direction requested.
*
* @param left_node node "start node"
* @param right_node node "end node"
* @param mode string function to apply to each node. cullids or emptyset.
* @param direction string traversal direction "ltr" (left to right) or "rtl" (right_to_left)
* @param init boolean or object.
*/

EnterParagraphs.prototype.forEachNode = function (left_node, right_node, mode, direction, init)
	{

	//this.ddt._ddt( "enter-paragraphs.js", "175", "forEachNode(): top - mode is:" + mode + "' direction '" + direction + "'" );
	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): top - left node is:", left_node );
	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): top - right node is:", right_node );

	// returns "Brother" node either left or right.

  var getSibling = function(elem, direction)
							{
							return ( direction == "ltr" ? elem.nextSibling : elem.previousSibling );
							};

  var getChild = function(elem, direction)
							{
							return ( direction == "ltr" ? elem.firstChild : elem.lastChild );
							};

  var walk, lookup, fnReturnVal;

	// FIXME: init is a boolean in the emptyset case and an object in
	// the cullids case. Used inconsistently.

	var next_node = init;

	// used to flag having reached the last node.

	var done_flag = false;

  // loop ntil we've hit the last node in the given direction.
	// if we're going left to right that's the right_node and visa-versa.

  while ( walk != direction == "ltr" ? right_node : left_node )
		{

    // on first entry, walk here is null. So this is how
		// we prime the loop with the first node.

    if ( !walk )
			{
			walk = direction == "ltr" ? left_node : right_node;

			//this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): !walk - current node is:", walk );
			}
    else
			{

			// is there a child node?

      if ( getChild(walk,direction) )
				{

				// descend down into the child.

				walk = getChild(walk,direction);

				//this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode():descending to child node:", walk );

				}
      else
				{

				// is there a sibling node on this level?

        if ( getSibling(walk,direction) )
					{

					// move to the sibling.

					walk = getSibling(walk,direction);

					//this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): moving to sibling node:", walk );

					}
        else
					{
          lookup = walk;

					// climb back up the tree until we find a level where we are not the end
					// node on the level (i.e. that we have a sibling in the direction
					// we are searching) or until we reach the end.

          while ( !getSibling(lookup,direction) && lookup != (direction == "ltr" ? right_node : left_node) )
						{
						lookup = lookup.parentNode;
						}

					// did we find a level with a sibling?

          // walk = ( lookup.nextSibling ? lookup.nextSibling : lookup ) ;

          walk = ( getSibling(lookup,direction) ? getSibling(lookup,direction) : lookup ) ;

					//this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): climbed back up (or found right node):", walk );

			    }
				}

			}	// end of else walk.

		// have we reached the end? either as a result of the top while loop or climbing
		// back out above.

		done_flag = (walk==( direction == "ltr" ? right_node : left_node));

		// call the requested function on the current node. Functions
		// return an array.
		//
		// Possible functions are _fenCullIds, _fenEmptySet
		//
		// The situation is complicated by the fact that sometimes we want to
		// return the base node and sometimes we do not.
		//
		// next_node can be an object (this.takenIds), a node (text, el, etc) or false.

		//this.ddt._ddt( "enter-paragraphs.js", "175", "forEachNode(): calling function" );

		switch( mode )
			{

			case "cullids":

    		fnReturnVal = this._fenCullIds(walk, next_node );
				break;

			case "find_fill":

    		fnReturnVal = this._fenEmptySet(walk, next_node, mode, done_flag);
				break;

			case "find_cursorpoint":

    		fnReturnVal = this._fenEmptySet(walk, next_node, mode, done_flag);
				break;

			}

		// If this node wants us to return, return next_node

    if ( fnReturnVal[0] )
			{
			//this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): returning node:", fnReturnVal[1] );

			return fnReturnVal[1];
			}

		// are we done with the loop?

		if ( done_flag )
			{
			break;
			}

		// Otherwise, pass to the next node

    if ( fnReturnVal[1] )
			{
			next_node = fnReturnVal[1];
			}

	  }	// end of while loop

	//this.ddt._ddt( "enter-paragraphs.js", "175", "forEachNode(): returning false." );

  return false;

	};	// end of forEachNode()

// -------------------------------------------------------------------

/**
* Find a post-insertion node, only if all nodes are empty, or the first content
*
* @param node node current node beinge examined.
* @param next_node node next node to be examined.
* @param node string "find_fill" or "find_cursorpoint"
* @param last_flag boolean is this the last node?
*/

EnterParagraphs.prototype._fenEmptySet = function( node, next_node, mode, last_flag)
	{

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "263", "_fenEmptySet() : top with mode '" + mode + "' and last_flag '" + last_flag + "' and node:", node );

  // Mark this if it's the first base

  if ( !next_node && !node.firstChild )
		{
		next_node = node;
		}

  // Is it an element node and is it considered content? (br, hr, etc)
	// or is it a text node that is not just whitespace?
	// or is it not an element node and not a text node?

  if ( (node.nodeType == 1 && this._elemSolid.test(node.nodeName)) ||
    (node.nodeType == 3 && !this._whiteSpace.test(node.nodeValue)) ||
    (node.nodeType != 1 && node.nodeType != 3) )
		{

		//this.ddt._ddtDumpNode( "enter-paragraphs.js", "263", "_fenEmptySet() : found content in node:", node );

		switch( mode )
			{

			case "find_fill":

				// does not return content.

		    return new Array(true, false );
				breal;

			case "find_cursorpoint":

				// returns content

		    return new Array(true, node );
				break;

			}

	  }

  // In either case (fill or findcursor) we return the base node. The avoids
	// problems in terminal cases (beginning or end of document or container tags)

  if ( last_flag )
		{
		//this.ddt._ddtDumpNode( "enter-paragraphs.js", "263", "_fenEmptySet() : return 'base' node:", next_node );

		return new Array( true, next_node );
		}

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "263", "_fenEmptySet() : bottom returning false and :", next_node );

  return new Array( false, next_node );

	};	// end of _fenEmptySet()

// ------------------------------------------------------------------------------

/**
* remove duplicate Id's.
*
* @param ep_ref enterparagraphs reference to enterparagraphs object
*/

EnterParagraphs.prototype._fenCullIds = function ( ep_ref, node, pong )
	{

	//this.ddt._ddt( "enter-paragraphs.js", "299", "_fenCullIds(): top" );

  // Check for an id, blast it if it's in the store, otherwise add it

  if ( node.id )
		{

		//this.ddt._ddt( "enter-paragraphs.js", "299", "_fenCullIds(): node '" + node.nodeName + "' has an id '" + node.id + "'" );

		pong[node.id] ? node.id = '' : pong[node.id] = true;
		}

  return new Array(false,pong);

	};

// ---------------------------------------------------------------------------------

/**
* Grabs a range suitable for paragraph stuffing
*
* @param rng Range
* @param search_direction string "left" or "right"
*
* @todo check blank node issue in roaming loop.
*/

EnterParagraphs.prototype.processSide = function( rng, search_direction)
	{

	//this.ddt._ddt( "enter-paragraphs.js", "329", "processSide(): top search_direction == '" + search_direction + "'" );

  var next = function(element, search_direction)
							{
							return ( search_direction == "left" ? element.previousSibling : element.nextSibling );
							};

  var node = search_direction == "left" ? rng.startContainer : rng.endContainer;
  var offset = search_direction == "left" ? rng.startOffset : rng.endOffset;
  var roam, start = node;

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "337", "processSide(): starting with node:", node );

  // Never start with an element, because then the first roaming node might
  // be on the exclusion list and we wouldn't know until it was too late

  while ( start.nodeType == 1 && !this._permEmpty.test(start.nodeName) )
		{
		start = ( offset ? start.lastChild : start.firstChild );
		}

  // Climb the tree, left or right, until our course of action presents itself
	//
	// if roam is NULL try start.
	// if roam is NOT NULL, try next node in our search_direction
	// If that node is NULL, get our parent node.
	//
	// If all the above turns out NULL end the loop.
	//
	// FIXME: gecko (firefox 1.0.3) - enter "test" into an empty document and press enter.
	// sometimes this loop finds a blank text node, sometimes it doesn't.

  while ( roam = roam ? ( next(roam,search_direction) ? next(roam,search_direction) : roam.parentNode ) : start )
		{

		//this.ddt._ddtDumpNode( "enter-paragraphs.js", "357", "processSide(): roaming loop, search_direction is '" + search_direction + "' current node is: ", roam );

		// next() is an inline function defined above that returns the next node depending
		// on the direction we're searching.

    if ( next(roam,search_direction) )
			{

			//this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Checking next node '" + next(roam,search_direction).NodeName + "' for _pExclusions list." );

      // If the next sibling's on the exclusion list, stop before it

      if ( this._pExclusions.test(next(roam,search_direction).nodeName) )
				{

				//this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Node '" + next(roam,search_direction).NodeName + "' is on the _pExclusions list. Stopping before it." );

        return this.processRng(rng, search_direction, roam, next(roam,search_direction), (search_direction == "left"?'AfterEnd':'BeforeBegin'), true, false);
		    }
			}
		else
			{

			//this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): No next node, examing parent node '" + roam.parentNode.nodeName + "' for containers or exclusions." );

      // If our parent's on the container list, stop inside it

      if (this._pContainers.test(roam.parentNode.nodeName))
				{

				//this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Parent Node '" + roam.parentNode.nodeName + "' is on the _pContainer list. Stopping inside it." );

        return this.processRng(rng, search_direction, roam, roam.parentNode, (search_direction == "left"?'AfterBegin':'BeforeEnd'), true, false);
	      }
      else if (this._pExclusions.test(roam.parentNode.nodeName))
				{

				//this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Parent Node '" + roam.parentNode.nodeName + "' is on the _pExclusion list." );

	      // chop without wrapping

        if (this._pBreak.test(roam.parentNode.nodeName))
					{

					//this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Parent Node '" + roam.parentNode.nodeName + "' is on the _pBreak list." );

          return this.processRng(rng, search_direction, roam, roam.parentNode,
                            (search_direction == "left"?'AfterBegin':'BeforeEnd'), false, (search_direction == "left" ?true:false));
	        }
				else
					{

					//this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Parent Node '" + roam.parentNode.nodeName + "' is not on the _pBreak list." );

					// the next(roam,search_direction) in this call is redundant since we know it's false
					// because of the "if next(roam,search_direction)" above.
					//
					// the final false prevents this range from being wrapped in <p>'s most likely
					// because it's already wrapped.

          return this.processRng(rng,
																search_direction,
																(roam = roam.parentNode),
		                            (next(roam,search_direction) ? next(roam,search_direction) : roam.parentNode),
									              (next(roam,search_direction) ? (search_direction == "left"?'AfterEnd':'BeforeBegin') : (search_direction == "left"?'AfterBegin':'BeforeEnd')),
																false,
																false);
					}
				}
			}
		}

	//this.ddt._ddt( "enter-paragraphs.js", "424", "processSide(): bottom" );

	};	// end of processSide()

// ------------------------------------------------------------------------------

/**
* processRng - process Range.
*
* Neighbour and insertion identify where the new node, roam, needs to enter
* the document; landmarks in our selection will be deleted before insertion
*
* @param rn Range original selected range
* @param search_direction string Direction to search in.
* @param roam node
* @param insertion string may be AfterBegin of BeforeEnd
* @return array
*/

EnterParagraphs.prototype.processRng = function(rng, search_direction, roam, neighbour, insertion, pWrap, preBr)
	{

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "398", "processRng(): top - roam arg is:", roam );
	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "398", "processRng(): top - neighbor arg is:", neighbour );

	//this.ddt._ddt( "enter-paragraphs.js", "398", "processRng(): top - insertion arg is: '" + insertion + "'" );

  var node = search_direction == "left" ? rng.startContainer : rng.endContainer;
  var offset = search_direction == "left" ? rng.startOffset : rng.endOffset;

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "447", "processRng(): range start (or end) is at offset '" + offset + "' is node :", node );

  // Define the range to cut, and extend the selection range to the same boundary

  var editor = this.editor;
  var newRng = editor._doc.createRange();

  newRng.selectNode(roam);

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): selecting newRng is:", newRng );
	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): selecting original rng is:", rng );

	// extend the range in the given direction.

  if ( search_direction == "left")
		{
    newRng.setEnd(node, offset);
    rng.setStart(newRng.startContainer, newRng.startOffset);

		//this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): extending direction left - newRng is:", newRng );
		//this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): extending direction left - rng is:", rng );

	  }
	else if ( search_direction == "right" )
		{

    newRng.setStart(node, offset);
		rng.setEnd(newRng.endContainer, newRng.endOffset);

		//this.ddt._ddt( "enter-paragraphs.js", "522", "processRng(): right - new range start is '" + offset + "' end offset is '" + newRng.endOffset + "'" );
	  }

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): rng is:", rng );
	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): newRng is:", newRng );

  // Clone the range and remove duplicate ids it would otherwise produce

  var cnt = newRng.cloneContents();

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "509", "processRng(): culling duplicate ids from:", cnt );

	// in this case "init" is an object not a boolen.

  this.forEachNodeUnder( cnt, "cullids", "ltr", this.takenIds, false, false);

  // Special case, for inserting paragraphs before some blocks when caret is at
	// their zero offset.
	//
	// Used to "open up space" in front of a list, table. Usefull if the list is at
	// the top of the document. (otherwise you'd have no way of "moving it down").

  var pify, pifyOffset, fill;
  pify = search_direction == "left" ? (newRng.endContainer.nodeType == 3 ? true:false) : (newRng.startContainer.nodeType == 3 ? false:true);
  pifyOffset = pify ? newRng.startOffset : newRng.endOffset;
  pify = pify ? newRng.startContainer : newRng.endContainer;

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "521", "processRng(): pify is '" + pify.nodeName + "' pifyOffset is '" + pifyOffset + "':", pify );

  if ( this._pifyParent.test(pify.nodeName) && pify.parentNode.childNodes.item(0) == pify )
		{
    while ( !this._pifySibling.test(pify.nodeName) )
			{
			pify = pify.parentNode;
			}
	  }

	// NODE TYPE 11 is DOCUMENT_FRAGMENT NODE

  if ( cnt.nodeType == 11 && !cnt.firstChild )
		{
		cnt.appendChild(editor._doc.createElement(pify.nodeName));
		}

	// YmL: Added additional last parameter for fill case to work around logic
	// error in forEachNode()

	//this.ddt._ddt( "enter-paragraphs.js", "612", "processRng(): find_fill in cnt." );

  fill = this.forEachNodeUnder(cnt, "find_fill", "ltr", false );

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "612", "processRng(): fill node:" , fill );

  if ( fill &&
				this._pifySibling.test(pify.nodeName) &&
	    	( (pifyOffset == 0) || ( pifyOffset == 1 && this._pifyForced.test(pify.nodeName) ) ) )
		{

		//this.ddt._ddt( "enter-paragraphs.js", "544", "processRng(): pify handling. Creating p tag followed by nbsp tag" );

		roam = editor._doc.createElement( 'p' );
		roam.innerHTML = "&nbsp;";

    // roam = editor._doc.createElement('p');
    // roam.appendChild(editor._doc.createElement('br'));

		// for these cases, if we are processing the left hand side we want it to halt
		// processing instead of doing the right hand side. (Avoids adding another <p>&nbsp</p>
		// after the list etc.

    if ((search_direction == "left" ) && pify.previousSibling)
			{

			//this.ddt._ddt( "enter-paragraphs.js", "682", "processRng(): returning created roam AfterEnd" );

			return new Array(pify.previousSibling, 'AfterEnd', roam);
			}
    else if (( search_direction == "right") && pify.nextSibling)
			{

			//this.ddt._ddt( "enter-paragraphs.js", "682", "processRng(): returning created roam BeforeBegin" );

			return new Array(pify.nextSibling, 'BeforeBegin', roam);
			}
    else
			{

			//this.ddt._ddt( "enter-paragraphs.js", "682", "processRng(): returning created roam for direction '" + search_direction + "'" );

			return new Array(pify.parentNode, (search_direction == "left"?'AfterBegin':'BeforeEnd'), roam);
			}

	  }

  // If our cloned contents are 'content'-less, shove a break in them

  if ( fill )
		{

		// Ill-concieved?
		//
		// 3 is a TEXT node and it should be empty.
		//

		if ( fill.nodeType == 3 )
			{
			// fill = fill.parentNode;

			fill = editor._doc.createDocumentFragment();

			//this.ddt._ddtDumpNode( "enter-paragraphs.js", "575", "processRng(): fill.nodeType is 3. Moving up to parent:", fill );
			}

    if ( (fill.nodeType == 1 && !this._elemSolid.test()) || fill.nodeType == 11 )
			{

			// FIXME:/CHECKME: When Xinha is switched from WYSIWYG to text mode
			// HTMLArea.getHTMLWrapper() will strip out the trailing br. Not sure why.

			// fill.appendChild(editor._doc.createElement('br'));

			var pterminator = editor._doc.createElement( 'p' );
			pterminator.innerHTML = "&nbsp;";

			fill.appendChild( pterminator );

			//this.ddt._ddtDumpNode( "enter-paragraphs.js", "583", "processRng(): fill type is 1 and !elemsolid or it's type 11. Appending an nbsp tag:", fill );

			}
    else
			{

			//this.ddt._ddt( "enter-paragraphs.js", "583", "processRng(): inserting a br tag before." );

			// fill.parentNode.insertBefore(editor._doc.createElement('br'),fill);

			var pterminator = editor._doc.createElement( 'p' );
			pterminator.innerHTML = "&nbsp;";

			fill.parentNode.insertBefore(parentNode,fill);

			}
	  }

	// YmL: If there was no content replace with fill
	// (previous code did not use fill and we ended up with the
	// <p>test</p><p></p> because Gecko was finding two empty text nodes
	// when traversing on the right hand side of an empty document.

	if ( fill )
		{

		//this.ddt._ddtDumpNode( "enter-paragraphs.js", "606", "processRng(): no content. Using fill.", fill );

		roam = fill;
		}
	else
		{
	  // And stuff a shiny new object with whatever contents we have

		//this.ddt._ddt( "enter-paragraphs.js", "606", "processRng(): creating p tag or document fragment - pWrap is '" + pWrap + "' " );

	  roam = (pWrap || (cnt.nodeType == 11 && !cnt.firstChild)) ? editor._doc.createElement('p') : editor._doc.createDocumentFragment();
	  roam.appendChild(cnt);
		}

  if (preBr)
		{
		//this.ddt._ddt( "enter-paragraphs.js", "767", "processRng(): appending a br based on preBr flag" );

		// MT: This br adds the erroneous <br /> at the end of a list in
		// FF.  However removing it makes it so that we can never escape
		// from list creations.  Maybe we can store this element and
		// remove it at a later point to make this go away without
		// impacting functionality?
		roam.appendChild(editor._doc.createElement('br'));
		}

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "606", "processRng(): bottom with roam:", roam );
	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "606", "processRng(): bottom with neighbour:", neighbour );

  // Return the nearest relative, relative insertion point and fragment to insert

  return new Array(neighbour, insertion, roam);

	};	// end of processRng()

// ----------------------------------------------------------------------------------

/**
* are we an <li> that should be handled by the browser?
*
* there is no good way to "get out of" ordered or unordered lists from Javascript.
* We have to pass the onKeyPress 13 event to the browser so it can take care of
* getting us "out of" the list.
*
* The Gecko engine does a good job of handling all the normal <li> cases except the "press
* enter at the first position" where we want a <p>&nbsp</p> inserted before the list. The
* built-in behavior is to open up a <li> before the current entry (not good).
*
* @param rng Range range.
*/

EnterParagraphs.prototype.isNormalListItem = function(rng)
	{

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "863", "isNormaListItem(): checking rng for list end:", rng );

	var node, listNode;

	node = rng.startContainer;

	if (( typeof node.nodeName != 'undefined') &&
		( node.nodeName.toLowerCase() == 'li' ))
		{

		//this.ddt._ddt( "enter-paragraphs.js", "863", "isNormaListItem(): node is a list item");

		// are we a list item?

		listNode = node;
		}
	else if (( typeof node.parentNode != 'undefined' ) &&
				( typeof node.parentNode.nodeName != 'undefined' ) &&
				( node.parentNode.nodeName.toLowerCase() == 'li' ))
		{

		//this.ddt._ddt( "enter-paragraphs.js", "863", "isNormaListItem(): parent is a list item");

		// our parent is a list item.

		listNode = node.parentNode;

		}
	else
		{
		//this.ddt._ddt( "enter-paragraphs.js", "863", "isNormaListItem(): not list item");

		// neither we nor our parent are a list item. this is not a normal
		// li case.

		return false;
		}

	// at this point we have a listNode. Is it the first list item?

	if ( ! listNode.previousSibling )
		{
		//this.ddt._ddt( "enter-paragraphs.js", "839", "isNormaListItem(): we are the first li." );

		// are we on the first character of the first li?

		if ( rng.startOffset == 0 )
			{
			//this.ddt._ddt( "enter-paragraphs.js", "839", "isNormaListItem(): we are on the first character." );

			return false;
			}
		}

	//this.ddt._ddt( "enter-paragraphs.js", "839", "isNormaListItem(): this is a normal list item case." );
	return true;

	};	// end of isNormalListItem()

// ----------------------------------------------------------------------------------
/**
* Called when a key is pressed in the editor
*/

EnterParagraphs.prototype.__onKeyPress = function(ev)
	{

	//this.ddt._ddt( "enter-paragraphs.js", "517", "__onKeyPress(): top with keyCode '" + ev.keyCode + "'" );

  // If they've hit enter and shift is not pressed, handle it

  if (ev.keyCode == 13 && !ev.shiftKey && this.editor._iframe.contentWindow.getSelection)
		{
		//this.ddt._ddt( "enter-paragraphs.js", "517", "__onKeyPress(): calling handleEnter" );

    return this.handleEnter(ev);
		}

	//this.ddt._ddt( "enter-paragraphs.js", "517", "__onKeyPress(): bottom" );

	};	// end of _onKeyPress()

// -----------------------------------------------------------------------------------

/**
* Handles the pressing of an unshifted enter for Gecko
*/

EnterParagraphs.prototype.handleEnter = function(ev)
	{

	//this.ddt._ddt( "enter-paragraphs.js", "537", "handleEnter(): top" );

	var cursorNode;

  // Grab the selection and associated range

  var sel = this.editor._getSelection();
  var rng = this.editor._createRange(sel);

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "757", "handleEnter(): initial range is: ", rng );

	// if we are at the end of a list and the node is empty let the browser handle
	// it to get us out of the list.

	if ( this.isNormalListItem(rng) )
		{
		//this.ddt._ddt( "enter-paragraphs.js", "757", "handleEnter(): we are at the end of a list with a blank item. Letting the browser handle it." );
		return true;
		}

	// as far as I can tell this isn't actually used.

  this.takenIds = new Object();

  // Grab ranges for document re-stuffing, if appropriate
	//
	// pStart and pEnd are arrays consisting of
	// [0] neighbor node
	// [1] insertion type
	// [2] roam

	//this.ddt._ddt( "enter-paragraphs.js", "537", "handleEnter(): calling processSide on left side." );

  var pStart = this.processSide(rng, "left");

	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "757", "handleEnter(): after processing left side range is: ", rng );

	//this.ddt._ddt( "enter-paragraphs.js", "537", "handleEnter(): calling processSide on right side." );

 	var pEnd = this.processSide(rng, "right");

	// used to position the cursor after insertion.

	cursorNode = pEnd[2];

  // Get rid of everything local to the selection

  sel.removeAllRanges();
  rng.deleteContents();

	// Grab a node we'll have after insertion, since fragments will be lost
	//
	// we'll use this to position the cursor.

	//this.ddt._ddt( "enter-paragraphs.js", "712", "handleEnter(): looking for cursor position" );

  var holdEnd = this.forEachNodeUnder( cursorNode, "find_cursorpoint", "ltr", false, true);

	if ( ! holdEnd )
		{
		alert( "INTERNAL ERROR - could not find place to put cursor after ENTER" );
		}

  // Insert our carefully chosen document fragments

  if ( pStart )
		{

		//this.ddt._ddt( "enter-paragraphs.js", "712", "handleEnter(): inserting pEnd" );

		this.insertAdjacentElement(pStart[0], pStart[1], pStart[2]);
		}

  if ( pEnd && pEnd.nodeType != 1)
		{

		//this.ddt._ddt( "enter-paragraphs.js", "712", "handleEnter(): inserting pEnd" );

		this.insertAdjacentElement(pEnd[0], pEnd[1], pEnd[2]);
		}

  // Move the caret in front of the first good text element

  if ((holdEnd) && (this._permEmpty.test(holdEnd.nodeName) ))
		{

		//this.ddt._ddt( "enter-paragraphs.js", "712", "handleEnter(): looping to find cursor element." );

    var prodigal = 0;
    while ( holdEnd.parentNode.childNodes.item(prodigal) != holdEnd )
			{
			prodigal++;
			}

    sel.collapse( holdEnd.parentNode, prodigal);
	  }
  else
		{

		// holdEnd might be false.

		try
			{
			sel.collapse(holdEnd, 0);

			//this.ddt._ddtDumpNode( "enter-paragraphs.js", "1057", "handleEnter(): scrolling to element:", holdEnd );

			// interestingly, scrollToElement() scroll so the top if holdEnd is a text node.

			if ( holdEnd.nodeType == 3 )
				{
				holdEnd = holdEnd.parentNode;
				}

		  this.editor.scrollToElement(holdEnd);
			}
		catch (e)
			{
			// we could try to place the cursor at the end of the document.
			}
		}

  this.editor.updateToolbar();

	HTMLArea._stopEvent(ev);

	return true;

	};	// end of handleEnter()

// END

// Spell Checker Plugin for HTMLArea-3.0
// Sponsored by www.americanbible.org
// Implementation by Mihai Bazon, http://dynarch.com/mishoo/
//
// (c) dynarch.com 2003.
// Distributed under the same terms as HTMLArea itself.
// This notice MUST stay intact for use (see license.txt).
//
// $Id: spell-checker.js 376 2005-10-01 09:23:52Z mokhet $

HTMLArea.Config.prototype.SpellChecker = { 'backend': 'php', 'personalFilesDir' : '', 'defaultDictionary' : 'en_US' };

function SpellChecker(editor) {
  this.editor = editor;

  var cfg = editor.config;
  var bl = SpellChecker.btnList;
  var self = this;

  // see if we can find the mode switch button, insert this before that
  var id = "SC-spell-check";
  // >MT: Change terminology of "spell-check" to "Spell Checker"
  cfg.registerButton(id, this._lc("Spell Checker"), editor.imgURL("spell-check.gif", "SpellChecker"), false,
  // <MT
             function(editor, id) {
               // dispatch button press event
               self.buttonPress(editor, id);
             });

  // >MT: relocate
  cfg.addToolbarElement("SC-spell-check", "removeformat", 1);
  // <MT
};

SpellChecker._pluginInfo = {
  name          : "SpellChecker",
  version       : "1.0",
  developer     : "Mihai Bazon",
  developer_url : "http://dynarch.com/mishoo/",
  c_owner       : "Mihai Bazon",
  sponsor       : "American Bible Society",
  sponsor_url   : "http://www.americanbible.org",
  license       : "htmlArea"
};

SpellChecker.prototype._lc = function(string) {
    return HTMLArea._lc(string, 'SpellChecker');
};

SpellChecker.btnList = [
  null, // separator
  ["spell-check"]
  ];

SpellChecker.prototype.buttonPress = function(editor, id) {
  switch (id) {
      case "SC-spell-check":
    SpellChecker.editor = editor;
    SpellChecker.init = true;
    var uiurl = _editor_url + "plugins/SpellChecker/spell-check-ui.html";
    var win;
    if (HTMLArea.is_ie) {
      win = window.open(uiurl, "SC_spell_checker",
            "toolbar=no,location=no,directories=no,status=no,menubar=no," +
            "scrollbars=no,resizable=yes,width=600,height=450");
    } else {
      win = window.open(uiurl, "SC_spell_checker",
            "toolbar=no,menubar=no,personalbar=no,width=600,height=450," +
            "scrollbars=no,resizable=yes");
    }
    win.focus();
    break;
  }
};

// this needs to be global, it's accessed from spell-check-ui.html
SpellChecker.editor = null;

function FullScreen(editor, args)
{
  this.editor = editor;
  editor._superclean_on = false;
  cfg = editor.config;

  cfg.registerButton
  ( 'fullscreen',
    // >MT: change tooltip
    //this._lc("Maximize/Minimize Editor"),
    this._lc("Toggle Full Screen Mode"),
    // <MT
    [_editor_url + cfg.imgURL + 'ed_buttons_main.gif',8,0], true,
      function(e, objname, obj)
      {
        e._fullScreen();
        if(e._isFullScreen)
        {
          obj.swapImage([_editor_url + cfg.imgURL + 'ed_buttons_main.gif',9,0]);
        }
        else
        {
          obj.swapImage([_editor_url + cfg.imgURL + 'ed_buttons_main.gif',8,0]);
        }
      }
  );

  // See if we can find 'popupeditor' and replace it with fullscreen
  // >MT: relocate button
  cfg.addToolbarElement("fullscreen", "mksQuicksave", 1);
  // <MT
}

FullScreen._pluginInfo =
{
  name     : "FullScreen",
  version  : "1.0",
  developer: "James Sleeman",
  developer_url: "http://www.gogo.co.nz/",
  c_owner      : "Gogo Internet Services",
  license      : "htmlArea",
  sponsor      : "Gogo Internet Services",
  sponsor_url  : "http://www.gogo.co.nz/"
};

FullScreen.prototype._lc = function(string) {
    return HTMLArea._lc(string, 'FullScreen');
};

/** fullScreen makes an editor take up the full window space (and resizes when the browser is resized)
 *  the principle is the same as the "popupwindow" functionality in the original htmlArea, except
 *  this one doesn't popup a window (it just uses to positioning hackery) so it's much more reliable
 *  and much faster to switch between
 */

HTMLArea.prototype._fullScreen = function()
{
  var e = this;
  function sizeItUp()
  {
    if(!e._isFullScreen || e._sizing) return false;
    e._sizing = true;
    // Width & Height of window
    var x,y;
    if (window.innerHeight) // all except Explorer
    {
      x = window.innerWidth;
      y = window.innerHeight;
    }
    else if (document.documentElement && document.documentElement.clientHeight)
      // Explorer 6 Strict Mode
    {
      x = document.documentElement.clientWidth;
      y = document.documentElement.clientHeight;
    }
    else if (document.body) // other Explorers
    {
      x = document.body.clientWidth;
      y = document.body.clientHeight;
    }

	// >MT: fix
    x -= 2;
	// <MT: fix
    e.sizeEditor(x + 'px',y + 'px',true,true);
    e._sizing = false;
	// >MT: allow callback (for hiding controls in fullscreen)
    if (typeof e._OnMode == "function")
      e._OnMode('maximize');
	// <MT
  }

  function sizeItDown()
  {
    if(e._isFullScreen || e._sizing) return false;
    e._sizing = true;
    e.initSize();
    e._sizing = false;
	// >MT: allow callback (for hiding controls in fullscreen)
    if (typeof e._OnMode == "function")
      e._OnMode('restore');
	// <MT
  }

  /** It's not possible to reliably get scroll events, particularly when we are hiding the scrollbars
   *   so we just reset the scroll ever so often while in fullscreen mode
   */
  function resetScroll()
  {
    if(e._isFullScreen)
    {
      window.scroll(0,0);
      window.setTimeout(resetScroll,150);
    }
  }

  if(typeof this._isFullScreen == 'undefined')
  {
    this._isFullScreen = false;
    if(e.target != e._iframe)
    {
      HTMLArea._addEvent(window, 'resize', sizeItUp);
    }
  }

  // Gecko has a bug where if you change position/display on a
  // designMode iframe that designMode dies.
  if(HTMLArea.is_gecko)
  {
    this.deactivateEditor();
  }

  if(this._isFullScreen)
  {
    // Unmaximize
    this._htmlArea.style.position = '';
    try
    {
      if(HTMLArea.is_ie)
      {
        var bod = document.getElementsByTagName('html');
      }
      else
      {
        var bod = document.getElementsByTagName('body');
      }
      bod[0].style.overflow='';
    }
    catch(e)
    {
      // Nutthin
    }
    this._isFullScreen = false;
    sizeItDown();

    // Restore all ancestor positions
    var ancestor = this._htmlArea;
    while((ancestor = ancestor.parentNode) && ancestor.style)
    {
      ancestor.style.position = ancestor._xinha_fullScreenOldPosition;
      ancestor._xinha_fullScreenOldPosition = null;
    }

    window.scroll(this._unScroll.x, this._unScroll.y);
  }
  else
  {

    // Get the current Scroll Positions
    this._unScroll =
    {
     x:(window.pageXOffset)?(window.pageXOffset):(document.documentElement)?document.documentElement.scrollLeft:document.body.scrollLeft,
     y:(window.pageYOffset)?(window.pageYOffset):(document.documentElement)?document.documentElement.scrollTop:document.body.scrollTop
    };


    // Make all ancestors position = static
    var ancestor = this._htmlArea;
    while((ancestor = ancestor.parentNode) && ancestor.style)
    {
      ancestor._xinha_fullScreenOldPosition = ancestor.style.position;
      ancestor.style.position = 'static';
    }

    // Maximize
    window.scroll(0,0);
    this._htmlArea.style.position = 'absolute';
    this._htmlArea.style.zIndex   = 999;
    this._htmlArea.style.left     = 0;
    this._htmlArea.style.top      = 0;
    this._isFullScreen = true;
    resetScroll();

    try
    {
      if(HTMLArea.is_ie)
      {
        var bod = document.getElementsByTagName('html');
      }
      else
      {
        var bod = document.getElementsByTagName('body');
      }
      bod[0].style.overflow='hidden';
    }
    catch(e)
    {
      // Nutthin
    }

    sizeItUp();
  }

  if(HTMLArea.is_gecko)
  {
    this.activateEditor();
  }
  this.focusEditor();
};

// Context Menu Plugin for HTMLArea-3.0
// Sponsored by www.americanbible.org
// Implementation by Mihai Bazon, http://dynarch.com/mishoo/
//
// (c) dynarch.com 2003.
// Copyright (C) MindTouch, Inc.
// Distributed under the same terms as HTMLArea itself.
// This notice MUST stay intact for use (see license.txt).
//
// $Id: context-menu.js 290 2005-08-05 10:04:54Z niko $

HTMLArea.loadStyle("menu.css", "ContextMenu");

function ContextMenu(editor) {
	this.editor = editor;
};

ContextMenu._pluginInfo = {
	name					: "ContextMenu",
	version			 : "1.0",
	developer		 : "Mihai Bazon",
	developer_url : "http://dynarch.com/mishoo/",
	c_owner			 : "dynarch.com",
	sponsor			 : "American Bible Society",
	sponsor_url	 : "http://www.americanbible.org",
	license			 : "htmlArea"
};

ContextMenu.prototype.onGenerate = function() {
	var self = this;
	var doc = this.editordoc = this.editor._iframe.contentWindow.document;
	HTMLArea._addEvents(doc, ["contextmenu"],
					function (event) {
						return self.popupMenu(HTMLArea.is_ie ? self.editor._iframe.contentWindow.event : event);
					});
	this.currentMenu = null;
};

ContextMenu.prototype.getContextMenu = function(target) {
	var self = this;
	var editor = this.editor;
	var config = editor.config;
	var menu = [];
	var tbo = this.editor.plugins.TableOperations;
	if (tbo) tbo = tbo.instance;

	var selection = editor.hasSelectedText();
	if (selection)
		menu.push([ HTMLArea._lc("Cut", "ContextMenu"), function() { editor.execCommand("cut"); }, null, config.btnList["cut"][1] ],
				[ HTMLArea._lc("Copy", "ContextMenu"), function() { editor.execCommand("copy"); }, null, config.btnList["copy"][1] ]);
	menu.push([ HTMLArea._lc("Paste", "ContextMenu"), function() { editor.execCommand("paste"); }, null, config.btnList["paste"][1] ]);

	// >MT: use current selection instead of event target if it is more accurate
	var rt = editor.getParentElement();
	var t = rt, targetInParent = false;
	while (t && !targetInParent) {
		targetInParent = t == target;
		t = t.parentNode;
	}
	if (targetInParent)
		target = rt;
	// <MT
	var currentTarget = target;
	var elmenus = [];

	var link = null;
	var table = null;
	var tr = null;
	var td = null;
	var img = null;

	function tableOperation(opcode) {
		tbo.buttonPress(editor, opcode);
	};

	function insertPara(after) {
		var el = currentTarget;
		var par = el.parentNode;
		var p = editor._doc.createElement("p");
		p.appendChild(editor._doc.createElement("br"));
		par.insertBefore(p, after ? el.nextSibling : el);
		var sel = editor._getSelection();
		var range = editor._createRange(sel);
		if (!HTMLArea.is_ie) {
			sel.removeAllRanges();
			range.selectNodeContents(p);
			range.collapse(true);
			sel.addRange(range);
		} else {
			range.moveToElementText(p);
			range.collapse(true);
			range.select();
		}
	};

	for (; target; target = target.parentNode) {
		var tag = target.tagName;
		if (!tag)
			continue;
		tag = tag.toLowerCase();
		switch (tag) {
		case "img":
			img = target;
			elmenus.push(null,
						 [ HTMLArea._lc("_Image Properties...", "ContextMenu"),
							 function() {
								 editor._insertImage(img);
							 },
							 HTMLArea._lc("Show the image properties dialog", "ContextMenu"),
							 config.btnList["insertimage"][1] ]
				);
			break;
		case "a":
			link = target;
			elmenus.push(null,
						 [ HTMLArea._lc("_Update Link...", "ContextMenu"),
							 function() { editor.config.btnList['createlink'][3](editor); },
							 HTMLArea._lc("Current URL is", "ContextMenu") + ': ' + link.href,
							 config.btnList["createlink"][1] ],

						 [ HTMLArea._lc("Chec_k Link...", "ContextMenu"),
						 // >MT: special handling for internal links
							 function() { MindTouch.checkLink(link); },
						 // <MT
							 HTMLArea._lc("Opens this link in a new window", "ContextMenu") ],

						 [ HTMLArea._lc("_Remove Link...", "ContextMenu"),
							 function() {
								 if (confirm(HTMLArea._lc("Please confirm that you want to unlink this element.", "ContextMenu") + "\n" +
								 HTMLArea._lc("Link points to:", "ContextMenu") + " " + link.href)) {
									 while (link.firstChild)
										 link.parentNode.insertBefore(link.firstChild, link);
									 link.parentNode.removeChild(link);
								 }
							 },
							 HTMLArea._lc("Unlink the current element", "ContextMenu") ]
				);
			break;
		case "td":
			td = target;
			if (!tbo) break;
			elmenus.push(null,
						 [ HTMLArea._lc("C_ell Properties...", "ContextMenu"),
							 function() { tableOperation("TO-cell-prop"); },
							 HTMLArea._lc("Show the Table Cell Properties dialog", "ContextMenu"),
							 config.btnList["TO-cell-prop"][1] ]
				);
			break;
		case "tr":
			tr = target;
			if (!tbo) break;
			elmenus.push(null,
						 [ HTMLArea._lc("Ro_w Properties...", "ContextMenu"),
							 function() { tableOperation("TO-row-prop"); },
							 HTMLArea._lc("Show the Table Row Properties dialog", "ContextMenu"),
							 config.btnList["TO-row-prop"][1] ],

						 [ HTMLArea._lc("I_nsert Row Before", "ContextMenu"),
							 function() { tableOperation("TO-row-insert-above"); },
							 HTMLArea._lc("Insert a new row before the current one", "ContextMenu"),
							 config.btnList["TO-row-insert-above"][1] ],

						 [ HTMLArea._lc("In_sert Row After", "ContextMenu"),
							 function() { tableOperation("TO-row-insert-under"); },
							 HTMLArea._lc("Insert a new row after the current one", "ContextMenu"),
							 config.btnList["TO-row-insert-under"][1] ],

						 [ HTMLArea._lc("_Delete Row", "ContextMenu"),
							 function() { tableOperation("TO-row-delete"); },
							 HTMLArea._lc("Delete the current row", "ContextMenu"),
							 config.btnList["TO-row-delete"][1] ]
				);
			break;
		case "table":
			table = target;
			if (!tbo) break;
			elmenus.push(null,
						 [ HTMLArea._lc("_Table Properties...", "ContextMenu"),
							 function() { tableOperation("TO-table-prop"); },
							 HTMLArea._lc("Show the Table Properties dialog", "ContextMenu"),
							 config.btnList["TO-table-prop"][1] ],

						 [ HTMLArea._lc("Insert _Column Before", "ContextMenu"),
							 function() { tableOperation("TO-col-insert-before"); },
							 HTMLArea._lc("Insert a new column before the current one", "ContextMenu"),
							 config.btnList["TO-col-insert-before"][1] ],

						 [ HTMLArea._lc("Insert C_olumn After", "ContextMenu"),
							 function() { tableOperation("TO-col-insert-after"); },
							 HTMLArea._lc("Insert a new column after the current one", "ContextMenu"),
							 config.btnList["TO-col-insert-after"][1] ],

						 [ HTMLArea._lc("De_lete Column", "ContextMenu"),
							 function() { tableOperation("TO-col-delete"); },
							 HTMLArea._lc("Delete the current column", "ContextMenu"),
							 config.btnList["TO-col-delete"][1] ]
				);
			break;
		case "body":
			elmenus.push(null,
						 [ HTMLArea._lc("Justify Left", "ContextMenu"),
							 function() { editor.execCommand("justifyleft"); }, null,
							 config.btnList["justifyleft"][1] ],
						 [ HTMLArea._lc("Justify Center", "ContextMenu"),
							 function() { editor.execCommand("justifycenter"); }, null,
							 config.btnList["justifycenter"][1] ],
						 [ HTMLArea._lc("Justify Right", "ContextMenu"),
							 function() { editor.execCommand("justifyright"); }, null,
							 config.btnList["justifyright"][1] ],
						 [ HTMLArea._lc("Justify Full", "ContextMenu"),
							 function() { editor.execCommand("justifyfull"); }, null,
							 config.btnList["justifyfull"][1] ]
				);
			break;
		}
	}

	if (selection && !link)
		menu.push(null, [ HTMLArea._lc("Make lin_k...", "ContextMenu"),
					 function() { editor.config.btnList['createlink'][3](editor); },
					HTMLArea._lc("Create a link", "ContextMenu"),
					config.btnList["createlink"][1] ]);

	for (var i = 0; i < elmenus.length; ++i)
		menu.push(elmenus[i]);

	// >MT: add remove tag vs remove element
	if (!/html|body/i.test(currentTarget.tagName)) {
	// <MT
		menu.push(null,
				// >MT: add remove tag vs remove element
				[ HTMLArea._lc({string: "Remove the $elem Element Content...", replace: {elem: "&lt;" + currentTarget.tagName + "&gt;"}}, "ContextMenu"),
				// <MT
					function() {
						// >MT: add remove tag vs remove element
						if (confirm(HTMLArea._lc("Please confirm that you want to remove this element and it's content:", "ContextMenu") + " " +
						// <MT
						currentTarget.tagName)) {
							var el = currentTarget;
							var p = el.parentNode;
							p.removeChild(el);
							if (HTMLArea.is_gecko) {
								if (p.tagName.toLowerCase() == "td" && !p.hasChildNodes())
									p.appendChild(editor._doc.createElement("br"));
								editor.forceRedraw();
								editor.focusEditor();
								editor.updateToolbar();
								if (table) {
									var save_collapse = table.style.borderCollapse;
									table.style.borderCollapse = "collapse";
									table.style.borderCollapse = "separate";
									table.style.borderCollapse = save_collapse;
								}
							}
						}
					},
		// >MT: add remove tag vs remove element
					HTMLArea._lc("Remove this node, and it's content from the document", "ContextMenu") ]);
		var data = HTMLArea.validTags[currentTarget.tagName.toLowerCase()];
		if (data.isTableElement) {
			menu.push(
				[ HTMLArea._lc("Convert Table to Text...", "ContextMenu"),
					function() {
						if (confirm(HTMLArea._lc("Please confirm that you want to convert the table into text:", "ContextMenu"))) {
							HTMLArea.convertTableToText(currentTarget);
						}
					},
					HTMLArea._lc("All the table elements will be converted into text elements", "ContextMenu") ]);
		} else {
			data = HTMLArea.validTags[currentTarget.parentNode.tagName.toLowerCase()];
			if (data && !data.noText)
				menu.push(
					[ HTMLArea._lc({string: "Remove the $elem Tag...", replace: {elem: "&lt;" + currentTarget.tagName + "&gt;"}}, "ContextMenu"),
						function() { 
							var p = currentTarget.parentNode;
							if (currentTarget.tagName.toLowerCase() == 'p') {
								if (currentTarget.previousSibling && !(currentTarget.previousSibling.nodeType == 1 && currentTarget.previousSibling.tagName.toLowerCase() == 'p'))
									currentTarget.parentNode.insertBefore(currentTarget.ownerDocument.createElement('br'), currentTarget);
								else if (currentTarget.nextSibling && !(currentTarget.nextSibling.nodeType == 1 && currentTarget.nextSibling.tagName.toLowerCase() == 'p'))
									currentTarget.parentNode.insertBefore(currentTarget.ownerDocument.createElement('br'), currentTarget.nextSibling);
							}
							HTMLArea.removeTag(currentTarget);
							HTMLArea.makeXHTML(p, editor.makeXHTMLContext(false));
						},
						HTMLArea._lc("Remove this tag, but not the content from the document", "ContextMenu") ]);
			// <MT
			menu.push(
				[ HTMLArea._lc("Insert paragraph before", "ContextMenu"),
					function() { insertPara(false); },
					HTMLArea._lc("Insert a paragraph before the current node", "ContextMenu") ],
				[ HTMLArea._lc("Insert paragraph after", "ContextMenu"),
					function() { insertPara(true); },
					HTMLArea._lc("Insert a paragraph after the current node", "ContextMenu") ]
				);
			// >MT: add remove tag vs remove element
		}
	}
	// <MT
	return menu;
};

// >MT: convert table to text
HTMLArea.convertTableToText = function(node) {
	var table = node;
	while (table && (table.nodeType != 1 || table.tagName.toLowerCase() != 'table'))
		table = table.parentNode;

	if (!table) return;

	function handleChild(child) {
		if (child.nodeType == 1) {
			var tag = HTMLArea.validTags[child.tagName.toLowerCase()];
			if (tag.isTableElement && tag.tag != 'table') {
				HTMLArea.xhtml_applyToChildren(child, handleChild);
				HTMLArea.removeTag(child);
			}
		}
	};

	HTMLArea.xhtml_applyToChildren(table, handleChild);
	HTMLArea.removeTag(table);
};
// <MT

ContextMenu.prototype.popupMenu = function(ev) {
	var self = this;
	if (this.currentMenu)
		this.currentMenu.parentNode.removeChild(this.currentMenu);
	function getPos(el) {
		var r = { x: el.offsetLeft, y: el.offsetTop };
		if (el.offsetParent) {
			var tmp = getPos(el.offsetParent);
			r.x += tmp.x;
			r.y += tmp.y;
		}
		return r;
	};
	function documentClick(ev) {
		ev || (ev = window.event);
		if (!self.currentMenu) {
			alert(HTMLArea._lc("How did you get here? (Please report!)", "ContextMenu"));
			return false;
		}
		var el = HTMLArea.is_ie ? ev.srcElement : ev.target;
		for (; el != null && el != self.currentMenu; el = el.parentNode);
		if (el == null)
			self.closeMenu();
		//HTMLArea._stopEvent(ev);
		//return false;
	};
	var keys = [];
	function keyPress(ev) {
		ev || (ev = window.event);
		HTMLArea._stopEvent(ev);
		if (ev.keyCode == 27) {
			self.closeMenu();
			return false;
		}
		var key = String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : ev.charCode).toLowerCase();
		for (var i = keys.length; --i >= 0;) {
			var k = keys[i];
			if (k[0].toLowerCase() == key)
				k[1].__msh.activate();
		}
	};
	self.closeMenu = function() {
		self.currentMenu.parentNode.removeChild(self.currentMenu);
		self.currentMenu = null;
		HTMLArea._removeEvent(document, "mousedown", documentClick);
		HTMLArea._removeEvent(self.editordoc, "mousedown", documentClick);
		if (keys.length > 0)
			HTMLArea._removeEvent(self.editordoc, "keypress", keyPress);
		if (HTMLArea.is_ie)
			self.iePopup.hide();
	};
	var target = HTMLArea.is_ie ? ev.srcElement : ev.target;
		 var ifpos = getPos(self.editor._htmlArea);//_iframe);
	var x = ev.clientX + ifpos.x;
	var y = ev.clientY + ifpos.y;

	var div;
	var doc;
	if (!HTMLArea.is_ie) {
		doc = document;
	} else {
		// IE stinks
		var popup = this.iePopup = window.createPopup();
		doc = popup.document;
		doc.open();
		doc.write("<html><head><style type='text/css'>@import url(" + _editor_url + "plugins/ContextMenu/menu.css); html, body { padding: 0px; margin: 0px; overflow: hidden; border: 0px; }</style></head><body unselectable='yes'></body></html>");
		doc.close();
	}
	div = doc.createElement("div");
	if (HTMLArea.is_ie)
		div.unselectable = "on";
	div.oncontextmenu = function() { return false; };
	div.className = "htmlarea-context-menu";
	if (!HTMLArea.is_ie)
		div.style.left = div.style.top = "0px";
	doc.body.appendChild(div);

	var table = doc.createElement("table");
	div.appendChild(table);
	table.cellSpacing = 0;
	table.cellPadding = 0;
	var parent = doc.createElement("tbody");
	table.appendChild(parent);

	var options = this.getContextMenu(target);
	for (var i = 0; i < options.length; ++i) {
		var option = options[i];
		var item = doc.createElement("tr");
		parent.appendChild(item);
		if (HTMLArea.is_ie)
			item.unselectable = "on";
		else item.onmousedown = function(ev) {
			HTMLArea._stopEvent(ev);
			return false;
		};
		if (!option) {
			item.className = "separator";
			var td = doc.createElement("td");
			td.className = "icon";
			var IE_IS_A_FUCKING_SHIT = '>';
			if (HTMLArea.is_ie) {
				td.unselectable = "on";
				IE_IS_A_FUCKING_SHIT = " unselectable='on' style='height=1px'>&nbsp;";
			}
			td.innerHTML = "<div" + IE_IS_A_FUCKING_SHIT + "</div>";
			var td1 = td.cloneNode(true);
			td1.className = "label";
			item.appendChild(td);
			item.appendChild(td1);
		} else {
			var label = option[0];
			item.className = "item";
			item.__msh = {
				item: item,
				label: label,
				action: option[1],
				tooltip: option[2] || null,
				icon: option[3] || null,
				activate: function() {
					self.closeMenu();
					self.editor.focusEditor();
					this.action();
				}
			};
			label = label.replace(/_([a-zA-Z0-9])/, "<u>$1</u>");
			if (label != option[0])
				keys.push([ RegExp.$1, item ]);
			label = label.replace(/__/, "_");
			var td1 = doc.createElement("td");
			if (HTMLArea.is_ie)
				td1.unselectable = "on";
			item.appendChild(td1);
			td1.className = "icon";
			if (item.__msh.icon)
			{
				var t = HTMLArea.makeBtnImg(item.__msh.icon, doc);
				td1.appendChild(t);
				// td1.innerHTML = "<img align='middle' src='" + item.__msh.icon + "' />";
			}
			var td2 = doc.createElement("td");
			if (HTMLArea.is_ie)
				td2.unselectable = "on";
			item.appendChild(td2);
			td2.className = "label";
			td2.innerHTML = label;
			item.onmouseover = function() {
				this.className += " hover";
				self.editor._statusBarTree.innerHTML = this.__msh.tooltip || '&nbsp;';
			};
			item.onmouseout = function() { this.className = "item"; };
			item.oncontextmenu = function(ev) {
				this.__msh.activate();
				if (!HTMLArea.is_ie)
					HTMLArea._stopEvent(ev);
				return false;
			};
			item.onmouseup = function(ev) {
				var timeStamp = (new Date()).getTime();
				if (timeStamp - self.timeStamp > 500)
					this.__msh.activate();
				if (!HTMLArea.is_ie)
					HTMLArea._stopEvent(ev);
				return false;
			};
			//if (typeof option[2] == "string")
			//item.title = option[2];
		}
	}

	if (!HTMLArea.is_ie) {
		/* FIXME: I think this is to stop the popup from running off the bottom of the screen?
		var dx = x + div.offsetWidth - window.innerWidth + 4;
		var dy = y + div.offsetHeight - window.innerHeight + 4;
		// alert('dy= (' + y + '+' + div.offsetHeight + '-' + window.innerHeight + ' + 4 ) = ' + dy);
		if (dx > 0) x -= dx;
		if (dy > 0) y -= dy;
		*/
		 // <MT deal with context menu appearing past the right side of the screen
		 // also, create visibility rules because offsetWidth for FF makes the context menu flash
		div.style.visibility = 'hidden';
		var w = div.offsetWidth;
		if ((x + w) > winX) {
			x = x - w;
		}
		 // >MT 
		div.style.left = x + "px";
		div.style.top = y + "px";
		 // <MT 
		div.style.visibility = 'visible';
		 // >MT 
	} else {
		// To get the size we need to display the popup with some width/height
		// then we can get the actual size of the div and redisplay the popup at the
		// correct dimensions.
		this.iePopup.show(ev.screenX, ev.screenY, 300,50);
		var w = div.offsetWidth;
		var h = div.offsetHeight;
		this.iePopup.show(ev.screenX, ev.screenY, w, h);
	}

	this.currentMenu = div;
	this.timeStamp = (new Date()).getTime();

	HTMLArea._addEvent(document, "mousedown", documentClick);
	HTMLArea._addEvent(this.editordoc, "mousedown", documentClick);
	if (keys.length > 0)
		HTMLArea._addEvent(this.editordoc, "keypress", keyPress);

	HTMLArea._stopEvent(ev);
	return false;
};

/*
 * MindTouch DekiWiki - a commercial grade open source wiki
 *  derived from MediaWiki (www.mediawiki.org)
 * Copyright (C) 2006 MindTouch, Inc.
 * www.mindtouch.com  oss@mindtouch.com
 *
 * For community documentation and downloads visit www.opengarden.org;
 *  please review the licensing section.
 *
 * 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.
 * http://www.gnu.org/copyleft/gpl.html
 */

/**
  * MindTouch additions/changes
  *
  */

HTMLArea.loadStyle("mind-touch.css", "MindTouch");
  
function MindTouch(editor) {
  this.editor = editor;
  var dir = HTMLArea.getPluginDir('MindTouch');
  if (typeof HTMLArea.Config.MTregisterButton != 'function') {
    HTMLArea._loadback(dir + "/mt-new-xinha.js", function() { });
    HTMLArea._loadback(dir + "/xhtml-handling.js", function() { });
    HTMLArea._loadback(dir + "/mt-cng-xinha.js", function() { resetTableButtons(editor) });
  } else resetTableButtons(editor);
};

String.prototype.htmlTrim = function() {
    return this.replace(/^[\s\xA0]+/, '').replace(/[\s\xA0]+$/, '');
};

MindTouch.prototype.onKeyPress = function(ev) {
  if (ev.keyCode == 13 && !ev.shiftKey)
    return this.handleEnter(ev);
};

MindTouch.checkLink = function(node) {
  window.open(MindTouch.getUrlFromName(node.href, true));
};

MindTouch.normalizeLink = function(node, editor) {
  function stripHost(host, href) {
    if (href.indexOf(host) != 0)
      return false;
    href = href.substr(host.length+1);
    if (href.indexOf('attachments/') == 0 && typeof getAttachmentUrl == 'function')
      getAttachmentUrl(href, node);
    MindTouch.setLink(editor, node, href);
    return true;
  };

  if (node.name != "") {
    node.id = node.name;
    node.name = "";
  }
  if (node.className == 'site')
    return;
  var isA = node.tagName.toLowerCase() == 'a';
  var attrName = isA ? 'href' : 'src';
  var attrVal = node[attrName];
  if (isA && node.innerHTML.replace(/(\s|&nbsp;|<br\s*\/?>)/gi).length == 0) {
      HTMLArea.removeTag(node);
      return;
  }
  if (isA && !attrVal) {
      HTMLArea.removeTag(node);
      return;
  }
  var host = document.location.protocol + '//' + document.location.host;
  if (stripHost(editor.config.baseHref, attrVal)) {}
  else if (stripHost(host, attrVal)) {}
  else if (!MindTouch.isLinkExternal(attrVal) && attrVal.indexOf(MindTouch.mksInternalPrefix) != 0)
    MindTouch.setLink(editor, node, attrVal);
  else {
    if (HTMLArea.is_gecko && isA && node.className.indexOf('internal') == 0 && typeof node.title != 'undefined' && node.title.length > 3 && (node.title.substring(0,3) == '../' || node.title.substring(0,2) == './')) {
      // fix issue with gecko when when pasting href to relative internal links
      var title = node.title;
      var href = MindTouch.hrefDecode(node.href);
      if (href.indexOf(MindTouch.mksInternalPrefix) == 0) href = href.substr(MindTouch.mksInternalPrefix.length);
      if (title != href) {
        var stripTitle = title.replace(/^\.\.?\//,'');
        if (href == stripTitle)
          node.href = MindTouch.hrefEncode(MindTouch.mksInternalPrefix + title);
      }
    }
    MindTouch.setLink(editor, node);
  }
  node.onmouseover = null;
  node.onmouseout = null;
  node.onclick = null;

  var children = node.getElementsByTagName("font");
  for (var i = 0; i < children.length; ++i) {
    var font = children[i];
    if (font.size == "" && font.face == "" && font.color != "")
      HTMLArea.removeTag(font);
  }
  children = node.getElementsByTagName("span");
  for (var i = 0; i < children.length; ++i) {
    var span = children[i];
    var text = HTMLArea.getInnerText(span).trim();
    if (text.length == 0)
      HTMLArea.removeFromParent(span);
  }
  // remove urlexpansion span
  var nextEl = node.nextSibling;
  if (nextEl && nextEl.nodeType == 1 && /^span$/i.test(nextEl.tagName) && /^urlexpansion$/i.test(nextEl.className))
    HTMLArea.removeFromParent(nextEl);
  var p = node.parentNode;
  if (p.nodeType == 1 && /^(li|td|th|p|blockquote|dl|pre)$/i.test(p.tagName) && p.innerHTML != p.innerHTML.replace(/<\/a>\s*(<\/(li|td|th|p|blockquote|dl|pre)>|$)/ig, "</a>&nbsp;$1")) {
    nextEl = node.nextSibling;
    if (!nextEl || (!nextEl.nextSibling && nextEl.nodeType == 3 && nextEl.data.trim().length == 0)) {
      if (nextEl) HTMLArea.removeFromParent(nextEl);
      node.parentNode.appendChild(HTMLArea.xhtml_createNBSP(node));
    }
  }
};

MindTouch.getPageTitle = function(title) {
  if (typeof title == 'undefined')
    return _page_titleName;
  title = title.replace(/_/g,' ');
  title = title.replace(/\x2F\x2F/g,'%2F%2F');
  var arr = title.split("/");
  var t = "";
  if (arr.length > 1) {
    t = arr [arr.length-1];
  } else {
    t = title;
  }
  var tt = unescape(t);
  if (tt != t)
    t = tt.utf8ToString();
  return t;
};

MindTouch.getPagePath = function(title, alsoNamespace) {
  if (typeof title == 'undefined')
    return _page_titlePath;
  title = title.replace(/_/g,' ');
  title = title.replace(/\x2F\x2F/g,'%2F%2F');
  var arr = title.split("/");
  var path = "";
  if (arr.length > 1) {
    for (i = 0; i < arr.length-1; i++)
      path += arr[i] + "/";
    path = path.substr (0, path.length-1);
  } else {
    if (alsoNamespace) {
      arr = title.split(":");
      if (arr.length > 1) return arr[0];
    }
    path = "/";
  }
  var tt = unescape(path);
  if (tt != path)
    path = tt.utf8ToString();
  return tt;
};

MindTouch.isLinkExternal = function(href) {
  var re = /^(http|https|ftp|irc|gopher|news|mailto):/i;
  return href.match(re) != null;
};

MindTouch.mksInternalPrefix = "mks://localhost/";
MindTouch.hrefEncode_regEx = HTMLArea.compileRegex(/[ \xA0\x20\x23\x26\x2B\x2E\x3C\x3E\x40\x5B\x5C\x5D\x7B\x7D\x7C]/g);
MindTouch.hrefEncode = function(str) {
  function hex(d) { return (d < 16) ? ("0" + d.toString(16)) : d.toString(16); };

  if(typeof str.replace == 'undefined') str = str.toString();
  var isInternal = str.indexOf(MindTouch.mksInternalPrefix) == 0;
  if (isInternal) {
    str = str.substr(MindTouch.mksInternalPrefix.length);
    str = str.utf8URL();
    str = str.replace(/\x2F\x2F/g, "%2f%2f");
    str = str.replace(/\x2E/g, "%2e");
    str = MindTouch.mksInternalPrefix + str;
  }
  return str;
};

MindTouch.hrefDecode = function(str) {
  if(typeof str.replace == 'undefined') str = str.toString();
  str = str.replace(/&nbsp;/ig, " ");
  if (str.indexOf(MindTouch.mksInternalPrefix) == 0) {
    str = unescape(str);
    str = str.utf8ToString();
    str = str.replace(/_/ig, " ");
  }
  return str;
};

MindTouch.extractName = function(href) {
  var isE = MindTouch.isLinkExternal(href);
  if (!isE) {
    if (href.indexOf(MindTouch.mksInternalPrefix) == 0)
      href = href.substr(MindTouch.mksInternalPrefix.length);
    while (href.charAt(0) == '/') href = href.substr(1);
    if (href.indexOf('index.php?title=') == 0)
      href = href.substr('index.php?title='.length);
    while (href.charAt(0) == '/') href = href.substr(1);
    if (href.toLowerCase().indexOf('file:///') == 0)
      href = 'File:' + href.substr('file:///'.length);
    href = href.replace(/&[a-z]+=.*$/i, '');
    href = href.replace(/_/g, ' ');
    var n = unescape(href);
    if (n != href)
      href = n.utf8ToString();
  }
  return href;
};

MindTouch.getUrlFromName = function(href, addContext) {
  var isE = MindTouch.isLinkExternal(href);
  if (!isE) {
    href = MindTouch.extractName(href).replace(/ /g,'_');
    if (href.indexOf('&') > 0 || href.indexOf('+') > 0 || href.indexOf('?') > 0 || href.indexOf('#') > 0 ||
      href.indexOf('\\') > 0 || href.indexOf('.') == 0 || href.indexOf('//') > 0 || href.indexOf('%') > 0
    )
      href = 'index.php?title=' + href.utf8URL();
    else
      href = href.utf8URL();
    href = '/' + href;
    if (addContext) {
      if (typeof contextTopicID != 'undefined' && contextTopicID)
        href += "&contextid=" + contextTopicID;
      else if (typeof _page_ID != 'undefined' && _page_ID)
        href += "&contextid=" + _page_ID;
    }
  }
  return href;
};

MindTouch.setLink = function(editor, node, href, text) {
  if (node.className == 'site')
    return;

  var isA = node.tagName.toLowerCase() == 'a';
  var attrName = isA ? 'href' : 'src';
  var oldHRef = MindTouch.hrefDecode(node[attrName]);

  // is not endcoded
  if (typeof href == 'undefined' && MindTouch.hrefEncode(oldHRef) != node[attrName])
    href = oldHRef;

  if (oldHRef.indexOf(MindTouch.mksInternalPrefix) == 0)
    oldHRef = oldHRef.substr(MindTouch.mksInternalPrefix.length);
  var oldText = HTMLArea.getInnerText(node);

  if (typeof href != 'undefined') {
    var isE = MindTouch.isLinkExternal(href);
    if (!isE) {
      if (isA)
        href = MindTouch.mksInternalPrefix + MindTouch.extractName(href).replace(/ /g,'_');
      if (!isA) {
        href = MindTouch.getUrlFromName(href,href.indexOf('./') > 0 || href.indexOf('../') > 0);
        node.alt = unescape(MindTouch.extractName(href).substr('file:'.length)).utf8ToString();
        href += '&action=thumb';
        if (parseInt(node.style.width) > 160 || parseInt(node.style.height) > 160)
            href += "&size=full";
      }
    } else {
        node.alt = unescape(href);
    }
    var html = node.innerHTML;
    node[attrName] = isA ? MindTouch.hrefEncode(href) : href;
    if (node.innerHTML != html) node.innerHTML = html;
  }

  if (isA) {
    node.title = MindTouch.hrefDecode(node.href);
    var isImg = node.firstChild && node.firstChild.nodeType == 1 && node.firstChild.tagName.toLowerCase() == 'img';
    if (node.title.indexOf(MindTouch.mksInternalPrefix) == 0) {
      node.title = node.title.substr(MindTouch.mksInternalPrefix.length);
      if (node.className.indexOf('internal') != 0 && !isImg)
        node.className = 'internal';
    }
    else if (node.href != "")
      if (!isImg) node.className = 'external';
    else
      node.className = '';

    if (typeof text == 'undefined' && oldHRef == oldText && node.href != oldHRef)
      text = node.title;

    if (typeof text != 'undefined' && text != "" && HTMLArea.getInnerText(node) != text 
      && !(node.firstChild && node.firstChild.nodeType == 1 && node.firstChild.tagName.toLowerCase() == 'img')
    )
      if (HTMLArea.is_ie)
        node.innerText = text;
      else
        node.textContent = text;
  } else if (editor) {
    var ialign = node.getAttribute('ialign');
    var divWrap = node.parentNode;
    if (divWrap.tagName.toLowerCase() == 'a')
       divWrap = divWrap.parentNode;
    var isDivWrap = divWrap.tagName.toLowerCase() == 'div';
    if (ialign != null) {
      if (ialign.substring(1) == 'nowrap') {
        var check = false;
        if (!isDivWrap) {
          divWrap = node.ownerDocument.createElement('div');
          var toWrap = node;
          if (node.parentNode.tagName.toLowerCase() == 'a')
              toWrap = node.parentNode;
          HTMLArea.xhtml_surroundNode(toWrap, divWrap);
          check = true;
        }
        if (divWrap.className != node.getAttribute('ialign')) {
          divWrap.className = node.getAttribute('ialign');
          check  = true;
        }
        node.removeAttribute('className');
        if (check && editor) HTMLArea.makeXHTML(divWrap, editor.makeXHTMLContext(false));
      } else {
        if (isDivWrap && divWrap.firstChild == divWrap.lastChild && divWrap.firstChild == node)
          HTMLArea.removeTag(divWrap);
        node.className = node.getAttribute('ialign');
      }
      /*
       * MT: royk
       * I'm going to need spans/divs later for polaroid effect
      */
    } else {
      if (isDivWrap && divWrap.firstChild == divWrap.lastChild && divWrap.firstChild == node)
        HTMLArea.removeTag(divWrap);
    }
  }
};

MindTouch.insertHTML = function(range, html) {
  if (HTMLArea.is_ie)
    range.pasteHTML(html);
  else {
    range.deleteContents();
    var node = range.startContainer;
    var pos = range.startOffset;
    var div = node.ownerDocument.createElement('div');
    div.innerHTML = html;
    switch (node.nodeType) {
    case 3: // Node.TEXT_NODE
      // we have to split it at the caret position.
      node = node.splitText(pos);
      node.parentNode.insertBefore(div.firstChild, node);
      break;
    case 1: // Node.ELEMENT_NODE
      node.insertBefore(div.firstChild, node.childNodes[pos]);
      break;
    }
  }
};

MindTouch.selectNode = function(range, node) {
  if (HTMLArea.is_ie)
    range.moveToElementText(node);
  else
    range.selectNode(node);
};

MindTouch.getTextNodeAndOffset = function(val) {
  var root = val.node;
  var cur = root;
  var offset = val.offset;
  while (true) {
    if (cur.nodeType == 3) {
      var curlen = cur.nodeValue.length;
      if (curlen >= offset) {
        val.node = cur;
        val.offset = offset;
        return;
      }
      offset -= curlen;
    }
    if (cur.firstChild)
      cur = cur.firstChild;
    else if (cur.nextSibling)
      cur = cur.nextSibling;
    else {
      while (!cur.parentNode.nextSibling)
        cur = cur.parentNode;
      cur = cur.parentNode.nextSibling;
    }
  }
};

MindTouch.setStart = function(range, node, offset) {
  if (HTMLArea.is_ie) {
    var r = range.duplicate();
    r.moveToElementText(node);
    r.collapse();
    r.move('character', offset);
    range.setEndPoint('EndToStart', r);
    range.setEndPoint('StartToStart', r);
  } else {
    var val = { node: node, offset: offset };
    MindTouch.getTextNodeAndOffset(val);
    if (val.offset) {
      var l = val.node.nodeValue.length - val.offset;
      range.selectNode(val.node);
      range.collapse(false);
      if (l > 0)
        range.setStart(val.node, val.offset);
    } else {
      range.selectNode(val.node);
      range.collapse(true);
    }
  }
};

MindTouch.setEnd = function(range, node, offset) {
  if (HTMLArea.is_ie) {
    var r = range.duplicate();
    r.moveToElementText(node);
    r.collapse();
    r.moveEnd('character', offset);
    range.setEndPoint('EndToEnd', r);
  } else {
    var val = { node: node, offset: offset };
    MindTouch.getTextNodeAndOffset(val);
    var start = range.startContainer;
    var sOffset = range.startOffset;
    if (val.offset) {
      var l = val.node.nodeValue.length - val.offset;
      if (l > 0)
        range.setEnd(val.node, val.offset);
      else {
        range.selectNode(val.node);
        range.collapse(false);
        range.setStart(start, sOffset);
      }
    } else {
      range.selectNode(val.node);
      range.collapse(true);
      range.setStart(start, sOffset);
    }
  }
};

MindTouch.cloneRange = function(range) {
  return HTMLArea.is_ie ? range.duplicate() : range.cloneRange();
};

MindTouch.setEndToEnd = function(r, r2) {
  if (HTMLArea.is_ie)
    r.setEndPoint("EndToEnd", r2);
  else
    r.setEnd(r2.endContainer, r2.endOffset);
};

MindTouch.setEndToStart = function(r, r2) {
  if (HTMLArea.is_ie)
    r.setEndPoint("EndToStart", r2);
  else
    r.setEnd(r2.startContainer, r2.startOffset);
};

MindTouch.commonAncestorContainer = function(range) {
  if (!range) return range;
  if (HTMLArea.is_ie) {
    if (typeof range.length != 'undefined') return range.item(0);
    var ret = range.parentElement();
    if (range.text.length > ret.innerText.length)
      ret = ret.parentNode;
    return ret;
  } else
    return range.commonAncestorContainer;
};

MindTouch.prototype.handleEnter = function(ev) {
  var editor = this.editor;
  var sel = editor._getSelection();
  var block = editor._getFirstAncestor(sel, ['p','h1','h2','h3','h4','h5','h6','li','dd','dl','pre','blockquote','tr','td','body']);
  if (!block || block.tagName.toLowerCase() == 'body') {
    if (HTMLArea.is_gecko && sel.focusNode.nodeType == 3 && sel.focusNode.parentNode.tagName.toLowerCase() == 'body') {
      editor.execCommand('formatblock', false, 'p');
      block = editor._getFirstAncestor(sel, ['p','h1','h2','h3','h4','h5','h6','li','dd','dl','pre','blockquote','tr','td','body']);
    } else
      return;
  }
  var innerTxt = HTMLArea.getInnerText(block);
  var userLink = '<a class="internal" title="User:'+_userName+'" href="mks://localhost/User:'+_userName+'">'+_userName+'</a>';
  innerTxt = editor.findAndReplace('~~~~',userLink+' '+_today,block,innerTxt);
  innerTxt = editor.findAndReplace('~~~',userLink,block,innerTxt);
  switch (block.tagName.toLowerCase()) {
  case 'p':
    handleP();
    break;
  case 'li':
    handleLi();
    return;
  default:
    return;
  }

  function handleLi() {
    if (HTMLArea.is_ie)
      return;
    var r = editor._createRange();
    if (r.startContainer != r.endContainer) return;
    var node = r.startContainer;
    if (node.nodeType != 3 || node.data.substr(r.startOffset).htmlTrim().length != 0)
      return;
    var n = node.nextSibling;
    if (n && n.nodeType == 1 && n.tagName.toLowerCase() == 'ul') {
      node.data = node.data.replace(/(\s|&nbsp;)+$/,'');
      r.setEnd(node, node.data.length);
      r.setStart(node, node.data.length);
      var sel = editor._getSelection();
      sel.removeAllRanges();
      sel.addRange(r);
      node.parentNode.insertBefore(node.ownerDocument.createElement('br'), n);
    }
  };

  function handleP() {
    /* FF is broken, removing
    var len = 2, pre = innerTxt.substring(0, len);

    function findNonSpace() {
      while (true) {
        var ch = innerTxt.substring(len, len+1);
        if (ch != ' ') break;
        ++len;
      }
    };
    
    if (pre == '- ' || pre == '* ' || pre == '~ ' || pre == '+ ' || pre == '= ') {
      findNonSpace();
      editor.insertList(block, len, 'insertunorderedlist');
      return;
    }
    len = 3;
    pre = innerTxt.substring(0, len);
    if (pre == '1. ' || pre == '1) ') {
      findNonSpace();
      editor.insertList(block, len, 'insertorderedlist');
      return;
    }
    len = 4;
    pre = innerTxt.substring(0, len);
    if (pre == '1). ') {
      findNonSpace();
      editor.insertList(block, len, 'insertorderedlist');
      return;
    }
    */
  };
};

resetTableButtons = function(editor) {
  var cfg = editor.config;
  var bl = TableOperations.btnList;
  var self = editor.plugins.TableOperations;
  var toolbar = ["linebreak"];
  for (var i = 0; i < bl.length; ++i) {
    var btn = bl[i];
    if (btn) {
      var id = "TO-" + btn[0];
      HTMLArea.Config.MTregisterButton(cfg, id, HTMLArea._lc(btn[2], "TableOperations"), editor.imgURL(btn[0] + ".gif", "TableOperations"), false,
        function(editor, id) {
          // dispatch button press event
          self.buttonPress(editor, id);
        }, btn[1], false);
      toolbar.push(id);
    }
  }
};

MindTouch._pluginInfo = {
	name          : "MindTouch Extensions",
	version       : "1.0",
	developer     : "Urs C Muff",
	developer_url : "http://www.mindtouch.com/",
	license       : "htmlArea"
};

/*
 * MindTouch DekiWiki - a commercial grade open source wiki
 *  derived from MediaWiki (www.mediawiki.org)
 * Copyright (C) 2006 MindTouch, Inc.
 * www.mindtouch.com  oss@mindtouch.com
 *
 * For community documentation and downloads visit www.opengarden.org;
 *  please review the licensing section.
 *
 * 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.
 * http://www.gnu.org/copyleft/gpl.html
 */

HTMLArea.RE_noHeaderCmd = /insertorderedlist|insertunorderedlist|indent|outdent|inserttable|insertimage|fontname|fontsize|bold|italic|underline|strikethrough|forecolor|hilitecolor|subscript|superscript|mksLink|mksInsertImage|mksFont|mksSize|mksAlign|mksFontColor|mksBackColor|mostemplates|moswidgets/i;

HTMLArea.prototype._OnResize = function() {
  this._htmlArea.style.height = getEditorHeight(this) + "px";
};

HTMLArea.prototype._OnMode = function(mode) {
  var searchBox = document.getElementById('searchBox');
  switch (mode) {
    case "textmode":
      //alert('switch to textmode');
      break;
    case "wysiwyg":
      //alert('switch to wysiwyg');
      break;
    case "maximize":
      if (searchBox) searchBox.style.display = 'none';
      //alert('switch to maximize');
      break;
    case "restore":
      if (searchBox) searchBox.style.display = 'inline';
      //alert('switch to restore');
      this._OnResize();
      break;
  }
};

HTMLArea.prototype.doOnAllElements = function(sel, tagNames, func) {
  var r = this._createRange(sel);
  var r2 = MindTouch.cloneRange(r);
  HTMLArea.is_ie ? r.collapse(true) : r.collapse(false);
  var start = MindTouch.commonAncestorContainer(r);
  HTMLArea.is_ie ? r2.collapse(false) : r2.collapse(true);
  var end = MindTouch.commonAncestorContainer(r2);
  if (start == end) {
    var node = this._getFirstAncestor(sel, tagNames);
    if (node) func(node);
  } else
    this.doUntilEnd(start, end, tagNames, func);
};

HTMLArea.prototype.doUntilEnd = function(cur, end, tagNames, func) {
  if(typeof tagNames == 'string')
    tagNames = [tagNames];
  while (true) {
    if (cur.nodeType == 1 && tagNames.contains(cur.tagName.toLowerCase())) 
      func(cur);

    if (cur == end)
      return;

    if (cur.firstChild && cur.nodeType == 1)
      cur = cur.firstChild;
    else if (cur.nextSibling)
      cur = cur.nextSibling;
    else {
      while (cur.parentNode && !cur.parentNode.nextSibling)
        cur = cur.parentNode;
      if (!cur.parentNode)
        return;
      cur = cur.parentNode.nextSibling;
    }
  }
};

// disallow formatting in certain cases
HTMLArea.prototype.preExecCommand = function(p) {
  var ancestors = this.getAllAncestors();
  if (p.cmdID == "formatblock") {
    if (this._isInAny(ancestors,["ul","ol","table"])) {
      // alert('WARNING: This actions is not allowed on lists or tables');
      if (/p/.test(p.param)) {
        this.doOnAllElements(this._getSelection(), ['span'], function(node) {
          if (/header_/.test(node.className))
            HTMLArea.removeTag(node);
        });
        return false;
      }
    }
    if (this._isInAny(ancestors,["blockquote"]))
      p.cmdID = "outdent";
    else if (/blockquote/i.test(p.param))
      p.cmdID = "indent";
  }
  if (typeof HTMLArea.RE_noHeaderCmd != "undefined" && HTMLArea.RE_noHeaderCmd.test(p.cmdID) 
    && this._isInAny(ancestors,["h1","h2","h3","h4","h5","h6"])) {
    // alert('WARNING: This actions is not allowed on headings');
    return false;
  }
  if (/^justify.*$/.test(p.cmdID) && this._doc.queryCommandState(p.cmdID)) {
    var changed = false;
    this.doOnAllElements(this._getSelection(), ['p','h1','h2','h3','h4','h5','h6','div','li','td','tr'], function(node) {
      if (/^div$/i.test(node.tagName))
        HTMLArea.removeTag(node);
      else if (/^(h[1-6]|p)$/i.test(node.tagName))
        node.align = "";
      changed = true;
    });
    if (changed) {
      this.updateToolbar();
      return false;
    }
  }
  if (p.cmdID == "fontname") {
    var params = p.param.split('|');
    var face = params[0];
    this.focusEditor();
    this._doc.execCommand("fontname", p.UI, face);
    var parent = this.getParentElement().parentNode;
    var editor = this;
    HTMLArea.applyToAll(parent, function(node) {
      if (node.nodeType != 1) return;
      if (node.style.fontFamily)
        HTMLArea.xhtml_checkFont(editor, node, node.style.fontFamily);
      else if (node.face)
        HTMLArea.xhtml_checkFont(editor, node, node.face);
    });
    this.updateToolbar();
    return false;
  }
  return true;
};

HTMLArea.prototype.getSelectionBoundaries = function(b) {
  var r = this._createRange();
  if (HTMLArea.is_ie) {
    var rStart = r.duplicate();
    var rEnd = r.duplicate();
    rStart.collapse();
    rEnd.collapse(false);
    b.Start = rStart.parentElement();
    b.End = rEnd.parentElement();
  } else {
    b.Start = r.startContainer;
    b.End = r.endContainer;
  }
};

HTMLArea.prototype.postExecCommand = function(cmdID, UI, param) {
  if (cmdID == 'formatblock' && /pre/.test(param)) {
    var b = {};
    this.getSelectionBoundaries(b);
    while (b.Start && (b.Start.nodeType != 1 || b.Start.tagName.toLowerCase() != 'pre'))
      b.Start = b.Start.parentNode;
    while (b.End && (b.End.nodeType != 1 || b.End.tagName.toLowerCase() != 'pre'))
      b.End = b.End.parentNode;
    if (b.Start && b.End && b.Start != b.End) {
      var n = b.Start.nextSibling;
      var p = n.parentNode;
      var ins = n.nextSibling;
      while (true) {
        var nn = n.nextSibling;
        var end = n == b.End;
        if (n.nodeType == 1) {
          b.Start.appendChild(b.Start.ownerDocument.createElement('br'));
          b.Start.appendChild(n);
          HTMLArea.removeTag(n);
        } else
          n.parentNode.removeChild(n);
        n = nn;
        if (end)
          break;
      }
    }
  }

  var root = MindTouch.commonAncestorContainer(this._createRange());
  if (root && root.nodeType == 3)
    root = root.parentNode;
  if (root && root.nodeType == 1) {
    var check = false;
    var sel = this._getSelection();
    var hTag = this._getFirstAncestor(sel, ['h1','h2','h3','h4','h5','h6']);
    if (hTag && HTMLArea.getInnerText(hTag).htmlTrim().length != 0) {
      root = hTag;
      check = true;
    } else {
      var listTag = this._getFirstAncestor(sel, ['ol','ul']);
      switch (cmdID) {
      case "indent":
      case "insertunorderedlist":
      case "insertorderedlist":
        if (listTag && HTMLArea.getInnerText(listTag).htmlTrim().length != 0) {
          root = listTag;
          if (root.parentNode.tagName.toLowerCase() != 'body')
            root = root.parentNode;
          if (root.parentNode.tagName.toLowerCase() != 'body')
            root = root.parentNode;
          check = true;
        }
        break;
      }
    }
    if (!check && cmdID == "formatblock" && this._isInAny(this.getAllAncestors(),["ul","ol","table"]))
      check = true;
    if (check)
      HTMLArea.makeXHTML(root, this.makeXHTMLContext(false));
  }
  return true;
};

HTMLArea.applyToAll = function(node, f) {
  f(node);
  var child = node.firstChild;
  while (child != null) {
    var n = child.nextSibling;
    HTMLArea.applyToAll(child, f);
    child = n;
  }
};

HTMLArea.prototype._onColorChange = function(cmdID, color) {
  var editor = this;
  if (color == '-None-') {
    var tags = editor.getSelectionTagsF("font",cmdID == "forecolor" ? function(el) { return el.color != ""; } : function(el) { return el.style.backgroundColor != ""; });
    if (typeof tags.tag != 'undefined') {
      if (editor.getHTMLText(HTMLArea.getOuterHTML(tags.tag)) == editor.getHTMLText(editor.getSelectedHTML()))
        HTMLArea.removeTag(tags.tag);
      else
        editor.splitOutRange(tags.tag, editor._createRange(editor._getSelection()));
    } else {
      var p = editor._getFirstAncestorF(editor._getSelection(),function(el) { return el.style.backgroundColor != ""; });
      if (p && p.style.backgroundColor != "")
        p.style.backgroundColor = "";
      else
        editor._doc.execCommand(cmdID, false, HTMLArea.is_ie ? "none" : '-');
    }
  } else
    editor._doc.execCommand(cmdID, false, color);
  if (HTMLArea.is_gecko && cmdID == "hilitecolor") {
    HTMLArea.replaceTagsF(editor.getParentElement().parentNode,function (el) {
      if (!/^span$/i.test(el.tagName) || el.style.backgroundColor == "")
        return null;
      var ret = editor._doc.createElement("font");
      ret.style.backgroundColor = el.style.backgroundColor;
      return HTMLArea.cloneNode(el,ret);
    });
  }
};

HTMLArea.debugTestPage = function(editor, url) {
  var a = window.XMLHttpRequest ? new XMLHttpRequest() : window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : null;
  a.open("GET", url, true);
  a.onreadystatechange = function() {
    if (a.readyState != 4) 
      return;
    var html = a.responseText;
    if (html.match(/((.|\n)*?)<body>((.|\n)*?)<\/body>((.|\n)*?)/ig)) {
      html = RegExp.$3.trim();
    }
    editor.setHTML(editor.inwardHtml(html));
    var context = editor.makeXHTMLContext(false);
    HTMLArea.makeXHTML(null, context);
    _starttime = new Date().getTime();
    var html = editor.getXHTML();
    _endtime = new Date().getTime();
    var getHTML_timeDiff = _endtime - _starttime;
    alert("make XHTML: " + context._timeDiff + " ms\nget HTML: " + getHTML_timeDiff + "ms");
  }
  a.send(null);
  delete a;
};

HTMLArea.prototype.editorLoaded = function() {
  var editor = this;
  if (this._doc.body == null) {
    setTimeout(function() { editor.editorLoaded(); }, 50);
    return;
  }

  if (HTMLArea.is_ie) {
    this._doc.body.onpaste = function (event) {
      event = editor._iframe.contentWindow.event;
      var sel = editor._getSelection();
      var r = editor._createRange(sel);
      var r2 = r.duplicate();
      var r3 = r.duplicate();
      r2.collapse();
      r2.move('character', -1);
      r3.collapse(false);
      r3.move('character', 1);
      try {
        r2.pasteHTML("<span class='pasteTag start'>|</span>");
        r3.pasteHTML("<span class='pasteTag end'>|</span>");
      } catch (e) {
//        debugger;
      }
      
      if (event.shiftKey) {
        var clip = window.clipboardData;
        var text = clip.getData('Text');
        clip.clearData();
        clip.setData('Text',text);
      }
    };
  }

  /* >MT: DEBUG 
  HTMLArea.debugTestPage(editor, "/editor/test-cases/test-x.htm");
  //HTMLArea.debugTestPage(editor, "/editor/test-cases/test-1.html");
  //HTMLArea.debugTestPage(editor, "/editor/test-cases/test-2 (real world).htm");
  //HTMLArea.debugTestPage(editor, "/editor/test-cases/test-3 (long 477k).html");
  //HTMLArea.debugTestPage(editor, "/editor/test-cases/test-all-styles.htm");
  //HTMLArea.debugTestPage(editor, "/editor/test-cases/test-4.htm");

  HTMLArea.makeXHTML(null, editor.makeXHTMLContext(false));
  /* <MT */
  if (window.Widget)
    Widget.initializeEditor(this._doc, this);

  if (this._readOnly) {
      try {
        if (HTMLArea.is_gecko) this._doc.designMode = 'off';
        else this._doc.body.contentEditable = false;
      } catch (e) {}
  }
  this._doc.body.id = "topic";
  if (typeof doCheckChanges == 'function')
    doCheckChanges(this);
  if (typeof this._OnResize == 'function')
    this._OnResize();
  setTimeout(function() {
    editor.focusEditor();
    editor.updateToolbar();
    var h1 = editor._doc.body.firstChild;
    while (h1 && h1.nodeType == 3) h1 = h1.nextSibling;
    if (h1 && h1.tagName.toLowerCase() == 'h1') {
      var el = h1.nextSibling;
      while (el && el.nodeType == 3) el = el.nextSibling;
      if (!el) return;
      var sel = editor._getSelection();
      var isCtrl = false;
      if (el.nodeType == 1) {
        var tag = el.tagName.toLowerCase();
        isCtrl = (tag == 'table' || tag != 'img' || tag == 'div');
      }
      if (!isCtrl)
        editor.selectNodeContents(el);
      setTimeout(function() {
        editor.focusEditor();
        if (!isCtrl)
          editor.selectNodeContents(el);
        var range = editor._createRange(sel);
        if (HTMLArea.is_ie) {
          if (sel.type != "Control" && range) {
            range.collapse();
            range.select();
          }
        } else {
          sel.removeAllRanges();
          range.collapse(true);
          sel.addRange(range);
        }
        editor.updateToolbar();
      }, 100);
    }
  }, 600);
};

HTMLArea.prototype.getPath = function(el) {
  if (typeof el == "undefined" || el == null)
    return "";
  var tagName = el.tagName;
  if (tagName == "BODY")
    return "";
  var index = 0;
  var s = el.previousSibling;
  while (s != null) {
    if (s.tagName == tagName)
      ++index;
    s = s.previousSibling;
  }
  var parentPath = this.getPath(el.parentNode);
  var path = parentPath + "/" + tagName;
  if (index > 0)
    path += "[" + index + "]"; 
  return path;
};

HTMLArea.prototype.selectPath = function(path,el) {
  if (path.charAt(0) == "/") {
    el = this._doc.body;
    path = path.substr(1);
  }
  var pos1 = path.indexOf('[');
  var pos2 = path.indexOf('/');
  var remain = "";
  var split;
  if (pos1 > 0 && pos2 > 0)
    split = pos1 < pos2 ? pos1 : pos2;
  else if (pos1 > 0)
    split = pos1;
  else if (pos2 > 0)
    split = pos2;
  else
    split = -1;
  var index = 0;
  if (split > 0) {
    remain = path.substr(split+1);
    path = path.substr(0,split);
    if (split == pos1) {
      pos2 = remain.indexOf(']');
      index = parseInt(remain.substr(0,pos2));
      remain = remain.substr(pos2+1);
      if (remain.charAt(0) == "/")
        remain = remain.substr(1);
    }
  }
  var c = el.firstChild;
  var i = 0;
  while (c != null) {
    if (c.tagName == path) {
      if (index == i)
        break;
      ++i;
    }
    c = c.nextSibling;
  }
  if (c == null)
    return null;
  if (remain != "")
    return this.selectPath(remain,c);
  return c;
};

HTMLArea.prototype._storeUndoCursor = function(state) {
  var sel = this._getSelection();
  var range = this._createRange(sel);
  var el = this.getParentElement(sel,range);
  var path = this.getPath(el);
  if (path == "")
    path = "/";
  var textEdit = el.parentTextEdit == null ? el : el.parentTextEdit;
  state.scrollTop = textEdit.scrollTop;
  state.scrollLeft = textEdit.scrollLeft;
  state.path = path;
  state.range = this.getRange();
  // alert("store #" + this._undoQueue.indexOf(state) + ", path = " + path + ", scrollTop = " + state.scrollTop);
};

HTMLArea.prototype.restoreState = function(state) {
  if (!state)
    return false;
  var html = state.html;
  if (!html)
    return false;
  this.setHTML(html);

  var curHtml = this.getInnerHTML();
  state.html = curHtml;

  var path = state.curNode;
  // alert("restore #" + this._undoQueue.indexOf(state) + ", path = " + path + ", scrollTop = " + state.scrollTop);
  if (!this.setRange(state.range) && HTMLArea.is_ie) {
    var el = this.selectPath(path,null);
    if (el != null)  {
      this.selectNodeContents(el);
      var range = this._createRange(this._getSelection());
      range.collapse();
      range.select();
    }
  }
  if (HTMLArea.is_ie) {
    this._doc.body.scrollTop = state.scrollTop;
    this._doc.body.scrollLeft = state.scrollLeft;
  }
  this.updateToolbar();
  return true;
};

HTMLArea.prototype._isInAny = function(ancestors,list) {
  if (ancestors == null)
    return false;
  for (var i = ancestors.length; --i >= 0;) {
    // A wonderful error condition that should be impossible
    if (ancestors[i]) {
      var tagName = ancestors[i].tagName.toLowerCase();
      for (var j = 0; j < list.length; ++j)
        if (tagName == list[j])
          return true;
    }
  }
  return false;
};

HTMLArea.prototype.cleanBRs = function() {
  var tags = HTMLArea.getElementsByTagNameF(this._doc,'br',function(el) {
    if (/^(h[1-6]|pre)$/i.test(el.parentNode.tagName))
      return true;
    return !el.nextSibling; 
  });
  for (var i = 0; i < tags.length; ++i) {
    var el = tags[i];
    var p = el.parentNode;
    if (/^pre$/i.test(p.tagName))
      p.insertBefore(this._doc.createTextNode("\r\n"),el);
    else if (/^h[1-6]$/i.test(p.tagName))
      p.insertBefore(this._doc.createTextNode(" "),el);
    HTMLArea.removeFromParent(el);
  }
};

HTMLArea.prototype.getSelectionTagsF = function(tag,fn) {
  var el = this._getFirstAncestorF(this._getSelection(),function(el) {
    return el.nodeType == 1 && (el.tagName.toLowerCase() == tag && fn(el) || /^(p|h[1-6]|blockquote|body)$/i.test(el.tagName));
  });
  if (el == null)
    el = this._doc.body;
  if (el.tagName.toLowerCase() == tag)
    return {tag: el};
  var tmp = this._doc.createElement("div");
  tmp.innerHTML = this.getSelectedHTML();
  return {root: el, tags: HTMLArea.getElementsByTagNameF(tmp,tag,fn)};
};


HTMLArea.prototype.getSelectedText = function() {
  var range = this._createRange(this._getSelection());
  if (HTMLArea.is_ie)
    return range.text;
  else
    return this.getHTMLText(HTMLArea.getHTML(range.cloneContents(), false, this));
};

HTMLArea.prototype.removeInRangeF = function(fn) {
  function parseTree(root) {
    if (fn(root))
      return false;
    else {
      for (var i = root.firstChild; i; i = next) {
        var next = i.nextSibling;
        i.nodeType == 1 && parseTree(i);
      }
    }
    return true;
  };

  var html = this.getSelectedHTML();
  var div = this._doc.createElement("div");
  div.innerHTML = html;
  parseTree(div);
  if (div.innerHTML == html)
    return;
  html = div.innerHTML;
  var r = this.getRange();
  this.insertHTML(html);
  this.setRange(r);
};

HTMLArea.prototype.getHTMLText = function(html) {
  var div = this._doc.createElement("div");
  div.innerHTML = html;
  return HTMLArea.getInnerText(div);
};

HTMLArea.prototype.isParagraphStart = function() {
  function findAncestor(node,testFirst) {
    while(node) {
      if (testFirst && node.previousSibling != null && (node.previousSibling.nodeType != 3 || node.previousSibling.nodeValue.trim() != ''))
        return null;
      if (/^(p|td|h[1-6]|li|dd|pre|)$/i.test(node.tagName))
        return node;
      if (/^(body|table)$/i.test(node.tagName))
        break;
      node = node.parentNode;
    }
  };

  var sel = this._getSelection();
  var range = this._createRange(sel);

  if (HTMLArea.is_ie) {
    var r2 = range.duplicate();
    r2.moveStart('character',-1);
    var a = findAncestor(range.parentElement(),false);
    var a2 = findAncestor(r2.parentElement(),false);
    return a != a2;
  } else {
    if (range.startOffset != 0)
      return false;
    //KA - if second param is true, function return null for block elements
    return findAncestor(range.startContainer, false) != null;
  }
};

HTMLArea.prototype.handleTab = function(ev) {
  var def = true;
  var sel = this._getSelection();
  var range = this._createRange(sel);
  var td = this._getFirstAncestor(sel, ['td']);

  if (td != null) {
    if (HTMLArea.is_gecko || ev.keyCode != 9)
      return false;
    var nextTd = ev.shiftKey ? td.previousSibling : td.nextSibling;
    if (nextTd == null) {
      nextTd = ev.shiftKey ? td.parentNode.previousSibling : td.parentNode.nextSibling;
      if (ev.shiftKey && nextTd != null)
        nextTd = nextTd.lastChild;
    }
    if (nextTd == null) {
      var otr = td.parentNode.cloneNode(true);
      var tds = otr.getElementsByTagName("td");
      for (var i = tds.length; --i >= 0;) {
	      var t = tds[i];
	      t.rowSpan = 1;
	      t.innerHTML = "";
      }
      td.parentNode.parentNode.insertBefore(otr, ev.shiftKey ? td.parentNode : null);
      nextTd = ev.shiftKey ? td.parentNode.previousSibling.lastChild : td.parentNode.nextSibling;
    }
    if (nextTd != null) {
      range.moveToElementText(nextTd);
      range.collapse();
      range.select();
    }
    def = false;
  } else if (this.isParagraphStart()) {
    var insert = ev.keyCode == 9 && !ev.shiftKey; 
    var a = this._getFirstAncestor(sel, ['p','h1','h2','h3','h4','h5','h6','ul','ol','td', 'pre']);
    if (a && /^ul|ol$/i.test(a.tagName)) {
      if (ev.keyCode != 9)
        return false;
      def = false;
      cmd = ev.shiftKey ? "outdent" : "indent";
      this.execCommand(cmd, false, null);
    } else if (a && /^p|tb$/i.test(a.tagName)) {
      var indent = a.style.marginLeft;
      if (indent == "") {
        if (!insert && ev.keyCode != 9)
          return false;
        indent = insert ? "1.5em" : "";
      } else if (indent.indexOf("em") > 0) {
        indent = Number(indent.substring(0,indent.length-2));
        if (!insert && indent == 0)
          indent = "0em";
        else
          indent = ( insert ? indent + 1.5 : indent - 1.5 ) + "em";
      }
      if (/^p|pre$/i.test(a.tagName))
        a.style.marginLeft = indent == "0em" ? '' : indent;
      else {
        var p = document.createElement('p');
        p.innerHTML = a.innerHTML;
        p.style.marginLeft = indent;
        a.innerHTML = HTMLArea.getOuterHTML(p);
      }
      def = false;
      if (ev.keyCode != 9)
        return true;
    }
  }
  if (ev.keyCode != 9)
    return false;
  if (def) {
    if (HTMLArea.is_ie)
      this.insertHTML("&nbsp;&nbsp;&nbsp;&nbsp;");
      //this.insertHTML("<img class='tab' height='0' src='' alt='' width='20' />");
    else
      return false;
  }
  HTMLArea._stopEvent(ev);
  return true;
};

HTMLArea.htmlDecode = function(str) {
  if(typeof str.replace == 'undefined') str = str.toString();
  // we don't need regexp for that, but.. so be it for now.
  str = str.replace(/&lt;/ig, "<");
  str = str.replace(/&gt;/ig, ">");
  str = str.replace(/&nbsp;/g, " "); // Decimal 160, non-breaking-space
  str = str.replace(/&quot;/g, "\"");
  str = str.replace(/&amp;/ig, "&");
  return str;
};

String.prototype.ltrim = function() {
  return this.replace(/^\s+/, '');
};

String.prototype.rtrim = function() {
  return this.replace(/\s+$/, '');
};

HTMLArea.removeTag = function(el) {
  var p = el.parentNode;
  if(!p)
    return;
  var c = el.firstChild;
  while (c != null) {
    var n = c.nextSibling;
    p.insertBefore(c, el);
    c = n;
  }
  HTMLArea.removeFromParent(el);
};

HTMLArea.getElementsByTagNameF = function(root,tag,fn) {
  var tas = root.getElementsByTagName(tag);
  var ret = [];
  for (var i = tas.length; i > 0; ) {
    var el = tas[--i];
    if (fn(el))
      ret[ret.length] = el;
  }
  return ret;
};

HTMLArea.prototype.splitOutRange = function(root,range) {
  if (HTMLArea.is_ie)
    range.select();
  this._doc.execCommand("fontname",false,"split");
  var isSplit = HTMLArea.is_ie ? function(el) {
    return /^font$/i.test(el.tagName) && /^split$/i.test(el.face);
  } : function(el) {
    return (/^font$/i.test(el.tagName) || /^span$/i.test(el.tagName)) && (/^split$/i.test(el.face) || /^split$/i.test(el.style.fontFamily));
  };
  if (isSplit(root))
    HTMLArea.removeTag(root);
  else
    this.splitOutTree(root,range,isSplit);
  
  HTMLArea.replaceTagsF(this.getParentElement().parentNode,function (el) {
    if (!isSplit(el))
      return null;
    HTMLArea.removeTag(el);
    return null;
  });
};

HTMLArea.prototype.adjustSelection = function(sel,range) {
  var text = this.getSelectedText();
  //if (!text) return '<nosel>';
  //KA - If the text wasn't selected, function returned '<nosel>'.
  //As a result, checking selected text length returned not null value.
  if (!text) return '';
  var ltrim = text.ltrim();
  var rtrim = ltrim.rtrim();

  if (text.length != rtrim.length) {
    if (typeof sel == 'undefined')
      sel = this._getSelection();
    if (typeof range == 'undefined')
      range = this._createRange(sel);
    var diff = text.length - ltrim.length;
    if (diff != 0) {
      if (HTMLArea.is_ie)
        range.moveStart('character',diff);
      else {
        if (range.startOffset + diff < 0)
          ltrim = text;
        else
          MindTouch.setStart(range, range.startContainer, range.startOffset + diff);
      }
    }
    diff = rtrim.length - ltrim.length;
    if (diff != 0) {
      if (HTMLArea.is_ie)
        range.moveEnd('character',diff);
      else {
        if (range.endOffset + diff < 0)
          rtrim = ltrim;
        else
          MindTouch.setEnd(range, range.endContainer, range.endOffset + diff);
      }
    }
    if (HTMLArea.is_ie)
      range.select();
    else {
      sel.removeAllRanges();
      sel.addRange(range);
    }
  }
  return rtrim;
}

HTMLArea.prototype.splitOutTree = function(root,range,isMiddle) {
  if (root == null)
    return;
  var left = root.cloneNode(false), middle = root.cloneNode(false), right = root.cloneNode(false);
  HTMLArea.splitOutTreeR(root,isMiddle,left,middle,right,false,false);
  var p = root.parentNode;
  if (HTMLArea.getInnerText(left).length != 0)
    p.insertBefore(left,root);
  var middleL = HTMLArea.getInnerText(middle).length;
  p.insertBefore(middle,root);
  this.selectNodeContents(middle);
  HTMLArea.removeTag(middle);
  var rightL = HTMLArea.getInnerText(right).length;
  if (rightL != 0)
    p.insertBefore(right,root);
  p.removeChild(root);
/*
  if (HTMLArea.is_ie) {
    range.move('character',-rightL);
    range.moveStart('character',-middleL);
    range.select();
  } else { // TODO: adjust selection to be like original
  }
*/
};

// @author Urs C Muff
// This function will split a tree into 3 parts: left, middle and right
// The entire structure is kept intakt of all parts
// Parts before 'isMiddle' are copied into the left part
// Parts that are 'isMiddle' are copied into the middle part
// Parts after 'isMiddle' are copied into the right part
HTMLArea.splitOutTreeR = function(cur,isMiddle,left,middle,right,found,isContextMiddle) {
  var curC = cur.firstChild;

  while (curC != null) {
    var curN = curC.nextSibling;
    var isText = curC.nodeType == 3;
    var isLeaf = !isText && curC.firstChild == null;
    var curIsMiddle = isMiddle(curC);
    if (curIsMiddle)
      found = true;

    if (isText || isLeaf) {
      if (isContextMiddle || curIsMiddle)
        middle.appendChild(curC.cloneNode(false));
      else if (!found) // before found
        left.appendChild(curC.cloneNode(false));
      else // after found
        right.appendChild(curC.cloneNode(false));
    } else {
      var leftC = curC.cloneNode(false), middleC = curC.cloneNode(false), rightC = curC.cloneNode(false);
      found = HTMLArea.splitOutTreeR(curC,isMiddle,leftC,middleC,rightC,found,isContextMiddle || curIsMiddle);
      if (HTMLArea.getInnerText(leftC).length != 0)
        left.appendChild(leftC);
      if (HTMLArea.getInnerText(middleC).length != 0)
        middle.appendChild(middleC);
      if (curIsMiddle)
        HTMLArea.removeTag(middleC);
      if (HTMLArea.getInnerText(rightC).length != 0)
        right.appendChild(rightC);
    }
    
    curC = curN;
  }
  return found;
};

HTMLArea.replaceTagsF = function(root,convertF) {
  var c = root.firstChild;
  while (c != null) {
    var n = c.nextSibling;
    HTMLArea.replaceTagsF(c,convertF);
    var newC = convertF(c);
    if (newC != null) {
      root.insertBefore(newC,c);
      HTMLArea.removeFromParent(c);
    }
    c = n;
  }
};

HTMLArea.prototype.getRange = function() {
  function getBodyOffset(el,cmp,s) {
    for (var i = el.firstChild; i; i = i.nextSibling) {
      if (i == cmp || i.firstChild == cmp)
        return true;
      if (i.nodeType == 3)
        s.len += i.data.length;
      else if (i.nodeType == 8)
        continue;
      else if (getBodyOffset(i,cmp,s))
        return true;
    }
    return false;
  };

  var sel = this._getSelection();
  var range = this._createRange(sel);
  if (HTMLArea.is_ie) {
    var selText = '';
    if (sel.type != 'Control' && range) {
      selText = range.text;
      range.collapse();
      var p = range.parentElement();
      var pOffset = 0;
      while (true) {
        var last = range.htmlText.length;
        range.moveStart('character',-1);
        if (range.parentElement() != p || last == range.htmlText.length)
          break;
        ++pOffset;
      }
    } else {
      var p = this.getParentElement(sel,range);
      var pOffset = 0;
    }
    var s = { len: 0 };
    getBodyOffset(this._doc.body,p,s);
    
    return {
      pOffset: pOffset,
      bOffset: s.len,
      selText: selText
    };
  } else {
    var s = { len: 0 };
    var SC = range.startContainer;
    getBodyOffset(this._doc.body,SC,s);
    var EC = range.endContainer;
    if (SC == EC)
      return {
        pOffset: range.startOffset,
        bOffset: s.len,
        length : range.endOffset - range.startOffset
      };
    else {
      var t = { len: 0 };
      getBodyOffset(this._doc.body,EC,t);
      return {
        pOffset : range.startOffset,
        bOffset : s.len,
        ePOffset: range.endOffset,
        eBOffset: t.len,
        length  : t.len + range.endOffset - range.startOffset - s.len
      };
    }
  }
};

HTMLArea.prototype.setRange = function(r) {
  function findBodyOffset(el,s) {
    if (s.len < 0)
      return el;
    for (var i = el.firstChild; i; i = i.nextSibling) {
      if (i.nodeType == 3)
        s.len -= i.data.length;
      else if (i.nodeType == 8)
        continue;
      else {
        var t = findBodyOffset(i,s);
        if (t != null)
          return t;
      }
      if (s.len < 0)
        return i;
    }
    return null;
  };

  var el = findBodyOffset(this._doc.body,{len:r.bOffset});
  if (el == null)
    return false;
  if (HTMLArea.is_ie) {
    range = this._doc.body.createTextRange();
    range.moveToElementText(el.nodeType == 3 ? el.parentNode : el);
    range.collapse(true);
    range.move('character',r.pOffset);
    range.moveEnd('character',r.selText.length);
    range.select();
    return true;
  } else {
    range = this._createRange();
    MindTouch.setStart(range, el,r.pOffset);
    if (r.length == 0)
      range.collapse(true);
    else if (typeof r.eBOffset == 'undefined') {
      MindTouch.setEnd(range, el,r.pOffset+r.length);
    } else {
      el = findBodyOffset(this._doc.body,{len:r.eBOffset});
      MindTouch.setEnd(range, el,r.ePOffset);
    }
  }
};

HTMLArea.prototype.selectWord = function() {
  if (HTMLArea.is_ie) {
    var sel = this._getSelection();
    var range = this._createRange(sel);
    range.expand('word');
    range.select();
    this.adjustSelection(sel,range);
  } else { // TODO: not handled yet
  }
};

HTMLArea.cloneNode = function(a,b) {
  var c = a.firstChild;
  while (c != null) {
    b.appendChild(c.cloneNode(true));
    c = c.nextSibling;
  }
  return b;
};

HTMLArea.prototype.insertContent = function(range, html) {
  if (HTMLArea.is_ie) {
    range.pasteHTML(html);
  } else {
    var fragment = this._doc.createDocumentFragment();
    var div = this._doc.createElement("div");
    div.innerHTML = html;
    while (div.firstChild) {
      // the following call also removes the node from div
      fragment.appendChild(div.firstChild);
    }
    range.insertNode(fragment);
  }
};

HTMLArea.prototype.getRangeHTML = function(range) {
  if (HTMLArea.is_ie)
    return range.htmlText;
  else
    return HTMLArea.getHTML(range.cloneContents(), false, this);
};

HTMLArea.prototype.selectRange = function(range) {
  if (HTMLArea.is_ie)
    range.select();
  else {
    var sel = this._getSelection();
    sel.removeAllRanges();
    sel.addRange(range);
  }
};

HTMLArea.prototype.insertList = function(para,len,cmd) {
  this._undoTakeSnapshot();
  var r = MindTouch.cloneRange(this._createRange());
  MindTouch.setStart(r, para, 0);
  MindTouch.setEnd(r, para, len);
  this.deleteContents(r);
  this.execCommand(cmd, false, null);
};

HTMLArea.prototype.findAndReplace = function(find,replace,block,innerTxt) {
  var pos = innerTxt.indexOf(find);
  while (pos >= 0) {
    this._undoTakeSnapshot();
    var rSel = this._createRange();
    if (HTMLArea.is_gecko) {
      this.insertContent(rSel,"<span class='marker'></span>");
      var marker = rSel.endContainer.nextSibling;
      var sel = this._getSelection();
      sel.removeAllRanges();
    }
    var r = MindTouch.cloneRange(rSel);
    MindTouch.setStart(r, block, pos);
    if (HTMLArea.is_gecko) {
      if (r.startContainer.nodeType == 1 && r.startContainer.childNodes[r.startOffset] == marker) {
        r.selectNode(marker.nextSibling);
        r.collapse(true);
      }
    }
    MindTouch.setEnd(r, block, pos + find.length);
    var root = MindTouch.commonAncestorContainer(r);
    if (root && root.nodeType == 1 && root.tagName.toLowerCase() == 'span' && root.className == 'plain') {
      pos = innerTxt.indexOf(find, pos+find.length);
      continue;
    }
    if (HTMLArea.is_ie)
      r.pasteHTML('');
    else
      r.deleteContents();
    this.insertContent(r, replace);
    if (marker) {
      if (marker.parentNode) {
        rSel.selectNode(marker);
        sel.addRange(rSel);
        rSel.deleteContents();
      } else
        sel.addRange(rSel);
    }
    innerTxt = HTMLArea.getInnerText(block);
    pos = innerTxt.indexOf(find, pos+find.length);
  }
  return innerTxt;
};

HTMLArea.prototype.deleteContents = function(range) {
  if (HTMLArea.is_ie)
    range.pasteHTML('');
  else {
    var sel = this._getSelection();
    var rSel = this._createRange();
    this.insertContent(rSel,"<span class='marker'></span>");
    var marker = rSel.endContainer.nextSibling;
    sel.removeAllRanges();
    range.deleteContents();
    if (marker.parentNode) {
      rSel.selectNode(marker);
      sel.addRange(rSel);
      rSel.deleteContents();
    } else
      sel.addRange(rSel);
  }
};

/*
 * MindTouch DekiWiki - a commercial grade open source wiki
 *  derived from MediaWiki (www.mediawiki.org)
 * Copyright (C) 2006 MindTouch, Inc.
 * www.mindtouch.com  oss@mindtouch.com
 *
 * For community documentation and downloads visit www.opengarden.org;
 *  please review the licensing section.
 *
 * 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.
 * http://www.gnu.org/copyleft/gpl.html
 */

// Author: Urs C. Muff

// NOTE: change the version above each function if changed, so that the C# version can be kept up to date.

// version 1.0
HTMLArea.xhtml_surroundNode = function(node, outer) {
  node.parentNode.insertBefore(outer, node);
  outer.appendChild(node);
};

// version 1.2
HTMLArea.xhtml_invalidFormating = function(node, context) {
  var prev = HTMLArea.xhtml_skipEmptyText(node, 'previousSibling');
  if (prev && prev.nodeType == 1 && prev.tagName.toLowerCase() == 'p') {
    if (node.nodeType == 1 && node.tagName.toLowerCase() == 'br') {
      HTMLArea.xhtml_surroundNode(node, node.ownerDocument.createElement('p'));
      return node;
    }
    prev.appendChild(node);
    return node;
  }
  var parentTag = node.parentNode.tagName.toLowerCase();
  if (parentTag != 'body' && parentTag != 'blockquote') {
    return HTMLArea.xhtml_invalidNonBlock(node, context);
  }
  var sibling = node.nextSibling;
  HTMLArea.xhtml_surroundNode(node, node.ownerDocument.createElement('p'));
  while (sibling) {
    var n = sibling.nextSibling;
    if (sibling.nodeType == 1) {
      var data = HTMLArea.validTags[sibling.tagName.toLowerCase()];
      if (data && data.isBlock)
        break;
    }
    node.parentNode.appendChild(sibling);
    sibling = n;
  }
  return node;
};

// version 1.0
HTMLArea.xhtml_getChildren = function(node) {
  var children = new Array();
  var child = node.firstChild;
  while (child) {
    children.push(child);
    child = child.nextSibling;
  }
  return children;
};

// version 1.0
HTMLArea.xhtml_handleChildren = function(children, context) {
  for (var c = 0; c < children.length; ++c) {
    var child = children[c];
    if (!HTMLArea.isNodeDeleted(child))
      HTMLArea.makeXHTML(child, context, child.parentNode);
  }
};

// version 1.1
HTMLArea.xhtml_removeTag = function(node, context) {
  var children = HTMLArea.xhtml_getChildren(node);
  HTMLArea.removeTag(node);
  HTMLArea.xhtml_handleChildren(children, context);
};

// version 1.1
HTMLArea.xhtml_convertTo = function(node, context, newNode) {
  var parent = node.parentNode;
  if (parent.tagName.toLowerCase() == 'body') {
    node = HTMLArea.xhtml_invalidFormating(node, context);
    parent = node.parentNode;
  }

  var parentData = HTMLArea.validTags[parent.tagName.toLowerCase()];
  if (!parentData.validChild || !parentData.validChild.test(newNode.tagName.toLowerCase())) {
    HTMLArea.xhtml_removeTag(node, context);
    return null;
  }

  HTMLArea.cloneNode(node,newNode);
  parent.replaceChild(newNode,node);
  return newNode;
};

// version 1.0
HTMLArea.xhtml_convertToStrong = function(node, context) {
  return HTMLArea.xhtml_convertTo(node, context, node.ownerDocument.createElement('strong'));
};

// version 1.1
HTMLArea.xhtml_convertToCenterStyle = function(node, context) {
  var c = node.firstChild;
  var parent = node.parentNode;
  while (c != null) {
    var n = c.nextSibling;
    if (c.nodeType == 1) {
      if (context.toSave) c.style.textAlign = "center";
      else c.align = "center";
    } else {
      var newC = node.ownerDocument.createElement('p');
      if (context.toSave) newC.style.textAlign = "center";
      else newC.align = "center";
      newC.appendChild(c);
      c = newC;
    }
    parent.insertBefore(c, node);
    c = n;
  }
  HTMLArea.removeFromParent(node);
  return null;
};

// version 1.1
HTMLArea.xhtml_convertToEm = function(node, context) {
  return HTMLArea.xhtml_convertTo(node, context, node.ownerDocument.createElement('em'));
};

// version 1.1
HTMLArea.xhtml_convertToCode = function(node, context) {
  return HTMLArea.xhtml_convertTo(node, context, node.ownerDocument.createElement('code'));
};

// version 1.1
HTMLArea.xhtml_invalidList = function(node, context) {
  var parent = node.parentNode;
  switch (parent.tagName.toLowerCase()) {
  case "ul":
  case "ol":
    var prev = HTMLArea.xhtml_skipEmptyText(node,'previousSibling');
    if (prev && prev.nodeType == 1 && prev.tagName.toLowerCase() == 'li') {
      prev.appendChild(node);
      return node;
    } else {
      HTMLArea.xhtml_surroundNode(node, node.ownerDocument.createElement('li'));
      node.parentNode.insertBefore(HTMLArea.xhtml_createNBSP(node), node);
      return node;
    }
    break;
  default:
    return HTMLArea.xhtml_moveToBlockContainer(node);
  }
};

// version 1.1
HTMLArea.xhtml_moveToBlockContainer = function(node) {
  var cur = node;
  var parent = cur.parentNode;
  var parentClone = null;
  while (true) {
    var oldClone = parentClone;
    var next = HTMLArea.xhtml_skipEmptyText(cur, 'nextSibling');
    parentClone = next || oldClone ? parent.cloneNode(false) : null;
    if (parentClone) {
      if (oldClone)
        parentClone.appendChild(oldClone);
      while (cur.nextSibling != null)
        parentClone.appendChild(cur.nextSibling);
    }
    cur = parent;
    parent = cur.parentNode;
    if (parent == null || typeof parent.tagName == "undefined")
      return null;
    if (HTMLArea.validTags[parent.tagName.toLowerCase()].isBlockContainer)
      break;
  }
  try {
    parent.insertBefore(node, cur.nextSibling);
    if (parentClone != null)
      parent.insertBefore(parentClone, node.nextSibling);
  } catch (e) {
    parent.appendChild(node);
  }
  return node;
};

// version 1.0
HTMLArea.xhtml_createNBSP = function(node) {
  return node.ownerDocument.createTextNode(unescape("%u00a0"));
};

// version 1.1
HTMLArea.xhtml_invalidListItem = function(node, context) {
  if (typeof context.ul != 'undefined') {
    var validUL = true;
    var p = node.parentNode;
    while (p) {
      var pData = HTMLArea.validTags[p.tagName.toLowerCase()];
      if (pData.tag == 'ul') break;
      if (pData.isBlock) {
        validUL = false;
        break;
      }
      p = p.parentNode;
    }
    if (validUL)
      return node;
  }
  var prev = HTMLArea.xhtml_skipEmptyText(node,'previousSibling');
  if (prev && prev.nodeType == 1) {
    var pTag = prev.tagName.toLowerCase();
    if (pTag == 'ul' || pTag == 'ol') {
      prev.appendChild(node);
      return node;
    }
  }
  var newNode = node.ownerDocument.createElement('ul');
  HTMLArea.xhtml_surroundNode(node, newNode);
  return node;
};

// version 1.1
HTMLArea.xhtml_invalidH = function(node, context) {
  var doSplit = true;
  var p = node.parentNode;
  while (p && typeof p.tagName != 'undefined' && doSplit) {
    switch (p.tagName.toLowerCase()) {
    case 'li': case 'td': case 'th':
      doSplit = false;
    }
    p = p.parentNode;
  }
  if (doSplit) {
    if (node.parentNode.tagName.toLowerCase() == 'center') {
      if (context.toSave) node.style.textAlign = "center";
      else node.align = "center";
    }
    return HTMLArea.xhtml_moveToBlockContainer(node);
  }
  var newNode = node.ownerDocument.createElement('span');
  newNode.className = 'header_' + node.tagName.substring(1);
  HTMLArea.xhtml_convertTo(node, context, newNode);
  if (!HTMLArea.isNodeDeleted(newNode))
    newNode.parentNode.appendChild(HTMLArea.xhtml_createNBSP(node));
  return newNode;
};

// version 1.1
HTMLArea.xhtml_invalidP = function(node, context) {
  var prev = HTMLArea.xhtml_skipEmptyText(node, 'previousSibling');
  if (prev != null) {
    var parent = node.parentNode;
    parent.insertBefore(parent.tagName.toLowerCase() == 'pre'
      ? node.ownerDocument.createTextNode("\r")
      : node.ownerDocument.createElement('br'), node);
  };
  HTMLArea.xhtml_removeTag(node, context);
  return null;
};

// version 1.1
HTMLArea.xhtml_invalidBlock = function(node, context) {
  return HTMLArea.xhtml_moveToBlockContainer(node);
};

// version 1.0
HTMLArea.xhtml_invalidNonBlock = function(node, context) {
  var tag = node.tagName.toLowerCase();
  var parentData = HTMLArea.validTags[node.parentNode.tagName.toLowerCase()];

  function handleChild(child) {
    if (child.nodeType == 1) {
      if (!parentData || !parentData.validChild || !parentData.validChild.test(child.tagName)) {
        HTMLArea.xhtml_applyToChildren(child, handleChild);
      } else {
        var childData = HTMLArea.validTags[child.tagName.toLowerCase()];
        if (childData && childData.validChild && childData.validChild.test(tag)) {
          HTMLArea.xhtml_applyToChildren(child, function(cc) {
            HTMLArea.xhtml_surroundNode(cc, node.cloneNode(false));
          });
        }
      }
    }
  };

  HTMLArea.xhtml_applyToChildren(node, handleChild);
  HTMLArea.xhtml_removeTag(node, context);
  return null;
};

// version 1.0
HTMLArea.xhtml_applyToChildren = function(node, func) {
  var child = node.firstChild;
  while (child != null) {
    var next = child.nextSibling;
    func(child);
    child = next;
  }
};

// version 1.1
HTMLArea.xhtml_convertToOl = function(node, context) {
  return HTMLArea.xhtml_convertTo(node, context, node.ownerDocument.createElement('ol'));
};

// version 1.1
HTMLArea.xhtml_convertToIns = function(node, context) {
  return HTMLArea.xhtml_convertTo(node, context, node.ownerDocument.createElement('ins'));
};

// version 1.1
HTMLArea.xhtml_convertToDel = function(node, context) {
  return HTMLArea.xhtml_convertTo(node, context, node.ownerDocument.createElement('del'));
};

// version 1.0
HTMLArea.xhtml_convertFontToSpan = function(node, context) {
  var newNode = node.ownerDocument.createElement('span');
  if (node.size != "") {
    switch (node.size) {
      case "-2":
        newNode = node.ownerDocument.createElement('small');
        break;
      case "+2":
        newNode = node.ownerDocument.createElement('big');
        break;
      case "+3":
        newNode = node.ownerDocument.createElement('big');
        break;
    default:
        newNode.style.fontSize = "";
        break;
    }
  }
  if (node.style.cssText != "")
    newNode.style.cssText = node.style.cssText;
  if (node.face != "")
    newNode.style.fontFamily = node.face;
  if (node.color != "")
    newNode.style.color = node.color;
  if (!HTMLArea.xhtml_convertTo(node, context, newNode))
    return null;
  if (node.size == "+3")
    HTMLArea.xhtml_surroundNode(newNode, node.ownerDocument.createElement('big'));
  return newNode;
};

HTMLArea.xhtml_findBlockOrContainer = function(node) {
  var block = node.parentNode;
  while (true) {
    if (block == null || typeof block.tagName == "undefined")
      return null;
    var tag = HTMLArea.validTags[block.tagName.toLowerCase()];
    if (tag.isBlock || tag.isBlockContainer)
      break;
    block = block.parentNode;
  }
  return block;
};

HTMLArea.xhtml_handleBr = function(node, context) {
  function cloneParents(pnt) {
    if (newContainer && !newContainer.firstChild)
      newContainer.appendChild(HTMLArea.xhtml_createNBSP(newContainer));
    newBlock = block.cloneNode(false);
    block.parentNode.insertBefore(newBlock, blockInsert);
    newContainer = newBlock;
    if (pnt.tagName != block.tagName) {
      var pps = new Array();
      while (pnt.tagName != block.tagName) {
        pps.push(pnt);
        pnt = pnt.parentNode;
      }
      pps.reverse();
      for (var i = 0; i < pps.length; ++i) {
        var newC = pps[i].cloneNode(false);
        newContainer.appendChild(newC);
        newContainer = newC;
      }
    }
  };

  var block = HTMLArea.xhtml_findBlockOrContainer(node);
  if (block == null) return null;
  var parentBlock = HTMLArea.xhtml_findBlockOrContainer(block);
  if (parentBlock != null) {
    switch (parentBlock.tagName.toLowerCase()) {
    case 'td': case 'th': case 'li': case 'dt':
      return null;
    }
  }
  var blockInsert = block.nextSibling;
  var p = node.previousSibling;
  var n = node.nextSibling;
  if (p && p.nodeType == 3 && p.data.trim().length == 0) p = null;
  if (n && n.nodeType == 3 && n.data.trim().length == 0) n = null;
  if ((!p || p.nodeType != 1 || p.tagName.toLowerCase() != 'br') && !n) {
    if (p && p.nodeType == 3) {
      HTMLArea.removeFromParent(node);
      return null;
    }
    return node;
  }
  switch (block.tagName.toLowerCase()) {
  case 'p': case 'blockquote': case 'dd':
    var newBlock, newContainer;
    cloneParents(node.parentNode);
    if (n) {
      HTMLArea.removeFromParent(node);
      while (n) {
        var nn = n.nextSibling;
        if (n.nodeType == 1 && n.tagName.toLowerCase() == 'br') {
          if (n.nextSibling) {
            cloneParents(n.parentNode);
            HTMLArea.removeFromParent(n);
          }
          else HTMLArea.removeFromParent(n);
        }
        else newContainer.appendChild(n);
        n = nn;
      }
    } else {
      var n = node.nextSibling;
      HTMLArea.removeFromParent(node);
      while (true) {
        HTMLArea.removeFromParent(n);
        if (n.nodeType == 1 && n.tagName.toLowerCase() == 'br')
          break;
        n = n.nextSibling;
      }
    }
    if (!newContainer.firstChild)
      newContainer.appendChild(HTMLArea.xhtml_createNBSP(newContainer));
  }
};

HTMLArea.xhtml_handleP = function(node, context) {
  var text = node.firstChild && node.firstChild.nodeType == 3 ? node.firstChild.data : '';
  var block = HTMLArea.xhtml_findBlockOrContainer(node);
  if (text.length > 0) {
    try {
      var level = 0;
      switch (text.charCodeAt(0)) {
      case 183: case '*': case '-': case '+': level = 1; break;
      case 111: level = 2; break;
      case 167: level = 3; break;
      }
      if (level && text.length == 1 && node.firstChild.nextSibling && node.firstChild.nextSibling.nodeType == 3) {
        node.firstChild.data += node.firstChild.nextSibling.data;
        HTMLArea.removeFromParent(node.firstChild.nextSibling);
        text = node.firstChild.data;
      }
      if (level && text.substring(1,2).htmlTrim().length == 0) {
        var curLevel = 0, p = node.previousSibling, lastUl;
        var newText = text.substring(1).htmlTrim();
        while (p && curLevel < level && p.lastChild && p.lastChild.nodeType == 1) {
          var t = p.tagName.toLowerCase();
          if (t == 'ul') {
            ++curLevel;
            lastUl = p;
          }
          p = p.lastChild;
        }
        if (curLevel < level) {
          var ul = node.ownerDocument.createElement('ul');
          HTMLArea.xhtml_surroundNode(node, ul);
        }
        if (newText.length)
          node.firstChild.data = newText;
        else
          HTMLArea.removeFromParent(node.firstChild);
        var li = node.ownerDocument.createElement('li');
        HTMLArea.cloneNode(node,li);
        node.parentNode.replaceChild(li,node);
        if (curLevel == level && lastUl) {
          lastUl.appendChild(li);
        } else if (curLevel < level && curLevel > 0 && lastUl) {
          lastUl.lastChild.appendChild(ul);
        }
        return;
      }
    } catch (e) {}
  }
  if (block == null) return;
  switch (block.tagName.toLowerCase()) {
  case 'td': case 'th': case 'li': case 'dt':
    var n = node.nextSibling;
    if (n && (n.nodeType != 1 || n.tagName.toLowerCase() != 'br' || node.style.cssText != "") 
      && !(node.firstChild == node.lastChild && node.nodeType == 1 && node.tagName.toLowerCase() == "br")) {
      node.parentNode.insertBefore(node.ownerDocument.createElement('br'),n);
    }
    if (node.style.cssText != "") {
      var newNode = node.ownerDocument.createElement('span');
      newNode.style.cssText = node.style.cssText;
      HTMLArea.xhtml_convertTo(node, context, newNode);
    } else {
      var text = HTMLArea.getInnerText(node);
      if (text.htmlTrim().length == 0) {
        if (n) node.parentNode.insertBefore(HTMLArea.xhtml_createNBSP(node),node.nextSibling);
        HTMLArea.removeFromParent(node);
      } else
        HTMLArea.removeTag(node);
    }
  }
};

// version 1.0
HTMLArea.xhtml_handleClassName = function(node, context) {
  var newc = node.className.replace(/(^|\s)mso.*?(\s|$)/ig, ' ');
  if (newc != node.className) {
    context.is_word = true;
    HTMLArea.xhtml_recordEvent(context, true, "className contains mso.*, removed");
    node.className = newc;
    if (!/\S/.test(node.className)) node.removeAttribute("className");
  }
};

// version 1.1 (C# version also handles text-indent, text-align valiues, and color/background-color values)
HTMLArea.xhtml_cssStyleR = HTMLArea.compileRegex("\s*;\s*");
HTMLArea.xhtml_msoCssR = HTMLArea.compileRegex(/^\s*mso|^\s*tab-stops|^\s*margin: 0in 0in 0pt|^\s*margin-top: 0in|^text-indent: -[0-9\.]+in|^font-weight: [a-z]+|^line-height: [a-z]+|font-style: [a-z]+|^font-size-adjust: [a-z]+|^font-stretch: [a-z]+/i);
HTMLArea.xhtml_handleCssStyle = function(node, context) {
  if (node.style.display == "none") {
    HTMLArea.removeFromParent(node);
    return null;
  }
  var declarations = node.style.cssText.split(HTMLArea.xhtml_cssStyleR);
  var changed = false;
  for (var i = declarations.length; --i >= 0;) {
    if (HTMLArea.xhtml_msoCssR.test(declarations[i]) /*||
        /^margin\s*:|^margin-top\s*:|^margin-right\s*:/i.test(declarations[i])*/) {
      context.is_word = true;
      changed = true;
      declarations.splice(i, 1);
    }
  }
  if (changed) {
    HTMLArea.xhtml_recordEvent(context, true, "style contains mso.*|tab-stops, removed");
    node.style.cssText = declarations.join("; ");
  }
  
  switch (node.style.fontSize) {
  case "-2":
  case "+2":
  case "+3":
    break;
  default:
    node.style.fontSize = null;
  }
  
  if (!context.toSave && node.style.textAlign != "") {
    node.align = node.style.textAlign;
    node.style.textAlign = "";
  }
};

// version 1.1
HTMLArea.xhtml_getStyle = function(node) {
  var ret = new Object();
  if (node.style.cssText != "") {
    var styles = node.style.cssText.split(';');
    for (var i = 0; i < styles.length; ++i) {
      var style = styles[i].trim();
      if (style != "") {
        var styleVal = style.split(':');
        ret[styleVal[0].replace(/-/g,'_').toUpperCase()] = styleVal[1].trim();
      }
    }
  }
  return ret;
};

// version 1.0
HTMLArea.xhtml_style2CssText = function(style) {
  var cssText = "";
  for (var s in style) {
    if (cssText != "") cssText += "; ";
    cssText += s.replace(/_/,'-') + ": " + style[s];
  }
  return cssText;
};

// version 1.0
HTMLArea.xhtml_handleTD = function(node, context) {
  if (!context.toSave) {
    if (node.firstChild && node.firstChild == node.lastChild && node.firstChild.nodeType == 3 && HTMLArea.getInnerText(node).htmlTrim().length == 0)
      node.removeChild(node.firstChild);
  }
};

// version 1.1
HTMLArea.xhtml_handleH = function(node, context) {
  if (node.style.cssText != "") {
    var textAlign = node.style.textAlign;
    node.style.cssText = "";
    node.style.textAlign = textAlign;
  }
  var title = HTMLArea.getInnerText(node);
  var nt = title.replace(/^[\s\xA0]+/, '').replace(/[\s\xA0]+$/, '');
  if (nt.length == 0)
    HTMLArea.removeFromParent(node);
  if (nt.length != title.length)
    HTMLArea.is_ie ? node.innerText = nt : node.textContent = nt;
};

HTMLArea.xhtml_skipEmptyText = function(node, property) {
  if (!node) return node;
  var ret = node[property];
  while (ret && ret.nodeType == 3 && ret.data.htmlTrim().length == 0)
    ret = ret[property];
  return ret;
};

// version 1.0
HTMLArea.xhtml_handleList = function(node, context) {
  if (node.getAttribute('type') != null)
    node.removeAttribute('type');
  var myLi = node.parentNode;
  var prev = HTMLArea.xhtml_skipEmptyText(node,'previousSibling');
  var parPrev = HTMLArea.xhtml_skipEmptyText(myLi,'previousSibling');
  var isSubList = myLi.tagName.toLowerCase() == 'li';
  if (!prev && !HTMLArea.xhtml_skipEmptyText(node,'nextSibling') && isSubList && parPrev && parPrev.nodeType == 1 && parPrev.tagName.toLowerCase() == 'li') {
    parPrev.appendChild(node);
    HTMLArea.removeFromParent(myLi);
    return node;
  }
  if (node.firstChild && node.firstChild.nodeType == 3 && !node.firstChild.nextSibling && node.innerHTML.htmlTrim().length == 0) {
    HTMLArea.removeFromParent(node);
    return null;
  }
  if (prev && prev.nodeType == 1 && prev.tagName == node.tagName && isSubList) {
    while (node.firstChild)
      prev.appendChild(node.firstChild);
    HTMLArea.removeFromParent(node);
    return null;
  }
  return node;
};

// version 1.0
HTMLArea.xhtml_fontConvert = null;

HTMLArea.xhtml_getFirstAncestorF = function(node, fn) {
  while(node) {
    if (fn(node))
      return node;
    if (/^(body|table)$/i.test(node.tagName))
      break;
    node = node.parentNode;
  }

  return null;
};

// version 1.0
HTMLArea.xhtml_checkFont = function(editor, node, face) {
  // version 1.0
  function setFace(node, val) {
    var vals = val.split('|');
    var face = vals[0];
    var p = HTMLArea.xhtml_getFirstAncestorF(node.parentNode,function(el) { return el.style.fontFamily || el.face; });
    if (!p && face.indexOf('sans-serif') >= 0)
      face = '';
    if (node.tagName.toLowerCase() == 'span') {
      node.style.fontFamily = face;
      if (face == '') node.style.cssText = node.style.cssText.replace(/font-family: ;?/i,'');
    } else
      node.face = face;
    if (vals.length > 1)
      node.style.fontVariant = vals[1];
    else
      node.style.fontVariant = p ? 'normal' : '';
  };
  
  if (HTMLArea.xhtml_fontConvert == null) {
    HTMLArea.xhtml_fontConvert = new Object();
    for (var _cfn in editor.config.fontname) {
      var cfn = editor.config.fontname[_cfn];
      var cfnFace = cfn.split('|')[0];
      if (cfnFace == '') continue;
      var cfnA = cfnFace.split(',');
      HTMLArea.xhtml_fontConvert[cfnFace] = cfn;
      for (var i = cfnA.length; --i >= 0;) {
        var cf = cfnA[i].toLowerCase();
        if (typeof HTMLArea.xhtml_fontConvert[cf] == "undefined" || i == 0)
          HTMLArea.xhtml_fontConvert[cf] = cfn;
      }
    }
  }
  face = face.toLowerCase();
  if (typeof HTMLArea.xhtml_fontConvert[face] != "undefined")
    setFace(node, HTMLArea.xhtml_fontConvert[face]);
  else {
    var faceA = face.split(',');
    for (var j = faceA.length; --j >= 0;) {
      var f = faceA[j];
      if (typeof HTMLArea.xhtml_fontConvert[f] != "undefined") {
        setFace(node, HTMLArea.xhtml_fontConvert[f]);
        HTMLArea.xhtml_fontConvert[face] = HTMLArea.xhtml_fontConvert[f];
        return;
      }
    }
    setFace(node, '');
  }
};

HTMLArea.xhtml_handleCssToFont = function(node, newNode, context) {
  if (node.style.fontFamily != "")
    HTMLArea.xhtml_checkFont(context.editor, newNode, node.style.fontFamily);
  if (node.style.color != "")
    newNode.color = HTMLArea._colorToRgb(node.style.color);
  if (node.style.cssText != "") {
    var style = HTMLArea.xhtml_getStyle(node);
    for (var s in {FONT_FAMILY: true, COLOR: true})
      delete style[s];
    newNode.style.cssText = HTMLArea.xhtml_style2CssText(style);
  }
};

// version 1.1
HTMLArea.xhtml_spanIgnoreAttrR = HTMLArea.compileRegex("(_moz)|(contenteditable)|(_msh)", "i");
HTMLArea.xhtml_handleSpan = function(node, context) {
  if (node.style.fontFamily != "")
    HTMLArea.xhtml_checkFont(context.editor, node, node.style.fontFamily);
  if (!context.toSave) {
    if (node.style.fontFamily != "" || node.style.color != "" || node.style.backgroundColor != "") {
      var newNode = node.ownerDocument.createElement('font');
      HTMLArea.xhtml_convertTo(node, context, newNode);
      HTMLArea.xhtml_handleCssToFont(node, newNode, context);
      return;
    }
  }

  HTMLArea.xhtml_removeTagWithNoAttribute(node, context);
};

// version 1.0
HTMLArea.xhtml_removeTagWithNoAttribute = function(node, context) {
  var hasAttrs;
  if (HTMLArea.is_ie)
    hasAttrs = node.outerHTML.htmlTrim().length - node.innerHTML.length > 2*node.tagName.length + 5;
  else {
    var attrs = node.attributes, count = 0;
    for (i = 0; i < attrs.length; ++i) {
      var a = attrs.item(i);
      if (!a.specified || HTMLArea.xhtml_spanIgnoreAttrR.test(a.nodeName))
        continue;
      ++count;
    }
    hasAttrs = count > 0;
  }
  if (!hasAttrs)
    HTMLArea.xhtml_removeTag(node, context);
};

// version 1.1
HTMLArea.xhtml_handleA = function(node, context) {
  MindTouch.normalizeLink(node, context.editor);
};

HTMLArea.xhtml_handleXmlDiff = function(node, context) {
  switch (node.className) {
  case "diff-insert":
  case "diff-delete":
    HTMLArea.xhtml_removeTag(node, context);
    break;
  }
};

// version 1.0
HTMLArea.xhtml_handleDiv = function(node, context) {
  if (node.className != "") {
    switch (node.className) {
    case 'imageWrap':
      HTMLArea.removeFromParent(node);
      return;
    }
    var img = node.firstChild;
    if (img && img.nodeType == 1) {
      var tag = img.tagName.toLowerCase();
	  if (tag == 'img')
        return;
      img = img.firstChild;
	  if (tag == 'a' && img && img.nodeType == 1 && img.tagName.toLowerCase() == 'img')
        return;
    }
    node.removeAttribute("className");
  }
  HTMLArea.xhtml_removeTagWithNoAttribute(node, context);
};

// version 1.0
HTMLArea.xhtml_handleFont = function(node, context) {
  if (node.face != "")
    HTMLArea.xhtml_checkFont(context.editor, node, node.face);
  switch (node.size) {
  case "-2":
  case "+2":
  case "+3":
    break;
  default:
    node.removeAttribute("size");
  }
  if (context.toSave)
    HTMLArea.xhtml_convertFontToSpan(node, context);
  else
    HTMLArea.xhtml_removeTagWithNoAttribute(node, context);
};

// version 1.0
HTMLArea.xhtml_handleBig = function(node, context) {
  if (!context.toSave) {
    var newNode = node.ownerDocument.createElement('font');
    newNode.size = "+2";
    HTMLArea.xhtml_handleCssToFont(node, newNode, context);
    if (node.firstChild != null && node.firstChild.nodeType == 1
      && node.firstChild == node.lastChild
      && node.firstChild.tagName.toLowerCase() == 'font' && node.firstChild.size == "+2") {
      var child = node.firstChild;
      if (child.face != "" && newNode.face == "")
        newNode.face = child.face;
      if (child.color != "" && newNode.color == "")
        newNode.color = child.color;
      HTMLArea.xhtml_removeTag(child, context);
      newNode.size = "+3";
    }
    HTMLArea.xhtml_convertTo(node, context, newNode);
  }
};

// version 1.0
HTMLArea.xhtml_handleSmall = function(node, context) {
  if (!context.toSave) {
    var newNode = node.ownerDocument.createElement('font');
    newNode.size = "-2";
    HTMLArea.xhtml_handleCssToFont(node, newNode, context);
    HTMLArea.xhtml_convertTo(node, context, newNode);
  }
};

// version 1.1
HTMLArea.xhtml_handleImg = function(node, context) {
  if (node.alt == "")
    node.alt = "alt missing";
  if (node.width == 0)
    node.removeAttribute("width");
  if (node.height == 0)
    node.removeAttribute("height");
  MindTouch.normalizeLink(node, context.editor);
};

// version 1.0
HTMLArea.xhtml_handleAttribute = function(node, attrName, styleAttrName, reset) {
  if (typeof node[attrName] != "undefined" && node[attrName] != "") {
    node.style[styleAttrName] = node[attrName];
    node[attrName] = reset;
  }
};

HTMLArea.xhtml_noText_remove = function(node, context) {
  HTMLArea.xhtml_recordEvent(context, true, parentData.tag + " has text, but not allowed");
  node.data = '';
};

HTMLArea.xhtml_noText_insertDd = function(node, context) {
  HTMLArea.xhtml_surroundNode(node, node.ownerDocument.createElement('dd'));
};

HTMLArea.xhtml_noText_insertLi = function(node, context) {
  HTMLArea.xhtml_surroundNode(node, node.ownerDocument.createElement('li'));
};

HTMLArea.xhtml_noText_insertTr = function(node, context) {
  HTMLArea.xhtml_surroundNode(node, node.ownerDocument.createElement('tr'));
  HTMLArea.xhtml_surroundNode(node, node.ownerDocument.createElement('td'));
};

HTMLArea.xhtml_noText_insertTd = function(node, context) {
  HTMLArea.xhtml_surroundNode(node, node.ownerDocument.createElement('td'));
};

// version 1.1
HTMLArea.isNodeDeleted = function(node) {
  return !node || typeof node.parentNode == "unknown" || !node.parentNode || typeof node.parentNode.tagName == "undefined";
};

// version 1.0
HTMLArea.xhtml_validA = "abbr|acronym|big|br|del|strike|em|i|font|img|ins|u|small|span|strong|b|sub|sup|iframe";
HTMLArea.xhtml_validNonBlocks = "a|"+HTMLArea.xhtml_validA;
HTMLArea.xhtml_validBlocks = "address|blockquote|del|div|dl|h[1-6r]|ins|ol|p|pre|table|ul|iframe";
HTMLArea.xhtml_validNonTopBlocks = "address|blockquote|del|div|dl|hr|ins|ol|p|pre|table|ul|iframe";

// version 1.0
HTMLArea.xhtml_validAR = HTMLArea.compileRegex("^("+HTMLArea.xhtml_validA+")$","i");
HTMLArea.xhtml_validNonBlocksR = HTMLArea.compileRegex("^("+HTMLArea.xhtml_validNonBlocks+")$","i");
HTMLArea.xhtml_validBlocksR = HTMLArea.compileRegex("^("+HTMLArea.xhtml_validBlocks+")$","i");
HTMLArea.xhtml_validAllR = HTMLArea.compileRegex("^("+HTMLArea.xhtml_validNonBlocks+"|"+HTMLArea.xhtml_validNonTopBlocks+")$","i");
HTMLArea.xhtml_validPreR = HTMLArea.compileRegex("^(a|abbr|acronym|br|del|strike|em|i|font|ins|u|span|strong|b)$","i");
HTMLArea.xhtml_widthHeightAttrR = HTMLArea.compileRegex("^img|col|colgroup|table|pre|iframe$", "i");

// version 1.0
HTMLArea.xhtml_isBlock = function(node) {
  return node && node.nodeType == 1 && HTMLArea.xhtml_validBlocksR.test(node.tagName);
};

// version 1.2
HTMLArea.validTags = {
  // anchor for hypertext link, http://www.december.com/html/x1/element/a.html
  'a'         : {tag: 'a', validChild: HTMLArea.xhtml_validAR, invalid: HTMLArea.xhtml_invalidFormating, removeRecursive: true, handleElement: HTMLArea.xhtml_handleA},

  // embed small Java program (applet) in document, http://www.december.com/html/4loose/element/applet.html
  // MKS: not supported
  'applet'    : {tag: 'applet'},

  // encloses shortened phrase which represents whole, http://www.december.com/html/x1/element/abbr.html
  'abbr'      : {tag: 'abbr', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_invalidFormating, removeRecursive: true},

  // encloses word formed from letters in a phrase, http://www.december.com/html/x1/element/acronym.html
  'acronym'   : {tag: 'acronym', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_invalidFormating, removeRecursive: true},

  // address, signature, or byline, http://www.december.com/html/x1/element/address.html
  'address'   : {isBlock: true, tag: 'address',  validChild: HTMLArea.xhtml_validNonBlocksR},

  // define region on an imagemap which is a hypertext link, http://www.december.com/html/x1/element/area.html
  // MKS: not supported
  'area'      : {tag: 'area'},

  // bold text, http://www.december.com/html/x1/element/b.html
  // will be convered into 'strong'
  'b'         : {tag: 'b', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_convertToStrong},

  // base context document, http://www.december.com/html/x1/element/base.html
  // MKS: not supported
  'base'      : {tag: 'base', validChild: /^(head|body)$/i},

  // change default font in the document, http://www.december.com/html/4loose/element/basefont.html
  // MKS: not supported
  'basefont'  : {tag: 'basefont'},

  // I18N BiDi over-ride, http://www.december.com/html/x1/element/bdo.html
  // MKS: not supported
  'bdo'       : {tag: 'bdo'},

  // set larger text relative to surrounding text, http://www.december.com/html/x1/element/big.html
  'big'       : {tag: 'big', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_invalidFormating, handleElement: HTMLArea.xhtml_handleBig},

  // quoted passage, http://www.december.com/html/x1/element/blockquote.html
  'blockquote': {isBlock: true, isBlockContainer: true, tag: 'blockquote', validChild: HTMLArea.xhtml_validBlocksR},

  // document body, http://www.december.com/html/x1/element/body.html
  'body'      : {isBlockContainer: true, tag: 'body', validChild: HTMLArea.xhtml_validBlocksR},

  // line break, http://www.december.com/html/x1/element/br.html
  'br'        : {tag: 'br', invalid: HTMLArea.xhtml_invalidFormating, noChildren: true, handleElement: HTMLArea.xhtml_handleBr},

  // push button, http://www.december.com/html/x1/element/button.html
  // MKS: not supported
  'button'    : {tag: 'button'},

  // descriptive phrase for table, http://www.december.com/html/x1/element/caption.html
  'caption'   : {tag: 'caption'},

  // MKS: not supported -> convert into <* style="text-align:center"></*>
  'center'    : {tag: 'center', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_convertToCenterStyle},

  // name or title of cited work, http://www.december.com/html/x1/element/cite.html
  // MKS: not supported, convert to <em></em>
  'cite'      : {tag: 'cite', invalid: HTMLArea.xhtml_convertToEm},

  // source (computer) code, http://www.december.com/html/x1/element/code.html
  // MKS: not supported, converted into 'code' style
  'code'      : {tag: 'code', invalid: HTMLArea.xhtml_convertToCode},

  // vertical alignment in cells, http://www.december.com/html/x1/element/col.html
  'col'       : {isTableElement: true, tag: 'col', noChildren: true},

  // vertical alignment in cells, http://www.december.com/html/x1/element/colgroup.html
  'colgroup'  : {isTableElement: true, tag: 'colgroup', validChild: /^col$/i, noText: HTMLArea.xhtml_noText_remove},

  // definition of term, http://www.december.com/html/x1/element/dd.html
  'dd'        : {isBlockContainer: true, tag: 'dd', validChild: HTMLArea.xhtml_validAllR},
  
  // inserted text, deleted text, http://www.december.com/html/x1/element/del.html
  'del'       : {isBlock: true, isBlockContainer: true, tag: 'del',  validChild: HTMLArea.xhtml_validAllR, handleElement: HTMLArea.xhtml_handleXmlDiff},

  // enclose term definition, http://www.december.com/html/x1/element/dfn.html
  // MKS: not supported, convert to <em></em>
  'dfn'       : {tag: 'dfn', invalid: HTMLArea.xhtml_convertToEm},

  // define parts of a document, http://www.december.com/html/x1/element/div.html
  'div'       : {isBlock: true, isBlockContainer: true, tag: 'div',  validChild: HTMLArea.xhtml_validAllR, handleElement: HTMLArea.xhtml_handleDiv},

  // directory list, http://www.december.com/html/4loose/element/dir.html
  // MKS: not supported, convert to <ol></ol>
  'dir'       : {tag: 'dir', invalid: HTMLArea.xhtml_convertToOl},

  // definition list or glossary, http://www.december.com/html/x1/element/dl.html
  'dl'        : {isBlock: true, tag: 'dl',  validChild: /^(dd|dt)$/i, noText: HTMLArea.xhtml_noText_insertDd},

  // term in definition list, http://www.december.com/html/x1/element/dt.html
  'dt'        : {tag: 'dt', validChild: HTMLArea.xhtml_validNonBlocksR},

  // emphasized phrase, http://www.december.com/html/x1/element/em.html
  'em'        : {tag: 'em', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_invalidFormating, removeRecursive: true},

  // form control group, http://www.december.com/html/x1/element/fieldset.html
  // MKS: not supported
  'fieldset'  : {tag: 'fieldset'},

  // set font face, color, and size of text, http://www.december.com/html/4loose/element/font.html
  // MKS: not XHTML 1.1, convert to <span style="xxx"></span>
  'font'      : {tag: 'font', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_invalidFormating, handleElement: HTMLArea.xhtml_handleFont},

  // fill-out or data-entry form, http://www.december.com/html/x1/element/form.html
  // MKS: not supported
  'form'      : {tag: 'form'},

  // primary heading, http://www.december.com/html/x1/element/h1.html
  'h1'        : {isBlock: true, tag: 'h1', invalid: HTMLArea.xhtml_invalidH, handleElement: HTMLArea.xhtml_handleH},

  // secondary heading, http://www.december.com/html/x1/element/h2.html
  'h2'        : {isBlock: true, tag: 'h2', invalid: HTMLArea.xhtml_invalidH, handleElement: HTMLArea.xhtml_handleH},

  // third-level heading, http://www.december.com/html/x1/element/h3.html
  'h3'        : {isBlock: true, tag: 'h3', invalid: HTMLArea.xhtml_invalidH, handleElement: HTMLArea.xhtml_handleH},

  // fourth-level heading, http://www.december.com/html/x1/element/h4.html
  'h4'        : {isBlock: true, tag: 'h4', invalid: HTMLArea.xhtml_invalidH, handleElement: HTMLArea.xhtml_handleH},

  // fifth-level heading, http://www.december.com/html/x1/element/h5.html
  'h5'        : {isBlock: true, tag: 'h5', invalid: HTMLArea.xhtml_invalidH, handleElement: HTMLArea.xhtml_handleH},

  // sixth-level heading, http://www.december.com/html/x1/element/h6.html
  'h6'        : {isBlock: true, tag: 'h6', invalid: HTMLArea.xhtml_invalidH, handleElement: HTMLArea.xhtml_handleH},

  // document head, http://www.december.com/html/x1/element/head.html
  // MKS: not supported
  'head'      : {tag: 'head'},

  // horizontal rule, http://www.december.com/html/x1/element/hr.html
  'hr'        : {isBlock: true, tag: 'hr', noChildren: true},

  // HTML document outer container, http://www.december.com/html/x1/element/html.html 
  // MKS: not supported
  'html'      : {tag: 'html', validChild: /^(head|body)$/i},

  // italic text, http://www.december.com/html/x1/element/i.html
  // MKS: not supported, convert into <em></em>
  'i'         : {tag: 'i', invalid: HTMLArea.xhtml_convertToEm},

  // MKS: not supported
  'iframe'    : {tag: 'iframe',isBlock: true, noChildren: true},

  // image; photo, icon, glyph, or illustration, http://www.december.com/html/x1/element/img.html
  'img'       : {tag: 'img', invalid: HTMLArea.xhtml_invalidFormating, noChildren: true, handleElement: HTMLArea.xhtml_handleImg},

  // form input datum, http://www.december.com/html/x1/element/input.html
  // MKS: not supported
  'input'     : {tag: 'input'},

  // inserted text, deleted text, http://www.december.com/html/x1/element/ins.html
  'ins'       : {isBlock: true, isBlockContainer: true, tag: 'ins',  validChild: HTMLArea.xhtml_validAllR, handleElement: HTMLArea.xhtml_handleXmlDiff},

  // searchable document input form, http://www.december.com/html/4loose/element/isindex.html
  // MKS: not supported
  'isindex'   : {tag: 'isindex'},

  // keyboard phrase (user input), http://www.december.com/html/x1/element/kbd.html
  // MKS: not supported, converted into 'code' style
  'kbd'       : {tag: 'kbd', invalid: HTMLArea.xhtml_convertToCode},

  // form field label text, http://www.december.com/html/x1/element/label.html
  // MKS: not supported
  'label'     : {tag: 'label'},

  // fieldset legend, http://www.december.com/html/x1/element/legend.html
  // MKS: not supported
  'legend'    : {tag: 'legend'},

  // list item, http://www.december.com/html/x1/element/li.html
  'li'        : {isBlockContainer: true, tag: 'li', validChild: HTMLArea.xhtml_validAllR, invalid: HTMLArea.xhtml_invalidListItem},

  // link from this document, http://www.december.com/html/x1/element/link.html
  // MKS: not supported
  'link'      : {tag: 'link'},

  // define client-side imagemap, http://www.december.com/html/x1/element/map.html
  // MKS: not supported
  'map'       : {tag: 'map'},

  // menu list, http://www.december.com/html/4loose/element/menu.html
  // MKS: not supported, convert to <ol></ol>
  'menu'      : {tag: 'menu', invalid: HTMLArea.xhtml_convertToOl},

  // generic meta-information about the document, http://www.december.com/html/x1/element/meta.html
  // MKS: not supported
  'meta'      : {tag: 'meta'},

  // option group, http://www.december.com/html/x1/element/optgroup.html
  // MKS: not supported
  'optgroup'  : {tag: 'optgroup'},

  // a selection option, http://www.december.com/html/x1/element/option.html
  // MKS: not supported
  'option'    : {tag: 'option'},

  // alternate content container for non script-based rendering, http://www.december.com/html/x1/element/noscript.html
  // MKS: not supported
  'noscript'  : {tag: 'noscript'},

  // generic embedded object, http://www.december.com/html/x1/element/object.html
  // MKS: not supported
  'object'    : {tag: 'object'},

  // ordered list, http://www.december.com/html/x1/element/ol.html
  'ol'        : {isBlock: true, tag: 'ol', validChild: /^li$/i, invalid: HTMLArea.xhtml_invalidList, noText: HTMLArea.xhtml_noText_insertLi, handleElement: HTMLArea.xhtml_handleList},

  // paragraph, http://www.december.com/html/x1/element/p.html
  'p'         : {isBlock: true, tag: 'p', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_invalidP, handleElement: HTMLArea.xhtml_handleP},

  // named property value, http://www.december.com/html/x1/element/param.html
  // MKS: not supported
  'param'     : {tag: 'param'},

  // preformatted text, http://www.december.com/html/x1/element/pre.html
  // (no nested blocks, must not contain the img, object, big, small, sub, or sup elements.)
  'pre'       : {isBlock: true, tag: 'pre', validChild: HTMLArea.xhtml_validPreR},

  // short inline quotation, http://www.december.com/html/x1/element/q.html
  // MKS: not supported
  'q'         : {tag: 'q'},
  
  // cross out text, http://www.december.com/html/4loose/element/s.html
  // MKS: not supported, convert to <del></del>
  's'         : {tag: 's', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_convertToDel},

  // sample text or characters, http://www.december.com/html/x1/element/samp.html
  // MKS: not supported, converted into 'code' style
  'samp'      : {tag: 'samp', invalid: HTMLArea.xhtml_convertToCode},

  // script for user-document interaction, http://www.december.com/html/x1/element/script.html
  // MKS: not supported
  'script'    : {tag: 'script'},

  // selection of option(s), http://www.december.com/html/x1/element/select.html
  // MKS: not supported
  'select'    : {tag: 'select'},

  // set smaller text relative to surrounding text, http://www.december.com/html/x1/element/small.html
  'small'     : {tag: 'small', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_invalidFormating, handleElement: HTMLArea.xhtml_handleSmall},

  // generic language/style container, http://www.december.com/html/x1/element/span.html
  'span'      : {tag: 'span', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_invalidFormating, handleElement: HTMLArea.xhtml_handleSpan},

  // cross out text, http://www.december.com/html/4loose/element/strike.html
  // MKS: not supported, converted into <del></del>
  'strike'    : {tag: 'strike', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_convertToDel},

  // strong emphasis, http://www.december.com/html/x1/element/strong.html
  'strong'    : {tag: 'strong', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_invalidFormating, removeRecursive: true},

  // style information, http://www.december.com/html/x1/element/style.html
  // MKS: not supported (custom style sheets)
  'style'     : {tag: 'style'},

  // subscript text, http://www.december.com/html/x1/element/sub.html
  'sub'       : {tag: 'sub', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_invalidFormating},

  // superscript, http://www.december.com/html/x1/element/sup.html
  'sup'       : {tag: 'sup', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_invalidFormating},

  // tabular presentation of information, http://www.december.com/html/x1/element/table.html
  'table'     : {isTableElement: true, isBlock: true, tag: 'table', validChild: /^(caption|col|colgroup|thead|tbody|tr|tfoot)$/i, noText: HTMLArea.xhtml_noText_insertTr},

  // table body, http://www.december.com/html/x1/element/tbody.html
  'tbody'     : {isTableElement: true, tag: 'tbody', validChild: /^tr$/i, noText: HTMLArea.xhtml_noText_insertTr},

  // table data cell, http://www.december.com/html/x1/element/td.html
  'td'        : {isTableElement: true, isBlockContainer: true, tag: 'td', validChild: HTMLArea.xhtml_validAllR, handleElement: HTMLArea.xhtml_handleTD},

  // table footer, http://www.december.com/html/x1/element/tfoot.html
  'tfoot'     : {isTableElement: true, tag: 'tfoot', validChild: /^tr$/i, noText: HTMLArea.xhtml_noText_insertTr},

  // table header cell, http://www.december.com/html/x1/element/th.html
  'th'        : {isTableElement: true, isBlockContainer: true, tag: 'th', validChild: HTMLArea.xhtml_validAllR, handleElement: HTMLArea.xhtml_handleTD},
  
  // table header, http://www.december.com/html/x1/element/thead.html
  'thead'     : {isTableElement: true, tag: 'thead', validChild: /^tr$/i, noText: HTMLArea.xhtml_noText_insertTr},

  // title of document, http://www.december.com/html/x1/element/title.html
  // MKS: not supported
  'title'     : {tag: 'title'},

  // table row container, http://www.december.com/html/x1/element/tr.html
  'tr'        : {isTableElement: true, tag: 'tr', validChild: /^(td|th)$/i, noText: HTMLArea.xhtml_noText_insertTd},

  // an area for text input, http://www.december.com/html/x1/element/textarea.html
  // MKS: not supported
  'textarea'  : {tag: 'textarea'},

  // typewriter text, http://www.december.com/html/x1/element/tt.html
  // MKS: not supported, converted into 'code' style
  'tt'        : {tag: 'tt', invalid: HTMLArea.xhtml_convertToCode},
  
  // underline text, http://www.december.com/html/4loose/element/u.html
  // MKS: not supported, converted into <ins></ins>
  'u'         : {tag: 'u', validChild: HTMLArea.xhtml_validNonBlocksR, invalid: HTMLArea.xhtml_convertToIns},

  // unordered list, http://www.december.com/html/x1/element/ul.html
  'ul'        : {isBlock: true, tag: 'ul', validChild: /^li$/i, invalid: HTMLArea.xhtml_invalidList, noText: HTMLArea.xhtml_noText_insertLi, handleElement: HTMLArea.xhtml_handleList},

  // variable phrase or substitute, http://www.december.com/html/x1/element/var.html
  // MKS: not supported, convert to <em></em>
  'var'       : {tag: 'var', invalid: HTMLArea.xhtml_convertToEm}
};

HTMLArea.prototype.getXHTML = function() {
  var doc = this._doc.documentElement.cloneNode(true);
  var body = doc.getElementsByTagName('body')[0];
  HTMLArea.makeXHTML(body, this.makeXHTMLContext(true));
  var html = HTMLArea.getHTML(body, false, this);
  delete doc;
  return html;
};

// version 1.0
HTMLArea.prototype.makeXHTMLContext = function(toSave) {
  return {editor: this, toSave: toSave, invalid: 0, changed: 0, debugLog: "", _starttime: new Date().getTime(), _nodes: 0};
};

// version 1.0
HTMLArea.xhtml_recordEvent = function(context,isInvalid,text) {
  if (isInvalid) ++context.invalid;
  else ++context.changed;
  context.debugLog += (isInvalid ? "INVALID" : "CHANGED") + ": " + text + "\n";
};

// version 1.3
HTMLArea.xhtml_textUnescapeR = HTMLArea.compileRegex("%u([0-9A-F]{4})", "gi");
HTMLArea.makeXHTML = function(node, context, parent, parentData) {
  var top = !parent;
//  var start;
//  if (top) start = HTMLArea.getOuterHTML(node);

  ++context._nodes;
  if (node == null) node = context.editor._doc.body;
  if (!parent) { parent = node.parentNode; }
  else if (parent != node.parentNode) {
    parent = node.parentNode;
    parentData = null;
  }
  if (!parentData && parent)
    parentData = HTMLArea.validTags[parent.tagName.toLowerCase()];

  if (parentData && parentData.noChildren) {
    parent.removeChild(node);
    return;
  }

  switch (node.nodeType) {
    case 2: // Node.ATTRIBUTE_NODE
    case 7: // Node.PROCESSING_INSTRUCTION_NODE
    case 10:// Node.DOCUMENT_TYPE_NODE
    case 12:// Node.NOTATION_NODE
      break;

    case 8: // Node.COMMENT_NODE
      break;

    case 4: // Node.CDATA_SECTION_NODE
    case 5: // Node.ENTITY_REFERENCE_NODE
    case 6: // Node.ENTITY_NODE
      break;
      
    case 9: // Node.DOCUMENT_NODE
    case 11:// Node.DOCUMENT_FRAGMENT_NODE
      for (var i = node.firstChild; i; i = i.nextSibling)
        HTMLArea.makeXHTML(i, context, node);
      break;

    case 3: // Node.TEXT_NODE
      // handle %uXXXX form in text coming from Word
      var d = node.data;
      var nd = d.replace(HTMLArea.xhtml_textUnescapeR, function(s,b){return unescape(s);});
      if (d.length != nd.length) {
        HTMLArea.xhtml_recordEvent(context, false, "%uXXXX text decoded");
        node.data = nd;
      }

      if (parentData) {
        var l = node.data.htmlTrim().length;
        if (/^h[1-6]$/.test(parentData.tag)) {
          nd = nd.htmlTrim();
          if (nd.length != node.data.length)
            node.data = node.nextSibling ? nd + " " : nd;
        }

        if (l != 0 && (parentData.tag == 'body' || parentData.tag == 'blockquote')) {
          HTMLArea.xhtml_recordEvent(context, true, "text in 'body/blockquote' promoted");
          HTMLArea.xhtml_invalidFormating(node, context);
        }

        if (parentData.noText && l != 0) {
          parentData.noText(node, context);
        }
      }
      break;

    case 1: // Node.ELEMENT_NODE
    {
      var tagName = node.tagName.toLowerCase();
      var tagData = HTMLArea.validTags[tagName];
      var contextTag = tagName;
      var contextExists = typeof context[contextTag] != "undefined";
      if (!contextExists)
        context[contextTag] = 1;
      else
        ++context[contextTag];

      // handle all the children
      var children = HTMLArea.xhtml_getChildren(node);
      HTMLArea.xhtml_handleChildren(children, context);

      if (!contextExists)
        delete context[contextTag];
      else
        --context[contextTag];

      if (HTMLArea.isNodeDeleted(node))
        return;

      if (!tagData || (contextExists && !tagData.isBlock && tagData.removeRecursive)) {
        if (tagData)
          HTMLArea.xhtml_recordEvent(context, false, tagName + " recursive, removed");
        else
          HTMLArea.xhtml_recordEvent(context, true, tagName + " invalid, removed");
        // remove recusive or invalid tags
        HTMLArea.xhtml_removeTag(node, context);
        return;
      }

      if (node.firstChild == null && !tagData.noChildren && tagName != 'body') {
        if ((tagData.isBlock || tagName == 'td') && tagName != 'ul' && tagName != 'div') {
          if (context.toSave || !HTMLArea.is_ie) {
            node.appendChild(node.ownerDocument.createElement('br'));
            HTMLArea.xhtml_recordEvent(context, false, tagName + " empty, &nbsp; added");
          }
        } else {
          // remove empty format tags
          HTMLArea.xhtml_removeTag(node, context);
          HTMLArea.xhtml_recordEvent(context, false, tagName + " empty, removed");
          return;
        }
      }

      if (node.parentNode != parent) {
        parent = node.parentNode;
        parentData = HTMLArea.validTags[parent.tagName.toLowerCase()];
      }
      if (!parentData || !parentData.validChild || !parentData.validChild.test(node.tagName)) {
        HTMLArea.xhtml_recordEvent(context, true, (parentData ? parentData.tag : "???") + " does not allow " + tagName + ", " + (tagData.invalid ? "handled" : "removed"));
        // handle invalid tag's

        if (HTMLArea.isNodeDeleted(node))
          return;

        if (tagData.invalid)
          node = tagData.invalid(node, context);
        else if (tagData.isBlock)
          node = HTMLArea.xhtml_invalidBlock(node, context);
        else
          node = HTMLArea.xhtml_invalidNonBlock(node, context);
      }

      if (HTMLArea.isNodeDeleted(node))
        return;

      if (node.className.length > 0)
        HTMLArea.xhtml_handleClassName(node, context);
      if (context.toSave && tagName != "col" && tagName != "img" && tagName != "table" && tagName != "div")
        HTMLArea.xhtml_handleAttribute(node, "align", "textAlign", "");
      HTMLArea.xhtml_handleAttribute(node, "bgColor", "backgroundColor", "");
      if (tagName != "table")
        HTMLArea.xhtml_handleAttribute(node, "border", "border", null);
      if (!HTMLArea.xhtml_widthHeightAttrR.test(tagName)) {
        HTMLArea.xhtml_handleAttribute(node, "width", "width", "");
        HTMLArea.xhtml_handleAttribute(node, "height", "height", "");
      }
      if (tagName != "body" && node.id != "")
        node.removeAttribute('id');
      if (node.style.cssText.length > 0) {
        HTMLArea.xhtml_handleCssStyle(node, context);
        if (HTMLArea.isNodeDeleted(node))
          return;
      }
      node.onmouseover = node.onmouseout = null;
      if (tagData.handleElement)
        tagData.handleElement(node, context);
      break;
    }
  }

  if (top) {
//    var end = HTMLArea.getOuterHTML(node);
//    alert('start: ' + start.replace(/[\x10\x13]/g,'') + '\nend: ' + end.replace(/[\x10\x13]/g,''));
    context._endtime = new Date().getTime();
    context._timeDiff = context._endtime - context._starttime;
  }
  /* >MT: DEBUG
  if (top && context.invalid + context.changed > 0)
    alert(context.debugLog);
  /* <MT: DEBUG */
};

/*
 * MindTouch DekiWiki - a commercial grade open source wiki
 *  derived from MediaWiki (www.mediawiki.org)
 * Copyright (C) 2006 MindTouch, Inc.
 * www.mindtouch.com  oss@mindtouch.com
 *
 * For community documentation and downloads visit www.opengarden.org;
 *  please review the licensing section.
 *
 * 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.
 * http://www.gnu.org/copyleft/gpl.html
 */

// MT: adding showbutton
HTMLArea.Config.MTregisterButton = function(self, id, tooltip, image, textMode, action, context, showbutton) {
  var the_id;
  if (typeof id == "string") {
    the_id = id;
  } else if (typeof id == "object") {
    the_id = id.id;
  } else {
    alert("ERROR [HTMLArea.Config::registerButton]:\ninvalid arguments");
    return false;
  }
  // check for existing id
  if (typeof self.customSelects[the_id] != "undefined") {
    // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown with the same ID already exists.");
  }
  if (typeof self.btnList[the_id] != "undefined") {
    // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button with the same ID already exists.");
  }
  switch (typeof id) {
    // >MT: adding showbutton
    case "string": self.btnList[id] = [ tooltip, image, textMode, action, context, showbutton ]; break;
    case "object": self.btnList[id.id] = [ id.tooltip, id.image, id.textMode, id.action, id.context, id.showbutton ]; break;
    // <MT
  }
};

// MT: adding this._readOnly
HTMLArea.prototype._createToolbar = function () {
  var editor = this;	// to access this in nested functions
  var toolbar = document.createElement("div");

  // ._toolbar is for legacy, ._toolBar is better thanks.
  this._toolBar = this._toolbar = toolbar;
  toolbar.className = "toolbar";
  toolbar.unselectable = "1";
  // >MT: add this._readOnly
  this._readOnly = false;
  if (typeof prependHTMLToToolbar != "undefined") {
    var prependHTML = prependHTMLToToolbar(this);
    if (prependHTML == null)
      this._readOnly = true;
    else
      toolbar.innerHTML = prependHTML + toolbar.innerHTML;
  }
  // <MT
  
  HTMLArea.freeLater(this, '_toolBar');
  HTMLArea.freeLater(this, '_toolbar');
  
  var tb_row = null;
  var tb_objects = new Object();
  this._toolbarObjects = tb_objects;
  this._createToolbar1(editor, toolbar, tb_objects);
  this._htmlArea.appendChild(toolbar);

  return toolbar;
};


// >MT: update ._createToolbar1 for 2-D layout
HTMLArea.prototype._createToolbar1 = function(editor, toolbar, tb_objects) {

  // each toolbar control is added to a "line" (lineTable, lineRow)
  // a section (secTable/secBody) is a table with 1 or 2 lines
  // the toolbar is a table (tbTable) of sections and separators
  //   (horizontal layout)

  var secBody;
  var lineRow;
  
  var tbTable = document.createElement("table");
  tbTable.style.width = "auto";
  tbTable.border = "0px";
  tbTable.cellSpacing = "0px";
  tbTable.cellPadding = "0px";
  toolbar.appendChild(tbTable);
  var tbBody = document.createElement("tbody");
  tbTable.appendChild(tbBody);
  var tbRow = document.createElement("tr");
  tbBody.appendChild(tbRow);

  // creates a new section in the toolbar
  function newSection() {
    var tbCell = document.createElement("td");
    tbRow.appendChild(tbCell);

    var secTable = document.createElement("table");
    secTable.style.width = "auto";
    secTable.border = "0px";
    secTable.cellSpacing = "0px";
    secTable.cellPadding = "0px";
    tbCell.appendChild(secTable);
    secBody = document.createElement("tbody");
    secTable.appendChild(secBody);

    newLine();
  }; // END of function: newSection

  // creates a new line in the section
  function newLine() {
    var secRow = document.createElement("tr");
    secBody.appendChild(secRow);
    var secCell = document.createElement("td");
    secRow.appendChild(secCell);

    var lineTable = document.createElement("table");
    lineTable.className = "toolbarRow";
    secCell.appendChild(lineTable);
    var lineBody = document.createElement("tbody");
    lineTable.appendChild(lineBody);
    lineRow = document.createElement("tr");
    lineBody.appendChild(lineRow);
  }; // END of function: newLine

  // add the initial section
  newSection();

  // adds a separator to the toolbar, and starts a new section
  function addSeparator() {
    var tbCell = document.createElement("td");
    el = document.createElement("div");
    el.className = "separator";
    tbCell.width = "15px";
    tbCell.align = "center";
    tbCell.appendChild(el);
    tbRow.appendChild(tbCell);

    newSection();
  }; // END of function: addSeparator

  // updates the state of a toolbar element.  This function is member of
  // a toolbar element object (unnamed objects created by createButton or
  // createSelect functions below).
  function setButtonStatus(id, newval) {
    var oldval = this[id];
    var el = this.element;
    if (oldval != newval) {
      switch (id) {
        case "enabled":
        if (newval) {
          HTMLArea._removeClass(el, "buttonDisabled");
          el.disabled = false;
        } else {
          HTMLArea._addClass(el, "buttonDisabled");
          el.disabled = true;
        }
        break;
        case "active":
        if (newval) {
          HTMLArea._addClass(el, "buttonPressed");
        } else {
          HTMLArea._removeClass(el, "buttonPressed");
        }
        break;
      }
      this[id] = newval;
    }
  }; // END of function: setButtonStatus

  // this function will handle creation of combo boxes.  Receives as
  // parameter the name of a button as defined in the toolBar config.
  // This function is called from createButton, above, if the given "txt"
  // doesn't match a button.
  function createSelect(txt) {
    var options = null;
    var el = null;
    var cmd = null;
    var customSelects = editor.config.customSelects;
    var context = null;
    var tooltip = "";
    switch (txt) {
      case "fontsize":
      case "fontname":
      case "formatblock":
      // >MT: fontstyles
      case "fontstyles":
      // <MT
      // the following line retrieves the correct
      // configuration option because the variable name
      // inside the Config object is named the same as the
      // button/select in the toolbar.  For instance, if txt
      // == "formatblock" we retrieve config.formatblock (or
      // a different way to write it in JS is
      // config["formatblock"].
      options = editor.config[txt];
      cmd = txt;
      break;
      default:
      // try to fetch it from the list of registered selects
      cmd = txt;
      var dropdown = customSelects[cmd];
      if (typeof dropdown != "undefined") {
        options = dropdown.options;
        context = dropdown.context;
        if (typeof dropdown.tooltip != "undefined") {
          tooltip = dropdown.tooltip;
        }
      } else {
        alert("ERROR [createSelect]:\nCan't find the requested dropdown definition");
      }
      break;
    }
    if (options) {
      el = document.createElement("select");
      el.title = tooltip;
      var obj = {
        name  : txt,  // field name
        element : el,   // the UI element (SELECT)
        enabled : true,   // is it enabled?
        text  : false,  // enabled in text mode?
        cmd   : cmd,  // command ID
        state   : setButtonStatus, // for changing state
        context : context
      };

      HTMLArea.freeLater(obj);

      tb_objects[txt] = obj;

      for (var i in options) {
        var op = document.createElement("option");
        op.innerHTML = HTMLArea._lc(i);
        op.value = options[i];
        el.appendChild(op);
      }
      HTMLArea._addEvent(el, "change", function () {
        editor._comboSelected(el, txt);
      });
    }
    return el;
  }; // END of function: createSelect

  // appends a new button to toolbar
  function createButton(txt) {
    // >MT: handle 'link:' and 'label:'
    if (txt.substring(0, 5) == "link:") {
      var txtLbl = txt.substring(5).split('|');
      var el = document.createElement("a");
      el.href = "javascript:void(0)";
      el.txt = txtLbl[0];
      el.onclick = function() {
        var obj = tb_objects[this.txt]
        obj.cmd(editor, obj.name, obj);
        return false;
      };
      el.innerHTML = txtLbl[1];
      return el;
    }
    if (txt.substring(0, 6) == "label:") {
      var el = document.createElement("span");
      el.innerHTML = txt.substring(6);
      return el;
    }
    // <MT
    // >MT: handle 'showbutton'
    var btn = editor.config.btnList[txt];
    if (btn && btn[5] == false) {
      return -1;
    }
    // <MT
    // the element that will be created
    var el = null;
    var btn = null;
    switch (txt) {
      case "separator":
      addSeparator();
      return false;
      case "space":
      //el = document.createElement("div");
      //el.className = "space";
      //break;
      return false;
      case "linebreak":
      newLine();
      return false;
      case "textindicator":
      el = document.createElement("div");
      el.appendChild(document.createTextNode("A"));
      el.className = "indicator";
      el.title = HTMLArea._lc("Current style");
      var obj = {
        name	: txt, // the button name (i.e. 'bold')
        element : el, // the UI element (DIV)
        enabled : true, // is it enabled?
        active	: false, // is it pressed?
        text	: false, // enabled in text mode?
        cmd	  : "textindicator", // the command ID
        state	: setButtonStatus // for changing state
      };

      HTMLArea.freeLater(obj);

      tb_objects[txt] = obj;
      break;
      default:
      btn = editor.config.btnList[txt];
    }
    if (!el && btn) {
      var btnLabel = "";
      if (btn[0] == _lang_tooltip_save)
        btnLabel = _lang_label_save;
      else if (btn[0] == _lang_tooltip_cancel)
        btnLabel = _lang_label_cancel;
		
      el = document.createElement("a");
      el.id = 'ebi_' + btn[0].replace(/\s*/g,'');  // Editor Button Id
      el.style.display = 'block';
      el.href = 'javascript:void(0)';
      el.style.textDecoration = 'none';
      el.title = btn[0];
      el.className = "buttonMT";
      if (btnLabel == "")
        el.style.width = "18px";
      else
        el.style.width = "60px";
      el.style.height = "18px";

      // let's just pretend we have a button object, and
      // assign all the needed information to it.
      var obj = {
        name	: txt, // the button name (i.e. 'bold')
        element : el, // the UI element (DIV)
        enabled : true, // is it enabled?
        active	: false, // is it pressed?
        text	: btn[2], // enabled in text mode?
        cmd	  : btn[3], // the command ID
        state	: setButtonStatus, // for changing state
        context : btn[4] || null // enabled in a certain context?
      };

      HTMLArea.freeLater(obj);

      tb_objects[txt] = obj;
      // handlers to emulate nice flat toolbar buttons
      HTMLArea._addEvent(el, "mouseout", function () {
        if (obj.enabled) with (HTMLArea) {
          //_removeClass(el, "buttonHover");
          _removeClass(el, "buttonActive");
          (obj.active) && _addClass(el, "buttonPressed");
        }
      });

      HTMLArea._addEvent(el, "mousedown", function (ev) {
        if (obj.enabled) with (HTMLArea) {
          _addClass(el, "buttonActive");
          _removeClass(el, "buttonPressed");
          _stopEvent(is_ie ? window.event : ev);
        }
      });
      // when clicked, do the following:
      HTMLArea._addEvent(el, "click", function (ev) {
        if (obj.enabled) with (HTMLArea) {
          _removeClass(el, "buttonActive");
          //_removeClass(el, "buttonHover");
          if(HTMLArea.is_gecko)
          {
            editor.activateEditor();
          }
          obj.cmd(editor, obj.name, obj);
          _stopEvent(is_ie ? window.event : ev);
        }
      });
		
      //if (btnLabel == '') {
	      var i_contain = HTMLArea.makeBtnImg(btn[1]);
	      var img = i_contain.firstChild;
	      el.appendChild(i_contain);
      //}
      
      if (btnLabel != "") {
        var labelSpan = document.createElement("span");
        labelSpan.innerHTML = btnLabel;
		labelSpan.className = "buttonLabelMT";
		labelSpan.id = 'btn'+btnLabel;
		if (!HTMLArea.is_ie) {
		  labelSpan.style.left = "21px";
		  labelSpan.style.top = "-16px";
		}
        el.appendChild(labelSpan);
      }

      obj.imgel = img;
      obj.swapImage = function(newimg)
      {
        if(typeof newimg != 'string')
        {
          img.src = newimg[0];
          img.style.position = 'relative';
          img.style.top  = newimg[2] ? ('-' + (18 * (newimg[2] + 1)) + 'px') : '-18px';
          img.style.left = newimg[1] ? ('-' + (18 * (newimg[1] + 1)) + 'px') : '-18px';
        }
        else
        {
          obj.imgel.src = newimg;
          img.style.top = '0px';
          img.style.left = '0px';
        }
      }

    } else if (!el) {
      el = createSelect(txt);
    }

    return el;
  };

  var first = true;
  for (var i = 0; i < this.config.toolbar.length; ++i) {
    if (!first) {
      // createButton("linebreak");
    } else {
      first = false;
    }
    if(this.config.toolbar[i] == null) this.config.toolbar[i] = ['separator'];
    var group = this.config.toolbar[i];

    for (var j = 0; j < group.length; ++j)
    {
      var code = group[j];
      if (/^([IT])\[(.*?)\]/.test(code))
      {
        // special case, create text label
        var l7ed = RegExp.$1 == "I"; // localized?
        var label = RegExp.$2;
        if (l7ed) {
          label = HTMLArea._lc(label);
        }
        var tb_cell = document.createElement("td");
        lineRow.appendChild(tb_cell);
        tb_cell.className = "label";
        tb_cell.innerHTML = label;
      }
      else if(typeof code != 'function')
      {
        var tb_element = createButton(code);

        // >MT: handle hidden buttons
        if (tb_element && tb_element != -1)
        // <MT
        {
          var tb_cell = document.createElement("td");
          tb_cell.className = 'toolbarElement';
          lineRow.appendChild(tb_cell);
          tb_cell.appendChild(tb_element);
        }
        else if (tb_element == null)
        {
          alert("FIXME: Unknown toolbar item: " + code);
        }
      }
    }
  }

  return toolbar;
};
// <MT


// MT: add many more cases to _wordClean
HTMLArea.prototype._wordClean = function() {
  // _wordClean: main
  var startTag, endTag;
  var t = this._doc.body.innerHTML;
  HTMLArea.getElementsByTagNameF(this._doc.body,'span',function(el) {
    if (el.className == 'pasteTag start')
      startTag = el;
    if (el.className == 'pasteTag end')
      endTag = el;
  });
  var root = this._doc.body;
  if (startTag || endTag) {
    var r = this._createRange();
    if (startTag) {
      MindTouch.selectNode(r, startTag);
      this.deleteContents(r);
    }
    var r2 = MindTouch.cloneRange(r);
    if (endTag) {
      MindTouch.selectNode(r2, endTag);
      this.deleteContents(r2);
    }
    if (endTag && startTag) {
      MindTouch.setEndToStart(r, r2);
      root = MindTouch.commonAncestorContainer(r);
    }
    if (!root) root = this._doc.body;
  }

  HTMLArea.makeXHTML(root, this.makeXHTMLContext(false));
  // >MT: causing Mac FF to clean editor after load
  this.updateToolbar();
  // <MT
};

// MT: use an undo engine
HTMLArea.prototype._undoTakeSnapshot = function() {
  ++this._undoPos;
  if (this._undoPos >= this.config.undoSteps) {
    // remove the first element
    this._undoQueue.shift();
    --this._undoPos;
  }
  // use the fasted method (getInnerHTML);
  var take = typeof this._textArea != "undefined";
  var html = this.getInnerHTML();
  var oldState;
  if (this._undoPos > 0) {
    oldState = this._undoQueue[this._undoPos - 1];
    take = (oldState.html != html);
  }
  if (take) {
    if (oldState != null)
      this._storeUndoCursor(oldState);
    var state = {
        html:       html,
        scrollTop:  0,
        scrollLeft: 0,
        curNode:    "/"
    };
    this._undoQueue[this._undoPos] = state;
  } else {
    this._undoPos--;
  }
};

// MT: use an undo engine
HTMLArea.prototype.undo = function() {
  if (this._undoPos > 0) {
    this._storeUndoCursor(this._undoQueue[this._undoPos]);
    if (!this.restoreState(this._undoQueue[--this._undoPos]))
      ++this._undoPos;
  }
};

// MT: use an undo engine
HTMLArea.prototype.redo = function() {
  if (this._undoPos < this._undoQueue.length - 1) {
    this._storeUndoCursor(this._undoQueue[this._undoPos]);
    if (!this.restoreState(this._undoQueue[++this._undoPos]))
      --this._undoPos;
  }
};


// Returns the deepest ancestor of the selection that is of the current type
HTMLArea.prototype._getFirstAncestorF = function(sel, fn)
{
  var prnt = this._activeElement(sel);
  if(prnt == null)
  {
    try
    {
      prnt = (HTMLArea.is_ie ? this._createRange(sel).parentElement() : this._createRange(sel).commonAncestorContainer);
    }
    catch(e)
    {
      return null;
    }
  }

  while(prnt)
  {
    if (fn(prnt))
      return prnt;
    if (/^(body|table)$/i.test(prnt.tagName))
      break;
    prnt = prnt.parentNode;
  }

  return null;
}

// Returns the deepest ancestor of the selection that is of the current type
HTMLArea.prototype._getFirstAncestor = function(sel, types) {
  if(typeof types == 'string')
    types = [types];

  return this._getFirstAncestorF(sel,function(el) {
    if(el.nodeType == 1)
    {
      if(types == null)
        return true;
      if(types.contains(el.tagName.toLowerCase()))
        return true;
    }
    return false;
  });
};

// Called when the user clicks on "InsertImage" button.  If an image is already
// there, it will just modify it's properties.
HTMLArea.prototype._insertImageMT = function(image) {
    var editor = this;	// for nested functions
    var outparam = null;
    if (typeof image == "undefined") {
        image = this.getParentElement();
        if (image && !/^img$/i.test(image.tagName))
        image = null;
    }
    var stripState = this.config.stripBaseHref;
    this.config.stripBaseHref = true;
    outparam = image ? {
        f_base       : editor.config.baseHref,
        f_url        : MindTouch.extractName(editor.stripBaseURL(image.src)),
        name         : image.alt,
        ialign       : image.getAttribute('ialign'),
        size         : image.getAttribute('size_type'),
        captionText  : image.getAttribute('caption_text') ? image.getAttribute('caption_text') : '',
        resizeHeight : parseInt(image.style.height),
        resizeWidth  : parseInt(image.style.width)
    } : {
        f_base       : editor.config.baseHref,
        f_url        : ""
    };
    this.config.stripBaseHref = stripState;

    function doInsertImage(param) {
        if (!param) {	// user must have pressed Cancel
            return false;
        }
        var img = image;
        param.f_url = param.f_url.replace(/ /g, '_');
        if (!img) {
            var sel = editor._getSelection();
            var range = editor._createRange(sel);
            editor._doc.execCommand("insertimage", false, param.f_url);
            range = editor._createRange(sel);
            img = editor.findTagInRangeF(sel, range, function(el) {
                return /^img$/i.test(el.tagName) && !el.getAttribute('size_type');
            });
            if (!img)
                img = editor.getParentElement();
            while (img && !/^img$/i.test(img.tagName))
                img = img.parentNode;
            if (!(img && /^img$/i.test(img.tagName)))
                return false;
        } else {
            img.src = param.f_url;
        }
        img.setAttribute('ialign', param.ialign);
        img.setAttribute('size_type', param.size);
        MindTouch.setLink(editor, img, param.f_url);

        switch (param.size) {
        case 'direct':
            if (!MindTouch.isLinkExternal(param.f_url))
                img.src += "&size=full";
            img.style.height = param.imageHeight ? param.imageHeight + "px" : "auto";
            img.style.width = param.imageWidth ? param.imageWidth + "px" : "auto";
            break;
        case 'resize':
            if (!MindTouch.isLinkExternal(param.f_url) && (parseInt(param.resizeHeight) > 160 || parseInt(param.resizeWidth) > 160))
                img.src += "&size=full";
            img.style.height = param.resizeHeight;
            img.style.width = param.resizeWidth;
            break;
        case 'thumb':
        case 'caption':
            if (param.imageHeight && param.imageWidth) {
                if (param.imageWidth > param.imageHeight) {
                    if (param.imageWidth > 160) {
                        img.style.width = 160;
                        img.style.height = (param.imageHeight / param.imageWidth) * 160;
                    } else {
                        img.style.width = param.imageWidth;
                        img.style.height = param.imageHeight;
                    }
                }
                else {
                    if (param.imageHeight > 160) {
                        img.style.width = (param.imageWidth / param.imageHeight) * 160;
                        img.style.height = 160;
                    } else {
                        img.style.width = param.imageWidth;
                        img.style.height = param.imageHeight;
                    }
                }
            } else {
                img.style.width = "auto";
                img.style.height = "auto";
            }
            img.setAttribute('caption_text', param.captionText);
            break;
        }
    };

    this._popupDialog(700, 450,'/editor/popups/insert_image.php?href=' + outparam.f_url.utf8URL() 
        + '&cntxtID=' + editor.contextTopicID + '&cntxt=' + editor.contextTopic.utf8URL() + '&userName=' + _userName, doInsertImage, outparam);
};

HTMLArea.prototype.findTagInRangeF = function(sel, range, fn) {
   if (HTMLArea.is_ie) {
     var el = this.getParentElement(sel,range);
     if (fn(el))
       return el;
     return HTMLArea.findInChildren(el, fn);
   }
   var el = range.startContainer;
   var res = {found:null};
   HTMLArea.findTagInRangeRF(range, el, fn, res);
   if (!res.found && el.nodeType == 3) {
     if (el.nodeType == 3)
       el = el.parentNode;
     HTMLArea.findTagInRangeRF(range, el, fn, res);
   }
   return res.found;
};

HTMLArea.findInChildren = function(node, func) {
 var child = node.firstChild;
 while (child != null) {
   var next = child.nextSibling;
   if (func(child))
     return child;
   var ret = HTMLArea.findInChildren(child, func);
   if (ret)
     return ret;
   child = next;
 }
 return null;
};

HTMLArea.findTagInRangeRF = function(range, el, fn, res) {
   while (el) {
     var next = el.nextSibling;
     if (fn(el)) {
       res.found = el;
       return true;
     }
     var stop = HTMLArea.findTagInRangeRF(range, el.firstChild, fn, res);
     if (stop)
       return stop;
     if (el == range.endContainer)
       return true;
     el = next;
   }
   return false;
};

// MT: special handling for link creation
HTMLArea.prototype._createLinkMT = function(nopopup) {
  var editor = this;
  var outparam = null;

  nopopup = (typeof nopopup != "undefined" && nopopup == "no-popup");

  function doCreateLink(param) {
    editor.focusEditor();
    if (!param)
      return false;
    var a = link;
    var text = param.f_text.trim();
    var href = param.f_href.trim();
    if (text == "")
      text = href;
    if (!a) {
      if (text == "" || href == "")
        return false;
      var sel = editor._getSelection();
      var range = editor._createRange(sel);
      if (!MindTouch.isLinkExternal(href) && href != "")
        href = MindTouch.mksInternalPrefix + href;
      //KA - attempting to link an inserted image destroys the image
      if (HTMLArea.is_gecko) {
      	var ReplaceSel = (sel.focusNode.firstChild != null) ? !/^img$/i.test(sel.focusNode.firstChild.tagName) : true;
      } else {
      	var ReplaceSel = (sel.type == "Control") ? false : true;
      }
      if (editor.adjustSelection(sel,range).length == 0 && ReplaceSel) {
      	//If there is no text selection and link is created not for Control element (for example, image)
      	//If there is no text selection and link is created not for image
      	//KA - New links with no text selected
      	//If there is no selected fragment, we use page or file name as anchor.
      	//Find last '/' entry and truncate to it.
      	var lastSlash = text.lastIndexOf("/");
      	//If '/' is the last character, use all string with address.
      	if ((lastSlash + 1) < text.length) {
      		text = text.substring(lastSlash + 1);
      	}
        editor.insertHTML("<a href='" + MindTouch.hrefEncode(href) + "'>" + HTMLArea.htmlEncode(text) + "</a>");
      } else {
      	//If text or image is selected
        editor._doc.execCommand("createlink", false, MindTouch.hrefEncode(href));
      }
      range = editor._createRange(sel);
      a = editor.findTagInRangeF(sel, range, function(el) { return /^a$/i.test(el.tagName) && !el.title; });
      if (!a)
        a = editor.getParentElement();
      while (a && !/^a$/i.test(a.tagName))
        a = a.parentNode;
      if (!(a && /^a$/i.test(a.tagName)))
        return false;
      MindTouch.setLink(editor, a, href, text);
      MindTouch.normalizeLink(a, editor);
    }
    else {
      while (a && !/^a$/i.test(a.tagName))
        a = a.parentNode;
      if (!(a && /^a$/i.test(a.tagName)))
        return false;
      editor.selectNodeContents(a);
      if (href == "") {
        editor._doc.execCommand("unlink", false, null);
        editor.updateToolbar();
        return false;
      }
      else {
        if (nopopup) {
          var isE = MindTouch.isLinkExternal(href);
          var testHRef = href;
          if (!isE && testHRef.indexOf(MindTouch.mksInternalPrefix) != 0)
            testHRef = MindTouch.mksInternalPrefix + testHRef;
          if (a.href == MindTouch.hrefEncode(testHRef)) {
            if (isE)
              text = a.innerHTML == '#' ? a.href : text = '#';
            else
              href = MindTouch.mksInternalPrefix + text;
          }
        }
        MindTouch.setLink(editor, a, href, text);
        MindTouch.normalizeLink(a, editor);
      }
    }
    editor.selectNodeContents(a);
    editor.updateToolbar();
  };

  link = this.getParentElement();
  if (link) {
    while (link && !/^a$/i.test(link.tagName))
      link = link.parentNode;
    if (link && !/^a$/i.test(link.tagName))
      link = null;
  }
  if (!link) {
    var sel = editor.getSelectedText();
    sel = sel ? sel.trim() : '';
    outparam = {
      f_href         : !nopopup ? "./" + sel : sel,
      f_text         : sel,
      contextTopic   : editor.contextTopic,
      contextTopicID : editor.contextTopicID,
      userName       : _userName
    };
  } else {
    if (link.className == 'site')
      return;
    outparam = {
      f_href         : link.href,
      f_text         : HTMLArea.getInnerText(link),
      contextTopic   : editor.contextTopic,
      contextTopicID : editor.contextTopicID,
      userName       : _userName
    };
  }
  outparam.f_href = MindTouch.hrefDecode(outparam.f_href);
  if (outparam.f_href.indexOf(MindTouch.mksInternalPrefix) == 0)
    outparam.f_href = outparam.f_href.substr(MindTouch.mksInternalPrefix.length);
  if (!nopopup)
    this._popupDialog(600, 451, '/editor/popups/link.php?href=' + outparam.f_href.utf8URL()
        + '&cntxtID=' + editor.contextTopicID + '&cntxt=' + editor.contextTopic.utf8URL() + '&userName=' + _userName, doCreateLink, outparam);
  else
    doCreateLink(outparam);
};

HTMLArea.prototype.dropdownCommand = function(command, arg) {
	EditorMenu.hide();
	if (command == 'forecolor' || command == 'backcolor')
		this._onColorChange(command, arg);
	else if (command == 'fontsize')
		updateFontSizes(this, command, arg);
	else if (arg == '')
		this.execCommand(command);
	else
		this.execCommand(command, false, arg);
};

// htmlArea v3.0 - Copyright (c) 2003-2004 interactivetools.com, inc.
// This copyright notice MUST stay intact for use (see license.txt).
//
// Portions (c) dynarch.com, 2003-2004
//
// A free WYSIWYG editor replacement for <textarea> fields.
// For full source code and docs, visit http://www.interactivetools.com/
//
// Version 3.0 developed by Mihai Bazon.
//   http://dynarch.com/mishoo
//
// $Id: dialog.js 183 2005-05-20 06:11:44Z gogo $

// Though "Dialog" looks like an object, it isn't really an object.  Instead
// it's just namespace for protecting global symbols.

function Dialog(width, height, url, action, init, editor) {
// >MT: Cache the current selection before showing the popup
        if (HTMLArea.is_ie) {
                Dialog._editor = editor;
                Dialog._selection = editor._getSelection();
                Dialog._range = editor._createRange(Dialog._selection);
        }
// <MT
      
	if (typeof init == "undefined") {
		init = window;	// pass this window object by default
	}
	Dialog._geckoOpenModal(width, height, url, action, init);
};

Dialog._parentEvent = function(ev) {
	setTimeout( function() { if (Dialog._modal && !Dialog._modal.closed) { Dialog._modal.focus() } }, 50);
	if (Dialog._modal && !Dialog._modal.closed) {
		HTMLArea._stopEvent(ev);
	}
};

// >MT
// the calling editor
Dialog._editor = null;

// the previous selection
Dialog._selection = null;

// the previous range
Dialog._range = null;
// <MT

// should be a function, the return handler of the currently opened dialog.
Dialog._return = null;

// constant, the currently opened dialog
Dialog._modal = null;

// the dialog will read it's args from this variable
Dialog._arguments = null;

Dialog._geckoOpenModal = function(width, height, url, action, init) {
// MT>: use inline dialogs
      showPopWin (url, width, height);
//	var dlg = window.open(url, "hadialog",
//			      "toolbar=no,menubar=no,personalbar=no,width=10,height=10," +
// <MT
// >MT: use non-resizable diaglogs
//			      "scrollbars=no,resizable=no,modal=yes,dependable=yes");
// <MT
// MT>: use inline dialogs
//	Dialog._modal = dlg;
// <MT
	Dialog._arguments = init;

	// capture some window's events
	function capwin(w) {
		HTMLArea._addEvent(w, "click", Dialog._parentEvent);
		HTMLArea._addEvent(w, "mousedown", Dialog._parentEvent);
		HTMLArea._addEvent(w, "focus", Dialog._parentEvent);
	};
	// release the captured events
	function relwin(w) {
		HTMLArea._removeEvent(w, "click", Dialog._parentEvent);
		HTMLArea._removeEvent(w, "mousedown", Dialog._parentEvent);
		HTMLArea._removeEvent(w, "focus", Dialog._parentEvent);
	};
// >MT: use inline dialogs
//	capwin(window);
// <MT
	// capture other frames, note the exception trapping, this is because
  // we are not permitted to add events to frames outside of the current
  // window's domain.
// >MT: use inline dialogs
//	for (var i = 0; i < window.frames.length; i++) {try { capwin(window.frames[i]); } catch(e) { } };
// <MT
	// make up a function to be called when the Dialog ends.
	Dialog._return = function (val) {
		parent.hidePopWin (false);
// >MT: Reset the ie selection before acting
		if (val && action) {
                        if (HTMLArea.is_ie) {
                                Dialog._editor._selectRange(Dialog._range);
                        }
// <MT
			action(val);
		}
// >MT: use inline dialogs
//		relwin(window);
// <MT
		// capture other frames
// >MT: use inline dialogs
//		for (var i = 0; i < window.frames.length; i++) { try { relwin(window.frames[i]); } catch(e) { } };
// <MT
		Dialog._modal = null;
	};
// >MT: fix crash issue
  if (Dialog._modal) Dialog._modal.focus();
// <MT
};


HTMLArea.Dialog = function(editor, html, localizer)
{
  this.id    = { };
  this.r_id  = { }; // reverse lookup id
  this.editor   = editor;
  this.document = document;

  this.rootElem = document.createElement('div');
  this.rootElem.className = 'dialog';
  this.rootElem.style.position = 'absolute';
  this.rootElem.style.display  = 'none';
  this.editor._framework.ed_cell.insertBefore(this.rootElem, this.editor._framework.ed_cell.firstChild);
  this.rootElem.style.width  = this.width  =  this.editor._framework.ed_cell.offsetWidth + 'px';
  this.rootElem.style.height = this.height =  this.editor._framework.ed_cell.offsetHeight + 'px';

  var dialog = this;
  if(typeof localizer == 'function')
  {
    this._lc = localizer;
  }
  else if(localizer)
  {
    this._lc = function(string)
    {
      return HTMLArea._lc(string,localizer);
    };
  }
  else
  {
    this._lc = function(string)
    {
      return string;
    };
  }

  html = html.replace(/\[([a-z0-9_]+)\]/ig,
                      function(fullString, id)
                      {
                        if(typeof dialog.id[id] == 'undefined')
                        {
                          dialog.id[id] = HTMLArea.uniq('Dialog');
                          dialog.r_id[dialog.id[id]] = id;
                        }
                        return dialog.id[id];
                      }
             ).replace(/<l10n>(.*?)<\/l10n>/ig,
                       function(fullString,translate)
                       {
                         return dialog._lc(translate) ;
                       }
             ).replace(/="_\((.*?)\)"/g,
                       function(fullString, translate)
                       {
                         return '="' + dialog._lc(translate) + '"';
                       }
             );

  this.rootElem.innerHTML = html;




  this.editor.notifyOn
   ('resize',
      function(e, args)
      {
        dialog.rootElem.style.width  = dialog.width  =  dialog.editor._framework.ed_cell.offsetWidth + 'px';
        dialog.rootElem.style.height = dialog.height =  dialog.editor._framework.ed_cell.offsetHeight + 'px';
        dialog.onresize();
      }
    );
};

HTMLArea.Dialog.prototype.onresize = function()
{
  return true;
};

HTMLArea.Dialog.prototype.show = function(values)
{
  // We need to preserve the selection for IE
  if(HTMLArea.is_ie)
  {
    this._lastRange = this.editor._createRange(this.editor._getSelection());
  }

  if(typeof values != 'undefined')
  {
    this.setValues(values);
  }
  this._restoreTo = [this.editor._textArea.style.display, this.editor._iframe.style.visibility, this.editor.hidePanels()];

  this.editor._textArea.style.display = 'none';
  this.editor._iframe.style.visibility   = 'hidden';
  this.rootElem.style.display   = '';
};

HTMLArea.Dialog.prototype.hide = function()
{
  this.rootElem.style.display         = 'none';
  this.editor._textArea.style.display = this._restoreTo[0];
  this.editor._iframe.style.visibility   = this._restoreTo[1];
  this.editor.showPanels(this._restoreTo[2]);

  // Restore the selection
  if(HTMLArea.is_ie)
  {
    this._lastRange.select();
  }
  this.editor.updateToolbar();
  return this.getValues();
};

HTMLArea.Dialog.prototype.toggle = function()
{
  if(this.rootElem.style.display == 'none')
  {
    this.show();
  }
  else
  {
    this.hide();
  }
};

HTMLArea.Dialog.prototype.setValues = function(values)
{
  for(var i in values)
  {
    var elems = this.getElementsByName(i);
    if(!elems) continue;
    for(var x = 0; x < elems.length; x++)
    {
      var e = elems[x];
      switch(e.tagName.toLowerCase())
      {
        case 'select'  :
        {
          for(var j = 0; j < e.options.length; j++)
          {
            if(typeof values[i] == 'object')
            {
              for(var k = 0; k < values[i].length; k++)
              {
                if(values[i][k] == e.options[j].value)
                {
                  e.options[j].selected = true;
                }
              }
            }
            else if(values[i] == e.options[j].value)
            {
              e.options[j].selected = true;
            }
          }
          break;
        }


        case 'textarea':
        case 'input'   :
        {
          switch(e.getAttribute('type'))
          {
            case 'radio'   :
            {
              if(e.value == values[i])
              {
                e.checked = true;
              }
              break;
            }

            case 'checkbox':
            {
              if(typeof values[i] == 'object')
              {
                for(var j in values[i])
                {
                  if(values[i][j] == e.value)
                  {
                    e.checked = true;
                  }
                }
              }
              else
              {
                if(values[i] == e.value)
                {
                  e.checked = true;
                }
              }
              break;
            }

            default    :
            {
              e.value = values[i];
            }
          }
          break;
        }

        default        :
        break;
      }
    }
  }
};

HTMLArea.Dialog.prototype.getValues = function()
{
  var values = [ ];
  var inputs = HTMLArea.collectionToArray(this.rootElem.getElementsByTagName('input'))
              .append(HTMLArea.collectionToArray(this.rootElem.getElementsByTagName('textarea')))
              .append(HTMLArea.collectionToArray(this.rootElem.getElementsByTagName('select')));

  for(var x = 0; x < inputs.length; x++)
  {
    var i = inputs[x];
    if(!(i.name && this.r_id[i.name])) continue;

    if(typeof values[this.r_id[i.name]] == 'undefined')
    {
      values[this.r_id[i.name]] = null;
    }
    var v = values[this.r_id[i.name]];

    switch(i.tagName.toLowerCase())
    {
      case 'select':
      {
        if(i.multiple)
        {
          if(!v.push)
          {
            if(v != null)
            {
              v = [v];
            }
            else
            {
              v = new Array();
            }
          }
          for(var j = 0; j < i.options.length; j++)
          {
            if(i.options[j].selected)
            {
              v.push(i.options[j].value);
            }
          }
        }
        else
        {
          if(i.selectedIndex >= 0)
          {
            v = i.options[i.selectedIndex];
          }
        }
        break;
      }

      case 'textarea':
      case 'input'   :
      default        :
      {
        switch(i.type.toLowerCase())
        {
          case  'radio':
          {
            if(i.checked)
            {
              v = i.value;
              break;
            }
          }

          case 'checkbox':
          {
            if(v == null)
            {
              if(this.getElementsByName(this.r_id[i.name]).length > 1)
              {
                v = new Array();
              }
            }

            if(i.checked)
            {
              if(v != null && typeof v == 'object' && v.push)
              {
                v.push(i.value);
              }
              else
              {
                v = i.value;
              }
            }
            break;
          }

          default   :
          {
            v = i.value;
            break;
          }
        }
      }

    }

    values[this.r_id[i.name]] = v;
  }
  return values;
};

HTMLArea.Dialog.prototype.getElementById = function(id)
{
  return this.document.getElementById(this.id[id] ? this.id[id] : id);
};

HTMLArea.Dialog.prototype.getElementsByName = function(name)
{
  return this.document.getElementsByName(this.id[name] ? this.id[name] : name);
};

/** This file is derived from PopupDiv, developed by Mihai Bazon for
 * SamWare.net.  Modifications were needed to make it usable in HTMLArea.
 * HTMLArea is a free WYSIWYG online HTML editor from InteractiveTools.com.
 *
 * This file does not function standalone.  It is dependent of global functions
 * defined in HTMLArea-3.0 (htmlarea.js).
 *
 * Please see file htmlarea.js for further details.
 **/

var is_ie = ( (navigator.userAgent.toLowerCase().indexOf("msie") != -1) &&
	      (navigator.userAgent.toLowerCase().indexOf("opera") == -1) );
var is_compat = (document.compatMode == "BackCompat");

function PopupDiv(editor, titleText, handler, initFunction) {
	var self = this;

	this.editor = editor;
	this.doc = editor._mdoc;
	this.handler = handler;

	var el = this.doc.createElement("div");
	el.className = "content";

	var popup = this.doc.createElement("div");
	popup.className = "dialog popupdiv";
	this.element = popup;
	var s = popup.style;
	s.position = "absolute";
	s.left = "0px";
	s.top = "0px";

	var title = this.doc.createElement("div");
	title.className = "title";
	this.title = title;
	popup.appendChild(title);

	HTMLArea._addEvent(title, "mousedown", function(ev) {
		self._dragStart(is_ie ? window.event : ev);
	});

	var button = this.doc.createElement("div");
	button.className = "button";
	title.appendChild(button);
	button.innerHTML = "&#x00d7;";
	title.appendChild(this.doc.createTextNode(titleText));
	this.titleText = titleText;

	button.onmouseover = function() {
		this.className += " button-hilite";
	};
	button.onmouseout = function() {
		this.className = this.className.replace(/\s*button-hilite\s*/g, " ");
	};
	button.onclick = function() {
		this.className = this.className.replace(/\s*button-hilite\s*/g, " ");
		self.close();
	};

	popup.appendChild(el);
	this.content = el;

	this.doc.body.appendChild(popup);

	this.dragging = false;
	this.onShow = null;
	this.onClose = null;
	this.modal = false;

	initFunction(this);
};

PopupDiv.currentPopup = null;

PopupDiv.prototype.showAtElement = function(el, mode) {
	this.defaultSize();
	var pos, ew, eh;
	var popup = this.element;
	popup.style.display = "block";
	var w = popup.offsetWidth;
	var h = popup.offsetHeight;
	popup.style.display = "none";
	if (el != window) {
		pos = PopupDiv.getAbsolutePos(el);
		ew = el.offsetWidth;
		eh = el.offsetHeight;
	} else {
		pos = {x:0, y:0};
		var size = PopupDiv.getWindowSize();
		ew = size.x;
		eh = size.y;
	}
	var FX = false, FY = false;
	if (mode.indexOf("l") != -1) {
		pos.x -= w;
		FX = true;
	}
	if (mode.indexOf("r") != -1) {
		pos.x += ew;
		FX = true;
	}
	if (mode.indexOf("t") != -1) {
		pos.y -= h;
		FY = true;
	}
	if (mode.indexOf("b") != -1) {
		pos.y += eh;
		FY = true;
	}
	if (mode.indexOf("c") != -1) {
		FX || (pos.x += Math.round((ew - w) / 2));
		FY || (pos.y += Math.round((eh - h) / 2));
	}
	this.showAt(pos.x, pos.y);
};

PopupDiv.prototype.defaultSize = function() {
	var s = this.element.style;
	var cs = this.element.currentStyle;
	var addX = (is_ie && is_compat) ? (parseInt(cs.borderLeftWidth) +
					   parseInt(cs.borderRightWidth) +
					   parseInt(cs.paddingLeft) +
					   parseInt(cs.paddingRight)) : 0;
	var addY = (is_ie && is_compat) ? (parseInt(cs.borderTopWidth) +
					   parseInt(cs.borderBottomWidth) +
					   parseInt(cs.paddingTop) +
					   parseInt(cs.paddingBottom)) : 0;
	// >MT: fix
	if (String(addX) == "NaN") addX = 0;
	if (String(addY) == "NaN") addY = 0;
	// <MT
	s.display = "block";
	s.width = (this.content.offsetWidth + addX) + "px";
	s.height = (this.content.offsetHeight + this.title.offsetHeight) + "px";
	s.display = "none";
};

PopupDiv.prototype.showAt = function(x, y) {
	this.defaultSize();
	var s = this.element.style;
	s.display = "block";
	s.left = x + "px";
	s.top = y + "px";
	this.hideShowCovered();

	PopupDiv.currentPopup = this;
	HTMLArea._addEvents(this.doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
	HTMLArea._addEvents(this.editor._doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
	if (is_ie && this.modal) {
		this.doc.body.setCapture(false);
		// >MT: fix
		var self = this;
		// <MT
		this.doc.body.onlosecapture = function() {
			// >MT: fix
			(PopupDiv.currentPopup) && (self.doc.body.setCapture(false));
			// <MT
		};
	}
	window.event && HTMLArea._stopEvent(window.event);

	if (typeof this.onShow == "function") {
		this.onShow();
	} else if (typeof this.onShow == "string") {
		eval(this.onShow);
	}

	var field = this.element.getElementsByTagName("input")[0];
	if (!field) {
		field = this.element.getElementsByTagName("select")[0];
	}
	if (!field) {
		field = this.element.getElementsByTagName("textarea")[0];
	}
	if (field) {
		field.focus();
	}
};

PopupDiv.prototype.close = function() {
	this.element.style.display = "none";
	PopupDiv.currentPopup = null;
	this.hideShowCovered();
	HTMLArea._removeEvents(this.doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
	HTMLArea._removeEvents(this.editor._doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
	is_ie && this.modal && this.doc.body.releaseCapture();
	if (typeof this.onClose == "function") {
		this.onClose();
	} else if (typeof this.onClose == "string") {
		eval(this.onClose);
	}
	this.element.parentNode.removeChild(this.element);
};

PopupDiv.prototype.getForm = function() {
	var forms = this.content.getElementsByTagName("form");
	return (forms.length > 0) ? forms[0] : null;
};

PopupDiv.prototype.callHandler = function() {
	var tags = ["input", "textarea", "select"];
	var params = new Object();
	for (var ti = tags.length; --ti >= 0;) {
		var tag = tags[ti];
		var els = this.content.getElementsByTagName(tag);
		for (var j = 0; j < els.length; ++j) {
			var el = els[j];
			//Karen Ananiev
			if (el.type == "checkbox") {
				//If field type is 'checkbox',  then,
				//instead of 'value', the 'checked' value should be selected as parameter
				params[el.name] = el.checked;
			} else {
				params[el.name] = el.value;
			}
		}
	}
	this.handler(this, params);
	return false;
};

PopupDiv.getAbsolutePos = function(el) {
	var r = { x: el.offsetLeft, y: el.offsetTop };
	if (el.offsetParent) {
		var tmp = PopupDiv.getAbsolutePos(el.offsetParent);
		r.x += tmp.x;
		r.y += tmp.y;
	}
	return r;
};

PopupDiv.getWindowSize = function() {
	if (window.innerHeight) {
		return { y: window.innerHeight, x: window.innerWidth };
	}
	if (this.doc.body.clientHeight) {
		return { y: this.doc.body.clientHeight, x: this.doc.body.clientWidth };
	}
	return { y: this.doc.documentElement.clientHeight, x: this.doc.documentElement.clientWidth };
};

PopupDiv.prototype.hideShowCovered = function () {
	var self = this;
	function isContained(el) {
		while (el) {
			if (el == self.element) {
				return true;
			}
			el = el.parentNode;
		}
		return false;
	};
	var tags = new Array("applet", "select");
	var el = this.element;

	var p = PopupDiv.getAbsolutePos(el);
	var EX1 = p.x;
	var EX2 = el.offsetWidth + EX1;
	var EY1 = p.y;
	var EY2 = el.offsetHeight + EY1;

	if (el.style.display == "none") {
		EX1 = EX2 = EY1 = EY2 = 0;
	}

	for (var k = tags.length; k > 0; ) {
		var ar = this.doc.getElementsByTagName(tags[--k]);
		var cc = null;

		for (var i = ar.length; i > 0;) {
			cc = ar[--i];
			if (isContained(cc)) {
				cc.style.visibility = "visible";
				continue;
			}

			p = PopupDiv.getAbsolutePos(cc);
			var CX1 = p.x;
			var CX2 = cc.offsetWidth + CX1;
			var CY1 = p.y;
			var CY2 = cc.offsetHeight + CY1;

			if ((CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
				cc.style.visibility = "visible";
			} else {
				cc.style.visibility = "hidden";
			}
		}
	}
};

PopupDiv.prototype._dragStart = function (ev) {
	if (this.dragging) {
		return false;
	}
	this.dragging = true;
	PopupDiv.currentPopup = this;
	var posX = ev.clientX;
	var posY = ev.clientY;
	if (is_ie) {
		posY += this.doc.body.scrollTop;
		posX += this.doc.body.scrollLeft;
	} else {
		posY += window.scrollY;
		posX += window.scrollX;
	}
	var st = this.element.style;
	this.xOffs = posX - parseInt(st.left);
	this.yOffs = posY - parseInt(st.top);
	HTMLArea._addEvent(this.doc, "mousemove", PopupDiv.dragIt);
	HTMLArea._addEvent(this.doc, "mouseover", HTMLArea._stopEvent);
	HTMLArea._addEvent(this.doc, "mouseup", PopupDiv.dragEnd);
	HTMLArea._stopEvent(ev);
};

PopupDiv.dragIt = function (ev) {
	var popup = PopupDiv.currentPopup;
	if (!(popup && popup.dragging)) {
		return false;
	}
	is_ie && (ev = window.event);
	var posX = ev.clientX;
	var posY = ev.clientY;
	if (is_ie) {
		// >MT: fix
		posY += popup.doc.body.scrollTop;
		posX += popup.doc.body.scrollLeft;
		// <MT
	} else {
		posY += window.scrollY;
		posX += window.scrollX;
	}
	popup.hideShowCovered();
	var st = popup.element.style;
	st.left = (posX - popup.xOffs) + "px";
	st.top = (posY - popup.yOffs) + "px";
	HTMLArea._stopEvent(ev);
};

PopupDiv.dragEnd = function () {
	var popup = PopupDiv.currentPopup;
	if (!popup) {
		return false;
	}
	popup.dragging = false;
	HTMLArea._removeEvent(popup.doc, "mouseup", PopupDiv.dragEnd);
	HTMLArea._removeEvent(popup.doc, "mouseover", HTMLArea._stopEvent);
	HTMLArea._removeEvent(popup.doc, "mousemove", PopupDiv.dragIt);
	popup.hideShowCovered();
};

PopupDiv.checkPopup = function (ev) {
	is_ie && (ev = window.event);
	// >MT: fix
	if (!ev) return;
	// <MT: fix
	var el = is_ie ? ev.srcElement : ev.target;
	var cp = PopupDiv.currentPopup;
	for (; (el != null) && (el != cp.element); el = el.parentNode);
	if (el == null) {
		cp.modal || ev.type == "mouseover" || cp.close();
		HTMLArea._stopEvent(ev);
	}
};

PopupDiv.prototype.addButtons = function() {
	var self = this;
	var div = this.doc.createElement("div");
	this.content.appendChild(div);
	div.className = "buttons";
	for (var i = 0; i < arguments.length; ++i) {
		var btn = arguments[i];
		var button = this.doc.createElement("button");
		div.appendChild(button);
		// >MT: fix
		button.innerHTML = HTMLArea._lc(btn, 'HTMLArea');
		switch (btn.toLowerCase()) {
		// <MT
		    case "ok":
			button.onclick = function() {
				self.callHandler();
				self.close();
			};
			break;
		    case "cancel":
			button.onclick = function() {
				self.close();
			};
			break;
		}
	}
};

dojo.require("dojo.lang.declare");

var browserVer;
var chat;

dojo.declare("DreamChatHost", null, {
    globalChatUri: "",
    username: "",
    chatdialog: null,
    chatarea: null,
    chatinput: null,
    chatusers: null,
    MAX_STRING_LENGTH: 250,
    lastUpdate: 0,
    firstResult: true,
    firstMessage: true,
    userlist: null,
    lastuser:"",

    initializer: function(chatServiceUri, channelName, username) {
        this.globalChatUri = chatServiceUri + "/global/";
        this.username = username;
        this.chatdialog = dojo.byId("chatdialog");
        this.chatarea = dojo.byId("chatarea");
        this.chatinput = dojo.byId("chatinput");
        this.chatusers = dojo.byId("chatusers");
        this.userlist = new Array();
        dojo.event.connect(this.chatinput, "keyup", this, "onKeyUp");
        dojo.event.connect(this.chatinput, "keypress", this, "onKeyPress");
        /* TODO: fix by converting to dojo
        new Draggable("chatdialog", { handle: "chattitle" });
        */
        this.sendEnter();
        this.readMessages();
    },

    onWindowUnload: function(event) {
        this.sendExit();
    },

    readMessages: function() {
        dojo.io.bind({
            url : this.globalChatUri + "?output=json&callback=chat.onNewMessageReceived&wait=10" + (this.lastUpdate ? "&after=" + this.lastUpdate : ""),
            method: 'GET',
            error: dojo.lang.hitch(this, "onReadMessageError"),
            timeout: dojo.lang.hitch(this, "onReadMessageError"),
            mimetype: "text/javascript"
        });
    },

    onReadMessageError: function() {
        setTimeout(dojo.lang.hitch(this, "readMessages"), 2000);
    },

    sendEnter: function() {
        body = "<msg><user>" + DreamUtil.encodeSpecialChars(this.username) + "</user><action>enter</action></msg>";
        dojo.io.bind({
            url : this.globalChatUri + "?ttl=" + 5*60,
            contentType: 'application/xml',
            method: 'POST',
            postContent: body,
            error: dojo.lang.hitch(this, "showException")
        });
    },

    sendExit: function() {
        body = "<msg><user>" + DreamUtil.encodeSpecialChars(this.username) + "</user><action>exit</action></msg>";
        dojo.io.bind({
            url : this.globalChatUri + "?ttl=" + 5*60,
            contentType: 'application/xml',
            method: 'POST',
            postContent: body,
            error: dojo.lang.hitch(this, "showException")
        });
    },

    sendMessage: function(msg) {
        body = "<msg><user>" + DreamUtil.encodeSpecialChars(this.username) + "</user><text>" + DreamUtil.encodeSpecialChars(msg) + "</text></msg>";
        dojo.io.bind({
            url : this.globalChatUri + "?ttl=" + 5*60,
            contentType: 'application/xml',
            method: 'POST',
            postContent: body,
            error: dojo.lang.hitch(this, "showException")
        });
    },

    showException: function(transport, ex) {
        alert(ex.message);
    },

    onNewMessageReceived: function(response) {
        if(response) {
            var prevUpdate = this.lastUpdate;
            this.lastUpdate = Math.max(response["@maxeventid"] || this.lastUpdate, this.lastUpdate);
            if(DreamUtil.isArray(response.msg)) {
                var _this = this;
                dojo.lang.forEach(response.msg, function(item) {
                    if(item["@eventid"] > prevUpdate) {
                        _this.processMessage(item);
                    }
                });
            } else if(response.msg) {
                if(response.msg["@eventid"] > prevUpdate) {
                    this.processMessage(response.msg);
                }
            }
        }
        this.firstResult = false;
        setTimeout(dojo.lang.hitch(this, "readMessages"), 2000);
    },

    processMessage: function(msg) {
        var user =  DreamUtil.encodeSpecialChars(msg.user);

        // check if the scrollbar was at the bottom
        var scroll = Math.abs(this.chatarea.scrollTop - (this.chatarea.scrollHeight - this.chatarea.offsetHeight));

        // check what kind of message we received
        if(msg.text) {

            // check if this is the first message ever; if yes, clear contents
            if(this.firstMessage) {
                this.firstMessage = false;
                this.chatarea.innerHTML = "";
            } else {
                this.chatarea.innerHTML += "<br/>";
            }

            var text = msg.text;
            var text2;

            // check text for special sequences (note: we only make one replace per line to avoid odd interactions)

            // case 1: a uri, e.g. http://www.foo.com/bar
            text2 = text.replace(new RegExp("([a-zA-Z]{2,6}\\://[^ \"]*)"), "<a href=\"$1\" target=\"blank\">$1</a>");
            if(text == text2) {

                // case 2: email address, e.g. foo.bar@foobar.com
                text2 = text.replace(new RegExp("([-\\w]+(\\.[-\\w]+)*@([-\\w]+\\.)+\\w{2,6})"), "<a href=\"mailto:$1\">$1</a>");
            }
            text = text2;

            // update chat contents
            if(this.lastuser != user) {
                this.lastuser = user;
                this.chatarea.innerHTML += "<span class='chatusername'>" + user + ":</span><br/>";
            }
            this.chatarea.innerHTML += "<span class='chatmsg'>" + text  + "</span>";

            // check if our name was mentioned
            if(!this.firstResult && msg.text.toLowerCase().indexOf(this.username.toLowerCase()) >= 0) {
                /* TODO: port from Prototype to dojo
                if(dojo.style.isDisplayed(this.chatdialog)) {
                    new Effect.Highlight(this.chatarea);
                } else {
                    new Effect.Pulsate(dojo.byId("chatbutton"));
                }
                */
            }
        } else if(msg.action && msg.action=='enter') {

            // check if this is the first message ever; if yes, clear contents
            if(this.firstMessage) {
                this.firstMessage = false;
                this.chatarea.innerHTML = "";
            }

            this.addUser(user);
        } else if(msg.action &&  msg.action=='exit') {

            // check if this is the first message ever; if yes, clear contents
            if(this.firstMessage) {
                this.firstMessage = false;
                this.chatarea.innerHTML = "";
            }

            this.removeUser(user);
        }

        // update scrollbar to follow content
        /* TODO: port from Prototype to dojo
        if((scroll < 25) && dojo.style.isDisplayed(this.chatdialog)) {
            this.chatarea.scrollTop = this.chatarea.scrollHeight;
        }
        */
    },

    onKeyUp: function(event) {
        if(this.chatinput.value.length > this.MAX_STRING_LENGTH) {
            this.chatinput.value = this.chatinput.value.substring(0, this.MAX_STRING_LENGTH);
        }
    },

    onKeyPress: function(event) {
        if(event.keyCode == Event.KEY_RETURN) {
            var text = this.chatinput.value;
            this.chatinput.value = "";
            Event.stop(event);
            if(text.length != 0) {
                text = this.restrictTextLength(text);
                text = DreamUtil.encodeSpecialChars(text);
                this.sendMessage(text, false); 
                this.chatinput.focus();
            }
            return false;
        } else{
            if(this.chatinput.value.length > this.MAX_STRING_LENGTH) {
                this.chatinput.value = this.chatinput.value.substring(0, this.MAX_STRING_LENGTH);
            }
            return true;
        }
        
    },

    restrictTextLength: function(text) {
        if(text.length > this.MAX_STRING_LENGTH){
            text = text.substring(0, this.MAX_STRING_LENGTH) + "...";
        }
        return text
    },

    toggle: function() {
        if(dojo.style.isDisplayed(this.chatdialog)) {
            dojo.lfx.html.fadeOut(this.chatdialog, 400).play();
        } else {
            dojo.style.setOpacity(this.chatdialog, 1);
            this.chatdialog.show();
            this.chatinput.focus();
            setTimeout(dojo.lang.hitch(this, "adjustScroller"), 0.1);
        }
    },

    adjustScroller: function() {
        this.chatarea.scrollTop = this.chatarea.scrollHeight;
    },

    addUser: function(name) {
        var i;
        for(i = 0; i < this.userlist.length; ++i) {
            if(this.userlist[i] == name) {
                return;
            }
        }
        this.userlist.push(name);
        this.updateUserlist();
    },

    removeUser: function(name) {
        var i;
        for(i = 0; i < this.userlist.length; ++i) {
            if(this.userlist[i] == name) {
                this.userlist.splice(i, 1);
                break;
            }
        }
        this.updateUserlist();
    },

    updateUserlist: function() {
        var result = "";
        var i;
        this.userlist.sort();
        for(i = 0; i < this.userlist.length; ++i){
            result = result + "<li>" + DreamUtil.encodeSpecialChars(this.userlist[i]) + "</li>";
        }
        this.chatusers.innerHTML = "<ul>" + result + "</ul>";
    }
});

var DreamUtil = {
    encodeSpecialChars: function(s) {
        if((s != null) && (s.length > 0)) {
            s = s.replace(new RegExp("&", "g"), "&amp;");
            s = s.replace(new RegExp("<", "g"), "&lt;");
            s = s.replace(new RegExp(">", "g"), "&gt;");
            s = s.replace(new RegExp("\\[", "g"), "&#91;");
            s = s.replace(new RegExp("\\]", "g"), "&#93;");
            return s
        }
    },

    decodeSpecialChars: function(s) {
        if((s != null) && (s.length > 0)) {
            s = s.replace(new RegExp("&lt;", "g"), "<");
            s = s.replace(new RegExp("&gt;", "g"), ">");
            s = s.replace(new RegExp("&#91;", "g"), "[");
            s = s.replace(new RegExp("&#93;", "g"), "]");
            s = s.replace(new RegExp("&amp;", "g"), "&");
            return s
        }
    },

    isAlien: function(a) {
       return DreamUtil.isObject(a) && typeof a.constructor != 'function';
    },

    isArray: function(a) {
        return DreamUtil.isObject(a) && a.constructor == Array;
    },

    isBoolean: function(a) {
        return typeof a == 'boolean';
    },

    isEmpty: function(o) {
        var i, v;
        if (isObject(o)) {
            for (i in o) {
                v = o[i];
                if (DreamUtil.isUndefined(v) && DreamUtil.isFunction(v)) {
                    return false;
                }
            }
        }
        return true;
    },

    isFunction: function(a) {
        return typeof a == 'function';
    },

    isNull: function(a) {
        return typeof a == 'object' && !a;
    },

    isNumber: function(a) {
        return typeof a == 'number' && DreamUtil.isFinite(a);
    },

    isObject: function(a) {
        return (a && typeof a == 'object') || DreamUtil.isFunction(a);
    },

    isString: function(a) {
        return typeof a == 'string';
    },

    isUndefined: function(a) {
        return typeof a == 'undefined';
    },
    
    getRandomNumber: function(max) {
        var result;
        do {
            result = Math.floor(Math.random()*max);
        } while(result == max);
        return result;
    },

    getNormalizedDomainName: function(href) {
        var matches = href.match(new RegExp("([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z0-9]{2,6}", "i"));
        var domain = "localhost";
        if(matches == null){
            return domain;
        } else {
            domain = matches[0];
        }
        return domain
    },

    getUriSchema: function(href) {
        if(href.indexOf("https") == 0){
            return "https";
        } else{
            return "http";
        }
    },

    getRootUri: function() {
        var href = window.document.location.href;
        var domain = DreamUtil.getNormalizedDomainName(href);
        var path = href.substring(href.indexOf(domain) + domain.length, href.length);
        var port = "";
        if(path.indexOf(":") == 0){
            var slash = path.indexOf("/");
            if(slash == -1){
                path = path + "/";
                slash = path.length - 1
            }
            port = ":" + path.substring(1, slash)
        }
        return DreamUtil.getUriSchema(href) + "://" + domain + port + "/"
    }
};

function BrowserVersion(){
    BrowserVersion.minInternetExplorerVersion = 6.0;
    BrowserVersion.minFirefoxVersion = 1.5;
    BrowserVersion.minCaminoVersion = "1.0";
    BrowserVersion.minFlockVersion = "0.5";

    this.isIE = false;
    this.isFF = false;
    this.isNS = true;
    this.isCamino = false;
    this.isSafari = false;
    this.isFlock = false;
    this.version = null;
    this.isSupported = false;

    var browserApp = navigator.userAgent;
    var s = "MSIE";
    var i;
    if((i = browserApp.indexOf(s)) >= 0){
        this.isIE = true;
        this.isNS = false;
        this.version = parseFloat(browserApp.substr(i+s.length));
        if(this.version >= BrowserVersion.minInternetExplorerVersion){
            this.isSupported = true
        }
        return
    }
    s = "Firefox/";
    if((i = browserApp.indexOf(s)) >= 0){
        this.isFF = true;
        this.version = parseFloat(browserApp.substr(i+s.length));
        if(this.version >= BrowserVersion.minFirefoxVersion){
            this.isSupported = true
        }
        return
    }
    s = "Safari/";
    if((i = browserApp.indexOf(s)) >= 0){
        this.isSafari = true;
        this.isSupported = true;
        return
    }
    s = "Camino/";
    if((i = browserApp.indexOf(s)) >= 0){
        this.isCamino = true;
        this.version = browserApp.substr(i+s.length);
        if(this.version >= BrowserVersion.minCaminoVersion){
            this.isSupported = true
        }
        return
    }
    s = "Flock/";
    if((i = browserApp.indexOf(s)) >= 0){
        this.isFlock = true;
        this.version = browserApp.substr(i+s.length);
        if(this.version >= BrowserVersion.minFlockVersion){
            this.isSupported = true
        }
        return
    }
    s = "Netscape6/";
    if((i = browserApp.indexOf(s)) >= 0){
        this.isNS = true;
        this.version = parseFloat(browserApp.substr(i+s.length));
        return
    }
    s = "Gecko";
    if((i = browserApp.indexOf(s)) >= 0){
        this.isNS = true;
        this.version = 6.1
    }
};

function initChatApp(username, channelname) {
    browserVer = new BrowserVersion();

    if(!channelname) {
        channelname = DreamUtil.getNormalizedDomainName(window.document.location.href);
    }
    chat = new DreamChatHost(DreamUtil.getRootUri() + "dream/chat", channelname, username);
};

function deinitChatApp() {
    if (typeof chat != 'undefined')
        chat.onWindowUnload();
};

/* MindTouch Dream
 * Copyright (C) 2006 MindTouch, Inc 
 * www.mindtouch.com (http://www.mindtouch.com/) <oss@mindtouch.com (mailto:oss@mindtouch.com)>
 *
 * 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 3 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.
 * http://www.gnu.org/copyleft/gpl.html 
 */

dojo.require("dojo.lang.declare");

dojo.declare("WidgetManager", null, {
    _version : {
        'Release'   : 'Trunk',
        'Author'    : 'Urs C Muff',
        'Copyright' : '2006, MindTouch, Inc.'
    },

    _nextID : 1,
    Mode : 'view',
    Editor : null,

    initializer : function () {
        this._widgetsById = {};
    },

    toXml : function (node) {
        if (!node) {return null;}
        if (node.nodeType == 3) {return node.data;}
        var ret = "<" + node.className;
        var attrs = node.attributes;
        for (i = 0; i < attrs.length; ++i) {
            var a = attrs.item(i);
            if (!a.specified) continue;
            var name = a.nodeName.toLowerCase();
            if (!/xml:.+/.test(name)) continue;
            var value = a.nodeValue;
            ret += " " + name.substring("xml:".length) + '="' + value + '"';
        }
        ret += ">";
        var child = node.firstChild;
        while (child) {
            ret += this.toXml(child);
            child = child.nextSibling;
        }
        ret += "</" + node.className + ">";
        return ret;
    },
    _toXmlFromJson : function (name, value) {
        if (typeof value != 'string' && typeof value.length != 'undefined' && value.length > 0 && typeof value[0] != 'undefined') {
            var ret = "";
            for (var i = 0; i < value.length; ++i) {
                var item = value[i];
                ret += this._toXmlFromJson(name, item);
            }
            return ret;
        }
        var ret = "<" + name;
        if (typeof value['#text'] != 'undefined') {
            for (var attrName in value) {
                if (!/^@.+$/.test(attrName)) continue;
                var attrValue = value[attrName];
                ret += " " + attrName.substring(1) + "='" + attrValue + "'";
            }
            ret += ">" + value['#text'];
        } else {
            ret += ">";
            if (typeof value == 'string') {
                ret += value;
            } else {
                ret += this.toXmlFromJson(value);
            }
        }
        ret += "</" + name + ">";
        return ret;
    },
    toXmlFromJson : function (data) {
        var ret = "";
        for (var elementName in data) {
            ret += this._toXmlFromJson(elementName, data[elementName]);
        }
        return ret;
    },
    _toHtmlFromJson : function (name, value) {
        if (typeof value != 'string' && typeof value.length != 'undefined' && value.length > 0 && typeof value[0] != 'undefined') {
            var ret = "";
            for (var i = 0; i < value.length; ++i) {
                var item = value[i];
                ret += this._toHtmlFromJson(name, item);
            }
            return ret;
        }
        var ret = "<span class='" + name + "'";
        if (typeof value['#text'] != 'undefined') {
            for (var attrName in value) {
                if (!/^@.+$/.test(attrName)) continue;
                var attrValue = value[attrName];
                ret += " xml:" + attrName.substring(1) + "='" + attrValue + "'";
            }
            ret += ">" + value['#text'];
        } else {
            ret += ">";
            if (typeof value == 'string') {
                ret += value;
            } else {
                ret += this.toHtmlFromJson(value);
            }
        }
        ret += "</span>";
        return ret;
    },
    toHtmlFromJson : function (data) {
        var ret = "";
        for (var elementName in data) {
            var elementValue = data[elementName];
            ret += this._toHtmlFromJson(elementName, elementValue);
        }
        return ret;
    },
    createHtml : function (widgetType, callback) {
        var url = this._getRequestUri("/widget/create/" + widgetType);
        dojo.io.bind({
            url : url,
            contentType: 'application/xml',
            method: 'POST',
            error: dojo.lang.hitch(this, function (type, errObj, http, kwArgs) { Widget._handleException('createHtml ('+url+')', errObj); }),
            load: dojo.lang.hitch(this, function (type, ret, http, kwArgs) { callback(http); })
        });
    },
    insertWidget : function(editor, widgetHtml) {
        this.Editor = editor;
        try {
            editor.insertHTML(widgetHtml);
            var doc = editor._doc;
            var widgetIFrameDiv = null;
            var iframeDivs = doc.getElementsByTagName('div');
            for (var i = iframeDivs.length; i > 0; ) {
                var iframeDiv = iframeDivs[--i];
                if (iframeDiv.getAttribute('widgetid') == -1) {
                    widgetIFrameDiv = iframeDiv;
                    break;
                }
            }
            if (widgetIFrameDiv) {
                widgetIFrameDiv.setAttribute('widgetid', Widget._nextID++);
                var widget = this._initIFrame(widgetIFrameDiv);
                Widget._completeInsertWidget(widget, editor);
            } else debugger;
        } catch (ex) {
            Widget._handleException('insertWidget', ex);
        }
    },
    _completeInsertWidget : function(widget, editor) {
        if (!widget.data) {
            setTimeout(function() {Widget._completeInsertWidget(widget, editor);}, 100);
            return;
        }
        setTimeout(function() {popupWidgetForm(widget.mainIFrame, editor);}, 250);
    },
    updateWidget : function(editor, data, widgetID) {
        this.Editor = editor;
        var widget = parent.Widget._getWidgetByID(widgetID);
        widget.data = data;
        widget.innerWidget.ownerDocument.location.reload(true);
        widget.innerWidget = null;
        setTimeout(function() {Widget._connectInnerIframe(widget.mainIFrame);}, 250);
    },
    getWidget : function(node) {
        if (node.widget) {return node.widget;}
        var widgetID = node.getAttribute('widgetid');
        if (!widgetID) {return null;}
        var widget = parent.Widget._getWidgetByID(widgetID);
        if (!widget) {return null;}
        node.widget = widget;
        return widget;
    },

    magicInsert : function(editor) {
        dojo.io.bind({
            url : "/dream/wiki-render/paste?insertMagic=true",
            contentType: 'application/xml',
            mimetype: 'text/plain',
            method: 'POST',
            postContent: "<html><body></body></html>",
            sync: true,
            error: function (type, errorObj, http) {
                debugger;
            },
            load: function(type, result, http, kwArgs) {
                var str = http.responseText;
                str = str.substring(str.indexOf('<body>') + '<body>'.length);
                str = str.substring(0, str.indexOf('</body>'));
                editor.insertHTML(str);
                Widget.initializeEditor(editor._doc, editor);
            }
        });
    },

    // Widget body load
    initializeEditor : function (doc, editor) {
        this.Editor = editor;
        parent.Widget._widgetsById = {};
        parent.Widget._nextID = 0;
        var iframeDivs = doc.getElementsByTagName('div');
        for (var i = iframeDivs.length; i > 0; ) {
            var iframeDiv = iframeDivs[--i];
            if (iframeDiv.className == 'widget') {
                this._initIFrame(iframeDiv);
            }
        }
        var spans = doc.getElementsByTagName('span');
        for (var i = spans.length; i > 0; ) {
            var span = spans[--i];
            if (span.className == 'widget') {
                this._initEditorSpan(span);
            }
        }
    },
    body_init : function () {},
    _htmlEncode_regEx : new RegExp().compile(/[&<>\x22\u0080-\uFFFF]/g),
    htmlEncode : function(str) {
        if(typeof str.replace == 'undefined') str = str.toString();
        return str.replace(this._htmlEncode_regEx, function(s,b) {
            switch (s) {
            case '&': return "&amp;";
            case '<': return "&lt;";
            case '>': return "&gt;";
            case "\xA0": return "&nbsp;";
            case '"': return "&quot;";
            default: return "&#"+s.charCodeAt(0)+";";
            }
        });
    },
    setInnerText : function(node, text) {
        if (!node) {debugger; return;}
        if (typeof node.innerText != 'undefined') {node.innerText = text; }
        else if (typeof node.textContent != 'undefined') {node.textContent = text; }
        else {node.innerHTML = this.htmlEncode(text);}
    },
    getInnerText : function(node) {
        if (!node) {debugger; return '';}
        if (typeof node.innerText != 'undefined') {return node.innerText;}
        if (typeof node.textContent != 'undefined') {return node.textContent;}
        return HTMLArea.getInnerText(node);
    },

    // internal implementation
    _handleException : function(name, ex) {
        debugger;
        alert('Unhandled exception: '+name+': ' + (ex.description ? ex.name + ': ' + ex.description : ex));
        throw ex;
    },
    _handleBadResponse : function(name, request) {
        debugger;
        alert('Request failed: '+name+' (' + request.status + ') ' + request.statusText);
    },
    _setDimentsions : function (widgetIFrame, dimensions) {
        widgetIFrame.style.width = dimensions.width + "px";
        widgetIFrame.style.height = dimensions.height + "px";
    },
    _getWidgetByID : function (widgetID) {
        var widget = this._widgetsById[widgetID];
        if (widget == 'loading') return null;
        return widget;
    },
    _getUniqueID : function(node) {
        var ID = node.getAttribute('widgetid');
        if (!ID) {
            ID = parent.Widget._nextID++;
            node.setAttribute('widgetid', ID);
        }
        else {
            if (parent.Widget._widgetsById[ID]) {
                ID = parent.Widget._nextID++;
                node.setAttribute('widgetid', ID);
            }
            if (parent.Widget._nextID <= ID) { parent.Widget._nextID = parseInt(ID,10)+1; }
        }
        return ID;
    },
    _initEditorSpan : function (widgetSpan) {
        var widgetType = widgetSpan.getAttribute('widgettype');
        var xmlData = this.toXml(this._findChildElement(widgetSpan));
        var self = this;
        var ID = this._getUniqueID(widgetSpan);
        parent.Widget._widgetsById[ID] = 'loading';
        var url = this._getRequestUri("/widget/load/" + widgetType + "?mode=edit&id=" + ID);
        setTimeout(function() {
            dojo.io.bind({
                url : url,
                contentType: 'application/xml',
                method: 'POST',
                postContent: xmlData,
                error: dojo.lang.hitch(this, function (type, errObj, http, kwArgs) { Widget._handleException('initEditorSpan ('+url+')', errObj); }),
                load: dojo.lang.hitch(this, function (type, ret, http, kwArgs) { self._onEditorSpanLoaded(http, widgetSpan); })
            });
        }, 0);
    },
    _onEditorSpanLoaded : function (request, widgetSpan) {
        try {
            var tmp = widgetSpan.ownerDocument.createElement('div');
            tmp.innerHTML = request.responseText;
            var widgetIFrameDiv = tmp.firstChild;
            if (widgetIFrameDiv.nodeType != 1) widgetIFrameDiv = widgetIFrameDiv.nextSibling;
            widgetSpan.parentNode.insertBefore(widgetIFrameDiv, widgetSpan);
            widgetIFrameDiv.setAttribute('widgetid', widgetSpan.getAttribute('widgetid'));
            widgetSpan.parentNode.removeChild(widgetSpan);
            this._initIFrame(widgetIFrameDiv);
        } catch (ex) {
            Widget._handleException('_onEditorSpanLoaded', ex);
        }
    },
    registerWidget : function(id, data) {
        var widget = parent.Widget._getWidgetByID(id);
        if (widget)
            widget.data = data;
    },
    _connectInnerIframe : function(widgetIFrame, viewHTML) {
        var innerWin = widgetIFrame.contentWindow;
        if (!innerWin) return;
        var iframeBody = innerWin.document ? innerWin.document.body : null;
        var loading = dojo.byId('loading', innerWin.document);
        if (!widgetIFrame.widget.data || !iframeBody || !iframeBody.ownerDocument.body || !loading) {
            setTimeout(function() {Widget._connectInnerIframe(widgetIFrame, viewHTML);}, 100);
            return;
        }

        var win = widgetIFrame.contentWindow;
        var editor = this.Editor;
        HTMLArea._addEvents(win.document, ["contextmenu"],
            function (event) {
                popupWidgetForm(widgetIFrame, editor);
                HTMLArea._stopEvent(HTMLArea.is_ie ? win.event : event);
            }
        );

        iframeBody = innerWin.document.body;
        loading.parentNode.removeChild(loading);
        var widgetDiv = iframeBody.ownerDocument.createElement('div');
        iframeBody.appendChild(widgetDiv);
        widgetDiv.className = 'widget';
        widgetDiv.setAttribute('widgettype', widgetIFrame.widget.type);
        widgetDiv.widget = new WidgetInstance(widgetDiv, false, widgetIFrame.widget, viewHTML);
    },
    _initIFrame : function (iframeDiv) {
        var widgetIFrame = iframeDiv.ownerDocument.createElement('iframe');
        widgetIFrame.src= "/editor/widgets/blank.html";
        widgetIFrame.style.display = "block";
        widgetIFrame.setAttribute('widgettype', iframeDiv.getAttribute('widgettype'));
        widgetIFrame.setAttribute('widgetid', iframeDiv.getAttribute('widgetid'));
        iframeDiv.parentNode.insertBefore(widgetIFrame, iframeDiv);

        var script, viewHTML, child;
        child = iframeDiv.firstChild;
        while (child) {
            if (child.nodeType == 1) {
                switch (child.className) {
                case 'data': script = Widget.getInnerText(child); break;
                case 'view': viewHTML = child.innerHTML; break;
                }
            }
            child = child.nextSibling;
        }
        iframeDiv.parentNode.removeChild(iframeDiv);
        widgetIFrame.widget = new WidgetInstance(widgetIFrame, true);

        var ID = widgetIFrame.widget.ID;
        var registerCall = script.replace(/registerWidget\(-?[0-9]+,/,'registerWidget('+ID+',');
        eval(registerCall);
        setTimeout(function() {Widget._connectInnerIframe(widgetIFrame, viewHTML);}, 250);
        return widgetIFrame.widget;
    },
    _findChildElement : function (node) {
        var child = node.firstChild;
        while (child && child.nodeType == 3) child = child.nextSibling;
        return child;
    },
    _getRequestUri : function(uri) {
        if (window.location.port != "8081") {
            uri = "/dream" + uri;
        }
        return uri;
    }
});

window.Widget = new WidgetManager();

dojo.declare("WidgetInstance", null, {
    mainDiv : null,
    mainIFrame : null,
    type : null,
    ID : -1,
    innerWidget : null,
    outerWidget : null,
    data : null,

    initializer: function(widgetDivOrIFrame, isIFrame, parentWidget, viewHTML) {
        if (!isIFrame) {
            this.mainDiv = widgetDivOrIFrame;
            this.ownerDocument = this.mainDiv.ownerDocument;
        } else {
            this.mainIFrame = widgetDivOrIFrame;
            dojo.event.connect(this.mainIFrame, "resize", this, "onIFrameResize");
        }
        this.type = widgetDivOrIFrame.getAttribute('widgettype');

        var xmlData = null;
        if (parentWidget) {
            // this is the editor iframe div, don't record it
            this.ID = parentWidget.ID;
            parentWidget.innerWidget = this;
            this.outerWidget = parentWidget;
            if (!viewHTML)
                xmlData = '<'+parentWidget.type+'>'+Widget.toXmlFromJson(parentWidget.data)+'</'+parentWidget.type+'>';
        } else {
            this.ID = widgetDivOrIFrame.getAttribute('widgetid');
            if (!this.ID || this.ID < 1)
                this.ID = parent.Widget._nextID++;
            else {
                if (parent.Widget._getWidgetByID(this.ID))
                    this.ID = parent.Widget._nextID++;
                if (parent.Widget._nextID <= this.ID) { parent.Widget._nextID = parseInt(this.ID,10)+1; }
            }
            parent.Widget._widgetsById[this.ID] = this;
        }
        widgetDivOrIFrame.setAttribute('widgetid', this.ID);
        if (viewHTML)
            this._attachView(viewHTML);
        else if (this.outerWidget && xmlData)
            this._requestView(xmlData);
    },
    toHtml : function() {
        var html = '<span class="widget" widgettype="'+this.type+'" widgetid="'+this.ID+'"><span class="'+this.type+'">'+Widget.toHtmlFromJson(this.data)+'</span></span>';
        return html;
    },
    onIFrameResize : function (event) {
        if (this.innerWidget) {
            this.innerWidget.onResize(this.mainIFrame.offsetWidth, this.mainIFrame.offsetHeight);
        }
    },
    onResize : function(width, height) {
    },

    // internal implementation
    _requestView : function(xmlData) {
        var self = this;
        var url = Widget._getRequestUri("/widget/load/" + this.type + "?mode=" + Widget.Mode + "&id=" + this.ID);
        dojo.io.bind({
            url : url,
            contentType: 'application/xml',
            method: 'POST',
            postContent: xmlData,
            error: dojo.lang.hitch(this, function (type, errObj, http, kwArgs) { Widget._handleException('request ('+url+')', errObj); }),
            load: dojo.lang.hitch(this, function (type, ret, http, kwArgs) { self._requestViewOk(http); })
        });
    },
    _attachView : function(viewHTML) {
        this._copyView(viewHTML);
    },
    _copyView : function(viewHTML) {
        var tmp = this.ownerDocument.createElement('div');
        tmp.innerHTML = viewHTML;
        var child = tmp.firstChild;
        while (child) {
            var next = child.nextSibling;
            if (child.nodeType == 1) {
                this.mainDiv.parentNode.insertBefore(child, this.mainDiv);
            }
            child = next;
        }
        this.mainDiv.parentNode.removeChild(this.mainDiv);
        this.mainDiv = null;
        this._applyDimensions();
    },
    _requestViewOk : function(request) {
        this._copyView(request.responseText);
    },
    _applyDimensions : function () {
        if (this.outerWidget) {
            var parentWidget = this.outerWidget;
            var widgetViewNode = this.ownerDocument.body;
            if (!widgetViewNode.scrollWidth) {
                var self = this;
                window.setTimeout(function () {self._applyDimensions();}, 250);
                return;
            }
            if (widgetViewNode.scrollWidth) {
                var left = widgetViewNode.clientLeft ? 2*widgetViewNode.clientLeft : 10;
                var top = widgetViewNode.clientTop ? 2*widgetViewNode.clientTop : 4;
                window.parent.parent.Widget._setDimentsions(parentWidget.mainIFrame, {
                    width: left+widgetViewNode.scrollWidth, 
                    height: top+widgetViewNode.scrollHeight
                });
            }
        }
    }
});

dojo.declare("AppleWidgetManager", null, {
    iframe : null,
    widget : null,
    widgetApi : null,
    data : null,
    identifier : null,
    startupRequest : null,
    onhide : null,
    onshow : null,
    onreceiverequest : null,

    initializer : function (widget, iframe, data) {
        this.iframe = iframe;
        this.widget = widget;
        this.identifier = widget.type;
        this.data = data;
        var self = this;
        window.setTimeout(function() {self.start(); }, 250);
    },
    applyData : function(data) {
        this.data = data;
        if (this.widgetApi) {this.widgetApi.onDataChanged();}
    },
    start : function() {
        if (!window.WidgetApi) {
            var self = this;
            window.setTimeout(function() {self.start(); }, 250);
            return;
        }
        this.widgetApi = window.WidgetApi;
        this.widgetApi.start();
    },
    preferenceForKey : function(fullKey) {
        if (fullKey.indexOf(this.identifier) !== 0)
            return undefined;
        var key = fullKey.substring(this.identifier.length+1);
        return this.data[key] ? this.data[key] : undefined;
    },
    setPreferenceForKey : function(value, fullKey) {
        if (fullKey.indexOf(this.identifier) !== 0)
            return;
        var key = fullKey.substring(this.identifier.length+1);
        this.data[key] = value;
        this.widget._saveData();
    },
    resizeAndMoveTo : function(left, top, width, height) {},
    setCloseBoxOffset : function(left, top) {},
    setPositionOffset : function(left, top) {},
    prepareForTransition : function(toWhere) {},
    performTransition : function() {},
    createMenu : function() {},
    closestCity : function() {},
    setInnerText : function(node, text) { Widget.setInnerText(node, text); },
    setOpacity : function(node, opacity) { Widget.setOpacity(node, opacity); },
    getRequestUri : function(uri) { return Widget._getRequestUri(uri); },
    defaultShowSettings : function() { return false; },
    resize : function(width, height) {
        if (!document.body.filters) {
            width += 20;
            height += 20;
        } else {
            width += 10;
            height += 10;
        }
        if (window.frameElement) {
            window.frameElement.style.width = width + "px";
            window.frameElement.style.height = height + "px";
        }
        if (this.widget && this.widget.outerWidget) {
            if (!document.body.filters) {
                width += 40;
                height += 20;
            } else {
                width += 10;
                height += 10;
            }
            var bdy = this.widget.ownerDocument.body;
            this.widget.outerWidget.mainIFrame.style.width = parseInt(bdy.leftMargin,10) + parseInt(bdy.rightMargin,10) + width + "px";
            this.widget.outerWidget.mainIFrame.style.height = parseInt(bdy.topMargin,10) + parseInt(bdy.bottomMargin,10) + height + "px";
        }
    }
});

