/**
* Sitefactor Rich Internet Application standart library, v 1.0
* TODO: http://xhtml.ru/2006/06/21/onload/
*/
function png(img){ // png prepared from stupid msie 
	if(img.runtimeStyle && img.src.match( /\.png$/ )){
		img.runtimeStyle.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src='	+ img.src + ', sizingMethod=scale)'; img.src = '/sitefactor/0.gif';
	}
}
function getElements(tagName, attrName, attrValue){ // выборка элементов по тегу, атрибуту и/или значению атрибута
	var startSet; var endSet = new Array( );
	if(tagName) startSet = document.getElementsByTagName(tagName);    
	else startSet = (document.all) ? document.all : document.getElementsByTagName("*");
	if(attrName){
		for(var i = 0; i < startSet.length; i++){
			if(startSet[i].getAttribute(attrName)){
				if(attrValue){
					if(startSet[i].getAttribute(attrName) == attrValue) endSet[endSet.length] = startSet[i];
					else endSet[endSet.length] = startSet[i];
				}
			} else endSet = startSet;
		}
	} return endSet;
}
function getElementsByClass(oElm, className, strTagName){ // возвращает все элементы с нужным классом DEPRECATED
	var arrElements = oElm.getElementsByTagName(strTagName || "*"); var arrReturnElements = new Array();
	var oCurrent; var oAttribute;
    for(var i=0; i < arrElements.length; i++){
        oCurrent = arrElements[i]; if(oCurrent.className == className) arrReturnElements.push(oCurrent);
    } return arrReturnElements;
}
var Debug = new function(){ // методы отладки и вывода сообщений
	this.show = function(o){ var t = ""; if(o){ for(var i in o){t += i + ": " + o[i] + "\n";} alert(t); } }
	this.alert = function(message, type){ // выводит алерт
		if(!message) return; if(!type) type = 'info';
		try	{
			var alrt = document.createElement('div'); document.getElementById('alerter').appendChild(alrt); 
			alrt.className = type; alrt.innerHTML = message.replace('\n', '<br/>');
		}catch(e){ alert(message||e); }
	}
}
var Styles = new function(){ // работа со стилями
	// добавление класса элементу
	this.apply = function(el, cName){ el.className += ' ' + cName; }
	// удаление класса у элемента
	this.remove = function(el, cName){ el.className = el.className.replace( new RegExp(cName,'g'), ''); }
}
var Forms = new function(){ // работа с формами
	this.validate = function(form){ // проверка формы, в обязательных полях определять атрибуты tip и errmsg
		var fields = form.getElementsByTagName('input');
		for (var i = 0; i < fields.length; i++) { var el = fields.item(i); if(el.type == 'text') {
			var tip = el.getAttribute('tip'); var errm = el.getAttribute('errmsg');
			switch(tip){
				case "txt": // просто наличие данных
					if(!el.value) { this.errField(el, errm); return false; } break; 
				case "email": // e-mail
					if(!this.validEmail(el.value)){ this.errField(el, errm); return false; } break;
				case "tel": // обязательный номер телефона
					if(!el.value) { this.errField(el, errm); return false; } break; // корректность телефона
				default: // не требует проверки 
			}
		} } return true;
	}
	this.errField = function(el, errmsg) { // подсветка поля с ошибкой
		el.style.backgroundColor = "#FFCCCC"; el.focus(); if(errmsg) alert(errmsg);
	}
	this.validEmail = function(eml){ // проверка корректности e-mail
		return /^[^\s]+@([a-z0-9_\-\.]+\.)+[a-z]{2,4}$/i.test(eml); 
	} 
	this.validPassw = function(pwd){ // проверка корректности пароля
		return /^[a-zA-Z0-9_]{4,8}$/i.test(pwd); 
	} 
}
var Cookies = new function(){ // работа с куками
	this.get = function(name, asArray){ // возвращает значение куки по имени
		var dc = document.cookie; var prefix = name + "="; var begin = dc.indexOf("; " + prefix);
		if(begin == -1){ begin = dc.indexOf(prefix); if (begin != 0) return (asArray) ? [] : null; } else begin += 2;
        var end = document.cookie.indexOf(";", begin);
		if (end == -1) end = dc.length; var ret = unescape(dc.substring(begin + prefix.length, end));	
		if(asArray){ ret = eval("[" + ret + "]"); return ret || []; } else return ret;
	}
	this.set = function(name, data, expiries, path, host, secure){ // ставит куку с заданным именем
	// ДАННЫЕ ПРИХОДЯТ В МАССИВЕ, експирес - в днях !
		var expDate = new Date(); expDate.setDate(expDate.getDate() + expiries);
		document.cookie = name + "=" + ((typeof(data) == 'array') ? data.join(",") : data) + 
		((expiries) ? "; expiries=" + expDate.toGMTString() : "") +	('; path="/"') + ((host) ? "; domain=" + host : "") + ((secure) ? "; secure" : "");
	}
}
var RIA = new function(){ // враппер к библиотеке Котерова
	this.init = function(host){ // опциональная инициализация
		if(host) server = host;
	}
	this.query = function(className, methodName, argv, callback, onerror, asGET, noCache){
        // Создаем новый объект JSHttpRequest, Разрешаем кэширование 
		var req = new Subsys_JsHttpRequest_Js(); req.caching = (noCache) ? false : true;
        // Код, АВТОМАТИЧЕСКИ вызываемый при окончании загрузки асинхронного запроса.
		req.onreadystatechange = function() {
			if (req.readyState == 4) {
				if(req.responseJS._STATUS == 500 && onerror){ // проверка ошибки
					onerror(req.responseText); return false;
				} 
				if(callback) callback(req.responseText, req.responseJS); return true;
			}
		};
        // Подготваливаем объект. Посылаем данные запроса (задаются в виде хэша)
        req.open(asGET?'GET':'POST', server + '/' + className + '/' + methodName + '.RIA', true); req.send(argv);
	}
	var server = '/sitefactor'; // каталог с обработчиком ajax-запросов
}
/**
* Subsys_JsHttpRequest_Js: JavaScript DHTML data loader.
* (C) 2005 Dmitry Koterov, http://forum.dklab.ru/users/DmitryKoterov/
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* See http://www.gnu.org/copyleft/lesser.html
*
* Do not remove this comment if you want to use script!
* Не удаляйте данный комментарий, если вы хотите использовать скрипт!
*
* This library tries to use XMLHttpRequest (if available), and on 
* failure - use dynamically created <script> elements. Backend code
* is the same for both cases.
*
* @author Dmitry Koterov 
* @version 3.34
*/
function Subsys_JsHttpRequest_Js() { this._construct() }
(function() { // to create local-scope variables
    var COUNT = 0; var PENDING = {}; var CACHE = {};
    Subsys_JsHttpRequest_Js.dataReady = function(id, text, js) { // Called by server script on data load.
		document.body.style.cursor = 'default';
        var undef; var th = PENDING[id]; delete PENDING[id];
        if (th) {
            delete th._xmlReq; if (th.caching) CACHE[th.hash] = [text, js]; th._dataReady(text, js);
        } else if (typeof(th) != typeof(undef)) { alert("ScriptLoader: unknown pending id: "+id); }
    }
    Subsys_JsHttpRequest_Js.prototype = {
        // Standard properties.
        onreadystatechange:null, readyState:0, responseText:null, responseXML:null, status:200, statusText:"OK",
        // Additional properties.
        session_name:       "PHPSESSID",  // set to SID cookie or GET parameter name
        responseJS:         null,         // JavaScript response alerts and status hash
        caching:            false,        // need to use caching?
        fallbackToScript:   false,
        // Internals.
        _span:null, _id:null, _xmlReq:null, _openArg:null, _reqHeaders:null,
        dummy: function() {}, // empty function
        abort: function() {
            if (this._xmlReq) return this._xmlReq.abort();
            if (this._span) {
                this.readyState = 0;
                if (this.onreadystatechange) this.onreadystatechange();
                this._cleanupScript();
            }
        },
        open: function(method, url, asyncFlag, username, password) {
            this._openArg = {
                'method':method, 'url':url, 'asyncFlag':asyncFlag,
                'username':username != null? username : '',
                'password':password != null? password : ''
            };
            this._id = null; this._xmlReq = null; this._reqHeaders = []; return true;
        },
        send: function(content) {
			document.body.style.cursor = 'wait';
            var id = (new Date().getTime()) + "" + COUNT++;
            // Build QUERY_STRING from query hash.
            var query = this._hash2query(content);
            // Append SID to original URL now.
            var url = this._openArg.url; var sid = this._getSid();
            if (sid) url += (url.indexOf('?')>=0? '&' : '?') + this.session_name + "=" + this.escape(sid);
            // Solve hash BEFORE appending ID.
            var hash = this.hash = url + '?' + query;
            if (this.caching && CACHE[hash]) {
                var c = CACHE[hash]; this._dataReady(c[0], c[1]);
                return false;
            }
            // Try to use XMLHttpRequest.
            this._xmlReq = this._obtainXmlReq(id, url);
            // Pass data in URL (GET, HEAD etc.) or in request body (POST)?
            var hasSetHeader = this._xmlReq && (window.ActiveXObject || this._xmlReq.setRequestHeader); 
            var href, body;
            var method = (""+this._openArg.method).toUpperCase();
            if (this._xmlReq && hasSetHeader && method == "POST") {
                // Use POST method. Pass query in request body.
                // Opera 8.01 does not support setRequestHeader, so no POST method.
                this._openArg.method = "POST"; href = url; body = query;
            } else {
                if (method != 'GET' && !this.fallbackToScript && query.length > 2000) {
					var msg = 'Cannot use XMLHttpRequest nor Microsoft.XMLHTTP for long POST query: object not implemented or disabled in browser.'; alert(msg); throw msg;
                }
                this._openArg.method = "GET"; href = url + (url.indexOf('?')>=0? '&' : '?') + query; body = null;
            }
            // Append ID: a=aaa&b=bbb&<id>, Save loading script.
            href = href + (href.indexOf('?')>=0? '&' : '?') + id; PENDING[id] = this;
            if (this._xmlReq) {
                // Open request now & send it. In XMLHttpRequest mode request URL MUST be ended with "<id>-xml".
                var a = this._openArg;
                this._xmlReq.open(a.method, href+"-xml", a.asyncFlag, a.username, a.password);
                if (hasSetHeader) {
                    // Pass pending headers.
                    for (var i=0; i<this._reqHeaders.length; i++)
                        this._xmlReq.setRequestHeader(this._reqHeaders[i][0], this._reqHeaders[i][1]);
                    // Set non-default Content-type. We cannot use "application/x-www-form-urlencoded" here, because 
                    // in PHP variable HTTP_RAW_POST_DATA is accessible only when enctype is not default 
					// (e.g., "application/octet-stream" is a good start). 
					// We parse POST data manually in backend library code.
                    this._xmlReq.setRequestHeader('Content-Type', 'application/octet-stream');
                }
                return this._xmlReq.send(body);
            } else { // Create <script> element and run it.
                this._obtainScript(id, href); return true;
            }
        },
        getAllResponseHeaders: function() {
            if (this._xmlReq) return this._xmlReq.getAllResponseHeaders(); return '';
        },
        getResponseHeader: function(label) {
            if (this._xmlReq) return this._xmlReq.getResponseHeader(label); return '';
        },
        setRequestHeader: function(label, value) { // Collect headers.
            this._reqHeaders[this._reqHeaders.length] = [label, value];
        },
        // Internal functions.
        _construct: function() {}, // Constructor.
        // Do all work when data is ready.
        _dataReady: function(text, js) { with (this) {
            if (text !== null || js !== null) {
				document.body.style.cursor = 'default';
                readyState = 4; responseText = responseXML = text; responseJS = js; status = responseJS._STATUS;
            } else {
                readyState = 0; responseText = responseXML = responseJS = null;
            }
            if (onreadystatechange) onreadystatechange();
            _cleanupScript();
        }},
        _obtainXmlReq: function(id, url) { // Create new XMLHttpRequest object.
            // If url.domain specified and differ from current, cannot use XMLHttpRequest!
            // XMLHttpRequest (and MS ActiveX'es) cannot work with different domains.
            var p = url.match(new RegExp('^[a-z]+://(.*)', 'i'));
            if (p) {
                var curHost = document.location.host.toLowerCase();
                if (p[1].substring(0, curHost.length).toLowerCase() == curHost) {
                    url = p[1].substring(curHost.length, p[1].length);
                } else return null;
            }
            // Try to use built-in loaders.
            var req = null;
            if (window.XMLHttpRequest) {
                try { req = new XMLHttpRequest() } catch(e) {}
            } else if (window.ActiveXObject) {
                try { req = new ActiveXObject("Microsoft.XMLHTTP") } catch(e) {}
                if (!req) try { req = new ActiveXObject("Msxml2.XMLHTTP") } catch (e) {}
            }
            if (req) {
                var th = this;
                req.onreadystatechange = function() { 
                    var s = req.readyState;
                    if (s == 4) {
                        // Avoid memory leak by removing closure.
                        req.onreadystatechange = th.dummy;
                        // Remove possible junk from response.
                        var responseText = req.responseText;
                        try { // Call associated dataReady().
                            eval(responseText);
                        } catch (e) {
                            Subsys_JsHttpRequest_Js.dataReady(id, "JavaScript code generated by backend is invalid !\n" + responseText, {_STATUS:500}, null);
                        }
                    } else { th.readyState = s; if (th.onreadystatechange) th.onreadystatechange(); }
                }; this._id = id;
            } return req;
        },
        _obtainScript: function(id, href) { with (document) { // Create new script element and start loading.
            var span = null;
            // Oh shit! Damned stupid fucked Opera 7.23 does not allow to create SCRIPT 
            // element over createElement (in HEAD or BODY section or in nested SPAN - 
            // no matter): it is created deadly, and does not respons on href assignment.
            // So - always create SPAN.
            var span = createElement("SPAN"); span.style.display = 'none'; body.appendChild(span);
            span.innerHTML = 'Text for stupid MSIE.<script></script>';
            setTimeout(function() {
                var s = span.getElementsByTagName("script")[0]; s.language = "JavaScript";
                if (s.setAttribute) s.setAttribute('src', href); else s.src = href;
            }, 10);
            this._id = id; this._span = span;
        }},
        _cleanupScript: function() { // Remove last used script element (clean memory).
            var span = this._span;
            if (span) {
                this._span = null;
                setTimeout(function() { // without setTimeout - crash in IE 5.0!
                    span.parentNode.removeChild(span);
                }, 50);
            } return false;
        },
        _hash2query: function(content, prefix) { // Convert hash to QUERY_STRING.
            if (prefix == null) prefix = ""; var query = [];
            if (content instanceof Object) {
                for (var k in content) {
                    var v = content[k];
                    if (v == null || ((v.constructor||{}).prototype||{})[k]) continue;
                    var curPrefix = prefix? prefix+'['+this.escape(k)+']' : this.escape(k);
                    if (v instanceof Object) query[query.length] = this._hash2query(v, curPrefix);
                    else query[query.length] = curPrefix + "=" + this.escape(v);
                }
            } else query = [content];
            return query.join('&');
        },
        _getSid: function() { // Return value of SID based on QUERY_STRING or cookie (PHP compatible sessions).
            var m = document.location.search.match(new RegExp('[&?]'+this.session_name+'=([^&?]*)')); var sid = null;
            if (m) sid = m[1];
            else {
                var m = document.cookie.match(new RegExp('(;|^)\\s*'+this.session_name+'=([^;]*)')); 
				if (m) sid = m[2];
            } return sid;
        },
        escape: function(s) { // Stupid JS escape() does not quote '+'.
            return escape(s).replace(new RegExp('\\+','g'), '%2B');
        }
    }
})();

