if(document.all && !document.getElementById) 
{
    document.getElementById = function(id) 
	{
         return document.all[id];
    }
}

if(!String.repeat)
{
    String.prototype.repeat = function(l)
	{
        return new Array(l+1).join(this);
    }
}

if (!String.trim) 
{
    String.prototype.trim = function() 
	{
        return this.replace(/^\s+|\s+$/g,'');
    }
}

(function(){

if(!window['JAY']) 
{
    window['JAY'] = {};
}

function isCompatible(other) 
{
    if( other===false 
        || !Array.prototype.push
        || !Object.hasOwnProperty
        || !document.createElement
        || !document.getElementsByTagName
        )
	{
        alert('TR- if you see this message isCompatible is failing incorrectly.');
        return false;
    }
    return true;
}
window['JAY']['isCompatible'] = isCompatible;

function $() 
{
	var elements = new Array();
		
	for (var i = 0; i < arguments.length; i++) 
	{
		var element = arguments[i];
		
		if (typeof element == 'string')
		{
			element = document.getElementById(element);
		}	

		if (arguments.length == 1) 
		{
			return element;
		}
		elements.push(element);
	}
    return elements;
};
window['JAY']['$'] = $;

function browser()
{
	var browser = navigator.appVersion || null;
	if(browser.match("MSIE 6"))
	{
		return 'm6';
	}else if(browser.match("MSIE 7"))
	{
		return 'm7';
	}else if(browser.match("SAFARI"))
	{
		return 's';
	}else if(browser.match("APPLE"))
	{
		return 'a';
	}else
	{
		return 'f';
	}
}
window['JAY']['browser'] = browser;

function getElementsByClassName(className, tag, parent)
{
    parent = parent || document;
    if(!(parent = $(parent))) return false;
    
    var allTags = (tag == "*" && parent.all) ? parent.all : parent.getElementsByTagName(tag);
    var matchingElements = new Array();
    
    className = className.replace(/\-/g, "\\-");
    var regex = new RegExp("(^|\\s)" + className + "(\\s|$)");
    
    var element;
    for(var i=0; i<allTags.length; i++)
	{
		element = allTags[i];
        if(regex.test(element.className))
		{
            matchingElements.push(element);
        }
    }    
    return matchingElements;
};
window['JAY']['getElementsByClassName'] = getElementsByClassName;

function addEvent( node, type, listener ) 
{
    if(!isCompatible()){ return false }
    if(!(node = $(node))) return false;
    
    if (node.addEventListener) 
	{
        node.addEventListener( type, listener, false );
        return true;
    }else if(node.attachEvent) 
	{
        node['e'+type+listener] = listener;
        node[type+listener] = function(){node['e'+type+listener]( window.event );}
        node.attachEvent( 'on'+type, node[type+listener] );
        return true;
    }    
    return false;
};
window['JAY']['addEvent'] = addEvent;

function removeEvent(node, type, listener ) 
{
    if(!(node = $(node))) return false;
    if (node.removeEventListener) 
	{
        node.removeEventListener( type, listener, false );
        return true;
    }else if (node.detachEvent) 
	{
        node.detachEvent( 'on'+type, node[type+listener] );
        node[type+listener] = null;
        return true;
    }
    return false;
};
window['JAY']['removeEvent'] = removeEvent;

function toggleDisplay(node, value)
{
    if(!(node = $(node))) return false;
    if ( node.style.display != 'none' )
	{
        node.style.display = 'none';
    } else
	{
        node.style.display = value || '';
    }
    return true;
}
window['JAY']['toggleDisplay'] = toggleDisplay;

function insertAfter(node, referenceNode)
{
    if(!(node = $(node))) return false;
    if(!(referenceNode = $(referenceNode))) return false;
    return referenceNode.parentNode.appendChild(node, referenceNode.nextSibling);//insertBefore
};
window['JAY']['insertAfter'] = insertAfter;

function prependChild(parent,newChild)
{
    if(!(parent = $(parent))) return false;
    if(!(newChild = $(newChild))) return false;
    if(parent.firstChild)
	{
        parent.insertBefore(newChild,parent.firstChild);
    }else
	{
        parent.appendChild(newChild);
    }
    return parent;
} 
window['JAY']['prependChild'] = prependChild;

function getPos(ele)
{
    if(!(ele = $(ele))) return false;
	if(typeof(ele.offsetParent) != 'undefined')
	{
		for(var posX = 0, posY = 0; ele; ele = ele.offsetParent)
		{
			posX += ele.offsetLeft;
			posY += ele.offsetTop;
		}
		return {x:posX, y:posY};
	}else
	{
		return {x:ele.x, y:ele.y};
	}
};
window['JAY']['getPos'] = getPos;

function removeChildren(parent)
{
    if(!(parent = $(parent))) return false;
    
    while (parent.firstChild)
	{
         parent.firstChild.parentNode.removeChild(parent.firstChild);
    }
    return parent;
};
window['JAY']['removeChildren'] = removeChildren;

function bindFunction(obj, func)
{
    return function()
	{
        func.apply(obj,arguments);    
    };
};
window['JAY']['bindFunction'] = bindFunction;

function getBrowserWindowSize()
{
    var de = document.documentElement;
   
    return {
        'width':(
            window.innerWidth 
            || (de && de.clientWidth ) 
            || document.body.clientWidth),
        'height':(
            window.innerHeight 
            || (de && de.clientHeight ) 
            || document.body.clientHeight)
    }
};
window['JAY']['getBrowserWindowSize'] = getBrowserWindowSize;

window['JAY']['node'] = {
    ELEMENT_NODE                : 1,
    ATTRIBUTE_NODE              : 2,
    TEXT_NODE                   : 3,
    CDATA_SECTION_NODE          : 4,
    ENTITY_REFERENCE_NODE       : 5,
    ENTITY_NODE                 : 6,
    PROCESSING_INSTRUCTION_NODE : 7,
    COMMENT_NODE                : 8,
    DOCUMENT_NODE               : 9,
    DOCUMENT_TYPE_NODE          : 10,
    DOCUMENT_FRAGMENT_NODE      : 11,
    NOTATION_NODE               : 12
};

function walkElementsLinear(func,node)
{
    var root = node || window.document;
    var nodes = root.getElementsByTagName("*");
    for(var i = 0 ; i < nodes.length ; i++)
	{
        func.call(nodes[i]);
    }
};
window['JAY']['walkElementsLinear'] = walkElementsLinear;

function walkTheDOMRecursive(func,node,depth,returnedFromParent)
{
    var root = node || window.document;
    returnedFromParent = func.call(root,depth++,returnedFromParent);
    node = root.firstChild;
    while(node)
	{
        walkTheDOMRecursive(func,node,depth,returnedFromParent);
        node = node.nextSibling;
    }
};
window['JAY']['walkTheDOMRecursive'] = walkTheDOMRecursive;

function walkTheDOMWithAttributes(node,func,depth,returnedFromParent)
{
    var root = node || window.document;
    returnedFromParent = func(root,depth++,returnedFromParent);
    if (root.attributes)
	{
        for(var i=0; i < root.attributes.length; i++)
		{
            walkTheDOMWithAttributes(root.attributes[i],func,depth-1,returnedFromParent);
        }
    }
    if(root.nodeType != JAY.node.ATTRIBUTE_NODE)
	{
        node = root.firstChild;
        while(node)
		{
            walkTheDOMWithAttributes(node,func,depth,returnedFromParent);
            node = node.nextSibling;
        }
    }
};
window['JAY']['walkTheDOMWithAttributes'] = walkTheDOMWithAttributes;

function walkTheDOM(node, func)
{
    func(node);
    node = node.firstChild;
    while (node)
	{
         walkTheDOM(node, func);
         node = node.nextSibling;
    }
}
window['JAY']['walkTheDOM'] = walkTheDOM;

function camelize(s)
{
    return s.replace(/-(\w)/g, function (strMatch, p1){
        return p1.toUpperCase();
    });
}
window['JAY']['camelize'] = camelize;

function uncamelize(s, sep)
{
    sep = sep || '-';
    return s.replace(/([a-z])([A-Z])/g, function (strMatch, p1, p2){
        return p1 + sep + p2.toLowerCase();
    });
}
window['JAY']['camelize'] = camelize;

function addLoadEvent(loadEvent,waitForImages)
{
    if(!isCompatible()) return false;
    
    if(waitForImages)
	{
        return addEvent(window, 'load', loadEvent);
    }
    
    var init = function()
	{
        if (arguments.callee.done) return;
		
        arguments.callee.done = true;

        loadEvent.apply(document,arguments);
    };
    
    if (document.addEventListener)
	{
        document.addEventListener("DOMContentLoaded", init, false);
    }
    
    if (/WebKit/i.test(navigator.userAgent))
	{
        var _timer = setInterval(function()
		{
            if (/loaded|complete/.test(document.readyState))
			{
                clearInterval(_timer);
                init();
            }
        },10);
    }
    // For Internet Explorer (using conditional comments) attach a script 
    // that is deferred to the end of the load process and then check to see
    // if it has loaded
    /*@cc_on @*/
    /*@if (@_win32)
    document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
    var script = document.getElementById("__ie_onload");
    script.onreadystatechange = function()
	{
        if (this.readyState == "complete")
		{
            init();
        }
    };
    /*@end @*/
    return true;
}
window['JAY']['addLoadEvent'] = addLoadEvent;

function stopPropagation(eventObject)
{
    eventObject = eventObject || getEventObject(eventObject);
    if(eventObject.stopPropagation)
	{
        eventObject.stopPropagation();
    }else
	{
        eventObject.cancelBubble = true;
    }
}
window['JAY']['stopPropagation'] = stopPropagation;

function preventDefault(eventObject)
{
    eventObject = eventObject || getEventObject(eventObject);
    if(eventObject.preventDefault)
	{
        eventObject.preventDefault();
    }else
	{
        eventObject.returnValue = false;
    }
}
window['JAY']['preventDefault'] = preventDefault;

function getEventObject(W3CEvent)
{
    return W3CEvent || window.event;
}
window['JAY']['getEventObject'] = getEventObject;

function getTarget(eventObject)
{
    eventObject = eventObject || getEventObject(eventObject);
    // Check if the target is W3C or MSIE
    var target = eventObject.target || eventObject.scrElement;
    // Reassign the target to the parent
    // if it is a text node like in Safari
	if(browser() != 'm7')
	{
		if(target.nodeType == JAY.node.TEXT_NODE)
		{
			target = node.parentNode;
		}
	}
    return target;

}
window['JAY']['getTarget'] = getTarget;

function getMouseButton(eventObject)
{
    eventObject = eventObject || getEventObject(eventObject);
	
    var buttons = {
        'left':false,
        'middle':false,
        'right':false
    };
	
    if(eventObject.toString && eventObject.toString().indexOf('MouseEvent') != -1)
	{
        switch(eventObject.button)
		{
            case 0: buttons.left = true; break;
            case 1: buttons.middle = true; break;
            case 2: buttons.right = true; break;
            default: break;
        }
    }else if(eventObject.button)
	{
        switch(eventObject.button)
		{
            case 1: buttons.left = true; break;
            case 2: buttons.right = true; break;
            case 3:
                buttons.left = true;
                buttons.right = true;
            break;
            case 4: buttons.middle = true; break;
            case 5:
                buttons.left = true;
                buttons.middle = true;
            break;
            case 6:
                buttons.middle = true;
                buttons.right = true;
            break;
            case 7:
                buttons.left = true;
                buttons.middle = true;
                buttons.right = true;
            break;
            default: break;
        }
    } else
	{
        return false;
    }
    return buttons;

}
window['JAY']['getMouseButton'] = getMouseButton;

function getPointerPositionInDocument(eventObject)
{
    eventObject = eventObject || getEventObject(eventObject);
    var x = eventObject.pageX || (eventObject.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft));
    var y = eventObject.pageY || (eventObject.clientY + (document.documentElement.scrollTop || document.body.scrollTop));
    return {'x':x,'y':y};
}
window['JAY']['getPointerPositionInDocument'] = getPointerPositionInDocument;

function getKeyPressed(eventObject)
{
    eventObject = eventObject || getEventObject(eventObject);
    var code = eventObject.keyCode;
    var value = String.fromCharCode(code);
    return {'code':code,'value':value};
}
window['JAY']['getKeyPressed'] = getKeyPressed;

function setStyle(element, styles)
{
    if(!(element = $(element))) return false;
    for (property in styles)
	{
        if(!styles.hasOwnProperty(property)) continue;
		if(element.style.setProperty)
		{
            element.style.setProperty(uncamelize(property,'-'), styles[property], null);
        }else
		{
            element.style[camelize(property)] = styles[property];
        }
    }
    return true;
}
window['JAY']['setStyle'] = setStyle;

function setStylesByClassName(parent, tag, className, styles)
{
    if(!(parent = $(parent))) return false;
    var elements = getElementsByClassName(className, tag, parent);
    for (var e = 0 ; e < elements.length ; e++)
	{
        setStyleById(elements[e], styles);
    }
    return true;
}
window['JAY']['setStylesByClassName'] = setStylesByClassName;

function setStylesByTagName(tagname, styles, parent)
{
    parent = $(parent) || document;
    var elements = parent.getElementsByTagName(tagname);
    for (var e = 0 ; e < elements.length ; e++)
	{
        setStyleById(elements[e], styles);
    }
}
window['JAY']['setStylesByTagName'] = setStylesByTagName;

function getClassNames(element)
{
    if(!(element = $(element))) return false;
    return element.className.replace(/\s+/,' ').split(' ');
};
window['JAY']['getClassNames'] = getClassNames;

function hasClassName(element, className)
{
    if(!(element = $(element))) return false;
    var classes = getClassNames(element);
    for (var i = 0; i < classes.length; i++)
	{
        if (classes[i] === className){ return true; }
    }
    return false;
};
window['JAY']['hasClassName'] = hasClassName;

function addClassName(element, className)
{
    if(!(element = $(element))) return false;
    element.className += (element.className ? ' ' : '') + className;
    return true;
};
window['JAY']['addClassName'] = addClassName;

function removeClassName(element, className)
{
    if(!(element = $(element))) return false;
    var classes = getClassNames(element);
    var length = classes.length
    for (var i = length-1; i >= 0; i--)
	{
        if (classes[i] === className){ delete(classes[i]); }
    }
    element.className = classes.join(' ');
    return (length == classes.length ? false : true);
};
window['JAY']['removeClassName'] = removeClassName;

function addStyleSheet(url,media)
{
    media = media || 'screen';
    var link = document.createElement('LINK');
    link.setAttribute('rel','stylesheet');
    link.setAttribute('type','text/css');
    link.setAttribute('href',url);
    link.setAttribute('media',media);
    document.getElementsByTagName('head')[0].appendChild(link);
}
window['JAY']['addStyleSheet'] = addStyleSheet;

function removeStyleSheet(url,media)
{
    var styles = getStyleSheets(url,media);
    for(var i = 0 ; i < styles.length ; i++)
	{
        var node = styles[i].ownerNode || styles[i].owningElement;
        // Disable the stylesheet
        styles[i].disabled = true;
        // Remove the node
        node.parentNode.removeChild(node);
    }
}
window['JAY']['removeStyleSheet'] = removeStyleSheet;

function getStyleSheets(url,media)
{
    var sheets = [];
    for(var i = 0 ; i < document.styleSheets.length ; i++)
	{
        if (url &&  document.styleSheets[i].href.indexOf(url) == -1){ continue; }
        if(media)
		{
            media = media.replace(/,\s*/,',');
            var sheetMedia;
                
            if(document.styleSheets[i].media.mediaText)
			{
                sheetMedia = document.styleSheets[i].media.mediaText.replace(/,\s*/,',');
                sheetMedia = sheetMedia.replace(/,\s*$/,'');
            } else
			{
                sheetMedia = document.styleSheets[i].media.replace(/,\s*/,',');
            }

            if (media != sheetMedia){ continue; }
        }
        sheets.push(document.styleSheets[i]);
    }
    return sheets;
}
window['JAY']['getStyleSheets'] = getStyleSheets;

function editCSSRule(selector,styles,url,media)
{
    var styleSheets = (typeof url == 'array' ? url : getStyleSheets(url,media));
    for ( i = 0; i < styleSheets.length; i++ )
	{
        var rules = styleSheets[i].cssRules || styleSheets[i].rules;
        if (!rules){ continue; }
        selector = selector.toUpperCase();        
        for(var j = 0; j < rules.length; j++)
		{
            if(rules[j].selectorText.toUpperCase() == selector)
			{
                for (property in styles)
				{
                    if(!styles.hasOwnProperty(property)){ continue; }	
                    rules[j].style[camelize(property)] = styles[property];
                }
            }
        }
    }
}
window['JAY']['editCSSRule'] = editCSSRule;

function addCSSRule(selector, styles, index, url, media)
{
    var declaration = '';

    for (property in styles)
	{
        if(!styles.hasOwnProperty(property)){ continue; }
        declaration += property + ':' + styles[property] + '; ';
    }

    var styleSheets = (typeof url == 'array' ? url : getStyleSheets(url,media));
    var newIndex;
    for(var i = 0 ; i < styleSheets.length ; i++)
	{
		if(styleSheets[i].insertRule)
		{
            newIndex = (index >= 0 ? index : styleSheets[i].cssRules.length);
            styleSheets[i].insertRule(selector + ' { ' + declaration + ' } ', 
                newIndex);
        }else if(styleSheets[i].addRule)
		{
            newIndex = (index >= 0 ? index : -1);
            styleSheets[i].addRule(selector, declaration, newIndex);
        }
    }
}
window['JAY']['addCSSRule'] = addCSSRule;

function getStyle(element,property)
{
    if(!(element = $(element)) || !property) return false;
    var value = element.style[camelize(property)];
    if (!value)
	{
        if (document.defaultView && document.defaultView.getComputedStyle)
		{
            var css = document.defaultView.getComputedStyle(element, null);
            value = css ? css.getPropertyValue(property) : null;
        }else if (element.currentStyle)
		{
            value = element.currentStyle[camelize(property)];
        }
    }
    return value == 'auto' ? '' : value;
}
window['JAY']['getStyle'] = getStyle;

function getRequestObject(url, options, obj)
{
	// Initialize the request object
    var req = false;
    if(window.XMLHttpRequest)
	{
        var req = new window.XMLHttpRequest();
    }else if(window.ActiveXObject)
	{
        var req = new window.ActiveXObject('Microsoft.XMLHTTP');
    }
    if(!req) return false;
    
    // Define the default options
    options = options || {};
    options.method = options.method || 'GET';
    options.send = options.send || null;
	
    // Define the various listeners for each state of the request
    req.onreadystatechange = function()
	{
        switch (req.readyState)
		{
            case 1:
                // Loading
                if(options.loadListener)
				{
                    options.loadListener.apply(req,arguments);
                }
                break;
            case 2:
                // Loaded
                if(options.loadedListener)
				{
                    options.loadedListener.apply(req,arguments);
                }
                break;
            case 3:
                // Interactive
                if(options.ineractiveListener)
				{
                    options.ineractiveListener.apply(req,arguments);
                }
                break;
            case 4:
                // Complete
                // if aborted FF throws errors
				try { 
					if (req.status && req.status == 200)
					{                    
						// Specific listeners for content-type
						// The Content-Type header can include the charset:
						// Content-Type: text/html; charset=ISO-8859-4
						// So we'll use a match to extract the part we need.
						var contentType = req.getResponseHeader('Content-Type');
						var mimeType = contentType.match(/\s*([^;]+)\s*(;|$)/i)[1];
											
						switch(mimeType)
						{
							case 'text/javascript':
							case 'application/javascript':
								// The response is JavaScript so use the 
								// req.responseText as the argument to the callback
								if(options.jsResponseListener)
								{
									options.jsResponseListener.call(
										req,
										req.responseText
									);
								}
								break;
							case 'text/xml':
							case 'application/xml':
							case 'application/xhtml+xml':
								// The response is XML so use the 
								// req.responseXML as the argument to the callback
								// This will be a Document object
								if(options.xmlResponseListener)
								{
									options.xmlResponseListener.call(
										req,
										req.responseXML
									);
								}
								break;
							case 'text/html':
								// The response is HTML so use the 
								// req.responseText as the argument to the callback
								if(options.htmlResponseListener)
								{
									options.htmlResponseListener.call(
										req,
										req.responseText
									);
								}
								break;
						}
					
						// A complete listener
						if(options.completeListener)
						{
							options.completeListener.apply(req,arguments);
						}
					} else
					{
						// Response completed but there was an error
						if(options.errorListener)
						{
							options.errorListener.apply(req,arguments);
						}
					}                
				} catch(e)
				{
					//ignore errors
					//alert('Response Error: ' + e['message']);
				}
			break;
        }
    };
    // Open the request
    req.open(options.method, url, true);
    req.setRequestHeader('X-JAY-Ajax-Request','AjaxRequest');
	return req;
}
window['JAY']['getRequestObject'] = getRequestObject;

function ajaxRequest(url, options, obj)
{
	try
	{
		var req = getRequestObject(url, options, obj);
		req.obj = obj;
		return req.send(options.send);
	}catch(e)
	{
		var req = getRequestObject(url, options, obj);
		return req.send(options.send);
	}
}
window['JAY']['ajaxRequest'] = ajaxRequest;

function makeCallback(method, target)
{
    return function(){ method.apply(target,arguments); }
}

var actionPager =  {
    // The previous hash
    lastHash : '',
    // A list of the methods registered for the hash patterns
    callbacks: [],
    // The safari history list
    safariHistory : false,
    // A reference to the iframe for Internet Explorer
    msieHistory: false,
    // The class name of the links that should be converted
    ajaxifyClassName: '',
    // The root URL of the application. This will be stripped off the URLS
    // when creating the hashes
    ajaxifyRoot: '',
    
    
    init: function(ajaxifyClass,ajaxifyRoot,startingHash)
	{

        this.ajaxifyClassName = ajaxifyClass || 'JAYActionLink';
        this.ajaxifyRoot = ajaxifyRoot || '';

        if (/Safari/i.test(navigator.userAgent))
		{
            this.safariHistory = [];
        } else if (/MSIE/i.test(navigator.userAgent))
		{
            // In the case of MSIE, add a iframe to track override the back button
            this.msieHistory = document.createElement("iframe");
            this.msieHistory.setAttribute("id", "msieHistory");
            this.msieHistory.setAttribute("name", "msieHistory");
            setStyleById(this.msieHistory,{
                'width':'100px',
                'height':'100px',
                'border':'1px solid black',
                'visibility':'visible',
                'zIndex':'-1'
            });
            document.body.appendChild(this.msieHistory);
            this.msieHistory = frames['msieHistory'];
            
        }

        // Convert the links to AJAX links
        this.ajaxifyLinks();

        // Get the current location
        var location = this.getLocation();

        // Check if the location has a hash (from a bookmark)
        // or if a hash has bee provided
        if(!location.hash && !startingHash){ startingHash = 'start'; }

        // Store the hash as necessary
        ajaxHash = this.getHashFromURL(location.hash) || startingHash;
        this.addBackButtonHash(ajaxHash);

        // Add a watching event to look for changes in the location bar
        var watcherCallback = makeCallback(this.watchLocationForChange,this);
        window.setInterval(watcherCallback,200);
    },
    ajaxifyLinks: function()
	{
        // Convert the links to anchors for ajax handling
        links = getElementsByClassName(this.ajaxifyClassName, 'a', document);
        for(var i=0 ; i < links.length ; i++)
		{
            if(hasClassName(links[i],'JAYActionPagerModified')){ continue; }
        
            // Convert the herf attribute to #value
            links[i].setAttribute(
                'href',
                this.convertURLToHash(links[i].getAttribute('href'))
            );
            addClassName(links[i],'JAYActionPagerModified');

            // Attach a click event to add history as necessary
            addEvent(links[i],'click',function()
			{
                if (this.href && this.href.indexOf('#') > -1)
				{
                     actionPager.addBackButtonHash(
                        actionPager.getHashFromURL(this.href)
                    );
                 }
            });
        }
    },
    addBackButtonHash: function(ajaxHash)
	{
        // Store the hash
        if (!ajaxHash) return false;
        if (this.safariHistory !== false)
		{
            // Using a special array for Safari
            if (this.safariHistory.length == 0)
			{
                this.safariHistory[window.history.length] = ajaxHash;
            } else {
                this.safariHistory[window.history.length+1] = ajaxHash;
            }
            return true;
        } else if (this.msieHistory !== false)
		{
            // By navigating the iframe in MSIE
            this.msieHistory.document.execCommand('Stop');
            this.msieHistory.location.href = '/fakepage?hash='
                + ajaxHash
                + '&title='+document.title;
            return true;
        } else {
            // By changing the location value
            // The function is wrapped using makeCallback so that this 
            // will refer to the actionPager from within the timeout method
            var timeoutCallback = makeCallback(function()
			{
                if (this.getHashFromURL(window.location.href) != ajaxHash)
				{
                    window.location.replace(location.href+'#'+ajaxHash);
                }
            },this);
            setTimeout(timeoutCallback, 200);
            return true;
        }
        return false;
    },
    watchLocationForChange: function()
	{
        
        var newHash;
        // Retrieve the value for the new hash
        if (this.safariHistory !== false)
		{
            // From the history array for safari
            if (this.safariHistory[history.length])
			{
                newHash = this.safariHistory[history.length];
            }
        } else if (this.msieHistory !== false)
		{
            // From the location of the iframe in MSIE
            newHash = this.msieHistory.location.href.split('&')[0].split('=')[1];
        } else if (location.hash != '')
		{
            newHash = this.getHashFromURL(window.location.href);

        }
        if (newHash && this.lastHash != newHash)
		{
            if (this.msieHistory !== false && this.getHashFromURL(window.location.href) != newHash)
			{
                location.hash = newHash;
            }
            try {
                this.executeListeners(newHash);
                this.ajaxifyLinks();
            } catch(e)
			{
                alert(e);
            }
            this.lastHash = newHash;
        }
    },
    register: function(regex,method,context)
	{
        var obj = {'regex':regex};
        if(context)
		{
            obj.callback = function(matches){ method.apply(context,matches); };
        } else {

            obj.callback = function(matches){ method.apply(window,matches); };
        }

        this.callbacks.push(obj)
    }, convertURLToHash: function(url)
	{
        if (!url)
		{

            return '#';
        } else if(url.indexOf("#") != -1)
		{

            return url.split("#")[1];
        } else {

            if(url.indexOf("://") != -1)
			{
                url = url.match(/:\/\/[^\/]+(.*)/)[1];
            }

            return '#' + url.substr(this.ajaxifyRoot.length)
        }
    }, getHashFromURL: function(url)
	{
        if (!url || url.indexOf("#") == -1){ return ''; }
        return url.split("#")[1];
    }, getLocation: function()
	{
        if(!window.location.hash)
		{
            // Not one so make it
            var url = {host:null,hash:null}
            if (window.location.href.indexOf("#") > -1)
			{
                parts = window.location.href.split("#")[1];
                url.domain = parts[0];
                url.hash = parts[1];
            } else {
                url.domain = window.location;
            }
            return url;
        }
        return window.location;
    }, executeListeners: function(hash){
        for(var i in this.callbacks)
		{
            if((matches = hash.match(this.callbacks[i].regex)))
			{
                this.callbacks[i].callback(matches);
            }
        }
    }
}
window['JAY']['actionPager'] = actionPager;

function clone(myObj)
{
    if(typeof(myObj) != 'object') return myObj;
    if(myObj == null) return myObj;
    var myNewObj = new Object();
    for(var i in myObj)
	{
        myNewObj[i] = clone(myObj[i]);
    }
    return myNewObj;
}

var requestQueue = [];

function ajaxRequestQueue(url,options,queue)
{
    queue = queue || 'default';
    
    options = clone(options) || {};
    if(!requestQueue[queue]) requestQueue[queue] = [];
     
    var userCompleteListener = options.completeListener;

    options.completeListener = function()
	{
        if(userCompleteListener)
		{
            userCompleteListener.apply(this,arguments);        
        };

        requestQueue[queue].shift();

        if(requestQueue[queue][0])
		{
            var q = requestQueue[queue][0].req.send(requestQueue[queue][0].send);
        }
    }

    var userErrorListener = options.errorListener;

    options.errorListener = function()
	{
    
        if(userErrorListener)
		{
            userErrorListener.apply(this,arguments);        
        };

		requestQueue[queue].shift();

        if(requestQueue[queue].length)
		{
            var q = requestQueue[queue].shift();

            q.req.abort();

            var fakeRequest = new Object();

            fakeRequest.status = 0;
            fakeRequest.readyState = 4

            fakeRequest.responseText = null;
            fakeRequest.responseXML = null;

            fakeRequest.statusText = 'A request in the queue received an error';

            q.error.apply(fakeRequest);
        }       
    }

    requestQueue[queue].push(
	{
        req:getRequestObject(url,options),
        send:options.send,
        error:options.errorListener
    });
  
    if(requestQueue[queue].length == 1)
	{
        ajaxRequest(url,options);
    }
}

window['JAY']['ajaxRequestQueue'] = ajaxRequestQueue;

function autocompleter(input, url, prop)
{	
	if(!(input = $(input)));
	input.setAttribute("autocomplete", "off");
	var cnt = document.createElement("select"); 
	cnt.setAttribute('id', 'TTP');
	
	addEvent(input, 'keyup', function(W3CEvent)
	{
		preventDefault(W3CEvent);
		if(getKeyPressed(W3CEvent)['code'] == '40')
		{
			cnt.focus();
		}else
		{
			setStyle(cnt, {"visibility":'visible'});
			for(var f in cnt.options)
			{
				cnt.remove(f);
			}			
			var offSet = input.offsetWidth - 10;
			setStyle(cnt,{'position':'absolute','display':'block','z-index':'1000',
				'left':getPos(this)['x'] + 'px',
				'top':(getPos(this)['y'] + input.offsetHeight) + 'px'});
			
			prependChild($(document.body), cnt);
			
			addEvent($(document.body), 'click', function(e)
			{
				if(getTarget(e))
				{
					if(getTarget(e)['id'] != 'TTP' && getTarget(e)['id'] != input['id'])
					{
						removeTT();
					}
				}
			});			
			
			var H = 0;
			ajaxRequest(url + this.value,
			{
				completeListener:function()
				{
					var results = this.responseText.split("<br />");
					if(this.responseText != '')
					{
						cnt.size = results.length;
						
						for(var g in results)
						{
							var parts = results[g].split('|');
							
							if(parts[0] !== '')
							{						
								var opt = document.createElement("option");
								opt.text = parts[0] + ' - ' + parts[2];
								opt.value = parts[0].replace(/ /g, '');
								try
								{
									cnt.add(opt,null); // standards compliant
								}catch(ex)
								{
									cnt.add(opt); // IE only
								}								
								addEvent(cnt, 'click', function()
								{
									if(input)
									{
										input.value = this.options[this.selectedIndex].value.replace(/ /g, '');
										setStyle(this, {"visibility":'hidden'});
									}
								});								
								addEvent(cnt, 'keyup', function(W3CEvent)
								{
									if(getKeyPressed(W3CEvent)['code'] == '13')
									{	
										input.value = this.options[this.selectedIndex].value.replace(/ /g, '');
										setStyle(this, {"visibility":'hidden'});
									}
								});
							}
						}
					}else
					{
						var opt = document.createElement("option");
						opt.text = 'Please try another ISBN!';
						opt.value = '';
						try
						{
							cnt.add(opt,null); // standards compliant
						}catch(ex)
						{
							cnt.add(opt); // IE only
						}
					}
				}
			});
		}
	});
	
	function removeTT()
	{
		var timer = setTimeout(function()
		{
			setStyle(cnt, {"visibility":'hidden'});
			clearTimeout(timer);
		}, 1000);		
	}
}
window['JAY']['autocompleter'] = autocompleter;

function numberFormat(theNum)
{
    if(isNaN(theNum))
    {
        alert("Not a number: "+theNum);
        return "";
    }
    theNum = (theNum+"00.00").split(".");
    return theNum[0]+"."+Math.ceil(Number(theNum[1].substr(0,2)));
}//format as number

window['JAY']['numberFormat'] = numberFormat;

function CE(tag, addTo, name)
{
	var ce = document.createElement(tag);
	ce.setAttribute('id', '' + name);
	insertAfter(ce, $(addTo));
	return ce;
}

function message(ele, msg)
{
	if(browser() != 'm6')
	{
		var div = document.createElement("div");
		div.setAttribute("id", "msg");
		setStyle(div,{'position':'absolute','border':'2px #FF0000 solid','background-color':'#FFFFFF','z-index':'1000','font-size':'11px','padding':'3px',
				'left':(getPos(ele)['x'] + ele.offsetWidth) + 'px',
				'top':getPos(ele)['y'] + 'px'});
		div.innerHTML = msg;
	
		prependChild($(document.body), div);
		var timer = setTimeout(function()
		{
			if($("msg")){ $("msg").parentNode.removeChild($("msg")); }
			clearTimeout(timer);
		}, 3000);
	}
}
window['JAY']['message'] = message;

function dragDrop(obj)
{
	var dragObject = null;
	var mouseOffset = null;
	setStyle(obj, {'position':'absolute', 'cursor':'pointer','top':'0px','left':'70%'});
	addEvent(obj, 'mousedown', function(e)
	{
		var mousePos = getPointerPositionInDocument(e);
		var obsPos = getPos(this);
		
		mouseOffset = {'x':(mousePos.x - obsPos.x), 'y':(mousePos.y - obsPos.y)};
		dragObject = this;
	});
	addEvent(obj, 'mousemove', function(e)
	{
		e = getEventObject(e);
		var mousePos = getPointerPositionInDocument(e);
		
		if(dragObject)
		{
			setStyle(dragObject, {'top':(mousePos.y - (mouseOffset.y)) + 'px', 'left':(mousePos.x - (mouseOffset.x)) + 'px'});
			return false;
		}
	});
	addEvent(document.body, 'mouseup', function(e)
	{
		dragObject = null;
	});
}
window['JAY']['dragDrop'] = dragDrop;

function print_r( array, return_val ) {
    // Prints human-readable information about a variable
    // 
    // +    discuss at: http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_print_r/
    // +       version: 809.2411
    // +   original by: Michael White (http://getsprink.com)
    // +   improved by: Ben Bryan
    // *     example 1: print_r(1, true);
    // *     returns 1: 1
    
    var output = "", pad_char = " ", pad_val = 4;

    var formatArray = function (obj, cur_depth, pad_val, pad_char) {
        if (cur_depth > 0) {
            cur_depth++;
        }

        var base_pad = repeat_char(pad_val*cur_depth, pad_char);
        var thick_pad = repeat_char(pad_val*(cur_depth+1), pad_char);
        var str = "";

        if (obj instanceof Array || obj instanceof Object) {
            str += "Array\n" + base_pad + "(\n";
            for (var key in obj) {
                if (obj[key] instanceof Array) {
                    str += thick_pad + "["+key+"] => "+formatArray(obj[key], cur_depth+1, pad_val, pad_char);
                } else {
                    str += thick_pad + "["+key+"] => " + obj[key] + "\n";
                }
            }
            str += base_pad + ")\n";
        } else if(obj == null || obj == undefined) {
            str = '';
        } else {
            str = obj.toString();
        }

        return str;
    };

    var repeat_char = function (len, pad_char) {
        var str = "";
        for(var i=0; i < len; i++) { 
            str += pad_char; 
        };
        return str;
    };
    output = formatArray(array, 0, pad_val, pad_char);

    if (return_val !== true) {
        document.write("<pre>" + output + "</pre>");
        return true;
    } else {
        return output;
    }
}
window['JAY']['print_r'] = print_r;

})();