(function( window, undefined ) { // jQuery 代码 })(window);
var jQuery = (function() { // 创建 jQuery 对象 var jQuery = function( selector, context ) { // 略 }; // 创建 jQuery.fn 对象 jQuery.fn = jQuery.prototype = { // 略 }; // 声明 jQuery.extend jQuery.extend = jQuery.fn.extend = function() { // 略 }; // 使用 jQuery.extend 扩展自己 jQuery.extend({ // 略 }); // 浏览器方面的一些琐碎 // 略 // 定义全局对象 return (window.jQuery = window.$ = jQuery); })();
var jQuery = function( selector, context ) { // 实际上 jQuery 对象是 jQuery.fn.init 返回的。 return new jQuery.fn.init( selector, context, rootjQuery ); }
init: function( selector, context, rootjQuery ) { // 参数: selector 选择器 // context 上下文 // rootjQuery 父节点 // 处理 $("")、 $(null) 和 $(undefined) if ( !selector ) { return this; } // 处理 $(DOMElement) if ( selector.nodeType ) { // 直接扔数组中, 就搞定了。 this.context = this[0] = selector; this.length = 1; return this; } // 处理 $("body") body 元素只存在一次,单独找它 if ( selector === "body" && !context && document.body ) { // 同样扔数组中, 顺便把 selector 更新更新。 this.context = document; this[0] = document.body; thisis.selector = "body"; this.length = 1; return this; } // 处理 $(HTML 代码 或者是 css 选择器) if ( typeof selector === "string" ) { // 略 // 处理 $(函数) } else if ( jQuery.isFunction( selector ) ) { // 如果是函数,则执行 $(document).ready , 这样 $(document).ready(func) 简为 $(func) return rootjQuery.ready( selector ); } // 略。 // 如果传入的是一个 Dom列表 ( getElementsByTagName 结果 ) 则转为 jQuery 数组。 return jQuery.makeArray( selector, this ); }
// 这部分代码是 上段中 略 的 也就是说是 jQuery(字符串) 处理。 // 检查是否字符串是常用选择器 (/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/) match = quickExpr.exec( selector ); // 检查是否正确匹配 if ( match && (match[1] || !context) ) { // 处理: $(html) -> $(array) if ( match[1] ) { // 获取正文,默认 document context = context instanceof jQuery ? context[0] : context; doc = (context ? context.ownerDocument || context : document); // 如果传入简单的 "<标签>", ( /^<(\w+)\s*\/?>(?:<\/\1>)?$/) ret = rsingleTag.exec( selector ); // 返回 createElement("tag") return jQuery.merge( this, selector ); // 处理: $("#id") } else { elem = document.getElementById( match[2] ); // 因为有的浏览器 getElementById 不只返回 id匹配的,所以做检查。 return this; } // 处理 $("标签") } else if ( !context && !rnonword.test( selector ) ) { this.selector = selector; this.context = document; selector = document.getElementsByTagName( selector ); return jQuery.merge( this, selector ); //处理: $(选择器, $(...)) } else if ( !context || context.jquery ) { return (context || rootjQuery).find( selector ); // 处理: $(选择器, 上下文) // (相当于: $(上下文).find(选择器) } else { return this.constructor( context ).find( selector ); }
noConflict: function( deep ) { window.$ = _$; if ( deep ) { window.jQuery = _jQuery; } return jQuery; },
bindReady: function() { // 如果已经执行 bindReady 则返回。 if ( readyBound ) { return; } readyBound = true; // 如果页面已经加载, 马上执行 jQuery.ready if ( document.readyState === "complete" ) { return setTimeout( jQuery.ready, 1 ); } // 标准浏览器支持 DOMContentLoaded if ( document.addEventListener ) { // 你懂的 document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); // 为什么还要 load ? , 因为有些时候 DOMContentLoaded 失败(如 iframe) ,而 load 总是会成功, 所以,同时处理 DOMContentLoaded load, 在 jQuery.ready 中会删除监听函数,保证最后这个函数只执行一次 window.addEventListener( "load", jQuery.ready, false ); // IE浏览器( IE 8 以下) } else if ( document.attachEvent ) { // 使用 onreadystatechange document.attachEvent("onreadystatechange", DOMContentLoaded); // 同理 window.attachEvent( "onload", jQuery.ready ); // 如果 IE 下且非 iframe, 这里有个技巧。 见 doScrollCheck(); // 原理: 浏览器在没加载时 设置 scrollLeft 会错误,所哟每隔1秒厕所 是否 scrollLeft 成功,如果发现成功,则执行 jQuery.ready 。但这只对非 frame 会有用。 var toplevel = false; try { toplevel = window.frameElement == null; } catch(e) {} if ( document.documentElement.doScroll && toplevel ) { doScrollCheck(); } } },
attr: function( elem, name, value, pass ) { // 检查是否为 nodeType 为 Element if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) { return undefined; } // 如果这个属性需要特殊对待。 height/width/left 等属性需特殊计算 if ( pass && name in jQuery.attrFn ) { return jQuery(elem)[name](value); } // 检查是否为 XML 还 HTML var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), // Whether we are setting (or getting) set = value !== undefined; // 修正名字, 比如 float 改 cssFloat name = notxml && jQuery.props[ name ] || name; // 只有在节点的时候执行。 if ( elem.nodeType === 1 ) { // 在 IE7- 下, href src 属性直接获取会返回绝对位置,而不是真实的位置字符串, // 要获得它们的真实值,需要 elem.getAttribute("href", 2); var special = rspecialurl.test( name ); // Safari 误报默认选项。通过获取父元素的已选择索引来修复。 if ( name === "selected" && !jQuery.support.optSelected ) { var parent = elem.parentNode; if ( parent ) { parent.selectedIndex; // 对 optgroups ,同理 if ( parent.parentNode ) { parent.parentNode.selectedIndex; } } } // 检查属性是否存在, 有些时候 name in elem 会失败,所以多次测试。 if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) { // 如果设置属性 if ( set ) { // 在IE, 不能设置属性 type 。 if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { jQuery.error( "type property can't be changed" ); } // 如果 value === null, 表示移除属性 if ( value === null ) { if ( elem.nodeType === 1 ) { elem.removeAttribute( name ); } } else { // 一切属性设置就是1句话。。。 elem[ name ] = value; } } // 表单索引元素获取需要 getAttributeNode( name ).nodeValue if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { return elem.getAttributeNode( name ).nodeValue; } // elem.tabIndex 特殊处理 if ( name === "tabIndex" ) { var attributeNode = elem.getAttributeNode( "tabIndex" ); return attributeNode && attributeNode.specified ? attributeNode.value : rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? 0 : undefined; } return elem[ name ]; } // 处理 style 属性 if ( !jQuery.support.style && notxml && name === "style" ) { if ( set ) { elem.style.cssText = "" + value; } return elem.style.cssText; } if ( set ) { // 这里除了 IE, 其它属性使用标准 setAttribute elem.setAttribute( name, "" + value ); } // 如果属性不存在,返回 undefined, 而不是 null 或 "" 之类的。 if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) { return undefined; } // 见上 var attr = !jQuery.support.hrefNormalized && notxml && special ? // Some attributes require a special call on IE elem.getAttribute( name, 2 ) : elem.getAttribute( name ); // 同上 return attr === null ? undefined : attr; } // 如果不是 DOM 元素,检查处理。 if ( set ) { elem[ name ] = value; } return elem[ name ]; }
add: function( elem, types, handler, data ) { // 只对节点操作。 if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } // IE 无法传递 window,而是复制这个对象 。 if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) { elem = window; } // 如果 handler === false, 也就是说就是阻止某事件, // 这样只要 bind("evt", false); 就是阻止此事件。 if ( handler === false ) { handler = returnFalse; } else if ( !handler ) { return; } // handleObjIn 是内部处理句柄, handleObj 是直接使用的处理句柄。 var handleObjIn, handleObj; if ( handler.handler ) { handleObjIn = handler; handler = handleObjIn.handler; } // 为函数生成唯一的 guid 。具体下面介绍。 if ( !handler.guid ) { handler.guid = jQuery.guid++; } // 获取一个节点的数据。 var elemData = jQuery.data( elem ); // 如果没有数据,则直接返回。 if ( !elemData ) { return; } // 避免和原生的js对象混淆。 var eventKey = elem.nodeType ? "events" : "__events__", // 这里就是关键。 // elemData 是存储数据的位置, 而 elemData[ eventKey ] 就是存储当前事件的对象。 elemData.handle 就是当前绑定的所有函数数组。 // 也就是说,当我们绑定一个函数时,会往 elemData.handle 放这个函数,然后事件触发时,会遍历 elemData.handle 中函数然后去执行。 // 肯能有人会问,为什么这么做,因为原生的DOM内部也有一个 函数数组,事件触发后会执行全部函数。答案还是 兼容。 // 标准浏览器使用 addEventListener // IE 使用 attachEvent // 而这2者还是有差距的。因为 addEventListener 执行函数的顺序即添加函数的顺序,然而 attachEvent 执行函数的顺序和添加的顺序是相反的。 // jQuery 使用自定义的 handler 数组,好处有: // 因为最后仅绑定一次原生事件,事件触发后,手动执行 数组中的函数。这样保证兼容。 // 同时也可以知道到底绑定了什么函数,可以方便 trigger 函数的完成。 events = elemData[ eventKey ], eventHandle = elemData.handle; // 一些功能。。 if ( typeof events === "function" ) { eventHandle = events.handle; events = events.events; } else if ( !events ) { if ( !elem.nodeType ) { elemData[ eventKey ] = elemData = function(){}; } elemData.events = events = {}; } // 如果是第一次执行,需创建 eventHandle if ( !eventHandle ) { // eventHandle 就是真正绑定到原生事件的那个函数,这个函数用来执行events.hadlers 用。 elemData.handle = eventHandle = function() { // Handle the second event of a trigger and when // an event is called after a page has unloaded return typeof jQuery !== "undefined" && !jQuery.event.triggered ? jQuery.event.handle.apply( eventHandle.elem, arguments ) : undefined; }; } // 绑定函数和原生,这样可以保证函数可执行为目前作用域。 eventHandle.elem = elem; // 处理 jQuery(...).bind("mouseover mouseout", fn); types = types.split(" "); var type, i = 0, namespaces; while ( (type = types[ i++ ]) ) { handleObj = handleObjIn ? jQuery.extend({}, handleObjIn) : { handler: handler, data: data }; // 略 // 绑定 type guid handleObj.type = type; if ( !handleObj.guid ) { handleObj.guid = handler.guid; } // 获取当前的函数数组。 var handlers = events[ type ], special = jQuery.event.special[ type ] || {}; // 如果第一次,则创建这个数组。 if ( !handlers ) { handlers = events[ type ] = []; // 特殊事件要执行 setup 而不是标准 addEventListener。 // 此行用来支持自定义的事件。 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { // 标准事件。 这里绑定的为 eventHandle if ( elem.addEventListener ) { elem.addEventListener( type, eventHandle, false ); } else if ( elem.attachEvent ) { elem.attachEvent( "on" + type, eventHandle ); } } } // 自定义事件,执行 add if ( special.add ) { special.add.call( elem, handleObj ); if ( !handleObj.handler.guid ) { handleObj.handler.guid = handler.guid; } } // 不管是不是首次,都放入目前绑定的函数。 handlers.push( handleObj ); // 为实现 trigger 。 jQuery.event.global[ type ] = true; } // 让IE下可以正常回收 elem 内存。 elem
- 全部评论(0)
- 商品推荐
机械节能产品生产企业官网模板...
¥20.00大气智能家居家具装修装饰类企业通用网站模板...
¥20.00礼品公司网站模板
¥25.00宽屏简约大气婚纱摄影影楼模板...
¥25.00蓝白WAP手机综合医院类整站源码(独立后台)...
¥25.00
苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有