function dbi(t) { return document.getElementById(t) }
function isHide(a) { return a && a.style && a.style.display == "none" }
function showE(a) { a.style.display = "block" }
function hideE(a) { a.style.display = "none" }
function toggleE(a) { if(isHide(a)) showE(a); else hideE(a); }
function goPage(a){ location.href=a }
function trimall(v) {return /^\s*(.*)\s*$/.test(v)? RegExp.$1 : v }
function alwaysTrue() { return true }
function alwaysFalse() { return false }
function read_style(element, property) {
		if (property in element.style) return element.style[property]
		else if (element.currentStyle) return element.currentStyle[property]
		else if (document.defaultView && document.defaultView.getComputedStyle)
			return document.defaultView.getComputedStyle(element, null).getPropertyValue(property)
		else return null
}
function hasAttr(e,n) {
		if(e.hasAttribute) return e.hasAttribute(n)
		return e[n] != undefined
	}

function is_abs_path(s) { return s[0] == "/" || s.indexOf(":")>0 }

function get_event_coords( e )
{
       if(e.pageX!=null && e.pageY!=null ) {
               return { x: e.pageX, y: e.pageY }
       } else if( e.clientX!=null && e.clientY!=null ) {
               return { x: e.clientX+document.body.scrollLeft,
                        y: e.clientY+document.body.scrollTop }
       }
       return null
}

function get_absolute_coords(obj) {
	var curleft = curtop = 0;
	do {
		curleft += obj.offsetLeft || 0 
		curtop += obj.offsetTop || 0
	} while(obj = obj.offsetParent);
	return {x:curleft,y:curtop}
}

function print_coord(e,x,y) { alert(e + " X:"+x+" Y:"+y) }

function Event(e) {
	e = e || window.event
	if(e.event) return e
	var ec = get_event_coords(e) // это где нажали
	return {
		event: e,
		target: e.target || e.srcElement, // это тот кого нажали
		x: ec && ec.x,
		y: ec && ec.y,
		shift : e.shiftKey,
		alt: e.altKey,
		ctrl: e.ctrlKey,
		button: e.target ? e.button : (e.button==1?0:e.button==2?2:e.button==4?1:-1),
		stop: function() {
				this.event.cancelBubble = true
				this.event.stopPropagation && this.event.stopPropagation()
			},
		preventDefault: function() {
			this.event.returnValue = false
			this.event.preventDefault && this.event.preventDefault()
			return false
		}
	}
}

function capture_event(n,f) {
	var real = function(e) { 
				e.cancelBubble = true
				e.stopPropagation && e.stopPropagation()
				return f(e)
			}
	!document.body.captureCount && (document.body.captureCount = 0) || ++document.body.captureCount
	document.body.setCapture && document.body.setCapture()
	if(document.body.attachEvent) document.body.attachEvent("on"+n, real )
	if(window.addEventListener) window.addEventListener(n, real, true)
	return real
}
function release_event(n,f) {
	--document.body.captureCount
	document.body.captureCount==0 && document.body.releaseCapture && document.body.releaseCapture()
	if(document.body.detachEvent) document.body.detachEvent("on"+n, f )
	if(window.removeEventListener) window.removeEventListener(n, f, true)
}

function attach_event(n,f) {
	if(document.body && document.body.attachEvent) document.body.attachEvent("on"+n, f )
	if(window.addEventListener) window.addEventListener(n, f, false)
}
function detach_event(n,f) {
	if(document.body && document.body.detachEvent) document.body.detachEvent("on"+n, f )
	if(window.removeEventListener) window.removeEventListener(n, f, false)
}
function post_event(f) {
	window.setTimeout(f,0)
}

function pt_in_elem(e,x,y,round_test)
{
	var p = get_absolute_coords(e)
	if(round_test && round_test(e))
	{
		var r = e.offsetWidth/2
		if( (p.x-x+r)*(p.x-x+r)+(p.y-y+r)*(p.y-y+r) <= r*r )
			return e
	}
	else if(p.x <= x && x < p.x+e.offsetWidth &&
		p.y <= y && y < p.y+e.offsetHeight)
		return e
	return null
}

function pt_in_elem_rec(e,x,y,round_test,solid_test)
{
	if(solid_test && solid_test(e)) 
		return pt_in_elem(e,x,y,round_test)
	var cn = e.childNodes
	for(var t=0; t < cn.length; ++t)
	{
		var r = pt_in_elem_rec(cn[t],x,y,round_test,solid_test)
		if(r) 
			return r
	}
	return null
}

function is_subnode_of(e1,e2) {
	while(e1) {
		if(e1===e2) return true
		e1 = e1.parentNode
	}
	return false
}


var mouseParams = { capture: null, capture_patch: false, x:0, y: 0 }

function alwaysFalse_mp(e) { return Event(e).preventDefault() }

function capture_mouse(eh) {
	!mouseParams.capture || release_mouse()
	!mouseParams.capture_patch || release_capture_patch()
	mouseParams.capture = eh
	mouseParams.capture.fmousedown = capture_event('mousedown', eh.mousedown || alwaysFalse_mp)
	mouseParams.capture.fmousemove = capture_event('mousemove', eh.mousemove || alwaysFalse_mp)
	mouseParams.capture.fmouseup = capture_event('mouseup', eh.mouseup || alwaysFalse_mp)
	mouseParams.capture.fclick = capture_event('click', eh.click || alwaysFalse_mp)
	mouseParams.capture.fblur = capture_event('blur', function(e) { release_mouse(); return Event(e).preventDefault() })
	window.focus()
}
function release_capture_patch(){
	detach_event('mousedown', release_capture_mp)
	detach_event('mousemove', release_capture_mp)
	detach_event('mouseup', release_capture_mp)
	release_event('click', mouseParams.capture_patch)
	mouseParams.capture_patch = null
}

function release_capture_mp(e) { release_capture_patch(); return true }
function release_mouse() {
	if(mouseParams.capture)	{
		mouseParams.capture.release()
		release_event('mousedown', mouseParams.capture.fmousedown)
		release_event('mousemove', mouseParams.capture.fmousemove)
		release_event('mouseup', mouseParams.capture.fmouseup)
		release_event('click', mouseParams.capture.fclick)
		release_event('blur', mouseParams.capture.fblur)
		mouseParams.capture = null
		//ставим патч для события click - его надо игнорировать
		attach_event('mousedown', release_capture_mp)
		attach_event('mousemove', release_capture_mp)
		attach_event('mouseup', release_capture_mp)
		mouseParams.capture_patch = capture_event('click', alwaysFalse_mp )
	}
}

var _DnD = { param: null }

function check_coord_def(c, p, i) {
	return p == undefined ||
		(p.constructor==Function ? p(c) : i ? p<=c : c<=p)
}
function move_object_to(dnd,x,y) {
	if( dnd.h && check_coord_def(x,dnd.h.min,true) && check_coord_def(x,dnd.h.max,false) )
		dnd.root.style.left = x+"px"
	if( dnd.v && check_coord_def(y,dnd.v.min,true) && check_coord_def(y,dnd.v.max,false) )
		dnd.root.style.top = y+"px"
	dnd.onmoved && dnd.onmoved()
}


/*ставится на mousedown инициирующего элемента
	параметры :
	root - элемент, который будем двигать (или ф-я, возвращающая его при первом нажатии)
	h - двигаем по горизонтали true | {min,max} | ф-я проверки
	v - двигаем по вертикали true | {min,max} | ф-я проверки
	button - на какую кнопку реагирует (нет - на любую)
	onstart - при начале (true - можно начинать)
	onmove - при перемещении (true - можно двигать, false - двигать нельзя)
	onmoved - когда переместили
	ondrop - когда бросили 
	oncancel - когда отменили

	в объект добавляются методы (если еще не объявлены. они вызвают release_mouse)
		drop - бросить 
		cancel - отменить

	z - ф-я, возвращающая новый z-ордер на время таскания
	
*/

