(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){



/**
 * @version    0.5.0
 * @date       2015-02-02
 * @stability  1 - Experimental
 * @author     Lauri Rooden <lauri@rooden.ee>
 * @license    MIT License
 */



!function(window, document, protoStr) {
	var currentLang
	, body = document.body
	, createElement = document.createElement
	, txtAttr = "textContent" in body ? "textContent" : "innerText"
	, elCache = {}
	, fnCache = {}
	, proto = (window.HTMLElement || window.Element || El)[protoStr]
	, selectorCache = {}
	, selectorRe = /([.#:[])([-\w]+)(?:([~^$*|]?)=((["'\/])(?:\\?.)*?\5|[-\w]+)])?]?/g
	, lastSelectorRe = /(\s*[>+]?\s*)((["'\/])(?:\\?.)*?\2|[^\s+>])+$/
	, pseudoClasses = {
		"empty": "!_.hasChildNodes()",
		"first-child": "_.parentNode&&_.parentNode.firstChild==_",
		"last-child" : "_.parentNode&&_.parentNode.lastChild==_",
		"link": "_.nodeName=='A'&&_.getAttribute('href')"
	}
	, templateRe = /^([ \t]*)(@?)((?:(["'\/])(?:\\?.)*?\4|[-\w\:.#\[\]=])+)[ \t]*(.*)$/gm
	, renderRe = /[;\s]*(\w+)(?:\s*\:((?:(["'\/])(?:\\?.)*?\3|[-,\s\w])*))?/g
	, bindings = El.bindings = {
		"class": function(node, data, name, fn) {
			toggleClass.call(node, name, fn.fn("_")(data))
		},
		"html": function(node, data, html) {
			node.innerHTML = html.format(data)
		},
		"txt": function(node, data, text) {
			node.txt(text.format(data))
		},
		"val": function(node, data, text) {
			node.val(text.format(data))
		}
	}


	/**
	 * Turns CSS selector like syntax to DOM Node
	 * @returns {Node}
	 *
	 * @example
	 * El("input#12.nice[type=checkbox]:checked:disabled[data-lang=en].class")
	 * <input id="12" class="nice class" type="checkbox" checked="checked" disabled="disabled" data-lang="en">
	 */

	function El(name, args, silence) {
		var el
		, pre = {}
		name = name.replace(selectorRe, function(_, op, key, fn, val, quotation) {
			pre[
				op == "." ?
				((pre[op = "class"] && (key = pre[op] + " " + key)), op) :
				op == "#" ?
				"id" :
				key
			] = quotation ? val.slice(1, -1) : val || key
			return ""
		}) || "div"

		// NOTE: IE-s cloneNode consolidates the two text nodes together as one
		// http://brooknovak.wordpress.com/2009/08/23/ies-clonenode-doesnt-actually-clone/
		el = (elCache[name] || (elCache[name] = document.createElement(name))).cloneNode(true).set(pre)

		return silence ?
		(fnCache[name] && el.setAttribute("data-call", name), el) :
		fnCache[name] && fnCache[name].call(el, args) || el.set(args)
	}
	window.El = El

	function append(child, before) {
		var fragment
		, el = this
		, i = 0
		, tmp = typeof child
		if (child) {
			if (tmp == "string" || tmp == "number") child = El.text(child)
			else if ( !("nodeType" in child) && "length" in child ) {
				// document.createDocumentFragment is unsupported in IE5.5
				// fragment = "createDocumentFragment" in document ? document.createDocumentFragment() : El("div")
				for (
					tmp = child.length
					, fragment = document.createDocumentFragment();
					i < tmp; ) append.call(fragment, child[i++])
				child = fragment
			}

			if (child.nodeType) el.insertBefore(child,
				(before === true ? el.firstChild :
				typeof before == "number" ? el.childNodes[
					before < 0 ? el.childNodes.length - before - 2 : before
				] : before) || null
			)
			if (child.appendHook) child.appendHook()
			//"childHook" in el && el.childHook()
		}
		return el
	}
	proto.append = append

	proto.after = function(silbing, before) {
		// call append so it works with DocumentFragment
		append.call(silbing.parentNode, this, before ? silbing : silbing.nextSibling)
		return this
	}

	proto.to = function(parent, before) {
		append.call(parent, this, before)
		return this
	}

	function hasClass(name) {
		// http://jsperf.com/regexp-indexof-perf/32
		return (" " + this.className + " ").indexOf(" " + name + " ") > -1
	}
	proto.hasClass = hasClass

	function addClass(name) {
		var el = this
		el.className += !el.className ? name : hasClass.call(el, name) ? "" : " " + name
		return el
	}
	proto.addClass = addClass

	function rmClass(name) {
		var el = this
		el.className = (" "+el.className+" ").replace(" "+name+" ", " ").trim()
		return el
	}
	proto.rmClass = rmClass

	function toggleClass(name, force) {
		if (arguments.length == 1) force = !hasClass.call(this, name)
		return ( force ? addClass : rmClass ).call(this, name), force
	}
	proto.toggleClass = toggleClass

	proto.empty = function() {
		for (var node, el = this; node = el.firstChild; ) kill.call(node)
		return el
	}

	function kill() {
		var el = this
		if (el.parentNode) el.parentNode.removeChild(el)
		if (Event.removeAll) Event.removeAll(el)
		if (el.killHook) el.killHook()
		if (el.empty) el.empty()
		return el
	}
	proto.kill = kill

	proto.on = function(ev, fn) {
		Event.add(this, ev, fn)
		return this
	}

	proto.non = function(ev, fn) {
		Event.remove(this, ev, fn)
		return this
	}

	proto.attr = attr
	function attr(key, val) {
		var el = this
		if (arguments.length == 1) {
			if (key && key.constructor === Object) {
				Object.each(key, function(val, key) {
					attr.call(el, key, val)
				})
				return
			}
			return el.getAttribute(key)
		}
		// Note: IE5-7 doesn't set styles and removes events when you try to set them.
		//
		// in IE6, a label with a for attribute linked to a select list
		// will cause a re-selection of the first option instead of just giving focus.
		// http://webbugtrack.blogspot.com/2007/09/bug-116-for-attribute-woes-in-ie6.html

		// there are bug in IE<9 where changed 'name' param not accepted on form submit
		// The JScript engine used in IE doesn't recognize vertical tabulation character
		// oldIE = "\v" == "v"
		//
		// IE8 and below also support document.createElement('<P>')
		//
		// http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/
		// http://msdn.microsoft.com/en-us/library/ms536614(VS.85).aspx

		//** modernBrowser
		if ((key == "id" || key == "name" || key == "type") && "\v" == "v") {
			el.mergeAttributes(createElement('<INPUT '+key+'="' + val + '">'), false)
		} else {
			el.setAttribute(key, val)
		}
		/*/
		el.setAttribute(key, val)
		//*/
	}

	proto.set = set
	function set(args, key, val) {
		var el = this
		if (args) {
			if (typeof args == "object") for (key in args) {
				val = args[key]
				// El uses class
				if (key == "class") addClass.call(el, val)
				else if (typeof val == "string") {
					attr.call(el, key, val)
				}
				else if (!val) el.removeAttribute(key)
			}
			else append.call(el, args)
		}
		return el
	}

	function render(data, skipSelf) {
		var bind, fn, lang
		, node = this

		if (bind = !skipSelf && node.getAttribute("data-call")) {
			node.removeAttribute("data-call")
			fnCache[bind].call(node)
		}
		if (bind = !skipSelf && node.getAttribute("data-bind")) {
			lang = node.getAttribute("lang") || lang
			// HACK: allow .el ={name} short syntax
			if (bind.charAt(0) == "{") bind='txt:"' + bind.replace(/"/g, '\\"') + '"'
			// i18n(bind, lang).format(data)
			// document.documentElement.lang
			// document.getElementsByTagName('html')[0].getAttribute('lang')

			fn = "n d p r->d&&(" + bind.replace(renderRe, "(p['$1']?(r=p['$1'](n,d,$2)||r):(n['$1']=$2.format(d))),") + "r)"

			if (Fn(fn)(node, data, bindings)) return node
		}

		for (node = node.firstChild; node; node = node.nextSibling) {
			if (node.nodeType == 1) {
				render.call(node, data)
			}
		}
		return this
	}

	proto.render = render

	// In Safari 2.x, innerText functions properly only
	// if an element is neither hidden (via style.display == "none")
	// nor orphaned from the document.
	// Otherwise, innerText results in an empty string.
	//
	// textContent is suported from IE9
	// Opera 9-10 have Node.text so we use Node.txt

	proto.txt = function(newText) {
		return arguments.length ? (this[txtAttr] = newText) : this[txtAttr]
	}

	proto.val = function(val) {
		var el = this
		, type = el.type
		, opts = el.options

		if (arguments.length) {
			return el.value = val
		}

		if (type == "select-multiple") {
			for (val = [], type = 0; el = opts[type++];) {
				if (el.selected && !el.disabled && !el.parentNode.disabled) val.push(el.value)
			}
			return val
		}

		return (type == "checkbox" || type == "radio") && !el.checked ? "" :
			el.value ||
			options && options[el.selectedIndex].value ||
			"on"
	}

	function findEl(node, sel, first) {
		var el
		, i = 0
		, out = []
		, els = node.getElementsByTagName("*")
		, fn = selectorFn(sel.split(/\s*,\s*/).map(function(sel) {
			return "_.matches('" + sel + "')"
		}).join("||"))

		for (; (el = els[i++]); ) if (fn(el)) {
			if (first) return el
			out.push(el)
		}
		return first ? null : out
	}

	function selectorFnStr(sel) {
		var rules = ["_"]
		, tag = sel.replace(selectorRe, function(_, op, key, fn, val, quotation, len) {
			if (quotation) val = val.slice(1, -1)
			if (val) {
				len = val.length
				val = val.replace(/'/g, "\\'")
			}
			rules.push(
				op == "." ? "(' '+_.className+' ').indexOf(' " + key + " ')>-1" :
				op == "#" ? "_.id=='" + key + "'" :
				op == ":" && pseudoClasses[key] ||
				"(a=_.getAttribute('" + key + "'))" + (!fn && val ? "=='" + val + "'" : "")
			)
			if (fn) rules.push(
				fn == "^" ? "a.slice(0," + len + ")=='" + val + "'" :
				fn == "|" ? "a.split('-')[0]=='" + val + "'" :
				fn == "$" ? "a.slice(-" + len + ")=='" + val + "'" :
				fn == "~" ? "(' '+a+' ').indexOf(' " + val + " ')>-1" :
				"a.indexOf('" + val + "')>-1" // fn == "*"
			)
			return ""
		})

		if (tag && tag != "*") rules.unshift("_.nodeName=='" + tag.toUpperCase() + "'")
		return rules.join("&&")
	}

	function selectorFn(str) {
		// jshint evil:true
		return selectorCache[str] ||
		(selectorCache[str] = Function("_,a", "return " + str))
	}

	proto.matches = proto.matches || function(sel) {
		var relation, from
		, parentSel = sel.replace(lastSelectorRe, function(_, _rel, a, b, start) {
			from = start + _rel.length
			relation = _rel.trim()
			return ""
		})
		, next = relation == "+" ? this.previousSibling : this.parentNode
		, fn = selectorFn(selectorFnStr(sel.slice(from)))

		if (!fn(this)) return false

		if (parentSel) {
			if (!relation) return !!(next && next.closest && next.closest(parentSel))
			return next && next.matches && next.matches(parentSel) || false
		}
		return true
	}

	proto.closest = proto.closest || function(sel) {
		for (var el = this; el; el = el.parentNode) if (el.matches && el.matches(sel)) return el
		return null
	}

	//** modernBrowser
	// Note: IE8 don't support :disabled
	proto.find = "\v" !== "v" && proto.querySelector || function(sel) {
		return findEl(this, sel, true)
	}

	proto.findAll = proto.querySelectorAll ?
		function(sel) {
			return new ElWrap(this.querySelectorAll(sel))
		} :
		function(sel) {
			return new ElWrap(findEl(this, sel))
		}
	/*/
	proto.find = proto.querySelector
	proto.findAll = function(sel) {
		return new ElWrap(this.querySelectorAll(sel))
	}
	//*/


	function ElWrap(nodes) {
		this._nodes = nodes
	}
	El.wrap = ElWrap

	ElWrap.prototype = Object.keys(proto).reduce(function(memo, key) {
		memo[key] = function() {
			var nodes = this._nodes
			, i = 0
			, len = nodes.length
			for (; i < len; ) {
				proto[key].apply(nodes[i++], arguments)
			}
			return this
		}
		return memo
	}, {})

	//** modernBrowser
	function extend(node, key) {
		if (node) for (key in proto) node[key] = proto[key]
		return node
	}

	// IE 6-7
	if (proto === El[protoStr]) {
		document.createElement = function(name) {
			return extend(createElement(name))
		}

		// NOTE: document.body will not get extended with later added extensions
		extend(body)
	}
	//*/

	El[protoStr] = proto

	El.get = function(id) {
		if (typeof id == "string") id = document.getElementById(id)
		//** modernBrowser
		return id && id.to ? id : extend(id)
		/*/
		return id
		//*/
	}

	function elCacheFn(name, el, custom) {
		elCache[name] = typeof el == "string" ? El(el) : el
		if (custom) {
			fnCache[name] = custom
		}
	}

	elCacheFn._el = elCache
	elCacheFn._fn = fnCache
	El.cache = elCacheFn

	El.text = function(str) {
		return document.createTextNode(str)
	}

	//** templates

	function tpl(str) {
		var root = document.createDocumentFragment()
		, parent = root
		, stack = [-1]

		function work(all, indent, plugin, name, q, text) {
			for (var i = indent.length; i <= stack[0]; ) {
				stack.shift()
				parent = (parent.plugin) ? parent.plugin.done() : parent.parentNode
			}

			if (plugin) {
				if (tpl.plugins[name]) {
					parent = (new tpl.plugins[name](parent, text)).el
					stack.unshift(i)
				} else {
					parent.append(El.text( name == "text" ? text : all ))
				}
			} else {
				if (name) {
					parent = El(name, 0, 1).to(parent)
					stack.unshift(i)
				}
				if (text) {
					q = text.charAt(0)
					if (q == ">") {
						(indent +" "+ text.slice(1)).replace(templateRe, work)
					} else if (q == "=") {
						parent.set({"data-bind": text.slice(1)})
					} else {
						parent.append(text.replace(/\\([=>:])/g, "$1"))
					}
				}
			}
		}
		str.replace(templateRe, work)
		root = root.childNodes
		if (root.length == 1) return root[0]

		for (stack = [], parent = root.length; parent--;) stack[parent] = root[parent]
		return stack
	}

	function template(parent, name) {
		var t = this
		t.name = name
		t.parent = parent
		t.el = El("div")
		t.el.plugin = t
		return t
	}

	template.prototype.done = function() {
		var t = this
		El.cache(t.name, t.el.removeChild(t.el.firstChild), render)
		t.el.plugin = null
		return t.parent
	}

	tpl.plugins = {
		"template": template
	}

	El.create = El.tpl = function(str) {
		return tpl(str).render()
	}
	El.include = function(id, data, parent) {
		var src = El.get(id)
		new template(null, id).el.append( El.tpl(src.innerHTML) ).plugin.done()
		src.kill()
	}
	//*/


	//** i18n
	function i18n(text, lang) {
		return i18n[ lang ? getLang(lang) : currentLang ][text] || text
	}
	El.i18n = i18n

	function getLang(lang) {
		if (!lang) return currentLang
		lang = (lang || "").toLowerCase()
		return i18n[lang] ? lang : ((lang = lang.split("-")[0]), i18n[lang]) ? lang : currentLang
	}

	function setLang(lang) {
		lang = getLang(lang)
		if (currentLang != (currentLang = lang)) {
			i18n[lang] = i18n[lang] || {}
		}
		// Use setAttribute
		document.documentElement.lang = lang
		return lang
	}

	function addLang(lang, texts) {
		Object.merge(i18n[lang] || (i18n[lang] = {}), texts)
	}

	i18n.get = getLang
	i18n.use = setLang
	i18n.add = addLang
	i18n.def = function(map) {
		Object.each(map, function(name, tag) {
			addLang(tag, map)
		})
	}
	// navigator.userLanguage for IE, navigator.language for others
	// var lang = navigator.language || navigator.userLanguage;
	// setLang("en")
	//*/

}(window, document, "prototype")



},{}],2:[function(require,module,exports){



/*
* @version    1.1.0
* @date       2014-09-12
* @stability  3 - Stable
* @author     Lauri Rooden <lauri@rooden.ee>
* @license    MIT License
*/




!function(window) {
	var a, b, c, O
	, P = "prototype"
	, F = Function
	, esc = escape
	, patched = window._patched = []


	function add(key, src) {
		if (!O[key]) {
			O[key] = new F("a,b,c","var P='"+P+"';"+src)
			patched.push(key)
		}
	}

	F.Nop = function(){}

	/*
	* The HTML5 document.head DOM tree accessor
	*/

	//doc.head = doc.head || doc.getElementsByTagName("head")[0]

	/*
	* Function.prototype.bind from ECMAScript5
	* Basic support:	Chrome 7 Firefox (Gecko) 4.0 (2) IE 9 Opera 11.60 Safari 5.1.4
	*
	* http://msdn.microsoft.com/en-us/library/s4esdbwz(v=vs.94).aspx
	*/
	O = F[P]
	add("bind", "var t=this;b=[].slice.call(arguments,1);c=function(){return t.apply(this instanceof c?this:a,b.concat.apply(b,arguments))};if(t[P])c[P]=t[P];return c")


	// Object extensions
	// -----------------

	O = Object
	add("create" , "b=Function.Nop;b[P]=a;return new b")
	add("keys"   , "c=[];for(b in a)Object.prototype.hasOwnProperty.call(a,b)&&c.push(b);return c")




	// Array extensions
	// ----------------

	O = Array
	add("isArray", "return a instanceof Array")

	O = O[P]
	a = "var t=this,l=t.length,o=[],i=-1;"
	c = "if(t[i]===a)return i;return -1"
	add("indexOf",     a+"i+=b|0;while(++i<l)"+c)
	add("lastIndexOf", a+"i=(b|0)||l;i>--l&&(i=l)||i<0&&(i+=l);++i;while(--i>-1)"+c)

	b = a+"if(arguments.length<2)b=t"
	c = "b=a.call(null,b,t[i],i,t);return b"
	add("reduce",      b+"[++i];while(++i<l)"+c)
	add("reduceRight", b+"[--l];i=l;while(i--)"+c)

	b = a+"while(++i<l)if(i in t)"
	add("forEach",     b+"a.call(b,t[i],i,t)")
	add("every",       b+"if(!a.call(b,t[i],i,t))return!1;return!0")

	c = ";return o"
	add("map",         b+"o[i]=a.call(b,t[i],i,t)"+c)

	b += "if(a.call(b,t[i],i,t))"
	add("filter",      b+"o.push(t[i])"+c)
	add("some",        b+"return!0;return!1")


	O = String[P]
	add("trim", "return this.replace(/^\\s+|\\s+$/g, '')")

	O = Date
	add("now", "return+new Date")

	/*
	* `Date.prototype.format` is implemented in `date-format-lite` module.
	*/

	O = O[P]
	add("toISOString", "return this.format('isoUtcDateTime')")


	if (!window.JSON) {
		patched.push("JSON")
		window.JSON = {
			map: {"\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r","\t":"\\t",'"':'\\"',"\\":"\\\\"},
			parse: new F("t", "return new Function('return('+t+')')()"),
			//parse: Fn("t->new Function('return('+t+')')()"),
			stringify: new F("o", "if(o==null)return'null';if(o instanceof Date)return'\"'+o.toISOString()+'\"';var i,s=[],c;if(Array.isArray(o)){for(i=o.length;i--;s[i]=JSON.stringify(o[i]));return'['+s.join()+']'}c=typeof o;if(c=='string'){for(i=o.length;c=o.charAt(--i);s[i]=JSON.map[c]||(c<' '?'\\\\u00'+((c=c.charCodeAt(0))|4)+(c%16).toString(16):c));return'\"'+s.join('')+'\"'}if(c=='object'){for(i in o)Object.prototype.hasOwnProperty.call(o,i)&&s.push(JSON.stringify(i)+':'+JSON.stringify(o[i]));return'{'+s.join()+'}'}return''+o")
		}
	}

	// Ignore FF3 escape second non-standard argument
	// https://bugzilla.mozilla.org/show_bug.cgi?id=666448
	if (esc("a",0) != "a") {
		patched.push("escape")
		window.escape = function(s) {
			return esc(s)
		}
	}

}(this)




},{}],3:[function(require,module,exports){



/**
 * @version    0.3.0
 * @date       2014-12-08
 * @stability  2 - Unstable
 * @author     Lauri Rooden <lauri@rooden.ee>
 * @license    MIT License
 */



!function(exports) {
	var P = "prototype"
	, A = Array[P], F = Function[P], S = String[P]
	, O = Object
	, hasOwn = O[P].hasOwnProperty
	, slice = F.call.bind(A.slice)
	, constructFns = []
	, fnRe = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|this|arguments|\.\w+|\w+:/g



	// Function extensions
	// -------------------


	F.construct = function(a) {
		// bind version have bad performance and memory consumption
		// return new(F.bind.apply(this, A.concat.apply([null], a)))
		var len = a.length
		return len ?
			(constructFns[len] || (constructFns[len] = Fn("t a->new t(a["+O.keys(slice(a)).join("],a[")+"])")))(this, a) :
			new this
	}

	F.partial = function() {
		var self = this
		, a = slice(arguments)
		return function() {
			return self.apply(this, a.concat.apply(a, arguments))
		}
	}

	/*
	 * **argi** - index of argument, which will be split
	 * **re**   - optional RegExp for matching words
	 */

	F.byWords = function(argi, re) {
		var self = this
		return function() {
			var s = this
			, r = s
			, a = arguments
			;(a[argi |= 0]||"").replace(re || /\S+/g, function(w) {
				a[argi] = w
				r = self.apply(s, a)
			})
			return r
		}
	}

	F.byKeyVal = function() {
		var self = this
		return function(o) {
			var r
			, s = this
			, a = slice(arguments)
			if (typeof o == "object") for (r in o) {
				a[0] = r
				a[1] = o[r]
				r = self.apply(s, a)
			} else r = self.apply(s, a)
			return r
		}
	}

	// Run function once and return cached value or cached instance
	F.cache = function(instance, keyFn, cache) {
		var self = this
		, c = cache || {}
		, f = function() {
			var a = arguments
			, i = !!instance || this instanceof f
			, k = keyFn ? keyFn.apply(self, a) : i + ":" + a.length + ":" + slice(a)

			return k in c ? c[k] : (c[k] = i ? self.construct(a) : self.apply(this, a))
		}

		f.origin = self
		f.cached = c
		f.extend = function() {
			return self.extend.apply(self, arguments).cache(instance, keyFn, cache)
		}
		f[P] = self[P] // prototype for better access on extending 
		return f
	}

	F.extend = function() {
		var a
		, self = this
		, i = 0

		function f() {
			return self.apply(this, arguments)
		}

		for (f[P] = O.create(self[P]); a = arguments[i++];) O.merge(f[P], a)
		f[P].constructor = f
		return f
	}


	// Non-standard
	O.each = function(obj, fn, scope, key) {
		if (obj) for (key in obj) hasOwn.call(obj, key) && fn.call(scope, obj[key], key, obj)
	}

	// Object.assign ( target, source ) in ECMAScript 6

	O.merge = function(target, source) {
		for (var key, i = 1; source = arguments[i++];)
			for (key in source) if (hasOwn.call(source, key)) target[key] = source[key]
		return target
	}

	// Note: use for Object literals only,
	// as it returns false for custom objects,
	// like new Date or new YourObject.

	function isObject(obj) {
		return obj && obj.constructor === O
	}

	O.clone = function(source, temp, key) {
		if (isObject(source)) {
			temp = {}
			for (key in source) if (hasOwn.call(source, key))
				temp[key] = O.clone(source[key])
			source = temp
		}
		return source
	}

	O.zip = function(keys, vals) {
		return keys.fold(function(_, key, i) {
			_[key] = vals[i]
			return _
		}, {})
	}

	/*
	Array.flatten = function(arr) {
	for(var i=arr.length;i--;)
	0 in arr[i] && A.splice.apply(arr, [i, 1].concat(Array.flatten(arr[i])))
	return arr
	}
	flat([1,2,[3,4,[5,6]],7])
	*/
	// Non-standard
	// // IE < 9 bug: [1,2].splice(0).join("") == "" but should be "12"
	A.remove = function() {
		var arr = this
		, len = arr.length
		, o = slice(arguments)
		, lastId = -1

		for (;len--;) if (~o.indexOf(arr[len])) arr.splice(lastId = len, 1)
		return lastId
	}

	A.each = A.forEach
	A.fold = A.reduce
	A.foldr = A.reduceRight
	// uniq
	// first item preserved
	A.uniq = A.filter.partial(function(elem, i, arr) {
		return i == arr.indexOf(elem)
	})

	A.pushUniq = function(item) {
		return this.indexOf(item) == -1 ? this.push(item) : false
	}

	!function(n) {
		F[n] = S[n] = function() {
			var a = arguments, l = a[0]
			a[0] = this.fn()
			return A[n].apply(l, a)
		}
	}.byWords()("every filter each map fold foldr some")


	F.fn = function() {
		return this
	}

	S.fn = function(scope) {
		return Fn(this, scope)
	}

	// THANKS: Oliver Steele http://www.osteele.com/sources/javascript/functional/
	function Fn(expr, scope) {
		for (var args = "_", body = expr, arr = expr.split("->"); arr.length > 1; ) {
			body = arr.pop()
			args = arr.pop().match(/\w+/g) || ""
			if (arr.length) arr.push("(function("+args+"){return("+body+")})")
		}
		// `replace` removes symbols that follow '.',
		//  precede ':', are 'this' or 'arguments'; and also the insides of
		//  strings (by a crude test).  `match` extracts the remaining
		//  symbols.
		return new Function(args, (scope && (expr = expr.replace(fnRe, "").match(/\b[a-z]\w*|\b_\w+/g)) ?
			"var " + expr.uniq().join("='',") + "='';with(" + scope + "||{})" : "") + "return(" + body + ")")
	}

	exports.Fn = Fn.cache()

}(this)




},{}],4:[function(require,module,exports){



/*
* @version    0.1.0
* @date       2014-08-24
* @stability  2 - Unstable
* @author     Lauri Rooden <lauri@rooden.ee>
* @license    MIT License
*/



!function(P) {
	var A = Array[P]
	, D = Date[P]
	, N = Number[P]
	, S = String[P]
	, formatRe = /\{(?!\\)(.+?)\}/g
	, filterRe = /\|\s*(\w+)(?:\s*\:((?:(["'\/])(?:\\.|.)*?\3|\-?\d*\.?\d+|[,\s])*))?/g
	, digitRe = /^\s*\d+/
	, unescapeRe = /{\\/g

	S.format = function(data, recursions) {
		var args = typeof data == "object" ? data : arguments
		return this.replace(formatRe, function(_, arg) {
			_ = Fn(arg.replace(digitRe, "_[$&]").replace(filterRe, ".$1($2)"), "_")(args)
			return args === data && recursions ? _.format(data, recursions - 1) : _
		}).replace(unescapeRe, "{")
	}

	N.format = function(data, recursions) {
		return ("" + this).format(data, recursions)
	}

	S.safe = function() {
		return this
		.replace(/&/g, "&amp;")
		.replace(/</g, "&lt;")
		.replace(/>/g, "&gt;")
		.replace(/\"/g, "&quot;")
	}


	S.capitalize = function() {
		return this.charAt(0).toUpperCase() + this.slice(1)
	}

	S.lower = S.downcase = S.toLowerCase // lower
	S.upper = S.upcase = S.toUpperCase   // upper
	S.size = A.size = function() {
		return this.length
	}
	S.truncate = function(num) {
		return this.slice(0, num)
	}
	S.truncatewords = function(num) {
		return this.split(" ").splice(0, num).join(" ")
	}
	S.remove = function(str) {
		return this.split(str).join("")
	}
	S.remove_first = function(str) {
		var arr = this.split(str)
		return arr.shift() + arr.join(str)
	}

	S.camelback = function() {
		return this.replace(/[ _-]+([a-z])/g, function(_, a){return a.toUpperCase()})
	}
	S.camelcase = function() {
		return this.camelback().capitalize()
	}
	//*
	S.repeat = S.times = function(times) {
		return times < 1 ? "" : Array(++times).join(this)
	}
	/*/
	// High porformance repeat when we should need it
	// http://stackoverflow.com/questions/202605/repeat-string-javascript

	function stringFill3(x, n) {
		var s = '';
		for (;;) {
			if (n & 1) s += x;
			n >>= 1;
			if (n) x += x;
			else break;
		}
		return s;
	}


	//*/


	A.first = function() {
		return this[0]
	}
	A.last = function() {
		return this[this.length - 1]
	}
	A.pluck = function(name) {
		var t = this, i = t.length, out = []
		while (i--) out[i] = t[i][name]
		return out
	}

	S.step = N.step = S.toAccuracy = N.toAccuracy = function(a) {
		var x = (""+a).split("."), n = ~~((this/a)+.5) * a
		return ""+(1 in x ? n.toFixed(x[1].length) : n)
	}

	S.pick = N.pick = function() {
		var val = this + "="
		for (var s, a = arguments, i = 0, len = a.length; i < len;) {
			s = a[i++]
			if (s.indexOf(val) == 0) {
				s = s.slice(val.length)
				i = len
			}
		}
		return s.replace("#", this)
	}
	S.plural = N.plural = function() {
		// Plural-Forms: nplurals=2; plural=n != 1;
		// http://www.gnu.org/software/gettext/manual/html_mono/gettext.html#Plural-forms
		return arguments[ +Fn("n->n != 1")( parseFloat(this) ) ].replace("#", this)
	}
	S.ordinal = N.ordinal = function() {
		return this+'{0|substr:-1|pick:"1=st","2=nd","3=rd","th"}'.format(""+this)
	}

	function words(input, steps, units, strings, overflow) {
		var n = +input
		, i = 0
		, s = strings || {"default":"{0} {1}{2}"}

		while(n>steps[i])n/=steps[i++]
		if (i == steps.length && overflow) return overflow(this)
		i=units[i]
		n=(n+.5)|0
		return (s[n<2?i:i+"s"]||s["default"]).format(n, i, n<2?"":"s")
	}

	S.humanSize = N.humanSize = function() {
		return words(this, [1024,1024,1024], ["byte","KB","MB","GB"])
	}
	S.humanTime = N.humanTime = function(texts) {
		return words(this, [60,60,24,7,30], ["second","minute","hour","day","week","month"], texts)
	}

	//** Date.daysInMonth
	D.daysInMonth = function() {
		return (new Date(this.getFullYear(),this.getMonth()+1,0)).getDate()
	}
	//*/

	//** Date.startOfWeek
	D.startOfWeek = function() {
		var t = this
		return new Date(t.getFullYear(), t.getMonth(), t.getDate() - (t.getDay() || 7) +1)
	}
	//*/
	//** Date.timeAgo convert dates to human-readable
	D.timeAgo = function(format, custom) {
		var t = this, d = (new Date() - t + 1) / 1000
		return d.humanTime({"default":"{0} {1}{2} ago", "day":"Yesterday"}, function(){return t.format(format)})
	}
	//*/
}("prototype")



},{}],5:[function(require,module,exports){
(function (process){



/*
* @version    0.1.8
* @date       2014-05-21
* @stability  2 - Unstable
* @author     Lauri Rooden <lauri@rooden.ee>
* @license    MIT License
*/



!function(root) {
	var undef
	, tests = []
	, toString = Object.prototype.toString
	, bold  = '\u001b[1m'
	, red   = '\u001b[31m'
	, green = '\u001b[32m'
	, reset = '\u001b[0m'

	function This() {
		return this
	}

	/*

	var tick = root.process && root.process.nextTick || setTimeout
	, codes = {
		bold: 1,
		underline: 4,
		reverse: 7,
		black: 30,
		red: 31,
		green: 32,
		yellow: 33,
		blue: 34,
		magenta: 35,
		cyan: 36,
		white: 37
	}


	function Async(fn) {
		var t = this
		t.pending = 0
		t.cb = function() {
			tick(function(){--t.pending==0&&fn()}, 0)
		}
	}

	Async.prototype.wait = function(next) {
		var t = this
		t.pending++
		return next ? 
			function() {
				next.apply(this, arguments)
				t.cb()
			} :
			t.cb
	}
	*/

	function Lazy() {
		var t = this
		, hooks = []
		, hooked = []

		for (var a = arguments, i = a.length; i--; ) !function(k) {
			hooked.push([k, t.hasOwnProperty(k) && t[k]])
			t[k] = function(){hooks.push([k, arguments]);return t}
		}(a[i])

		t.resume = function() {
			delete t.resume

			for (var v, i = hooked.length;i--;) {
				if (hooked[i][1]) t[hooked[i][0]] = hooked[i][1]
				else delete t[hooked[i][0]]
			}
			// i == -1 from previous loop
			for (;v=hooks[++i];) t = t[v[0]].apply(t, v[1])
			t = hooks = hooked = null
		}
		return t
	}

	function type(obj) {
		if (obj === null) return "null"
		if (obj === undef) return "undefined"
		/*
		* Standard clearly states that NaN is a number
		* but it is not useful for testing.
		*/
		if (obj !== obj) return "nan"

		return toString.call(obj).slice(8, -1).toLowerCase()
	}

	console.log("TAP version 13")
	var started;

	var just_one = parseInt(process.argv[2]) || false
	var just_two = parseInt(process.argv[3]) || false

	function describe(name) {
		var t = this
		if (!(t instanceof describe)) return new describe(name)

		if (!started) started = +new Date()

		t.name  = name || "{anonymous test}"
		t.it    = function(name, options){
			return t._it(name, options)
		}
		t.done  = function(){
			setTimeout(function(){
				t._done()
			}, 1)
		}
		t.cases = []

		console.log("# "+t.name)
		tests.push(t)

		if (just_one && tests.length != just_one) {
			console.log("# skip ", just_one, tests.length)
			t.it = t.ok = t.equal = t.type = t.run = This
		}
		return t
	}

	var assert_num = 1

	describe.prototype = {
		describe: function(name) {
			return new describe(name)
		},
		_it: function(name, options) {
			var t = this
			, assert = new it(name, options, assert_num)

			assert.it = function(){
				assert.end()
				return t.it.apply(t, arguments)
			}
			assert.done = function(){
				assert.end()
				return t.done.apply(t, arguments)
			}
			assert.num = assert_num++
			t.cases.push( assert )
			return assert
		},
		_done: function() {
			var i, j, test, assert
			, count = 0
			, failed = 0
			, passed_asserts = 0
			, failed_asserts = 0
			, ended = +new Date()

			for (i = 0; test = tests[i++]; ) {
				for (j = 0; assert = test.cases[j++]; ) {
					if (assert.failed.length) failed++
					failed_asserts += assert.failed.length
					passed_asserts += assert.passed.length
				}
				count += test.cases.length
			}
			console.log("1.." + count)
			console.log("#" + (failed ? "" : green + bold) + " pass  " + (count - failed) 
				+ "/" + count
				+ " [" + passed_asserts + "/" +(passed_asserts + failed_asserts)+ "]"
				+ " in " + (ended - started) + " ms"
				+ reset)

			failed && console.log("#" + red + bold + " fail  " + failed
				+ " [" +failed_asserts+ "]"
				+ reset)
			/*
			* FAILED tests 1, 3, 6
			* Failed 3/6 tests, 50.00% okay
			* PASS 1 test executed in 0.023s, 1 passed, 0 failed, 0 dubious, 0 skipped.
			*/
			if (typeof process != "undefined" && process.exit) process.exit()
		}
	}

	function it(name, options, num){
		var t = this
		if (!(t instanceof it)) return new it(name, options)
		t.name = name || "{anonymous assert}"
		t.options = options || {}
		t.hooks = []
		t.failed = []
		t.passed = []

		if (just_two && num != just_two) t.options.skip = "by argv"
		if (t.options.skip) {
			t.ok = t.equal = t.type = t.run = This
		}
		return t
	}

	it.prototype = describe.asserts = {
		describe: function(){
			this.end()
			return describe.apply(this, arguments)
		},
		end: function(){
			console.log(""+this)
		},
		wait: function() {
			Lazy.call(this, "it", "wait", "run", "ok", "equal", "anyOf", "describe", "done")
			return this.resume
		},
		run: function(fn) {
			fn.call(this)
			return this
		},
		ok: function(value, options) {
			var t = this
			options = options || {}

			if (typeof options == "string") options = { message: options }

			if (typeof value == "function") value = value.call(t)
			t[ value ? "passed" : "failed" ].push(options.message + " #" + (t.passed.length+t.failed.length+1))
			return t
		},
		equal: function(a, b, options) {
			if (typeof a == "function") a = a.call(this)
			if (typeof b == "function") b = b.call(this)
			return this.ok( a === b, options || "Expected: "+b+" Got: "+a )
		},
		anyOf: function(a, b, options) {
			return this.ok( Array.isArray(b) && b.indexOf(a) != -1, options || "should be one of '" + b + "', got " + a )
		},
		type: function(thing, expected, options) {
			var t = type(thing)
			return this.ok( t === expected, options || "type should be " + expected + ", got " + t )
		},
		toString: function() {
			var t = this
			, fail = t.failed.length
			, fail_log = ""
			, name = t.num + " - it " + t.name

			if (t.options.skip) {
				return "ok " + name + " # skip - " + t.options.skip
			}

			if (fail) {
				fail_log = "\n  ---\n    messages:\n      - " + this.failed.join("\n      - ") + "\n  ---"
			}

			return (fail ? "not ok " : "ok ") + name + 
						" [" + (this.passed.length) + "/" + (this.passed.length+fail) + "]" + fail_log

		}
	}
	module.exports = describe.describe = describe

}(this)


/*
* http://sourceforge.net/projects/portableapps/files/
*/


}).call(this,require("/usr/lib/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"/usr/lib/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":7}],6:[function(require,module,exports){
(function (global){
require("browser-upgrade-lite")
global.Fn = require("functional-lite").Fn

global.Event = global.Event || {}

require("liquid-filters-lite")
require("../")
global.i18n = window.El.i18n

function getString(node) {
	if ('outerHTML' in node)
		return node.outerHTML.toLowerCase().replace(/>[\n\r]+</g, "><").trim()

	var div = document.createElement("div")
	div.appendChild(node.cloneNode(true))
	return div.innerHTML
}

i18n.def({ "et":"Eesti keeles"
	, "en":"In English"
	, "ru":"На русском"
	, "fi":"Suomeksi"
	, "se":"på Svenska"
})

i18n.add("en", {
	date: "%a, %d %b %Y %H:%M:%S %z",
	name: "Name {date|lang}"
})

i18n.add("et", {
	date: "%Y %H:%M:%S %z",
	name: "Nimi {date|lang:'et'}"
})

/*
 * navigator.language
 * "et"
 * navigator.languages
 * ["et", "en-US", "en"]
 */
//i18n.setLang(navigator.language || navigator.userLanguage)

Date.prototype.lang = function(lang) {
	return this.format( i18n("date", lang) )
}

String.prototype.lang = function(lang) {
	return i18n(this, lang)
}

i18n.add("en", {
	firstName: "First Name",
	lastName: "Last Name"
})

i18n.use("en")

var el, h1, h2, h3, h4, input, select, t1

require("testman").

describe("El").
	it ("should build elements").
		run(function(){
			el = El("div")
			select = El("select#id2.cl2:disabled")
			input = El("input")
			h1 = El("h1")
			h2 = El("h2")
			h3 = El("h3")
			h4 = El("h4")
		}).
		equal(getString(el), "<div></div>").
		equal(getString(h1), "<h1></h1>").
		equal(getString(h2), "<h2></h2>").
		equal(getString(h3), "<h3></h3>").
		equal(getString(h4), "<h4></h4>").

		equal(getString(El("")), "<div></div>").
		equal(getString(El("div")), "<div></div>").
		equal(getString(El("", "element")), "<div>element</div>").
		equal(getString(El("div", "element")), "<div>element</div>").
		equal(getString(El("p", "element")), "<p>element</p>").
		anyOf(getString(El("#123")),	[ '<div id="123"></div>'
						, '<div id=123></div>'
						]).
		anyOf(getString(El("div#123")),	[ '<div id="123"></div>'
						, '<div id=123></div>'
						]).
		anyOf(getString(El("p#123")),	[ '<p id="123"></p>'
						, '<p id=123></p>'
						]).
		anyOf(getString(El(".c-1")),	[ '<div class="c-1"></div>'
						, '<div class=c-1></div>'
						]).
		anyOf(getString(El("div.c1")),	[ '<div class="c1"></div>'
						, '<div class=c1></div>'
						]).
		anyOf(getString(El("p.c1")),	[ '<p class="c1"></p>'
						, '<p class=c1></p>'
						]).
		equal(getString(El(".c1.c2")), '<div class="c1 c2"></div>').
		equal(getString(El("div.c1.c2")), '<div class="c1 c2"></div>').
		equal(getString(El("p.c1.c2")), '<p class="c1 c2"></p>').
		anyOf(getString(El("#123.c1")),	[ '<div id="123" class="c1"></div>'
		     				, '<div class="c1" id="123"></div>'
						, '<div class=c1 id=123></div>'
						, '<div id=123 class=c1></div>'
						]).
		anyOf(getString(El("div#123.c1")),	[ '<div id="123" class="c1"></div>'
		     					, '<div class="c1" id="123"></div>'
							, '<div class=c1 id=123></div>'
							, '<div id=123 class=c1></div>'
		     					]).

		equal(getString(El("a[href='http://example.com/']")), '<a href="http://example.com/"></a>').
		equal(getString(El('a[href="http://example.com/"]')), '<a href="http://example.com/"></a>').
		anyOf(getString(El("a[href='http://example.com/'][title=link]")),
			[ '<a href="http://example.com/" title="link"></a>'
			, '<a title="link" href="http://example.com/"></a>',
			, '<a title=link href="http://example.com/"></a>'
			]).
		anyOf(getString(El('a[href="http://example.com/"][title="link to site"]')),
			[ '<a href="http://example.com/" title="link to site"></a>'
			, '<a title="link to site" href="http://example.com/"></a>'
			]).

	it ("shoult set attributes").
		equal(input.set({id: "set_id", title:"set title"}), input).
		equal(input.id, "set_id").
		equal(input.title, "set title").
		equal(input.set({title:"change title", name:"new name", id: "new_id"}), input).
		equal(input.title, "change title").
		equal(input.name, "new name").
		equal(input.id, "new_id").
		equal(input.set({title: null}), input).
		ok(!input.title).

	it ("has kill() and empty() methods").
		equal(select.kill(), select).
		equal(h2.innerHTML, "").
		equal(el.empty(), el).
		equal(el.innerHTML, "").

	it ("set childs").
		equal(getString(el.to(document.body)), "<div></div>").
		equal(getString(el.append(h2)), "<div><h2></h2></div>").
		equal(getString(el.append(h1, h2)), "<div><h1></h1><h2></h2></div>").
		equal(getString(h4.after(h2)), "<h4></h4>").
		equal(getString(el), "<div><h1></h1><h2></h2><h4></h4></div>").
		equal(getString(h3.after(h4, true)), "<h3></h3>").
		equal(getString(el), "<div><h1></h1><h2></h2><h3></h3><h4></h4></div>").
		equal(getString(h3.to(el, h4)), "<h3></h3>").
		equal(getString(el), "<div><h1></h1><h2></h2><h3></h3><h4></h4></div>").

		equal(getString(h1.append([h2, h3])), "<h1><h2></h2><h3></h3></h1>").
		equal(getString(el), "<div><h1><h2></h2><h3></h3></h1><h4></h4></div>").

		anyOf(getString(select.to(h2)),	[ '<select id="id2" disabled="disabled" class="cl2"></select>'
		     				, '<select disabled="disabled" class="cl2" id="id2"></select>'
						, '<select id="id2" class="cl2" disabled="disabled"></select>'
						, '<select class=cl2 id=id2 disabled></select>'
						, '<select id=id2 class=cl2 disabled></select>'
						, '<select disabled id=id2 class=cl2></select>'
						, '<select disabled class=cl2 id=id2></select>'
		     				]).
	it ("should get element by id").
		equal(El.get("id2"), select).

	it ("find childs").
		equal(el.find("#id2"), select).
		equal(el.find(".cl2"), select).
		equal(el.find("#id2.cl2"), select).
		equal(el.find(".cl2#id2"), select).
		equal(el.find("select"), select).
		equal(el.find("select#id2"), select).
		equal(el.find("select.cl2"), select).
		equal(el.find("select#id2.cl2"), select).
		equal(el.find("select.cl2#id2"), select).
		equal(el.find("SELECT"), select).
		equal(el.find("SELECT#id2"), select).
		equal(el.find("SELECT.cl2"), select).
		equal(el.find("SELECT#id2.cl2"), select).
		equal(el.find("SELECT.cl2#id2"), select).

		equal(el.find("h2"), h2).
		equal(!!el.find(".cl3"), false).


	it ("supports boolean attributes").
		equal(getString(El("input:selected")), '<input selected="selected">').

	it ("has txt() method").
		equal(el.txt(), "").
		equal(el.txt("hello"), "hello").
		equal(el.txt(), "hello").


	it ("has class methods").
		equal(el.className, "").
		equal(el.hasClass("c1"), false).
		equal(el.hasClass("c2"), false).
		equal(el.hasClass("c3"), false).

		equal(el.addClass("c1"), el).
		equal(el.hasClass("c1"), true).
		equal(el.hasClass("c2"), false).
		equal(el.hasClass("c3"), false).

		equal(el.addClass("c2"), el).
		equal(el.hasClass("c1"), true).
		equal(el.hasClass("c2"), true).
		equal(el.hasClass("c3"), false).

		equal(el.rmClass("c3"), el).
		equal(el.hasClass("c1"), true).
		equal(el.hasClass("c2"), true).
		equal(el.hasClass("c3"), false).

		equal(el.rmClass("c2"), el).
		equal(el.hasClass("c1"), true).
		equal(el.hasClass("c2"), false).
		equal(el.hasClass("c3"), false).

		equal(el.rmClass("c1"), el).
		equal(el.hasClass("c1"), false).
		equal(el.hasClass("c2"), false).
		equal(el.hasClass("c3"), false).

		equal(el.className, "").

		equal(el.toggleClass("c1"), true).
		equal(el.hasClass("c1"), true).
		equal(el.toggleClass("c1", true), true).
		equal(el.hasClass("c1"), true).
		equal(el.toggleClass("c1"), false).
		equal(el.hasClass("c1"), false).
		equal(el.toggleClass("c1", false), false).
		equal(el.hasClass("c1"), false).

		equal(el.className, "").



describe( "Templates" ).
	it ("supports tpl").
		equal(getString(El.tpl("a\n b\n  i")), '<a><b><i></i></b></a>').
		equal(getString(El.tpl("a \n b\n  i")), '<a><b><i></i></b></a>').
		equal(getString(El.tpl("a\n b\n  i link")), '<a><b><i>link</i></b></a>').
		equal(getString(El.tpl("a\n b \n  i link")), '<a><b><i>link</i></b></a>').
		equal(getString(El.tpl("a\n b\n  i link>to")), '<a><b><i>link&gt;to</i></b></a>').
		anyOf(getString(El.tpl("a[href='#a>b']\n b.bold \n  i#ital link")),
			[ '<a href="#a>b"><b class=bold><i id=ital>link</i></b></a>'
			, '<a href="#a>b"><b class="bold"><i id="ital">link</i></b></a>'
			, '<a href="#a&gt;b"><b class="bold"><i id="ital">link</i></b></a>'
			, '<a href="#a%3Eb"><b class="bold"><i id="ital">link</i></b></a>'
			]).

	it ("supports block expansion").
		equal(getString(El.tpl("a>b>i")), '<a><b><i></i></b></a>').
		equal(getString(El.tpl("a > b>i")), '<a><b><i></i></b></a>').
		equal(getString(El.tpl("a>b>i link")), '<a><b><i>link</i></b></a>').
		equal(getString(El.tpl("a>b > i link")), '<a><b><i>link</i></b></a>').
		equal(getString(El.tpl("a>b>i link>to")), '<a><b><i>link&gt;to</i></b></a>').
		anyOf(getString(El.tpl("a[href='#a>b']>b.bold > i#ital link")),
			[ '<a href="#a>b"><b class=bold><i id=ital>link</i></b></a>'
			, '<a href="#a>b"><b class="bold"><i id="ital">link</i></b></a>'
			, '<a href="#a&gt;b"><b class="bold"><i id="ital">link</i></b></a>'
			, '<a href="#a%3Eb"><b class="bold"><i id="ital">link</i></b></a>'
			]).

	it ("supports templates").
		anyOf(getString(El.tpl("@template t1\n .temp1 t123\nt1")),
			[ '<div class=temp1>t123</div>'
			, '<div class="temp1">t123</div>'
			]).
		anyOf(getString(El.tpl("@template t2\n .temp2>b t123\nt2")),
			[ '<div class=temp2><b>t123</b></div>'
			, '<div class="temp2"><b>t123</b></div>'
			]).
		anyOf(getString(El.tpl("@template t3\n .temp3\n  b t123\nt3")),
			[ '<div class=temp3><b>t123</b></div>'
			, '<div class="temp3"><b>t123</b></div>'
			]).

	it ( "should render data to elements" ).
		equal(getString(t1 = El.tpl("a>b[data-bind=\"class:'red','i>1'\"]>i =txt:'hello {name}'")), "<a><b data-bind=\"class:'red','i>1'\"><i data-bind=\"txt:'hello {name}'\"></i></b></a>").
		anyOf(getString(t1.render({i:1,name:"world"})),
			[ "<a><b data-bind=\"class:'red','i>1'\"><i data-bind=\"txt:'hello {name}'\">hello world</i></b></a>"
			, "<a><b class=\"\" data-bind=\"class:'red','i>1'\"><i data-bind=\"txt:'hello {name}'\">hello world</i></b></a>"
			, "<a><b data-bind=\"class:'red','i>1'\" class=\"\"><i data-bind=\"txt:'hello {name}'\">hello world</i></b></a>"
			]).
		anyOf(getString(t1.render({i:2,name:"moon"})),
			[ "<a><b data-bind=\"class:'red','i>1'\" class=\"red\"><i data-bind=\"txt:'hello {name}'\">hello moon</i></b></a>"
			, "<a><b class=\"red\" data-bind=\"class:'red','i>1'\"><i data-bind=\"txt:'hello {name}'\">hello moon</i></b></a>"
			, "<a><b class=red data-bind=\"class:'red','i>1'\"><i data-bind=\"txt:'hello {name}'\">hello moon</i></b></a>"
			]).

	it ( "should show set DOM propperty when plugin not found" , {skip: "Browsers does not show attrs set by node.unknown_plugin = '123', should use node.set()"}).
		equal(getString(t1 = El.tpl("a =unknown_plugin:\'hello {name}\'")), '<a data-bind="unknown_plugin:\'hello {name}\'"></a>').
		equal(getString(t1.render({name:"world"})), '<a data-bind="unknown_plugin:\'hello {name}\'" unknown_plugin="hello world"></a>').
		equal(getString(t1.render({name:"moon"})), '<a data-bind="unknown_plugin:\'hello {name}\'" unknown_plugin="hello moon"></a>').

	/*
	it ("supports declaring a leaf node").
	run(function() {
		t1 = El.tpl([""
			, "@template leaf1"
			, "  a"
			, "    b[data-leaf]"
			, "div"
			, "  leaf1"
			, "    i 1"
			, "  leaf1"
			, "    i 2"
		].join("\n"))
	}).
	equal(getString(t1), '<div><a><b data-leaf="data-leaf"><i>1</i></b></a><a><b data-leaf="data-leaf"><i>2</i></b></a></div>').
	*/
	it ("supports IF binding").

done()


/** Tests for El
!function(){
	var test_el = new TestCase("El");



	, el.find("h2"), h2
	//, !!el.find("select:enabled"), false
	, !!el.find("select.cl3"), false
	, "El.find()");
	select.kill();

	el.append(h4, true);
	test_el.compare(el.innerHTML.toLowerCase().replace(/[\s\t\n\r]+/g,""), "<h4></h4><h2></h2>", "El.append");
	h4.kill();
	test_el.compare(el.innerHTML.toLowerCase(), "<h2></h2>", "El.kill");
	h1.after(h2, true);
	test_el.compare(el.innerHTML.toLowerCase().replace(/[\s\t\n\r]+/g,""), "<h1></h1><h2></h2>", "El.after");
	h3.after(h2);
	test_el.compare(el.innerHTML.toLowerCase().replace(/[\s\t\n\r]+/g,""), "<h1></h1><h2></h2><h3></h3>", "El.after");
	el.empty();
	test_el.compare(el.innerHTML.toLowerCase(), "", "El.empty");
	el.append([h3,h4])
	var str = el.innerHTML.toLowerCase().replace(/[\s\t\n\r]+/g,"");
	test_el.compare(
		str == "<h3></h3><h4></h4>" || str == "<div><h3></h3><h4></h4></div>", true, "El.append array");

	el.addClass("test1");
	test_el.compare(el.className, "test1", "El.addClass");

	el.addClass("test2");
	test_el.compare(el.className, "test1 test2");

	el.addClass("test3");
	test_el.compare(el.className, "test1 test2 test3");

	el.addClass("test4");
	test_el.compare(el.className, "test1 test2 test3 test4");

	el.rmClass("test2");
	test_el.compare(el.className, "test1 test3 test4", "El.rmClass");

	el.rmClass("test1");
	test_el.compare(el.className, "test3 test4");

	el.rmClass("test4");
	test_el.compare(el.className, "test3");

	el.rmClass("c4");
	test_el.compare(el.className, "test3");

	var s;

	s = el.toggleClass("test4");
	test_el.compare(el.className, "test3 test4", s, true, "El.toggleClass");

	s = el.toggleClass("test4", true);
	test_el.compare(el.className, "test3 test4", s, true);

	s = el.toggleClass("test4");
	test_el.compare(el.className, "test3", s, false);

	s = el.toggleClass("test4", false);
	test_el.compare(el.className, "test3", s, false);
	test_el.compare(el.hasClass("test3"), true, el.hasClass("test4"), false, "El.hasClass");

	el.css("left","1px");
	test_el.compare(el.css("left"), "1px", "El.css");

	el.css({"top":"2px","left":"3px"});
	test_el.compare(el.css("top"), "2px", el.css("left"), "3px", "El.css");


	test_el.done();
}()
//*/



}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"../":1,"browser-upgrade-lite":2,"functional-lite":3,"liquid-filters-lite":4,"testman":5}],7:[function(require,module,exports){
// shim for using process in browser

var process = module.exports = {};

process.nextTick = (function () {
    var canSetImmediate = typeof window !== 'undefined'
    && window.setImmediate;
    var canPost = typeof window !== 'undefined'
    && window.postMessage && window.addEventListener
    ;

    if (canSetImmediate) {
        return function (f) { return window.setImmediate(f) };
    }

    if (canPost) {
        var queue = [];
        window.addEventListener('message', function (ev) {
            var source = ev.source;
            if ((source === window || source === null) && ev.data === 'process-tick') {
                ev.stopPropagation();
                if (queue.length > 0) {
                    var fn = queue.shift();
                    fn();
                }
            }
        }, true);

        return function nextTick(fn) {
            queue.push(fn);
            window.postMessage('process-tick', '*');
        };
    }

    return function nextTick(fn) {
        setTimeout(fn, 0);
    };
})();

process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];

process.binding = function (name) {
    throw new Error('process.binding is not supported');
}

// TODO(shtylman)
process.cwd = function () { return '/' };
process.chdir = function (dir) {
    throw new Error('process.chdir is not supported');
};

},{}]},{},[6])