var cm = {};

var userAgent = navigator.userAgent.toLowerCase();
var browser = {
	version: (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1],
	safari: /webkit/.test(userAgent),
	opera: /opera/.test(userAgent),
	msie: /msie/.test(userAgent) && !/opera/.test(userAgent),
	mozilla: /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent)
};

var getAncestors = cm.getAncestors = function(obj, tag, asArray, className) {
	var parent = obj.parentNode;
	var result = asArray ? [] : null;
	asArray = !!asArray;
	if (className) {
		var checkClassName = new RegExp(className);
	}
	while (parent.nodeName.toLowerCase() !== 'html') {
		if (parent.nodeName.toLowerCase() === tag.toLowerCase()
			&& (!className || (className && checkClassName.test(parent.className)))
		) {
			if (!asArray) {
				return parent;
			}
			result.push(parent);
		}
		parent = parent.parentNode;
	}
	return result;
};

var emptyNode = emptyComboBox = function(comboBox) {
	var full = arguments[1];
	var option, optionIE, i, child = browser.IE ? 'firstChild' : 'lastChild';
	optionIE = comboBox.firstChild;
	while (comboBox[child]) {option = comboBox.removeChild(comboBox[child]);}
	if (!full) {comboBox.appendChild(browser.IE ? optionIE : option);}
};

var fillComboBox = function(comboBox, data) {
	emptyNode(comboBox, arguments[2]);
	for(i=0;i<data.length;i++) {
		option = document.createElement('option');
		if (typeof data[i]['value'] !== 'undefined') {
			option.value = data[i]['value'];
		}
		option.innerHTML = data[i]['title'];
		comboBox.appendChild(option);
	}
};

cm.getLocale = function() {
	return 'ru';
};

cm.isArray = function(o) {
	return typeof o == 'object'  && 'splice' in o && 'join' in o;
};

cm.addEvent = function(el, type, fn) {
	if (cm.isArray(el)) {
		for (var i = 0, l = el.length; i < l; i++) {
			cm.addEvent(el[i], type, fn);
		}
		return;
	}
	if (el.attachEvent) {
		el['e'+ type + fn] = fn;
		el[type + fn] = function() {
			el['e'+ type + fn](window.event);
		};
		el.attachEvent('on'+ type, el[type+fn]);
	} else {
		el.addEventListener(type, fn, false);
	}
};

cm.removeEvent = function(el, type, fn) {
	if (el.detachEvent) {
		el.detachEvent('on'+ type, el[type + fn]);
		el[type + fn] = null;
	} else {
		el.removeEventListener(type, fn, false);
	}
};

cm.stopEvent = function(e) {

	if (document.all) {
		e.cancelBubble = false;
		e.returnValue = false;
		return;
	}

	e.preventDefault();
	e.stopPropagation();
	e.stopped = true;
};

cm.dependentComboBox = function(hComboBox, dComboBox, data, run) {

	hComboBox = document.getElementById(hComboBox);
	dComboBox = document.getElementById(dComboBox);
	data = data || {};

	if (!hComboBox || !dComboBox) {
		return;
	}

	var fillComboBox = function(comboBox, data) {
		while (comboBox.firstChild) {
			comboBox.removeChild(comboBox.firstChild);
		}
		var option, i;
		for (i = 0; i < data.length; i++) {
			if (data[i].data !== undefined && data[i].value !== undefined) {
				option = comboBox.appendChild(document.createElement('option'));
				option.appendChild(document.createTextNode(data[i].data));
				option.value = data[i].value;
			}
		}
	};

	var hHandler = function(event) {
		if (typeof data[this.value] === 'undefined') {
			while (dComboBox.firstChild) {
				dComboBox.removeChild(dComboBox.firstChild);
			}
			return;
		}
		var value = dComboBox.value;
		fillComboBox(dComboBox, data[this.value]);
		dComboBox.value = value;
	};

	cm.addEvent(hComboBox, 'change', hHandler);
	if (run !== false) {
		hHandler.call(hComboBox);
	}
};

var initSimpleTabs = function(name){

	var tabHolder = getElement(name);
	var tabs = tabHolder.getElementsByTagName('li');

	var tabHandler = function(e) {
		for (var i=0; i<tabs.length; i++) {
			tabs[i].className = 'tab';
			document.getElementById(tabs[i].id +'-content').style.display = 'none';
		}
		this.className = 'tab current';
		document.getElementById(this.id +'-content').style.display = 'block';
	};

	for (var i=0; i<tabs.length; i++) {
		cm.addEvent(tabs[i], 'click', tabHandler);
	}

};

cm.getOffset = function(elem) {
		//~ if (!this[0]) error();
		var x = 0, y = 0, sl = 0, st = 0,
		    parent = elem, op, parPos, elemPos = elem.style.position,
		    mo = browser.mozilla, ie = browser.msie, oa = browser.opera,
		    sf = browser.safari, sf3 = browser.safari && parseInt(browser.version) > 520,
		    absparent = false, relparent = false;

		var num = function(el, prop) {
			return parseInt(el.style[prop])||0;
		};

		var handleOffsetReturn = function(elem, options, x, y, sl, st) {
			if ( !options.margin ) {
				x -= num(elem, 'marginLeft');
				y -= num(elem, 'marginTop');
			}

			// Safari and Opera do not add the border for the element
			if ( options.border && ((browser.safari && parseInt(browser.version) < 520) || browser.opera) ) {
				x += num(elem, 'borderLeftWidth');
				y += num(elem, 'borderTopWidth');
			} else if ( !options.border && !((browser.safari && parseInt(browser.version) < 520) || browser.opera) ) {
				x -= num(elem, 'borderLeftWidth');
				y -= num(elem, 'borderTopWidth');
			}

			if ( options.padding ) {
				x += num(elem, 'paddingLeft');
				y += num(elem, 'paddingTop');
			}

			// do not include scroll offset on the element ... opera sometimes reports scroll offset as actual offset
			if ( options.scroll && (!browser.opera || elem.offsetLeft != elem.scrollLeft && elem.offsetTop != elem.scrollLeft) ) {
				sl -= elem.scrollLeft;
				st -= elem.scrollTop;
			}

			return options.scroll ? {top: y - st, left: x - sl, scrollTop:  st, scrollLeft: sl}
								  : {top: y, left: x};
		};

		var options = arguments[1] || {};
		options = {
			margin: typeof options.margin == 'undefined' ? true : options.margin,
			border: typeof options.border == 'undefined' ? false : options.border,
			padding: typeof options.padding == 'undefined' ? false : options.padding,
			scroll: typeof options.scroll == 'undefined' ? true : options.scroll,
			relativeTo: typeof options.relativeTo == 'undefined' ? document.body : options.relativeTo
		}

		// Use offsetLite if lite option is true
		//~ if (options.lite) return this.offsetLite(options, returnObject);
		// Get the HTMLElement if relativeTo is a jquery collection
		//~ if (options.relativeTo.jquery) options.relativeTo = options.relativeTo[0];

		if (elem.tagName == 'BODY') {
			// Safari 2 is the only one to get offsetLeft and offsetTop properties of the body "correct"
			// Except they all mess up when the body is positioned absolute or relative
			x = elem.offsetLeft;
			y = elem.offsetTop;
			// Mozilla ignores margin and subtracts border from body element
			if (mo) {
				x += num(elem, 'marginLeft') + (num(elem, 'borderLeftWidth')*2);
				y += num(elem, 'marginTop')  + (num(elem, 'borderTopWidth') *2);
			} else
			// Opera ignores margin
			if (oa) {
				x += num(elem, 'marginLeft');
				y += num(elem, 'marginTop');
			} else
			// IE does not add the border in Standards Mode
			if ((ie && jQuery.boxModel)) {
				x += num(elem, 'borderLeftWidth');
				y += num(elem, 'borderTopWidth');
			} else
			// Safari 3 doesn't not include border or margin
			if (sf3) {
				x += num(elem, 'marginLeft') + num(elem, 'borderLeftWidth');
				y += num(elem, 'marginTop')  + num(elem, 'borderTopWidth');
			}
		} else {
			do {
				//~ parPos = $.css(parent, 'position');
				parPos = parent.style.position;

				x += parent.offsetLeft;
				y += parent.offsetTop;

				// Mozilla and IE do not add the border
				// Mozilla adds the border for table cells
				if ((mo && !parent.tagName.match(/^t[d|h]$/i)) || ie || sf3) {
					// add borders to offset
					x += num(parent, 'borderLeftWidth');
					y += num(parent, 'borderTopWidth');

					// Mozilla does not include the border on body if an element isn't positioned absolute and is without an absolute parent
					if (mo && parPos == 'absolute') absparent = true;
					// IE does not include the border on the body if an element is position static and without an absolute or relative parent
					if (ie && parPos == 'relative') relparent = true;
				}

				op = parent.offsetParent || document.body;
				if (options.scroll || mo) {
					do {
						if (options.scroll) {
							// get scroll offsets
							sl += parent.scrollLeft;
							st += parent.scrollTop;
						}

						// Opera sometimes incorrectly reports scroll offset for elements with display set to table-row or inline
						if (oa && (parent.style.display || '').match(/table-row|inline/)) {
							sl = sl - ((parent.scrollLeft == parent.offsetLeft) ? parent.scrollLeft : 0);
							st = st - ((parent.scrollTop == parent.offsetTop) ? parent.scrollTop : 0);
						}

						// Mozilla does not add the border for a parent that has overflow set to anything but visible
						if (mo && parent != elem && parent.style.overflow != 'visible') {
							x += num(parent, 'borderLeftWidth');
							y += num(parent, 'borderTopWidth');
						}

						parent = parent.parentNode;
					} while (parent != op);
				}
				parent = op;

				// exit the loop if we are at the relativeTo option but not if it is the body or html tag
				if (parent == options.relativeTo && !(parent.tagName == 'BODY' || parent.tagName == 'HTML'))  {
					// Mozilla does not add the border for a parent that has overflow set to anything but visible
					if (mo && parent != elem && arent.style.overflow != 'visible') {
						x += num(parent, 'borderLeftWidth');
						y += num(parent, 'borderTopWidth');
					}
					// Safari 2 and opera includes border on positioned parents
					if ( ((sf && !sf3) || oa) && parPos != 'static' ) {
						x -= num(op, 'borderLeftWidth');
						y -= num(op, 'borderTopWidth');
					}
					break;
				}
				if (parent.tagName == 'BODY' || parent.tagName == 'HTML') {
					// Safari 2 and IE Standards Mode doesn't add the body margin for elments positioned with static or relative
					if (((sf && !sf3) || (ie && (document.compatMode == "CSS1Compat"))) && elemPos != 'absolute' && elemPos != 'fixed') {
						x += num(parent, 'marginLeft');
						y += num(parent, 'marginTop');
					}
					// Safari 3 does not include the border on body
					// Mozilla does not include the border on body if an element isn't positioned absolute and is without an absolute parent
					// IE does not include the border on the body if an element is positioned static and without an absolute or relative parent
					if ( sf3 || (mo && !absparent && elemPos != 'fixed') ||
					     (ie && elemPos == 'static' && !relparent) ) {
						x += num(parent, 'borderLeftWidth');
						y += num(parent, 'borderTopWidth');
					}
					break; // Exit the loop
				}
			} while (parent);
		}

		var returnValue = handleOffsetReturn(elem, options, x, y, sl, st);
		return returnValue;
};

