Created
April 3, 2012 11:20
-
-
Save kaixiang-li/2291119 to your computer and use it in GitHub Desktop.
minimal jQuery
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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