function DnDProcessor(dnd) { 
	return function(e) {
			e = Event(e)
			if(dnd.root.constructor === Function) dnd.root = dnd.root(e.target)
			else if(dnd.root.constructor === String) dnd.root = dbi(dnd.root)
			_DnD.param = dnd
			var ac =  get_absolute_coords(dnd.root)
			_DnD.x = ac.x - e.x
			_DnD.y = ac.y - e.y
			if( (dnd.button == undefined|| e.button==dnd.button) &&
			  (!dnd.onstart || dnd.onstart(e)) ) {
				if(_DnD.param.z && _DnD.param.saveZ) _DnD.oldZ = read_style(_DnD.param.root,"zIndex")
				_DnD.param.drop || (_DnD.param.drop = function(e) { release_mouse(); _DnD.param.ondrop && this.ondrop(e); })
				_DnD.param.cancel || (_DnD.param.cancel = function(e) { release_mouse(); _DnD.param.oncancel && this.oncancel(e); })
				var x = { 
					mousemove: function(e) { 
						e = Event(e)
						if(!_DnD.param.onmove || _DnD.param.onmove(e))
							move_object_to(_DnD.param, _DnD.x + e.x, _DnD.y + e.y) 
						return e.preventDefault()
						},
					mouseup: function(e) { 
						e = Event(e)
						if( !_DnD.param.onmove || _DnD.param.onmove(e) )
							move_object_to(_DnD.param, _DnD.x + e.x, _DnD.y + e.y)
						_DnD.param.drop(e)
						 return e.preventDefault()
						},
					release: function() {
						_DnD.oldZ!=undefined && _DnD.oldZ!=null && ( _DnD.param.root.style.zIndex = _DnD.oldZ ) }
				}
				capture_mouse(x)
				_DnD.param.z && (_DnD.param.root.style.zIndex = _DnD.param.z())
			}
			e.stop()
			return e.preventDefault()
		}
}

if(document.activeElement == undefined)
	attach_event('focus',function(e){ document.activeElement = Event(e).target })

var _Menus = null
function close_menu(always) {
	if(_Menus)
		for(var i = _Menus.length-1; i>=0; --i)
		{
			var cur = _Menus[i]
			if(always==true || !is_subnode_of(document.activeElement,cur.root))
				cur.root.style.display = "none"
		}
}

function MenuProcessor(par) {
	return function(e) {
			e = Event(e)
			if(par.root.constructor === Function) par.root = par.root(e.target)
			else if(par.root.constructor === String) par.root = dbi(par.root)
			if(!_Menus) {
				_Menus = []
				attach_event('blur', function(e){ post_event(close_menu) })
				attach_event('focusout', function(e){ post_event(close_menu) })
			}
			!par.prepare || par.prepare(e)
			par.root.style.display = "block"
			if(par.x!=undefined) par.root.style.left = par.x + "px"
			if(par.y!=undefined) par.root.style.top = par.y + "px"
			par.root.tabIndex = 0
			par.root.focus()
			_Menus.push(par)
		}
}

function popup_window(s) {
	var spar = ""
	if(s.x!=undefined) spar+=",left="+s.x
	if(s.y!=undefined) spar+=",top="+s.y
	if(s.w!=undefined) spar+=",width="+s.w
	if(s.h!=undefined) spar+=",height="+s.h
	if(s.params) spar += ","+s.params
	var url = s.url? s.url : 'about:blank'
	if(spar[0]==',') spar = spar.substr(1)
	var w = open(url,"xxx",spar)
	if(s.data) {
		var popdoc = w.document
		popdoc.open()
		popdoc.write(s.data)
		popdoc.close()
	}
	w.focused = true
	w.cond_close = function() { if(!w.focused) w.close() }
	w.document.body.onfocusin = w.onfocus = function() { w.focused = true }
	w.document.body.onfocusout = w.onblur = function() { w.focused = false; w.setTimeout(w.cond_close,0) }
}

function find_class(p,s) {
	if(s.constructor == String)
		s = new RegExp("\b"+s+"\b")
	do {
		if( s.test(p.className) ) return p
		p = p.parentNode
	} while(p);
}

var sss =""
function find_class_down_real(coll,s) {
	for(var c = 0; c<coll.length; ++c) {
		var p = coll[c]
		if( s.test(p.className) ) return p
		var r = find_class_down_real(p.childNodes,s)
		if(r) return r
	}
	return null
}

