<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<!--div*3>div.wrap*3>input*3-->
<div>
<div class="wrap">
<input type="text">
<input type="text">
<input type="text">
</div>
<div class="wrap">
<input type="text">
<input type="text">
<input type="text">
</div>
<div class="wrap">
<input type="text">
<input type="text">
<input type="text">
</div>
</div>
<div>
<div class="wrap">
<input type="text">
<input type="text">
<input type="text">
</div>
<div class="wrap">
<input type="text">
<input type="text">
<input type="text">
</div>
<div class="wrap">
<input type="text">
<input type="text">
<input type="text">
</div>
</div>
<div>
<div class="wrap">
<input type="text">
<input type="text">
<input type="text">
</div>
<div class="wrap">
<input type="text">
<input type="text">
<input type="text">
</div>
<div class="wrap">
<input type="text">
<input type="text">
<input type="text">
</div>
</div>
<script type="text/javascript">
//参数分三种情况:
//1. 字符串: 选择器
//2. function: ready方法
//3. 原生对象: 原生对象转JQ对象
function JQ(arg) {
//用来放原生对象的数组
this.elements = [];
switch(typeof arg) {
case "string":
this.elements = getEle(arg);
break;
case "function":
ready(arg);
break;
case "object":
this.elements.push(arg);
break;
}
}
//JQ对象转原生
JQ.prototype.get = function(index) {
return this.elements[index];
}
//eq: 从JQ对象中取出某一个原生对象, 再转成新的JQ对象
JQ.prototype.eq = function(index) {
return new JQ(this.elements[index]);
}
function ready(fn) {
//DOMContentLoaded DOM加载完成之后浏览器发出的通知
if(window.addEventListenner) {
window.addEventListenner("DOMContentLoaded", fn, false);
} else {
//defer表示当dom加载完成之后再去加载script标签
//ie8之前, 了解即可
var script = document.createElement("script");
script.defer = true;
var head = document.getElementsByTagName('head')[0];
script.onreadystatechange = function() {
if(script.readystate == "complete") {
fn();
}
}
}
return window;
}
/*
//$("div")当JQ的参数只有一级选择器的时候
function getEle(selector) {
//1. 去掉首尾空格
var reg = /^\s+|\s+$/g;
selector.replace(reg, "");
//2. 判断选择器类型
if (/^#/.test(selector)) {
//id选择器
return document.getElementById(selector);
}else if (/^./.test(selector)) {
//class选择器
return getEleByClass(selector);
}else{
return document.getElementsByTagName(selector);
}
}
*/
//$("xx xx xx")多级选择器的情况
function getEle(selector) {
var reg = /^\s+|\s+$/g;
selecter = selector.replace(reg, "");
//arr = [xx,xx,xx];
var arr = selector.split(" ");
//
var parents = [document];
var children = [];
// 以$("div .wrap input")为例
// 第一次循环:arr[i]是div,parents是document,children里是当前文档里所有的div
// 第二次循环:arr[i]是.wrap,parents是div,children里是所有的div>.wrap
// 第三次循环:arr[i]是input,parents是.wrap,children里是所有的div>.wrap>input
for(var i = 0; i < arr.length; i++) {
children = [];
for(var j = 0; j < parents.length; j++) {
// 查找class
if(/^\./.test(arr[i])) {
var nodes = getEleByClass(parents[j], arr[i].substr(1));
// children = nodes;
for(var k = 0; k < nodes.length; k++) {
children.push(nodes[k]);
}
// 查找id
} else if(/^#/.test(arr[i])) {
var node = parents[j].getElementById(arr[i].substr(1));
children.push(node);
// 查找标签名
} else {
var nodes = parents[j].getElementsByTagName(arr[i]);
for(var k = 0; k < nodes.length; k++) {
children.push(nodes[k]);
}
}
}
parents = children;
}
return children;
}
//因为getElementsByClassName存在兼容性, 所以单独处理
function getEleByClass(parentObj, selector) {
//现代浏览器
if(parentObj.getElementsByClassName) {
return parentObj.getElementsByClassName(selector);
} else {
//mark jq效率
//ie, 不支持直接根据className查找, 所以需要一个一个遍历
var nodes = parentObj.getElementsByTagName("*");
var arr = [];
for(var i = 0; i < nodes.length; i++) {
if(nodes[i].className == selector) {
arr.push(nodes[i]);
}
}
return arr;
}
}
/******************************* 事件 *********************************/
// 两个参数
// 1.事件名
// 2.回调函数
JQ.prototype.on = function(eventName,fn){
for(var i = 0; i < this.elements.length; i++){
addEvent(eventName,this.elements[i],fn);
}
}
JQ.prototype.click = function(fn){
for (var i = 0; i < this.elements.length; i++) {
addEvent('click',this.elements[i],fn);
}
}
// 因为addEventListen存在兼容性问题,IE8之前用attachEvent
function addEvent(eventName,obj,fn){
// 现代浏览器
if (obj.addEventListener) {
obj.addEventListener(eventName,fn,false);
}else{
// IE8以下
obj.attachEvent("on" + eventName,fn);
}
}
/******************************* CSS *********************************/
JQ.prototype.css = function(){
// css使用时参数有两种情况
// 1. 一个参数时有两种情况:
// 1.1 字符串$("div").css("color")表示取值
// 1.2 对象$("div").css({color:red})表示给样式赋值
// 2. 两个参数为直接给一个样式赋值$("div").css("color","red")
switch (arguments.length){
case 1:
// $("div").css({"color":red,"width":100})
if (typeof(arguments[0]) == "object") {
for (prop in arguments[0]) {
for (var i = 0; i < this.elements.length; i++) {
// prop = color,arguments[0]["color"] = red
setStyle(this.elements[i],prop,arguments[0][prop])
}
}
}else{
// 从样式中取值
// 可能jq对象中有多个原生对象,只取第一个的样式
return getStyle(this.elements[0],arguments[0])
}
break;
case 2:
for (var i = 0; i < this.elements.length; i++) {
// $("div").css("color","red");
setStyle(this.elements[i],arguments[0],arguments[1]);
}
break;
}
}
// 获取样式
// 1. 要获取样式的对象
// 2. 样式名
function getStyle(obj,styleName){
if (window.getComputedStyle) {
return window.getComputedStyle(obj,null)[styleName];
}else{
// IE
return obj.currentStyle(styleName);
}
}
// 设置样式
// 1. 要赋值的对象
// 2. 样式名
// 3. 样式的值
function setStyle(obj,styleName,styleValue){
var arr = ["left", "top", "width", "height"];
for (var i = 0; i < arr.length; i++) {
// 如果要设置的样式在数组的范围内,表示需要带"px"
if (arr[i] == styleName) {
// 如果值中没有"px"的话,添加"px"
if (!/px/.test(styleValue)) {
styleValue = styleValue + "px";
}
}
}
obj.style[styleName] = styleValue;
}
function $(arg) {
return new JQ(arg);
}
// 测试
console.log($("div .wrap input"));
$("div").on("click",function(){
alert("不约");
})
$("div").click(function(){
alert("啊 不约");
})
$("div").css("backgroundColor","red");
$("div").css({
backgroundColor:"yellow"
})
</script>
</body>
</html>