<!-- script -->
<!--

/**
 *		iDelve Web Mapping Core - JavaScript Support Utilities.
 *
 *		Copyright (C) 1999-2005 i-delve Pty Ltd (ACN 094 953 385).
 *		All rights reserved.
 *
 * 	The purpose of this code is to interact with the iDelve Java map
 * 	applet.
 *
 * 	@note id_callQueue maintains a queue of calls to be made to the map
 * 	    applet once it has initialised.
 *
 * 	@note Each queued call is maintained as an array, with the eval() call
 * 	    referencing the method name (index 0) and the method call
 * 	    parameters as array elements (index 1 and above); the intent is to
 * 	    have a generalised call mechanism which does *NOT* attempt to place
 * 	    string literals into eval calls.
 *
 *		@note The id_notifyReady flag is used to determine whether the map
 *			applet should attempt to call out when it has initialised or 
 *			whether the JavaScript control loop should 'ping' in to check 
 *			if the applet is ready. Mozilla (etc) browsers should notify, whilst
 *			Microsoft (etc) browsers should 'ping'.
 *
 *		@note Whenever actions are performed within the event loop, a 
 *		 setTimeout() call is used to yield the event thread and schedule the
 *		 action shortly thereafter (usually 100msec).
 *
 * 	@note This code requires 'remedial.js' and 'browser_detect.js' to be
 * 		available.
 * 
 */

/// Is the main map applet fully initialised?
var id_mapReady = false;

/// Have we done the initial applet resize (after applet ready but dataset not)?
var id_doneInitialResize = false;

/// A reference to the map applet.
var id_mapApplet;

/// Queue containing calls to be made to the map applet when it is ready.
var id_callQueue = new Array();

/// Should the map applet notify JavaScript when it is ready?
var id_notifyReady = browser.isGecko || browser.isMozilla || browser.isFirebird;

// the current tool (assuming applet started when call made!)
// Useful for changing layouts, etc, based on the current tool
var theTool = 0;

/**
 * Main applet ping count - how many times have we checked to see if the 
 * applet is initialised
 */
var id_mapPingCount = 1;

/**
 * Name of web application JavaScript method to handle call from
 * id_browseClickAction().
 */
var id_browseClickActionFunction = "";

var id_resizePending = false;

var temp=0;

function id_frameResize() {
	if(!id_resizePending) {
		id_resizePending = true;
		setTimeout("id_mapResize();", 200);
	}
}

/**
 * Performs applet resize; should be called by the map frame's body onResize.
 *
 * @note We used to set the size by calling into the applet, however this
 * 	produces inconsistent results, so now we just set the applet 
 * 	properties using JavaScript; see references below.
 * @note We still call the applet to ensure a repaint/validate is performed.
 * 	
 * @see http://blog.taragana.com/index.php/archive/resizing-applets-dynamically-within-browser-frames/
 * @see http://blog.taragana.com/index.php/archive/resizing-applets-from-java-code-a-second-look/
 */
function id_mapResize()
{
	id_resizePending = false;
	//if(!id_mapReady) return;

	var b = Array();
	if(id_mapReady) {
		b = id_decodeStringArray( id_mapApplet.apiGetView() );
	}
	var w_newWidth,w_newHeight;
	var w_maxWidth=1600, w_maxHeight=1200;
	if(navigator.appName.indexOf("Microsoft") != -1) {
		w_newWidth=mapF.document.body.clientWidth;
		w_newHeight=mapF.document.body.clientHeight;
	} else {
		var netscapeScrollWidth=0; // no scrollbar. 15;
		w_newWidth=mapF.window.innerWidth-netscapeScrollWidth;
		w_newHeight=mapF.window.innerHeight-netscapeScrollWidth;
	}
	if(w_newWidth>w_maxWidth) w_newWidth=w_maxWidth;
	if(w_newHeight>w_maxHeight) w_newHeight=w_maxHeight;
	mapF.document.map.width = w_newWidth;
	mapF.document.map.height = w_newHeight;
	/* called directly as we may call before full applet (dataset) ready */
	mapF.document.map.apiSetSize(w_newWidth,w_newHeight);
	mapF.window.scroll(0,0);

	if(b.length==5) {
		// Maintain location in y direction to avoid aspect ratio changing issues.
		var tmp = (parseFloat(b[0])+parseFloat(b[2]))/2.0;
		id_appletCall(new Array("apiSetView",parseInt(0), tmp,parseFloat(b[1]), tmp, parseFloat(b[3]),0,0,true));
		//id_appletCall(new Array("apiSetView",0, b[0], b[1], b[2], b[3],0,0,true));
	}
		//temp++;
		//setTimeout("alert('resize done "+time()+" "+temp+"')", 10000);
}

