
	if(window.ActiveXObject) // for IE
	{
	//	TEMPORARY SWITCHED OF FOR IE
	/*
		include(styleUrl + 'ajaxslt/util.js');
		include(styleUrl + 'ajaxslt/xmltoken.js');
		include(styleUrl + 'ajaxslt/dom.js');
		include(styleUrl + 'ajaxslt/xpath.js');
	*/
	}

	function createXMLHttpRequest()
	{
		if(window.XMLHttpRequest) return new XMLHttpRequest();
		else if(window.ActiveXObject)
		{
			try { return new ActiveXObject('Msxml2.XMLHTTP'); }
			catch (e) { return new ActiveXObject('Microsoft.XMLHTTP'); }
		}
	}

	function createDOMDocument()
	{
		if(window.ActiveXObject)
		{
			try { return new ActiveXObject('Microsoft.XMLDOM'); }
			catch (e) { return new ActiveXObject('Msxml2.DOMDocument'); }
		}
		return document.implementation.createDocument("", "", null);
	}

	function cloneDocument(doc)
	{
		return loadXmlFromString(saveXml(doc));
	}

	function getFrameDocument(frame)
	{
		if(frame.contentWindow.document) return frame.contentWindow.document;
		else if(frame.contentDocument) return frame.contentDocument;
		return frame.document;
	}

	function getFrameWindow(frame)
	{
		if(frame.contentWindow) return frame.contentWindow;
		return frame.window;
	}

//  *** XSLT transformations ***

	function importChilds(element, doc, importNamespace)
	{
		var fragment = doc.createDocumentFragment();
		for(var i = 0; i < element.childNodes.length; i++)
		{
			var childNode = element.childNodes[i];
			switch(childNode.nodeType)
			{
				case 1: // ELEMENT_NODE
					if(childNode.nodeName.indexOf('/') < 0) // IE!
						fragment.appendChild(importElement(childNode, doc, importNamespace));
					break;
				case 3:  // TEXT_NODE
					fragment.appendChild(doc.createTextNode(childNode.nodeValue));
					break;
				case 4:  // CDATA_SECTION_NODE
					fragment.appendChild(doc.createCDATASection(childNode.data));
					break;
				case 5:  // ENTITY_REFERENCE_NODE
					fragment.appendChild(doc.createComment('ENTITY_REFERENCE_NODE'));
					break;
				case 6:  // ENTITY_NODE
					fragment.appendChild(doc.createComment('ENTITY_NODE'));
					break;
				case 7:  // PROCESSING_INSTRUCTION_NODE
					fragment.appendChild(doc.createComment('PROCESSING_INSTRUCTION_NODE'));
					break;
				case 8:  // COMMENT_NODE
					fragment.appendChild(doc.createComment(childNode.data));
					break;
			}
		}

		return fragment;
	}

	function importElement(element, doc, importNamespace)
	{
		if(importNamespace == undefined) importNamespace = true;
		
		try { var imported = importNamespace && element.namespaceURI ? doc.createElementNS(element.namespaceURI, element.nodeName/*.toLowerCase()*/) : doc.createElement(element.nodeName/*.toLowerCase()*/); }
		catch(e) { var imported = doc.createElement(element.nodeName/*.toLowerCase()*/); }

		for(var i = 0; i < element.attributes.length; i++)
		{
			var attribute = element.attributes[i];
			if(attribute.value != 'null' && attribute.value != '')
			{
				imported.setAttribute(attribute.nodeName, attribute.value);
			}
		}

		var fragment = importChilds(element, doc, importNamespace);
		
		if(fragment.childNodes.length) imported.appendChild(fragment);

		return imported;
	}

	function transform(doc, stylesheetName)
	{
		// TODO: optimization - async loading
		if(window.XSLTProcessor)
		{
			var xsltProcessor = new XSLTProcessor();
			xsltProcessor.importStylesheet(loadXml(stylesheetName));

			/*
			try { xsltProcessor.importStylesheet(loadXml(stylesheetName)); }
			catch(e) {
				
				var tmp = loadNormalizedXslt(stylesheetName);
				alert(saveXml(tmp));
				xsltProcessor.importStylesheet(loadNormalizedXslt(stylesheetName));
			
			} // Opera
			*/
			return xsltProcessor.transformToDocument(doc);

			//// TODO: INCLUDES
		}
		else if(window.ActiveXObject)
		{
			var result = createDOMDocument();
			result.async = false;
			result.validateOnParse = true;

			var xsltDoc = createDOMDocument();
			try
			{
				xsltDoc.resolveExternals = true;
				xsltDoc.setProperty("AllowDocumentFunction", true);
			}
			catch(e) {}
            xsltDoc.async = false;
            xsltDoc.load(stylesheetName);

			var xslOutput = selectNode('xsl:output[@doctype-public]', xsltDoc.documentElement);
			if(xslOutput != null) xslOutput.removeAttribute('doctype-public');
			var xslOutput = selectNode('xsl:output[@doctype-system]', xsltDoc.documentElement);
			if(xslOutput != null) xslOutput.removeAttribute('doctype-system');

			doc.transformNodeToObject(xsltDoc, result);
			
			return result;
		}
	}

	// for Opera
	function loadNormalizedXslt(fileName)
	{
		var cacheKey = 'norm-xslt:' + fileName;
		if(filesCache[cacheKey] !== undefined) return filesCache[cacheKey];

		var doc = loadXml(fileName);
		var node = doc.documentElement.firstChild;
		while(node)
		{
			if(node.nodeType == 1 /* ELEMENT_NODE */ && node.nodeName.match(/(:|^)(include|import)$/i) && node.namespaceURI == 'http://www.w3.org/1999/XSL/Transform')
			{
				var includeElement = node;
				var ref = includeElement.getAttribute('href');

				if(fileName.lastIndexOf('/'))
				{
					var base = fileName.substr(0, fileName.lastIndexOf('/'));

					while(ref.indexOf('../') == 0)
					{
						base = base.substr(0, base.lastIndexOf('/'));
						ref = ref.substr(3);
					}

					ref = base + '/' + ref;
				}

				var childDoc = loadNormalizedXslt(ref);
				doc.documentElement.insertBefore(importChilds(childDoc.documentElement, doc), includeElement);
				node = includeElement.nextSibling;
				doc.documentElement.removeChild(includeElement);
			}
			else node = node.nextSibling;
		}

		return doc;
	}


//  *** XML loading and saving ***

	var filesCache = new Object();

	function loadXml(fileName, postData, callback)
	{
		var async = (callback != undefined);
		var request = createXMLHttpRequest();

		if(async)
		{
			request.onreadystatechange = function()
			{
				if(request.readyState == 4)
				{
					if(request.status == 200)
						callback(request.responseXML);
					else
					{
						alert('loadXml: ' + request.statusText);
					}
				}
			}
		}

		if(postData == undefined)
		{
//			var cacheKey = 'xml:' + fileName;
//			if(filesCache[cacheKey] !== undefined) return filesCache[cacheKey];
/*
			if(window.ActiveXObject)
				try
				{
					var doc = createDOMDocument();
					doc.async = false;
					doc.load(fileName);
					return filesCache[cacheKey] = doc;
				}
				catch(e) {}
*/				
			request.open('GET', fileName, async);
			request.setRequestHeader("Connection", "close");
			request.send(null);

//			return filesCache[cacheKey] = request.responseXML;
		}
		else
		{
			request.open('POST', fileName, async);
			request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			request.setRequestHeader("Content-length", postData.length);
			request.setRequestHeader("Connection", "close");

			request.send(postData);
		}

		if(!async) return request.responseXML;
	}

	function loadXmlFromString(string)
	{
		if(window.DOMParser)
		{
			var parser = new DOMParser();
			return parser.parseFromString(string, "text/xml");
		}
		else if(window.ActiveXObject)
			try
			{
				var doc = createDOMDocument();
				doc.async = false;
				doc.loadXML(string);
				return doc;
			}
			catch(e) {}
	}

	function saveXml(doc)
	{
		if(window.XMLSerializer)
		{
			var serializer = new XMLSerializer();
			try{ return XML(serializer.serializeToString(doc)).toXMLString(); }
			catch(e) { return serializer.serializeToString(doc); }
		}
		else return doc.xml
	}

//  *** XPath ***
	function selectNode(xpath, contextNode)
	{
		if(window.ActiveXObject)
			try
			{
				contextNode.ownerDocument.setProperty("SelectionLanguage", "XPath");
				return contextNode.selectSingleNode(xpath);
			}
			catch(e)
			{
				// Using ajaxslt modules
				return xpathParse(xpath).evaluate(new ExprContext(contextNode)).nodeSetValue()[0];
			}

		var result = contextNode.ownerDocument.evaluate(xpath, contextNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
		return result.singleNodeValue;
	}
	
	function selectNodes(xpath, contextNode)
	{
		if(window.ActiveXObject)
			try
			{
				//contextNode.ownerDocument.setProperty("SelectionLanguage", "XPath");
				return contextNode.selectNodes(xpath);
			}
			catch(e)
			{
				// Using ajaxslt modules
				return xpathParse(xpath).evaluate(new ExprContext(contextNode)).nodeSetValue();
			}
		
		var iterator = contextNode.ownerDocument.evaluate(xpath, contextNode, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
		var result = [];
		var node = iterator.iterateNext();
		while(node)
		{
			result.push(node);
			node = iterator.iterateNext();
		}
		return result;
	}
	
	function getScrollOffset() 
	{
		var top = 0, left = 0;
		if(typeof( window.pageYOffset ) == 'number' ) //Netscape compliant
		{
			top = window.pageYOffset;
			left = window.pageXOffset;
		} 
		else if(document.body && (document.body.scrollLeft || document.body.scrollTop))  //DOM compliant
		{
			top = document.body.scrollTop;
			left = document.body.scrollLeft;
		} 
		else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) 
		{
			//IE6 standards compliant mode
			top = document.documentElement.scrollTop;
			left = document.documentElement.scrollLeft;
		  }
		return {left: left, top: top};
	}	

	// classes
	function checkClass(className, element)
	{
		var pattern = new RegExp(className);
		return element.className.search(pattern) >= 0;
	}

	function setClass(className, element)
	{
		if(!checkClass(className, element)) element.className += ' ' + className;
	}

	function clearClass(className, element)
	{
		var pattern = new RegExp(className + ' ?', 'g');
		if(checkClass(className, element))  element.className = element.className.replace(pattern, '');
	}

	function toggleClass(className, element)
	{
		var pattern = new RegExp(className + ' ?', 'g');
		if(checkClass(className, element)) element.className = element.className.replace(pattern, '');
		else  element.className += ' ' + className;
	}

