includes/clientside/static/ajax.js
author Dan Fuhry <dan@enanocms.org>
Wed, 29 Dec 2010 13:25:32 -0500
changeset 1332 12286b3ee214
parent 1284 35380c89b5bf
permissions -rw-r--r--
Added some more hooks to the page editing pipeline. It should now be possible to add controls to the page editor, send the data from them out to the server, and process them on the server side.

/*
 * AJAX applets
 */
 
window.ajaxReset = function()
{
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	var ns_id = strToPageID(physical_title);
	if ( ns_id[1] == 'Special' || ns_id[1] == 'Admin' )
		return false;
	enableUnload();
	setAjaxLoading();
	var redir = ( disable_redirect ) ? '&redirect=no' : '';
	ajaxGet(append_sid(scriptPath + '/ajax.php?title=' + physical_title +'&_mode=getpage&noheaders' + redir), function(ajax) {
		// Allow for 404 here, it's generated by the "page not found" error message
		// (even with noheaders specified, probably should be fixed)
		if ( ajax.readyState == 4 && ( ajax.status == 200 || ajax.status == 404 ) ) {
			unsetAjaxLoading();
			document.getElementById('ajaxEditContainer').innerHTML = ajax.responseText;
			selectButtonMajor('article');
			unselectAllButtonsMinor();
			// if we're on a userpage, call the onload function to rebuild the tabs
			if ( typeof(userpage_onload) == 'function' )
			{
				window.userpage_blocks = [];
				userpage_onload();
			}
		}
	});
}

// Miscellaneous AJAX applets

window.ajaxProtect = function(existing_level)
{
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	
	// touch this variable to allow it to be used in child functions
	void(existing_level);
	
	// require re-auth
	if ( auth_level <= USER_LEVEL_MEMBER )
	{
		load_component(['login', 'fadefilter', 'flyin', 'jquery', 'jquery-ui', 'crypto', 'messagebox']);
		ajaxDynamicReauth(function(key)
			{
				ajaxProtect(existing_level);
			}, user_level);
		
		return false;
	}
	
	load_component(['messagebox', 'jquery', 'jquery-ui', 'l10n', 'fadefilter', 'flyin']);
	
	// preload language
	$lang.get('meta_meta');
	
	var mp = miniPrompt(function(parent)
		{
			var icon_full = gen_sprite_html(cdnPath + '/images/protect-icons.png', 22, 22, 0, 0);
			var icon_semi = gen_sprite_html(cdnPath + '/images/protect-icons.png', 22, 22, 22, 0);
			var icon_none = gen_sprite_html(cdnPath + '/images/protect-icons.png', 22, 22, 44, 0);
			
			$(parent).append('<h3>' + $lang.get('onpage_protect_heading') + '</h3>');
			$(parent).append('<p>' + $lang.get('onpage_protect_msg_select_level') + '</p>');
			
			$(parent).append('<div class="protectlevel"><label><input type="radio" id="protect_level_1" name="protect_level" /> ' + icon_full + ' ' + $lang.get('onpage_protect_btn_full') + '</label></div>');
			$(parent).append('<div class="protectlevel_hint" id="protect_level_1_hint">' + $lang.get('onpage_protect_btn_full_hint') + '</div>');
			$(parent).append('<div class="protectlevel"><label><input type="radio" id="protect_level_2" name="protect_level" /> ' + icon_semi + ' ' + $lang.get('onpage_protect_btn_semi') + '</label></div>');
			$(parent).append('<div class="protectlevel_hint" id="protect_level_2_hint">' + $lang.get('onpage_protect_btn_semi_hint') + '</div>');
			$(parent).append('<div class="protectlevel"><label><input type="radio" id="protect_level_0" name="protect_level" /> ' + icon_none + ' ' + $lang.get('onpage_protect_btn_none') + '</label></div>');
			$(parent).append('<div class="protectlevel_hint" id="protect_level_0_hint">' + $lang.get('onpage_protect_btn_none_hint') + '</div>');
			
			$(parent).append('<table class="protectreason"><tr><td valign="top">' + $lang.get('onpage_protect_lbl_reason') + '</td><td><input id="protect_reason" size="30" type="text" /><br /><small>' + $lang.get('onpage_protect_lbl_reason_hint') + '</small></td></tr></table>');
			
			$(parent).append('<p class="buttons"><a class="submitbutton abutton abutton_green" style="font-weight: bold;" href="#" onclick="ajaxProtectSubmit(this); return false;">' + $lang.get('onpage_protect_btn_submit') + '</a> <a class="submitbutton abutton" href="#" onclick="miniPromptDestroy(this); return false;">' + $lang.get('etc_cancel') + '</a></p>');
			
			$('.protectlevel', parent).css('line-height', '22px');
			$('h3', parent).css('text-align', 'center');
			$('.protectlevel_hint', parent)
				.css('font-size', 'smaller')
				.css('margin-left', '52px')
				.hide();
			$('p.buttons', parent).css('margin-top', '15px').css('text-align', 'center');
			
			if ( typeof(existing_level) == 'number' )
			{
				$('#protect_level_' + existing_level, parent).attr('checked', 'checked');
				$('#protect_level_' + existing_level + '_hint', parent).show();
				$('#protect_level_' + existing_level, parent).parent().append(' <small><span style="color: #050; background-color: #eee; padding: 0 4px;">' + $lang.get('onpage_protect_lbl_current') + '</span></small>');
			}
			
			$('input:radio', parent).click(function()
				{
					var mp = miniPromptGetParent(this);
					$('.protectlevel_hint:visible', mp).hide('blind', 150);
					$('#' + this.id + '_hint').show('blind', 150);
					$('#protect_reason').focus();
				});
			$('input:text', parent).keyup(function(e)
				{
					if ( e.keyCode == 13 )
						ajaxProtectSubmit(this);
				});
		});
}

window.ajaxProtectSubmit = function(el)
{
	var mp = miniPromptGetParent(el);
	
	var reason = trim($('#protect_reason', mp).attr('value'));
	if ( reason == '' )
	{
		var oldbg = $('#protect_reason').css('background-color');
		if ( jQuery.fx.off )
		{
			$('#protect_reason').css('background-color', '#a00');
			setTimeout(function()
				{
					$('#protect_reason').css('background-color', oldbg);
				}, 1000);
		}
		else
		{
			$('#protect_reason').css('background-color', '#a00').animate({ backgroundColor: oldbg }, 1000);
		}
		return false;
	}
	
	var level = 0;
	if ( $('#protect_level_1', mp).attr('checked') )
		level = 1;
	if ( $('#protect_level_2', mp).attr('checked') )
		level = 2;
	
	var whitey = whiteOutMiniPrompt(mp);
	$.post(stdAjaxPrefix + '&_mode=protect', { level: level, reason: reason }, function(response, statustext)
		{
			if ( response.success )
			{
				whiteOutReportSuccess(whitey);
				// update protect button
				var btn = $('#tb_ajax_protect_btn').get(0);
				btn.level = level;
				btn.setAttribute('onclick', null);
				btn.onclick = null;
				$(btn).click(function()
					{
						ajaxProtect(this.level);
						return false;
					});
				var status = '';
				switch(level)
				{
					case 1: status = $lang.get('onpage_btn_protect_on'); break;
					case 0: status = $lang.get('onpage_btn_protect_off'); break;
					case 2: status = $lang.get('onpage_btn_protect_semi'); break;
				}
				$('#tb_ajax_protect_status').text(status);
			}
			else
			{
				whiteOutReportFailure(whitey);
				alert($lang.get('page_err_' + response.error));
			}
		}, 'json');
}

window.ajaxRename = function()
{
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	
	// updated - 1.1.4 to use miniPrompt
	load_component(['l10n', 'messagebox', 'flyin', 'fadefilter']);
	miniPrompt(ajaxRenameConstructDialog);
}

var ajaxRenameConstructDialog = function(div)
{
	// title
	var heading = document.createElement('h3');
	heading.appendChild(document.createTextNode($lang.get('ajax_rename_prompt_short')));
	div.appendChild(heading);
	
	// form
	var form = document.createElement('form');
	form.action = 'javascript:void(0);';
	
	// box
	var box = document.createElement('input');
	box.size = '43';
	box.style.width = '100%';
	form.appendChild(box);
	div.appendChild(form);
	
	// notice
	var notice = document.createElement('small');
	notice.appendChild(document.createTextNode($lang.get('ajax_rename_notice')));
	div.appendChild(notice);
	
	// button area
	var btndiv = document.createElement('div');
	btndiv.className = 'mp-buttons';
	
	// buttons
	var btn_submit = document.createElement('a');
	btn_submit.href = '#';
	btn_submit.appendChild(document.createTextNode($lang.get('etc_go')));
	btn_submit.className = 'abutton abutton_green';
	
	var btn_cancel = document.createElement('a');
	btn_cancel.href = '#';
	btn_cancel.appendChild(document.createTextNode($lang.get('etc_cancel')));
	btn_cancel.className = 'abutton';
	
	btndiv.appendChild(btn_submit);
	btndiv.appendChild(document.createTextNode(' | '));
	btndiv.appendChild(btn_cancel);
	div.appendChild(btndiv);
	
	// events
	btn_submit.onclick = function()
	{
		ajaxRenameSubmit(this);
		return false;
	}
	btn_cancel.onclick = function()
	{
		miniPromptDestroy(this);
		return false;
	}
	form.onsubmit = function()
	{
		ajaxRenameSubmit(this);
		return false;
	}
	
	setTimeout(function()
		{
			box.focus();
		}, ( aclDisableTransitionFX ? 200 : 750 ));
}

window.ajaxRenameSubmit = function(obj)
{
	var box = miniPromptGetParent(obj);
	if ( !box )
		return false;
	
	var input = box.getElementsByTagName('input')[0];
	if ( !input )
		return false;
		
	var newname = input.value;
	newname = trim(newname);
	
	if ( newname.length < 1 )
	{
		alert($lang.get('ajax_rename_too_short'));
		return false;
	}
	
	if ( !newname )
	{
		return false;
	}
	
	var innerBox = getElementsByClassName(box, 'div', 'mp-body')[0];
	var whiteout = whiteOutElement(innerBox);
	whiteout.style.width = ( $dynano(whiteout).Width() - 78 ) + 'px';
	whiteout.style.left = ( $dynano(whiteout).Left() + 44 ) + 'px';
	
	ajaxPost(stdAjaxPrefix + '&_mode=rename', 'newtitle=' + ajaxEscape(newname), function(ajax)
		{
			if ( ajax.readyState == 4 && ajax.status == 200 )
			{
				whiteout.parentNode.removeChild(whiteout);
				var response = String(ajax.responseText);
				if ( !check_json_response(response) )
				{
					handle_invalid_json(response);
					return false;
				}
				response = parseJSON(response);
				if ( response.success )
				{
					miniPromptDestroy(box, true);
					ajaxRenameDoClientTransform(newname);
					new MessageBox( MB_OK|MB_ICONINFORMATION, $lang.get('ajax_rename_success_title'), $lang.get('ajax_rename_success_body', { page_name_new: newname }) );
					mb_previously_had_darkener = false;
				}
				else
				{
					var errmsg = $lang.get('page_err_' + response.error);
					alert(errmsg);
				}
			}
		}, true);
}

window.ajaxRenameDoClientTransform = function(newname)
{
	var obj = document.getElementById('h2PageName');
	if ( obj )
	{
		obj.firstChild.nodeValue = newname;
	}
	document.title = newname;
}

window.ajaxDeletePage = function()
{
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	
	// require re-auth
	if ( auth_level <= USER_LEVEL_MEMBER )
	{
		load_component(['login', 'fadefilter', 'flyin', 'jquery', 'jquery-ui', 'crypto', 'messagebox']);
		ajaxDynamicReauth(function(key)
			{
				ajaxDeletePage();
			}, user_level);
		
		return false;
	}
	
	load_component(['l10n', 'messagebox', 'jquery', 'jquery-ui', 'fadefilter', 'flyin']);
	
	// stage 1: prompt for reason and confirmation
	miniPrompt(function(parent)
		{
			// heading/title
			var h3 = document.createElement('h3');
			h3.appendChild(document.createTextNode($lang.get('ajax_delete_header')));
			parent.appendChild(h3);
			
			// "please enter your reason"
			var p1 = document.createElement('p');
			p1.appendChild(document.createTextNode($lang.get('ajax_delete_prompt_reason')));
			parent.appendChild(p1);
			
			// textbox + label thereof
			var p2 = document.createElement('p');
			var tb = document.createElement('input');
			var dl = document.createElement('label');
			
			tb.type = 'text';
			tb.size = '30';
			tb.onkeyup = function(e)
			{
				if ( e )
				if ( e.keyCode )
				if ( e.keyCode == 13 )
				{
					if ( ajaxDeletePageSubmit(this) )
					{
						miniPromptDestroy(this);
					}
				}
				else if ( e.keyCode == 27 )
				{
					miniPromptDestroy(this);
				}
			}
			
			dl.appendChild(document.createTextNode($lang.get('ajax_delete_lbl_reason') + ' '));
			dl.appendChild(tb);
			p2.appendChild(dl);
			parent.appendChild(p2);
			
			// notice underneath
			var p3 = document.createElement('p');
			p3.style.fontSize = 'smaller';
			p3.appendChild(document.createTextNode($lang.get('ajax_delete_msg_confirm')));
			parent.appendChild(p3);
			
			// confirmation + submit/cancel (structure)
			var divleft  = document.createElement('div');
			var divright = document.createElement('div');
			var divclear = document.createElement('div');
			
			divleft.style.cssFloat = 'left';
			divleft.style.styleFloat = 'left';
			
			divright.style.cssFloat = 'right';
			divright.style.styleFloat = 'right';
			
			divclear.style.clear = 'both';
			
			parent.appendChild(divleft);
			parent.appendChild(divright);
			parent.appendChild(divclear);
			
			// confirmation + submit/cancel (controls)
			var cb = document.createElement('input');
			var cl = document.createElement('label');
			
			cb.type = 'checkbox';
			cb.checked = false;
			
			// a bit of a hack here, doesn't seem to work in fx3
			cb.onblur = function(e)
			{
				var parent = this.parentNode.parentNode.parentNode;
				var submitter = parent.getElementsByTagName('a')[0];
				if ( submitter )
					submitter.focus();
			}
			
			cl.appendChild(cb);
			cl.appendChild(document.createTextNode(' ' + $lang.get('ajax_delete_lbl_confirm')));
			divleft.appendChild(cl);
			
			var btn_submit = document.createElement('a');
			btn_submit.className = 'abutton abutton_red';
			btn_submit.href = '#';
			btn_submit.appendChild(document.createTextNode($lang.get('ajax_delete_btn_delete')));
			btn_submit.onclick = function()
			{
				if ( ajaxDeletePageSubmit(this) )
				{
					miniPromptDestroy(this);
				}
				return false;
			}
			
			var btn_cancel = document.createElement('a');
			btn_cancel.className = 'abutton';
			btn_cancel.href = '#';
			btn_cancel.appendChild(document.createTextNode($lang.get('etc_cancel')));
			btn_cancel.onclick = function()
			{
				miniPromptDestroy(this);
				return false;
			}
			
			divright.appendChild(btn_submit);
			divright.appendChild(document.createTextNode(' '));
			divright.appendChild(btn_cancel);
			
			var timeout = ( aclDisableTransitionFX ) ? 10 : 1000;
			setTimeout(function()
				{
					tb.focus();
				}, timeout);
		});
}

window.ajaxDeletePageSubmit = function(prompt_obj)
{
	prompt_obj = miniPromptGetParent(prompt_obj).childNodes[1];
	var inputs = prompt_obj.getElementsByTagName('input');
	var reason = inputs[0];
	var confirm = inputs[1];
	
	if ( trim(reason.value) == '' )
	{
		// flash the background of the reason entry
		$(reason.parentNode).effect("highlight", {}, 1000);
		return false;
	}
	
	if ( !confirm.checked )
	{
		// flash the background of the confirm checkbox
		$(confirm.parentNode).effect("highlight", {}, 1000);
		return false;
	}
	
	prompt_obj.innerHTML = '<img alt="loading" style="display: block; margin: 0 auto;" src="' + cdnPath + '/images/loading-big.gif" />';
	
	// tenemos la confirmación y la razón - borre la página.
	setAjaxLoading();
	ajaxPost(stdAjaxPrefix + '&_mode=deletepage', 'reason=' + ajaxEscape(trim(reason.value)), function(ajax)
		{
			if ( ajax.readyState == 4 && ajax.status == 200 )
			{
				unsetAjaxLoading();
				
				// show the response in the same prompt window
				prompt_obj.style.textAlign = 'center';
				prompt_obj.innerHTML = '';
				
				var p1 = document.createElement('div');
				p1.style.marginBottom = '15px';
				p1.appendChild(document.createTextNode(ajax.responseText));
				prompt_obj.appendChild(p1);
				
				var p2 = document.createElement('p');
				var a = document.createElement('a');
				a.className = 'abutton';
				a.href = '#';
				a.appendChild(document.createTextNode($lang.get('etc_close')));
				a.onclick = function()
				{
					miniPromptDestroy(this);
					window.location.reload();
					return false;
				}
				p2.appendChild(a);
				prompt_obj.appendChild(a);
				
				a.focus();
			}
		});
	
	return true;
}

window.ajaxDelVote = function()
{
	load_component(['l10n', 'messagebox', 'flyin', 'fadefilter']);
	
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	miniPromptMessage({
			title: $lang.get('ajax_delvote_confirm_title'),
			message: $lang.get('ajax_delvote_confirm_body'),
			buttons: [
				{
					text: $lang.get('ajax_delvote_btn_submit'),
					color: 'red',
					style: {
						fontWeight: 'bold'
					},
					onclick: function(e)
					{
						miniPromptDestroy(this);
						setAjaxLoading();
						ajaxGet(stdAjaxPrefix+'&_mode=delvote', function(ajax) {
							if ( ajax.readyState == 4 && ajax.status == 200 ) {
								unsetAjaxLoading();
								alert(ajax.responseText);
							}
						}, true);
					}
				},
				{
					text: $lang.get('etc_cancel'),
					onclick: function(e)
					{
						miniPromptDestroy(this);
					}
				}
			]
		});
}

window.ajaxResetDelVotes = function()
{
	load_component(['l10n', 'messagebox', 'flyin', 'fadefilter']);
	
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	miniPromptMessage({
			title: $lang.get('ajax_delvote_reset_confirm_title'),
			message: $lang.get('ajax_delvote_reset_confirm_body'),
			buttons: [
				{
					text: $lang.get('ajax_delvote_reset_btn_submit'),
					color: 'red',
					style: {
						fontWeight: 'bold'
					},
					onclick: function(e)
					{
						var box = miniPromptGetParent(this);
						var whitey = whiteOutMiniPrompt(box);
						ajaxGet(stdAjaxPrefix+'&_mode=resetdelvotes', function(ajax) {
							if ( ajax.readyState == 4 && ajax.status == 200 ) {
								whiteOutReportSuccess(whitey);
								
								item = document.getElementById('mdgDeleteVoteNoticeBox');
								if(item)
								{
									opacity('mdgDeleteVoteNoticeBox', 100, 0, 1000);
									setTimeout("document.getElementById('mdgDeleteVoteNoticeBox').style.display = 'none';", 1000);
								}
							}
						}, true);
					}
				},
				{
					text: $lang.get('etc_cancel'),
					onclick: function(e)
					{
						miniPromptDestroy(this);
					}
				}
			]
		});
}

// Editing/saving category information
// This was not easy to write, I hope enjoy it, and dang I swear I'm gonna
// find someone to work on just the Javascript part of Enano...

window.ajaxCatEdit = function()
{
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	setAjaxLoading();
	ajaxGet(stdAjaxPrefix+'&_mode=catedit', function(ajax) {
		if ( ajax.readyState == 4 && ajax.status == 200 ) {
			unsetAjaxLoading();
			edit_open = false;
			eval(ajax.responseText);
		}
	});
}

window.ajaxCatSave = function()
{
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	var query = 'hello=';
	$('.catCheck input:checkbox:checked').each(function(i, e)
		{
			query += '&categories[]=' + ajaxEscape($(e).val())
		});
	
	ajaxPost(stdAjaxPrefix+'&_mode=catsave', query, function(ajax) {
		if ( ajax.readyState == 4 && ajax.status == 200 ) {
			unsetAjaxLoading();
			edit_open = false;
			if(ajax.responseText != 'GOOD') alert(ajax.responseText);
			ajaxReset();
		}
	});
}

// History stuff

window.ajaxHistory = function()
{
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	setAjaxLoading();
	ajaxGet(stdAjaxPrefix+'&_mode=histlist', function(ajax) {
		if ( ajax.readyState == 4 && ajax.status == 200 ) {
			unsetAjaxLoading();
			edit_open = false;
			selectButtonMajor('article');
			selectButtonMinor('history');
			document.getElementById('ajaxEditContainer').innerHTML = ajax.responseText;
			buildDiffList();
		}
	});
}

window.ajaxHistView = function(oldid, ttl) {
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	if(!ttl) ttl=title;
	setAjaxLoading();
	ajaxGet(append_sid(scriptPath+'/ajax.php?title='+ttl+'&_mode=getpage&oldid='+oldid), function(ajax) {
		if ( ajax.readyState == 4 && ajax.status == 200 ) {
			unsetAjaxLoading();
			edit_open = false;
			document.getElementById('ajaxEditContainer').innerHTML = ajax.responseText;
		}
	});
}

window.ajaxRollback = function(id) {
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	setAjaxLoading();
	ajaxGet(stdAjaxPrefix+'&_mode=rollback&id='+id, function(ajax) {
		if ( ajax.readyState == 4 && ajax.status == 200 ) {
			unsetAjaxLoading();
			
			var response = String(ajax.responseText + '');
			if ( !check_json_response(response) )
			{
				handle_invalid_json(response);
				return false;
			}
			
			response = parseJSON(response);
			if ( response.success )
			{
				alert( $lang.get('page_msg_rb_success_' + response.action, { dateline: response.dateline }) )
			}
			else
			{
				if ( response.action )
				{
					alert( $lang.get('page_err_' + response.error, { action: response.action }) );
				}
				else
				{
					alert( $lang.get('page_err_' + response.error) );
				}
			}
		}
	});
}