/**
 * times (prototypejs.org)
 */
String.prototype.times = function(count) {
    return count < 1 ? '' : new Array(count + 1).join(this);
};

/**
 * toPaddedString (prototypejs.org)
 */
Number.prototype.toPaddedString = function(length, radix) {
    var string = this.toString(radix || 10);
    return '0'.times(length - string.length) + string;
};

/**
 * gsub (prototypejs.org)
 */
String.prototype.gsub = function(pattern, replacement) {
	if (typeof replacement !== 'function') {
		return this;
	}

	var result = '', source = this, match, value;

	if (typeof pattern == 'string') {
		pattern = RegExp.escape(pattern);
	}
	if (!(pattern.length || pattern.source)) {
		replacement = replacement('');
		return replacement + source.split('').join(replacement) + replacement;
	}

	while (source.length > 0) {
		if ((match = source.match(pattern))) {
			result += source.slice(0, match.index);
			result += (value = replacement(match)) == null ? '' : value;
			source  = source.slice(match.index + match[0].length);
		} else {
			result += source, source = '';
		}
	}
	return result;
};

String.prototype.render = function(v, s, e) {
	var p, m = this;
	for(var k in v){
		p = (s || '%') + k + (e || '%');
		while(m.indexOf(p) !== -1){
			m = m.replace(p, v[k]);
		}
	}return m;
};

