Skip to content

Instantly share code, notes, and snippets.

@antimatter15
Created June 17, 2010 10:53
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save antimatter15/441966 to your computer and use it in GitHub Desktop.
Save antimatter15/441966 to your computer and use it in GitHub Desktop.
//eLite
(function(){
var core = function(e){ //this is the constructor behind the library
var _this = this, i = _this[_length] = e[_length];
//*
if(i===_undefined){
//if no length value, set it to be that thingy
_this[0] = e;
_this[_length] = 1;
}
//i===_undefined&&(t[_length] = (t[0] = e, 1));
for(;i--;)_this[i]=e[i]; //count backwards and set the properties
},
proto = core.prototype,
ie = /msie/i.test(navigator.userAgent), //better check?
_length = 'length',
_undefined = undefined,
I = proto.I = function(callback){ //magical
//THIS IS THE SINGLE MOST IMPORTANT PART OF CODE IN THE WHOLE APP
//~230 bytes in size
var _fn = function(){
for(var r, //r stores the return of the function
w = [], //stores the new array
i = -1, //this increments!
_this = this, //a shortenable reference to this
len = _this[_length], //length to be faster?
arg = _this.a(arguments); //finally, a copy of argumetns
++i<len;){ //while its not done looping, loop.
r = callback.apply(_this,[i, _this[i]].concat(arg))
w = w.concat(_this.a( //append an array to the array
r===_undefined? //undefined, make it return default
[_this[i]]: //return the original element
(typeof(r)<'c'?( //'boolean'<'c'
//its a boolean, so now what
r?[_this[i]]:[] //add original if true, do nothing if false
):r) //if it's not a boolean or undefined, make it an array
));
}
return _this.g(w);
}
_fn.orig = callback;
return _fn;
};
proto.get = proto.g = function(list, no_select){ //exposed core
//this is the magical function that acutally gets exposed!
if(list.substr)
return /^</.test(list)||no_select?this.make(list):this.find(list); //if its a string, either .make() it or .find() it
return list.fn?list:(new core(list)); //if the list is already magical, don't re-magicalize
}
//Miscallaneous definitions
proto.fn = proto;
proto.core = core;
proto.v = 0.1337;
//{{{ Enumerables
proto.array = proto.a = function(list){
return [].slice.call(list||this)
}
proto.filter = I(function(index, item, filter){
return !!filter(item)
})
proto.map = I(function(index, item, callback){
return [callback(item)]
})
proto.each = I(function(index, item, fn){
//fn(index, item);
fn.call(item, index, item)
})
proto.is = I(function(index, item, check){
return [item==check];
})
proto.not = I(function(index, item){
return [!item];
})
proto.defined = I(function(index, item){
//remove the false/undefined/0 stuff
return !!item;
})
proto.first = function(){
return this.eq(0);
}
proto.last = function(){
//negative index
return this.eq(-1);
}
proto.eq = function(index){
//expanded from the original version, supports negative indexes
return this.g(this[index<0?(this.length+index):index]);
}
proto.toString = proto.tj = function(delimiter){
return this.a().join(delimiter||'');
}
proto.add = function(item){
//current object -> array -> add the item -> new object -> return
return this.g(this.a().concat(this.g(item).array()));
}
proto.del = I(function(index, item, check){
//create a new list with all except the ones that match
return check==item?[]:[item];
})
proto.count = function(item){
return this.is(item).defined().length;
}
proto.has = function(item){
//return !!this.count(item);
for(var i = 0, _this=this; //redefine _this to shorten it
_this[i]!=item && ++i < _this[_length]; //loop/increment until element is found
){}; //closure gets rid of {}
return i<_this[_length]?i:-1 //if not found, it's a huge number
}
proto.unique = I(function(index, item){
return this.has(item) == index;
})
proto.slice = function(begin, end){
return this.get([].slice.apply(this,arguments));
}
//}}}
//{{{ Utilities
proto.no = function(){};
proto.trim = function(str){
return (str||this+'').replace(/^\s+|\s+$/g,'');
}
proto.now = function(){
return +new Date;
}
proto.set = proto.extend = function(old, properties){
if (!properties) {
properties = old;
old = this;
}
for(var i in properties)
old[i] = properties[i];
return old; //== this;
}
proto.rand = function(range){
return ~~(Math.random()*range);
}
proto._xdecode = function(str){
return eval('('+str+')');
}
proto._xencode = function(obj){
var x, t=[], N=proto.encode; //arguments.callee
if(obj.split) //string
return "'"+obj.replace(/(['\n\\])/g,"\\$1")+"'";
if(typeof obj < 'o') //number/boolean
return obj+'';
for(x in obj) t.push( //object/array
(obj.pop?'':(N(x)+':'))+N(obj[x]));
obj = t.join();
return obj.pop?('{'+obj+'}'):('['+obj+']')
}
proto.decode = window.JSON?JSON.parse:proto._xdecode;
proto.encode = window.JSON?JSON.stringify:proto._xencode;
proto.ajax = function(url, callback, post){
var x = new(window.XMLHttpRequest||ActiveXObject)('Microsoft.XMLHTTP')
x.open(post?'POST':'GET',url||'.',1);
post&&x.setRequestHeader('Content-type','application/x-www-form-urlencoded');
x.onreadystatechange=function(){
x.readyState>3&&callback&&callback(x.responseText,x)
};
x.send(post)
return x
}
//}}}
//{{{ Animation
proto.fxrate = 10; //10ms per iteration
proto.fxdefault = 400; //default animation is 400ms
proto.ease = proto.esine = function(v){return (1-Math.cos(v*Math.PI))/2};
//proto.eline = function(v){return v};
proto.fx = I(function(index,
element, //the affected element
duration, //duration in milliseconds
callback //callback for each iteration args: (post-easing val 0-1, pre-easing val 0-1)
){
var _this = this,
now = _this.now, //assign a shortuct to this.now(), which is +new Date
begin = now(), //store the startup time
amount, //here is the amount, its from 0-1 and pre-easing
loop //this stores the main animation looper
if(element.R) //if it's running
return (element.Q=(element.Q||[]).concat([arguments]),[element]); //add to Q(ueue)
element.R = 1; //set thta the animation is running
;(loop = function(){ //set the main recursive looper
if(
(amount = (now()-begin)/duration) < 1 //terminate if amount is > 1
&& element.R
&& callback(_this.ease(amount),element) != 9 //9 terminates execution, it's a random number
) setTimeout(loop, _this.fxrate); else{
amount>1&&callback(1,element); //the last value must be greater than 1 for the loop to terminate
//or else it has been cancelled in the middle, in which case, it shouldn't be called again
//and because of that you dont call it again.
element.R = 0; //animation is no longer running
element.Q && element.Q.length &&
_this.g(element).fx.apply(_this.g(element), _this.a(element.Q.shift()).slice(2));
}
})() //start off the looper
});
proto.fade = function(d, r){
var t = this;
t.fx(d || t.fxdefault, function(a,e){
if(!a && t.get(e).hidden()[0]==r)return 9;
if(a==1) t.css('opacity','').css('filter', '').show(!r);
else{
r&&(a=1-a);
t.show().css('opacity', a+'');
ie &&
t.css('filter', 'alpha(opacity='+100*a+')');
}
})
return t;
}
proto.slide = function(d, r){
var t = this, _height = 'height';
return t.fx(d || t.fxdefault, function(a, e){
if(!a && t.get(e).hidden()[0]==r) return 9;
a==1?
t.get(e).css(_height, e.p + 'px').show(!r,e.p=0):
t.get(e).css(_height, (e.p ? ((r?(1-a):a)*e.p):(
(e.p=t.get(e).show().pos()[0].h)*(+r)
)) + 'px');
})
}
proto.show = I(function(index, item, state){
this.g(item).css('display',(state||state===_undefined)?'':'none')
})
proto.hide = function(){
return this.show(0);
}
proto.hidden = I(function(index, item){
return [item.style.display == 'none']
})
proto.fadeIn = function(duration){
return this.fade(duration,0)
}
proto.fadeOut = function(duration){
return this.fade(duration,1)
}
proto.slideDown = function(duration){
return this.slide(duration,0) //weird how i cant get rid of the zero without breaking it
//issue: using it without the zero prevents hidden() from working properly
//cuz undefined!=false
}
proto.slideUp = function(duration){
return this.slide(duration,1)
}
proto.delay = function(duration){
return this.fx(duration,this.no);
}
proto.queue = function(callback){
var _this = this;
//it cant be zero because division by zero equals infinity which is > 1.0
//but if its negative, i cant see any negative side effects
_this.fx(-1, function(u, element){
callback();
return 9 //SIGKILL, read: http://en.wikipedia.org/wiki/SIGKILL
})
return _this;
}
//}}}
//{{{ CSS Selectors/DOM Traversal
proto._nfind = I(function(index, item, selector){
return item.querySelectorAll(selector)
});
proto._xfind = function(selector){
//parse it and search manually yay yay yay
var item = this;
(' '+this.trim(selector))
.replace(/ *([>\+]) */g,'$1;%')
.replace(/ ([\.#:])/g, ' *$1')
.replace(/([ %\.#:>\+\[]|^)(;% .+?\]|;|[^\[\.#:>\+% ]*)/g, function(all, op, arg){
item = item[op](arg).nodeType(1);
})
return item;
};
proto.find = document.querySelectorAll?proto._nfind:proto._xfind;
proto[' '] = proto.tag = I(function(index, item, tag){
return item.getElementsByTagName(tag||'*');
})
proto.id = function(id){
return this.g(this.d().getElementById(id));
}
proto.cls = function(cls){
return this.find('.'+cls);
}
proto['%'] = proto.filterTag = I(function(index, item, tag){
return item.tagName.toLowerCase() == tag.toLowerCase()
})
proto['#'] = proto.filterId = I(function(index, item, id){
return item.id == id
})
proto['.'] = proto.filterClass = I(function(index, item, cls){
return this.g(item).hasClass(cls)[0]
})
proto.children = function(){
return this.contents().nodeType(1)
}
proto['>'] = proto.contents = I(function(index, item){
return item.childNodes
});
proto['+'] = proto.next = I(function(index, item){
return item.nextSibling;
})
proto.prev = I(function(item){
return item.previousSibling;
})
proto.nodeType = I(function(index, item, type){
return item.nodeType == type
})
proto.parent = I(function(index, item){
return [item.parentNode];
})
//}}}
//{{{ Dom Manipulation
proto.d = function(){
return this[0].ownerDocument||document;
}
proto.make = function(str){
return this.create().html(str).contents(); //maybe .contents() at the end?
}
proto.create = function(tag){
return this.g(this.d().createElement(tag||'div'))
}
proto.remove = I(function(index, item){
item.parentNode.removeChild(item);
})
proto.append = function(el){
this.g(el,1).appendTo(this);
return this;
}
proto.prepend = function(el){
this.g(el,1).prependTo(this);
return this;
}
proto.appendTo = I(function(index, item, target){
this.g(target)[0].appendChild(item);
})
proto.prependTo = I(function(index, item, target){
target = this.g(target)[0];
target.insertBefore(item, target.firstChild);
})
proto.insertAfter = I(function(index, item, target){
//this.insertBefore(target.nextSibling);
target = this.g(target)[0];
target.parentNode.insertBefore(item, target.nextSibling);
})
proto.insertBefore = I(function(index, item, target){
target = this.g(target)[0];
target.parentNode.insertBefore(item, target);
})
proto.before = function(el){
this.g(el).insertBefore(this);
return this;
}
proto.after = function(el){
this.g(el).insertAfter(this);
return this;
}
//}}}
//{{{ Attributes
proto.html = function(val){
return this.prop('innerHTML',val)
}
proto.val = function(val){
return this.prop('value', val)
}
proto.text = function(val){
return this.prop(document.body.innerText?'innerText':'contentText', val)
}
proto.attr = I(function(index, item, name, val){
if(val===_undefined) return [item.getAttribute(name)];
item.setAttribute(name, val);
})
proto.removeAttr = I(function(index, item, name){
item.removeAttribute(name)
})
proto.toggleClass = I(function(index, item, name){
item = this.g(item);
item.hasClass(name)[0]?item.removeClass(name):item.addClass(name);
})
proto.prop = I(function(index, item, name, val){
if(val===_undefined) return [item[name]];
item[name] = val;
})
proto.hasClass = I(function(index, item, cls){
return [this.g(item.className.split(' ')).has(cls)>-1]
})
proto.addClass = I(function(index, item, cls){
this.g(item).hasClass(cls)||(item.className+=' '+cls);
})
proto.removeClass = I(function(index, item, cls){
item.className = this.g(item).del(cls).tj(' ');
})
proto.css = I(function(index, item, name, val){
name = name.replace(/-(.)/,function(all, match){return match.toUpperCase()});
if(val===_undefined)
return [item.style[name]];
item.style[name] = val;
})
proto.pos = I(function(index, item){
var pos = {l:0, t:0, w:item.offsetWidth, h:item.offsetHeight};
do{
pos.l += item.offsetLeft;
pos.t += item.offsetTop
}while(item = item.offsetParent)
return [pos]
})
//}}}
//{{{ Events
//should this be unbound for all elements immediately
//when its first triggered for one element or after each?
proto.one = function(t, f){
var j = this, g = function(a){
j.un(t, g)
f.call(this, a)
}
return j.on(t, g)
}
proto.on = I(function(index, item, type, callback){
if(item.attachEvent || item.addEventListener(type,callback,0)){
item['e'+type+callback] = callback;
item[type+callback] = function(){
item['e'+type+callback].call(event.srcElement, event)
};
item.attachEvent('on'+type,item[type+callback])
}
})
proto.un = I(function(index, item, type, callback){
item.attachEvent?
item.detachEvent('on'+type,item[type+callback]):
item.removeEventListener(type,callback,0);
})
proto.fire = I(function(index, item, type){
if (item.fireEvent) {
item.fireEvent('on' + type)
} else {
var event = this.d().createEvent('Events');
event.initEvent(type);
item.dispatchEvent(event);
}
})
proto.ready = function(f){
ie? //if unhappy browser
setTimeout(f,0): //do ugly hack for ie
this.g(this.d()).on('DOMContentLoaded', f)
}
//or should it be .proxy?
proto.bind = function(callback, scope){
return function(){
return callback.apply(scope, arguments)
}
}
//}}}
var methods = proto.get(document.documentElement),
exposed = proto.bind(methods.get, methods),
property;
for(property in proto)
exposed[property] = methods[property].apply? //basic function-ity test
proto.bind(methods[property], methods):
methods[property];
proto._old$ = window.$;
window.eLite = window.$ = exposed;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment