/*
 * ====================================================================
 * About Sarissa: http://dev.abiss.gr/sarissa
 * ====================================================================
 * Sarissa is an ECMAScript library acting as a cross-browser wrapper for native XML APIs.
 * The library supports Gecko based browsers like Mozilla and Firefox,
 * Internet Explorer (5.5+ with MSXML3.0+), Konqueror, Safari and Opera
 * @author: Copyright 2004-2007 Emmanouil Batsis, mailto: mbatsis at users full stop sourceforge full stop net
 * ====================================================================
 * Licence
 * ====================================================================
 * Sarissa is free software distributed under the GNU GPL version 2 (see <a href="gpl.txt">gpl.txt</a>) or higher, 
 * GNU LGPL version 2.1 (see <a href="lgpl.txt">lgpl.txt</a>) or higher and Apache Software License 2.0 or higher 
 * (see <a href="asl.txt">asl.txt</a>). This means you can choose one of the three and use that if you like. If 
 * you make modifications under the ASL, i would appreciate it if you submitted those.
 * In case your copy of Sarissa does not include the license texts, you may find
 * them online in various formats at <a href="http://www.gnu.org">http://www.gnu.org</a> and 
 * <a href="http://www.apache.org">http://www.apache.org</a>.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 
 * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
 * WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE 
 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Extensively modified by Ittrium LLC - 11March2008 
 */
/** Sarissa is a utility class */
function Sarissa(){}
Sarissa._SARISSA_HAS_DOM_IMPLEMENTATION = document.implementation && true;
Sarissa._SARISSA_HAS_DOM_CREATE_DOCUMENT = Sarissa._SARISSA_HAS_DOM_IMPLEMENTATION && document.implementation.createDocument;
Sarissa._SARISSA_HAS_DOM_FEATURE = Sarissa._SARISSA_HAS_DOM_IMPLEMENTATION && document.implementation.hasFeature;
Sarissa._SARISSA_IS_MOZ = Sarissa._SARISSA_HAS_DOM_CREATE_DOCUMENT && Sarissa._SARISSA_HAS_DOM_FEATURE;
Sarissa._SARISSA_IS_SAFARI = navigator.userAgent.toLowerCase().indexOf("safari") != -1 || navigator.userAgent.toLowerCase().indexOf("konqueror") != -1;
Sarissa._SARISSA_IS_SAFARI_OLD = Sarissa._SARISSA_IS_SAFARI && (parseInt((navigator.userAgent.match(/AppleWebKit\/(\d+)/)||{})[1], 10) < 420);
Sarissa._SARISSA_IS_IE = document.all && window.ActiveXObject && navigator.userAgent.toLowerCase().indexOf("msie") > -1  && navigator.userAgent.toLowerCase().indexOf("opera") == -1;
Sarissa._SARISSA_IS_OPERA = navigator.userAgent.toLowerCase().indexOf("opera") != -1;
// IE initialization
if(Sarissa._SARISSA_IS_IE){
    /**
     * Called when the sarissa.js file is parsed, to pick most recent
     * ProgIDs for IE, then gets destroyed.
     * @memberOf Sarissa
     * @private
     * @param idList an array of MSXML PROGIDs from which the most recent will be picked for a given object
     * @param enabledList an array of arrays where each array has two items; the index of the PROGID for 
     *        which a certain feature is enabled
     */
    Sarissa.pickRecentProgID = function (idList){
        // found progID flag
        var bFound = false, e;
        var o2Store;
        for(var i=0; i < idList.length && !bFound; i++){
            try{
                var oDoc = new ActiveXObject(idList[i]);
                o2Store = idList[i];
                bFound = true;
            }catch (objException){
                // trap; try next progID
                e = objException;
            }
        }
        if (!bFound) {
            throw "Could not retrieve a valid progID of Class: " + idList[idList.length-1]+". (original exception: "+e+")";
        }
        idList = null;
        return o2Store;
    };
    // pick best available MSXML progIDs
    var _SARISSA_THREADEDDOM_PROGID = null;
    var _SARISSA_XSLTEMPLATE_PROGID = null;
    var _SARISSA_DOM_PROGID = null;
    var _ITTRIUM_AJAX_PROGID = null;
	
	// Create a DOM 
    Sarissa.createEmptyDOM = function(){
        if(!_SARISSA_DOM_PROGID){
            _SARISSA_DOM_PROGID = Sarissa.pickRecentProgID(["Msxml2.DOMDocument.6.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"]);
        }
        var oDoc = new ActiveXObject(_SARISSA_DOM_PROGID);
        return( oDoc );
    };

    /** A class that reuses the same XSLT stylesheet for multiple transforms */
    XSLTProcessor = function(){
        if(!_SARISSA_THREADEDDOM_PROGID){
            _SARISSA_THREADEDDOM_PROGID = Sarissa.pickRecentProgID(["MSXML2.FreeThreadedDOMDocument.6.0", "MSXML2.FreeThreadedDOMDocument.3.0"]);
        }
        if(!_SARISSA_XSLTEMPLATE_PROGID){
            _SARISSA_XSLTEMPLATE_PROGID = Sarissa.pickRecentProgID(["Msxml2.XSLTemplate.6.0", "MSXML2.XSLTemplate.3.0"]);
        }
        this.template = new ActiveXObject(_SARISSA_XSLTEMPLATE_PROGID);
        this.processor = null;
    };
    /** Imports the given XSLT DOM and compiles it to a reusable transform
        NOTE: If the stylesheet was loaded from a URL and contains xsl:import or 
              xsl:include elements,it will be reloaded to resolve those
     */
    XSLTProcessor.prototype.importStylesheet = function(xslDoc){
        xslDoc.setProperty("SelectionLanguage", "XPath");
        xslDoc.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
        // convert stylesheet to free threaded
        var converted = new ActiveXObject(_SARISSA_THREADEDDOM_PROGID);
        // make included/imported stylesheets work if exist and xsl was originally loaded from url
        try{
            converted.resolveExternals = true; 
            converted.setProperty("AllowDocumentFunction", true); 
        } catch(e){
            // Ignore. "AllowDocumentFunction" is only supported in MSXML 3.0 SP4 and later.
        } 
        if(xslDoc.url && xslDoc.selectSingleNode("//xsl:*[local-name() = 'import' or local-name() = 'include']") != null){
            converted.async = false;
            converted.load(xslDoc.url);
        } else {
            converted.loadXML(xslDoc.xml);
        }
        converted.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
        var output = converted.selectSingleNode("//xsl:output");
        if( output ) {
            this.outputMethod = output.getAttribute("method");
        } else {
            delete this.outputMethod;
        } 
        this.template.stylesheet = converted;
        this.processor = this.template.createProcessor();
        // for getParameter and clearParameters
        this.paramsSet = [];
    };

    /** Transform the given XML DOM and return the transformation result */
    XSLTProcessor.prototype.transformToDocument = function(sourceDoc){
        // fix for bug 1549749
        var outDoc;
        this.processor.input=sourceDoc;
        outDoc=new ActiveXObject(_SARISSA_THREADEDDOM_PROGID);
        this.processor.output=outDoc;
        this.processor.transform();
        return outDoc;
    };
        
    /** Set global XSLT parameter of the imported stylesheet */
    XSLTProcessor.prototype.setParameter = function(nsURI, name, value){
         value = value ? value : "";
         // nsURI is optional but cannot be null
         if(nsURI && (nsURI.length > 0)){
             this.processor.addParameter(name, value, nsURI);
         } else {
             this.processor.addParameter(name, value);
         }
    };
}else{ /* end IE initialization, try to deal with real browsers now ;-) */
    Sarissa.createEmptyDOM = function(){
        var oDoc = document.implementation.createDocument(null, null, null);
        return oDoc;
    };
}
if( !window.XMLSerializer ) {
    XMLSerializer = function(){};
    XMLSerializer.prototype.serializeToString = function(oNode) { return oNode.xml; };
}
//==========================================
// Common stuff
//==========================================
/** Escape the given string chacters that correspond to the five predefined XML entities */
Sarissa.escape = function(sXml){
    return sXml.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
};

