text: /*!
  	Typeahead search v0.1.5
  */
  (function(root){
  
  	function Builder(){
  		this.version = "0.1.5";
  		this.init = function(el,opt){ return new TA(el,opt); };
  		return this;
  	}
  	/**
  	 * @desc Create a new TypeAhead object
  	 * @param {DOM|string} el - the DOM element
  	 * @param {object} opt - configuration options
  	 */
  	function TA(el,opt){
  		if(!opt) opt = {};
  		if(typeof el==="string") el = document.querySelector(el);
  		if(!el){
  			console.warn('No valid element provided');
  			return this;
  		}
  		var _obj = this;
  		var evs = {};
  		var results,form;
  		var inline = (typeof opt.inline==="boolean" ? opt.inline : false);
  		this.el = el;
  
  		function search(s,e,t){
  
  			var n,i,tmp,str,html,datum,ev;
  			str = s.toUpperCase();
  
  			// Rank the results
  			tmp = [];
  			if(str){
  				for(i = 0 ; i < opt.items.length; i++){
  					datum = {'rank':0,'key':i,'value':opt.items[i]};
  					if(typeof opt.rank==="function") datum.rank = opt.rank(opt.items[i],s);
  					else{
  						if(opt.items[i].toUpperCase().indexOf(str) == 0) datum.rank += 3;
  						if(opt.items[i].toUpperCase().indexOf(str) > 0) datum.rank += 1;
  					}
  					tmp.push(datum);
  				}
  				tmp = sortBy(tmp,'rank');
  			}
  
  			// Add results to DOM
  			if(!results){
  				el.parentElement.style.position = "relative";
  				results = document.createElement('div');
  				results.classList.add('typeahead-results');
  				results.style.top = (el.offsetTop + el.offsetHeight)+'px';
  				results.style.left = el.offsetLeft+'px';
  				results.style.maxWidth = (el.parentElement.offsetWidth - el.offsetLeft - parseInt(window.getComputedStyle(el.parentElement, null).getPropertyValue('padding-right')))+'px';
  				results.style.position = "absolute";
  				form.style.position = "relative";
  				el.insertAdjacentElement('afterend',results);
  			}
  
  			html = "";
  			if(tmp.length > 0){
  				n = Math.min(tmp.length,(typeof opt.max==="number" ? opt.max : 10));
  				html = "<ol>";
  				for(i = 0; i < n; i++){
  					if(tmp[i].rank > 0) html += '<li data-id="'+tmp[i].key+'" '+(i==0 ? ' class="selected"':'')+'><a tabindex="0" href="#" class="name">'+(typeof opt.render==="function" ? opt.render(opt.items[tmp[i].key]) : opt.items[tmp[i].key])+"</a></li>";
  				}
  				html += "</ol>";
  			}
  			results.innerHTML = html;
  			if(inline){
  				el.style.marginBottom = results.offsetHeight+'px';
  			}
  
  			// Add click events
  			var li = getLi();
  			for(i = 0 ; i < li.length ; i++){
  				li[i].addEventListener('click',function(ev){
  					ev.preventDefault();
  					ev.stopPropagation();
  					selectLI(this.getAttribute('data-id'));
  				});
  			}
  			
  			if(evs[t]){
  				e._typeahead = _obj;
  				// Process each of the events attached to this event
  				for(i = 0; i < evs[t].length; i++){
  					ev = evs[t][i];
  					e.data = ev.data||{};
  					if(typeof ev.fn==="function") ev.fn.call(e.data['this']||_obj,e);
  				}
  			}
  
  			return this;
  		}
  
  		function getLi(){ return (results ? results.querySelectorAll('li') : []); }
  		
  		function selectLI(i){
  			if(i){
  				_obj.input = el;
  				if(typeof opt.process==="function") opt.process.call(_obj,opt.items[i]);
  				else console.log(opt.items[i]);
  			}
  			if(results) results.innerHTML = "";
  			if(inline) el.style.marginBottom = "0px";
  			return;
  		}
  
  		function submit(){
  			var li = getLi();
  			for(var i = 0; i < li.length; i++){
  				if(li[i].classList.contains('selected')) return selectLI(li[i].getAttribute('data-id'));
  			}
  			return;
  		}
  
  		function highlight(keyCode){
  			var li = getLi();
  			var s = -1;
  			var sel;
  			for(var i = 0; i < li.length; i++){
  				if(li[i].classList.contains('selected')) s = i;
  			}
  			sel = s;
  			if(keyCode==40) s++;
  			else s--;
  			if(s < 0) s = li.length-1;
  			if(s >= li.length) s = 0;
  			if(sel >= 0) li[sel].classList.remove('selected');
  			li[s].classList.add('selected');
  		}
  
  		this.on = function(event,data,fn){
  			if(!el){
  				console.warn('Unable to attach event '+event);
  				return this;
  			}
  			if(event=="change"){
  				if(!evs[event]){
  					evs[event] = [];
  					var _obj = this;
  					el.addEventListener('keyup',function(e){
  						e.preventDefault();
  						e.stopPropagation();
  						if(e.keyCode==40 || e.keyCode==38){
  							highlight(e.keyCode);
  						}else if(e.keyCode==13){
  							submit();
  						}else{
  							// Match here
  							search(this.value,e,event);
  							if(typeof opt.endsearch==="function") opt.endsearch(this.value);
  						}
  					});
  					el.addEventListener('blur',function(e){
  						if(typeof opt.blur==="function") opt.blur();
  					});
  				}
  				evs[event].push({'fn':fn,'data':data});
  			}else if(event=="blur"){
  				console.log('blur');
  			}else console.warn('No event of type '+event);
  			return this;
  		};
  		this.off = function(e,fn){
  			// Remove any existing event from our list
  			if(evs[e]){
  				for(var i = 0; i < evs[e].length; i++){
  					if(evs[e][i].fn==fn) evs[e].splice(i,1);
  				}
  			}
  		};
  		if(el.form){
  			form = el.form;
  			form.addEventListener('submit',function(e){
  				e.preventDefault();
  				e.stopPropagation();
  				submit();
  			},false);
  		}
  		if(el){
  			el.setAttribute('autocomplete','off');
  		}
  		this.addItems = function(d){
  			if(!opt.items) opt.items = [];
  			opt.items = opt.items.concat(d);
  		};
  		//this.on('change',{'test':'blah'},function(e){ console.log('change end'); });
  
  		return this;
  	}
  
  	root.TypeAhead = new Builder();
  
  	// Extend objects
  	extendObject = (typeof Object.extend === 'undefined') ? function(destination, source){ for(var property in source){ if (source.hasOwnProperty(property)) destination[property] = source[property]; } return destination; } : Object.extend;
  
  	// Sort the data
  	function sortBy(arr,i){
  		return arr.sort(function (a, b) {
  			return a[i] < b[i] ? 1 : -1;
  		});
  	}
  	/* End Typeahead */
  
  })(window || this);