// general constants

var hrefbase = document.location.href.match("^https?://[^/]*(:[0-9]*)?/([^_][^/]*/)*")[0];
document.location.hrefbase = hrefbase;


//////////////////////////////////////////////////////////
// Some utility functions
//////////////////////////////////////////////////////////

function getAllTextNodes(root) {
	var children;
	var	textNodes = new Array();
	children = root.childNodes;
	for(var i=0; i<children.length; i++) {
		var node = children[i];
		if(node.nodeType == 3)
			textNodes.push(node);
		if(node.canHaveHTML) {
			var tmp = textNodes.concat(getAllTextNodes(node));
			textNodes = tmp;
		}
	}
	return textNodes;
}

function getContextNode(textNode) {
	var container;
	for(container=textNode; container && ! container.nodeName.match(/^(BODY|DIV|P|TD|H1|H2|H3|LI|TH)$/); container=container.parentNode);
	return container;
}

function openDialog(url, name, properties, data) {
	var newwindow = window.open(url, name, properties);
	if(newwindow) {
		newwindow.dialogData = data;
	}
}

function addOption(control, value, text) {
	if(!control) return;
	if(!text) text = value;
	var opt = document.createElement('OPTION');
	opt.value = value;
	opt.innerText = text;
	control.appendChild(opt);
	return;
}

function disableElement(node) {
	if(!node) return;
	node.disabled = true;
	if(node.nodeName == 'INPUT')
		node.style.backgroundColor = 'gray';
}

function enableElement(node) {
	if(!node) return;
	node.disabled = false;
	if(node.nodeName == 'INPUT')
		node.style.backgroundColor = 'white';
}

function disableElements(elementType) {
	var nodes = document.getElementsByTagName(elementType);
	for(i=0; i<nodes.length; i++)
		disableElement(nodes[i]);
}

function enableElements(elementType) {
	var nodes = document.getElementsByTagName(elementType);
	for(i=0; i<nodes.length; i++)
		enableElement(nodes[i]);
}

function setStyleRecursive(node, attribute, value) {
	var allnodes = node.getElementsByTagName('*');
	for(var i=0; i < allnodes.length; i++)
		if(allnodes[i].style)
			allnodes[i].style[attribute] = value;
}

function decodeHTMLEntity(entity) {
	// Stip the & and ; if they've been passed
	entity = entity.replace(/[&;]/g,'');

	// Decode numerical entities
	if(entity.search(/^#[0-9]+$/))
		return String.fromCharCode(parseInt(entity.slice(1)));

	// Decode other common entitites
	switch (entity) {
	case 'amp':  return '&';
	case 'nbsp': return ' ';
	case 'gt':   return '>';
	case 'lt':   return '<';
	case 'quot': return '"';
	case 'lsquo','rsquo': return "'";
	case 'ldquo','rdquo': return '"';
	case 'laquo': return String.fromCharCode(171);
	case 'raquo': return String.fromCharCode(187);
	default: return '';
	}
	
}

function togglePanel(toggle, panelID, label, panelIframe) {
	var panel;
	panel=document.getElementById(panelID);
	if(!panel) return;
	if(toggle.collapsed){
		if(panelIframe) panelIframe.style.display = '';
		panel.style.display='';
		toggle.innerHTML='&laquo;<br />&laquo;';
		toggle.title='Hide ' + label;
		document.selection.empty();
		toggle.collapsed=false;
	}
	else {
		if(panelIframe) panelIframe.style.display = 'none';
		panel.style.display='none';
		toggle.innerHTML='&raquo;<br />&raquo;';
		toggle.title='Show ' + label;
		document.selection.empty();
		toggle.collapsed=true;
	}
}

//////////////////////////////////////////////////////////
// objects
//////////////////////////////////////////////////////////

function hierarchy_obj(id, name)
{
	this.id = id;
	this.name = name;
	this.children = new Array();
	this.find   = _hierarchyFind;

	function _hierarchyFind(needle){
		var obj;
		if(this.id == needle) return this;
		for(var child in this.children) {
			if(this.debug) {
				alert(child);
				alert(this.children[child]);
				alert(this.children[child].find);
			}
			if (obj = this.children[child].find(needle))
				return obj;
		}
		return null;
	}
}

function page_obj(page_id, parent_page_id, name, name_width, type, active, access, meta_description, nice_url, meta_keywords, place, banner_jpeg, banner_flash, nav_image_id, nav_active_image_id, nav_rollover_image_id, banner_image_id, title, blurb, html_title, owner)
{
	this.page_id = page_id;
	this.parent_page_id = parent_page_id;
	this.name = name;
	this.name_width = name_width;
	this.type = type;
	this.active = active;
	this.access = access;
	this.meta_description = meta_description;
	this.nice_url = nice_url;
	this.meta_keywords = meta_keywords;
	this.html_title = html_title;
	this.title = title;
	this.blurb = blurb;
	this.place = place;
	this.banner_jpeg = banner_jpeg;
	this.banner_flash = banner_flash;
	this.nav_image_id = nav_image_id;
	this.nav_active_image_id = nav_active_image_id;
	this.nav_rollover_image_id = nav_rollover_image_id;
	this.banner_image_id = banner_image_id;
	this.owner = owner;
}

function content_obj(content_id, pagev_id, section, type, place, display_date, title, text, text_colour, text_bgcolour, content_html, content_plain, url, image_id, date_create, date_modified, date_start, date_end)
{
	this.content_id = content_id;
	this.pagev_id = pagev_id;
	this.section = section;
	this.type = type;
	this.place = place;
	this.display_date = display_date;
	this.title = title;
	this.text = text;
	this.text_colour = text_colour;
	this.text_bgcolour = text_bgcolour;
	this.content_html = content_html;
	this.content_plain = content_plain;
	this.url = url;
	this.image_id = image_id;
	this.date_create = date_create;
	this.date_modified = date_modified;
	this.date_start = date_start;
	this.date_end = date_end;
}

function image_obj(image_id, directory, file, size, date_modified, width, height)
{
	this.image_id = image_id;
	this.directory = directory;
	this.file = file;
	this.size = size;
	this.date_modified = date_modified;
	this.width = width;
	this.height = height;
}

function user_obj(user_id, name, nicename, email, password, administrator, type)
{
	this.user_id = user_id;
	this.name = name;
	this.nicename = nicename;
	this.email = email;
	this.password = password ? password : '';
	this.administrator = administrator ? administrator : 'n';
	this.type = type ? type : 'refract';
}

function workflow_obj(workflow_id, workflow_name, locked) {
	this.workflow_id = workflow_id;
	this.workflow_name = workflow_name;
	this.locked = locked;
}

function role_obj(role_id, role_name, permissions) {
	this.role_id = role_id;
	this.role_name = role_name;
	this.permissions = permissions;
}

function banner_obj(banner_id, banner_image_id, url)
{
	this.banner_id = banner_id;
	this.banner_image_id = banner_image_id;
	this.url = url;
}

function file_obj(directory, file, size, date_modified)
{
	this.directory = directory;
	this.file = file;
	this.size = size;
	this.date_modified = date_modified;
}

function location_obj() {
	this.dummy = true;
}

function region_obj() {
	this.dummy = true;
}


//////////////////////////////////////////////////////////
// interface functions
//////////////////////////////////////////////////////////

function showFileManager(mode) {
	var scriptname

	if(refract.administrator == 'y') {
		setdisplaymode('filemanager');
		switch(mode) {
			case 'image':
				scriptname = 'medialibrary.asp';
				break;
			default:
				scriptname = 'filemanager.asp';
		}
		window.top.frames['dymamite_filemanager_list'].document.location.replace('_common/' + scriptname + '?command=folderlist');
		window.top.frames['dymamite_filemanager_form_iframe'].document.location.replace('_common/blank.html');
	}
	else {
		setdisplaymode('noaccess');
	}
}




//////////////////////////////////////////////////////////
// dialog functions
//////////////////////////////////////////////////////////

function dialog_areyousure(message)
{
//*** This function is currently on the back burner. Maybe we'll re-instate it if we re-skin the interface
//*** For now it's just a wrapper around the javascript "confirm" function 

	return confirm(message);
/*

	var xin=new Array(), xout;

	xin['message'] = message;

	xout = window.showModalDialog(hrefbase + '_common/dialog/areyousure.asp', xin, 'dialogWidth: 382px; dialogHeight: 137px; status: no;');

	return xout['ok'] == 'yes';
*/
}

function dialog_cellproperties(xin)
{
	var xout;

	xout = window.showModalDialog(hrefbase + '_common/dialog/cellproperties.asp', xin, 'dialogWidth: 510px; dialogHeight: 200px; status: no;');

	if (xout['ok'] == 'yes')
	{
		xin['width'] = xout['width'];
		xin['height'] = xout['height'];
		xin['rowspan'] = xout['rowspan'];
		xin['colspan'] = xout['colspan'];
		xin['align'] = xout['align'];
		xin['valign'] = xout['valign'];
		xin['bgcolor'] = xout['bgcolor'];
	}

	return xout['ok'] == 'yes';
}

function dialog_colourchooser(heading, colour)
{
	var xin=new Array(), xout;

	xin['heading'] = heading;
	xin['colour'] = colour;

	xout = window.showModalDialog(hrefbase + '_common/dialog/colourchooser.asp', xin, 'dialogWidth: 250px; dialogHeight: 275px; status: no;');

	if (xout['ok'] == 'yes')
		return xout['colour'];
	else
		return colour;
}

function dialog_getline(heading, text)
{
	var xin=new Array(), xout;

	xin['heading'] = heading;
	xin['text'] = text;

	xout = window.showModalDialog(hrefbase + '_common/dialog/getline.asp', xin, 'dialogWidth: 415px; dialogHeight: 200px; status: no;');

	if (xout['ok'] == 'yes')
		return xout['text'];
	else
		return text;
}

function dialog_htmlimagechooser(xin)
{
	var xout;

	xout = window.showModalDialog(hrefbase + '_common/dialog/htmlimagechooser.asp', xin, 'dialogWidth: 452px; dialogHeight: 550px; status: no;');

	if (xout['ok'] == 'yes')
	{
		xin['url'] = xout['url'];
		xin['align'] = xout['align'];
		xin['alt'] = xout['alt'];
		xin['caption'] = xout['caption'];
	}

	return xout['ok'] == 'yes';
}

function dialog_imagechooser(heading, image_id)
{
	var xin=new Array(), xout;

	xin['heading'] = heading;
	xin['image_id'] = image_id;

	xout = window.showModalDialog(hrefbase + '_common/dialog/imagechooser.asp', xin, 'dialogWidth: 432px; dialogHeight: 381px; status: no;');

	if (xout['ok'] == 'yes')
		return xout['image_id'];
	else
		return image_id;
}

function dialog_filechooser(heading, filename) {
	var xin=new Array(), xout;

	xin['refract'] = refract;
	xin['heading'] = heading;
	xin['filename'] = filename;

	xout = window.showModalDialog(hrefbase + '_common/dialog/filechooser.asp', xin, 'dialogWidth: 700px; dialogHeight: 500px; status: no;');

	if (xout['ok'] == 'yes') {
		return xout['filename'];
	}
	else {
		return filename;
	}
}

function dialog_linkproperties(xin)
{
	var xout;

	xin['page_id'] = (window.page_id ? window.page_id : 0);

	xout = window.showModalDialog(hrefbase + '_common/dialog/linkproperties.asp', xin, 'dialogWidth: 483px; dialogHeight: 350px; status: no;');

	if (xout['ok'] == 'yes')
	{
		xin['href'] = xout['href'];
		xin['rel']  = xout['rel'];
	}

	return xout['ok'] == 'yes';
}

function dialog_rowproperties(xin)
{
	var xout;

	xout = window.showModalDialog(hrefbase + '_common/dialog/rowproperties.asp', xin, 'dialogWidth: 275px; dialogHeight: 180px; status: no;');

	if (xout['ok'] == 'yes')
	{
		xin['height'] = xout['height'];
		xin['bgcolor'] = xout['bgcolor'];
	}

	return xout['ok'] == 'yes';
}

function dialog_showmessage(message)
{
//*** This function is currently on the back burner. Maybe we'll re-instate it if we re-skin the interface
//*** For now it's just a wrapper around the javascript "alert" function 
	return alert(message);
/*

	var xin=new Array(), xout;

	xin['message'] = message;

	window.showModalDialog(hrefbase + '_common/dialog/showmessage.asp', xin, 'dialogWidth: 382px; dialogHeight: 137px; status: no;');
*/
}

function dialog_tableproperties(xin)
{
	var xout;

	xout = window.showModalDialog(hrefbase + '_common/dialog/tableproperties.asp', xin, 'dialogWidth: 460px; dialogHeight: 260px; status: no;');

	if (xout['ok'] == 'yes')
	{
		xin['width'] = xout['width'];
		xin['cellpadding'] = xout['cellpadding'];
		xin['rows'] = xout['rows'];
		xin['columns'] = xout['columns'];
		xin['type'] = xout['type'];
		xin['caption'] = xout['caption'];
	}

	return xout['ok'] == 'yes';
}

function dialog_textedit(xin, required)
{
	var xout;

	// Correct any undefined values
	if(!required) required = false;

	xout = window.showModalDialog(hrefbase + '_common/dialog/textedit.asp?required=' + required.toString(), xin, 'dialogWidth: 606px; dialogHeight: 425px; status: no;');

	if (xout['ok'] == 'yes') {
		xin['text'] = xout['text'];
		return true;
	}
	else {
		return false;
	}
}


// dialog helper
function dialog_colourchooser_helper(heading, id)
{
	var xin=new Array(), xout;

	xin['heading'] = heading;
	xin['colour'] = document.getElementById(id).value;

	xout = window.showModalDialog(hrefbase + '_common/dialog/colourchooser.asp', xin, 'dialogWidth: 226px; dialogHeight: 265px; status: no;');

	if (xout['ok'] == 'yes')
		document.getElementById(id).value = xout['colour'];
}

function dialog_imagechooser_helper(heading, base)
{
	var xin=new Array(), xout;

	//alert('general.js/dialog_imagechooser_helper: heading=[' + heading + '], base=[' + base + ']');

	xin['heading'] = heading;
	xin['image_id'] = document.getElementById(base + '_image_id').value;

	xout = window.showModalDialog(hrefbase + '_common/dialog/imagechooser.asp', xin, 'dialogWidth: 550px; dialogHeight: 381px; status: no;');

	if (xout['ok'] == 'yes')
	{
		document.getElementById(base + '_image_id').value = xout['image_id'];
		document.getElementById(base + '_image_name').value = xout['name'];
	}
}

function dialog_linkproperties_helper(heading, base)
{
	var xin=new Array(), xout;

	xin['heading'] = heading;
	xin['href'] = document.getElementById(base + '_url').value;
	xin['refract'] = refract;
	xin['anchors'] = new Array();
	xin['page_id'] = (window.page_id ? window.page_id : 0);

	xout = window.showModalDialog(hrefbase + '_common/dialog/linkproperties.asp', xin, 'dialogWidth: 500px; dialogHeight: 341px; status: no;');

	if (xout['ok'] == 'yes')
		document.getElementById(base + '_url').value = xout['href'];
}

function dialog_linkproperties_helper2(heading, base)
{

	var xin=new Array(), xout;

	xin['heading'] = heading;
	xin['href'] = document.getElementById(base).value;
	xin['refract'] = refract;
	xin['anchors'] = new Array();
	xin['page_id'] = (window.page_id ? window.page_id : 0);

	xout = window.showModalDialog(hrefbase + '_common/dialog/linkproperties.asp', xin, 'dialogWidth: 500px; dialogHeight: 341px; status: no;');

	if (xout['ok'] == 'yes')
		document.getElementById(base).value = xout['href'];
}


//////////////////////////////////////////////////////////
// general functions
//////////////////////////////////////////////////////////

function isdigit()
{
	return ((event.keyCode >= 48) && (event.keyCode <= 57))
}

window.count = '';
function unselectable(root)
{
	var i, node, children;

	//alert('general.js/unselectable: root.tagName=[' + root.tagName + ']');

	if(!root) return;
	root.unselectable = true;
	if(!root.childNodes) return;
	children = root.childNodes;
	for (i=0; i<children.length; i++)
	{
		node = children[i];
		if(node.nodeType != 1) continue;
		if (node.className == 'alwaysSelectable' || node.tagName == 'SELECT' || node.tagName == 'INPUT' || node.tagName == 'TEXTAREA' || (node.nodeType == 1 && node.tagName == 'DIV' && node.contentEditable == 'true')) {
			node.unselectable = false;
		}
		else {window.count += node.nodeName + '\n';
			node.unselectable = true;
			unselectable(node);
		}
	}
}

// Shuffles any DOM node up or down amongst its siblings
function shuffle(dir, node)
{
	var tmp;
	if(!node) return;
	if (dir == 'up')
	{
		tmp = node;
		while((tmp = tmp.previousSibling) && (tmp.nodeType != 1));
		if (tmp)
			tmp.insertAdjacentElement('beforeBegin', node);
		else
			dialog_showmessage('This is already at the top.');
	}
	else if (dir == 'down')
	{
		tmp = node;
		while((tmp = tmp.nextSibling) && (tmp.nodeType != 1));
		if (tmp)
			tmp.insertAdjacentElement('afterEnd', node);
		else
			dialog_showmessage('This is already at the bottom.');
	}
	else
	{
		dialog_showmessage('Direction is unknown.');
	}
}

function scrollNodeIntoView(node, container) {
	if(!node || !container) return;
	if((node.offsetTop + node.offsetHeight) > (container.clientHeight + container.scrollTop)) {
		// Node is wholly or partially off the bottom of the container
		container.scrollTop = (node.offsetTop + node.offsetHeight) - (3*container.offsetHeight/4);
	}
	else if((node.offsetTop) < container.scrollTop) {
		// Node is wholly or partially off the top of the container
		container.scrollTop = node.offsetTop - (container.clientHeight/4);
	}
}

/***********************************************************************
 * General utilities
 ***********************************************************************/

	function ordinal(a) {
		var i;
		if(typeof a == 'number')
			i = Math.floor(a);
		else
			i = parseInt(a);

		if ((Math.floor((i%100)/10) != 1) && (i % 10 > 0) && (i % 10 < 4)) {
			switch (i % 10) {
				case 1: return i + "st";
				case 2: return i + "nd";
				case 3: return i + "rd";
			}
		}
		else {
			return a + "th";
		}
	}

	function zfill(x, n) {
	// Left-pad number x with zeros to a with of n
		var tmp = x.toString();
		if (n <= tmp.length)
			return tmp
		else
			return space('0', n - tmp.length) + tmp;
	}

	function space(c, n) {
	// Use a binary algorithm to efficiently create a string of n instances of string c
		var s = '';
		var i = 1;
		var tmp = c;
		while(i <= n) {
			if((n & i) == i) s += tmp;
			tmp += tmp;
			i = i << 1;
		}
		return s;
	}

	function niceSize(s) {
		var ex = 0;
		var extensions = new Array("B", "kB", "MB", "GB");

		while(s > (3072)) {
			s = s / 1024;
			ex = ex + 1;
		}

		ex = extensions[ex];
		return  Math.round(s) + ' ' + ex;
		
	}

	// The next three functions MUST product the same output as the
	// VBScript version in _common/include/util.inc.asp
	function uriQuerySegmentEncode(a) {
		return encodeURIComponent(a).replace(/%20/g, '+').replace(/%(24|2C|2F|3A|5B|5D)/g, function(a, b){return String.fromCharCode(parseInt(b, 16))});
	}

	function uriStemSegmentEncode(a) {
		return encodeURIComponent(a);
	}

	function uriStemEncode(a) {
		var s = a.split('/');
		for(i = 0; i < s.length; i++) {
			s[i] = encodeURIComponent(s[i]);
		}
		return s.join('/');
	}

/***********************************************************************
 * Date utilities
 ***********************************************************************/
	Date.prototype.weekdayNames = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
	Date.prototype.weekdayAbbrNames = new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
	Date.prototype.monthNames = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
	Date.prototype.monthAbbrNames = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');


Date.prototype.format = function(f) {
//Note non-standard "%E" which gives the day-of-month as
//  1st, 2nd, 3rd, 4th, etc.
	var s;
	var d = this;

	if (!d || !d.getDate) return d;

	s = f;

	s = s.replace(/%a/g, this.weekdayAbbrNames[d.getDay()]); //Abbreviated weekday name
	s = s.replace(/%A/g, this.weekdayNames[d.getDay()]); //Full weekday name
	s = s.replace(/%b/g, this.monthAbbrNames[d.getMonth()]); //Abbreviated month name
	s = s.replace(/(%B)|(%h)/g, this.monthNames[d.getMonth()]); //Full month name
	s = s.replace(/%d/g, zfill(d.getDate(), 2)); //Day of month with leading zero
	s = s.replace(/%e/g, d.getDate()); //Day of month without leading zero
	s = s.replace(/%E/g, ordinal(d.getDate())) //Ordinal day of month
	s = s.replace(/%H/g, zfill(d.getHours(), 2)) //Hour with leading zero
	s = s.replace(/%I/g, zfill(((d.getHours() % 12) + (((d.getHours() % 12) == 0) ? 12 : 0)), 2)); //12-hour with leading zero
	s = s.replace(/%j/g, zfill(Math.floor((new Date(d.getFullYear(), d.getMonth(), d.getDate()).valueOf() - new Date(d.getFullYear(), 0, 1).valueOf())/86400000) + 1, 3)) //Day of year with leading zeros
	s = s.replace(/%k/g, d.getHours()); //Hour without leading zero
	s = s.replace(/%l/g, (d.getHours() % 12) + ((d.getHours() % 12 == 0) ? 12 : 0)); //12-hour without leading zero
	s = s.replace(/%m/g, zfill(d.getMonth()+1, 2)); //Month with leading zero
	s = s.replace(/%M/g, zfill(d.getMinutes(), 2)); //Minutes
	s = s.replace(/%n/g, '\n'); //Newline
	s = s.replace(/%p/g, (d.getHours() < 12) ? "AM" : "PM"); //AM or PM
	s = s.replace(/%S/g, zfill(d.getSeconds(), 2)); //Seconds
	s = s.replace(/%Y/g, zfill(d.getFullYear(), 4)); //4-digit year

	s = s.replace("%%", "%")
	return s;
}