/**
 * открывается окошко со списком городов
 */
function showCitiesList() {
	var input = document.getElementById('city_input');
	var inputOffset = cm.getOffset(input);
	document.getElementById('cities-list').style.display = 'block';
	if (document.getElementById('direction')) {
		document.getElementById('direction').style.display = 'none';
	}
	document.getElementById('cities-list-shadow').style.width = document.getElementById('cities-list').offsetWidth +'px';
	document.getElementById('cities-list-shadow').style.height = document.getElementById('cities-list').offsetHeight +'px';
	document.getElementById('cities-list-shadow').style.display = 'block';
}

function closeCitiesList() {
	if (document.getElementById('direction')) {
		document.getElementById('direction').style.display = 'block';
	}
	document.getElementById('cities-list-shadow').style.display = 'none';
	document.getElementById('cities-list').style.display = 'none';
}

var closeCitiesListByClick = function (e) {
	var el = e.target || e.srcElement;
	while (el !== document.getElementById('cities-list') && el !== document.getElementById('cities-list-btn') && el.nodeName !== 'HTML') {
		el = el.parentNode;
	}

	if (el.nodeName === 'HTML' || (document.getElementById('cities-list').style.display == '' && el.id == 'cities-list-btn')) {
		closeCitiesList();
	}
}

//cm.addEvent(document, 'click', closeCitiesListByClick);

/*
 *	(c) 3dots 2007
 *	<element class="dropdown-list">
 *		<element class="dropdown-item">
 *			<element class="item-title">Title</element>
 *			<element class="item-content">Content</element>
 *		</element>
 *	</element>
 */
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('c g=l(e){c a=6.4.4;d(c i=0;i<a.5.8;i++){7(a.5[i]!==6){a.5[i].4.3=a.5[i].4.3.n(\'9\',\'\')}}6.4.3=/\\s*9\\s*/.b(6.4.3)?6.4.3.n(\'9\',\'\'):6.4.3+\' 9\'};k(w,\'v\',l(){c a=u.t(\'q\'),i,j,y;d(i=0;i<a.8;i++){7(/\\s*f-p\\s*/.b(a[i].3)){7(o a[i].5==\'r\'){a[i].5=[]}d(j=0;j<a[i].2.8;j++){7(a[i].2[j].m===1&&(/\\s*f-h\\s*/.b(a[i].2[j].3))){d(y=0;y<a[i].2[j].2.8;y++){7(a[i].2[j].2[y].m===1&&(/\\s*h-z\\s*/.b(a[i].2[j].2[y].3))){a[i].5.x(a[i].2[j].2[y]);k(a[i].2[j].2[y],\'A\',g)}}}}}}});',37,37,'||childNodes|className|parentNode|ddItems|this|if|length|opened||test|var|for||dropdown|dropDownListItemHandler|item|||cm.addEvent|function|nodeType|replace|typeof|list|DIV|undefined||getElementsByTagName|document|load|window|push||title|click'.split('|'),0,{}))