Skip to content

Instantly share code, notes, and snippets.

@kaixiang-li
Created April 3, 2012 11:20
Show Gist options
  • Save kaixiang-li/2291119 to your computer and use it in GitHub Desktop.
Save kaixiang-li/2291119 to your computer and use it in GitHub Desktop.
minimal jQuery
(function(undefined) {
var root = this,
previous = root.k,
k = function(selector,context){
return new k.fn.init(selector,context);
},
//check if html strings
quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
toString = Object.prototype.toString,
hasOwn = Object.prototype.hasOwnProperty,
push = Array.prototype.push,
slice = Array.prototype.slice,
trim = String.prototype.trim,
indexOf = Array.prototype.indexOf;
if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = k;
}
exports.k = k;
} else {
root['k'] = k;
}
k.VERSION = '0.1';
k.fn = k.prototype = {
constructor : k,
length:0,
init : function(selector,context){
if(typeof selector === "string"){
var first = selector[0],
elem,
match = quickExpr.exec(selector);
}
if(match && match[1]){
elem = this.createElement(match[1].slice(1,-1));
}
if(first === "#"){
elem = document.getElementById(selector.slice(1));
}
if(first === "."){
elem = this.getElementsByClassName(selector.slice(1))
}
if(elem){
push.call(this,elem);
}
return this;
},
eq:function(i){
return i === -1 ?
this.slice( i ) :
this.slice( i, +i + 1 );
},
first:function(){
return this.eq(0);
},
last:function(){
return this.eq(-1);
},
pushStack:function(elems){
//new matched set
var ret = this.constructor();
push.call(ret,elems)
return ret;
},
createElement:function(elem){
return document.createElementNS ?
document.createElementNS("http://www.w3.org/1999/xhtml",elem) :
document.createElement(elem);
},
getElementsByClassName:function(className, parentElement){
var elems = ($(parentElement)||document.body).getElementsByTagName("*");
var result=[];
for (i=0; j=elems[i]; i++){
if ((" "+j.className+" ").indexOf(" "+className+" ")!=-1){
result.push(j);
}
}
return result;
},
push:push,
splice:function(){},
slice:slice
};
k.fn.init.prototype = k.prototype;
//adding class properties
k.extend = function(obj){
for(var i in obj){
k[i] = obj[i];
}
};
//adding instance properties
k.include = function(obj){
for(var i in obj){
k.fn[i] = obj[i];
}
};
//cache system
//refer to http://stylechen.com/cachedata.html
k.extend({
uuid:0,
cacheData:{},
expando:"cacheData" + (+new Date() + "").slice(-8),
//js object直接保存,HTMLElement通过cacheData间接保存,防止IE内存泄露
data:function(elem,key,value){
var getValue = typeof key === "string",
internalKey = this.expando,
isNode = elem.nodeType,
cache = isNode ? this.cacheData : elem, // 是节点则保存到cacheData上
id = isNode ? elem[internalKey] : internalKey,//节点id = $div["cacheData1234342432"] = uuid;
thisCache;
if(isNode && !id){
elem[internalKey] = id = ++this.uuid;
}
if(!cache[id])
cache[id] = {};
thisCache = cache[id];
if(value !== undefined){
thisCache[key] = value;
}
return getValue ? thisCache[key] : thisCache;
},
removeData:function(elem,key){
var isNode = elem.nodeType,
internalKey = this.expando,
id = isNode ? elem[internalKey] : internalKey,
thisCache = isNode ? this.cacheData[id] : elem;
console.log(thisCache)
if( !id || !thisCache){
return;
}
if(typeof key === "string"){
delete thisCache[id];
delete thisCache[key];
}
},
each : function(array,fn){
for( var i = 0 ; i < array.length ; i++){
fn.call(null,array[i]);
}
return this;
}
});
k.include({
data:function(key,value){
if(value === undefined)
return k.data(this[0],key);
return k.each(this,function(item){
k.data(item,key,value)
});
},
removeData:function(key){
return k.each(this,function(item){
k.removeData(item,key);
});
}
});
//DOM MANIP
k.include({
prev:function(){
var elem = this[0];
do{
elem = elem.previousSibling;
}while(elem && elem.nodeType != 1);
return this.pushStack(elem);
},
next:function(){
var elem = this[0];
do{
elem = elem.nextSibling;
}while(elem && elem.nodeType != 1);
return this.pushStack(elem);
},
parent:function(num){
var elem = this[0];
num = num || 1;
for( var i = 0 ; i < num ; i++){
if( elem != null ) elem = elem.parentNode;
return this.pushStack(elem);
}
},
text:function(){
var t = "";
elem = this[0].childNodes || this[0];
for( var i = 0; i < elem.length ; i ++){
t += elem[i].nodeType !=1 ?
elem[i].nodeValue : text(elem[i].childNodes);
}
return t;
},
attr:function( name,value){
var elem = this[0];
if( !name || name.constructor !== String) return "";
name = { 'for':'htmlFor','class':'className'}[name] || name;
if(typeof value !== 'undefined'){
elem[name] = value;
if(elem.setAttribute)
elem.setAttribute(name,value);
return this;
}
else{
return elem.getAttribute(name);
}
},
append:function(elem){
var elems = this.checkElem(elem);
console.log(elems)
for( var i = 0 ; i < elems.length ; i++){
this[0].appendChild(elems[i]);
}
return this;
},
remove:function(){
k.each(this,function(elem){
elem.parentNode.removeChild(elem);
});
return this;
},
checkElem:function(a){
var r = [];
if(a.constructor != Array) a = [a];
for( var i = 0 ; i < a.length; i++){
if(a[i].constructor == String){
var div = document.createElement("div");
div.innerHTML = a[i];
for(var j = 0 ; j < div.childNodes.length;j++){
//r.length => 0++++++
r[r.length] = div.childNodes[j];
}
}
else if(a[i].length){
for(var j = 0 ; j < a[i].length ; j++){
r[r.length] = a[i][j];
}
}
else{
r[r.length] = a[i];
}
}
return r;
}
});
//css position
k.include({
getStyle:function(name){
var elem = this[0];
if(elem.style[name]){
return elem.style[name];
}
else if(elem.currentStyle)
return elem.currentStyle[name];
else if(document.defaultView &&
document.defaultView.getComputedStyle){
name = name.replace(/([A-Z])/g,"-$1");
name = name.toLowerCase();
var s = document.defaultView.getComputedStyle(elem,"");
return s && s.getPropertyValue(name);
}else
return null;
},
//相对于文档的x和y位置
pageX:function(){
var elem = this[0],
p = 0;
while( elem.offsetParent ){
p += elem.offsetLeft;
elem = elem.offsetParent;
}
return p;
},
pageY:function(){
var elem = this[0],
p = 0;
while( elem.offsetParent ){
p += elem.offsetTop;
elem = elem.offsetParent;
}
return p;
},
//相对于父元素的位置
parentX:function(){
var elem = this[0];
return elem.parentNode == elem.offsetParent ?
elem.offsetLeft :
this.pageX(elem) - this.pageX(elem.parentNode);
},
parentY:function(){
var elem = this[0];
return elem.parentNode == elem.offsetParent ?
elem.offsetTop :
this.pageY(elem) -this.pageY(elem.parentNode);
},
//确定relative元素的位置
posX:function(){
return parseInt(this.getStyle("left")) || 0;
},
posY:function(){
return parseInt(this.getStyle("right")) || 0;
},
//设置位置
setX:function(pos){
this[0].style.left = pos + "px";
},
setY:function(pos){
this[0].style.top = pos + "px";
},
//调整与当前元素位置
addX:function(pos){
this.setX(this.posX() + parseInt(pos));
},
addY:function(pos){
this.setX(this.posY() + parseInt(pos));
}
});
//DOM dimensions
k.include({
getWidth:function(){
return parseInt(this.getStyle("width"));
},
getHeight:function(){
return parseInt(this.getStyle("height"));
},
//potential width and height
getFullHeight:function(){
if(this.getStyle("display") != "none")
return this[0].offsetHeight || this.getHeight();
var old = this.resetCSS({
display:"",
visibility:"hidden",
position:"absolute"
});
var h = this[0].clientHeight || this.getHeight() || 0;
this.restoreCSS(old)
return h;
},
getFullWidth:function(){
if(this.getStyle("display") != "none")
return this[0].offsetWidth || this.getWidth();
var old = this.resetCSS({
display:"",
visibility:"hidden",
position:"absolute"
});
var h = this[0].clientWidth || this.getWidth() || 0;
this.restoreCSS(old)
return h;
},
hide:function(){
var elem = this[0],
curDisplay = this.getStyle("display");
if( curDisplay != "none")
elem.$oldDisplay = curDisplay;
elem.style.display = "none";
return this;
},
show:function(){
var elem = this[0],
curDisplay = this.getStyle("display");
if( curDisplay == "none")
elem.style.display = "block";
//elem.style.display = elem.$oldDisplay || "";
return this;
},
setOpacity:function(level){
var elem = this[0];
if( elem.filters)
elem.style.filters = "alpha(opactity= " + level + ")" ;
else
elem.style.opacity = level / 100;
return this;
},
resetCSS:function(prop){
var elem = this[0],
old = {};
for( var i in prop ){
old[i] = elem.style[i];
elem.style[i] = prop[i];
}
return old;
},
restoreCSS:function(prop){
for( var i in prop){
this[0].style[i] = prop[i];
}
}
});
//BOM dimensions
k.extend({
//页面高度和宽度
pageHeight:function(){
return document.body.scrollHeight;
},
pageWidth:function(){
return document.body.scrollWidth;
},
//滚动条位置
scrollX:function(){
var de = document.documentElement;
return self.pageXOffset ||
( de && de.scrollLeft ) ||
document.body.scrollLeft;
},
scrollY:function(){
var de = document.documentElement;
console.log(self.pageYOffset)
return self.pageYOffset ||
( de && de.scrollTop ) ||
document.body.scrollTop;
},
//浏览器视口高度和宽度
windowHeight:function(){
var de = document.documentElement;
return self.innerHeight ||
(de && de.clientHeight) ||
(document.body.clientHeight);
},
windowWidth:function(){
var de = document.documentElement;
return self.innerWidth ||
(de && de.clientWidth) ||
(document.body.clientWidth);
}
});
//animation
k.include({
slideDown:function(){
var elem = this[0],
h = this.getFullHeight();
elem.style.height = "0px";
this.show();
for( var i = 0 ; i <= 100 ; i += 5){
(function(){
var pos = i;
setTimeout(function(){
elem.style.height = ( pos / 100 ) * h + "px";
}, (pos + 1) * 10);
})();
}
return this;
},
fadeIn:function(){
var self = this;
this.setOpacity(0);
this.show();
//default 20 fps
for( var i = 0 ; i < 100 ; i += 5){
(function() {
var pos = i ;
setTimeout(function() {
self.setOpacity(pos);
},(pos + 1) * 10);
})();
}
return this;
}
});
//event
k.extend({
addEvent:function(elem,type,handler){
if(elem.addEventListener){
elem.addEventListener( type,handler,false);
}
else if( elem.attachEvent){
elem.attachEvent("on" + type,handler);
}
},
removeEvent:function(elem,type,handler){
if(elem.removeEventListener){
elem.removeEventListener( type,handler,false);
}
else if( elem.attachEvent){
elem.detachEvent("on" + type,handler);
}
},
fixEvent:function(e){
if(e.target) {
return e;
}
var event = {};
event.target = e.srcElement || document;
event.preventDefault = function(){
e.returnValue = false;
};
event.stopPropagation = function(){
e.cancelBubble = true;
}
//IE6/7/8中写入自定义属性,会内存泄露
for( var name in e){
event[name] = e[name];
}
return event;
},
eventHandler:function(elem){
return function(event){
event = k.fixEvent(event || window.event);
var type = event.type,
events = k.data(elem,"e" + type);
for( var i = 0,handler;handler = events[i++];){
//handler返回false时,阻止默认事件
if( handler.call(elem,event) == false){
event.preventDefault();
event.stopPropagation();
}
}
};
}
});
k.include({
bind:function(type,handler){
k.each(this,function(elem){
var events = k.data(elem,"e" + type) || k.data(elem,"e" + type,[]);
events.push(handler);
if(events.length === 1){
var eventHandler = k.eventHandler(elem);
k.data(elem,type + "Handler",eventHandler);
k.addEvent(elem,type,eventHandler);
}
})
},
unbind:function(type,handler){
return k.each(this,function(elem){
var events = k.data(elem,"e" + type);
if(!events) return ;
if(!handler){
events = undefined;
}
else{
for(var i = events.length - 1 ; i >= 0 ; i--){
var fn = events[i];
if( fn === handler ){
events.splice(i,1);
}
}
}
if( !events || !events.length){
var eventHandler = k.data(elem,type + "Handler");
k.removeEvent(elem,type,eventHandler);
k.removeData(elem,type+"Handler");
k.removeData(elem,"e" + type);
}
});
},
trigger:function(name){
k.each(this,function(elem){
var handler = k.data(elem,"e" + name);
handler[0]();
})
}
});
//shorthand methods;
k.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
"change select submit keydown keypress keyup error").split(" "), function( name ) {
k.fn[name] = function(fn){
return arguments.length > 0 ?
this.bind(name,fn) :
this.trigger(name);
}
});
k
//ajax
k.ajax = function ajax( options ) {
options = {
type: options.type || "POST",
url: options.url || "",
timeout: options.timeout || 5000,
onComplete: options.onComplete || function(){},
onError: options.onError || function(){},
onSuccess: options.onSuccess || function(){},
data: options.data || ""
};
var xml = new XMLHttpRequest();
xml.open("GET", options.url, true);
var timeoutLength = 5000;
var requestDone = false;
setTimeout(function(){
requestDone = true;
}, timeoutLength);
xml.onreadystatechange = function(){
if ( xml.readyState == 4 && !requestDone ) {
if ( httpSuccess( xml ) ) {
options.onSuccess( httpData( xml, options.type ) );
} else {
options.onError();
}
options.onComplete();
xml = null;
}
};
xml.send();
function httpSuccess(r) {
try {
return !r.status && location.protocol == "file:" ||
( r.status >= 200 && r.status < 300 ) ||
r.status == 304 ||
navigator.userAgent.indexOf("Safari") >= 0 && typeof r.status == "undefined";
} catch(e){}
return false;
}
function httpData(r,type) {
var ct = r.getResponseHeader("content-type");
var data = !type && ct && ct.indexOf("xml") >= 0;
data = type == "xml" || data ? r.responseXML : r.responseText;
if ( type == "script" )
eval.call( window, data );
return data;
}
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment