/*
 *
 * This file was originally based on ...
 *
 * JSON-RPC JavaScript client
 *
 * $Id: jsonrpc.js,v 1.36.2.3 2006/03/08 15:09:37 mclark Exp $
 *
 * Copyright (c) 2003-2004 Jan-Klaas Kollhof
 * Copyright (c) 2005 Michael Clark, Metaparadigm Pte Ltd
 *
 * This code is based on Jan-Klaas' JavaScript o lait library (jsolait).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */



//Example of usage:
//progressWrap(myFunction, [my1stArgument, my2ndArgument]);
function progressWrap(theFunction, theArguments){
    if (typeof(theFunction) == "function"){
        progressClockImage = IMG({
            'id' : 'progressClock',
            'src' : '/images/waiting.gif',
            'style' : 'left:0; position:absolute; top:0;'
        });
        document.childNodes[1].childNodes[1].appendChild(progressClockImage);

        var doTheWork = function() {
            theFunction(theArguments);
            removeElement($('progressClock'));
        };
        setTimeout(doTheWork, 0);

    } else{
        alert('progressWrap requires a function as its first argument');
        return false;
    }
}

/* escape a character */

escapeJSONChar =
function escapeJSONChar(c)
{
    if(c == "\"" || c == "\\") return "\\" + c;
    else if (c == "\b") return "\\b";
    else if (c == "\f") return "\\f";
    else if (c == "\n") return "\\n";
    else if (c == "\r") return "\\r";
    else if (c == "\t") return "\\t";
    var hex = c.charCodeAt(0).toString(16);
    if(hex.length == 1) return "\\u000" + hex;
    else if(hex.length == 2) return "\\u00" + hex;
    else if(hex.length == 3) return "\\u0" + hex;
    else return "\\u" + hex;
};


/* encode a string into JSON format */

escapeJSONString =
function escapeJSONString(s)
{
    /* The following should suffice but Safari's regex is b0rken
       (doesn't support callback substitutions)
       return "\"" + s.replace(/([^\u0020-\u007f]|[\\\"])/g,
       escapeJSONChar) + "\"";
    */

    /* Rather inefficient way to do it */
    var parts = s.split("");
    for(var i=0; i < parts.length; i++) {
    var c =parts[i];
    if(c == '"' ||
       c == '\\' ||
       c.charCodeAt(0) < 32 ||
       c.charCodeAt(0) >= 128)
        parts[i] = escapeJSONChar(parts[i]);
    }
    return "\"" + parts.join("") + "\"";
};


/* Marshall objects to JSON format */

toJSON = function toJSON(o)
{
    if(o == null) {
    return "null";
    } else if(o.constructor == String) {
    return escapeJSONString(o);
    } else if(o.constructor == Number) {
    return o.toString();
    } else if(o.constructor == Boolean) {
    return o.toString();
    } else if(o.constructor == Date) {
    return '{javaClass: "java.util.Date", time: ' + o.valueOf() +'}';
    } else if(o.constructor == Array) {
    var v = [];
    for(var i = 0; i < o.length; i++) v.push(toJSON(o[i]));
    return "[" + v.join(", ") + "]";
    } else {
    var v = [];
    for(attr in o) {
        if(o[attr] == null) v.push("\"" + attr + "\": null");
        else if(typeof o[attr] == "function"); /* skip */
        else v.push(escapeJSONString(attr) + ": " + toJSON(o[attr]));
    }
    return "{" + v.join(", ") + "}";
    }
};


/* JSONRpcClient constructor */

JSONRpcClient =
function JSONRpcClient_ctor(serverURL, user, pass, objectID)
{
    this.serverURL = serverURL;
    this.user = user;
    this.pass = pass;
    this.objectID = objectID;

    /* Add standard methods */
    if(this.objectID) {
    this._addMethods(["listMethods"]);
    var req = this._makeRequest("listMethods", []);
    } else {
    this._addMethods(["system.listMethods"]);
    var req = this._makeRequest("system.listMethods", []);
    }
    var m = this._sendRequest(req);
    this._addMethods(m);
};


/* JSONRpcCLient.Exception */

JSONRpcClient.Exception =
function JSONRpcClient_Exception_ctor(code, message, javaStack)
{
    this.code = code;
    var name;
    if(javaStack) {
    this.javaStack = javaStack;
    var m = javaStack.match(/^([^:]*)/);
    if(m) name = m[0];
    }
    if(name) this.name = name;
    else this.name = "JSONRpcClientException";
    this.message = message;
};

JSONRpcClient.Exception.CODE_REMOTE_EXCEPTION = 490;
JSONRpcClient.Exception.CODE_ERR_CLIENT = 550;
JSONRpcClient.Exception.CODE_ERR_PARSE = 590;
JSONRpcClient.Exception.CODE_ERR_NOMETHOD = 591;
JSONRpcClient.Exception.CODE_ERR_UNMARSHALL = 592;
JSONRpcClient.Exception.CODE_ERR_MARSHALL = 593;

JSONRpcClient.Exception.prototype = new Error();

JSONRpcClient.Exception.prototype.toString =
function JSONRpcClient_Exception_toString(code, msg)
{
    return this.name + ": " + this.message;
};


/* Default top level exception handler */

JSONRpcClient.default_ex_handler =
function JSONRpcClient_default_ex_handler(e) { alert(e); };


/* Client settable variables */

JSONRpcClient.toplevel_ex_handler = JSONRpcClient.default_ex_handler;
JSONRpcClient.profile_async = false;
JSONRpcClient.max_req_active = 1;
JSONRpcClient.requestId = 1;


/* JSONRpcClient implementation */

JSONRpcClient.prototype._createMethod =
function JSONRpcClient_createMethod(methodName)
{
    var fn=function()
    {
    var args = [];
    var callback = null;
    for(var i=0;i<arguments.length;i++) args.push(arguments[i]);
    if(typeof args[0] == "function") callback = args.shift();
    var req = fn.client._makeRequest.call(fn.client, fn.methodName,
                          args, callback);
    if(callback == null) {
        return fn.client._sendRequest.call(fn.client, req);
    } else {
        JSONRpcClient.async_requests.push(req);
        JSONRpcClient.kick_async();
        return req.requestId;
    }
    };
    fn.client = this;
    fn.methodName = methodName;
    return fn;
};

JSONRpcClient.prototype._addMethods =
function JSONRpcClient_addMethods(methodNames)
{
    for(var i=0; i<methodNames.length; i++) {
    var obj = this;
    var names = methodNames[i].split(".");
    for(var n=0; n<names.length-1; n++) {
        var name = names[n];
        if(obj[name]) {
        obj = obj[name];
        } else {
        obj[name]  = new Object();
        obj = obj[name];
        }
    }
    var name = names[names.length-1];
    if(!obj[name]) {
        var method = this._createMethod(methodNames[i]);
        obj[name] = method;
    }
    }
};

JSONRpcClient._getCharsetFromHeaders =
function JSONRpcClient_getCharsetFromHeaders(http)
{
    try {
    var contentType = http.getResponseHeader("Content-type");
    var parts = contentType.split(/\s*;\s*/);
    for(var i =0; i < parts.length; i++) {
        if(parts[i].substring(0, 8) == "charset=")
        return parts[i].substring(8, parts[i].length);
    }
    } catch (e) {}
    return "UTF-8"; /* default */
};

/* Async queue globals */
JSONRpcClient.async_requests = [];
JSONRpcClient.async_inflight = {};
JSONRpcClient.async_responses = [];
JSONRpcClient.async_timeout = null;
JSONRpcClient.num_req_active = 0;

JSONRpcClient._async_handler =
function JSONRpcClient_async_handler()
{
    JSONRpcClient.async_timeout = null;

    while(JSONRpcClient.async_responses.length > 0) {
    var res = JSONRpcClient.async_responses.shift();
    if(res.canceled) continue;
    if(res.profile) res.profile.dispatch = new Date();
    try {
        res.cb(res.result, res.ex, res.profile);
    } catch(e) {
        JSONRpcClient.toplevel_ex_handler(e);
    }
    }

    while(JSONRpcClient.async_requests.length > 0 &&
      JSONRpcClient.num_req_active < JSONRpcClient.max_req_active) {
    var req = JSONRpcClient.async_requests.shift();
    if(req.canceled) continue;
    req.client._sendRequest.call(req.client, req);
    }
};

JSONRpcClient.kick_async =
function JSONRpcClient_kick_async()
{
    if(JSONRpcClient.async_timeout == null)
    JSONRpcClient.async_timeout =
        setTimeout(JSONRpcClient._async_handler, 0);
};

JSONRpcClient.cancelRequest =
function JSONRpcClient_cancelRequest(requestId)
{
    /* If it is in flight then mark it as canceled in the inflight map
       and the XMLHttpRequest callback will discard the reply. */
    if(JSONRpcClient.async_inflight[requestId]) {
    JSONRpcClient.async_inflight[requestId].canceled = true;
    return true;
    }

    /* If its not in flight yet then we can just mark it as canceled in
       the the request queue and it will get discarded before being sent. */
    for(var i in JSONRpcClient.async_requests) {
    if(JSONRpcClient.async_requests[i].requestId == requestId) {
        JSONRpcClient.async_requests[i].canceled = true;
        return true;
    }
    }

    /* It may have returned from the network and be waiting for its callback
       to be dispatched, so mark it as canceled in the response queue
       and the response will get discarded before calling the callback. */
    for(var i in JSONRpcClient.async_responses) {
    if(JSONRpcClient.async_responses[i].requestId == requestId) {
        JSONRpcClient.async_responses[i].canceled = true;
        return true;
    }
    }

    return false;
};

JSONRpcClient.prototype._makeRequest =
function JSONRpcClient_makeRequest(methodName, args, cb)
{
    var req = {};
    req.client = this;
    req.requestId = JSONRpcClient.requestId++;

    var obj = {};
    obj.id = req.requestId;
    if (this.objectID)
    obj.method = ".obj#" + this.objectID + "." + methodName;
    else
    obj.method = methodName;
    obj.params = args;

    if (cb) req.cb = cb;
    if (JSONRpcClient.profile_async)
    req.profile = { "submit": new Date() };
    req.data = toJSON(obj);

    return req;
};

JSONRpcClient.prototype._sendRequest =
function JSONRpcClient_sendRequest(req)
{
    if(req.profile) req.profile.start = new Date();

    /* Get free http object from the pool */
    var http = JSONRpcClient.poolGetHTTPRequest();
    JSONRpcClient.num_req_active++;

    /* Send the request */
    if (typeof(this.user) == "undefined") {
    http.open("POST", this.serverURL, (req.cb != null));
    } else {
    http.open("POST", this.serverURL, (req.cb != null), this.user, this.pass);
    }

    /* setRequestHeader is missing in Opera 8 Beta */
    try { http.setRequestHeader("Content-type", "text/plain"); } catch(e) {}

    /* Construct call back if we have one */
    if(req.cb) {
    var self = this;
    http.onreadystatechange = function() {
        if(http.readyState == 4) {
        http.onreadystatechange = function () {};
        var res = { "cb": req.cb, "result": null, "ex": null};
        if (req.profile) {
            res.profile = req.profile;
            res.profile.end = new Date();
        }
        try { res.result = self._handleResponse(http); }
        catch(e) { res.ex = e; }
        if(!JSONRpcClient.async_inflight[req.requestId].canceled)
            JSONRpcClient.async_responses.push(res);
        delete JSONRpcClient.async_inflight[req.requestId];
        JSONRpcClient.kick_async();
        }
    };
    } else {
    http.onreadystatechange = function() {};
    }

    JSONRpcClient.async_inflight[req.requestId] = req;

    try {
    http.send(req.data);
    } catch(e) {
    JSONRpcClient.poolReturnHTTPRequest(http);
    JSONRpcClient.num_req_active--;
    throw new JSONRpcClient.Exception
        (JSONRpcClient.Exception.CODE_ERR_CLIENT, "Connection failed");
    }

    if(!req.cb) return this._handleResponse(http);
};

JSONRpcClient.prototype._handleResponse =
function JSONRpcClient_handleResponse(http)
{
    /* Get the charset */
    if(!this.charset) {
    this.charset = JSONRpcClient._getCharsetFromHeaders(http);
    }

    /* Get request results */
    var status, statusText, data;
    try {
    status = http.status;
    statusText = http.statusText;
    data = http.responseText;
    } catch(e) {
    JSONRpcClient.poolReturnHTTPRequest(http);
    JSONRpcClient.num_req_active--;
    JSONRpcClient.kick_async();
    throw new JSONRpcClient.Exception
        (JSONRpcClient.Exception.CODE_ERR_CLIENT, "Connection failed");
    }

    /* Return http object to the pool; */
    JSONRpcClient.poolReturnHTTPRequest(http);
    JSONRpcClient.num_req_active--;

    /* Unmarshall the response */
    if(status != 200) {
    throw new JSONRpcClient.Exception(status, statusText);
    }
    var obj;
    try {
    eval("obj = " + data);
    } catch(e) {
    throw new JSONRpcClient.Exception(550, "error parsing result");
    }
    if(obj.error)
    throw new JSONRpcClient.Exception(obj.error.code, obj.error.msg,
                      obj.error.trace);
    var res = obj.result;

    /* Handle CallableProxy */
    if(res && res.objectID && res.JSONRPCType == "CallableReference")
    return new JSONRpcClient(this.serverURL, this.user,
                 this.pass, res.objectID);

    return res;
};


/* XMLHttpRequest wrapper code */

/* XMLHttpRequest pool globals */
JSONRpcClient.http_spare = [];
JSONRpcClient.http_max_spare = 8;

JSONRpcClient.poolGetHTTPRequest =
function JSONRpcClient_pool_getHTTPRequest()
{
    if(JSONRpcClient.http_spare.length > 0) {
    return JSONRpcClient.http_spare.pop();
    }
    return JSONRpcClient.getHTTPRequest();
};

JSONRpcClient.poolReturnHTTPRequest =
function JSONRpcClient_poolReturnHTTPRequest(http)
{
    if(JSONRpcClient.http_spare.length >= JSONRpcClient.http_max_spare)
    delete http;
    else
    JSONRpcClient.http_spare.push(http);
};

JSONRpcClient.msxmlNames = [ "MSXML2.XMLHTTP.5.0",
                 "MSXML2.XMLHTTP.4.0",
                 "MSXML2.XMLHTTP.3.0",
                 "MSXML2.XMLHTTP",
                 "Microsoft.XMLHTTP" ];

JSONRpcClient.getHTTPRequest =
function JSONRpcClient_getHTTPRequest()
{
    /* Mozilla XMLHttpRequest */
    try {
    JSONRpcClient.httpObjectName = "XMLHttpRequest";
    return new XMLHttpRequest();
    } catch(e) {}

    /* Microsoft MSXML ActiveX */
    for (var i=0;i < JSONRpcClient.msxmlNames.length; i++) {
    try {
        JSONRpcClient.httpObjectName = JSONRpcClient.msxmlNames[i];
        return new ActiveXObject(JSONRpcClient.msxmlNames[i]);
    } catch (e) {}
    }

    /* None found */
    JSONRpcClient.httpObjectName = null;
    throw new JSONRpcClient.Exception(0, "Can't create XMLHttpRequest object");
};


/**
 * js_forms.js
 * A function library for Acrobat plug-in checking and cookie manipulation
 */

var osmWinParams = "width=600,height=365,resizable=yes,scrollbars=yes";

/**
 * Determine whether the user has the Acrobat Reader ActiveX control by 
 * attempting to instantiate it
 * 
 * @return true if the ActiveX control was successfully instantiated,
 * false otherwise
 * 
 */
function tryActiveXAcro() {
	try {
		acro = new ActiveXObject("PDF.PdfCtrl.1");
		if(!acro) return;
		acro = null;
		return true;
	} catch (e) { return false; }
}

function checkAcrobat(url, doPopup) {
	if(getCookie('HasAcrobat') != 1) {
		if(tryActiveXAcro()) {
			setThreeYearCookie('HasAcrobat');
			window.location = url;
		} else {
			var acroUrl = "/acrobat_help.jsp?url=" + escape(url);
			if(doPopup) {
				var zwindow = window.open(acroUrl, "usePolicy", osmWinParams);
				zwindow.focus();
			} else
				window.location = acroUrl + "&popup=no";
		}
	} else window.location = url;
}

function checkAcrobatAlt(url, alt, doPopup) {
	if(getCookie('HasAcrobat') == 1) window.location = url;
	else if(getCookie('HasAcrobat') == 0) window.location = alt;
	else {
		if(!document.layers && tryActiveXAcro()) {
			setThreeYearCookie('HasAcrobat');
			window.location = url;
		} else {
			var acroUrl =
				"/acrobat_help.jsp?url=" + escape(url) + "&alt=" + escape(alt);
			if(doPopup) window.open(acroUrl, "usePolicy", osmWinParams).focus();
			else window.location = acroUrl + "&popup=no";
		}
	}
}

function changeCookie (name, isChecked) {
	if (isChecked) setThreeYearCookie(name);
	else deleteCookie(name);
}

function setThreeYearCookieVal(name, value) {
	var expireDate = new Date();
	expireDate.setTime(expireDate.getTime() + 1000*60*60*24*365*3);
	document.cookie = name + "=" + value + ";expires="+expireDate.toGMTString();
}

function setThreeYearCookie(name) {
	setThreeYearCookieVal(name, 1);
}

function deleteCookie (name) {
	var oldDate = new Date();
	oldDate.setFullYear(1970); // the expiredate is set to Jan. 1st 1970
	document.cookie = name + "=0" + "; expires="+oldDate.toGMTString();
}

/**
 * read a cookie value
 */
function getCookie (name) {
	var cookieString = document.cookie;
	var startIndex = cookieString.indexOf(name);
	if(startIndex == -1) return (-1);	// the cookie doesn't exist!
	startIndex += name.length + 1;
	endIndex = cookieString.indexOf(";", startIndex);
	if (endIndex == -1) endIndex = cookieString.length;
	return unescape(cookieString.substring(startIndex, endIndex));
}

// Throwing js_forms.js  back in here (temporarily) as the
// JavascriptServlet isn't ready yet

/**
 * js_forms.js
 * A function library for Acrobat plug-in checking and cookie manipulation
 */

var osmWinParams = "width=600,height=365,resizable=yes,scrollbars=yes";

/**
 * Determine whether the user has the Acrobat Reader ActiveX control by 
 * attempting to instantiate it
 * 
 * @return true if the ActiveX control was successfully instantiated,
 * false otherwise
 * 
 */
function tryActiveXAcro() {
	try {
		acro = new ActiveXObject("PDF.PdfCtrl.1");
		if(!acro) return;
		acro = null;
		return true;
	} catch (e) { return false; }
}

function checkAcrobat(url, doPopup) {
	if(getCookie('HasAcrobat') != 1) {
		if(tryActiveXAcro()) {
			setThreeYearCookie('HasAcrobat');
			window.location = url;
		} else {
			var acroUrl = "/acrobat_help.jsp?url=" + escape(url);
			if(doPopup) {
				var zwindow = window.open(acroUrl, "usePolicy", osmWinParams);
				zwindow.focus();
			} else
				window.location = acroUrl + "&popup=no";
		}
	} else window.location = url;
}

function checkAcrobatAlt(url, alt, doPopup) {
	if(getCookie('HasAcrobat') == 1) window.location = url;
	else if(getCookie('HasAcrobat') == 0) window.location = alt;
	else {
		if(!document.layers && tryActiveXAcro()) {
			setThreeYearCookie('HasAcrobat');
			window.location = url;
		} else {
			var acroUrl =
				"/acrobat_help.jsp?url=" + escape(url) + "&alt=" + escape(alt);
			if(doPopup) window.open(acroUrl, "usePolicy", osmWinParams).focus();
			else window.location = acroUrl + "&popup=no";
		}
	}
}

function changeCookie (name, isChecked) {
	if (isChecked) setThreeYearCookie(name);
	else deleteCookie(name);
}

function setThreeYearCookieVal(name, value) {
	var expireDate = new Date();
	expireDate.setTime(expireDate.getTime() + 1000*60*60*24*365*3);
	document.cookie = name + "=" + value + ";expires="+expireDate.toGMTString();
}

function setThreeYearCookie(name) {
	setThreeYearCookieVal(name, 1);
}

function deleteCookie (name) {
	var oldDate = new Date();
	oldDate.setFullYear(1970); // the expiredate is set to Jan. 1st 1970
	document.cookie = name + "=0" + "; expires="+oldDate.toGMTString();
}

/**
 * read a cookie value
 */
function getCookie (name) {
	var cookieString = document.cookie;
	var startIndex = cookieString.indexOf(name);
	if(startIndex == -1) return (-1);	// the cookie doesn't exist!
	startIndex += name.length + 1;
	endIndex = cookieString.indexOf(";", startIndex);
	if (endIndex == -1) endIndex = cookieString.length;
	return unescape(cookieString.substring(startIndex, endIndex));
}


/**
 * js_public.js
 */
if(!window.OSM) OSM = {};
OSM.PUB = {};
OSM.PUB.expandOrContract = function(e, expand) {
	e.stop();
	var expander = e.target();
	// Change the expander
	expander.innerHTML = expand ? "- hide" : "+ see more";
	removeClass(expander, expand ? "expander" : "contractor");
	addClass(expander, expand ? "contractor" : "expander");
	// Change the expandee
	var oldClass = expand ? "expandee" : "expanded";
	var expandee = getByTagAndClass("*", oldClass, expander.parentNode)[0];
	removeClass(expandee, oldClass);
	addClass(expandee, expand ? "expanded" : "expandee");	
}
OSM.PUB.handlers = {};
OSM.PUB.handlers.expanderContractorClick = function(e) {
	if(hasElementClass(e.target(), "expander"))
		OSM.PUB.expandOrContract(e, true);
	else if(hasElementClass(e.target(), "contractor"))
		OSM.PUB.expandOrContract(e, false);
}

/**
 * This library holds JavaScript for front-page image thumbnail roll-overs.
 * These are images with a src that ends in "sm.jpg", "sm".gif, or "sm.png",
 * which are contained within a div with a class of ra_thumb, and which have
 * a corresponding larger image that has the same src name except instead of
 * "sm" it has "lg".  Any image marked up this way will display the larger image
 * when the user moves their mouse over the smaller (or thumbnail) image.
 */
OSM.PUB.thumbRoll = {};
/**
 * This utility function converts a thumbnail image src path to a larger image
 * src path (or vice versa if a second argument of "true" is provided)
 */
OSM.PUB.thumbRoll.convertSrc = function(src, lgToSm) {
	var extension = src.match("(gif|jpg|png)$")[1];
	var retSrc = src.slice(0,-6) + (lgToSm ? "sm" : "lg") + "." + extension;
	return retSrc;
}
/**
 * This function handles thumbnail mouse over events.  Specifically, it sets
 * the hoverImage's src to the thumbnail's corresponding larger image, then
 * makes the the hoverImage appear above and to the left of the thumbnail.
 */
OSM.PUB.thumbRoll.mouseOver = function(e) {
	e.stop();
	var x = getElementPosition(e.src()).x;
	var y = getElementPosition(e.src()).y;
	$("hoverImage").src = OSM.PUB.thumbRoll.convertSrc(e.src().src);
	// Deborah this is where you want to edit (the following 2 lines)
	$("hoverImage").style.left = (x -230) + "px";
	$("hoverImage").style.top = (y -240) + "px";
	$$("#hoverImage").show();
	$("thumbOverlay").style.width = getElementDimensions(e.src()).w + "px";
	$("thumbOverlay").style.height = getElementDimensions(e.src()).h + "px";
	$("thumbOverlay").style.left = x + "px";
	$("thumbOverlay").style.top = y + "px";
	$$("#thumbOverlay").show();
	window.thumbOverlayIdent =
		connect("thumbOverlay", "onmouseout", OSM.PUB.thumbRoll.mouseOut);
}
/**
 * 
 */
OSM.PUB.thumbRoll.mouseOut = function(e) {
	e.stop();
	disconnect(window.thumbOverlayIdent);
	$$("#thumbOverlay").hide();
	$$("#hoverImage").hide();
}
/**
 * This function connects the necessary event handlers for any thumbnail images
 * on the page.
 */
OSM.PUB.thumbRoll.connectThumbs = function() {
	var thumbnails = getByTagAndClass("div", "ra_thumb");
	if(thumbnails.length > 0) {
		var hoverIMG  = IMG({"id":"hoverImage", "style":"display:none"});
		document.body.appendChild(hoverIMG);
		var thumbOverlay = DIV({"id":"thumbOverlay", "style":"display:none"});
		document.body.appendChild(thumbOverlay);
		forEach(thumbnails, OSM.PUB.thumbRoll.connectThumbnail);
	}
}
/**
 * This function connects the event handlers for a single thumbnail image
 */
OSM.PUB.thumbRoll.connectThumbnail = function(x) {
	x = x.getElementsByTagName("img")[0];
	// Preload the larger image
	IMG({"src":OSM.PUB.thumbRoll.convertSrc(x.src)});
	connect(x, "onmouseover", OSM.PUB.thumbRoll.mouseOver);
}

// "Contact Us" Form Code
try {
	var jsonrpc = new JSONRpcClient("/JSON-RPC");
} catch(e) {
	if (window.console)
		console.log("Unable to initialize JSON-RPC");
}
/**
 * How to use OSM.PUB.contact:
 * 0. Include this file (duh)
 * 1. Create a contact form with the class "contactForm" and some ID (NOTE: The
 *    parent node of the form will be hidden after the form is "submitted", so
 *    design accordingly)
 * 2. Add children with appropriate class names; the following are supported:
 * 		* emailContactField (used as "from" in generated email)
 * 		* subjectContactField (used as the subject in the generated email)
 * 		* nameContactField (used in contact info section of email's body)
 * 		* phoneContactField (used in contact info section of email's body)
 * 		* messageContactField (added to email's body)
 * 		* otherContactField (added, with field name, to email's body)
 * 3. Add an element outside of the form's parent, with an id of the form's ID
 * 	  plus "SuccessContainer" (so for a form with id "form" it would be
 * 	  "formSuccessContainer").  Hide this element.  If the form is successfully
 *    "submitted", this element will be displayed.
 * 4.. Add an element outside of the form's parent, with an id of the form's ID
 * 	  plus "FailureContainer" (so for a form with id "form" it would be
 * 	  "formFailureContainer").  Hide this element.  If the form is NOT
 *    successfully "submitted", this element will be displayed.
 */
OSM.PUB.contact = {};
OSM.PUB.contact.defaults = {
	"email":"unknown-contact@on-site.com",
	"message":"No message was entered.",
	"name":"Unknown Contact",
	"phone":"No phone number was provided",
	"subject":"Contact Form Submission (" + window.location + ")"
};
/**
 * 
 */
OSM.PUB.contact.getValidatedField = function(field, isOtherField) {
	var required = getByClass("required", field.parentNode);
	if (required.length > 0 && (field.value == null || field.value == "")) {
		// If it is required but has a value of null or "", something's wrong
		var fieldLabel = required[0].innerHTML;
		alert("Please provide your " + field.name.toLowerCase()) + ".";
		throw "No " + field.name + " provided!";
	}
	// We need to return the whole field for other fields, so that we can get
	// the name and value from it; regular fields just need a value
	return isOtherField ? field : field.value;
}
/**
 * 
 */
OSM.PUB.contact.getField = function(className, form) {
	var fields = getByClass(className + "ContactField", form);
	if(className == "other") {
		var ret = [];
		forEach(fields, function(field) {
			ret.push(OSM.PUB.contact.getValidatedField(field));
		});
		return ret;
	}
	else {
		if (fields.length == 0)
			// If the field doesn't exist on the page, we obvioously can't
			// validate it, so instead we return the default value for it
			return OSM.PUB.contact.defaults[className];
		else
			return OSM.PUB.contact.getValidatedField(fields[0]);
	}
		
}
OSM.PUB.contact.getEmail = partial(OSM.PUB.contact.getField, "email");
OSM.PUB.contact.getName = partial(OSM.PUB.contact.getField, "name");
OSM.PUB.contact.getPhone = partial(OSM.PUB.contact.getField, "phone");
OSM.PUB.contact.getSubject = partial(OSM.PUB.contact.getField, "subject");
OSM.PUB.contact.getMessage = partial(OSM.PUB.contact.getField, "message");
OSM.PUB.contact.getOtherFields = partial(OSM.PUB.contact.getField, "other");

OSM.PUB.contact.submitContactForm = function(e) {
	e.stop();
	var form = e.src();
	try {
		var contactName = OSM.PUB.contact.getName(form);
		var subject = OSM.PUB.contact.getSubject(form);
		var email = OSM.PUB.contact.getEmail(form);
		var phone = OSM.PUB.contact.getPhone(form);
		var otherFields = OSM.PUB.contact.getOtherFields(form);
	} catch (e) {
		return false;
	}
	var body = "**********************\n"; 
	body += "Contact's Information:\n";
	body += "**********************\n";
	body += "Name: " + contactName + "\n";
	 // Add email, if there is one
	if(email != OSM.PUB.contact.defaults["email"])
		body += "Email Address: " + email + "\n";
	if (phone != OSM.PUB.contact.defaults["phone"])
		body += "Phone Number: " + phone + "\n";
	body += "**********************\n";
	if (otherFields.length > 0) {
		body += "** Other Information **\n";
		forEach(otherFields, function(otherField) {
			body += otherField.name + ": " + otherField.value + "\n"; 
		});
		body += "**********************\n";
	}
	body += OSM.PUB.contact.getMessage(form) + "\n";
	
	var reply = jsonrpc.contactHandler.submit(email, subject, body);
	if (reply) {
		$$(form.parentNode).hide();
		$$("#" + form.id + "SuccessContainer").show();
	} else {
		$$(form.parentNode).hide();
		$$("#" + form.id + "FailureContainer").show();
	}
}

/**
 * OnLoad Events
 */
connect(window, "onload", function() {
	// Hook up the image thumbnails, if any
	OSM.PUB.thumbRoll.connectThumbs();
	// Hook up the expander click event (even if it's not needed; it won't hurt)
	connect(document.body, "onclick", OSM.PUB.handlers.expanderContractorClick);
	var contactForms = getByTagAndClass("form", "contactForm");
	forEach(contactForms, function(contactForm) {
		connect(contactForm, "onsubmit", OSM.PUB.contact.submitContactForm);
	});
});

var supersleight=function(){var root=false;
	var applyPositioning=false;
	var shim='/images/x.gif';
	var shim_pattern=/x\.gif$/i;
	var fnLoadPngs=function(){
		if(root){
		  root=document.getElementById(root);
		}else{
		  root=document;
		}
	
		for(var i=root.all.length-1,obj=null;(obj=root.all[i]);i--){
			if (obj.className == 'noSupersleight'){
				continue;
			}
			if(obj.currentStyle.backgroundImage.match(/\.png/i)!==null){
			  bg_fnFixPng(obj);
			}
			
			if(obj.tagName=='IMG'&&obj.src.match(/\.png$/i)!==null){
			  el_fnFixPng(obj);
			}
			
			if(applyPositioning&&(obj.tagName=='A'||obj.tagName=='INPUT')&&obj.style.position===''){
			  obj.style.position='relative';
			}
		}
	};
	
	var bg_fnFixPng=function(obj){
		var mode='scale';
		var bg=obj.currentStyle.backgroundImage;
		var src=bg.substring(5,bg.length-2);
		if(obj.currentStyle.backgroundRepeat=='no-repeat'){
			mode='crop';
		}
		
			obj.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+src+"', sizingMethod='"+mode+"')";
			obj.style.backgroundImage='url('+shim+')';
	};
	
	var el_fnFixPng=function(img){
			var src=img.src;
				img.style.width=img.width+"px";
				img.style.height=img.height+"px";
			        img.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+src+"', sizingMethod='scale')";
				img.src=shim;
			};
			
	var addLoadEvent=function(func){
		var oldonload=window.onload;
		if(typeof window.onload!='function'){
				window.onload=func;
			}else{
				window.onload=function(){
					if(oldonload){
						oldonload();
					}
				
				func();
				};
			}
		};

return{
	init:function(){
		addLoadEvent(fnLoadPngs);
	},

	limitTo:function(el){
		  root=el;
		},
	run:function(){
		fnLoadPngs();
	}};}();
	
	supersleight.init();

