贡献一个连jquery都觉的大的时候可以用的 js库
生活随笔
收集整理的這篇文章主要介紹了
贡献一个连jquery都觉的大的时候可以用的 js库
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在一些很小的項目里,連用jquery都還覺的大的時候,你就可以用我的這個庫了。
一個庫或者框架,是應需求而生的,當你的項目實際上只需要簡單的一個好用的選擇器 一個ajax 封裝 一個兼容的事件封裝的時候,你當然就會覺的jquery都太臃腫了,好吧,我那jquery剝離了這幾個功能出來,本來我是只剝離jquery的domready 的, 但是發現這個東西牽扯到了jquery的事件模型的封裝,那我就把jquery的事件也一并的剝離了下來,然后自己寫了一個ajax封裝。ok,一個最簡單的js開發庫成型了。代碼在下面:
/** 簡易的開發js庫 暫命名為 --- 呃沒有命名
* $選擇器,ajax,event模塊,dom.ready()方法
* 該js library 暫時不能和同樣用$符號注冊window標志符的js framework or library比如jquery等協作,會有命名空間沖突
*/
(function(scope){
var _my_library=scope.my_library,_$=scope.$;
var my_library=scope.my_library=scope.$=function(selector,context){
return my_library.fn.init(selector,context);
}
var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;
// 簡單的判斷是一個html片段or是一個dom的id
//undefined;//定義一個局部的undefined
my_library.fn = {
init : function(selector,context){
selector = selector || document;
if(selector.nodeType){
return selector;
}
if ( typeof selector == "string" ) {
var match = quickExpr.exec( selector );
if ( match && (match[1] || !context) ) {
if ( match[1] ){
//return new String(selector);
var temp = document.createElement('div'),
frag = document.createDocumentFragment();
temp.innerHTML = selector;
(function(){
if(temp.firstChild) {
frag.appendChild(temp.firstChild);
arguments.callee();
}
})();
//傳入的為html串,則返回包含該html串的documentfragmet文檔碎片
return frag;
} else {
var elem = document.getElementById( match[3] );
if ( elem )
return elem;
return undefined;
}
} else
var $ret=PetQuery(selector,context);
return $ret.length==0 ? undefined : $ret;
} else if (my_library.isFunction(selector)){
my_library.ready( selector,document);
//如果傳入的是方法,那么就自動啟動ready加栽執行
}
}
};
var PetQuery = (function(){
//pet query javascript選擇器 begin
var snack = /(?:[\w\-\\.#]+)+(?:\[\w+?=([\'"])?(?:\\\1|.)+?\1\])?|\*|>/ig,
exprClassName = /^(?:[\w\-_]+)?\.([\w\-_]+)/,
exprId = /^(?:[\w\-_]+)?#([\w\-_]+)/,
exprNodeName = /^([\w\*\-_]+)/,
na = [null,null];
function _find(selector, context) {
context = context || document;
var simple = /^[\w\-_#]+$/.test(selector);
if (!simple && context.querySelectorAll) {
return realArray(context.querySelectorAll(selector));
}
if (selector.indexOf(',') > -1) {
var split = selector.split(/,/g), ret = [], sIndex = 0, len = split.length;
for(; sIndex < len; ++sIndex) {
ret = ret.concat( _find(split[sIndex], context) );
}
return unique(ret);
}
var parts = selector.match(snack),
part = parts.pop(),
id = (part.match(exprId) || na)[1],
className = !id && (part.match(exprClassName) || na)[1],
nodeName = !id && (part.match(exprNodeName) || na)[1],
collection;
if (className && !nodeName && context.getElementsByClassName) {
collection = realArray(context.getElementsByClassName(className));
} else {
collection = !id && realArray(context.getElementsByTagName(nodeName || '*'));
if (className) {
collection = filterByAttr(collection, 'className', RegExp('(^|\\s)' + className + '(\\s|$)'));
}
if (id) {
var byId = context.getElementById(id);
return byId?[byId]:[];
}
}
return parts[0] && collection[0] ? filterParents(parts, collection) : collection;
}
function realArray(c) {
try {
return Array.prototype.slice.call(c);
} catch(e) {
var ret = [], i = 0, len = c.length;
for (; i < len; ++i) {
ret[i] = c[i];
}
return ret;
}
}
function filterParents(selectorParts, collection, direct) {
var parentSelector = selectorParts.pop();
if (parentSelector === '>') {
return filterParents(selectorParts, collection, true);
}
var ret = [],
r = -1,
id = (parentSelector.match(exprId) || na)[1],
className = !id && (parentSelector.match(exprClassName) || na)[1],
nodeName = !id && (parentSelector.match(exprNodeName) || na)[1],
cIndex = -1,
node, parent,
matches;
nodeName = nodeName && nodeName.toLowerCase();
while ( (node = collection[++cIndex]) ) {
parent = node.parentNode;
do {
matches = !nodeName || nodeName === '*' || nodeName === parent.nodeName.toLowerCase();
matches = matches && (!id || parent.id === id);
matches = matches && (!className || RegExp('(^|\\s)' + className + '(\\s|$)').test(parent.className));
if (direct || matches) { break; }
} while ( (parent = parent.parentNode) );
if (matches) {
ret[++r] = node;
}
}
return selectorParts[0] && ret[0] ? filterParents(selectorParts, ret) : ret;
}
var unique = (function(){
var uid = +new Date();
var data = (function(){
var n = 1;
return function(elem) {
var cacheIndex = elem[uid],
nextCacheIndex = n++;
if(!cacheIndex) {
elem[uid] = nextCacheIndex;
return true;
}
return false;
};
})();
return function(arr) {
var length = arr.length,
ret = [],
r = -1,
i = 0,
item;
for (; i < length; ++i) {
item = arr[i];
if (data(item)) {
ret[++r] = item;
}
}
uid += 1;
return ret;
};
})();
function filterByAttr(collection, attr, regex) {
var i = -1, node, r = -1, ret = [];
while ( (node = collection[++i]) ) {
if (regex.test(node[attr])) {
ret[++r] = node;
}
}
return ret;
}
return _find;
})();
//query is end
my_library.isFunction = (function() {
//修復jquery中isFunction的 BUG
// Performance optimization: Lazy Function Definition
return "object" === typeof document.getElementById ?
isFunction = function(fn){
try {
return /^\s*\bfunction\b/.test("" + fn);
} catch (x) {
return false
}
}:
isFunction = function(fn){
return "[object Function]" === Object.prototype.toString.call(fn);
};
})();
my_library.Each = function( object, callback, args ) {
var name, i = 0, length = object.length;
if ( args ) {
if ( length === undefined ) {
for ( name in object )
if ( callback.apply( object[ name ], args ) === false )
break;
} else
for ( ; i < length; )
if ( callback.apply( object[ i++ ], args ) === false )
break;
// A special, fast, case for the most common use of each
} else {
if ( length === undefined ) {
for ( name in object )
if ( callback.call( object[ name ], name, object[ name ] ) === false )
break;
} else
for ( var value = object[0];
i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
}
return object;
};
////開始為dom ready做準備 begin
Function.prototype.hookend = function(hook){
//這里侵入了Function的原形,一個掛鉤函數,讓函數可以繼承自己執行新的函數,唉,取舍啊
var fn = this;
return function(){
var ret = fn.apply(this, arguments);
hook.apply(this, arguments);
return ret;
}
};
my_library.domReady=function(){
//domready 頁面load 回調的 頂層函數,后面通過$(function(){})添加的 函數 都 在由這個函數為頂層函數的閉包作用域鏈上
if(scope.location.href.toString().indexOf("file:")!=0)
document.domain="qq.com";
};
my_library.isReady = false;
// Handle when the DOM is ready
my_library.ready_run = function() {
// Make sure that the DOM is not already loaded
if ( !my_library.isReady ) {
// Remember that the DOM is ready
my_library.isReady = true;
// If there are functions bound, to execute
my_library.domReady();
//這里執行所有的domready函數
my_library.domReady=null;
//把擴展的hookend原型去掉,還原原型污染
Function.prototype.hookend=null;
delete Function.prototype.hookend;
//這個方法的使命完成了
}
};
my_library.ready = function(fn) {
bindReady();
if (my_library.isReady)
fn.call(scope.document);
else
my_library.domReady=my_library.domReady.hookend(fn);
//用掛鉤閉包來緩存要domready執行的function
return this;
};
var readyBound=false;
function bindReady(){
if ( readyBound ) return;
readyBound = true;
if ( document.addEventListener ) {
document.addEventListener( "DOMContentLoaded", function(){
document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
my_library.ready_run();
}, false );
// If IE event model is used
} else if ( document.attachEvent ) {
document.attachEvent("onreadystatechange", function(){
if ( document.readyState === "complete" ) {
document.detachEvent( "onreadystatechange", arguments.callee );
my_library.ready_run();
}
});
if ( document.documentElement.doScroll && window == window.top ) (function(){
if ( my_library.isReady ) return;
try {
document.documentElement.doScroll("left");
} catch( error ) {
setTimeout( arguments.callee, 0 );
return;
}
my_library.ready_run();
})();
}
my_library.event.add( window, "load", my_library.ready_run );
};
var expando = "my_library" + now(), uuid = 0, windowData = {};
function now(){
return +new Date;
}
my_library.cache = {};
my_library.data = function( elem, name, data ) {
elem = elem == window ?
windowData :
elem;
var id = elem[ expando ];
if ( !id )
id = elem[ expando ] = ++uuid;
if ( name && !my_library.cache[ id ] )
my_library.cache[ id ] = {};
if ( data !== undefined )
my_library.cache[ id ][ name ] = data;
return name ?
my_library.cache[ id ][ name ] :
id;
};
my_library.removeData = function( elem, name ) {
elem = elem == window ?
windowData :
elem;
var id = elem[ expando ];
if ( name ) {
if ( my_library.cache[ id ] ) {
delete my_library.cache[ id ][ name ];
name = "";
for ( name in my_library.cache[ id ] )
break;
if ( !name )
my_library.removeData( elem );
}
} else {
try {
delete elem[ expando ];
} catch(e){
if ( elem.removeAttribute )
elem.removeAttribute( expando );
}
delete my_library.cache[ id ];
}
};
my_library.event = {
//該模塊來自己jquery,所以相關注釋請查看jquery的develope版本
add: function(elem, types, handler, data) {
if ( elem.nodeType == 3 || elem.nodeType == 8 )
return;
if ( elem.setInterval && elem != window )
elem = window;
if ( !handler.guid )
handler.guid = this.guid++;
if ( data !== undefined ) {
var fn = handler;
handler = this.proxy( fn );
handler.data = data;
}
var events = my_library.data(elem, "events") || my_library.data(elem, "events", {}),
handle = my_library.data(elem, "handle") || my_library.data(elem, "handle", function(){
return typeof my_library !== "undefined" && !my_library.event.triggered ?
my_library.event.handle.apply(arguments.callee.elem, arguments) :
undefined;
});
// event in IE.
handle.elem = elem;
my_library.Each(types.split(/\s+/), function(index, type) {
var namespaces = type.split(".");
type = namespaces.shift();
handler.type = namespaces.slice().sort().join(".");
var handlers = events[type];
if ( my_library.event.specialAll[type] )
my_library.event.specialAll[type].setup.call(elem, data, namespaces);
if (!handlers) {
handlers = events[type] = {};
if ( !my_library.event.special[type] || my_library.event.special[type].setup.call(elem, data, namespaces) === false ) {
if (elem.addEventListener)
elem.addEventListener(type, handle, false);
else if (elem.attachEvent)
elem.attachEvent("on" + type, handle);
}
}
handlers[handler.guid] = handler;
my_library.event.global[type] = true;
});
// Nullify elem to prevent memory leaks in IE
elem = null;
},
guid: 1,
global: {},
proxy: function( fn, proxy ){
proxy = proxy || function(){ return fn.apply(this, arguments); };
proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
return proxy;
},
remove: function(elem, types, handler) {
if ( elem.nodeType == 3 || elem.nodeType == 8 )
return;
var events = my_library.data(elem, "events"), ret, index;
if ( events ) {
if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
for ( var type in events )
this.remove( elem, type + (types || "") );
else {
if ( types.type ) {
handler = types.handler;
types = types.type;
}
my_library.Each(types.split(/\s+/), function(index, type){
var namespaces = type.split(".");
type = namespaces.shift();
var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
if ( events[type] ) {
if ( handler )
delete events[type][handler.guid];
else
for ( var handle in events[type] )
if ( namespace.test(events[type][handle].type) )
delete events[type][handle];
if ( my_library.event.specialAll[type] )
my_library.event.specialAll[type].teardown.call(elem, namespaces);
for ( ret in events[type] ) break;
if ( !ret ) {
if ( !my_library.event.special[type] || my_library.event.special[type].teardown.call(elem, namespaces) === false ) {
if (elem.removeEventListener)
elem.removeEventListener(type, my_library.data(elem, "handle"), false);
else if (elem.detachEvent)
elem.detachEvent("on" + type, my_library.data(elem, "handle"));
}
ret = null;
delete events[type];
}
}
});
}
// Remove the expando if it's no longer used
for ( ret in events ) break;
if ( !ret ) {
var handle = my_library.data( elem, "handle" );
if ( handle ) handle.elem = null;
my_library.removeData( elem, "events" );
my_library.removeData( elem, "handle" );
}
}
},
handle: function(event) {
var all, handlers;
event = arguments[0] = my_library.event.fix( event || window.event );
event.currentTarget = this;
var namespaces = event.type.split(".");
event.type = namespaces.shift();
all = !namespaces.length && !event.exclusive;
var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
handlers = ( my_library.data(this, "events") || {} )[event.type];
for ( var j in handlers ) {
var handler = handlers[j];
if ( all || namespace.test(handler.type) ) {
event.handler = handler;
event.data = handler.data;
var ret = handler.apply(this, arguments);
if( ret !== undefined ){
event.result = ret;
if ( ret === false ) {
event.preventDefault();
event.stopPropagation();
}
}
if( event.isImmediatePropagationStopped() )
break;
}
}
},
props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix: function(event) {
if ( event[expando] )
return event;
var originalEvent = event;
event = my_library.Event( originalEvent );
for ( var i = this.props.length, prop; i; ){
prop = this.props[ --i ];
event[ prop ] = originalEvent[ prop ];
}
if ( !event.target )
event.target = event.srcElement || document;
if ( event.target.nodeType == 3 )
event.target = event.target.parentNode;
if ( !event.relatedTarget && event.fromElement )
event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
if ( event.pageX == null && event.clientX != null ) {
var doc = document.documentElement, body = document.body;
event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
}
if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
event.which = event.charCode || event.keyCode;
if ( !event.metaKey && event.ctrlKey )
event.metaKey = event.ctrlKey;
if ( !event.which && event.button )
event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
return event;
},
proxy: function( fn, proxy ){
proxy = proxy || function(){ return fn.apply(this, arguments); };
proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
return proxy;
},
special: {
ready: {
setup: bindReady,
teardown: function() {}
}
},
specialAll: {
live: {
setup: function( selector, namespaces ){
my_library.event.add( this, namespaces[0], liveHandler );
},
teardown: function( namespaces ){
if ( namespaces.length ) {
var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
my_library.each( (my_library.data(this, "events").live || {}), function(){
if ( name.test(this.type) )
remove++;
});
if ( remove < 1 )
my_library.event.remove( this, namespaces[0], liveHandler );
}
}
}
}
};
my_library.Event = function( src ){
if( !this.preventDefault )
return new my_library.Event(src);
if( src && src.type ){
this.originalEvent = src;
this.type = src.type;
}else
this.type = src;
this.timeStamp = now();
this[expando] = true;
};
function returnFalse(){
return false;
}
function returnTrue(){
return true;
}
my_library.Event.prototype = {
preventDefault: function() {
this.isDefaultPrevented = returnTrue;
var e = this.originalEvent;
if( !e )
return;
if (e.preventDefault)
e.preventDefault();
e.returnValue = false;
},
stopPropagation: function() {
this.isPropagationStopped = returnTrue;
var e = this.originalEvent;
if( !e )
return;
if (e.stopPropagation)
e.stopPropagation();
e.cancelBubble = true;
},
stopImmediatePropagation:function(){
this.isImmediatePropagationStopped = returnTrue;
this.stopPropagation();
},
isDefaultPrevented: returnFalse,
isPropagationStopped: returnFalse,
isImmediatePropagationStopped: returnFalse
};
my_library.ajax=function(options){
var hastype= ("type" in options) ? true : false;
options={
//默認設置
method : options.method || "GET",
type : options.type || "xml",
url : options.url || "",
//超時連接,默認5秒
timeout: options.timeout || 50000,
delaytime:options.delaytime || 300,
onComplete: options.onComplete || function(){},
onError: options.onError || function(){},
onSuccess: options.onSuccess || function(){},
data : options.data || ""
//服務器將會返回的數據類型
};
var xml=getXMLHttpRequest(options.type);
//創建請求對象
xml.open(options.method , options.url);
//初始化異步請求
//超時計算 begin//
var timeoutLength=options.timeout;
var delaylength = options.delaytime;
//我們在請求5秒超時后放棄請求
var requestDone=false;
//請求超過300毫秒(目前默認為300毫秒)則延時
var isdelay=false;
setTimeout(function(){
//如果這個時候onreadystatechange回調函數已經執行請求已經返回,isdelay被該回調函數修改為null,否則設置isdelay=true說明系統已經開始延時
if (isdelay==null)
return;
isdelay=true; //系統已經延時
//記錄請求是否完成,這個時候就要注意設置請求可能超時的定時監聽了
setTimeout(function(){
requestDone=true;
},timeoutLength);
},delaylength)
//超時計算 end//
xml.onreadystatechange = function(){
if(xml.readyState == 4 && !requestDone){
if(httpSuccess(xml)){
var r_data=httpData( xml , options.type);
if(r_data != null)
options.onSuccess(r_data);
else
options.onError(null);
} else {
//否則就發生了錯誤
$.ui.showErr("服務器響應失敗!http狀態為"+xml.status);
options.onError();
}
options.onComplete();
//調用完成回調函數
xml = null;
//為避免內存泄漏,清理文檔
}
};
xml.send();
//發送請求,建立連接
function httpSuccess(r){
try
{
//得不到服務器狀態,而且我們正在請求本地文件,認為成功,200到300間的狀態碼表示成功 304未修改狀態也酸成功 safari在文檔為修改時返回空狀態,,,
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){
//如果該方法返回null的話,則onsuccess回調函數不執行
//組裝返回的對象數據
//抓去響應的http頭部信息
var ct = r.getResponseHeader("content-type");
//檢索返回是否為xml對象
var data = ct && ct.indexOf("xml") >= 0;
//alert(data)
//如果用戶設置要輸出xml,只有在type參數為xml 并且是手動配置的xml才解析response
data = (type == "xml" && hastype ) || data ? r.responseXML : r.responseText;
//因為ie不能解析responsexml
if(((type == "xml" && hastype ) || (ct && ct.indexOf("xml") >= 0) ) && window.ActiveXObject){
//ie下面需要轉換一下
//data=r.responseText;
var doc = new ActiveXObject("MSxml2.DOMDocument")
doc.loadXML(r.responseText);
data=doc;
//避免內存泄漏,清理該文檔
doc=null;
}
//返回json對象
if(type == "json") {
try{
/*return (new Function("return"+data))();*/
var c_obj=(new Function("return"+data))();
if(c_obj.result && c_obj.result == -1){
$.ui.showErr(c_obj.msg);
return null;
} else
return c_obj;
}
catch (e){
alert(e.message)
alert(data);
return null;
//如果alert出了這里,說明組織的json對象的數據結構錯誤,無法解析成對象
}
}
//請求一個script腳本
if(type == "script") {
//eval.call(window,data);//這個不行,被john騙了
var script_o=document.createElement("script");
script_o.nodeValue=data;
script_o.setAttribute("charset","utf-8");
$("head")[0].appendChild(script_o);
}
return data;
};
function getXMLHttpRequest (type){
var xmlHR=false;
if(scope.ActiveXObject){
try {xmlHR=new ActiveXObject("Msxml2.XMLHTTP");}
catch(e){try{xmlHR=new ActiveXObject("Microsoft.XMLHTTP");}
catch(e){try{xmlHR=new ActiveXObject("Msxml2.XmlHttp.4.0");}catch(e){}}}
}else if(scope.XMLHttpRequest){
xmlHR=new XMLHttpRequest();
if(xmlHR.overrideMimeType){
if (!hastype){//如果沒有傳入type參數那么頭定義為html的
xmlHR.overrideMimeType('text/xml');
} else {
switch (type){
case "xml": xmlHR.overrideMimeType('text/xml');
break
case "json":xmlHR.overrideMimeType('text/json');
break
default : xmlHR.overrideMimeType('text/html');
}
}
}
}else{alert("Create XMLHttpRequest object false!");return false;}
return xmlHR;
}
};
})(window);
關鍵的 我來說下我的這個 選擇器啊,這個選擇器和jq最大的不同 ,就是 返回的不是一個jq對象,而是直接返回你所以找到的dom對象 or domlist。其他的,很,很簡單,自己看看吧。 至于domready ?就是$(function(){//這個就是push進ready準備執行的 處理函數了,})
?簡單吧,真的很簡單。
轉載于:https://www.cnblogs.com/litao229/archive/2012/03/08/2385255.html
總結
以上是生活随笔為你收集整理的贡献一个连jquery都觉的大的时候可以用的 js库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 有农村合作医疗还用买医疗保险吗
- 下一篇: C/C++编译预处理指令