function find_class_down(p,s) {
	if(s.constructor == String)
		s = new RegExp("\b"+s+"\b")
	if( s.test(p.className) ) return p
	var coll = 
		document.getAnonymousNodes && document.getAnonymousNodes(p) ||
		p.childNodes
	return find_class_down_real(coll,s)
}

function topZ () { return 1000 }

function send_mouse(obj,event) {
	if(obj.dispatchEvent) {
		var e1 = document.createEvent("MouseEvents")
		e1.initMouseEvent(event.type, event.bubbles, event.cancelable, event.view,
			event.detail,event.screenX,event.screenY,event.clientX,event.clientY,
			event.ctrlKey,event.altKey,event.shiftKey,event.metaKey,event.button,
			event.relatedTarget)
		return obj.dispatchEvent(e1)
	}
	else if(obj.fireEvent) {
		obj.fireEvent("on"+event.type,event)
	}
}

function stop_event(event) {
	event.cancelBubble = true
	event.stopPropagation && event.stopPropagation()
	return true
}

function read_cookie(cval) {
	var c = document.cookie
	var lst = c.split(";")
	for(var i in lst)
		if( lst[i].match( /\s*(.*)=(.*)/ ) && RegExp.$1 == cval)
			return unescape(RegExp.$2)
	return ""
}

function write_cookie(cval,data) {
	var d = new Date(3000,0,1)
	document.cookie =  cval+"="+escape(data)+ "; expires="+d.toGMTString()
}

function ondominit(init_par) {
	var init = function() {
		   if (arguments.callee.done) return;
		   arguments.callee.done = true
		   init_par()
	}
	if (document.addEventListener) {
	    document.addEventListener("DOMContentLoaded", init, false)
	} 
	// for Internet Explorer (using conditional comments)
	/*@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() // call the onload handler
	    }
	}
	/*@end @*/
	if (/WebKit/i.test(navigator.userAgent)) { // sniff
	    var _timer = setInterval(function() {
		if (/loaded|complete/.test(document.readyState)) {
		    clearInterval(_timer)
		    init() // call the onload handler
		}
	    }, 10)
	}
	window.onload = init
}

function lbberty_alert(x) { alert(x) }

var doc_head = document.documentElement.childNodes[0]

function find_last_script() {
	var head = doc_head
	var ls = null
	for(var i = 0; i < head.childNodes.length; ++i) {
		if( head.childNodes[i].tagName == "SCRIPT") 
			ls = head.childNodes[i]
	}
	return ls
}

var libberty_script = find_last_script()
var libberty_pathname = libberty_script.src ? libberty_script.src : document.URL
var libberty_path = libberty_pathname.lastIndexOf("/") >= 0 ? libberty_pathname.substr(0,libberty_pathname.lastIndexOf("/")) : ""
if(!libberty_path) libberty_path = "."