window.ajaxClearLogs = function()
{
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	
	// require re-auth
	if ( auth_level <= USER_LEVEL_MEMBER )
	{
		load_component(['login', 'fadefilter', 'flyin', 'jquery', 'jquery-ui', 'crypto', 'messagebox']);
		ajaxDynamicReauth(function(key)
			{
				ajaxClearLogs();
			}, user_level);
		
		return false;
	}
	
	load_component(['l10n', 'messagebox', 'flyin', 'fadefilter']);
	
	miniPromptMessage({
			title: $lang.get('ajax_clearlogs_confirm_title'),
			message: $lang.get('ajax_clearlogs_confirm_body'),
			buttons: [
				{
					text: $lang.get('ajax_clearlogs_btn_submit'),
					color: 'red',
					style: {
						fontWeight: 'bold'
					},
					onclick: function(e)
					{
						miniPromptDestroy(this);
						setAjaxLoading();
						ajaxGet(stdAjaxPrefix+'&_mode=flushlogs', function(ajax) {
							if ( ajax.readyState == 4 && ajax.status == 200 ) {
								unsetAjaxLoading();
								alert(ajax.responseText);
								window.location.reload();
							}
						});
					}
				},
				{
					text: $lang.get('etc_cancel'),
					onclick: function(e)
					{
						miniPromptDestroy(this);
					}
				}
			]
		});
}

window.buildDiffList = function()
{
	arrDiff1Buttons = getElementsByClassName(document, 'input', 'clsDiff1Radio');
	arrDiff2Buttons = getElementsByClassName(document, 'input', 'clsDiff2Radio');
	var len = arrDiff1Buttons.length;
	if ( len < 1 )
		return false;
	timelist = new Array();
	for ( var i = 0; i < len; i++ )
	{
		timelist.push( arrDiff2Buttons[i].id.substr(6) );
	}
	timelist.push( arrDiff1Buttons[len-1].id.substr(6) );
	delete(timelist.toJSONString);
	for ( var i = 1; i < timelist.length-1; i++ )
	{
		if ( i >= timelist.length ) break;
		arrDiff2Buttons[i].style.display = 'none';
	}
}

window.selectDiff1Button = function(obj)
{
	var this_time = obj.id.substr(6);
	var index = parseInt(in_array(this_time, timelist));
	for ( var i = 0; i < timelist.length - 1; i++ )
	{
		if ( i < timelist.length - 1 )
		{
			var state = ( i < index ) ? 'inline' : 'none';
			var id = 'diff2_' + timelist[i];
			document.getElementById(id).style.display = state;
			
			// alert("Debug:\nIndex: "+index+"\nState: "+state+"\ni: "+i);
		}
	}
}

window.selectDiff2Button = function(obj)
{
	var this_time = obj.id.substr(6);
	var index = parseInt(in_array(this_time, timelist));
	for ( var i = 1; i < timelist.length; i++ )
	{
		if ( i < timelist.length - 1 )
		{
			var state = ( i > index ) ? 'inline' : 'none';
			var id = 'diff1_' + timelist[i];
			document.getElementById(id).style.display = state;
			
			// alert("Debug:\nIndex: "+index+"\nState: "+state+"\ni: "+i);
		}
	}
}

window.ajaxHistDiff = function()
{
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	var id1=false;
	var id2=false;
	for ( i = 0; i < arrDiff1Buttons.length; i++ )
	{
		k = i + '';
		kpp = i + 1;
		kpp = kpp + '';
		if(arrDiff1Buttons[k].checked) id1 = arrDiff1Buttons[k].id.substr(6);
		if(arrDiff2Buttons[k].checked) id2 = arrDiff2Buttons[k].id.substr(6);
	}
	if(!id1 || !id2) { alert('BUG: Couldn\'t get checked radiobutton state'); return; }
	setAjaxLoading();
	ajaxGet(stdAjaxPrefix+'&_mode=pagediff&diff1='+id1+'&diff2='+id2, function(ajax)
		{
			if ( ajax.readyState == 4 && ajax.status == 200 )
			{
				unsetAjaxLoading();
				document.getElementById('ajaxEditContainer').innerHTML = ajax.responseText;
			}
		});
}

// Change the user's preferred style/theme

window.ajaxChangeStyle = function()
{
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	load_component(['l10n', 'fadefilter', 'jquery', 'jquery-ui']);
	
	// force string fetch
	$lang.get('etc_cancel');
	
	// preload some images
	var i1 = new Image();
	i1.src = cdnPath + '/images/loading-big.gif';
	var i2 = new Image();
	i2.src = cdnPath + '/images/check-large.png';
	
	darken(true, 70, 'theme-selector-shade');
	
	$('body').append('<div id="theme-selector-wrapper"><div id="theme-selector-body"><div id="theme-selector-inner"><div class="theme-selector-spinner"></div></div></div></div>');
	$('#theme-selector-wrapper')
		.css('top', String(getScrollOffset()) + 'px')
		.css('left', 0)
		.css('z-index', String( getHighestZ() + 20 ));
	
	$.get(stdAjaxPrefix + '&_mode=theme_list', {}, function(data, status)
		{
			$('#theme-selector-inner .theme-selector-spinner').fadeOut(650);
			$('#theme-selector-body').animate({ width: 728 }, 600, function()
				{
					// avoiding jQuery's fade functions because they insist on toggling display as well
					if ( !aclDisableTransitionFX )
						changeOpac(0, 'theme-selector-inner');
					$('#theme-selector-inner').html('<h3></h3>');
					$('#theme-selector-inner > h3').text($lang.get('ajax_thmsel_lbl_choosetheme'));
					$('#theme-selector-inner').append('<ul></ul>');
					for ( var i = 0; i < data.length; i++ )
					{
						var bgi = data[i].have_thumb ? cdnPath + '/themes/' + data[i].theme_id + '/preview.png' : cdnPath + '/images/themepreview.png';
						var maxheight = getHeight() - 325;
						$('#theme-selector-inner > ul')
							.css('clip', 'rect(0px, auto, auto, 0px)')
							.css('overflow', 'auto')
							.css('max-height', maxheight)
							.append('<li id="theme_' + i + '"><a href="#"><span></span></a></li>');
						$('#theme-selector-inner li#theme_' + i + ' > a')
							.css('background-image', 'url(' + bgi + ')')
							.attr('enano:theme_id', data[i].theme_id);
						$('#theme-selector-inner li#theme_' + i + ' > a > span')
							.text(data[i].theme_name);
					}
					$('#theme-selector-inner').append('<span class="menuclear"></span>');
					$('#theme-selector-inner').append('<div style="padding-top: 40px;"><a class="abutton abutton_green" style="font-size: larger;" href="#" onclick="ajaxChangeStyleClose(); return false;">' + $lang.get('etc_cancel') + '</a></div>');
					
					$('#theme-selector-body').animate({ height: $('#theme-selector-inner').height() + 30 }, 600, function()
						{
							if ( !aclDisableTransitionFX )
								opacity('theme-selector-inner', 0, 100, 750);
						});
					
					$('#theme-selector-inner li a').click(function()
						{
							var theme_id = $(this).attr('enano:theme_id');
							$('span', this).html('&nbsp;').addClass('loading').fadeTo('fast', 0.6)
							$.get(stdAjaxPrefix + '&_mode=get_styles', { theme_id: theme_id }, function(data, status)
								{
									if ( data.length > 1 )
									{
										$('#theme-selector-inner').css('height', $('#theme-selector-inner').height()).fadeOut(600, function()
										{
											var div = document.createElement('div');
											if ( !aclDisableTransitionFX )
												domObjChangeOpac(0, div);
											
											$(div).attr('id', 'theme-selector-style-list').append('<h3></h3>');
											$('h3', div).text($lang.get('ajax_thmsel_lbl_choosestyle'));
											
											for ( var i = 0; i < data.length; i++ )
											{
												$(div).append('<a class="abutton block stylebtn" id="stylebtn_' + i + '" enano:style_id="' + data[i] + '">' + themeid_to_title(data[i]) + '</a>');
											}
											
											$(div).append('<div style="padding-top: 40px;"><a class="abutton abutton_green" style="font-size: larger;" href="#" onclick="ajaxChangeStyleClose(); return false;">' + $lang.get('etc_cancel') + '</a></div>');
											
											if ( !aclDisableTransitionFX )
												changeOpac(0, 'theme-selector-style-list');
											$(this).html(div).show();
											
											$('#theme-selector-body').animate({width: 300, height: $('#theme-selector-style-list').height() + 30}, 300, function()
												{
													if ( !aclDisableTransitionFX )
														opacity('theme-selector-style-list', 0, 100, 500);
												});
											
											$('.stylebtn').click(function()
												{
													ajaxChangeThemeSetLoading();
													$.post(stdAjaxPrefix + '&_mode=change_theme', { theme_id: theme_id, style_id: $(this).attr('enano:style_id') }, function(data, status)
														{
															if ( data.error )
															{
																alert(data.error);
																ajaxChangeStyleClose();
																return false;
															}
															ajaxChangeThemeShowSuccess();
														}, 2000);
													
													return false;
												});
										});
									}
									else
									{
										if ( !data[0] )
										{
											alert('Didn\'t find any CSS files. :-/');
											ajaxChangeStyleClose();
										}
										
										$.post(stdAjaxPrefix + '&_mode=change_theme', { theme_id: theme_id, style_id: data[0] }, function(data, status)
											{
												if ( data.error )
												{
													alert(data.error);
													ajaxChangeStyleClose();
													return false;
												}
												ajaxChangeThemeShowSuccess();
											}, 'json');
									}
								}, 'json');
							return false;
						}); // click function
				}); // animate
		}, 'json'); // get
}