/** Unescape the given string. This turns the occurences of the predefined XML */
Sarissa.unescape = function(sXml){
    return sXml.replace(/&apos;/g,"'").replace(/&quot;/g,"\"").replace(/&gt;/g,">").replace(/&lt;/g,"<").replace(/&amp;/g,"&");
};
//===========================================
// Ittrium common AJAX support
//===========================================
/*** Simple AJAX support -- request a dom ***/
function doAJAXGet( pURL, pCallback, p1, p2, p3, p4 ) {
    var httpRequest = getAJAXHandler();
    if ( !httpRequest ) {
        return false;
    }
    if ( pCallback != null ) {
    	httpRequest.onreadystatechange = function() { ajaxResponse( httpRequest, pCallback, p1, p2, p3, p4 ); };
    }
    httpRequest.open( 'GET', pURL.replace("&amp;","&"), true );
    httpRequest.send( '' );
    return true;
}
/*** Simple AJAX support -- post a dom ***/
function doAJAXPost( pURL, pParams, pType, pCallback, p1, p2, p3, p4 ) {
    var httpRequest = getAJAXHandler();
    if ( !httpRequest ) {
        return false;
    }
    if ( pType.length == 0 ) pType = 'application/x-www-form-urlencoded';
    if ( pCallback != null ) {
    	httpRequest.onreadystatechange = function() { ajaxResponse( httpRequest, pCallback, p1, p2, p3, p4 ); };
    }
    httpRequest.open( 'POST', pURL.replace("&amp;","&"), true );
	httpRequest.setRequestHeader('Content-Type', pType );
    httpRequest.send( pParams );
    return true;
}
function getAJAXHandler() {
    var httpRequest;
    if ( window.XMLHttpRequest ) { 
    	// Mozilla, Safari, ...
        httpRequest = new XMLHttpRequest();
        if ( httpRequest.overrideMimeType ) {
        	// Force into XML mode
            httpRequest.overrideMimeType( 'text/xml' );
        }
    }  else if ( window.ActiveXObject ) { 
    	// IE
    	if(!_ITTRIUM_AJAX_PROGID){
            _ITTRIUM_AJAX_PROGID = 
            	Sarissa.pickRecentProgID(["Msxml2.XMLHTTP.6.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"]);
        }
        httpRequest = new ActiveXObject( _ITTRIUM_AJAX_PROGID );
    }
    return( httpRequest );
}
function ajaxResponse( httpRequest, pCallback, p1, p2, p3, p4 ) {
    try {
    	// Wait until the response is ready
	    if ( httpRequest.readyState == 4 ) {
	        if ( httpRequest.status == 200 ) {
	        	pCallback( httpRequest, p1, p2, p3, p4 );
	            //alert( httpRequest.responseText + pCallback );
	        } else {
	            alert( 'AJAX request failed: ' + httpRequest.status );
	        }
	    }
	} catch( ex ) {
		alert( 'AJAX callback failed: ' + ex.message );
	}
}

/** AJAX callback that does nothing **/
function doAJAXNull( httpRequest ) {
}
/** AJAX callback that replaces text based on an xpath into the dom, and a target id */
function doAJAXReplace( httpRequest, xpath, divID ) {
    var target = getElement( divID );
    if ( target ) {
		var xmldoc = httpRequest.responseXML;
		includeNodes( target, xmldoc.childNodes, xpath, true );
//alert( "INNER: " + target.innerHTML );
	}
}

// Match each level to a segment in the xpath
function includeNodes( target, nodeList, xpath, clearTarget ) {
    try {
		if ( nodeList && (nodeList.length > 0) ) {
//alert( "LIST: " + nodeList.length + "/" + xpath );
			if ( xpath.length == 0 ) {
				if ( clearTarget ) {
					while( target.lastChild ) {
						target.removeChild( target.lastChild );
					}
					clearTarget = false;
				}
		    	for( var i = 0; i < nodeList.length; i += 1 ) {
		    		var childNode = nodeList[i];
		    		importHTML( target, childNode );
		    	}
			} else {
			    while( xpath.length > 0 ) {
			    	var tagName = xpath;
			    	var index = xpath.indexOf( '/' );
			    	if ( index >= 0 ) {
			    		tagName = xpath.substring( 0, index );
			    		xpath = xpath.substring( index+1 );
			    	} else {
			    		xpath = "";
			    	}
				    for( var j = 0; j < nodeList.length; j += 1 ) {
				    	var childNode = nodeList[j];
//alert( "CHILD: " + childNode.nodeName + "/" + tagName );
				    	if ( childNode.nodeName == tagName ) {
				    		clearTarget = includeNodes( target, childNode.childNodes, xpath, clearTarget );
				    	}
				    }
			    }
			}
		}
	} catch( ex ) {
		alert( "Failed to includeNodes: " + ex.message );
	}
	return clearTarget;
}
/* IE does not support importNode(), and Firefox did not want
   to apply formatting to xml nodes imported into an html document,
   so do the work ourself.
 */
function importHTML( target, source ) {
//alert( "IMPORT: " + target.nodeName + "/" + source.nodeName );
    try {
		switch( source.nodeType ) {
		case 1: /*document.ELEMENT_NODE*/
	        var newNode;
	        var nodeName = source.nodeName.toLowerCase();
	        switch( nodeName ) {
	        case "input":
	        	newNode = createElementWithName( "input", source.getAttribute( "name" ) );
	        	newNode.type = source.getAttribute( "type" );
	            break;
	        case "select":
	        	newNode = createElementWithName( "select", source.getAttribute( "name" ) );
	        	newNode.multiple = false;
	        	newNode.selectedIndex = -1;
	        	newNode.value = null;
	            break;
	        case "option":
	        	newNode = createElementWithName( "option", source.getAttribute( "name" ) );
	        	newNode.selected = false;
	        	newNode.defaultSelected = false;
	            break;
	        case "script":
	        	newNode = document.createElement( "script" );
	        	var newText = '';
		        if ( source.childNodes && (source.childNodes.length > 0) ) {
		            for (var i = 0; i < source.childNodes.length; i += 1 ) {
		          	  newText += source.childNodes[i].nodeValue;
		            }
		        }
		        newNode.text = newText;
	        	source = null;
	        	break;
	        default:
	        	newNode = createElementWithName( source.nodeName, source.getAttribute( "name" ) );
	        	break;
	        }
	        target.appendChild( newNode );
	        
	        if ( (source != null) && source.attributes && (source.attributes.length > 0) ) {
	          for (var i = 0; i < source.attributes.length; i += 1 ) {
	          	var attrNode = source.attributes[i];
	          	var attrName = attrNode.nodeName.toLowerCase();
				if ( attrName == "style" ) {
					newNode.style.cssText = attrNode.nodeValue;
	        	} else if ( attrName == "checked" ) {
	        	    newNode.checked = true;
	        	} else if ( attrName == "selected" ) {
	        		newNode.selected = true;
	        	} else if ( attrName == "multiple" ) {
	        		newNode.multiple = true;
	        		newNode.selectedIndex = -1;
	        	} else if ( attrName == "value" ) {
	        		newNode.value = attrNode.nodeValue;
				} else {
					var newAttr = document.createAttribute( attrNode.nodeName );
					newAttr.nodeValue = attrNode.nodeValue;
					newNode.setAttributeNode( newAttr );
				}
	          }
	        }
	        if ( (source != null) && source.childNodes && (source.childNodes.length > 0) ) {
	        	if ( (nodeName == "select") && newNode.multiple ) {
	        		// IE screws up the first option in multi select (I suspect defaultSelected)
			        for (var i = 0; i < source.childNodes.length; i += 1 ) {
			        	var childNode = source.childNodes[i];
			        	var isSelected = childNode.getAttribute( "selected" );
			        	
			          	importHTML( newNode, childNode );
			          	
			          	if ( (i == 0) && (isSelected == null) ) {
			          		newNode.selectedIndex = -1;
			          	}
			        }
	        	} else {
			        for (var i = 0; i < source.childNodes.length; i += 1 ) {
			          	importHTML( newNode, source.childNodes[i] );
			        }
			    }
			}
	        break;
		case 3: /*document.TEXT_NODE*/
		case 4: /*document.CDATA_SECTION_NODE*/
	        var newText = document.createTextNode( source.nodeValue );
	        target.appendChild( newText );
	        break;
		}
	} catch( ex ) {
		alert( "ImportHTML failed: " + ex + "- " + target.nodeName + "/" + source.nodeName );
	}
}
function createElementWithName(type, name) {
  var element = null;
  if ( name != null ) {
  	if (document.all) {
    	/* IE does not support setting the .name property for dom created objects */
		element = document.createElement( '<'+type+' name="'+name+'"></'+type+'>' );
	} else {
		element = document.createElement( type );
  		element.setAttribute('name', name);
  	}
  } else {
  	element = document.createElement(type);
  }
  return element;
}