var urlpatch_re = /url\(\s*(['"]?)([^\/#].*)\1\s*\)/g
function patch_css(coll) {
	for(var ssn in coll) {
		var ss = coll[ssn]
		if(ss.href && !is_abs_path(ss.href) && ss.href.indexOf("/")>0) 
		{
			var refpath = ss.href.substr(0,ss.href.lastIndexOf("/"))
			for(var rulen = 0;  rulen < ss.rules.length; ++rulen) {
				var rule = ss.rules[rulen]
				for(var stn in rule.style)
					if(stn != "cssText") {
						var st = rule.style[stn]
						var r = st && st.constructor === String? 
							st.replace(urlpatch_re, "url($1"+ refpath +"/$2$1)") 
							: ""
						if(r && st != r) rule.style[stn] = r
					}
			}
		}
	}
}

document.all && patch_css(document.styleSheets)

function html(tag) {
	var f = function() {
		var g = html(tag)
		for(var i = 0; i<f.args.length; ++i)
			g.args[g.args.length] = f.args[i]
		for(var i = 0; i<arguments.length; ++i)
			g.args[g.args.length] = arguments[i]
		return g
	}
	f.tag = tag
	f.args = []
	for(var sn in { href:0, src:0, style:0 } )
		f[sn] = function (a) { 
				var g = html(tag)
				for(var i = 0; i<f.args.length; ++i)
					g.args[g.args.length] = f.args[i]
				var r = {}; r[sn] = a
				g.args[g.args.length] = r
				return g
			}
	return f
}

var well_known_tags = {
	//generic block-level elements
		address:0, blockquote:0, center:0, del:0, div:0, h1 :0, h2:0, h3:0, h4:0, h5:0, h6:0, hr:0, ins:0, isindex:0, p:0, pre:0,
	//lists
		dir:0, dl:0, dt:0, dd:0, li:0, menu:0, ol:0, ul:0,
	//tables,
		table:0, caption:0, colgroup:0, col:0, thead:0, tfoot:0, tbody:0, tr:0, td:0, th:0,
	//forms:0,
		form:0, button:0, fieldset:0, legend:0, input:0, label:0, select:0, optgroup:0, option:0, textarea:0,
	//special inline elements:0,
		a:0, applet:0, basefont:0, bdo:0, br:0, font:0, iframe:0, img:0, map:0, area:0, object:0, param:0, q:0, script:0, span:0, sub:0, sup:0,
	//phrase elements:0,
		abbr:0, acronym:0, cite:0, code:0, del:0, dfn:0, em:0, ins:0, kbd:0, samp:0, strong:0, 'var':0, 
	//font style elements:0,
		b:0, big:0, i:0, s:0, small:0, strike:0, tt:0, u:0
	}
for(var i in well_known_tags)
	html[i] = html(i)
html.table.nospace = html.table({cellspacing:0, cellpadding:0})

var jsml2htm =  {
	createElement: function(name) { return document.createElement(name) },
	createTextElemenet: function(data) { return document.createTextNode(data) },
	addAtribute: function(element,name,value) { 
		if(name === 'class') element.className = value
		else if(value.constructor == Function)  element[name] = value
			else element.setAttribute(name, value, 0) 
		},
	appendChild: function(element,child) { 
					if(child.nodeType === 3) {
						var lc = element.lastChild
						if(lc && lc.nodeType === 3) 
							return lc.nodeValue += " " + child.nodeValue
					} 
					element.appendChild(child) 
				}
}

function map_jsml(mapper, jsml) {
	if(jsml.tag) {
		var newchild = mapper.createElement(jsml.tag)
		append_jsml(mapper, newchild, jsml.args)
		return newchild
	}
	return null
}

function append_jsml(mapper, parent, arg) {
	if(arg)
		switch(arg.constructor) {
		case Function:
			if(arg.tag) mapper.appendChild( parent, map_jsml(mapper, arg) )
			else  append_jsml(mapper, parent, arg(mapper, parent))
			break
		case Array: 
			for(var i =0; i<arg.length; ++i)
				append_jsml(mapper, parent, arg[i])
			break
		case Object: //attribute
			for(var j in arg) {
				var attr = arg[j]
				switch(attr.constructor) { 
				case Object: //like style
					var res = ""
					for(var k in attr) {
						var subsattr = attr[k]
						if(subsattr.constructor === Function) res += k + ":" + subsattr() + ";" 
						else res += k + ":" + subsattr + ";" 
					}
					mapper.addAtribute(parent, j, res)
					break
				case Array: //like class
					var res = ""
					for(var k in attr) {
						var subsattr = attr[k]
						if(subsattr.constructor === Function) res += " " + subsattr() 
						else res += " " + subsattr
					}
					mapper.addAtribute(parent, j, res)
					break
				default:
					mapper.addAtribute(parent, j, attr)
				}
			}
			break
		case String: 
			mapper.appendChild( parent, mapper.createTextElemenet(arg) )
		}
}

function checkXblAttacment(x,e) {
	switch(x.constructor) {
	case Function : return x(e)
	case Object: for(var i in x)
				if(e.hasAttribute ? !e.hasAttribute(i) : 
					!e.getAttribute || i!='class' && e.getAttribute(i)===null) { return false }
				else if(x != null)  {
					var v = i === 'class'? e.className : e.getAttribute(i)
					if(x[i].constructor === RegExp)
						{ if(!x[i].test(v)) return false }
					else
						{ if(String(x[i]) != v)  return false }
				}
			return true
	case Array: for(var i = 0; i <x.length; ++i)
				if(!checkXblAttacment(x[i], e)) return false
			return true
	case String: return e.tagName === x
	}
}
function filter_coll(coll,tg) {
	var r  = [], ncoll = [];
	for(var j=0; j<coll.length; ++j)
	{ 
		if(!tg || checkXblAttacment(tg, coll[j]))
			r.push(coll[j]) 
		else
			ncoll.push(coll[j])
	}	
	for(var i in r) {
		r[i].removeNode && (r[i] = r[i].removeNode(true)) ||
		r[i].parentNode.removeChild && r[i].parentNode.removeChild(r[i])
	}
		
	return { selected: r, rest:ncoll }
}

function make_children_subst(elem,tags) {
	var cur = elem.childNodes
	var r = {}
	for(var i in tags) {
		var x = filter_coll(cur, tags[i]) 
		r["$"+i] = x.selected
		cur = x.rest
	}
	r.$ = filter_coll(cur).selected
	return r
}

function subst_child(area, tg) {
	tg = tg!=undefined ? "$" + tg : "$"
	var coll = area[tg]
	delete area[tg]
	return function(mapper, parent) {
		for(var i in coll)
			mapper.appendChild(parent, coll[i])
	}
}

var _XBLAttacments = []
function xblAttached(element) {
	for(var i = 0; i < _XBLAttacments.length; ++i) {
		var x = _XBLAttacments[i]
		checkXblAttacment(x.selector, element) &&
			append_jsml(jsml2htm, element, x.code)
	}
}


function regAttach(selector,code) { _XBLAttacments.push( { selector: selector, code: code } ) }

function addText(obj,txt) { obj.appendChild(document.createTextNode(txt)) }
function addTextH(obj,txt) { obj.innerHTML = "<span>"+txt+"</span>"; }

function doAttached(e) {
	do {
		xblAttached(e)
		if(e.firstChild)
			doAttached(e.firstChild)
	} while( e = e.nextSibling )
}


/*
Drag&Drop + scroll
ScrollContainer с определенным шагом
Table - базируются на специальных split-окнах
	FrozenTable (item based container)
	FrozenTbale + dynamic content
WindowLikeContainer
InplaceEdit
скролиинг по мышке, т.е. генерация по таймеру событий 
если мышь находится в определенной области определенного элемента
*/

function HSBtoRGB (hue, saturation, brightness) {
    var r = 0;
    var g = 0;
    var b = 0;
    if (saturation == 0.0) {
        r = g = b = Math.floor(brightness * 255.0 + 0.5);
    }
    else {
        var h = (hue - Math.floor(hue)) * 6.0;
        var f = h - Math.floor(h);
        var p = brightness * (1.0 - saturation);
        var q = brightness * (1.0 - saturation * f);
        var t = brightness * (1.0 - (saturation * (1.0 - f)));

        switch (Math.floor(h)) {
            case 0:
            r = Math.floor(brightness * 255.0 + 0.5);
            g = Math.floor(t * 255.0 + 0.5);
            b = Math.floor(p * 255.0 + 0.5);
            break;

            case 1:
            r = Math.floor(q * 255.0 + 0.5);
            g = Math.floor(brightness * 255.0 + 0.5);
            b = Math.floor(p * 255.0 + 0.5);
            break;

            case 2:
            r = Math.floor(p * 255.0 + 0.5);
            g = Math.floor(brightness * 255.0 + 0.5);
            b = Math.floor(t * 255.0 + 0.5);
            break;

            case 3:
            r = Math.floor(p * 255.0 + 0.5);
            g = Math.floor(q * 255.0 + 0.5);
            b = Math.floor(brightness * 255.0 + 0.5);
            break;

            case 4:
            r = Math.floor(t * 255.0 + 0.5);
            g = Math.floor(p * 255.0 + 0.5);
            b = Math.floor(brightness * 255.0 + 0.5);
            break;

            case 5:
            r = Math.floor(brightness * 255.0 + 0.5);
            g = Math.floor(p * 255.0 + 0.5);
            b = Math.floor(q * 255.0 + 0.5);
            break;
        }
    }
    return "rgb("+r+","+g+","+b+")";
}