window.ajaxChangeThemeSetLoading = function()
{
	$('#theme-selector-body').animate({width: 130, height: 130});
	$('#theme-selector-inner').empty().html('<div class="theme-selector-spinner"></div>');
}

window.ajaxChangeThemeShowSuccess = function()
{
	if ( aclDisableTransitionFX )
	{
		$('#theme-selector-inner').empty();
	}
	else
	{
		setTimeout(function()
			{
				$('#theme-selector-inner').empty();
			}, 10);
	}
	
	$('#theme-selector-body').animate({width: 400, height: 300 }, 600, function()
			{
				$('#theme-selector-inner').append('<img src="' + cdnPath + '/images/check-large.png" alt=" " style="display: block; margin: 15px auto;" />');
				$('#theme-selector-inner').append('<h3>' + $lang.get('ajax_thmsel_msg_success') + '</h3>');
				$('#theme-selector-inner').append('<div style="padding-top: 20px;"><a class="abutton abutton_green" style="font-size: larger;" href="#" onclick="window.location.reload(); return false;">' + $lang.get('ajax_thmsel_btn_reload') + '</a></div>');
				$('#theme-selector-inner').append('<div style="padding-top: 25px;"><a href="#" style="font-size: smaller;" onclick="ajaxChangeStyleClose(); return false;">' + $lang.get('ajax_thmsel_btn_close') + '</a><br /><small>' + $lang.get('ajax_thmsel_btn_close_hint') + '</small></div>');
				$('#theme-selector-inner').fadeIn();
			});
}

window.ajaxChangeStyleClose = function()
{
	setTimeout(function()
		{
			enlighten(false, 'theme-selector-shade');
			$('#theme-selector-wrapper').fadeOut(500, function()
				{
					$(this).remove();
				});
		}, ( aclDisableTransitionFX ? 0 : 300));
	if ( !aclDisableTransitionFX )
		opacity('theme-selector-inner', 100, 0, 250);
}

function themeid_to_title(id)
{
	if ( typeof(id) != 'string' )
		return false;
	id = id.substr(0, 1).toUpperCase() + id.substr(1);
	id = id.replace(/_/g, ' ');
	id = id.replace(/-/g, ' ');
	return id;
}

window.ajaxSetPassword = function()
{
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	load_component('crypto');
	pass = hex_sha1(document.getElementById('mdgPassSetField').value);
	setAjaxLoading();
	ajaxPost(stdAjaxPrefix+'&_mode=setpass', 'password='+pass, function(ajax)
		{
			unsetAjaxLoading();
			if ( ajax.readyState == 4 && ajax.status == 200 )
			{
				alert(ajax.responseText);
			}
		}, true);
}

window.ajaxDisableEmbeddedPHP = function()
{
	// IE <6 pseudo-compatibility
	if ( KILL_SWITCH )
		return true;
	if ( !confirm($lang.get('ajax_killphp_confirm')) )
		return false;
	var $killdiv = $dynano('php_killer');
	if ( !$killdiv.object )
	{
		alert('Can\'t get kill div object');
		return false;
	}
	$killdiv.object.innerHTML = '<img alt="Loading..." src="' + scriptPath + '/images/loading-big.gif" /><br />Making request...';
	var url = makeUrlNS('Admin', 'Home', 'src=ajax');
	ajaxPost(url, 'act=kill_php', function(ajax) {
			if ( ajax.readyState == 4 && ajax.status == 200 )
			{
				if ( ajax.responseText == '1' )
				{
					var $killdiv = $dynano('php_killer');
					//$killdiv.object.innerHTML = '<img alt="Success" src="' + scriptPath + '/images/error.png" /><br />Embedded PHP in pages has been disabled.';
					$killdiv.object.parentNode.removeChild($killdiv.object);
					var newdiv = document.createElement('div');
					// newdiv.style = $killdiv.object.style;
					newdiv.className = $killdiv.object.className;
					newdiv.innerHTML = '<img alt="Success" src="' + scriptPath + '/images/error.png" /><br />' + $lang.get('ajax_killphp_success');
					$killdiv.object.parentNode.appendChild(newdiv);
					$killdiv.object.parentNode.removeChild($killdiv.object);
				}
				else
				{
					var $killdiv = $dynano('php_killer');
					$killdiv.object.innerHTML = ajax.responseText;
				}
			}
		});
}

var catHTMLBuf = false;

