Fixed a bunch of issues, added more unit tests. All pass

This commit is contained in:
Timothy Warren 2011-07-14 21:52:17 -04:00
parent afde37c6e3
commit 457ccf07a4
2 changed files with 287 additions and 182 deletions

378
kis.js
View File

@ -6,7 +6,7 @@
*/
(function (){
"use strict";
//"use strict";
// Property name for expandos on DOM objects
var kis_expando = "KIS_0_2_0";
@ -17,17 +17,7 @@
return;
}
var $_, $, dcopy;
/**
* String trim function polyfill
*/
if(typeof String.prototype.trim === "undefined")
{
String.prototype.trim = function(){
return this.replace(/^\s+|\s+$/g, "");
};
}
var $_, $, dcopy, sel;
/**
* $
@ -37,7 +27,7 @@
$ = function (a)
{
var x;
if (typeof a !== "string"){ return a;}
if (typeof a !== "string" || typeof a === "undefined"){ return a;}
//Pick the quickest method for each kind of selector
if(a.match(/^#([\w\-]+$)/))
@ -62,22 +52,23 @@
*
* Constructor function
*/
$_ = function(sel)
$_ = function(s)
{
//Have documentElement be default selector, just in case
if(typeof s == "undefined")
{
sel = (typeof $_.el !== "undefined")
? $_.el
: document.documentElement;
}
else
{
sel = $(s);// || document.documentElement;
}
// Make a copy before adding properties
var self = dcopy($_);
//Get the DOM objects from the selector
sel = $(sel);
//Have window be default selector, just in case
if(typeof sel === "undefined")
{
sel = (typeof self.el !== "undefined")
? self.el
: window;
}
self.el = sel;
return self;
@ -115,6 +106,40 @@
};
//Function to add to $_ object, and get sel
$_.ext = function(name, obj)
{
$_[name] = obj;
obj.el = sel;
console.log(obj.el);
};
//Selector iteration
$_.ext('each', function (callback)
{
if(typeof sel.length !== "undefined")
{
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(selx);
}
}
else
{
callback(sel);
}
});
//Set global variables
$_ = window.$_ = window.$_ || $_;
$_.$ = $;
@ -127,44 +152,22 @@
};
}
// --------------------------------------------------------------------------
$_.each = function (callback)
/**
* String trim function polyfill
*/
if(typeof String.prototype.trim === "undefined")
{
var sel = $_.el;
//Don't try to iterate over the window object
if(sel === window || typeof sel === "undefined")
{
return;
}
if(typeof sel.length !== "undefined")
{
var len = sel.length;
if (len === 0)
{
return;
}
if (len === 1)
{
return callback(sel);
}
var selx;
for (var x = 0; x < sel.length; x++)
{
selx = (sel.item(x)) ? sel.item(x) : sel[x];
callback(selx);
}
}
else
{
callback(sel);
}
String.prototype.trim = function(){
return this.replace(/^\s+|\s+$/g, "");
};
}
// --------------------------------------------------------------------------
}());
(function(){
"use strict";
/**
* Ajax
@ -239,15 +242,13 @@
}
};
$_.get = function (url, data, callback)
{
$_.ext('get', function (url, data, callback){
ajax._do(url, data, callback, false);
};
});
$_.post = function (url, data, callback)
{
$_.ext('post', function (url, data, callback){
ajax._do(url, data, callback, true);
};
});
}());
/**
@ -338,7 +339,7 @@
}
};
$_.qs = qs;
$_.ext('qs', qs);
}());
@ -380,7 +381,7 @@
}
};
$_.store = store;
$_.ext('store', store);
}());
/**
@ -469,21 +470,10 @@
};
}
add_remove = function (event, callback, add)
add_remove = function (sel, event, callback, add)
{
var i, len;
//Get the DOM object
var sel = $_.el;
if(arguments.length === 4)
{
sel = arguments[0];
event = arguments[1];
callback = arguments[2];
add = arguments[3];
}
if(typeof sel === "undefined")
{
console.log(arguments);
@ -500,34 +490,34 @@
for (i = 0; i < len; i++)
{
add_remove(event[i], callback, add);
add_remove(sel, event[i], callback, add);
}
return;
}
//Go over additonal DOM objects as needed
$_.each(function(e){
(add === true)
? attach(e, event, callback)
: remove(e, event, callback);
});
};
e = {
add: function (event, callback)
{
add_remove(event, callback, true);
$_.each(function(e){
add_remove(e, event, callback, true);
});
},
remove: function (event, callback)
{
add_remove(event, callback, false);
$_.each(function(e){
add_remove(e, event, callback, false);
});
}
};
$_.event = e;
$_.ext('event', e);
}());
@ -602,86 +592,163 @@
return (typeof value !== "undefined") ? value : oldVal;
}
// Private function for class manipulation
function _class(sel, c, add)
{
var ec, cs, len, i, classInd;
/*
* 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.
*/
//We can do this the easy way
if (sel.classList)
{
if (add === true)
{
sel.classList.add(c);
return;
}
else if (add === false)
{
sel.classList.remove(c);
return;
}
}
else //Or the hard way
{
//No class attribute? Set an empty string
ec = sel.className;//_attr("class");
ec = (typeof ec === "string") ? ec : '';
/*global self, document, DOMException */
//Convert class attribute string into array
if (typeof ec === "string")
{
cs = (ec !== '') ? ec.split(" ") : [];
/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/
len = cs.length;
classInd = false;
if (typeof document !== "undefined" && !("classList" in document.createElement("a")))
{
(function (view){
"use strict";
//Check for the class in the array
for (i = 0; i < len; i++)
var classListProp = "classList",
protoProp = "prototype",
elemCtrProto = (view.HTMLElement || view.Element)[protoProp],
objCtr = Object,
strTrim = String[protoProp].trim ||
function ()
{
if (cs[i] === c)
return this.replace(/^\s+|\s+$/g, "");
},
arrIndexOf = Array[protoProp].indexOf ||
function (item)
{
classInd = i;
break;
var
i = 0,
len = this.length;
for (; i < len; i++)
{
if (i in this && this[i] === item)
{
return i;
}
}
return -1;
}
//Add or remove from class array
if (add === true)
// Vendors: please allow content code to instantiate DOMExceptions
,
DOMEx = function (type, message)
{
//Only add the class if isn't already there
if (classInd === false)
this.name = type;
this.code = DOMException[type];
this.message = message;
},
checkTokenAndGetIndex = function (classList, token)
{
cs.push(c);
if (token === "")
{
throw new DOMEx("SYNTAX_ERR", "An invalid or illegal string was specified");
}
}
else if (add === false)
if (/\s/.test(token))
{
//Make sure the class you want to remove exists
if (classInd !== false)
{
cs.splice(classInd, 1);
throw new DOMEx("INVALID_CHARACTER_ERR", "String contains an invalid character");
}
}
var cName = (cs.length > 1) ? cs.join(" ") : cs[0];
if (typeof sel.className !== "undefined")
return arrIndexOf.call(classList, token);
},
ClassList = function (elem)
{
sel.className = cName;
}
else if (typeof sel.setAttribute !== "undefined")
var
trimmedClasses = strTrim.call(elem.className),
classes = trimmedClasses ? trimmedClasses.split(/\s+/) : [],
i = 0,
len = classes.length;
for (; i < len; i++)
{
sel.setAttribute('class', cName);
this.push(classes[i]);
}
this._updateClassName = function ()
{
elem.className = this.toString();
};
},
classListProto = ClassList[protoProp] = [],
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
{
console.log(sel);
}
return cName;
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));
}
function _toCamel(s)
@ -733,13 +800,15 @@
addClass: function (c)
{
$_.each(function (e){
_class(e, c, true);
console.log(e);
console.log(c);
e.classList.add(c);
});
},
removeClass: function (c)
{
$_.each(function (e){
_class(e, c, false);
e.classList.remove(c);
});
},
hide: function ()
@ -757,7 +826,7 @@
},
attr: function (name, value)
{
var sel = $_.el;
var sel = this.el;
//Make sure you don't try to get a bunch of elements
if (sel.length > 1 && typeof value === "undefined")
@ -769,7 +838,7 @@
else if (sel.length > 1 && typeof value !== "undefined") //You can set a bunch, though
{
$_.each(function (e){
_attr(e, name, value);
return _attr(e, name, value);
});
}
else //Normal behavior
@ -781,7 +850,7 @@
{
var oldValue, set, type, sel;
sel = $_.el;
sel = this.el;
set = (typeof value !== "undefined") ? true : false;
@ -811,7 +880,8 @@
}
};
$_.dom = d;
$_.ext('dom', d);
}());
}());

View File

@ -17,36 +17,68 @@
var y = $_("aside");
expect(1);
notEqual(x.el, y.el, "Unique Query Objects - see Issue #5");
notStrictEqual(x.el, y.el, "Unique Query Objects - see Issue #5");
});
test("Extend function", function(){
var o = $_("ol");
expect(3);
ok(o.ext, "Extend function exists");
$_.ext('test', {});
strictEqual(typeof o.test, "object", "Extend function adds to $_");
equal(o.test.el, $_("ol").el, "Extend function adds selector to passed object");
});
test("Selector tests", function(){
var i=0;
$_("div").each(function(e){
equal(e, $_("div").el[i], ".each function has current selector");
i++;
});
equal($_().el, window.document.documentElement, "Empty selector is set to documentElement");
});
test("Sub-modules", function(){
expect(5);
ok($_.get, "AJAX get method");
ok($_.post, "AJAX post method");
expect(4);
ok($_.qs, "Query String module");
ok($_().event, "Event module");
ok($_.store, "Local Storage module");
ok($_.dom, "Dom manipulation module");
ok($_().dom, "Dom manipulation module");
});
// --------------------------------------------------------------------------
module("ajax");
test("Methods defined", function(){
expect(2);
ok($_.get, "AJAX get method");
ok($_.post, "AJAX post method");
});
// --------------------------------------------------------------------------
module("events");
test("Events defined", function(){
expect(2);
ok($_.event.add, "Add Method Exists");
ok($_.event.remove, "Remove Method Exists");
});
test("Browser expando support", function() {
expect(3);
// kis-js events uses expando properties to store event listeners
// kis-js events uses expando properties to store event listeners for IE
// If this test fails, the event module will likely fail as well
var ele = document.createElement("div");
ele.expando = {a:5, b:"c", c: function cool(){return ele}};
equals(ele.expando.a, 5);
equals(ele.expando.b, "c");
equals(ele.expando.c(), ele,
equal(ele.expando.a, 5);
equal(ele.expando.b, "c");
equal(ele.expando.c(), ele,
"Closure isn't broken by being assigned to an expando property");
});
@ -56,19 +88,22 @@
test("Add/Remove Class", function() {
expect(4);
var $test = $_("#testSpan");
var ele = $test.el;
//var $test = $_("#testSpan");
//var ele = $test.el;
var ele = document.getElementById('testSpan');
var $test = $_(ele);
$test.dom.addClass("coolClass");
equals(ele.className, "coolClass");
equal(ele.className, "coolClass");
$test.dom.addClass("anotherClass");
equals(ele.className, "coolClass anotherClass");
equal(ele.className, "coolClass anotherClass");
$test.dom.removeClass("coolClass");
equals(ele.className, "anotherClass");
equal(ele.className, "anotherClass");
$test.dom.removeClass("anotherClass");
ok(ele.className === undefined || ele.className === "", "testSpan.className is empty");
});
}());