// {{{ addListener

/**
 * Adds event listener
 *
 * Adds specific event listener to a given element
 * @param	HTMLElement	el		HTML element to attach the handler to
 * @param	string		type	String representation of the event type
 * @param	function	fn		A callback function to hanle the event
 */
var addListener = function() {
	if ( window.addEventListener ) {
		// Mozilla style
		return function(el, type, fn) {
			el.addEventListener(type, fn, false);
		};
	} else if ( window.attachEvent ) {
		// MSIE style
		return function(el, type, fn) {
			var f = function() {
				fn.call(el, window.event);
			};
			el.attachEvent('on'+type, f);
		};
	} else {
		return function(el, type, fn) {
			el['on'+type] = fn;
		}
	}
}();

// }}}
// {{{ addAttribute

/**
 * Adds attribute named attrName with value attrValue to the element in a cross-browser way.
 */
function addAttribute(element, attrName, attrValue) {
	var attr = document.createAttribute(attrName);
	if (typeof attrValue !== "undefined") {
		attr.nodeValue = attrValue;
	}
	element.setAttributeNode(attr);
}


// {{{ uniqId

/**
 * Возвращает уникальный идентификатор для заданного "пространства имён" (любой строки).
 * Если не передано пространство имён, оно по умолчанию равно null
 */
uniqid.currentIdList = {};
function uniqid(namespace) {
	if (typeof namespace == "undefined") { namespace = null; }
	if (typeof uniqid.currentIdList[namespace] == "undefined") { uniqid.currentIdList[namespace] = 0; }
	return ++uniqid.currentIdList[namespace];
}

// }}}
// {{{ dump

function dump(d,l) {
	if (l == null) l = 1;

	if (l > 10) return '[#recursion]';

	var s = '';
	if (typeof(d) == "object") {
			s += typeof(d) + " {\n";
			for (var k in d) {
					for (var i=0; i<l; i++) s += "  ";
					s += k+": " + dump(d[k],l+1);
			}
			for (var i=0; i<l-1; i++) s += "  ";
			s += "}\n"
	} else {
			s += "" + d + "\n";
	}
	return s;
}


function dump_html(d,l) {
  if (l == null) l = 1;
	if (l > 10) return '[#recursion]';

	if (typeof(d) == "object") {
			document.write(typeof(d) + " {<br />\n");
			for (var k in d) {
		var spc = "<br />\n";
					for (var i=0; i<l; i++) spc += "&nbsp;.&nbsp;";
					document.write(spc + k+": " + dump(d[k],l+1));
			}
			for (var i=0; i<l-1; i++) document.write("&nbsp;.&nbsp;");
			document.write("}<br/>\n");
	} else {
			document.write("" + d + "<br />\n");
	}
}

// }}}
// {{{ getElementsByTagNameEx

/**
 * This function is an extended analogue of getElementsByTagName() method.
 * Provides filtering by element properties (filters).
 */
function getElementsByTagNameEx(tagName, filters, container) {

	if (typeof container == "undefined") {
		container = document;
	} else if (typeof container == "string") {
		container = document.getElementById(container);
	}

	if (typeof filters == "undefined") filters = {};
	if (typeof tagName == "undefined") tagName = "*";

	var elements = "*" == tagName ? document.all || container.getElementsByTagName(tagName) : container.getElementsByTagName(tagName);

	var filteredElements = [];
	var len = elements.length;

	elementsLoop:
	for (var i=0; i < len; i++) {
		for (var k in filters) {
			if (elements[i][k] != filters[k])
				continue elementsLoop;
		}
		filteredElements[filteredElements.length] = elements[i];
	}
	return filteredElements;
}

// }}}
// {{{ getElementsByTagNameExCallback

/**
 * This function is an extended analogue of getElementsByTagName() method.
 * Provides filtering by element properties (filters).
 */
function getElementsByTagNameExCallback(tagName, callbackFunc, container) {

	if (typeof container == "undefined") {
		container = document;
	} else if (typeof container == "string") {
		container = document.getElementById(container);
	}

	if (typeof tagName == "undefined") tagName = "*";

	var elements = "*" == tagName ? document.all || container.getElementsByTagName(tagName) : container.getElementsByTagName(tagName);

	var filteredElements = [];
	var len = elements.length;

	elementsLoop:
	for (var i=0; i < len; i++) {
		if (callbackFunc(elements[i], tagName, container)) {
			filteredElements[filteredElements.length] = elements[i];
		}
	}
	return filteredElements;
}

// }}}