/**
 * This function will check if the map applet has initialised and then call
 * itself until the applet does initialise, waiting a maximum time
 * before warning the user and aborting.
 * Has to be called asynchronously
 *
 * @note On some browsers we call out to notify applet ready; see 
 * 	\ref id_notifyReady
 */
function id_pingApplet()
{
	if(id_notifyReady) return;

	if(mapF!=null												// find the map frame doc
			&& mapF.document!=null 
			)
	{
																	// find the map applet
		var applet = mapF.document.getElementById("mapApplet");
		if((typeof applet != "undefined"))
		{
			try {
				if(browser.isIE || applet.apiGetState) {		// find check method
					var state = applet.apiGetState();
					//alert(state);
					if(state==0) {
						
						/* loading, keep pinging */
						setTimeout("id_pingApplet();", 100);
					} else if(state==1) {
						/* loaded applet, still loading dataset */
						
						id_appletReady(state);
						setTimeout("id_pingApplet();", 100);
					} else if(state==2) {
						/* applet & dataset fully ready */
						id_appletReady(state);
					} else if(state==3) {
						/* applet/dataset has an error during initialisation */
						id_appletReady(state);
					}
					return;
				}
			} catch(e) {}
		}
	}
	id_mapPingCount++;
	//alert(id_mapPingCount);
	if(id_mapPingCount>=100)								// wait 100 pings at 10/sec
	{
		ans = confirm(
				"The iDelve map applet does not appear to have initialised"
				+ " correctly."
				+ " It may be necessary to reload the map and/or the page."
				+ " If you continue to have problems, please report this problem to"
				+ " the web site administrator."
				+ " Thanks."
				+ " Please select 'OK' to reload the map, or 'Cancel' otherwise."
 				);
		if(ans) setTimeout("location.href=location.href;", 100);
	} else {
		setTimeout("id_pingApplet();", 100);
	}
}

/**
 * Called when the map applet has initialised to compete JS<->Java
 * initialisation. State > 0.
 */
function id_appletReady(state)
{
	id_mapApplet = mapF.document.getElementById("mapApplet");
	if(!id_doneInitialResize) {
		//setTimeout("id_mapResize();", 50);
		id_mapResize();
		id_doneInitialResize = true;
	}
	//id_mapResize();
	if (state==2){
		id_appletCallFlushQueue();
		id_mapReady = true;
		if((typeof id_overviewURL) != "undefined") {
			setTimeout("oviewF.document.location.href=id_overviewURL;", 100);
		}
	}
}

/**
 * Called to queue map applet method call. Call is queued, and a flush is
 * scheduled if the map applet is ready.
 */
function id_appletCall(e)
{
	id_callQueue.push(e);
	if(id_mapReady) {
		id_appletCallFlushQueue();
		return true;
	}
	return false;
}


/**
 * Calls (live) the applet and returns the value.
 * Should be called from a timer thread if possible.
 * No order guarenteed.
 * false returned if applet not ready.
 */
function id_appletCallDirect(e)
{
	if(id_mapReady) {
		return id_appletCallNow(e, true);
	}
	return false;
}

/// Schedules a map applet method call queue flush
function id_appletCallFlushQueue()
{
	setTimeout("id_appletCallFlushQueueInternal();",100);
}

/// Actually performs a map applet method call queue flush
function id_appletCallFlushQueueInternal()
{
	while(id_callQueue.length>0) {
		id_appletCallNow(id_callQueue.shift(), false);
	}
}

function time() {
	return ""+(new Date()).getSeconds();
}

/**
 * Perform mapp applet method call now.
 * @param e[0] applet method name
 * @param e[>=1] remainder parameters
 */
