/* The code represented in this file is compressed for optimization purposes. The full source code is available in includes/clientside/static/. */

var ENANO_JSRES_COMPRESSED = true;

/*
 * Enano - an open source wiki-like CMS
 * Copyright (C) 2006-2007 Dan Fuhry
 * Javascript client library
 *
 * This program is Free Software; you can redistribute 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 details.
 *
 * For more information about Enano, please visit http://enanocms.org/.
 * Unless otherwise noted, all of the code in these script files may be used freely so long as the above license block
 * is displayed and your modified code is distributed in compliance with the GPL. See the special page "About Enano" on
 * this website for more information.
 */

if ( typeof(title) != 'string')
{
	alert('There was a problem loading the PHP-generated Javascript variables that control parameters for AJAX applets. Most on-page functionality will be very badly broken.\n\nTheme developers, ensure that you are using {JS_DYNAMIC_VARS} *before* you include jsres.php.');
}

// placeholder for window.console - used if firebug isn't present
// http://getfirebug.com/firebug/firebugx.js
if (!window.console || !console.firebug)
{
		var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
		"group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];

		window.console = {};
		for (var i = 0; i < names.length; ++i)
				window.console[names[i]] = function() {}
}

console.info('Enano::JS runtime: starting system init');

if ( typeof(ENANO_JSRES_COMPRESSED) == undefined )
{
	var ENANO_JSRES_COMPRESSED = false;
}

// Run-time variables

var detect = navigator.userAgent.toLowerCase();
var IE;
var is_Safari;

// Detect whether the user is running the Evil One or not...

function checkIt(string) {
	place = detect.indexOf(string) + 1;
	thestring = string;
	return place ? true : false;
}

var IE = checkIt('msie');
var IE_8 = checkIt('msie 8.');
var is_Opera = checkIt('opera');
var is_iPhone = checkIt('iphone') || checkIt('ipod');
var is_iPhone_3 = checkIt('iphone os 3_');
var is_Webkit = checkIt('applewebkit');
var is_Gecko = checkIt('gecko');
var is_firefox2 = checkIt('firefox/2.');

var KILL_SWITCH = false;

if ( IE )
{
	var version = window.navigator.appVersion;
	version = version.substr( ( version.indexOf('MSIE') + 5 ) );
	var rawversion = '';
	for ( var i = 0; i < version.length; i++ )
	{
		var chr = version.substr(i, 1);
		if ( !chr.match(/[0-9\.]/) )
		{
			break;
		}
		rawversion += chr;
	}
	rawversion = parseInt(rawversion);
	if ( rawversion < 6 )
	{
		KILL_SWITCH = true;
	}
}

var tinymce_initted = false;

if ( typeof(DISABLE_MCE) == undefined )
{
	var DISABLE_MCE = false;
}

is_Safari = checkIt('safari') ? true : false;

var cmt_open;
var editor_open = false;
var list;
var edit_open = false;
var catlist = new Array();
var arrDiff1Buttons = new Array();
var arrDiff2Buttons = new Array();
var arrTimeIdList   = new Array();
var list;
var unObj;
var unSelectMenuOn = false;
var unObjDivCurrentId = false;
var unObjCurrentSelection = false;
var userlist = new Array();
var submitAuthorized = true;
var timelist = [];
var rDnsObj;
var rDnsBannerObj;
var ns4 = document.layers;
var op5 = (navigator.userAgent.indexOf("Opera 5")!=-1) ||(navigator.userAgent.indexOf("Opera/5")!=-1);
var op6 = (navigator.userAgent.indexOf("Opera 6")!=-1) ||(navigator.userAgent.indexOf("Opera/6")!=-1);
var agt=navigator.userAgent.toLowerCase();
var mac = (agt.indexOf("mac")!=-1);
var ie = (agt.indexOf("msie") != -1);
var mac_ie = mac && ie;
var mouseX = 0;
var mouseY = 0;
var menuheight;
var inertiabase = 1;
var inertiainc = 1;
var slideintervalinc = 20;
var inertiabaseoriginal = inertiabase;
var heightnow;
var targetheight;
var block;
var slideinterval;
var divheights = new Array();
var __menutimeout = false;
var startmouseX = false;
var startmouseY = false;
var startScroll = false;
var is_dragging = false;
var current_ta  = false;
var startwidth  = false;
var startheight = false;
var do_width    = false;
var ajax_load_icon = cdnPath + '/images/loading.gif';
var editor_use_modal_window = false;

// You have an NSIS coder in your midst...
var MB_OK = 1;
var MB_OKCANCEL = 2;
var MB_YESNO = 4;
var MB_YESNOCANCEL = 8;
var MB_ABORTRETRYIGNORE = 16;
var MB_ICONINFORMATION = 32;
var MB_ICONEXCLAMATION = 64;
var MB_ICONSTOP = 128;
var MB_ICONQUESTION = 256;
var MB_ICONLOCK = 512;

// Can be set to true by slow themes (St. Patty)
if ( typeof(pref_disable_js_fx) != 'boolean' )
{
	var pref_disable_js_fx = false;
}
var aclDisableTransitionFX = ( is_firefox2 || pref_disable_js_fx ) ? true : false;

// Syntax:
// messagebox(MB_OK|MB_ICONINFORMATION, 'Title', 'Text');
// :-D

var $_REQUEST = new Object();
if ( window.location.hash )
{
	var hash = String(window.location.hash);
	hash = hash.substr(1);
	var reqobj = hash.split(';');
	var a, b;
	for ( var i = 0; i < reqobj.length; i++ )
	{
		a = reqobj[i].substr(0, reqobj[i].indexOf(':'));
		b = reqobj[i].substr( ( reqobj[i].indexOf(':') + 1 ) );
		$_REQUEST[a] = b;
	}
}

if ( !onload_hooks )
	var onload_hooks = new Array();

function addOnloadHook(func)
{
	if ( typeof ( func ) == 'function' )
	{
		if ( typeof(onload_hooks.push) == 'function' )
		{
			onload_hooks.push(func);
		}
		else
		{
			onload_hooks[onload_hooks.length] = func;
		}
	}
}

function runOnloadHooks(e)
{
	var _errorTrapper = 0;
	for ( var _oLc = 0; _oLc < onload_hooks.length; _oLc++ )
	{
		_errorTrapper++;
		if ( _errorTrapper >= 1000 )
			break;
		var _f = onload_hooks[_oLc];
		if ( typeof(_f) == 'function' )
		{
			_f(e);
		}
	}
	onload_hooks = [];
}

var enano_hooks = {};
function setHook(hook_name)
{
	if ( enano_hooks[hook_name] )
	{
		return enano_hooks[hook_name];
	}
	return 'void(0);';
}

function attachHook(hook_name, code)
{
	if ( !enano_hooks[hook_name] )
		enano_hooks[hook_name] = '';
	
	enano_hooks[hook_name] += code;
}

var loaded_components = loaded_components || {};
var _load_component_running = false;
function load_component(file)
{
	var multiple = false;
	if ( typeof(file) == 'object' )
	{
		if ( ENANO_JSRES_COMPRESSED )
		{
			multiple = true;
			for ( var i = 0; i < file.length; i++ )
			{
				file[i] = (file[i].replace(/\.js$/, '')) + '.js';
				if ( loaded_components[file[i]] )
				{
					file[i] = false;
				}
			}
			var file2 = [];
			for ( var i = 0; i < file.length; i++ )
			{
				if ( file[i] )
					file2.push(file[i]);
			}
			file = file2;
			delete(file2);
			if ( file.length < 1 )
			{
				return true;
			}
			var file_flat = implode(',', file);
		}
		else
		{
			for ( var i = 0; i < file.length; i++ )
			{
				load_component(file[i]);
			}
			return true;
		}
	}
	_load_component_running = true;
	if ( !multiple )
	{
		file = file.replace(/\.js$/, '');
	
		if ( loaded_components[file + '.js'] )
		{
			// already loaded
			return true;
		}
	}
	
	console.info('Loading component %s via AJAX', ( multiple ? file_flat : file ));
	
	load_show_win(( multiple ? file_flat : file ));
	
	// get an XHR instance
	var ajax = ajaxMakeXHR();
	
	if ( !multiple )
		file = file + '.js';
	var uri = ( ENANO_JSRES_COMPRESSED ) ? scriptPath + '/includes/clientside/jsres.php?f=' + (multiple ? file_flat : file ) + '&' + enano_version : scriptPath + '/includes/clientside/static/' + file + '?' + enano_version;
	try
	{
		ajax.open('GET', uri, false);
		ajax.onreadystatechange = function()
		{
			if ( this.readyState == 4 && this.status != 200 )
			{
				alert('There was a problem loading a script from the server. Please check your network connection.');
				load_hide_win();
				throw('load_component(): XHR for component ' + file + ' failed');
			}
		}
		ajax.send(null);
		// async request, so if status != 200 at this point then we're screwed
		if ( ajax.readyState == 4 && ajax.status == 200 )
		{
			if ( onload_complete )
				onload_hooks = [];
			eval_global(ajax.responseText);
			if ( window.jQuery && aclDisableTransitionFX )
				if ( window.jQuery.fx )
					window.jQuery.fx.off = true;
			load_hide_win();
			if ( onload_complete )
				runOnloadHooks();
		}
	}
	catch(e)
	{
		alert('There was a problem loading a script from the server. Please check your network connection.');
		load_hide_win();
		console.info("Component loader exception is shown below.");
		console.debug(e);
		console.trace();
		throw('load_component(): XHR for component ' + file + ' failed');
	}
	
	if ( !multiple )
	{
		loaded_components[file] = true;
	}
	_load_component_running = false;
	return true;
}

function load_show_win(file)
{
	var img = '<img style="margin-right: 5px" src="' + cdnPath + '/images/loading.gif" />';
	if ( document.getElementById('_js_load_component') )
	{
		document.getElementById('_js_load_component').innerHTML = img + msg_loading_component.replace('%component%', file);
		return;
	}
	file = file.replace(/\.js$/, '').replace(/\.js,/g, ', ');
	var ld = document.createElement('div');
	ld.style.padding = '10px';
	ld.style.height = '12px';
	ld.style.position = 'fixed';
	ld.style.right = '5px';
	ld.style.bottom = '0px';
	ld.innerHTML = img + msg_loading_component.replace('%component%', file);
	ld.id = '_js_load_component';
	
	// FYI: The base64 encoded image is a 70% opacity 1x1px white PNG.
	ld.style.backgroundImage = 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAA1JREFUCNdj+P///xkACcgDypG+nnEAAAAASUVORK5CYII=)';
	
	document.body.appendChild(ld);
	document.body.style.cursor = 'wait';
}

function load_hide_win()
{
	var ld = document.getElementById('_js_load_component');
	if ( !ld )
		return false;
	ld.parentNode.removeChild(ld);
	document.body.style.cursor = 'default';
}

