diff --git a/docs/symbols/src/kis-js_src_modules_store.js.html b/docs/symbols/src/kis-js_src_modules_store.js.html index da04e19..19c4e35 100644 --- a/docs/symbols/src/kis-js_src_modules_store.js.html +++ b/docs/symbols/src/kis-js_src_modules_store.js.html @@ -5,11 +5,11 @@ .STRN {color: #393;} .REGX {color: #339;} .line {border-right: 1px dotted #666; color: #666; font-style: normal;} -
  1 /**
-  2  * Store 
-  3  * 
-  4  * Wrapper for local / sessionstorage
-  5  */
+	
  1 /**
+  2  * Store 
+  3  * 
+  4  * Wrapper for local / sessionstorage
+  5  */
   6 (function (){
   7 	"use strict";
   8 	
diff --git a/docs/symbols/src/kis-js_src_modules_util.js.html b/docs/symbols/src/kis-js_src_modules_util.js.html
index ee6389c..b7b6975 100644
--- a/docs/symbols/src/kis-js_src_modules_util.js.html
+++ b/docs/symbols/src/kis-js_src_modules_util.js.html
@@ -33,8 +33,8 @@
  26 				bFloat = parseFloat(b),
  27 				aNumeric = aFloat + '' === a,
  28 				bNumeric = bFloat + '' === b;
- 29             
- 30 			if (aNumeric && bNumeric) 
+ 29 
+ 30 			if (aNumeric && bNumeric) 
  31 			{
  32 				return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0;
  33 			} 
diff --git a/kis-all.js b/kis-all.js
index 2e7db7b..7a42901 100755
--- a/kis-all.js
+++ b/kis-all.js
@@ -418,17 +418,17 @@
 	 * event.preventDefault/e.stopPropagation polyfill
 	 * @private
 	 */
-	 if(typeof Event.preventDefault === "undefined" && typeof window.event !== "undefined")
-	 {
-	 	Event.prototype.preventDefault = function() 
-	 	{
-	 		window.event.stop();
-	 	},
-	 	Event.prototype.stopPropagation = function()
-	 	{
-	 		window.event.returnValue = false;
-	 	}
-	 }
+	if(typeof Event.preventDefault === "undefined" && typeof window.event !== "undefined")
+	{
+		Event.prototype.preventDefault = function() 
+		{
+			window.event.stop();
+		},
+		Event.prototype.stopPropagation = function()
+		{
+			window.event.returnValue = false;
+		}
+	}
 	
 }());
 
@@ -1074,7 +1074,7 @@
 				bFloat = parseFloat(b),
 				aNumeric = aFloat + '' === a,
 				bNumeric = bFloat + '' === b;
-            
+
 			if (aNumeric && bNumeric) 
 			{
 				return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0;
diff --git a/kis-lite-dom-min.js b/kis-lite-dom-min.js
new file mode 100644
index 0000000..64c80dc
--- /dev/null
+++ b/kis-lite-dom-min.js
@@ -0,0 +1,1178 @@
+/**
+	Kis JS		Keep It Simple JS Library
+	Copyright	Timothy J. Warren
+	License		Public Domain
+	Version		0.5.0-pre
+ */
+(function (){
+
+	"use strict";
+
+	// Most functions rely on a string selector
+	// which returns html elements. This requires
+	// document.querySelectorAll or a custom
+	// selector engine. I choose to just use the
+	// browser feature, since it is present in
+	// IE 8+, and all other major browsers
+	if (typeof document.querySelector === "undefined")
+	{
+		return;
+	}
+
+	var $_, $, dcopy, sel;
+	
+
+	/**
+	 * $_
+	 *
+	 * Constructor function
+	 *
+	 * @constuctor
+	 * @namespace
+	 * @param string selector
+	 * @return object
+	 */
+	$_ = function(s)
+	{
+		//Have documentElement be default selector, just in case
+		if(typeof s === "undefined")
+		{
+			//Defines a "global" selector for that instance
+			sel = (typeof $_.el !== "undefined") 
+				? $_.el
+				: document.documentElement;
+		}
+		else
+		{
+			sel = (typeof s !== "object") ? $(s) : s;
+		}
+		
+		// Add the selector to the prototype
+		$_.prototype.el = sel;
+
+		// Make a copy before adding properties
+		var self = dcopy($_);
+
+		// Give sel to each extension.
+		for(var i in self) 
+		{
+			if(typeof self[i] === "object")
+			{
+				self[i].el = sel;
+			}	
+		}
+
+		self.el = sel;
+	
+		return self;
+	};
+	
+	/**
+	 * Simple DOM selector function
+	 *
+	 * @memberOf $_
+	 * @param string selector
+	 * @param object context
+	 * @return object
+	 * @type object
+	 */
+	$ = function (a, context)
+	{
+		var x, c;
+		
+		if (typeof a != "string" || typeof a === "undefined"){ return a;}
+		
+		//Check for a context of a specific element, otherwise, just run on the document
+		c  = (context != null && context.nodeType === 1) 
+			? context 
+			: document;
+		
+		//Pick the quickest method for each kind of selector
+		if (a.match(/^#([\w\-]+$)/))
+		{
+			return document.getElementById(a.split('#')[1]);
+		}
+		else
+		{
+			x = c.querySelectorAll(a);
+		}
+		
+		//Return the single object if applicable
+		return (x.length === 1) ? x[0] : x;
+	};
+	
+	/**
+	 * Deep copy/prototypical constructor function
+	 *
+	 * @param object obj
+	 * @private
+	 * @return object
+	 * @type object
+	 */
+	dcopy = function(obj)
+	{
+		var type, F;
+		
+		if(typeof obj === "undefined")
+		{
+			return;
+		}
+		
+		if(typeof Object.create !== "undefined")
+		{
+			return Object.create(obj);
+		}
+		
+		type = typeof obj;
+		
+		if(type !== "object" && type !== "function")
+		{
+			return;
+		}
+		
+		/**
+		 * @private
+		 */
+		F = function(){};
+		
+		F.prototype = obj;
+		
+		return new F();
+		
+	};
+	
+	/**
+	 * Adds the property `obj` to the $_ object, calling it `name`
+	 * 
+	 * @param string name
+	 * @param object obj
+	 */
+	$_.ext = function(name, obj)
+	{
+		obj.el = sel;
+		$_[name] = obj;
+	};
+	
+	/**
+	 * Iterates over a $_ object, applying a callback to each item
+	 *
+	 * @name $_.each
+	 * @function
+	 * @param function callback
+	 */
+	$_.ext('each', function (callback)
+	{
+		if(typeof sel.length !== "undefined" && sel !== window)
+		{
+			var len = sel.length;
+
+			if (len === 0)
+			{
+				return;
+			}
+
+			var selx;
+			for (var x = 0; x < len; x++)
+			{
+				selx = (sel.item(x)) ? sel.item(x) : sel[x];
+				callback.call(selx, selx);
+			}
+		}
+		else
+		{
+			callback.call(sel, sel);
+		}
+	});
+	
+	/**
+	 * Retrieves the type of the passed variable
+	 *
+	 * @param mixed obj
+	 * @return string
+	 * @type string
+	 */
+	$_.type = function(obj) 
+	{	
+		if((function() {return obj && (obj !== this)}).call(obj))
+		{
+			//fallback on 'typeof' for truthy primitive values
+			return (typeof obj).toLowerCase();
+		}
+		
+		//Strip x from [object x] and return 
+		return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
+	};
+
+	//Set global variables
+	$_ = window.$_ = window.$_ || $_;
+	$_.$ = $;
+	
+}());
+
+// --------------------------------------------------------------------------
+
+/**
+ * A module of various browser polyfills
+ * @file polyfill.js
+ */
+(function(){
+
+	"use strict";
+ 
+	// Console.log polyfill for IE 8 stupidity
+	if(typeof window.console === "undefined")
+	{
+		window.console = {
+			log:function(){}
+		};
+	}
+	
+	// --------------------------------------------------------------------------
+	
+	/**
+	 * String trim function polyfill
+	 */
+	if(typeof String.prototype.trim === "undefined")
+	{
+		/**
+		 * @private
+		 */
+		String.prototype.trim = function()
+		{
+			return this.replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, "");
+		};
+	}
+	
+	// --------------------------------------------------------------------------
+	
+	//This is used so IE 8 can use the classList api
+	/*
+	 * classList.js: Cross-browser full element.classList implementation.
+	 * 2011-06-15
+	 *
+	 * By Eli Grey, http://eligrey.com
+	 * Public Domain.
+	 * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+	 */
+	
+	if (typeof document !== "undefined" && !("classList" in document.createElement("a")))
+	{
+		(function (view){
+		
+			var classListProp = "classList",
+				protoProp = "prototype",
+				elemCtrProto = (view.HTMLElement || view.Element)[protoProp],
+				objCtr = Object,
+				strTrim = String[protoProp].trim ||
+				function ()
+				{
+					return this.replace(/^\s+|\s+$/g, "");
+				},
+				arrIndexOf = Array[protoProp].indexOf ||
+				function (item)
+				{
+					var
+					i = 0,
+						len = this.length;
+					for (; i < len; i++)
+					{
+						if (i in this && this[i] === item)
+						{
+							return i;
+						}
+					}
+					return -1;
+				}
+				// Vendors: please allow content code to instantiate DOMExceptions
+				,
+				/**
+				 * @private
+				 */
+				DOMEx = function (type, message)
+				{
+					this.name = type;
+					this.code = DOMException[type];
+					this.message = message;
+				},
+				/**
+				 * @private
+				 */
+				checkTokenAndGetIndex = function (classList, token)
+				{
+					if (token === "")
+					{
+						throw new DOMEx("SYNTAX_ERR", "An invalid or illegal string was specified");
+					}
+					if (/\s/.test(token))
+					{
+						throw new DOMEx("INVALID_CHARACTER_ERR", "String contains an invalid character");
+					}
+					return arrIndexOf.call(classList, token);
+				},
+				/**
+				 * @private
+				 */
+				ClassList = function (elem)
+				{
+					var
+					trimmedClasses = strTrim.call(elem.className),
+						classes = trimmedClasses ? trimmedClasses.split(/\s+/) : [],
+						i = 0,
+						len = classes.length;
+					for (; i < len; i++)
+					{
+						this.push(classes[i]);
+					}
+					this._updateClassName = function ()
+					{
+						elem.className = this.toString();
+					};
+				},
+				classListProto = ClassList[protoProp] = [],
+				/**
+				 * @private
+				 */
+				classListGetter = function ()
+				{
+					return new ClassList(this);
+				};
+			// Most DOMException implementations don't allow calling DOMException's toString()
+			// on non-DOMExceptions. Error's toString() is sufficient here.
+			DOMEx[protoProp] = Error[protoProp];
+			classListProto.item = function (i)
+			{
+				return this[i] || null;
+			};
+			classListProto.contains = function (token)
+			{
+				token += "";
+				return checkTokenAndGetIndex(this, token) !== -1;
+			};
+			classListProto.add = function (token)
+			{
+				token += "";
+				if (checkTokenAndGetIndex(this, token) === -1)
+				{
+					this.push(token);
+					this._updateClassName();
+				}
+			};
+			classListProto.remove = function (token)
+			{
+				token += "";
+				var index = checkTokenAndGetIndex(this, token);
+				if (index !== -1)
+				{
+					this.splice(index, 1);
+					this._updateClassName();
+				}
+			};
+			classListProto.toggle = function (token)
+			{
+				token += "";
+				if (checkTokenAndGetIndex(this, token) === -1)
+				{
+					this.add(token);
+				}
+				else
+				{
+					this.remove(token);
+				}
+			};
+			classListProto.toString = function ()
+			{
+				return this.join(" ");
+			};
+	
+			if (objCtr.defineProperty)
+			{
+				var classListPropDesc = {
+					get: classListGetter,
+					enumerable: true,
+					configurable: true
+				};
+				try
+				{
+					objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+				}
+				catch (ex)
+				{ // IE 8 doesn't support enumerable:true
+					if (ex.number === -0x7FF5EC54)
+					{
+						classListPropDesc.enumerable = false;
+						objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+					}
+				}
+			}
+			else if (objCtr[protoProp].__defineGetter__)
+			{
+				elemCtrProto.__defineGetter__(classListProp, classListGetter);
+			}
+	
+		}(self));
+	}
+	
+	// --------------------------------------------------------------------------
+	
+	/**
+	 * event.preventDefault/e.stopPropagation polyfill
+	 * @private
+	 */
+	if(typeof Event.preventDefault === "undefined" && typeof window.event !== "undefined")
+	{
+		Event.prototype.preventDefault = function() 
+		{
+			window.event.stop();
+		},
+		Event.prototype.stopPropagation = function()
+		{
+			window.event.returnValue = false;
+		}
+	}
+	
+}());
+
+// --------------------------------------------------------------------------
+
+/**
+ * Ajax
+ *
+ * Module for making ajax requests
+ */
+(function (){
+
+	"use strict";
+	
+	// Don't bother even defining the object if the XMLHttpRequest isn't available
+	if(typeof window.XMLHttpRequest === "undefined")
+	{
+		return;
+	}
+
+	var ajax = {
+		_do: function (url, data, callback, isPost)
+		{
+			var type, 
+				request = new XMLHttpRequest();
+		
+			if (typeof callback === "undefined")
+			{
+				/**
+				 * @private
+				 */
+				callback = function (){};
+			}
+
+			type = (isPost) ? "POST" : "GET";
+
+			url += (type === "GET") ? "?"+this._serialize(data) : '';
+			
+			request.open(type, url);
+
+			request.onreadystatechange = function ()
+			{
+				if (request.readyState === 4)
+				{
+					callback(request.responseText);
+				}
+			};
+
+			if (type === "POST")
+			{
+				request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+				request.send(this._serialize(data));
+			}
+			else
+			{
+				request.send(null);
+			}
+		},
+		_serialize: function (data)
+		{
+			var name,
+				value,
+				pairs = [];
+
+			for (name in data)
+			{
+				if (!data.hasOwnProperty(name))
+				{
+					continue;
+				}
+				if (typeof data[name] === "function")
+				{
+					continue;
+				}
+
+				value = data[name].toString();
+
+				name = encodeURIComponent(name);
+				value = encodeURIComponent(value);
+
+				pairs.push(name + "=" + value);
+			}
+
+			return pairs.join("&");
+		}
+	};
+
+	/**
+	 * Sends a GET type ajax request
+	 * 
+	 * @name get
+	 * @function
+	 * @memberOf $_
+	 * @param string url
+	 * @param object data
+	 * @param function callback
+	 */
+	$_.ext('get', function (url, data, callback){
+		ajax._do(url, data, callback, false);
+	});
+	
+	/**
+	 * Sends a POST type ajax request
+	 * 
+	 * @name post
+	 * @function
+	 * @memberOf $_
+	 * @param string url
+	 * @param object data
+	 * @param function callback
+	 */
+	$_.ext('post', function (url, data, callback){
+		ajax._do(url, data, callback, true);
+	});
+}());
+
+// --------------------------------------------------------------------------
+
+/**
+ * Event
+ *
+ * Event api wrapper
+ */
+(function (){
+
+	"use strict";
+
+	// Property name for expandos on DOM objects
+	var kis_expando = "KIS_0_5_0";
+
+	var _attach, _remove, _add_remove, e, _attach_delegate;
+
+	// Define the proper _attach and _remove functions
+	// based on browser support
+	if(typeof document.addEventListener !== "undefined")
+	{
+		/**
+		 * @private
+		 */
+		_attach = function (sel, event, callback)
+		{
+			if(typeof sel.addEventListener !== "undefined")
+			{
+				// Duplicated events are dropped, per the specification
+				sel.addEventListener(event, callback, false);
+			}
+		};
+		/**
+		 * @private
+		 */
+		_remove = function (sel, event, callback)
+		{
+			if(typeof sel.removeEventListener !== "undefined")
+			{
+				sel.removeEventListener(event, callback, false);
+			}
+		};
+	}
+	// typeof function doesn't work in IE where attachEvent is available: brute force it
+	else if(typeof document.attachEvent !== "undefined") 
+	{
+		/**
+		 * @private
+		 */
+		_attach = function (sel, event, callback)
+		{
+			function _listener () {
+				// Internet Explorer fails to correctly set the 'this' object
+				// for event listeners, so we need to set it ourselves.
+				callback.apply(arguments[0]);
+			}
+			
+			if (typeof sel.attachEvent !== "undefined")
+			{
+				_remove(event, callback); // Make sure we don't have duplicate listeners
+				
+				sel.attachEvent("on" + event, _listener);
+				// Store our _listener so we can remove it later
+				var expando = sel[kis_expando] = sel[kis_expando] || {};
+				expando.listeners = expando.listeners || {};
+				expando.listeners[event] = expando.listeners[event] || [];
+				expando.listeners[event].push({
+					callback: callback,
+					_listener: _listener
+				});
+			}
+			else
+			{
+				console.log("Failed to _attach event:"+event+" on "+sel);
+			}
+		};
+		/**
+		 * @private
+		 */
+		_remove = function (sel, event, callback)
+		{
+			if(typeof sel.detachEvent !== "undefined")
+			{
+				var expando = sel[kis_expando];
+				if (expando && expando.listeners
+						&& expando.listeners[event])
+				{
+					var listeners = expando.listeners[event];
+					var len = listeners.length;
+					for (var i=0; i 1 && typeof value === "undefined")
+			{
+				console.log(sel);
+				console.log("Must be a singular element");
+				return;
+			}
+			else if (sel.length > 1 && typeof value !== "undefined") //You can set a bunch, though
+			{
+				$_.each(function (e){
+					return _attr(e, name, value);
+				});
+			}
+			else //Normal behavior
+			{
+				return _attr(sel, name, value);
+			}
+		},
+		/**
+		 * Sets or retrieves the text content of the element
+		 * specified by the current selector. If a value is 
+		 * passed, it will set that value on the current element,
+		 * otherwise it will return the value of the current element
+		 *
+		 * @name text
+		 * @memberOf $_.dom
+		 * @function
+		 * @param [string] value
+		 * @return string
+		 * @type string
+		 */
+		text: function (value)
+		{
+			var oldValue, set, type, sel;
+		
+			sel = this.el;
+			
+			set = (typeof value !== "undefined") ? true : false;
+			
+			type = (typeof sel.innerText !== "undefined")
+				? "innerText"
+				: (typeof sel.textContent !== "undefined")
+					? "textContent"
+					: "innerHTML";
+
+			oldValue = sel[type];
+			
+			if(set)
+			{
+				sel[type] = value;
+				return value;
+			}
+			else
+			{
+				return oldValue;
+			}
+		},
+		/**
+		 * Sets or retrieves a css property of the element
+		 * specified by the current selector. If a value is 
+		 * passed, it will set that value on the current element,
+		 * otherwise it will return the value of the css property
+		 * on the current element
+		 *
+		 * @name css
+		 * @memberOf $_.dom
+		 * @function
+		 * @param string property
+		 * @param [string] value
+		 * @return string
+		 * @type string
+		 */
+		css: function (prop, val)
+		{
+			//Return the current value if a value is not set
+			if(typeof val === "undefined")
+			{
+				return _css(this.el, prop);
+			}
+		
+			$_.each(function (e){
+				_css(e, prop, val);
+			});
+		},
+		/**
+		 * Adds to the innerHTML of the current element, after the last child.
+		 * 
+		 * @example $_("ul").dom.append("<li></li>") adds an li element to the end of the selected ul element
+		 * @name append
+		 * @memberOf $_.dom
+		 * @function
+		 * @param string htm
+		 */
+		append: function(htm)
+		{
+			if(typeof document.insertAdjacentHTML !== "undefined")
+			{
+				this.el.insertAdjacentHTML('beforeend', htm);
+			}
+			else
+			{
+				this.el.innerHTML += htm;
+			}
+		},
+		/**
+		 * Adds to the innerHTML of the selected element, before the current children
+		 * 
+		 * @name prepend
+		 * @memberOf $_.dom
+		 * @function
+		 * @param string htm
+		 */
+		 prepend: function(htm)
+		 {
+		 	if(typeof document.insertAdjacentHTML !== "undefined")
+		 	{
+		 		this.el.insertAdjacentHTML('afterbegin', htm);
+		 	}
+		 	else
+		 	{
+		 		this.el.innerHTML = htm + this.el.innerHTML;
+		 	}
+		 },
+		/**
+		 * Sets or gets the innerHTML propery of the element(s) passed
+		 *
+		 * @name html
+		 * @memberOf $_.dom
+		 * @function
+		 * @param [string] htm
+		 * @return string
+		 * @type string
+		 */
+		html: function(htm)
+		{
+			
+			if(typeof htm !== "undefined")
+			{
+				this.el.innerHTML = htm;
+			}
+			
+			//If the parameter is undefined, just return the current value
+			return this.el.innerHTML;
+		}
+	};
+
+	$_.ext('dom', d);
+	
+}());
+
diff --git a/kis-lite-dom.js b/kis-lite-dom.js
new file mode 100644
index 0000000..64c80dc
--- /dev/null
+++ b/kis-lite-dom.js
@@ -0,0 +1,1178 @@
+/**
+	Kis JS		Keep It Simple JS Library
+	Copyright	Timothy J. Warren
+	License		Public Domain
+	Version		0.5.0-pre
+ */
+(function (){
+
+	"use strict";
+
+	// Most functions rely on a string selector
+	// which returns html elements. This requires
+	// document.querySelectorAll or a custom
+	// selector engine. I choose to just use the
+	// browser feature, since it is present in
+	// IE 8+, and all other major browsers
+	if (typeof document.querySelector === "undefined")
+	{
+		return;
+	}
+
+	var $_, $, dcopy, sel;
+	
+
+	/**
+	 * $_
+	 *
+	 * Constructor function
+	 *
+	 * @constuctor
+	 * @namespace
+	 * @param string selector
+	 * @return object
+	 */
+	$_ = function(s)
+	{
+		//Have documentElement be default selector, just in case
+		if(typeof s === "undefined")
+		{
+			//Defines a "global" selector for that instance
+			sel = (typeof $_.el !== "undefined") 
+				? $_.el
+				: document.documentElement;
+		}
+		else
+		{
+			sel = (typeof s !== "object") ? $(s) : s;
+		}
+		
+		// Add the selector to the prototype
+		$_.prototype.el = sel;
+
+		// Make a copy before adding properties
+		var self = dcopy($_);
+
+		// Give sel to each extension.
+		for(var i in self) 
+		{
+			if(typeof self[i] === "object")
+			{
+				self[i].el = sel;
+			}	
+		}
+
+		self.el = sel;
+	
+		return self;
+	};
+	
+	/**
+	 * Simple DOM selector function
+	 *
+	 * @memberOf $_
+	 * @param string selector
+	 * @param object context
+	 * @return object
+	 * @type object
+	 */
+	$ = function (a, context)
+	{
+		var x, c;
+		
+		if (typeof a != "string" || typeof a === "undefined"){ return a;}
+		
+		//Check for a context of a specific element, otherwise, just run on the document
+		c  = (context != null && context.nodeType === 1) 
+			? context 
+			: document;
+		
+		//Pick the quickest method for each kind of selector
+		if (a.match(/^#([\w\-]+$)/))
+		{
+			return document.getElementById(a.split('#')[1]);
+		}
+		else
+		{
+			x = c.querySelectorAll(a);
+		}
+		
+		//Return the single object if applicable
+		return (x.length === 1) ? x[0] : x;
+	};
+	
+	/**
+	 * Deep copy/prototypical constructor function
+	 *
+	 * @param object obj
+	 * @private
+	 * @return object
+	 * @type object
+	 */
+	dcopy = function(obj)
+	{
+		var type, F;
+		
+		if(typeof obj === "undefined")
+		{
+			return;
+		}
+		
+		if(typeof Object.create !== "undefined")
+		{
+			return Object.create(obj);
+		}
+		
+		type = typeof obj;
+		
+		if(type !== "object" && type !== "function")
+		{
+			return;
+		}
+		
+		/**
+		 * @private
+		 */
+		F = function(){};
+		
+		F.prototype = obj;
+		
+		return new F();
+		
+	};
+	
+	/**
+	 * Adds the property `obj` to the $_ object, calling it `name`
+	 * 
+	 * @param string name
+	 * @param object obj
+	 */
+	$_.ext = function(name, obj)
+	{
+		obj.el = sel;
+		$_[name] = obj;
+	};
+	
+	/**
+	 * Iterates over a $_ object, applying a callback to each item
+	 *
+	 * @name $_.each
+	 * @function
+	 * @param function callback
+	 */
+	$_.ext('each', function (callback)
+	{
+		if(typeof sel.length !== "undefined" && sel !== window)
+		{
+			var len = sel.length;
+
+			if (len === 0)
+			{
+				return;
+			}
+
+			var selx;
+			for (var x = 0; x < len; x++)
+			{
+				selx = (sel.item(x)) ? sel.item(x) : sel[x];
+				callback.call(selx, selx);
+			}
+		}
+		else
+		{
+			callback.call(sel, sel);
+		}
+	});
+	
+	/**
+	 * Retrieves the type of the passed variable
+	 *
+	 * @param mixed obj
+	 * @return string
+	 * @type string
+	 */
+	$_.type = function(obj) 
+	{	
+		if((function() {return obj && (obj !== this)}).call(obj))
+		{
+			//fallback on 'typeof' for truthy primitive values
+			return (typeof obj).toLowerCase();
+		}
+		
+		//Strip x from [object x] and return 
+		return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
+	};
+
+	//Set global variables
+	$_ = window.$_ = window.$_ || $_;
+	$_.$ = $;
+	
+}());
+
+// --------------------------------------------------------------------------
+
+/**
+ * A module of various browser polyfills
+ * @file polyfill.js
+ */
+(function(){
+
+	"use strict";
+ 
+	// Console.log polyfill for IE 8 stupidity
+	if(typeof window.console === "undefined")
+	{
+		window.console = {
+			log:function(){}
+		};
+	}
+	
+	// --------------------------------------------------------------------------
+	
+	/**
+	 * String trim function polyfill
+	 */
+	if(typeof String.prototype.trim === "undefined")
+	{
+		/**
+		 * @private
+		 */
+		String.prototype.trim = function()
+		{
+			return this.replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, "");
+		};
+	}
+	
+	// --------------------------------------------------------------------------
+	
+	//This is used so IE 8 can use the classList api
+	/*
+	 * classList.js: Cross-browser full element.classList implementation.
+	 * 2011-06-15
+	 *
+	 * By Eli Grey, http://eligrey.com
+	 * Public Domain.
+	 * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+	 */
+	
+	if (typeof document !== "undefined" && !("classList" in document.createElement("a")))
+	{
+		(function (view){
+		
+			var classListProp = "classList",
+				protoProp = "prototype",
+				elemCtrProto = (view.HTMLElement || view.Element)[protoProp],
+				objCtr = Object,
+				strTrim = String[protoProp].trim ||
+				function ()
+				{
+					return this.replace(/^\s+|\s+$/g, "");
+				},
+				arrIndexOf = Array[protoProp].indexOf ||
+				function (item)
+				{
+					var
+					i = 0,
+						len = this.length;
+					for (; i < len; i++)
+					{
+						if (i in this && this[i] === item)
+						{
+							return i;
+						}
+					}
+					return -1;
+				}
+				// Vendors: please allow content code to instantiate DOMExceptions
+				,
+				/**
+				 * @private
+				 */
+				DOMEx = function (type, message)
+				{
+					this.name = type;
+					this.code = DOMException[type];
+					this.message = message;
+				},
+				/**
+				 * @private
+				 */
+				checkTokenAndGetIndex = function (classList, token)
+				{
+					if (token === "")
+					{
+						throw new DOMEx("SYNTAX_ERR", "An invalid or illegal string was specified");
+					}
+					if (/\s/.test(token))
+					{
+						throw new DOMEx("INVALID_CHARACTER_ERR", "String contains an invalid character");
+					}
+					return arrIndexOf.call(classList, token);
+				},
+				/**
+				 * @private
+				 */
+				ClassList = function (elem)
+				{
+					var
+					trimmedClasses = strTrim.call(elem.className),
+						classes = trimmedClasses ? trimmedClasses.split(/\s+/) : [],
+						i = 0,
+						len = classes.length;
+					for (; i < len; i++)
+					{
+						this.push(classes[i]);
+					}
+					this._updateClassName = function ()
+					{
+						elem.className = this.toString();
+					};
+				},
+				classListProto = ClassList[protoProp] = [],
+				/**
+				 * @private
+				 */
+				classListGetter = function ()
+				{
+					return new ClassList(this);
+				};
+			// Most DOMException implementations don't allow calling DOMException's toString()
+			// on non-DOMExceptions. Error's toString() is sufficient here.
+			DOMEx[protoProp] = Error[protoProp];
+			classListProto.item = function (i)
+			{
+				return this[i] || null;
+			};
+			classListProto.contains = function (token)
+			{
+				token += "";
+				return checkTokenAndGetIndex(this, token) !== -1;
+			};
+			classListProto.add = function (token)
+			{
+				token += "";
+				if (checkTokenAndGetIndex(this, token) === -1)
+				{
+					this.push(token);
+					this._updateClassName();
+				}
+			};
+			classListProto.remove = function (token)
+			{
+				token += "";
+				var index = checkTokenAndGetIndex(this, token);
+				if (index !== -1)
+				{
+					this.splice(index, 1);
+					this._updateClassName();
+				}
+			};
+			classListProto.toggle = function (token)
+			{
+				token += "";
+				if (checkTokenAndGetIndex(this, token) === -1)
+				{
+					this.add(token);
+				}
+				else
+				{
+					this.remove(token);
+				}
+			};
+			classListProto.toString = function ()
+			{
+				return this.join(" ");
+			};
+	
+			if (objCtr.defineProperty)
+			{
+				var classListPropDesc = {
+					get: classListGetter,
+					enumerable: true,
+					configurable: true
+				};
+				try
+				{
+					objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+				}
+				catch (ex)
+				{ // IE 8 doesn't support enumerable:true
+					if (ex.number === -0x7FF5EC54)
+					{
+						classListPropDesc.enumerable = false;
+						objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+					}
+				}
+			}
+			else if (objCtr[protoProp].__defineGetter__)
+			{
+				elemCtrProto.__defineGetter__(classListProp, classListGetter);
+			}
+	
+		}(self));
+	}
+	
+	// --------------------------------------------------------------------------
+	
+	/**
+	 * event.preventDefault/e.stopPropagation polyfill
+	 * @private
+	 */
+	if(typeof Event.preventDefault === "undefined" && typeof window.event !== "undefined")
+	{
+		Event.prototype.preventDefault = function() 
+		{
+			window.event.stop();
+		},
+		Event.prototype.stopPropagation = function()
+		{
+			window.event.returnValue = false;
+		}
+	}
+	
+}());
+
+// --------------------------------------------------------------------------
+
+/**
+ * Ajax
+ *
+ * Module for making ajax requests
+ */
+(function (){
+
+	"use strict";
+	
+	// Don't bother even defining the object if the XMLHttpRequest isn't available
+	if(typeof window.XMLHttpRequest === "undefined")
+	{
+		return;
+	}
+
+	var ajax = {
+		_do: function (url, data, callback, isPost)
+		{
+			var type, 
+				request = new XMLHttpRequest();
+		
+			if (typeof callback === "undefined")
+			{
+				/**
+				 * @private
+				 */
+				callback = function (){};
+			}
+
+			type = (isPost) ? "POST" : "GET";
+
+			url += (type === "GET") ? "?"+this._serialize(data) : '';
+			
+			request.open(type, url);
+
+			request.onreadystatechange = function ()
+			{
+				if (request.readyState === 4)
+				{
+					callback(request.responseText);
+				}
+			};
+
+			if (type === "POST")
+			{
+				request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+				request.send(this._serialize(data));
+			}
+			else
+			{
+				request.send(null);
+			}
+		},
+		_serialize: function (data)
+		{
+			var name,
+				value,
+				pairs = [];
+
+			for (name in data)
+			{
+				if (!data.hasOwnProperty(name))
+				{
+					continue;
+				}
+				if (typeof data[name] === "function")
+				{
+					continue;
+				}
+
+				value = data[name].toString();
+
+				name = encodeURIComponent(name);
+				value = encodeURIComponent(value);
+
+				pairs.push(name + "=" + value);
+			}
+
+			return pairs.join("&");
+		}
+	};
+
+	/**
+	 * Sends a GET type ajax request
+	 * 
+	 * @name get
+	 * @function
+	 * @memberOf $_
+	 * @param string url
+	 * @param object data
+	 * @param function callback
+	 */
+	$_.ext('get', function (url, data, callback){
+		ajax._do(url, data, callback, false);
+	});
+	
+	/**
+	 * Sends a POST type ajax request
+	 * 
+	 * @name post
+	 * @function
+	 * @memberOf $_
+	 * @param string url
+	 * @param object data
+	 * @param function callback
+	 */
+	$_.ext('post', function (url, data, callback){
+		ajax._do(url, data, callback, true);
+	});
+}());
+
+// --------------------------------------------------------------------------
+
+/**
+ * Event
+ *
+ * Event api wrapper
+ */
+(function (){
+
+	"use strict";
+
+	// Property name for expandos on DOM objects
+	var kis_expando = "KIS_0_5_0";
+
+	var _attach, _remove, _add_remove, e, _attach_delegate;
+
+	// Define the proper _attach and _remove functions
+	// based on browser support
+	if(typeof document.addEventListener !== "undefined")
+	{
+		/**
+		 * @private
+		 */
+		_attach = function (sel, event, callback)
+		{
+			if(typeof sel.addEventListener !== "undefined")
+			{
+				// Duplicated events are dropped, per the specification
+				sel.addEventListener(event, callback, false);
+			}
+		};
+		/**
+		 * @private
+		 */
+		_remove = function (sel, event, callback)
+		{
+			if(typeof sel.removeEventListener !== "undefined")
+			{
+				sel.removeEventListener(event, callback, false);
+			}
+		};
+	}
+	// typeof function doesn't work in IE where attachEvent is available: brute force it
+	else if(typeof document.attachEvent !== "undefined") 
+	{
+		/**
+		 * @private
+		 */
+		_attach = function (sel, event, callback)
+		{
+			function _listener () {
+				// Internet Explorer fails to correctly set the 'this' object
+				// for event listeners, so we need to set it ourselves.
+				callback.apply(arguments[0]);
+			}
+			
+			if (typeof sel.attachEvent !== "undefined")
+			{
+				_remove(event, callback); // Make sure we don't have duplicate listeners
+				
+				sel.attachEvent("on" + event, _listener);
+				// Store our _listener so we can remove it later
+				var expando = sel[kis_expando] = sel[kis_expando] || {};
+				expando.listeners = expando.listeners || {};
+				expando.listeners[event] = expando.listeners[event] || [];
+				expando.listeners[event].push({
+					callback: callback,
+					_listener: _listener
+				});
+			}
+			else
+			{
+				console.log("Failed to _attach event:"+event+" on "+sel);
+			}
+		};
+		/**
+		 * @private
+		 */
+		_remove = function (sel, event, callback)
+		{
+			if(typeof sel.detachEvent !== "undefined")
+			{
+				var expando = sel[kis_expando];
+				if (expando && expando.listeners
+						&& expando.listeners[event])
+				{
+					var listeners = expando.listeners[event];
+					var len = listeners.length;
+					for (var i=0; i 1 && typeof value === "undefined")
+			{
+				console.log(sel);
+				console.log("Must be a singular element");
+				return;
+			}
+			else if (sel.length > 1 && typeof value !== "undefined") //You can set a bunch, though
+			{
+				$_.each(function (e){
+					return _attr(e, name, value);
+				});
+			}
+			else //Normal behavior
+			{
+				return _attr(sel, name, value);
+			}
+		},
+		/**
+		 * Sets or retrieves the text content of the element
+		 * specified by the current selector. If a value is 
+		 * passed, it will set that value on the current element,
+		 * otherwise it will return the value of the current element
+		 *
+		 * @name text
+		 * @memberOf $_.dom
+		 * @function
+		 * @param [string] value
+		 * @return string
+		 * @type string
+		 */
+		text: function (value)
+		{
+			var oldValue, set, type, sel;
+		
+			sel = this.el;
+			
+			set = (typeof value !== "undefined") ? true : false;
+			
+			type = (typeof sel.innerText !== "undefined")
+				? "innerText"
+				: (typeof sel.textContent !== "undefined")
+					? "textContent"
+					: "innerHTML";
+
+			oldValue = sel[type];
+			
+			if(set)
+			{
+				sel[type] = value;
+				return value;
+			}
+			else
+			{
+				return oldValue;
+			}
+		},
+		/**
+		 * Sets or retrieves a css property of the element
+		 * specified by the current selector. If a value is 
+		 * passed, it will set that value on the current element,
+		 * otherwise it will return the value of the css property
+		 * on the current element
+		 *
+		 * @name css
+		 * @memberOf $_.dom
+		 * @function
+		 * @param string property
+		 * @param [string] value
+		 * @return string
+		 * @type string
+		 */
+		css: function (prop, val)
+		{
+			//Return the current value if a value is not set
+			if(typeof val === "undefined")
+			{
+				return _css(this.el, prop);
+			}
+		
+			$_.each(function (e){
+				_css(e, prop, val);
+			});
+		},
+		/**
+		 * Adds to the innerHTML of the current element, after the last child.
+		 * 
+		 * @example $_("ul").dom.append("<li></li>") adds an li element to the end of the selected ul element
+		 * @name append
+		 * @memberOf $_.dom
+		 * @function
+		 * @param string htm
+		 */
+		append: function(htm)
+		{
+			if(typeof document.insertAdjacentHTML !== "undefined")
+			{
+				this.el.insertAdjacentHTML('beforeend', htm);
+			}
+			else
+			{
+				this.el.innerHTML += htm;
+			}
+		},
+		/**
+		 * Adds to the innerHTML of the selected element, before the current children
+		 * 
+		 * @name prepend
+		 * @memberOf $_.dom
+		 * @function
+		 * @param string htm
+		 */
+		 prepend: function(htm)
+		 {
+		 	if(typeof document.insertAdjacentHTML !== "undefined")
+		 	{
+		 		this.el.insertAdjacentHTML('afterbegin', htm);
+		 	}
+		 	else
+		 	{
+		 		this.el.innerHTML = htm + this.el.innerHTML;
+		 	}
+		 },
+		/**
+		 * Sets or gets the innerHTML propery of the element(s) passed
+		 *
+		 * @name html
+		 * @memberOf $_.dom
+		 * @function
+		 * @param [string] htm
+		 * @return string
+		 * @type string
+		 */
+		html: function(htm)
+		{
+			
+			if(typeof htm !== "undefined")
+			{
+				this.el.innerHTML = htm;
+			}
+			
+			//If the parameter is undefined, just return the current value
+			return this.el.innerHTML;
+		}
+	};
+
+	$_.ext('dom', d);
+	
+}());
+
diff --git a/kis-lite-min.js b/kis-lite-min.js
new file mode 100644
index 0000000..dc35c1c
--- /dev/null
+++ b/kis-lite-min.js
@@ -0,0 +1,12 @@
+(function(){if("undefined"!==typeof document.querySelector){var d,g,f,e;d=function(a){e="undefined"===typeof a?"undefined"!==typeof d.el?d.el:document.documentElement:"object"!==typeof a?g(a):a;d.prototype.el=e;var a=f(d),b;for(b in a)if("object"===typeof a[b])a[b].el=e;a.el=e;return a};g=function(a,b){var c;if("string"!=typeof a||"undefined"===typeof a)return a;c=null!=b&&1===b.nodeType?b:document;if(a.match(/^#([\w\-]+$)/))return document.getElementById(a.split("#")[1]);c=c.querySelectorAll(a);
+return 1===c.length?c[0]:c};f=function(a){var b;if("undefined"!==typeof a){if("undefined"!==typeof Object.create)return Object.create(a);b=typeof a;if(!("object"!==b&&"function"!==b))return b=function(){},b.prototype=a,new b}};d.ext=function(a,b){b.el=e;d[a]=b};d.ext("each",function(a){if("undefined"!==typeof e.length&&e!==window){var b=e.length;if(0!==b)for(var c,h=0;h bFloat ? 1 : aFloat < bFloat ? -1 : 0;
diff --git a/src/polyfill.js b/src/polyfill.js
index 0560ebe..0d575ba 100644
--- a/src/polyfill.js
+++ b/src/polyfill.js
@@ -205,16 +205,16 @@
 	 * event.preventDefault/e.stopPropagation polyfill
 	 * @private
 	 */
-	 if(typeof Event.preventDefault === "undefined" && typeof window.event !== "undefined")
-	 {
-	 	Event.prototype.preventDefault = function() 
-	 	{
-	 		window.event.stop();
-	 	},
-	 	Event.prototype.stopPropagation = function()
-	 	{
-	 		window.event.returnValue = false;
-	 	}
-	 }
+	if(typeof Event.preventDefault === "undefined" && typeof window.event !== "undefined")
+	{
+		Event.prototype.preventDefault = function() 
+		{
+			window.event.stop();
+		},
+		Event.prototype.stopPropagation = function()
+		{
+			window.event.returnValue = false;
+		}
+	}
 	
 }());
\ No newline at end of file