我要学习之墨鱼JQ
/** * moyuQuery的大部分API方法名和jQuery保持一致,可以结合jQuery的文档来阅读本库 * www.moyu-edu.com * */ //立即函数自执行 //把window传进来,可以不用每次访问都去全局作用域,提高代码执行速度 //因为在有的低版本IE中undefined的值有可能改写,所以传进来,但是调用的时候实参没有这个,所以保证是正确的undefined ;(function(window,undefined){ //代码9到96行的作用在于选择出来了我们要的一组DOM对象,并存到我们的moyuQuery对象中作为一个属性名为arr的数组中 //moyuQuery构造器 function moyuQuery(str){ //防止非法访问 if(this === window){ return new moyuQuery(str); } //Sizzle解析引擎,模拟jQuery的sizzle function Sizzle(str){ var str = str.toLowerCase(); //如果是类似$("#abc")这样的形式,直接返回,提高性能 var quickMatchIdReg = /^#[a-z]+$/; if(quickMatchIdReg.test(str)){ return [document.getElementById(str)]; } var list = str.split(" "); var eleArr = []; var tempArr = []; for(var i=0;i<list.length;i++){ if(eleArr.length === 0){ eleArr = manipuEasyDom(list[i],document); }else{ tempArr = [];//每次进来执行的时候置空tempArr for(var j=0;j<eleArr.length;j++){ tempArr = tempArr.concat(manipuEasyDom(list[i],eleArr[j])); } eleArr = tempArr; } } // 只考虑了最简单的三种情况选择器 id,class,标签 function manipuEasyDom(str,fatherDom){ var reg1 = /^#(\w+)/;//匹配id var reg2 = /^\.(\w+)/;//匹配class var reg3 = /^\w+/;//匹配标签 var myArr = []; //str代表的是传进来的参数 "#abc" ".abc" "abc" if(reg1.test(str) === true){ var arr = reg1.exec(str); //console.log(arr); var oDiv = fatherDom.getElementById(arr[1]); myArr.push(oDiv); } if(reg2.test(str) === true){ var arr = reg2.exec(str); var aList = fatherDom.getElementsByClassName(arr[1]); myArr = Array.prototype.slice.call(aList,0); } if(reg3.test(str) === true){ var aList = fatherDom.getElementsByTagName(str); myArr = Array.prototype.slice.call(aList,0); } return myArr; } return eleArr; } //判断是 $(function(){})、$("#demo") 还是其他的调用类型 switch(typeof str){ case "function"://如果是$(function(){})这种方式,那就是简写的ready形式 moyuQuery.ready(str); break; case "string"://只考虑像 $("#a div") $(".a div") $("div .item") $("div") $(".item") $("#a")这些形式,不考虑伪类、CSS3选择器 this.arr = Sizzle(str); break; case "object": //说明是用getElementsByTagName,getElementsByClassName选择出来的 if(str.toString().indexOf("Element") > -1){ this.arr = [str]; //说明是用getElementsByTagName,getElementsByClassName选择出来的 }else if(str.toString().indexOf("Collection") > -1){ this.arr = str; //出错了 }else{ return {}; } break; default: //出错了 return {}; break; } } //eq就是等于的意思 //eq(0) --> 把arr数组的第1个拿出来 moyuQuery.prototype.eq = function(num){ return new moyuQuery(this.arr[num]); } //获取第一个元素DOM对象并转换成moyuQuery对象 moyuQuery.prototype.first = function(){ return new moyuQuery(this.arr[0]); } //获取最后一个元素DOM对象并转换成moyuQuery对象 moyuQuery.prototype.last = function(){ return new moyuQuery(this.arr[this.arr.length - 1]); } //求整个moyuQuery对象中的DOM元素的个数 moyuQuery.prototype.length = function(){ return this.arr.length; } //求整个moyuQuery对象中的DOM元素的个数 moyuQuery.prototype.size = moyuQuery.prototype.length; //+++++++++++++++++++++++++++++事件模块开始+++++++++++++++++++++++++++++++++++++++++++ //on相当于给this.arr里所有的元素对象加事件 moyuQuery.prototype.on = function(eventType,fn){ for(var i=0;i<this.arr.length;i++){ this.arr[i].addEventListener(eventType,fn,false); } return this; } //给一些常见的事情设置一些快捷方式,比如click可以直接 $("div").click(function(){})这样用 var eventList = 'click mouseover mouseout mousedown mousemove mouseup keydown keyup dblclick contextmenu input propertychange change blur focus resize scroll load'.split(" "); for(var i=0;i<eventList.length;i++){ //这里用到了闭包的技巧 moyuQuery.prototype[eventList[i]] = (function(eventType){ var eventFn = function(fn){ this.on(eventType,fn); } return eventFn; })(eventList[i]); } //ele.removeEventListener("click",fnName); //off相当于给this.arr里面所有的元素对象移除事件 moyuQuery.prototype.off = function(eventType,fn){ for(var i=0;i<this.arr.length;i++){ this.arr[i].removeEventListener(eventType,fn); } return this; } //类似css中的hover伪类 moyuQuery.prototype.hover = function(fn1,fn2){ for(var i=0;i<this.arr.length;i++){ this.arr[i].addEventListener("mouseenter",fn1,false); this.arr[i].addEventListener("mouseleave",fn2,false); } } //++++++++++++++++++++++++++++++++事件模块结束++++++++++++++++++++++++++++++++++++++++ //++++++++++++++++++++++++++++++++DOM模块开始++++++++++++++++++++++++++++++++++++++++ //show给this.arr里所有的元素让它显示出来 moyuQuery.prototype.show = function(){ for(var i=0;i<this.arr.length;i++){ this.arr[i].style.display = "block"; } return this; } //hide给this.arr里所有的元素让它隐藏出来 moyuQuery.prototype.hide = function(){ console.log(this.arr); for(var i=0;i<this.arr.length;i++){ this.arr[i].style.display = "none"; } return this; } //如果显示,就隐藏,否则显示 moyuQuery.prototype.toggle = function(){ for(var i=0;i<this.arr.length;i++){ this.arr[i].addEventListener("click",function(){ if(getStyle(this).display === "block"){ this.style.display = "none"; }else{ this.style.display = "block"; } },false); } } //获取计算后样式 function getStyle(ele){ if(window.getComputedStyle){ return getComputedStyle(ele); }else{ return ele.currentStyle; } } //如果传进来一个参数是获取,否则是设置 moyuQuery.prototype.css = function(styleName,styleValue){ if(styleValue === undefined){ return getStyle(this.arr[0])[styleName]; }else{ for(var i=0;i<this.arr.length;i++){ this.arr[i].style[styleName] = styleValue; } } } //如果传进来一个参数是获取,否则是设置 moyuQuery.prototype.attr = function(attrName,attrValue){ if(attrValue === undefined){ return this.arr[0].getAttribute(attrName); }else{ for(var i=0;i<this.arr.length;i++){ this.arr[i].setAttribute(attrName,attrValue); } } } //如果传进来一个参数是获取,否则是设置 moyuQuery.prototype.val = function(valName,valValue){ if(valName === undefined){ return this.arr[0][valName]; }else{ for(var i=0;i<this.arr.length;i++){ this.arr[i][valName] = valValue; } } } // 给this.arr里所有的元素加一个className "abc def" moyuQuery.prototype.addClass = function(str){ for(var i=0;i<this.arr.length;i++){ //"abc" "abc def" this.arr[i].className += " " + str; } } //移出类名 moyuQuery.prototype.removeClass = function(str){ for(var i=0;i<this.arr.length;i++){ //"abc def abc" var reg = new RegExp("\\b" + str + "\\b","g"); this.arr[i].className = this.arr[i].className.replace(reg,""); // this.arr[i].className += " " + str; } } //如果存在(不存在)就删除(添加)一个类。 //原型 moyuQuery.prototype.toggleClass = function(str){ for(var i=0;i<this.arr.length;i++){ var reg = new RegExp("\\b" + str + "\\b","g"); "abc def" if(reg.test(this.arr[i].className) === true){ this.arr[i].className = this.arr[i].className.replace(reg,""); }else{ this.arr[i].className += " " + str; } } } // myObj.html("abc"); moyuQuery.prototype.html = function(str){ if(str === undefined){ return this.arr[0].innerHTML; } for(var i=0;i<this.arr.length;i++){ this.arr[i].innerHTML = str; } } //参考innerText的功能 moyuQuery.prototype.text = function(str){ if(str === undefined){ return this.arr[0].innerText; } for(var i=0;i<this.arr.length;i++){ this.arr[i].innerHTML = str; } } //清空moyuQuery中的DOM对象的innerHTML moyuQuery.prototype.empty = function(){ for(var i=0;i<this.arr.length;i++){ this.arr[i].innerHTML = ""; } } //删除moyuQuery中的DOM对象 moyuQuery.prototype.remove = function(){ for(var i=0;i<this.arr.length;i++){ this.arr[i].parentNode.removeChild(this.arr[i]); } } //获取和设置 moyuQuery.prototype.width = function(widthValue){ if(widthValue === undefined){ return getStyle(this.arr[0]).width; }else{ for(var i=0;i<this.arr.length;i++){ this.arr[i].style.width = widthValue + "px"; } } } //获取和设置 moyuQuery.prototype.height = function(heightValue){ if(heightValue === undefined){ return getStyle(this.arr[0]).height; }else{ for(var i=0;i<this.arr.length;i++){ this.arr[i].style.height = heightValue + "px"; } } } moyuQuery.prototype.innerWidth = function(){ var styleObj = getStyle(this.arr[0]); return parseInt(styleObj["width"]) + parseInt(styleObj["paddingLeft"]) + parseInt(styleObj["paddingRight"]); } moyuQuery.prototype.innerHeight = function(){ var styleObj = getStyle(this.arr[0]); return parseInt(styleObj["height"]) + parseInt(styleObj["paddingTop"]) + parseInt(styleObj["paddingBottom"]); } moyuQuery.prototype.outerWidth = function(check){ var styleObj = getStyle(this.arr[0]); if(check === true){ return parseInt(styleObj["width"]) + parseInt(styleObj["paddingLeft"]) + parseInt(styleObj["paddingRight"]) + parseInt(styleObj["borderLeftWidth"]) + parseInt(styleObj["borderRightWidth"]) + parseInt(styleObj["marginLeft"]) + parseInt(styleObj["marginRight"]); }else{ return parseInt(styleObj["width"]) + parseInt(styleObj["paddingLeft"]) + parseInt(styleObj["paddingRight"]) + parseInt(styleObj["borderLeftWidth"]) + parseInt(styleObj["borderRightWidth"]); } } moyuQuery.prototype.outerHeight = function(){ var styleObj = getStyle(this.arr[0]); if(check === true){ return parseInt(styleObj["height"]) + parseInt(styleObj["paddingTop"]) + parseInt(styleObj["paddingBottom"]) + parseInt(styleObj["borderTopWidth"]) + parseInt(styleObj["borderBottomWidth"]) + parseInt(styleObj["marginTop"]) + parseInt(styleObj["marginBottom"]); }else{ return parseInt(styleObj["height"]) + parseInt(styleObj["paddingTop"]) + parseInt(styleObj["paddingBottom"]) + parseInt(styleObj["borderTopWidth"]) + parseInt(styleObj["borderBottomWidth"]); } } //获取当前元素与CSS定位上的父级的偏移量 moyuQuery.prototype.offset = function(){ return { left:this.arr[0].offsetLeft, top:this.arr[0].offsetTop }; } function getPos(ele){ var posObj = { left:ele.offsetLeft + parent.clientLeft - parent.scrollLeft, top:ele.offsetTop + parent.clientTop- parent.scrollTop } var parent = ele.offsetParent; while(parent!=null){ posObj.left += parent.offsetLeft + parent.clientLeft - parent.scrollLeft; posObj.top += parent.offsetTop + parent.clientTop- parent.scrollTop; parent = parent.offsetParent; } return posObj; } // 把moyuQuery中的DOM对象包一层父级 moyuQuery.prototype.position = function(){ return getPos(this.arr[0]); } moyuQuery.prototype.scrollLeft = function(){ return this.arr[0].scrollLeft; } moyuQuery.prototype.scrollTop = function(){ return this.arr[0].scrollTop; } //获取第1个DOM对象与视窗的偏移坐标 moyuQuery.wrap = function(str){ var fragment = document.createDocumentFragment(); var oDiv = document.createElement("div"); fragment.appendChild(oDiv); oDiv.innerHTML = str; var myEle = oDiv.children[0]; for(var i=0;i<this.arr.length;i++){ var myEle1 = myEle.cloneNode(true); this.arr[i].parentNode.insertBefore(myEle1,this.arr[i]); myEle1.appendChild(this.arr[i]); } } //把当前的DOM对象这一层去掉 moyuQuery.prototype.unwrap = function(){ for(var i=0;i<this.arr.length;i++){ //找出来所有的当前DOM对象的子元素,先加到对应的位置,再把当前DOM对象删除掉 var myChildren = this.arr[i].children; for(var j=0;j<myChildren.length;j++){ this.arr[i].parentNode.insertBefore(this.arr[i].children,this.arr[i]); } this.arr[i].parentNode.removeChild(this.arr[i]); } } //++++++++++++++++++++++++++++++++DOM模块结束++++++++++++++++++++++++++++++++++++++++ //++++++++++++++++++++++++++++++++ajax&jsonp模块开始++++++++++++++++++++++++++++++++++++++++ //jsonp方式获取数据 moyuQuery.jsonp = function(link,fn){ window.fn = fn; var oScript = document.createElement("script"); oScript.src = link; } //args代表的是传的参数 moyuQuery.get = function(link,args,fn){ var xhr = null; if(window.XMLHttpRequest){ xhr = new XMLHttpRequest(); }else{ xhr = new ActiveXObject("Microsoft.XMLHTTP"); } xhr.open("GET",link+"?a="+(new Date()).getTime()+"&"+args); xhr.onreadystatechange = function(){ if(xhr.readyState === 4 && xhr.status === 200){ if(typeof fn === "function"){ fn(); } } } xhr.send(null); } //ajax的POST方式提交数据 moyuQuery.post = function(){ var xhr = null; if(window.XMLHttpRequest){ xhr = new XMLHttpRequest(); }else{ xhr = new ActiveXObject("Microsoft.XMLHTTP"); } xhr.open("POST",link); xhr.onreadystatechange = function(){ if(xhr.readyState === 4 && xhr.status === 200){ if(typeof fn === "function"){ fn(); } } } xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xhr.send(args); } //++++++++++++++++++++++++++++++++ajax&jsonp模块结束++++++++++++++++++++++++++++++++++++++++ //缓存数据 moyuQuery.prototype.data = function(valName,valValue){ if(valValue === undefined){ return this[valName]; }else{ this[valName] = valValue; } } //表单序列化 moyuQuery.prototype.serialize = function(){ var list = this.arr[0].getElementsByTagName('*'); var tempStr = ""; for(var i=0;i<list.length;i++){ if(list[i].tagName.toLowerCase() === "input"){ if(list[i].getAttribute("type").search(/text|password|email|date|range|color|url/)){ tempStr += list[i].getAttribute("name") + "=" + list[i].value + "&"; } } } return tempStr.replace(/&$/,""); } //裁剪 moyuQuery.prototype.slice = function(m,n){ this.arr.slice(m,n); return this; } //插件化 moyuQuery.prototype.extend = function(obj){ for(var i in obj){ this[i] = obj[i]; } } //each //fn默认形参 index ele moyuQuery.prototype.each = function(fn){ for(var i=0;i<this.arr.length;i++){ fn.call(window,i,this.arr[i]); } } //当DOM载入就绪可以查询及操纵时绑定一个要执行的函数。 moyuQuery.ready = function(fn){ if(document.addEventListener){ document.addEventListener("DOMContentLoaded",function(){ if(typeof fn === "function"){ fn(); } },false); }else{ document.onreadystatechange = function(evt){ evt = evt || event; if(evt.readyState === "complete"){ if(typeof fn === "functioin"){ fn(); } } } } } moyuQuery.each = function(arr,fn){ for(var i=0;i<arr.length;i++){ fn(i,arr[i]); } } //exObj对象的属性拷贝到srcObj身上 moyuQuery.extend = function(srcObj,exObj){ for(var i in exObj){ srcObj[i] = exObj[i]; } } //检测该字符串是否像数字 moyuQuery.isNumeric = function(str){ if(typeof str === "number"){ return true; } var reg = /^\d+$/; if(reg.test(str)){ return true; }else{ return false; } } //检测是否是数组类型数据 moyuQuery.isArray = function(arr){ if(Object.prototype.toString.call(arr).indexOf("Array") > -1){ return true; }else{ return false; } } moyuQuery.isPlainObject = function(obj){ if(Object.prototype.toString.call(obj) === "[object Object]"){ return true; }else{ return false; } } moyuQuery.type = function(ele){ switch(Object.prototype.toString.call(ele)){ case "[object Array]": return "array"; break; case "[object Date]": return "date"; break; case "[object RegExp]": return "regexp"; break; case "[object String]": return "string"; break; case "[object Function]": return "function"; break; case "[object Number]": return "number"; break; case "[object Boolean]": return "boolean"; break; case "[object Null]": return "null"; case "[object Undefined]": return "undefined"; break; } } moyuQuery.merge = function(arr1,arr2){ return arr1.concat(arr2); } //保证数组中没有元素相同,去重 moyuQuery.unique = function(arr1){ var arr = []; for(var i=0;i<arr1.length;i++){ if(arr.indexOf(arr1[i]) === -1){ arr.push(arr[i]); } } return arr; } moyuQuery.makeArray = function(list){ return Object.prototype.slice.call(list); } moyuQuery.inArray = function(item,arr){ if(arr.indexOf(item) > -1){ return true; }else{ return false; } } //过滤函数 moyuQuery.grep = function(arr,fn){ var myArr = []; for(var i=0;i<arr.length;i++){ if(fn(arr[i]) === true){ myArr.push(arr[i]); } } return myArr; } moyuQuery.noop = function(){} moyuQuery.trim = function(str){ var reg = /^\s+|\s+$/g; return str.replace(reg,""); } moyuQuery.map = function(arr,fn){ var newArr = []; for(var i=0;i<arr.length;i++){ newArr.push(fn(arr[i])); } return newArr; } //把"background-color"转换成"backgroundColor" moyuQuery.camelCase = function(str){ var reg = /-(\w)/g; return str.replace(reg,function(a,b){ return b.toUpperCase(); }); } //检查元素的 moyuQuery.now = function(){ return (new Date()); } //防冲突 moyuQuery._$ = window.$; moyuQuery.noConflict = function(){ window.$ = moyuQuery._$; } moyuQuery.VERSION = "0.01"; //var a = 1; //window.a = a; //暴露给全局只有moyuQuery和$对象 window.moyuQuery = moyuQuery;//设置了一个全局变量名字叫$,值是moyuQuery window.$ = moyuQuery }(window));