// evaluate a snippet of code in the global context, used for dynamic component loading
// from: http://dean.edwards.name/weblog/2006/11/sandbox/
function eval_global(_jsString)
{
	if (typeof _jsString != "string")
	{
		return false;
	}

	// Check whether window.eval executes code in the global scope.
	window.eval("var __INCLUDE_TEST_1__ = true;");
	if (typeof window.__INCLUDE_TEST_1__ != "undefined")
	{
		delete window.__INCLUDE_TEST_1__;
		window.eval(_jsString);
	}
	else if (typeof window.execScript != "undefined")	// IE only
	{
		window.execScript(_jsString);
	}
	else
	{
		// Test effectiveness of creating a new SCRIPT element and adding it to the document.
		this._insertScriptTag = function (_jsCode) {
			var _script = document.createElement("script");
			_script.type = "text/javascript";
			_script.defer = false;
			_script.text = _jsCode;
			var _headNodeSet = document.getElementsByTagName("head");
			if (_headNodeSet.length)
			{
				_script = _headNodeSet.item(0).appendChild(_script);
			}
			else
			{
				var _head = document.createElement("head");
				_head = document.documentElement.appendChild(_head);
				_script = _head.appendChild(_script);
			}
			return _script;
		}
		var _testScript = this._insertScriptTag("var __INCLUDE_TEST_2__ = true;");
		if (typeof window.__INCLUDE_TEST_2__ == "boolean")
		{
			_testScript.parentNode.removeChild(_testScript);
			this._insertScriptTag(_jsString);
		}
		else
		{
			// Check whether window.setTimeout works in real time.
			window.setTimeout("var __INCLUDE_TEST_3__ = true;", 0);
			if (typeof window.__INCLUDE_TEST_3__ != "undefined")
			{
				delete window.__INCLUDE_TEST_3__;
				window.setTimeout(_jsString, 0);
			}
		}
	}

	return true;
}

var autofill_check = function()
{
	var inputs = document.getElementsByTagName('input');
	for ( var i = 0; i < inputs.length; i++ )
	{
		if ( inputs[i].className )
		{
			if ( inputs[i].className.match(/^autofill/) )
			{
				load_component('autofill');
				return;
			}
		}
	}
}

addOnloadHook(autofill_check);

var head = document.getElementsByTagName('head')[0];

// safari has window.console but not the .debug() method
if ( is_Safari && !window.console.debug )
{
	window.console.debug = function() {};
}

// Do not remove the following comments, they are used by jsres.php.