window.ajaxCatToTag = function()
{
	if ( KILL_SWITCH )
		return false;
	setAjaxLoading();
	ajaxGet(stdAjaxPrefix + '&_mode=get_tags', function(ajax)
		{
			if ( ajax.readyState == 4 && ajax.status == 200 )
			{
				unsetAjaxLoading();
				var resptext = String(ajax.responseText + ' ');
				resptext = resptext.substr(0, resptext.length-1);
				if ( resptext.substr(0, 1) != '{' )
				{
					handle_invalid_json(resptext);
					return false;
				}
				var json = parseJSON(resptext);
				var catbox = document.getElementById('mdgCatBox');
				if ( !catbox )
					return false;
				var linkbox = catbox.parentNode.firstChild.firstChild.nextSibling;
				linkbox.firstChild.nodeValue = $lang.get('catedit_catbox_link_showcategorization');
				linkbox.onclick = function() { ajaxTagToCat(); return false; };
				catHTMLBuf = catbox.innerHTML;
				catbox.innerHTML = '';
				catbox.appendChild(document.createTextNode($lang.get('tags_lbl_page_tags')+' '));
				if ( json.tags.length < 1 )
				{
					catbox.appendChild(document.createTextNode($lang.get('tags_lbl_no_tags')));
				}
				for ( var i = 0; i < json.tags.length; i++ )
				{
					catbox.appendChild(document.createTextNode(json.tags[i].name));
					if ( json.tags[i].can_del )
					{
						catbox.appendChild(document.createTextNode(' '));
						var a = document.createElement('a');
						a.appendChild(document.createTextNode('[X]'));
						a.href = '#';
						a._js_tag_id = json.tags[i].id;
						a.onclick = function() { ajaxDeleteTag(this, this._js_tag_id); return false; }
						catbox.appendChild(a);
					}
					if ( ( i + 1 ) < json.tags.length )
						catbox.appendChild(document.createTextNode(', '));
				}
				if ( json.can_add )
				{
					catbox.appendChild(document.createTextNode(' '));
					var addlink = document.createElement('a');
					addlink.href = '#';
					addlink.onclick = function() { try { ajaxAddTagStage1(); } catch(e) { }; return false; };
					addlink.appendChild(document.createTextNode($lang.get('tags_btn_add_tag')));
					catbox.appendChild(addlink);
				}
			}
		});
}

var addtag_open = false;

window.ajaxAddTagStage1 = function()
{
	if ( addtag_open )
		return false;
	var catbox = document.getElementById('mdgCatBox');
	var adddiv = document.createElement('div');
	var text = document.createElement('input');
	var addlink = document.createElement('a');
	addlink.href = '#';
	addlink.onclick = function() { ajaxAddTagStage2(this.parentNode.firstChild.nextSibling.value, this.parentNode); return false; };
	addlink.appendChild(document.createTextNode($lang.get('tags_btn_add')));
	text.type = 'text';
	text.size = '15';
	text.onkeyup = function(e)
	{
		if ( e.keyCode == 13 )
		{
			ajaxAddTagStage2(this.value, this.parentNode);
		}
	}
	
	adddiv.style.margin = '5px 0 0 0';
	adddiv.appendChild(document.createTextNode($lang.get('tags_lbl_add_tag')+' '));
	adddiv.appendChild(text);
	adddiv.appendChild(document.createTextNode(' '));
	adddiv.appendChild(addlink);
	catbox.appendChild(adddiv);
	addtag_open = true;
}

var addtag_nukeme = false;

window.ajaxAddTagStage2 = function(tag, nukeme)
{
	if ( !addtag_open )
		return false;
	if ( addtag_nukeme )
		return false;
	addtag_nukeme = nukeme;
	tag = ajaxEscape(tag);
	setAjaxLoading();
	ajaxPost(stdAjaxPrefix + '&_mode=addtag', 'tag=' + tag, function(ajax)
		{
			if ( ajax.readyState == 4 && ajax.status == 200 )
			{
				unsetAjaxLoading();
				var nukeme = addtag_nukeme;
				addtag_nukeme = false;
				var resptext = String(ajax.responseText + ' ');
				resptext = resptext.substr(0, resptext.length-1);
				if ( resptext.substr(0, 1) != '{' )
				{
					handle_invalid_json(resptext);
					return false;
				}
				var json = parseJSON(resptext);
				var parent = nukeme.parentNode;
				parent.removeChild(nukeme);
				addtag_open = false;
				if ( json.success )
				{
					var node = parent.childNodes[1];
					var insertafter = false;
					var nukeafter = false;
					if ( node.nodeValue == $lang.get('tags_lbl_no_tags') )
					{
						nukeafter = true;
					}
					insertafter = parent.childNodes[ parent.childNodes.length - 3 ];
					// these need to be inserted in reverse order
					if ( json.can_del )
					{
						var a = document.createElement('a');
						a.appendChild(document.createTextNode('[X]'));
						a.href = '#';
						a._js_tag_id = json.tag_id;
						a.onclick = function() { ajaxDeleteTag(this, this._js_tag_id); return false; }
						insertAfter(parent, a, insertafter);
						insertAfter(parent, document.createTextNode(' '), insertafter);
					}
					insertAfter(parent, document.createTextNode(json.tag), insertafter);
					if ( !nukeafter )
					{
						insertAfter(parent, document.createTextNode(', '), insertafter);
					}
					if ( nukeafter )
					{
						parent.removeChild(insertafter);
					}
				}
				else
				{
					alert(json.error);
				}
			}
		});
}

window.ajaxDeleteTag = function(parentobj, tag_id)
{
	var arrDelete = [ parentobj, parentobj.previousSibling, parentobj.previousSibling.previousSibling ];
	var parent = parentobj.parentNode;
	var writeNoTags = false;
	if ( parentobj.previousSibling.previousSibling.previousSibling.nodeValue == ', ' )
		arrDelete.push(parentobj.previousSibling.previousSibling.previousSibling);
	else if ( parentobj.previousSibling.previousSibling.previousSibling.nodeValue == $lang.get('tags_lbl_page_tags') + ' ' )
		arrDelete.push(parentobj.nextSibling);
	
	if ( parentobj.previousSibling.previousSibling.previousSibling.nodeValue == $lang.get('tags_lbl_page_tags') + ' ' &&
 			parentobj.nextSibling.nextSibling.firstChild )
		if ( parentobj.nextSibling.nextSibling.firstChild.nodeValue == $lang.get('tags_btn_add_tag'))
			writeNoTags = true;
		
	ajaxPost(stdAjaxPrefix + '&_mode=deltag', 'tag_id=' + String(tag_id), function(ajax)
		{
			if ( ajax.readyState == 4 && ajax.status == 200 )
			{
				if ( ajax.responseText == 'success' )
				{
					for ( var i = 0; i < arrDelete.length; i++ )
					{
						try
						{
							parent.removeChild(arrDelete[i]);
						} catch(e) {}
					}
					if ( writeNoTags )
					{
						var node1 = document.createTextNode($lang.get('tags_lbl_no_tags'));
						var node2 = document.createTextNode(' ');
						insertAfter(parent, node1, parent.firstChild);
						insertAfter(parent, node2, node1);
					}
				}
				else
				{
					alert(ajax.responseText);
				}
			}
		});
}

window.ajaxTagToCat = function()
{
	if ( !catHTMLBuf )
		return false;
	var catbox = document.getElementById('mdgCatBox');
	if ( !catbox )
		return false;
	addtag_open = false;
	var linkbox = catbox.parentNode.firstChild.firstChild.nextSibling;
	linkbox.firstChild.nodeValue = $lang.get('tags_catbox_link');
	linkbox.onclick = function() { ajaxCatToTag(); return false; };
	catbox.innerHTML = catHTMLBuf;
	catHTMLBuf = false;
}

var keepalive_interval = false;

window.ajaxPingServer = function()
{
	ajaxGet(stdAjaxPrefix + '&_mode=ping', function(ajax)
		{
		});
}

window.ajaxToggleKeepalive = function()
{
	if ( readCookie('admin_keepalive') == '1' )
	{
		createCookie('admin_keepalive', '0', 3650);
		if ( keepalive_interval )
			clearInterval(keepalive_interval);
		var span = document.getElementById('keepalivestat');
		span.firstChild.nodeValue = $lang.get('adm_btn_keepalive_off');
	}
	else
	{
		createCookie('admin_keepalive', '1', 3650);
		if ( !keepalive_interval )
			keepalive_interval = setInterval('ajaxPingServer();', 600000);
		var span = document.getElementById('keepalivestat');
		span.firstChild.nodeValue = $lang.get('adm_btn_keepalive_on');
		ajaxPingServer();
	}
}

var keepalive_onload = function()
{
	if ( readCookie('admin_keepalive') == '1' )
	{
		if ( !keepalive_interval )
			keepalive_interval = setInterval('ajaxPingServer();', 600000);
		var span = document.getElementById('keepalivestat');
		span.firstChild.nodeValue = $lang.get('adm_btn_keepalive_on');
	}
	else
	{
		if ( keepalive_interval )
			clearInterval(keepalive_interval);
		var span = document.getElementById('keepalivestat');
		span.firstChild.nodeValue = $lang.get('adm_btn_keepalive_off');
	}
};

window.aboutKeepAlive = function()
{
	load_component(['messagebox', 'flyin', 'fadefilter']);
	new MessageBox(MB_OK|MB_ICONINFORMATION, $lang.get('user_keepalive_info_title'), $lang.get('user_keepalive_info_body'));
}

window.ajaxUpdateCheck = function(targetelement)
{
	if ( !document.getElementById(targetelement) )
	{
		return false;
	}
	var target = document.getElementById(targetelement);
	target.innerHTML = '';
	var img = document.createElement('img');
	img.src = cdnPath + '/images/loading.gif';
	img.alt = 'Loading...';
	target.appendChild(img);
	ajaxGet(makeUrlNS('Admin', 'Home/updates.xml'), function(ajax)
		{
			if ( ajax.readyState == 4 && ajax.status == 200 )
			{
				var releases = new Array();
				var update_available = false;
				if ( ajax.responseXML == null )
				{
					alert("Error fetching updates list:\n" + ajax.responseText);
					return false;
				}
				if ( ajax.responseXML.firstChild.tagName == 'enano' )
				{
					var enanotag = ajax.responseXML.firstChild;
					for ( var i = 0; i < enanotag.childNodes.length; i++ )
					{
						if ( enanotag.childNodes[i].tagName == 'error' )
						{
							alert(enanotag.childNodes[i].firstChild.nodeValue);
						}
						else if ( enanotag.childNodes[i].tagName == 'latest' )
						{
							// got <latest>
							var latesttag = enanotag.childNodes[i];
							for ( var j = 0; j < latesttag.childNodes.length; j++ )
							{
								var node = latesttag.childNodes[j];
								if ( node.tagName == 'release' )
								{
									var releasedata = new Object();
									for ( var k = 0; k < node.attributes.length; k++ )
									{
										releasedata[node.attributes[k].nodeName] = node.attributes[k].nodeValue;
									}
									releases.push(releasedata);
								}
								else if ( node.tagName == 'haveupdates' )
								{
									update_available = true;
								}
							}
							break;
						}
					}
				}
				else
				{
					return false;
				}
				var thediv = document.getElementById(targetelement);
				thediv.innerHTML = '';
				if ( !thediv )
				{
					return false;
				}
				if ( releases.length > 0 )
				{
					thediv.className = 'tblholder';
					// FIXME: l10n
					if ( update_available )
					{
						var infobox = document.createElement('div');
						infobox.className = 'info-box-mini';
						infobox.appendChild(document.createTextNode('An update for Enano is available. The newest release is highlighted below.'));
						infobox.style.borderWidth = '0';
						infobox.style.margin = '0 0 0 0';
						thediv.appendChild(infobox);
					}
					else
					{
						var infobox = document.createElement('div');
						infobox.className = 'info-box-mini';
						infobox.appendChild(document.createTextNode('No new updates are available. The latest available releases are shown below.'));
						infobox.style.borderWidth = '0';
						infobox.style.margin = '0 0 0 0';
						thediv.appendChild(infobox);
					}
					var table = document.createElement('table');
					table.setAttribute('border', '0');
					table.setAttribute('cellspacing', '1');
					table.setAttribute('cellpadding', '4');
					
					var tr = document.createElement('tr');
					
					var td1 = document.createElement('th');
					var td2 = document.createElement('th');
					var td3 = document.createElement('th');
					var td4 = document.createElement('th');
					
					// FIXME: l10n
					td1.appendChild( document.createTextNode('Release type') );
					td2.appendChild( document.createTextNode('Version') );
					td3.appendChild( document.createTextNode('Code name') );
					td4.appendChild( document.createTextNode('Release notes') );
					
					tr.appendChild(td1);
					tr.appendChild(td2);
					tr.appendChild(td3);
					tr.appendChild(td4);
						
					table.appendChild(tr);
					
					var cls = 'row2';
					
					var j = 0;
					for ( var i in releases )
					{
						j++;
						if ( j > 5 )
							break;
						if ( update_available && j == 1 )
							cls = 'row1_green';
						else
							cls = ( cls == 'row1' ) ? 'row2' : 'row1';
						var release = releases[i];
						var tr = document.createElement('tr');
						
						var td1 = document.createElement('td');
						var td2 = document.createElement('td');
						var td3 = document.createElement('td');
						var td4 = document.createElement('td');
						
						td1.className = cls;
						td2.className = cls;
						td3.className = cls;
						td4.className = cls;
						
						if ( release.tag )
							td1.appendChild( document.createTextNode(release.tag) );
						
						if ( release.version )
							td2.appendChild( document.createTextNode(release.version) );
						
						if ( release.codename )
							td3.appendChild( document.createTextNode(release.codename) );
						
						if ( release.relnotes )
						{
							var a = document.createElement('a');
							a.href = release.relnotes;
							a.appendChild(document.createTextNode('View'));
							td4.appendChild( a );
						}
						
						tr.appendChild(td1);
						tr.appendChild(td2);
						tr.appendChild(td3);
						tr.appendChild(td4);
						
						table.appendChild(tr);
					}
					thediv.appendChild(table);
				}
				else
				{
					thediv.appendChild(document.createTextNode('No releases available.'));
				}
			}
		});
}

window.ajaxPluginAction = function(action, plugin_filename, btnobj, send_confirm)
{
	// if installing, uninstalling, or re-importing, confirm
	if ( action == 'install' || action == 'uninstall' || action == 'reimport' )
	{
		var prompt = miniPrompt(function(div)
			{
				var txtholder = document.createElement('div');
				txtholder.style.textAlign = 'center';
				txtholder.appendChild(document.createTextNode($lang.get('acppl_msg_confirm_' + action)));
				txtholder.appendChild(document.createElement('br'));
				txtholder.appendChild(document.createElement('br'));
				
				// create buttons
				var btn_go = document.createElement('a');
				btn_go.className = 'abutton abutton_red';
				btn_go.href = '#';
				btn_go._action = action;
				btn_go._filename = plugin_filename;
				btn_go._button = btnobj;
				btn_go.appendChild(document.createTextNode($lang.get('acppl_btn_' + action)));
				btn_go.style.fontWeight = 'bold';
				txtholder.appendChild(btn_go);
				
				// space
				txtholder.appendChild(document.createTextNode(' '));
				
				// cancel
				var btn_cancel = document.createElement('a');
				btn_cancel.className = 'abutton abutton_blue';
				btn_cancel.href = '#';
				btn_cancel.appendChild(document.createTextNode($lang.get('etc_cancel')));
				
				txtholder.appendChild(btn_cancel);
				div.appendChild(txtholder);
				
				btn_go.onclick = function()
				{
					ajaxPluginAction(this._action + '_confirm', this._filename, this._button);
					miniPromptDestroy(this);
					return false;
				};
				btn_cancel.onclick = function()
				{
					miniPromptDestroy(this);
					return false;
				};
			});
		return true;
	}
	action = action.replace(/_confirm$/, '');
	// white-out the plugin info box
	if ( btnobj )
	{
		var td = btnobj.parentNode.parentNode.parentNode.parentNode;
		var blackbox = whiteOutElement(td);
	}
	var request = {
			mode: action,
			plugin: plugin_filename
		};
	if ( send_confirm )
	{
		request.install_confirmed = true;
	}
	request = toJSONString(request);
	ajaxPost(makeUrlNS('Admin', 'PluginManager/action.json'), 'r=' + ajaxEscape(request), function(ajax)
		{
			if ( ajax.readyState == 4 && ajax.status == 200 )
			{
				var response = String(ajax.responseText + '');
				if ( !check_json_response(response) )
				{
					handle_invalid_json(response);
					return false;
				}
				response = parseJSON(response);
				if ( blackbox )
				{
					if ( blackbox.parentNode )
					{
						blackbox.parentNode.removeChild(blackbox);
					}
				}
				if ( response.success )
				{
					ajaxPage( namespace_list['Admin'] + 'PluginManager' );
					return true;
				}
				if ( response.need_confirm )
				{
					miniPromptMessage({
							title: $lang.get(response.confirm_title),
							message: $lang.get(response.confirm_body),
							buttons: [
								{
									text: $lang.get('acppl_btn_install'),
									color: 'red',
									style: {
										fontWeight: 'bold'
									},
									onclick: function() {
										ajaxPluginAction(action + '_confirm', plugin_filename, btnobj, true);
										miniPromptDestroy(this);
									}
								},
								{
									text: $lang.get('etc_cancel'),
									color: 'blue',
									onclick: function() {
										miniPromptDestroy(this);
									}
								}
							]
						});
					return true;
				}
				// wait for fade effect to finish its run
				setTimeout(function()
					{
						miniPrompt(function(div)
							{
								if ( blackbox )
								{
									if ( blackbox.parentNode )
									{
										blackbox.parentNode.removeChild(blackbox);
									}
								}
								var txtholder = document.createElement('div');
								txtholder.style.textAlign = 'center';
								txtholder.appendChild(document.createTextNode(response.error));
								txtholder.appendChild(document.createElement('br'));
								txtholder.appendChild(document.createElement('br'));
								
								// close button
								var btn_cancel = document.createElement('a');
								btn_cancel.className = 'abutton abutton_red';
								btn_cancel.href = '#';
								btn_cancel.appendChild(document.createTextNode($lang.get('etc_ok')));
								
								txtholder.appendChild(btn_cancel);
								div.appendChild(txtholder);
								
								btn_cancel.onclick = function()
								{
									miniPromptDestroy(this);
									return false;
								}
							});
					}, 750);
			}
		});
}

window.ajaxReverseDNS = function(o, text)
{
	if(text) var ipaddr = text;
	else var ipaddr = o.innerHTML;
	rDnsObj = o;
	rDnsBannerObj = bannerOn('Retrieving reverse DNS info...');
	ajaxGet(stdAjaxPrefix+'&_mode=rdns&ip='+ipaddr, function(ajax) {
			if ( ajax.readyState == 4 && ajax.status == 200 )
			{
				off = fetch_offset(rDnsObj);
				dim = fetch_dimensions(rDnsObj);
				right = off['left'] + dim['w'];
				top = off['top'] + dim['h'];
				var thediv = document.createElement('div');
				thediv.className = 'info-box';
				thediv.style.margin = '0';
				thediv.style.position = 'absolute';
				thediv.style.top  = top  + 'px';
				thediv.style.display = 'none';
				thediv.style.zIndex = getHighestZ() + 2;
				thediv.id = 'mdgDynamic_rDnsInfoDiv_'+Math.floor(Math.random() * 1000000);
				// FIXME: l10n
				thediv.innerHTML = '<b>Reverse DNS:</b><br />'+ajax.responseText+' <a href="#" onclick="elem = document.getElementById(\''+thediv.id+'\'); elem.innerHTML = \'\'; elem.style.display = \'none\';return false;">Close</a>';
				var body = document.getElementsByTagName('body');
				body = body[0];
				bannerOff(rDnsBannerObj);
				body.appendChild(thediv);
				thediv.style.display = 'block';
				left = fetch_dimensions(thediv);
				thediv.style.display = 'none';
				left = right - left['w'];
				thediv.style.left = left + 'px';
				thediv.style.display = 'block';
				fadeInfoBoxes();
			}
		});
}

window.ajaxGzipCheck = function()
{
	var resultdiv = document.getElementById('gzip_check_result');
	if ( !resultdiv )
		return false;
	
	resultdiv.innerHTML = '<img alt="Loading..." src="' + cdnPath + '/images/loading.gif" />';
	ajaxPost(makeUrlNS('Admin', 'GeneralConfig'), 'act=gzip_check', function(ajax)
		{
			if ( ajax.readyState == 4 && ajax.status == 200 )
			{
				resultdiv.innerHTML = '';
				var response = String(ajax.responseText + '');
				if ( !check_json_response(response) )
				{
					handle_invalid_json(response);
					return false;
				}
				response = parseJSON(response);
				if ( response.error )
				{
					resultdiv.innerHTML = '<div class="error-box-mini">' + response.error + '</div>';
				}
				else
				{
					// probably success.
					resultdiv.innerHTML += response.server_does_it ?
						'<div class="error-box-mini">' + $lang.get('acpgc_field_gzip_check_msg_server_does_it') + '</div>' :
						'<div class="info-box-mini">' + $lang.get('acpgc_field_gzip_check_msg_server_good') + '</div>';
					resultdiv.innerHTML += response.php_supports_gzip ?
						'<div class="info-box-mini">' + $lang.get('acpgc_field_gzip_check_msg_php_good') + '</div>' :
						'<div class="error-box-mini">' + $lang.get('acpgc_field_gzip_check_msg_php_bad') + '</div>';
						
					if ( response.php_supports_gzip && !response.server_does_it )
					{
						resultdiv.innerHTML += '<div class="success-box-mini">' + $lang.get('acpgc_field_gzip_check_msg_success') + '</div>';
					}
					else
					{
						resultdiv.innerHTML += '<div class="error-box-mini">' + $lang.get('acpgc_field_gzip_check_msg_failure') + '</div>';
					}
				}
			}
		});
}

window.ajaxVerifyFilePath = function(input)
{
	input._lastkeyup = new Date();
	// 500ms between keyup and trigger
	setTimeout(function()
		{
			var now = new Date();
			if ( input._lastkeyup.getTime() + 499 < now.getTime() )
			{
				// do the ajaxverify
				ajaxVerifyFilePathReal(input);
			}
		}, 500);
}

window.ajaxVerifyFilePathReal = function(input)
{
	if ( input.nextSibling && input.nextSibling.tagName == 'IMG' )
		input.parentNode.removeChild(input.nextSibling);
	var img = document.createElement('img');
	img.src = cdnPath + '/images/loading.gif';
	img.hspace = '7';
	ajaxPost(makeUrlNS('Admin', 'UploadConfig', 'act=verify_path'), 'path=' + ajaxEscape(input.value), function(ajax)
		{
			if ( ajax.readyState == 4 && ajax.status == 200 )
			{
				img.src = ( ajax.responseText == 'true' ) ? cdnPath + '/images/mini-success.png' : cdnPath + '/images/mini-error.png';
			}
		});
	insertAfter(input.parentNode, img, input);
}