function id_appletCallNow(e, returnValue)
{
	//var s = "mapF.document.map."+e[0]+"(";
	var s = "id_mapApplet."+e[0]+"(";
	if(e.length>1) {
		for(i=1; i<e.length; i++) {
			s += "e["+i+"],";
		}
		s = s.substring(0, s.length-1);
	}
	s += ");";
		//temp++;
		//setTimeout("alert('on applet call "+time()+" "+temp+e+"')", 10000);
	try {
		if(returnValue) {
			return id_decodeStringArray(eval(s));
		} else {
			eval(s);
		}
	} catch(ex) {
		var m = "The error detailed below has occurred."
				+ " If you continue to have problems, please report this problem to"
				+ " the web site administrator."
				+ " Thanks."
				+ "\n"
				+ "Error: "+ex
				+ "\n"
				+ "Failed call: '"+s+"'"
				+ "\n"
				+ "Parameters: ";
		for(i=1; i<e.length; i++) {
			m += "e["+i+"] = '"+e[i]+"'\n";
		}
		//alert(m);
	}
}

/**
 * Helper function to encode an array as a single whitespace separated
 * tokenised string
 * @see Inverse method toStringVector() in the map applet
 */
function id_encodeStringArray(a)
{
	var ret = "";
	while(a.length>0) {
		var val = a.shift();
		if(!isUndefined(val)) {
			ret += (""+val).quote()+" ";
		}
	}
	return ret.substring(0);
}

/**
 * Helper function to decode a single string value.
 * @see method encodeStringArray() in the map applet
 */
function id_unquoteString(s) {
	return s.replace(/&amp;/g, "&").replace(/&lt;/g, "<")
		.replace(/&gt;/g, ">").replace(/&quot;/g, "\"")
		.replace(/&eol;/g, "\n");
}

/**
 *	Restores an array encoded in Java using encodeStringArray().
 */
function id_decodeStringArray(s) {
	var a = Array();
	if(!isUndefined(s)) {
		s = ""+s;
		if(s!="") a = s.split("<");
	}

	for(var i=0; i<a.length; i++) {
		a[i] = id_unquoteString(a[i]);
	}

	return a;
}

function id_setTool(tool) 
{
	theTool = tool;
	return id_appletCall( new Array("apiSetTool", tool) );
}

function id_doTool(id, args) {
	var e = new Array("apiDoTool");
	e[1]=id;
	e[2]=id_encodeStringArray(args); // is an array of all args
	return id_appletCall(e);
}

/// Callback called by map applet
function id_browseClickAction(dataset, bbtlx, bbtly, bbbrx, bbbry, 
		clickx, clicky, width, height, clickType, timestamp, layerID, layerName,
		elemID, formattedTags, tags)
{
	dataset = id_unquoteString(dataset);
	layerName = id_unquoteString(layerName);
	formattedTags = id_unquoteString(formattedTags);

	var tagsArray = Array();
	if(!isUndefined(tags)) {
		tags = ""+tags;
		if(tags!="") tagsArray = tags.split("<");
	}

	for(var i=0; i<tagsArray.length; i++) {
		tagsArray[i] = id_unquoteString(tagsArray[i]);
	}


	try {
		eval(id_browseClickActionFunction+"("
				+ "dataset, bbtlx, bbtly, bbbrx, bbbry,"
				+ "clickx, clicky, width, height, clickType, timestamp, layerID,"
				+ "layerName, elemID, formattedTags, tagsArray"
				+ ");"
				);
	} catch(e) {}
}

/**
 * Use to set the web application method called by id_browseClickAction.
 */
function id_setBrowseClickAction(func)
{
	id_browseClickActionFunction = func;
}

function id_showOriginalMap()
{
	var fs = top.document.getElementById("FR1");
	fs.cols = "*,300px";
	//var success = id_setOverview(true);
	//if (success) success = id_setLayerSelector(true);
	//overview map & layer selector are visible
	var success = id_appletCall(new Array('apiOverviewMap',1));
	if (success) success = id_appletCall(new Array('apiLayerSelector',1));
	else return false;
	return success;
}

function id_showOriginalMapImageViewer()
{
	ecwLayout=0;
	ecwUpdateInternal();

	var fs = top.document.getElementById("FR1");
	fs.cols = "*,200px";
	//var success = id_setOverview(true);
	//if (success) success = id_setLayerSelector(true);
	//overview map & layer selector are visible
	var success = id_appletCall(new Array('apiOverviewMap',1));
	if (success) success = id_appletCall(new Array('apiLayerSelector',1));
	else return false;
	return success;
}

// --!>
<!-- /script -->