addOnloadHook(function() {
	if ( $_REQUEST['auth'] )
	{
		var key = $_REQUEST['auth'];
		var loc = String(window.location);
		loc = loc.replace(/#.+$/, '').replace(/&auth=[0-9a-f]+/, '').replace(/\?auth=[0-9a-f]+(&)?/, '$1');
		if ( key != 'false' )
		{
			var sep = loc.indexOf('?') != -1 ? '&' : '?';
			loc = loc + sep + 'auth=' + key;
		}
		console.debug(loc);
		window.location = loc;
	}
	if ( $_REQUEST['do'] )
	{
		var act = $_REQUEST['do'];
		switch(act)
		{
			case 'comments':
				ajaxComments();
				break;
			case 'edit':
				var revid = ( $_REQUEST['rev'] ) ? parseInt($_REQUEST['rev']) : false;
				ajaxEditor(revid);
				break;
			case 'login':
				ajaxStartLogin();
				break;
			case 'history':
				ajaxHistory();
				break;
			case 'catedit':
				ajaxCatEdit();
				break;
			case 'rename':
				ajaxRename();
				break;
			case 'aclmanager':
				ajaxOpenACLManager();
				break;
		}
	}
});

function Placeholder(funcname, filename)
{
	this.filename = filename;
	this.funcname = funcname;
	this.go = function()
	{
		window[funcname] = null;
		load_component(filename);
		var arglist = [];
		for ( var i = 0; i < arguments.length; i++ )
		{
			arglist[arglist.length] = 'arguments['+i+']';
		}
		arglist = implode(', ', arglist);
		return eval(funcname + '(' + arglist + ');');
	}
}

// list of public functions that need placeholders that fetch the component
var placeholder_list = {
	ajaxReset: 'ajax.js',
	ajaxComments: 'comments.js',
	ajaxEditor: 'editor.js',
	ajaxHistory: 'ajax.js',
	ajaxRename: 'ajax.js',
	ajaxDelVote: 'ajax.js',
	ajaxProtect: 'ajax.js',
	ajaxClearLogs: 'ajax.js',
	ajaxRollback: 'ajax.js',
	ajaxResetDelVotes: 'ajax.js',
	ajaxDeletePage: 'ajax.js',
	ajaxSetPassword: 'ajax.js',
	ajaxChangeStyle: 'ajax.js',
	ajaxCatToTag: 'ajax.js',
	ajaxCatEdit: 'ajax.js',
	ajaxReverseDNS: 'ajax.js',
	ajaxGzipCheck: 'ajax.js',
	ajaxOpenACLManager: 'acl.js',
	ajaxOpenDirectACLRule: 'acl.js',
	ajaxAdminPage: 'login.js',
	ajaxInitLogout: 'login.js',
	ajaxStartLogin: 'login.js',
	ajaxStartAdminLogin: 'login.js',
	ajaxLoginNavTo: 'login.js',
	ajaxLogonToElev: 'login.js',
	ajaxLoginInit: 'login.js',
	ajaxAdminPage: 'login.js',
	ajaxAdminUser: 'login.js',
	mb_logout: 'login.js',
	selectButtonMajor: 'toolbar.js',
	selectButtonMinor: 'toolbar.js',
	unselectAllButtonsMajor: 'toolbar.js',
	unselectAllButtonsMinor: 'toolbar.js',
	darken: 'fadefilter.js',
	enlighten: 'fadefilter.js',
	password_score: 'pwstrength.js',
	password_score_field: 'pwstrength.js',
	ajaxEditTheme: 'theme-manager.js',
	ajaxToggleSystemThemes: 'theme-manager.js',
	ajaxInstallTheme: 'theme-manager.js',
	ajaxInitRankEdit: 'rank-manager.js',
	ajaxInitRankCreate: 'rank-manager.js',
	autofill_init_element: 'autofill.js',
	autofill_init: 'autofill.js',
	paginator_goto: 'paginate.js'
};

function AutofillUsername(el, p)
{
	p = p || {};
	el.className = 'autofill username';
	el.onkeyup = null;
	autofill_init_element(el, p);
}

function AutofillPage(el, p)
{
	p = p || {};
	el.className = 'autofill page';
	el.onkeyup = null;
	autofill_init_element(el, p);
}

var placeholder_instances = {};

for ( var i in placeholder_list )
{
	var file = placeholder_list[i];
	placeholder_instances[i] = new Placeholder(i, file);
	window[i] = window[i] || placeholder_instances[i].go;
}

$lang = window.$lang || {
	get: function(a, b)
	{
		load_component('l10n');
		return $lang.get(a, b);
	},
	placeholder: true
}

//*/


// dynano.js

// The "Dynano" Javascript framework. Similar in syntax to JQuery but highly Enano-specific (TinyMCE, etc).

var $dynano = function(id)
{
	return new DNobj(id);
}
function DNobj(id)
{
	if ( id == undefined )
	{
		return {};
	}
	this.object = ( typeof(id) == 'object' ) ? id : document.getElementById(id);
	if ( !this.object )
	{
		console.warn('Dynano: requested object is bad. id parameter follows.');
		console.debug(id);
		this.object = false;
		return this;
	}
	if ( this.object.Dynano )
	{
		return this.object.Dynano;
	}
	this.object.Dynano = this;
	
	this.height = __DNObjGetHeight(this.object);
	this.width = __DNObjGetWidth(this.object);
	
	if ( this.object.tagName == 'TEXTAREA' && ( typeof(tinyMCE) == 'object' || typeof(tinyMCE_GZ) == 'object' ) )
	{
		this.object.dnIsMCE = 'no';
		this.switchToMCE = DN_switchToMCE;
		this.destroyMCE = DN_destroyMCE;
		this.getContent = DN_mceFetchContent;
		this.setContent = DN_mceSetContent;
		this.makeSwitchable = DN_makeSwitchableTA;
		this.isMCE = DN_isMCE;
	}
}
function __DNObjGetHeight(o) {
	return o.offsetHeight;
}

function __DNObjGetWidth(o) {
	return o.offsetWidth;
}

function addClass(obj, clsname)
{
	var cnt = obj.className;
	var space = ( (cnt + '').length > 0 ) ? ' ' : '';
	var cls = cnt + space + clsname;
	obj.className = cls;
}

function rmClass(obj, clsname)
{
	var cnt = obj.className;
	if ( cnt == clsname )
	{
		obj.className = '';
	}
	else
	{
		cnt = cnt.replace(clsname, '');
		cnt = trim(cnt);
		obj.className = cnt;
	}
}

function hasClass(obj, clsname)
{
	var cnt = obj.className;
	if ( !cnt )
		return false;
	if ( cnt == clsname )
		return true;
	cnt = cnt.split(' ');
	
	for ( var i in cnt )
		if ( cnt[i] == clsname )
			return true;
		
	return false;
}
function __DNObjGetLeft(obj) {
	var left_offset = obj.offsetLeft;
	while ((obj = obj.offsetParent) != null) {
		left_offset += obj.offsetLeft;
	}
	return left_offset;
}

function __DNObjGetTop(obj) {
	var left_offset = obj.offsetTop;
	while ((obj = obj.offsetParent) != null) {
		left_offset += obj.offsetTop;
	}
	return left_offset;
}

function DN_switchToMCE(performWikiTransform)
{
	if ( !this.object.id )
		this.object.id = 'textarea_' + Math.floor(Math.random() * 1000000);
	if ( !this.object.name )
		this.object.name = 'textarea_' + Math.floor(Math.random() * 1000000);
	// Updated for TinyMCE 3.x
	if ( performWikiTransform )
	{
		this.object.value = DN_WikitextToXHTML(this.object.value);
	}
	// If tinyMCE init hasn't been called yet, do it now.
	if ( !tinymce_initted )
	{
		console.info('$dynano().switchToMCE(): doing "exact"-type MCE init');
		enano_tinymce_options.mode = 'exact';
		enano_tinymce_options.elements = this.object.id;
		initTinyMCE();
		this.object.dnIsMCE = 'yes';
		return true;
	}
	else
	{
		console.info('$dynano().switchToMCE(): tinyMCE already loaded, calling mceAddControl');
		tinymce.EditorManager.execCommand("mceAddControl", true, this.object.id);
		this.object.dnIsMCE = 'yes';
	}
	return this;
}

function DN_destroyMCE(performWikiTransform)
{
	//if ( !this.object.dn_is_mce )
	//  return this;
	if ( this.object.id && window.tinymce )
	{
		// TinyMCE 2.x
		// tinymce.EditorManager.removeMCEControl(this.object.name);
		// TinyMCE 3.x
		var ed = tinymce.EditorManager.getInstanceById(this.object.id);
		if ( ed )
		{
			if ( !tinymce.EditorManager.execCommand("mceRemoveEditor", false, this.object.id) )
				alert('could not destroy editor');
			if ( performWikiTransform )
			{
				this.object.value = DN_XHTMLToWikitext(this.object.value);
			}
		}
	}
	this.object.dnIsMCE = 'no';
	return this;
}

function DN_isMCE()
{
	return ( this.object.dnIsMCE == 'yes' );
}

function DN_mceFetchContent()
{
	if ( this.object.name )
	{
		var text = this.object.value;
		if ( tinymce.EditorManager.get(this.object.id) )
		{
			var editor = tinymce.EditorManager.get(this.object.id);
			text = editor.getContent();
		}
		return text;
	}
	else
	{
		return this.object.value;
	}
}

function DN_mceSetContent(text)
{
	if ( this.object.name )
	{
		this.object.value = text;
		if ( tinymce.EditorManager.get(this.object.id) )
		{
			var editor = tinymce.EditorManager.get(this.object.id);
			editor.setContent(text);
		}
	}
	else
	{
		this.object.value = text;
	}
}

var P_BOTTOM = 1;
var P_TOP = 2;

function DN_makeSwitchableTA(pos)
{
	if ( this.toggler )
		return false;
	
	if ( !pos )
		pos = P_BOTTOM;
	
	load_component('l10n');
	var cookiename = 'enano_editor_mode';
	
	var toggler = document.createElement('div');
	toggler.dynano = this;
	this.toggler = toggler;
	
	if ( !this.object.id )
		this.object.id = 'dynano_auto_' + Math.floor(Math.random() * 1000000);
	
	toggler.s_mode_text = $lang.get('editor_btn_wikitext');
	toggler.s_mode_graphical = $lang.get('editor_btn_graphical');
	
	toggler.set_text = function()
	{
		if ( this.dynano.object.dnIsMCE == 'yes' )
			this.dynano.destroyMCE();
		
		this.innerHTML = '';
		this.appendChild(document.createTextNode(this.s_mode_text + ' | '));
		
		var link = document.createElement('a');
		link.href = '#';
		link.onclick = function()
		{
			this.parentNode.set_graphical();
			return false;
		}
		link.appendChild(document.createTextNode(this.s_mode_graphical));
		this.appendChild(link);
		
		createCookie('enano_editor_mode', 'text', 365);
	}
	
	toggler.set_graphical = function()
	{
		this.dynano.switchToMCE();
		this.innerHTML = '';
		
		var link = document.createElement('a');
		link.href = '#';
		link.onclick = function()
		{
			this.parentNode.set_text();
			return false;
		}
		link.appendChild(document.createTextNode(this.s_mode_text));
		this.appendChild(link);
		
		this.appendChild(document.createTextNode(' | ' + this.s_mode_graphical));
		createCookie('enano_editor_mode', 'tinymce', 365);
	}
	
	toggler.style.styleFloat = 'right';
	toggler.style.cssFloat = 'right';
	if ( pos == P_BOTTOM )
	{
		insertAfter(this.object.parentNode, toggler, this.object);
	}
	else
	{
		this.object.parentNode.insertBefore(toggler, this.object);
	}
	
	if ( readCookie(cookiename) == 'tinymce' )
	{
		toggler.set_graphical();
	}
	else
	{
		toggler.set_text();
	}
}

function DN_WikitextToXHTML(text)
{
	return DN_AjaxGetTransformedText(text, 'xhtml');
}

function DN_XHTMLToWikitext(text)
{
	return DN_AjaxGetTransformedText(text, 'wikitext');
}

// AJAX to the server to transform text
function DN_AjaxGetTransformedText(text, to)
{
	// get an XHR instance
	var ajax = ajaxMakeXHR();
	
	var uri = stdAjaxPrefix + '&_mode=transform&to=' + to;
	var parms = 'text=' + ajaxEscape(text);
	try
	{
		ajax.open('POST', uri, false);
		ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		// Setting Content-length in Safari triggers a warning
		if ( !is_Safari )
		{
			ajax.setRequestHeader("Content-length", parms.length);
		}
		ajax.send(parms);
		// async request, so if status != 200 at this point then we're screwed
		if ( ajax.readyState == 4 && ajax.status == 200 )
		{
			var response = String(ajax.responseText + '');
			if ( !check_json_response(response) )
			{
				handle_invalid_json(response);
				return text;
			}
			response = parseJSON(response);
			if ( response.mode == 'error' )
			{
				alert(response.error);
				return text;
			}
			return response.text;
		}
	}
	catch(e)
	{
		console.warn('DN_AjaxGetTransformedText: XHR failed');
	}
	return text;
}

DNobj.prototype.addClass = function(clsname) { addClass(this.object, clsname); return this; };
DNobj.prototype.rmClass  = function(clsname) { rmClass( this.object, clsname); return this; };
DNobj.prototype.hasClass = function(clsname) { return hasClass(this.object, clsname); };
DNobj.prototype.Height   = function()        { return __DNObjGetHeight(this.object); }
DNobj.prototype.Width    = function()        { return __DNObjGetWidth( this.object); }
DNobj.prototype.Left     = function()        { /* return this.object.offsetLeft; */ return __DNObjGetLeft(this.object); }
DNobj.prototype.Top      = function()        { /* return this.object.offsetTop;  */ return __DNObjGetTop( this.object); }



// functions.js

// all utility functions go in here

function makeUrl(page, query, html_friendly)
{
	url = contentPath+page;
	if(url.indexOf('?') > 0) sep = '&';
	else sep = '?';
	if(query)
	{
		url = url + sep + query;
	}
	if(html_friendly)
	{
		url = url.replace('&', '&amp;');
		url = url.replace('<', '&lt;');
		url = url.replace('>', '&gt;');
	}
	return append_sid(url);
}

function makeUrlNS(namespace, page, query, html_friendly)
{
	var url = contentPath+namespace_list[namespace]+(page.replace(/ /g, '_'));
	if(url.indexOf('?') > 0) sep = '&';
	else sep = '?';
	if(query)
	{
		url = url + sep + query;
	}
	if(html_friendly)
	{
		url = url.replace('&', '&amp;');
		url = url.replace('<', '&lt;');
		url = url.replace('>', '&gt;');
	}
	return append_sid(url);
}

function strToPageID(string)
{
	// Convert Special:UploadFile to ['UploadFile', 'Special'], but convert 'Image:Enano.png' to ['Enano.png', 'File']
	for(var i in namespace_list)
	{
		if(namespace_list[i] != '')
		{
			if(namespace_list[i] == string.substr(0, namespace_list[i].length))
			{
				return [string.substr(namespace_list[i].length), i];
			}
		}
	}
	return [string, 'Article'];
}

function append_sid(url)
{
	var match = url.match(/#(.*?)$/);
	url = url.replace(/#(.*?)$/, '');
	sep = ( url.indexOf('?') > 0 ) ? '&' : '?';
	if(ENANO_SID.length > 10)
	{
		url = url + sep + 'auth=' + ENANO_SID;
		sep = '&';
	}
	if ( pagepass.length > 0 )
	{
		url = url + sep + 'pagepass=' + pagepass;
	}
	if ( match )
	{
		url = url + match[0];
	}
	return url;
}

var stdAjaxPrefix = append_sid(scriptPath+'/ajax.php?title='+title);

/**
 * Core AJAX library
 */

function ajaxMakeXHR()
{
	var ajax;
	if (window.XMLHttpRequest) {
		ajax = new XMLHttpRequest();
	} else {
		if (window.ActiveXObject) {           
			ajax = new ActiveXObject("Microsoft.XMLHTTP");
		} else {
			alert('Enano client-side runtime error: No AJAX support, unable to continue');
			return;
		}
	}
	return ajax;
}

function ajaxGet(uri, f, call_editor_safe) {
	// Is the editor open?
	if ( editor_open && !call_editor_safe )
	{
		// Make sure the user is willing to close the editor
		var conf = confirm($lang.get('editor_msg_confirm_ajax'));
		if ( !conf )
		{
			// Kill off any "loading" windows, etc. and cancel the request
			unsetAjaxLoading();
			return false;
		}
		// The user allowed the editor to be closed. Reset flags and knock out the on-close confirmation.
		editor_open = false;
		enableUnload();
		// destroy the MCE instance so it can be recreated later
		$dynano('ajaxEditArea').destroyMCE(false);
	}
	var ajax = ajaxMakeXHR();
	if ( !ajax )
	{
		console.error('ajaxMakeXHR() failed');
		return false;
	}
	ajax.onreadystatechange = function()
	{
		f(ajax);
	};
	ajax.open('GET', uri, true);
	ajax.setRequestHeader( "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT" );
	ajax.send(null);
	window.ajax = ajax;
}

function ajaxPost(uri, parms, f, call_editor_safe) {
	// Is the editor open?
	if ( editor_open && !call_editor_safe )
	{
		// Make sure the user is willing to close the editor
		var conf = confirm($lang.get('editor_msg_confirm_ajax'));
		if ( !conf )
		{
			// Kill off any "loading" windows, etc. and cancel the request
			unsetAjaxLoading();
			return false;
		}
		// The user allowed the editor to be closed. Reset flags and knock out the on-close confirmation.
		editor_open = false;
		enableUnload();
		// destroy the MCE instance so it can be recreated later
		$dynano('ajaxEditArea').destroyMCE(false);
	}
	var ajax = ajaxMakeXHR();
	if ( !ajax )
	{
		console.error('ajaxMakeXHR() failed');
		return false;
	}
	ajax.onreadystatechange = function()
	{
		f(ajax);
	};
	ajax.open('POST', uri, true);
	ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	// Setting Content-length in Safari triggers a warning
	if ( !is_Safari )
	{
		ajax.setRequestHeader("Content-length", parms.length);
	}
	// fails under chrome 2.0
	// ajax.setRequestHeader("Connection", "close");
	ajax.send(parms);
	window.ajax = ajax;
}

/**
 * Show a friendly error message depicting an AJAX response that is not valid JSON
 * @param string Response text
 * @param string Custom error message. If omitted, the default will be shown.
 */

function handle_invalid_json(response, customerror)
{
	load_component(['messagebox', 'jquery', 'jquery-ui', 'fadefilter', 'flyin', 'l10n']);
	
	darken(aclDisableTransitionFX, 70, 'invalidjsondarkener');
	
	var box = document.createElement('div');
	var mainwin = document.createElement('div');
	var panel = document.createElement('div');
	
	//
	// main window
	//
	
		mainwin.style.padding = '10px';
		mainwin.style.width = '580px';
		mainwin.style.height = '360px';
		mainwin.style.clip = 'rect(0px,auto,auto,0px)';
		mainwin.style.overflow = 'auto';
		mainwin.style.backgroundColor = '#ffffff';
	
		// Title
		var h3 = document.createElement('h3');
		var h3_text = ( $lang.placeholder ) ? 'The site encountered an error while processing your request.' : $lang.get('ajax_badjson_title');
		h3.appendChild(document.createTextNode(h3_text));
		mainwin.appendChild(h3);
		
		if ( typeof(customerror) == 'string' )
		{
			var el = document.createElement('p');
			el.appendChild(document.createTextNode(customerror));
			mainwin.appendChild(el);
		}
		else
		{
			var error = 'We unexpectedly received the following response from the server. The response should have been in the JSON ';
			error += 'serialization format, but the response wasn\'t composed only of the JSON response. There are three possible triggers ';
			error += 'for this problem:';
			customerror = ( $lang.placeholder ) ? error : $lang.get('ajax_badjson_body');
			var el = document.createElement('p');
			el.appendChild(document.createTextNode(customerror));
			mainwin.appendChild(el);
			var ul = document.createElement('ul');
			var li1 = document.createElement('li');
			var li2 = document.createElement('li');
			var li3 = document.createElement('li');
			var li1_text = ( $lang.placeholder ) ? 'The server sent back a bad HTTP response code and thus sent an error page instead of running Enano. This indicates a possible problem with your server, and is not likely to be a bug with Enano.' : $lang.get('ajax_badjson_tip1');
			var li2_text = ( $lang.placeholder ) ? 'The server sent back the expected JSON response, but also injected some code into the response that should not be there. Typically this consists of advertisement code. In this case, the administrator of this site will have to contact their web host to have advertisements disabled.' : $lang.get('ajax_badjson_tip2');
			var li3_text = ( $lang.placeholder ) ? 'It\'s possible that Enano triggered a PHP error or warning. In this case, you may be looking at a bug in Enano.' : $lang.get('ajax_badjson_tip3');
			var osc_ex_data = ( $lang.placeholder ) ? 'This is KNOWN to be the case with the OpenSourceCMS.com demo version of Enano.' : $lang.get('ajax_badjson_osc');
			li1.appendChild(document.createTextNode(li1_text));
			var osc_exception = ( window.location.hostname == 'demo.opensourcecms.com' ) ? ' ' + osc_ex_data : '';
			li2.appendChild(document.createTextNode(li2_text + osc_exception));
			li3.appendChild(document.createTextNode(li3_text));
				
			ul.appendChild(li1);
			ul.appendChild(li2);
			ul.appendChild(li3);
			mainwin.appendChild(ul);
		}
		
		var p2 = document.createElement('p');
		var p2_text = ( $lang.placeholder ) ? 'The response received from the server is as follows:' : $lang.get('ajax_badjson_msg_response');
		p2.appendChild(document.createTextNode(p2_text));
		mainwin.appendChild(p2);
		
		var pre = document.createElement('pre');
		pre.appendChild(document.createTextNode(response));
		mainwin.appendChild(pre);
		
		var p3 = document.createElement('p');
		var p3_text = $lang.placeholder ? 'You may also choose to view the response as HTML.' : $lang.get('ajax_badjson_msg_viewashtml');
		p3.appendChild(document.createTextNode(p3_text + ' '));
		var a = document.createElement('a');
		var a_text = $lang.placeholder ? 'View as HTML' : $lang.get('ajax_badjson_btn_viewashtml');
		a.appendChild(document.createTextNode(a_text + '...'));
		a._resp = response;
		a.onclick = function()
		{
			var vah_title = ( $lang.placeholder ) ? 'View the response as HTML?' : $lang.get('ajax_badjson_html_confirm_title');
			var vah_body = ( $lang.placeholder ) ? 'If the server\'s response was modified by an attacker to include malicious code, viewing the response as HTML might allow that malicious code to run. Only continue if you have inspected the response text and verified that it is safe.' : $lang.get('ajax_badjson_html_confirm_body');
			var btn_confirm = $lang.placeholder ? 'View as HTML' : $lang.get('ajax_badjson_btn_viewashtml');
			var btn_cancel = $lang.placeholder ? 'Cancel' : $lang.get('etc_cancel');
			var mp = miniPromptMessage({
					title: vah_title,
					message: vah_body,
					buttons: [
						{
							text: btn_confirm,
							color: 'blue',
							style: {
								fontWeight: 'bold'
							},
							onclick: function() {
								var mp = miniPromptGetParent(this);
								var win = window.open('about:blank', 'invalidjson_htmlwin', 'width=550,height=400,status=no,toolbars=no,toolbar=no,address=no,scroll=yes');
								win.document.write(mp._response);
								win.document.close();
								miniPromptDestroy(this);
							}
						},
						{
							text: btn_cancel,
							onclick: function() {
								miniPromptDestroy(this);
							}
						}
					]
				});
			mp._response = this._resp;
			return false;
		}
		a.href = '#';
		p3.appendChild(a);
		mainwin.appendChild(p3);
	
	//
	// panel
	//
	
		panel.style.backgroundColor = '#D0D0D0';
		panel.style.textAlign = 'right';
		panel.style.padding = '0 10px';
		panel.style.lineHeight = '40px';
		panel.style.width = '580px';
		
		var closer = document.createElement('input');
		var btn_close = $lang.placeholder ? 'Close' : $lang.get('ajax_badjson_btn_close');
		closer.type = 'button';
		closer.value = btn_close;
		closer.onclick = function()
		{
			var parentdiv = this.parentNode.parentNode;
			if ( aclDisableTransitionFX )
			{
				parentdiv.parentNode.removeChild(parentdiv);
				enlighten(aclDisableTransitionFX, 'invalidjsondarkener');
			}
			else
			{
				$(parentdiv).hide("blind", {}, 1000, function()
					{
						parentdiv.parentNode.removeChild(parentdiv);
							enlighten(aclDisableTransitionFX, 'invalidjsondarkener');
					});
			}
		}
		panel.appendChild(closer);
		
	//
	// put it together
	//
	
		box.appendChild(mainwin);
		box.appendChild(panel);
		
		// add it to the body to allow height/width calculation
		
		box.style.display = 'block';
		box.style.position = 'absolute';
		box.style.zIndex = getHighestZ() + 1;
		domObjChangeOpac(0, box);
		
		var body = document.getElementsByTagName('body')[0];
		body.appendChild(box);
		
		
		// calculate position of the box
		// box should be exactly 640px high, 480px wide
		var top = ( getHeight() / 2 ) - ( $dynano(box).Height() / 2 ) + getScrollOffset();
		var left = ( getWidth() / 2 ) - ( $dynano(box).Width() / 2 );
		console.debug('top = %d, left = %d', top, left);
		box.style.top = top + 'px';
		box.style.left = left + 'px';
		
		// we have width and height, set display to none and reset opacity
		if ( aclDisableTransitionFX )
		{
			domObjChangeOpac(100, box);
			box.style.display = 'block';
		}
		else
		{
			box.style.display = 'none';
			domObjChangeOpac(100, box);
			
			setTimeout(function()
				{
					$(box).show("blind", {}, 1000);
				}, 1000);
		}
	return false;
}

/**
 * Verify that a string is roughly a valid JSON object. Warning - this is only a very cheap syntax check.
 * @param string
 * @return bool true if JSON is valid
 */

function check_json_response(response)
{
	response = trim(response);
	if ( response.substr(0, 1) == '{' && response.substr(response.length - 1, 1) == '}' )
	{
		return true;
	}
	return false;
}

function ajaxEscape(text)
{
	/*
	text = escape(text);
	text = text.replace(/\+/g, '%2B', text);
	*/
	text = window.encodeURIComponent(text);
	return text;
}

/**
 * String functions
 */

// Equivalent to PHP trim() function
function trim(text)
{
	text = text.replace(/^([\s]+)/, '');
	text = text.replace(/([\s]+)$/, '');
	return text;
}

// Equivalent to PHP implode() function
function implode(chr, arr)
{
	if ( typeof ( arr.toJSONString ) == 'function' )
		delete(arr.toJSONString);
	
	var ret = '';
	var c = 0;
	for ( var i in arr )
	{
		if(i=='toJSONString')continue;
		if ( c > 0 )
			ret += chr;
		ret += arr[i];
		c++;
	}
	return ret;
}

function form_fetch_field(form, name)
{
	var fields = form.getElementsByTagName('input');
	if ( fields.length < 1 )
		return false;
	for ( var i = 0; i < fields.length; i++ )
	{
		var field = fields[i];
		if ( field.name == name )
			return field;
	}
	return false;
}

function get_parent_form(o)
{
	if ( !o.parentNode )
		return false;
	if ( o.tagName == 'FORM' )
		return o;
	var p = o.parentNode;
	while(true)
	{
		if ( p.tagName == 'FORM' )
			return p;
		else if ( !p )
			return false;
		else
			p = p.parentNode;
	}
}

/**
 * Return a DOMElement that uses a sprite image.
 * @param string Path to sprite image
 * @param int Width of resulting image
 * @param int Height of resulting image
 * @param int X offset
 * @param int Y offset
 * @return object HTMLImageElement
 */

function gen_sprite(path, width, height, xpos, ypos)
{
	var image = document.createElement('img');
	image.src = cdnPath + '/images/spacer.gif';
	image.width = String(width);
	image.height = String(height);
	image.style.backgroundImage = 'url(' + path + ')';
	image.style.backgroundRepeat = 'no-repeat';
	xpos = ( xpos == 0 ) ? '0' : '-' + String(xpos);
	ypos = ( ypos == 0 ) ? '0' : '-' + String(ypos);
	image.style.backgroundPosition = ypos + 'px ' + xpos + 'px';
	
	return image;
}

/**
 * The same as gen_sprite but generates HTML instead of a DOMElement.
 * @param string Path to sprite image
 * @param int Width of resulting image
 * @param int Height of resulting image
 * @param int X offset
 * @param int Y offset
 * @return object HTMLImageElement
 */

function gen_sprite_html(path, width, height, xpos, ypos)
{
	var html = '<img src="' + scriptPath + '/images/spacer.gif" width="' + width + '" height="' + height + '" ';
	xpos = ( xpos == 0 ) ? '0' : '-' + String(xpos);
	ypos = ( ypos == 0 ) ? '0' : '-' + String(ypos);
	html += 'style="background-image: url(' + path + '); background-repeat: no-repeat; background-position: ' + ypos + 'px ' + xpos + 'px;"';
	html += ' />';
	
	return html;
}

function findParentForm(o)
{
	return get_parent_form(o);
}

function domObjChangeOpac(opacity, id)
{
	if ( !id )
		return false;
	
	var object = id.style;
	object.opacity = (opacity / 100);
	object.MozOpacity = (opacity / 100);
	object.KhtmlOpacity = (opacity / 100);
	object.filter = "alpha(opacity=" + opacity + ")";
}

function getScrollOffset(el)
{
	var position;
	var s = el || self;
	el = el || document;
	if ( el.scrollTop )
	{
		position = el.scrollTop;
	}
	else if (s.pageYOffset)
	{
		position = self.pageYOffset;
	}
	else if (document.documentElement && document.documentElement.scrollTop)
	{
		position = document.documentElement.scrollTop;
	}
	else if (document.body)
	{
		position = document.body.scrollTop;
	}
	return position;
}

function setScrollOffset(offset)
{
	window.scroll(0, offset);
}

// Function to fade classes info-box, warning-box, error-box, etc.

function fadeInfoBoxes()
{
	var divs = new Array();
	d = document.getElementsByTagName('div');
	j = 0;
	for(var i in d)
	{
		if ( !d[i] )
			continue;
		if ( !d[i].tagName )
			continue;
		if(d[i].className=='info-box' || d[i].className=='error-box' || d[i].className=='warning-box' || d[i].className=='question-box')
		{
			divs[j] = d[i];
			j++;
		}
	}
	if(divs.length < 1) return;
	load_component('fat');
	for(i in divs)
	{
		if(!divs[i].id) divs[i].id = 'autofade_'+Math.floor(Math.random() * 100000);
		switch(divs[i].className)
		{
			case 'info-box':
			default:
				from = '#3333FF';
				break;
			case 'error-box':
				from = '#FF3333';
				break;
			case 'warning-box':
				from = '#FFFF33';
				break;
			case 'question-box':
				from = '#33FF33';
				break;
		}
		Fat.fade_element(divs[i].id,30,2000,from,Fat.get_bgcolor(divs[i].id));
	}
}

addOnloadHook(fadeInfoBoxes);

// Alpha fades

function opacity(id, opacStart, opacEnd, millisec)
{
		var object = document.getElementById(id);
		domOpacity(object, opacStart, opacEnd, millisec);
}

var opacityDOMCache = {};
function domOpacity(obj, opacStart, opacEnd, millisec) {
		//speed for each frame
		var speed = Math.round(millisec / 100);
		var timer = 0;
		
		// unique ID for this animation
		var uniqid = Math.floor(Math.random() * 1000000);
		opacityDOMCache[uniqid] = obj;

		//determine the direction for the blending, if start and end are the same nothing happens
		if(opacStart > opacEnd) {
				for(i = opacStart; i >= opacEnd; i--) {
						setTimeout("if ( opacityDOMCache["+uniqid+"] ) { var obj = opacityDOMCache["+uniqid+"]; domObjChangeOpac(" + i + ",obj) }",(timer * speed));
						timer++;
				}
		} else if(opacStart < opacEnd) {
				for(i = opacStart; i <= opacEnd; i++)
						{
						setTimeout("if ( opacityDOMCache["+uniqid+"] ) { var obj = opacityDOMCache["+uniqid+"]; domObjChangeOpac(" + i + ",obj); }",(timer * speed));
						timer++;
				}
		}
		setTimeout("delete(opacityDOMCache["+uniqid+"]);",(timer * speed));
}

function abortFades()
{
	opacityDOMCache = {};
}

// change the opacity for different browsers
function changeOpac(opacity, id)
{
	var object = document.getElementById(id);
	return domObjChangeOpac(opacity, object);
}

// draw a white ajax-ey "loading" box over an object
function whiteOutElement(el)
{
	var top = $dynano(el).Top();
	var left = $dynano(el).Left();
	var width = $dynano(el).Width();
	var height = $dynano(el).Height();
	
	var blackout = document.createElement('div');
	// using fixed here allows modal windows to be blacked out
	blackout.style.position = ( el.style.position == 'fixed' ) ? 'fixed' : 'absolute';
	blackout.style.top = top + 'px';
	blackout.style.left = left + 'px';
	blackout.style.width = width + 'px';
	blackout.style.height = height + 'px';
	
	blackout.style.backgroundColor = '#FFFFFF';
	domObjChangeOpac(60, blackout);
	var background = ( $dynano(el).Height() < 48 ) ? 'url(' + scriptPath + '/images/loading.gif)' : 'url(' + scriptPath + '/includes/clientside/tinymce/themes/advanced/skins/default/img/progress.gif)';
	blackout.style.backgroundImage = background;
	blackout.style.backgroundPosition = 'center center';
	blackout.style.backgroundRepeat = 'no-repeat';
	blackout.style.zIndex = getHighestZ() + 2;
	
	var body = document.getElementsByTagName('body')[0];
	body.appendChild(blackout);
	
	return blackout;
}

/**
 * Take a div generated by whiteOutElement() and report success using the glossy "check" graphic. Sets the image, then
 * briefly fades in, then fades out and destroys the box so as to re-allow control over the underlying element
 */

function whiteOutReportSuccess(whitey, nodestroy_mp)
{
	whiteOutDestroyWithImage(whitey, cdnPath + '/images/check.png', nodestroy_mp);
}

function whiteOutReportFailure(whitey, nodestroy_mp)
{
	if ( typeof(nodestroy_mp) == undefined )
		nodestroy_mp = true;
		
	whiteOutDestroyWithImage(whitey, cdnPath + '/images/checkbad.png', nodestroy_mp);
}

function whiteOutDestroyWithImage(whitey, image, nodestroy_mp)
{
	// fade the status indicator in and then out
	whitey.style.backgroundImage = 'url(' + image + ')';
	if ( whitey.isMiniPrompt && !nodestroy_mp )
	{
		setTimeout(function()
			{
				whiteOutDestroyOnMiniPrompt(whitey);
			}, 500);
		return true;
	}
	if ( aclDisableTransitionFX )
	{
		domObjChangeOpac(80, whitey);
	}
	else
	{
		domOpacity(whitey, 60, 80, 500);
		setTimeout(function()
			{
				domOpacity(whitey, 60, 0, 500);
			}, 750);
	}
	setTimeout(function()
		{
			if ( whitey )
				if ( whitey.parentNode )
					whitey.parentNode.removeChild(whitey);
		}, 1250);
}

/**
 * Whites out a form and disables all buttons under it. Useful for onsubmit functions.
 * @example
 <code>
 <form action="foo" onsubmit="whiteOutForm(this);">
 </code>
 * @param object Form object
 * @return object Whiteout div
 */

function whiteOutForm(form)
{
	if ( !form.getElementsByTagName )
		return false;
	
	// disable all buttons
	var buttons = form.getElementsByTagName('input');
	for ( var i = 0; i < buttons.length; i++ )
	{
		if ( buttons[i].type == 'button' || buttons[i].type == 'submit' || buttons[i].type == 'image' )
		{
			buttons[i].disabled = 'disabled';
			// ... but also make a hidden element to preserve any flags
			var clone = buttons[i].cloneNode(true);
			clone.type = 'hidden';
			clone.disabled = false;
			console.debug(clone);
			form.appendChild(clone);
		}
	}
	var buttons = form.getElementsByTagName('button');
	for ( var i = 0; i < buttons.length; i++ )
	{
		buttons[i].disabled = 'disabled';
		// ... but also make a hidden element to preserve any flags
		if ( buttons[i].name )
		{
			var clone = document.createElement('input');
			clone.type = 'hidden';
			clone.name = buttons[i].name;
			clone.value = ( buttons[i].value ) ? buttons[i].value : '';
			form.appendChild(clone);
		}
	}
	
	return whiteOutElement(form);
}

// other DHTML functions

function fetch_offset(obj)
{
	var left_offset = obj.offsetLeft;
	var top_offset = obj.offsetTop;
	while ((obj = obj.offsetParent) != null) {
		left_offset += obj.offsetLeft;
		top_offset += obj.offsetTop;
	}
	return { 'left' : left_offset, 'top' : top_offset };
}

function fetch_dimensions(o) {
	var w = o.offsetWidth;
	var h = o.offsetHeight;
	return { 'w' : w, 'h' : h };
}

function findParentForm(o)
{
	if ( o.tagName == 'FORM' )
		return o;
	while(true)
	{
		o = o.parentNode;
		if ( !o )
			return false;
		if ( o.tagName == 'FORM' )
			return o;
	}
	return false;
}

function bannerOn(text)
{
	darken(true);
	var thediv = document.createElement('div');
	thediv.className = 'mdg-comment';
	thediv.style.padding = '0';
	thediv.style.marginLeft = '0';
	thediv.style.position = 'absolute';
	thediv.style.display = 'none';
	thediv.style.padding = '4px';
	thediv.style.fontSize = '14pt';
	thediv.id = 'mdgDynamic_bannerDiv_'+Math.floor(Math.random() * 1000000);
	thediv.innerHTML = text;
	
	var body = document.getElementsByTagName('body');
	body = body[0];
	body.appendChild(thediv);
	body.style.cursor = 'wait';
	
	thediv.style.display = 'block';
	dim = fetch_dimensions(thediv);
	thediv.style.display = 'none';
	bdim = { 'w' : getWidth(), 'h' : getHeight() };
	so = getScrollOffset();
	
	var left = (bdim['w'] / 2) - ( dim['w'] / 2 );
	
	var top  = (bdim['h'] / 2);
	top  = top - ( dim['h'] / 2 );
	
	top = top + so;
	
	thediv.style.top  = top  + 'px';
	thediv.style.left = left + 'px';
	
	thediv.style.display = 'block';
	
	return thediv.id;
}

function bannerOff(id)
{
	e = document.getElementById(id);
	if(!e) return;
	e.innerHTML = '';
	e.style.display = 'none';
	var body = document.getElementsByTagName('body');
	body = body[0];
	body.style.cursor = 'default';
	enlighten(true);
}

function disableUnload(message)
{
	if(typeof message != 'string') message = 'You may want to save your changes first.';
	window._unloadmsg = message;
	window.onbeforeunload = function(e)
	{
		if ( !e )
			e = window.event;
		e.returnValue = window._unloadmsg;
	}
}

function enableUnload()
{
	window._unloadmsg = null;
	window.onbeforeunload = null;
}

/**
 * Gets the highest z-index of all divs in the document
 * @return integer
 */
function getHighestZ()
{
	z = 0;
	var divs = document.getElementsByTagName('div');
	for(var i = 0; i < divs.length; i++)
	{
		if ( divs[i].style.zIndex > z && divs[i].style.display != 'none' )
			z = divs[i].style.zIndex;
	}
	return parseInt(z);
}

var shift = false;
function isKeyPressed(event)
{
	if (event.shiftKey==1)
	{
		shift = true;
	}
	else
	{
		shift = false;
	}
}

function moveDiv(div, newparent)
{
	var backup = div;
	var oldparent = div.parentNode;
	oldparent.removeChild(div);
	newparent.appendChild(backup);
}

var busyBannerID;
function goBusy(msg)
{
	if(!msg) msg = 'Please wait...';
	body = document.getElementsByTagName('body');
	body = body[0];
	body.style.cursor = 'wait';
	busyBannerID = bannerOn(msg);
}

function unBusy()
{
	body = document.getElementsByTagName('body');
	body = body[0];
	body.style.cursor = 'default';
	bannerOff(busyBannerID);
}

function setAjaxLoading()
{
	if ( document.getElementById('ajaxloadicon') )
	{
		document.getElementById('ajaxloadicon').src=ajax_load_icon;
	}
}

function unsetAjaxLoading()
{
	if ( document.getElementById('ajaxloadicon') )
	{
		document.getElementById('ajaxloadicon').src=cdnPath + '/images/spacer.gif';
	}
}

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 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 eraseCookie(name) {createCookie(name,"",-1);}

/*
 * AJAX login box (experimental)
 * Moved / rewritten in login.js
 */

// Included only for API-compatibility
function ajaxPromptAdminAuth(call_on_ok, level)
{
	ajaxLoginInit(call_on_ok, level);
}

/**
 * Insert a DOM object _after_ the specified child.
 * @param object Parent node
 * @param object Node to insert
 * @param object Node to insert after
 */

function insertAfter(parent, baby, bigsister)
{
	try
	{
		if ( parent.childNodes[parent.childNodes.length-1] == bigsister )
			parent.appendChild(baby);
		else
			parent.insertBefore(baby, bigsister.nextSibling);
	}
	catch(e)
	{
		alert(e.toString());
		if ( window.console )
		{
			// Firebug support
			window.console.warn(e);
		}
	}
}

/**
 * Validates an e-mail address.
 * @param string E-mail address
 * @return bool
 */

function validateEmail(email)
{
	return ( email.match(/^(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*|(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037]*(?:(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037]*)*<[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*(?:,[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*)*:[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)?(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*>)$/) ) ? true : false;
}

/**
 * Validates a username.
 * @param string Username to test
 * @return bool
 */

function validateUsername(username)
{
	var regex = new RegExp('^[^<>&\?\'"%\n\r/]+$', '');
	return ( username.match(regex) ) ? true : false;
}

/*
 * Utility functions, moved from windows.js
 */

function getHeight() {
	var myHeight = 0;
	if( typeof( window.innerWidth ) == 'number' ) {
		myHeight = window.innerHeight;
	} else if( document.documentElement &&
			( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
		myHeight = document.documentElement.clientHeight;
	} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
		myHeight = document.body.clientHeight;
	}
	return myHeight;
}

function getWidth() {
	var myWidth = 0;
	if( typeof( window.innerWidth ) == 'number' ) {
		myWidth = window.innerWidth;
	} else if( document.documentElement &&
			( document.documentElement.clientWidth || document.documentElement.clientWidth ) ) {
		myWidth = document.documentElement.clientWidth;
	} else if( document.body && ( document.body.clientWidth || document.body.clientWidth ) ) {
		myWidth = document.body.clientWidth;
	}
	return myWidth;
}

/**
 * Sanitizes a page URL string so that it can safely be stored in the database.
 * @param string Page ID to sanitize
 * @return string Cleaned text
 */

function sanitize_page_id(page_id)
{
	// Remove character escapes
	page_id = dirtify_page_id(page_id);

	var regex = new RegExp('[A-Za-z0-9\\[\\]\./:;\(\)@_-]', 'g');
	pid_clean = page_id.replace(regex, 'X');
	var pid_dirty = [];
	for ( var i = 0; i < pid_clean.length; i++ )
		pid_dirty[i] = pid_clean.substr(i, 1);

	for ( var i = 0; i < pid_dirty.length; i++ )
	{
		var chr = pid_dirty[i];
		if ( chr == 'X' )
			continue;
		var cid = chr.charCodeAt(0);
		cid = cid.toString(16).toUpperCase();
		if ( cid.length < 2 )
		{
			cid = '0' + cid;
		}
		pid_dirty[i] = "." + cid;
	}
	
	var pid_chars = [];
	for ( var i = 0; i < page_id.length; i++ )
		pid_chars[i] = page_id.substr(i, 1);
	
	var page_id_cleaned = '';

	for ( var id in pid_chars )
	{
		var chr = pid_chars[id];
		if ( pid_dirty[id] == 'X' )
			page_id_cleaned += chr;
		else
			page_id_cleaned += pid_dirty[id];
	}
	
	return page_id_cleaned;
}

/**
 * Removes character escapes in a page ID string
 * @param string Page ID string to dirty up
 * @return string
 */

function dirtify_page_id(page_id)
{
	// First, replace spaces with underscores
	page_id = page_id.replace(/ /g, '_');

	var matches = page_id.match(/\.[A-Fa-f0-9][A-Fa-f0-9]/g);
	
	if ( matches != null )
	{
		for ( var i = 0; i < matches.length; i++ )
		{
			var match = matches[i];
			var byt = (match.substr(1)).toUpperCase();
			var code = eval("0x" + byt);
			var regex = new RegExp('\\.' + byt, 'g');
			page_id = page_id.replace(regex, String.fromCharCode(code));
		}
	}
	
	return page_id;
}

/*
		the getElementsByClassName function I pilfered from this guy.  It's
		a useful function that'll return any/all tags with a specific css class.

		Written by Jonathan Snook, http://www.snook.ca/jonathan
		Add-ons by Robert Nyman, http://www.robertnyman.com
		
		Modified to match all elements that match the class name plus an integer after the name
		This is used in Enano to allow sliding sidebar widgets that use their own CSS
*/
function getElementsByClassName(oElm, strTagName, strClassName)
{
		// first it gets all of the specified tags
		var arrElements = (strTagName == "*" && document.all) ? document.all : oElm.getElementsByTagName(strTagName);
		
		// then it sets up an array that'll hold the results
		var arrReturnElements = new Array();

		// some regex stuff you don't need to worry about
		strClassName = strClassName.replace(/\-/g, "\\-");

		var oRegExp = new RegExp("(^|\\s)" + strClassName + "([0-9]*)(\\s|$)");
		var oElement;
		
		// now it iterates through the elements it grabbed above
		for(var i=0; i<arrElements.length; i++)
		{
				oElement = arrElements[i];

				// if the class matches what we're looking for it ads to the results array
				if(oElement.className.match(oRegExp))
				{
						arrReturnElements.push(oElement);
				}
		}

		// then it kicks the results back to us
		return (arrReturnElements)
}

/**
 * Equivalent to PHP's in_array function.
 */

function in_array(needle, haystack)
{
	for(var i in haystack)
	{
		if(haystack[i] == needle) return i;
	}
	return false;
}

/**
 * Equivalent of PHP's time()
 * @return int
 */

function unix_time()
{
	return parseInt((new Date()).getTime()/1000);
}


// dropdown.js

/*
 * The jBox menu system. Written by Dan Fuhry and licensed under the GPL.
 */

// Cache of DOM and event objects, used in setTimeout() calls due to scope rules
var jBoxObjCache = new Object();

// Cache of "correct" heights for unordered list objects used in submenus. Helps the animation routine know what height it's aiming for.
var jBoxMenuHeights = new Object();

// Blocks animations from running if there's already an animation going on the same object
var jBoxSlideBlocker = new Object();

// Switch to enable or disable jBox slide animation
var jBox_slide_enable = true;

// Speed at which the menus should slide open. 1 to 100 or -1 to disable.
// Setting this higher than 100 will cause an infinite loop in the browser.
// Default is 80 - anything higher than 90 means exponential speed increase
var slide_speed = 80;

// Inertia value to start with
// Default is 0
var inertia_base = 0;

// Value added to inertia_base on each frame - generally 1 to 3 is good, with 1 being slowest animation
// Default is 1
var inertia_inc  = 1;

// Opacity that menus should fade to. 1 to 100 or -1 to disable fades. This only works if the slide effect is also enabled.
// Default is 100
var jBox_opacity = 100;

// Adds the jBox CSS to the HTML header. Called on window onload.
var jBoxInit = function()
{
	setTimeout('jBoxBatchSetup();', 200);
}
addOnloadHook(jBoxInit);

// Initializes each menu.
function jBoxBatchSetup()
{
	if ( KILL_SWITCH )
		return false;
	var menus = document.getElementsByClassName('div', 'menu_nojs');
	if ( menus.length > 0 )
	{
		for ( var i in menus )
		{
			if ( typeof(menus[i]) != 'object')
				continue; // toJSONString() compatibility
			jBoxSetup(menus[i]);
		}
	}
}

// Initializes a div with a jBox menu in it.
function jBoxSetup(obj)
{
	$dynano(obj).addClass('menu');
	removeTextNodes(obj);
	
	var html = document.getElementsByTagName('html')[0];
	var direction = typeof(html.dir) != 'undefined' ? html.dir : 'ltr';
	
	for ( var i = 0; i < obj.childNodes.length; i++ )
	{
		/* normally this would be done in about 2 lines of code, but javascript is so picky..... */
		if ( obj.childNodes[i] )
		{
			if ( obj.childNodes[i].tagName )
			{
				if ( obj.childNodes[i].tagName == 'A' )
				{
					// if ( is_Safari ) alert('It\'s an A: '+obj);
					if ( obj.childNodes[i].nextSibling )
					{
						// alert("Next sibling: " + obj.childNodes[i].nextSibling);
						if ( obj.childNodes[i].nextSibling.tagName )
						{
							if ( obj.childNodes[i].nextSibling.tagName == 'UL' || ( obj.childNodes[i].nextSibling.tagName.toLowerCase() == 'div' && obj.childNodes[i].nextSibling.className == 'submenu' ) )
							{
								// Calculate height
								var ul = obj.childNodes[i].nextSibling;
								domObjChangeOpac(0, ul);
								ul.style.display = 'block';
								ul.style.zIndex = getHighestZ() + 2;
								var links = ul.getElementsByTagName('a');
								for ( var j = 0; j < links.length; j++ )
								{
									links[j].onmouseup = function()
									{
										var ul = this;
										while ( ul.tagName != 'UL' && ul.tagName != 'DIV' && ul.tagName != 'BODY' )
											ul = ul.parentNode;
										if ( ul.tagName == 'BODY' )
											return false;
										jBoxHideMenu(ul.previousSibling, ul);
									}
								}
								var dim = fetch_dimensions(ul);
								if ( !ul.id )
									ul.id = 'jBoxmenuobj_' + Math.floor(Math.random() * 10000000);
								jBoxMenuHeights[ul.id] = parseInt(dim['h']) - 2; // subtract 2px for border width
								
								// this is a little bit of a hack
								var should_be_right = ( direction == 'ltr' && $dynano(ul).hasClass('jbox_right') ) || ( direction == 'rtl' && !$dynano(ul).hasClass('jbox_right') );
								
								if ( ( direction == 'ltr' && dim['w'] + $dynano(ul).Left() > getWidth() ) || should_be_right )
								{
									$dynano(ul).addClass('jbox_right');
									ul.jbox_width = $dynano(ul).Width();
								}
								else
								{
									$dynano(ul).rmClass('jbox_right');
								}
								
								ul.style.display = 'none';
								domObjChangeOpac(100, ul);
								
								// Setup events
								obj.childNodes[i].onmouseover = function()  { jBoxOverHandler(this); };
								obj.childNodes[i].onmouseout = function(e)  { jBoxOutHandler(this, e); };
								obj.childNodes[i].nextSibling.onmouseout = function(e)  { jBoxOutHandler(this, e); };
								if ( is_iPhone )
								{
									obj.childNodes[i].onclick = function()  { jBoxOverHandler(this); return false; };
								}
							}
						}
					}
				}
			}
		}
	}
}

// Called when user hovers mouse over a submenu
function jBoxOverHandler(obj)
{
	// if ( is_Safari )
	//   alert('Safari and over');
	// Random ID used to track the object to perform on
	var seed = Math.floor(Math.random() * 1000000);
	jBoxObjCache[seed] = obj;
	
	// Sleep for a (little more than a tenth of a) second to see if the user really wants the menu to expand
	setTimeout('if(isOverObj(jBoxObjCache['+seed+'], false, false)) jBoxOverHandlerBin(jBoxObjCache['+seed+']);', 150);
}

// Displays a menu.
function jBoxOverHandlerBin(obj)
{
	var others = obj.parentNode.getElementsByTagName('ul');
	for ( var i in others )
	{
		if(typeof(others[i]) == 'object')
		{
			others[i].style.display = 'none';
			$dynano(others[i].previousSibling).rmClass('liteselected');
		}
	}
	var others = obj.parentNode.getElementsByTagName('div');
	for ( var i in others )
	{
		if(typeof(others[i]) == 'object')
		{
			if ( others[i].className == 'submenu' )
			{
				others[i].style.display = 'none';
				$dynano(others[i].previousSibling).rmClass('liteselected');
			}
		}
	}
	if(obj.nextSibling.tagName.toLowerCase() == 'ul' || ( obj.nextSibling.tagName.toLowerCase() == 'div' && obj.nextSibling.className == 'submenu' ))
	{
		$dynano(obj).addClass('liteselected');
		//obj.className = 'liteselected';
		var ul = obj.nextSibling;
		var dim = fetch_dimensions(obj);
		var off = fetch_offset(obj);
		var dimh = parseInt(dim['h']);
		var offtop = parseInt(off['top']);
		var top = dimh + offtop;
		
		if ( $dynano(ul).hasClass('jbox_right') )
		{
			left = $dynano(obj).Left() + $dynano(obj).Width() - ul.jbox_width; // ( link left + link width ) - ul width
		}
		else
		{
			left = off['left'];
		}
		if ( jBox_slide_enable )
		{
			domObjChangeOpac(0, ul);
		}
		ul.style.left = left + 'px';
		ul.style.top = top + 'px';
		ul.style.clip = 'rect(auto,auto,auto,auto)';
		ul.style.overflow = 'visible';
		ul.style.display = 'block';
		if ( jBox_slide_enable )
		{
			slideOut(ul);
		}
		else
		{
			domObjChangeOpac(100, ul);
		}
	}
}

function jBoxOutHandler(obj, event)
{
	var seed = Math.floor(Math.random() * 1000000);
	var seed2 = Math.floor(Math.random() * 1000000);
	jBoxObjCache[seed] = obj;
	jBoxObjCache[seed2] = event;
	setTimeout('jBoxOutHandlerBin(jBoxObjCache['+seed+'], jBoxObjCache['+seed2+']);', 750);
}

function jBoxOutHandlerBin(obj, event)
{
	var caller = obj.tagName.toLowerCase();
	if(caller == 'a')
	{
		a = obj;
		ul = obj.nextSibling;
	}
	else if(caller == 'ul' || caller == 'div')
	{
		a = obj.previousSibling;
		ul = obj;
	}
	else
	{
		return false;
	}
	
	if (!isOverObj(a, false, event) && !isOverObj(ul, true, event))
	{
		jBoxHideMenu(a, ul);
	}
	
	return true;
}

function jBoxHideMenu(a, ul)
{
	$dynano(a).rmClass('liteselected');
		
	if ( jBox_slide_enable )
	{
		slideIn(ul);
	}
	else
	{
		ul.style.display = 'none';
	}
}

// Slide an element downwards until it is at full height.
// First parameter should be a DOM object with style.display = block and opacity = 0.

var sliderobj = new Object();

function slideOut(obj)
{
	if ( jBoxSlideBlocker[obj.id] )
		return false;
	
	jBoxSlideBlocker[obj.id] = true;
	
	if ( slide_speed == -1 )
	{
		obj.style.display = 'block';
		return false;
	}
	
	var currentheight = 0;
	var targetheight = jBoxMenuHeights[obj.id];
	var inertiabase = inertia_base;
	var inertiainc = inertia_inc;
	slideStep(obj, 0);
	domObjChangeOpac(100, obj);
	obj.style.overflow = 'hidden';
	
	// Don't edit past here
	var timercnt = 0;
	
	var seed = Math.floor(Math.random() * 1000000);
	sliderobj[seed] = obj;
	
	var framecnt = 0;
	
	while(true)
	{
		framecnt++;
		timercnt += ( 100 - slide_speed );
		inertiabase += inertiainc;
		currentheight += inertiabase;
		if ( currentheight > targetheight )
			currentheight = targetheight;
		setTimeout('slideStep(sliderobj['+seed+'], '+currentheight+', '+targetheight+');', timercnt);
		if ( currentheight >= targetheight )
			break;
	}
	timercnt = timercnt + ( 100 - slide_speed );
	setTimeout('jBoxSlideBlocker[sliderobj['+seed+'].id] = false;', timercnt);
	var opacstep = jBox_opacity / framecnt;
	var opac = 0;
	var timerstep = 0;
	domObjChangeOpac(0, obj);
	while(true)
	{
		timerstep += ( 100 - slide_speed );
		opac += opacstep;
		setTimeout('domObjChangeOpac('+opac+', sliderobj['+seed+']);', timerstep);
		if ( opac >= jBox_opacity )
			break;
	}
}

function slideIn(obj)
{
	if ( obj.style.display != 'block' )
		return false;
	
	if ( jBoxSlideBlocker[obj.id] )
		return false;
	
	jBoxSlideBlocker[obj.id] = true;
	
	var targetheight = 0;
	var dim = fetch_dimensions(obj);
	var currentheight = jBoxMenuHeights[obj.id];
	var origheight = currentheight;
	var inertiabase = inertia_base;
	var inertiainc = inertia_inc;
	domObjChangeOpac(100, obj);
	obj.style.overflow = 'hidden';
	
	// Don't edit past here
	var timercnt = 0;
	
	var seed = Math.floor(Math.random() * 1000000);
	sliderobj[seed] = obj;
	
	var framecnt = 0;
	
	for(var j = 0;j<100;j++) // while(true)
	{
		framecnt++;
		timercnt = timercnt + ( 100 - slide_speed );
		inertiabase = inertiabase + inertiainc;
		currentheight = currentheight - inertiabase;
		if ( currentheight < targetheight )
			currentheight = targetheight;
		setTimeout('slideStep(sliderobj['+seed+'], '+currentheight+');', timercnt);
		if ( currentheight <= targetheight )
			break;
	}
	timercnt += ( 100 - slide_speed );
	setTimeout('sliderobj['+seed+'].style.display="none";sliderobj['+seed+'].style.height="'+origheight+'px";jBoxSlideBlocker[sliderobj['+seed+'].id] = false;', timercnt);
	
	var opacstep = jBox_opacity / framecnt;
	var opac = jBox_opacity;
	var timerstep = 0;
	domObjChangeOpac(100, obj);
	while(true)
	{
		timerstep += ( 100 - slide_speed );
		opac -= opacstep;
		setTimeout('domObjChangeOpac('+opac+', sliderobj['+seed+']);', timerstep);
		if ( opac <= 0 )
			break;
	}
	
}

function slideStep(obj, height, maxheight)
{
	obj.style.height = height + 'px';
	//obj.style.clip = 'rect(3px,auto,'+maxheight+'px,auto)';
	obj.style.overflow = 'hidden';
	//obj.style.clip = 'rect('+height+'px,0px,'+maxheight+'px,auto);';
}

function isOverObj(obj, bias, event)
{
	var fieldUL = new Object();
	var dim = fetch_dimensions(obj);
	var off = fetch_offset(obj);
	fieldUL['top'] = off['top'];
	fieldUL['left'] = off['left'];
	fieldUL['right'] = off['left'] + dim['w'];
	fieldUL['bottom'] = off['top'] + dim['h'];
	
	var mouseY_local = mouseY + getScrollOffset();
	
	// document.getElementById('debug').innerHTML = '<br />Mouse: x: '+mouseX+', y:' + mouseY + '<br />' + document.getElementById('debug').innerHTML;
	
	if(bias)
	{
		if ( ( mouseX < fieldUL['left'] + 2 || mouseX > fieldUL['right']  - 5 ) ||
 				( mouseY_local < fieldUL['top']  - 2 || mouseY_local > fieldUL['bottom'] - 2 ) )
		{
 			return false;
		}
	}
	else
	{
		if ( ( mouseX < fieldUL['left'] || mouseX > fieldUL['right']  ) ||
 				( mouseY_local < fieldUL['top']  || mouseY_local > fieldUL['bottom'] ) )
 			return false;
	}
 		
	return true;
}

function jBoxGarbageCollection(e)
{
	setMousePos(e);
	var menus = document.getElementsByClassName('div', 'menu');
	if ( menus.length > 0 )
	{
		for ( var i in menus )
		{
			if ( typeof(menus[i]) != 'object')
				continue; // toJSONString() compatibility
			var uls = menus[i].getElementsByTagName('ul');
			if ( uls.length > 0 )
			{
				for ( var j = 0; j < uls.length; j++ )
				{
					if ( !isOverObj(uls[j], false, e) )
					{
						$dynano(uls[j].previousSibling).rmClass('liteselected');
						//uls[j].style.display = 'none';
						slideIn(uls[j]);
					}
				}
			}
			var uls = getElementsByClassName(menus[i], 'divs', 'submenu');
			if ( uls.length > 0 )
			{
				for ( var j = 0; j < uls.length; j++ )
				{
					if ( !isOverObj(uls[j], false, e) )
					{
						$dynano(uls[j].previousSibling).rmClass('liteselected');
						//uls[j].style.display = 'none';
						slideIn(uls[j]);
					}
				}
			}
		}
	}
}

document.onclick = jBoxGarbageCollection;

var getElementsByClassName = function(parent, type, cls) {
	if(!type)
		type = '*';
	ret = new Array();
	if ( !parent )
		return ret;
	el = parent.getElementsByTagName(type);
	for ( var i = 0; i < el.length; i++ )
	{
		if ( typeof(el[i]) != 'object')
			continue; // toJSONString() compatibility
		if(el[i].className)
		{
			if(el[i].className.indexOf(' ') > 0)
			{
				classes = el[i].className.split(' ');
			}
			else
			{
				classes = new Array();
				classes.push(el[i].className);
			}
			if ( in_array(cls, classes) )
				ret.push(el[i]);
		}
	}
	return ret;
}

document.getElementsByClassName = function(type, cls) {
	return getElementsByClassName(document, type, cls);
}

function setMousePos(event)
{
	if(IE)
	{
		if(!event)
		{
			event = window.event;
		}
		clX = event.clientX;
		if ( document.body )
			sL  = document.body.scrollLeft;
		else
			sL  = 0;
		mouseX = clX + sL;
		mouseY = event.clientY + ( document.body ? document.body.scrollTop : 0 );
		return;
	}
	if( typeof(event.clientX) == 'number' )
	{
		mouseX = event.clientX;
		mouseY = event.clientY;
		return;
	}
	else if( typeof(event.layerX) == 'number' )
	{
		mouseX = event.layerX;
		mouseY = event.layerY;
		return;
	}
	else if( typeof(event.offsetX) == 'number' )
	{
		mouseX = event.offsetX;
		mouseY = event.offsetY;
		return;
	}
	else if( typeof(event.screenX) == 'number' )
	{
		mouseX = event.screenX;
		mouseY = event.screenY;
		return;
	}
	else if( typeof(event.x) == 'number' )
	{
		mouseX = event.x;
		mouseY = event.y;
		return;
	}
}

document.onmousemove = function(e)
{
	setMousePos(e);
};

function removeTextNodes(obj)
{
	if(obj)
	{
		if(typeof(obj.tagName) != 'string' || ( String(obj) == '[object Text]' && is_Safari ) )
		{
			if ( ( obj.nodeType == 3 && obj.data.match(/^([\s]*)$/ig) ) ) //  || ( typeof(obj.innerHTML) == undefined && is_Safari ) ) 
			{
				obj.parentNode.removeChild(obj);
				return;
			}
		}
		if(obj.firstChild)
		{
			for(var i = 0; i < obj.childNodes.length; i++)
			{
				removeTextNodes(obj.childNodes[i]);
			}
		}
	}
}



// json.js

/*
		json.js
		2007-03-20

		All of the code contained within this file is released into
		the public domain. Optionally, you may distribute this code
		under the terms of the GNU General Public License as well
		(public domain licensing allows this).
		
*/

function toJSONString(input)
{
	if ( window.JSON )
	{
		return window.JSON.stringify(input);
	}
	var m = {
					'\b': '\\b',
					'\t': '\\t',
					'\n': '\\n',
					'\f': '\\f',
					'\r': '\\r',
					'"' : '\\"',
					'\\': '\\\\'
					};
	var t = typeof(input);
	switch(t)
	{
		case 'string':
			if (/["\\\x00-\x1f]/.test(input))
			{
					return '"' + input.replace(/([\x00-\x1f\\"])/g, function(a, b)
						{
							var c = m[b];
							if (c) {
									return c;
							}
							c = b.charCodeAt();
							return '\\u00' +
									Math.floor(c / 16).toString(16) +
									(c % 16).toString(16);
					}) + '"';
			}
			return '"' + input + '"';
			break;
		case 'array':
			var a = ['['],  
						b,          
						i,          
						l = input.length,
						v;          

				var p = function (s) {

						if (b) {
								a.push(',');
						}
						a.push(s);
						b = true;
				}

				for (i = 0; i < l; i += 1) {
						v = input[i];
						switch (typeof v) {
						case 'object':
							if (v) {
								p(toJSONString(v));
							} else {
								p("null");
							}
							break;
						case 'array':
						case 'string':
						case 'number':
						case 'boolean':
								p(toJSONString(v));
						}
				}

				a.push(']');
				return a.join('');
			break;
		case 'date':
			var f = function (n)
			{
				return n < 10 ? '0' + n : n;
			}
			return '"' + input.getFullYear() + '-' +
 								f(input.getMonth() + 1) + '-' +
 								f(input.getDate()) + 'T' +
 								f(input.getHours()) + ':' +
 								f(input.getMinutes()) + ':' +
 								f(input.getSeconds()) + '"';
 								
		case 'boolean':
			return String(input);
			break;
		case 'number':
			return isFinite(input) ? String(input) : "null";
			break;
		case 'object':
			var a = ['{'],  
					b,          
					k,          
					v;          

			var p = function (s)
			{
				if (b)
				{
					a.push(',');
				}
				a.push(toJSONString(k), ':', s);
				b = true;
			}

			for (k in input) 
			{
				if (input.hasOwnProperty(k))
				{
					v = input[k];
					switch (typeof v) {

						case 'object':
							if (v) {
								p(toJSONString(v));
							} else {
								p("null");
							}
							break;
						case 'string':
						case 'number':
						case 'boolean':
							p(toJSONString(v));
							break;
					}
				}
			}

			a.push('}');
			return a.join('');
			break;
	}
}

function parseJSON(string, filter)
{
	if ( window.JSON )
	{
		return window.JSON.parse(string);
	}
	
	try {
		if (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.
						test(string))
		{
	
				var j = eval('(' + string + ')');
				if (typeof filter === 'function') {
	
						function walk(k, v)
						{
								if (v && typeof v === 'object') {
										for (var i in v) {
												if (v.hasOwnProperty(i)) {
														v[i] = walk(i, v[i]);
												}
										}
								}
								return filter(k, v);
						}
	
						j = walk('', j);
				}
				return j;
		}
	} catch (e) {
	
	}
	throw new SyntaxError("parseJSON");
}


// sliders.js

// Sliding drawers on the sidebar

// our global vars
// the delay between the slide in/out, and a little inertia

/*
pseudocode:
	oninit():
		i = 0
		for every div with class "slideblock", do
			if ( cookie['mdgSliderState_' || i] == 'closed' )
				div.hide()
				
			div.trigger.addEvent onclick():
				if ( div.hidden )
					div.show()
					cookie['mdgSliderState_' || i] = 'open'
				else
					div.hide()
					cookie['mdgSliderState_' || i] = 'closed
					
			i++
		
*/


var sliders_initted = false;
			
var initSliders = function()
{
	if ( KILL_SWITCH || IE )
		return false;
	
	var divs = getElementsByClassName(document, "div", "slideblock");
	var divs2 = getElementsByClassName(document, "div", "slideblock2");
	for ( var i = 0; i < divs2.length; i++ )
	{
		divs.push(divs2[i]);
	}
	delete divs2;
	
	if ( divs.length < 1 )
		return false;
	
	for ( var i = 0; i < divs.length; i++ )
	{
		var div = divs[i];
		// set a unique id for this slider
		div.metaid = i;
		
		var cookiename = 'mdgSliderState_' + i;
		if ( readCookie(cookiename) == 'closed' )
		{
			div.style.display = 'none';
		}
		
		var el = div.previousSibling;
		if ( !el )
			continue;
		while ( el.tagName == undefined )
		{
			el = el.previousSibling;
			if ( !el )
				break;
		}
		if ( !el )
			continue;
		var toggler = el.getElementsByTagName('a')[0];
		if ( !toggler )
			continue;
		toggler.onclick = function()
		{
			load_component(['jquery', 'jquery-ui']);
			
			var mydiv = this.parentNode.nextSibling;
			while ( mydiv.tagName != 'DIV' )
				mydiv = mydiv.nextSibling;
			if ( mydiv.style.display == 'none' )
			{
				$(mydiv).show('blind');
				var cookiename = 'mdgSliderState_' + mydiv.metaid;
				createCookie(cookiename, 'open', 365);
			}
			else
			{
				$(mydiv).hide('blind');
				var cookiename = 'mdgSliderState_' + mydiv.metaid;
				createCookie(cookiename, 'closed', 365);
			}
			
			return false;
		}
	}
}

addOnloadHook(initSliders);



// tinymce-init.js

//
// TinyMCE support
//

// Check tinyMCE to make sure its init is finished
var initTinyMCE = function(e)
{
	if ( typeof(tinyMCE_GZ) == 'object' )
	{
		if ( !KILL_SWITCH && !DISABLE_MCE )
		{
			tinyMCE_GZ.init(enano_tinymce_gz_options, function()
				{
					tinyMCE.init(enano_tinymce_options);
				});
			tinymce_initted = true;
		}
	}
};

// editor options
if ( document.getElementById('mdgCss') )
{
	var css_url = document.getElementById('mdgCss').href;
}
else
{
	var css_url = scriptPath + '/includes/clientside/css/enano_shared.css';
}

var do_popups = ( is_Safari ) ? '' : ',inlinepopups';
var _skin = ( typeof(tinymce_skin) == 'string' ) ? tinymce_skin : 'default';
var tinymce_initted = false;

var html = document.getElementsByTagName('html')[0];
var direction = typeof(html.dir) != 'undefined' ? html.dir : 'ltr';

var enano_tinymce_options = {
	mode : "none",
	plugins : 'table,save,safari,pagebreak,style,layer,advhr,insertdatetime,searchreplace,spellchecker,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,wordcount' + do_popups,
	theme : 'advanced',
	skin : _skin,
	theme_advanced_resize_horizontal : false,
	theme_advanced_resizing : true,
	theme_advanced_toolbar_location : "top",
	theme_advanced_toolbar_align : "left",
	theme_advanced_buttons1 : "save,|,bold,italic,underline,strikethrough,|,spellchecker,|,justifyleft,justifycenter,justifyright,justifyfull,|,forecolor,backcolor,|,formatselect,|,fontselect,fontsizeselect",
	theme_advanced_buttons3_add_before : "tablecontrols,separator",
	theme_advanced_buttons3_add_after : "|,fullscreen",
	theme_advanced_statusbar_location : 'bottom',
	noneditable_noneditable_class : 'mce_readonly',
	content_css : css_url,
	spellchecker_rpc_url : scriptPath + '/includes/clientside/tinymce/plugins/spellchecker/rpc.php',
	directionality : direction
};

var enano_tinymce_gz_options = {
	plugins : 'table,save,safari,pagebreak,style,layer,advhr,insertdatetime,searchreplace,spellchecker,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras' + do_popups,
	themes : 'advanced',
	languages : 'en',
	disk_cache : true,
	debug : false
};

// load the script

if ( !KILL_SWITCH && !DISABLE_MCE )
{
	var uri = scriptPath + '/includes/clientside/tinymce/tiny_mce_gzip.js?327';
	var sc = document.createElement('script');
	sc.src = uri;
	sc.type = 'text/javascript';
	var head = document.getElementsByTagName('head')[0];
	head.appendChild(sc);
}


// preformat.js

//
// Add the wrappers for preformatted tags within content.
//

addOnloadHook(function()
	{
		preformat_process_all();
	});

function preformat_process_all()
{
	var aec = document.getElementById('ajaxEditContainer');
	if ( !aec )
		return false;
	var pres = aec.getElementsByTagName('pre');
	for ( var i = 0; i < pres.length; i++ )
	{
		if ( pres[i].hasButtonPanel )
			continue;
		pres[i].hasButtonPanel = true;
		
		var btnp = document.createElement('div');
		btnp.mypre = pres[i];
		btnp.className = 'preformat-panel';
		btnp.appendChild(document.createTextNode($lang.get('onpage_pre_lbl_code')));
		btnp.appendChild(document.createTextNode(' <'));
		var a_sel = document.createElement('a');
		a_sel.href = '#';
		a_sel.onclick = function()
			{
				preformat_handle_select_click(this.parentNode);
				return false;
			};
		a_sel.appendChild(document.createTextNode($lang.get('onpage_pre_btn_select')));
		btnp.appendChild(a_sel);
		btnp.appendChild(document.createTextNode('> <'));
		var a_pop = document.createElement('a');
		a_pop.href = '#';
		a_pop.onclick = function()
			{
				preformat_handle_popup_click(this.parentNode);
				return false;
			};
		a_pop.appendChild(document.createTextNode($lang.get('onpage_pre_btn_popup')));
		btnp.appendChild(a_pop);
		btnp.appendChild(document.createTextNode('>'));
		pres[i].parentNode.insertBefore(btnp, pres[i]);
	}
}

function preformat_handle_select_click(btnp)
{
	var pre = btnp.mypre;
	select_element(pre);
}

function preformat_handle_popup_click(btnp)
{
	var pre = btnp.mypre;
	var text = pre.innerHTML;
	var newwin = window.open('about:blank', 'codepopwin', 'width=800,height=600,status=no,toolbars=no,toolbar=no,address=no,scroll=yes');
	newwin.document.open();
	newwin.document.write('<html><head><title>' + $lang.get('onpage_pre_popup_title') + '</title></head><body>');
	newwin.document.write('<pre>' + text + '</pre>');
	newwin.document.write('</body></html>');
	newwin.document.close();
}

function select_element(element)
{
	if (IE)
	{
		// IE
		var range = document.body.createTextRange();
		range.moveToElementText(element);
		range.select();
	}
	else if (is_Gecko || is_Opera)
	{
		// Mozilla/Opera
		var selection = window.getSelection();
		var range = document.createRange();
		range.selectNodeContents(element);
		selection.removeAllRanges();
		selection.addRange(range);
	}
	else if (is_Webkit)
	{
		// Safari (Chrome?)
		var selection = window.getSelection();
		selection.setBaseAndExtent(element, 0, element, 1);
	}
}



// loader.js

// Some final stuff - loader routines, etc.

var onload_complete = false;

function mdgInnerLoader(e)
{
	window.onkeydown = isKeyPressed;
	window.onkeyup = function(e) { isKeyPressed(e); };
	
	if ( typeof(dbx_set_key) == 'function')
	{
		dbx_set_key();
	}
	
	runOnloadHooks(e);
}

// Enano's main init function.
function enano_init(e)
{
	mdgInnerLoader(e);
	
	// we're loaded; set flags to true
	console.info('Enano::JS runtime: system init complete');
	onload_complete = true;
}

// don't init the page if less than IE6
if ( typeof(KILL_SWITCH) == 'boolean' && !KILL_SWITCH )
{
	window.onload = enano_init;
}