/** A Class that supports AJAX popups with client side xsl transformations */
function popupTransformLoad( httpRequest, handler ) {
    try {
		handler.setTransform( httpRequest.responseXML );
	} catch( ex ) {
		alert( 'popupTransformLoad failed: ' + ex.message );
	}
}
function popupXMLLoad( httpRequest, handler, mustRefresh ) {
	if ( typeof mustRefresh != "undefined" ) {
		handler.refreshRequested = mustRefresh;
	} else {
	    handler.refreshRequested = true;
	}
    try {
		handler.setData( httpRequest.responseXML );
	} catch( ex ) {
		alert( 'popupXMLLoad failed: ' + ex.message );
	}
}
PopupHandler = function( varname ) {
    this.varname = varname;
    this.reqDefault = null;
    
	this.xmlDom = null;
	this.xmlDomRequested = 0;
	
    this.xslProcessor = null;
    this.xslTransformRequested = 0;
    
    this.refreshRequested = false;
    
    this.baseElement = null;
    this.popupElement = null;
    this.xpath = null;
    
    this.ctrlPressed=0;
    this.altPressed=0;
    this.shiftPressed=0;
};
PopupHandler.prototype.setTransform = function( xsltDOM ) {
	if ( this.xslTransformRequested > 0 ) {
    	aProcessor = new XSLTProcessor();
    	aProcessor.importStylesheet( xsltDOM );
    	aProcessor.setParameter('','PopupHandler',this.varname);
    	this.xslProcessor = aProcessor;
    	this.xslTransformRequested = 0;
    }
};
PopupHandler.prototype.getData = function() { return xmlDom; };
PopupHandler.prototype.setData = function( dataDOM ) {
    if ( typeof dataDOM != "undefined" ) {
		this.xmlDom = dataDOM;
	}
	if ( this.xslProcessor == null ) {
		// Transform has not finished loading
		if ( this.xslTransformRequested > 0 ) {
			setTimeout( this.varname + ".setData()", 500 );
		}
		this.xslTransformRequested -= 1;
		return;
	}
	this.xmlDomRequested = 0;
	if ( this.refreshRequested ) {
		this.refresh();
	}
}
PopupHandler.prototype.openPopup = function( baseid, popupid, request, transform, xpath ) {
	if ( this.xmlDomRequested > 0 ) {
		this.xmlDomRequested = 0;
		throw( "request already pending" );
	}
	this.xpath = xpath;

   	this.baseElement = getElement( baseid );
   	this.popupElement = getElement( popupid );
   	this.baseElement.style.display = "none";
   	this.popupElement.style.display = "block";
   	
	if ( (transform.length > 0) && (this.xslProcessor == null) ) {
		// Ask for the transform
    	this.xslTransformRequested = 60;
		doAJAXGet( transform, popupTransformLoad, this );
	}
	if ( request.length > 0 ) {
		// The open request becomes the default for posting
		this.reqDefault = request;
		// Ask for the data
		var separator = "&";
		if ( request.indexOf( "?" ) < 0 ) separator = "?";
		this.xmlDomRequested = 1;
		doAJAXGet( request + separator + 'ajaxid=' + this.popupElement.id, popupXMLLoad, this );
	}
};
PopupHandler.prototype.closePopup = function( request ) {
    if ( request.length > 0 ) {
    	var serializer = new XMLSerializer();
    	var xmldata = serializer.serializeToString( this.xmlDom );
    	
		var separator = "&";
		if ( request.indexOf( "?" ) < 0 ) separator = "?";
		doAJAXPost( request + separator + 'ajaxid=' + this.popupElement.id, xmldata, 'text/xml', doAJAXNull );
    }
    this.popupElement.style.display = "none";    
    this.baseElement.style.display = "block";
};
PopupHandler.prototype.post = function( refresh, request, dom ) {
	if ( typeof dom == "undefined" ) dom = this.xmlDom;
	
    var serializer = new XMLSerializer();
    var xmldata = serializer.serializeToString( dom );
    	
    if ( (typeof request == "undefined") || (request.length == 0) ) request = this.reqDefault;
	var separator = "&";
	if ( request.indexOf( "?" ) < 0 ) separator = "?";
	if ( refresh > 0 ) {
		this.xmlDomRequested = 1;
		doAJAXPost( request + separator + 'ajaxid=' + this.popupElement.id, xmldata, 'text/xml'
					, popupXMLLoad, this, (refresh > 1) );
	} else {
		doAJAXPost( request + separator + 'ajaxid=' + this.popupElement.id, xmldata, 'text/xml', null );
	}
};
PopupHandler.prototype.refresh = function() {
    this.refreshRequested = false;
	var xhtmldoc;
	try {
    	xhtmldoc = this.xslProcessor.transformToDocument( this.xmlDom );
//alert( 'Transformed: ' + (new XMLSerializer()).serializeToString( xhtmldoc ) );
    } catch( ex ) {
    	alert( 'Failed -' + ex.message + '- to transform: ' + (new XMLSerializer()).serializeToString( this.xmlDom ) );
    	return;
    }
	includeNodes( this.popupElement, xhtmldoc.childNodes, this.xpath, true );
	if(Sarissa._SARISSA_IS_IE) { /* I have no idea why IE needs the following, but it does */
		var text = this.popupElement.innerHTML;
		this.popupElement.innerHTML = text;
	}
};
PopupHandler.prototype.isRequestActive = function( ) {
	return( this.xmlDomRequested > 0 );
};
PopupHandler.prototype.findNode = function( xpath ) {
	var result;
	if(this.xmlDom.evaluate){
		result = this.xmlDom.evaluate( xpath, this.xmlDom, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue;
	} else {
		result = this.xmlDom.selectSingleNode(xpath);
	}
	return( result );
};
PopupHandler.prototype.findNthNode = function( xpath, subtag, slot ) {
	var result;
	if(this.xmlDom.evaluate){
		var fullPath = xpath + "/" + subtag + "[" + slot + "]";
		result = this.xmlDom.evaluate( fullPath, this.xmlDom, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue;
	} else {
		result = this.xmlDom.selectSingleNode(xpath);
		if ( result != null ) {
			var subNode = result.firstChild;
			while( subNode != null ) {
				if ( subNode.nodeName == subtag ) {
					if ( --slot <= 0 ) {
						return( subNode );
					}
				}
				subNode = subNode.nextSibling;			
			}
			result = null;
		}
	}
	return( result );
};
PopupHandler.prototype.findNodes = function( xpath ) {
	var result;
	if(this.xmlDom.evaluate){
		// NOTE firefox is very touchy about changing the items just found, use a snapshot
		result = this.xmlDom.evaluate( xpath, this.xmlDom, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );
		result.nextNodeIndex = 0;
		result.nextNode = function() { return this.snapshotItem( this.nextNodeIndex++ ); }
	} else {
		result = this.xmlDom.selectNodes(xpath);
	}
	return( result );
};
PopupHandler.prototype.keyModifiers = function( e ) {
	var evt = (!e) ? window.event : e;
	this.shiftPressed = evt.shiftKey;
	this.altPressed   = evt.altKey;
	this.ctrlPressed  = evt.ctrlKey;
	evt.cancelBubble = true;
	if (evt.stopPropagation) evt.stopPropagation();
}





