var nodeHook, boolHook,
rclass = /[\t\r\n\f]/g,
rreturn = /\r/g,
rfocusable = /^(?:input|select|textarea|button)$/i; jQuery.fn.extend({
attr: function( name, value ) {
//遍历this
//arguments.length > 1,jQuery.attr(this[i],name,value),返回this
//arguments.length <= 1,jQuery.attr(this[i],name,value),返回this
return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
}, removeAttr: function( name ) {
return this.each(function() {
jQuery.removeAttr( this, name );
});
}, prop: function( name, value ) {
return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
}, removeProp: function( name ) {
return this.each(function() {
delete this[ jQuery.propFix[ name ] || name ];
});
}, //$('.div1').addClass('box2 box3');
addClass: function( value ) {
var classes, elem, cur, clazz, j,
i = 0,
len = this.length,
proceed = typeof value === "string" && value;//是字符串返回字符串,不是返回flase
/*
$('div').addClass( function(index){
alert(index);
return 'box'+index;
});
*/
if ( jQuery.isFunction( value ) ) {
console.log(this);//这里的this是jQuery对象,Object { 0: <div#div1.box>, 1: <div#div2.box>, 2: <div#div3.box>, length: 3},通过return ( context || rootjQuery ).find('.div1')原生方法获得,里面每一个是节点对象不是jQuery对象
return this.each(function( j ) {
console.log(this);//这里不是jQuery对象是dom节点对象,<div id='div1'></div>,<div id='div2'></div>,<div id='div3'></div>
console.log(jQuery( this ));//jQuery( this )是jQuery对象,Object { 0: <div#div1.box>, context: <div#div1.box>, length: 1 },Object { 0: <div#div2.box>, context: <div#div2.box>, length: 1 },Object { 0: <div#div3.box>, context: <div#div3.box>, length: 1 }
/*jQuery( this )走的是
if ( selector.nodeType ) {//节点都有nodeType属性
this.context = this[0] = selector;
this.length = 1;
return this;*/
jQuery( this ).addClass( value.call( this, j, this.className ) );
});
}
if ( proceed ) {
// 把字符串正则分割成数组
classes = ( value || "" ).match( core_rnotwhite ) || [];
for ( ; i < len; i++ ) {
elem = this[ i ];
//不是元素节点返回false,elem.className元素有没有class属性,有就合并(重复不合并),cur是之前的class
cur = elem.nodeType === 1 && ( elem.className ?
//非空格转换成空格
( " " + elem.className + " " ).replace( rclass, " " ) :
" "
);
if ( cur ) {
j = 0;
while ( (clazz = classes[j++]) ) {
if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
cur += clazz + " ";
}
}//前后去空格
elem.className = jQuery.trim( cur );
}
}
}
return this;
}, removeClass: function( value ) {
var classes, elem, cur, clazz, j,
i = 0,
len = this.length,
//先执行&&再||,proceed为true参数长度是0删除所有或者参数是字符串,为false传的不是字符串
proceed = arguments.length === 0 || typeof value === "string" && value;
if ( jQuery.isFunction( value ) ) {
return this.each(function( j ) {
jQuery( this ).removeClass( value.call( this, j, this.className ) );
});
}
if ( proceed ) {
classes = ( value || "" ).match( core_rnotwhite ) || [];
for ( ; i < len; i++ ) {
elem = this[ i ];
// This expression is here for better compressibility (see addClass)
cur = elem.nodeType === 1 && ( elem.className ?
( " " + elem.className + " " ).replace( rclass, " " ) :
""
);
if ( cur ) {
j = 0;
while ( (clazz = classes[j++]) ) {
// Remove *all* instances
while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
cur = cur.replace( " " + clazz + " ", " " );
}
}
elem.className = value ? jQuery.trim( cur ) : "";
}
}
}
return this;
}, toggleClass: function( value, stateVal ) {
var type = typeof value;
//$('#div1').toggleClass('box2 box3',true);//有没有都是add
//$('#div1').toggleClass('box2 box3',false);//有没有都是删除
if ( typeof stateVal === "boolean" && type === "string" ) {//真就添加,假就删除
return stateVal ? this.addClass( value ) : this.removeClass( value );
} if ( jQuery.isFunction( value ) ) {
return this.each(function( i ) {
jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
});
}
//$('#div1').toggleClass('box2 box3')
return this.each(function() {
if ( type === "string" ) {
// toggle individual class names
var className,
i = 0,
self = jQuery( this ),//转成jQuery对象,hasClass是jQuery对象的方法。
//空格分割成数组
classNames = value.match( core_rnotwhite ) || []; while ( (className = classNames[ i++ ]) ) {
// check each className given, space separated list
if ( self.hasClass( className ) ) {
self.removeClass( className );
} else {
self.addClass( className );
}
} // Toggle whole class name
//$('#div1').toggleClass(false);
} else if ( type === core_strundefined || type === "boolean" ) {
if ( this.className ) {
// store className if set
data_priv.set( this, "__className__", this.className );
} // If the element has a class name or if we're passed "false",
// then remove the whole classname (if there was one, the above saved it).
// Otherwise bring back whatever was previously saved (if anything),
// falling back to the empty string if nothing was stored.
this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || "";
}
});
}, hasClass: function( selector ) {
var className = " " + selector + " ",
i = 0,
l = this.length;
for ( ; i < l; i++ ) {
if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
return true;
}
} return false;
}, val: function( value ) {
var hooks, ret, isFunction,
elem = this[0];
//$('#input1').val()
if ( !arguments.length ) {//获取
if ( elem ) {//只获取第一个元素
//hooks兼容处理,jQuery.valHooks[ elem.type ]在valHooks 这个json中找不到就找jQuery.valHooks[ elem.nodeName.toLowerCase() ]
hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
/*
valHooks: {
hooks = option: { //elem.type || elem.nodeName.toLowerCase()
get: function( elem ) {}
},
hooks = select: {
get: function( elem ) {},
set: function( elem, value ) {}
}
下面的:
hooks = radio: {
set: function( elem ) {}
get: function( elem, value ) {}
},
hooks = checkbox: {
set: function( elem ) {},
get: function( elem, value ) {}
}
}
*/
if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
return ret;
}
//不再hooks里面
ret = elem.value; return typeof ret === "string" ?
// handle most common string cases
ret.replace(rreturn, "") :
// handle cases where value is null/undef or number
ret == null ? "" : ret;
} return;
}
//设置
isFunction = jQuery.isFunction( value ); return this.each(function( i ) {
var val;
if ( this.nodeType !== 1 ) {
return;
}
if ( isFunction ) {
val = value.call( this, i, jQuery( this ).val() );
} else {
val = value;
}
// Treat null/undefined as ""; convert numbers to string
if ( val == null ) {//$('#input1').val(null);
val = "";
} else if ( typeof val === "number" ) {//$('#input1').val(123123);
val += "";//转成字符串
} else if ( jQuery.isArray( val ) ) {//$('#input2').val(['hello']);
val = jQuery.map(val, function ( value ) {
return value == null ? "" : value + "";
});
}
hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
// If set returns undefined, fall back to normal setting
if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
this.value = val;
}
});
}
}); jQuery.extend({//静态属性只能通过jQuery静态方式调
valHooks: {//option-get,select-get.select-set 兼容性处理
option: {
get: function( elem ) {
// attributes.value is undefined in Blackberry 4.7 but
// uses .value. See #6932
var val = elem.attributes.value;
//val不存在输出elem.value,val存在specified为false走elem.text
return !val || val.specified ? elem.value : elem.text;
}
},
select: {
//$('select').val()
get: function( elem ) {
var value, option,
options = elem.options,//下拉选项
index = elem.selectedIndex,//当前索引值
//select只选了一个或者没有选,one为true,就是单选
one = elem.type === "select-one" || index < 0,
//one为true时单选values是空,one是false时多选values是一个数组存储所有的选择的多个
values = one ? null : [],
//单选时max是当前索引加1,多选时是下拉选项的长度
max = one ? index + 1 : options.length,
//
i = index < 0 ?
max /*index < 0没有选择时one=true,i=max=0*/
:one ?
index/*index >= 0有选择时,select-one单选one=true,i=index,max=index+1,*/
:0 /*index >= 0有选择时,不是select-one多选one=false,i=0,max=options.length*/
; // 没有选择不进入循环,不获取select的val()
//有选择单选,i=index,只获取index的val()
//有选择好多选,全部获取
for ( ; i < max; i++ ) {
option = options[ i ];//js对象 // IE6-9 doesn't update selected after form reset (#2551)
if ( ( option.selected || i === index ) &&
// Don't return options that are disabled or in a disabled optgroup
( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { // Get the specific value for the option
value = jQuery( option ).val();//转成jQuery对象 // We don't need an array for one selects
if ( one ) {
return value;
} // Multi-Selects return an array
values.push( value );
}
} return values;
},
// $('#select').val(111);//111被选中了
set: function( elem, value ) {
var optionSet, option,
options = elem.options,//所有的下拉选项,js对象
values = jQuery.makeArray( value ),//转成数组
i = options.length; while ( i-- ) {//遍历
option = options[ i ];
if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) {//在数组里面就把她设为选中
optionSet = true;
}
} // force browsers to behave consistently when non-matching value is set
if ( !optionSet ) {//都没有
elem.selectedIndex = -1;
}
return values;
}
}
}, attr: function( elem, name, value ) {
var hooks, ret,
nType = elem.nodeType; // 节点不存在,或者文本、属性、注释节点
if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
return;
} // core_strundefined = typeof undefined,
if ( typeof elem.getAttribute === core_strundefined ) {
//$(document).attr('title','hello'); 走这里通过.设置
return jQuery.prop( elem, name, value );
} // 1是元素节点,
if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
name = name.toLowerCase();
//只有type才做兼容性处理
hooks = jQuery.attrHooks[ name ] ||
//$('input').attr('checked',true);//没问题,做兼容了
( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
} if ( value !== undefined ) {//设置
//$('#div1').attr('miaov',null); 调用remove
if ( value === null ) {
jQuery.removeAttr( elem, name );
//hooks中,set方法存在,就调用set方法并且返回值存在,就返回返回值
} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
return ret;//有兼容性执行兼容操作,返回值 } else {//没有兼容性操作设置值
elem.setAttribute( name, value + "" );
return value;
}
//hooks中,get方法存在,就调用get方法并且返回值存在,就返回返回值
} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {//获取,有兼容性返回值
return ret; } else {//获取没有兼容性时
ret = jQuery.find.attr( elem, name ); // Non-existent attributes return null, we normalize to undefined
return ret == null ?
undefined :
ret;
}
}, removeAttr: function( elem, value ) {
var name, propName,
i = 0,
//$('#div1').removeAttr('maio href id');
attrNames = value && value.match( core_rnotwhite );//core_rnotwhite = /\S+/g, 非空格,返回数组 if ( attrNames && elem.nodeType === 1 ) {
while ( (name = attrNames[i++]) ) {
/*
propFix: {
"for": "htmlFor",
"class": "className"
},
*/// $('#div1').removeAttr('class');
propName = jQuery.propFix[ name ] || name; // Boolean attributes get special treatment (#10870)
if ( jQuery.expr.match.bool.test( name ) ) {
// $('#div1').removeAttr('checked');
elem[ propName ] = false;
} elem.removeAttribute( name );//调用原生
}
}
},
//hooks = jQuery.attrHooks[ name ]
attrHooks: {
type: {//只有name = 'type',才会有有兼容性判断。
set: function( elem, value ) {//只有set说明兼容只是针对设置没有获取
if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {//单选值的兼容
// Setting the type on a radio button after the value resets the value in IE6-9
// Reset value to default in case type is set after value during creation //当设置type = 'radio'时IE会有兼容性问题,所以要先设置类型才设置值
var val = elem.value;
elem.setAttribute( "type", value );
if ( val ) {
elem.value = val;
}
return value;
}
}
}
}, propFix: {
"for": "htmlFor",
"class": "className"
}, prop: function( elem, name, value ) {
var ret, hooks, notxml,
nType = elem.nodeType; // don't get/set properties on text, comment and attribute nodes
if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
return;
} notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); if ( notxml ) {
// Fix name and attach hooks
name = jQuery.propFix[ name ] || name;
hooks = jQuery.propHooks[ name ];//兼容性处理
} if ( value !== undefined ) {//设置值
return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
ret :
( elem[ name ] = value );//prop使用的是.操作 } else {//获取值
return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
ret :
elem[ name ];
}
}, propHooks: {
tabIndex: {//光标切换顺序,只对tabIndex属性做兼容
get: function( elem ) {//只对get方法做兼容
return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ?
elem.tabIndex :
-1;
}
}
}
}); // Hooks for boolean attributes
boolHook = {
set: function( elem, value, name ) {
if ( value === false ) {
// Remove boolean attributes when set to false
jQuery.removeAttr( elem, name );
} else {
elem.setAttribute( name, name );
}
return name;
}
};
jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr; jQuery.expr.attrHandle[ name ] = function( elem, name, isXML ) {
var fn = jQuery.expr.attrHandle[ name ],
ret = isXML ?
undefined :
/* jshint eqeqeq: false */
// Temporarily disable this handler to check existence
(jQuery.expr.attrHandle[ name ] = undefined) !=
getter( elem, name, isXML ) ? name.toLowerCase() :
null; // Restore handler
jQuery.expr.attrHandle[ name ] = fn; return ret;
};
}); // Support: IE9+
// Selectedness for an option in an optgroup can be inaccurate
if ( !jQuery.support.optSelected ) {
jQuery.propHooks.selected = {
get: function( elem ) {
var parent = elem.parentNode;
if ( parent && parent.parentNode ) {
parent.parentNode.selectedIndex;
}
return null;
}
};
} jQuery.each([
"tabIndex",
"readOnly",
"maxLength",
"cellSpacing",
"cellPadding",
"rowSpan",
"colSpan",
"useMap",
"frameBorder",
"contentEditable"
], function() {
//value = callback.call( obj[ i ], i, obj[ i ] );
jQuery.propFix[ this.toLowerCase() ] = this;
}); /*
valHooks: {
hooks = radio: {
set: function( elem ) {}
get: function( elem, value ) {}
},
hooks = checkbox: {
set: function( elem ) {},
get: function( elem, value ) {}
}
}
*/
jQuery.each([ "radio", "checkbox" ], function() {
jQuery.valHooks[ this ] = {
//$('#radio').val(['hello']);
set: function( elem, value ) {
if ( jQuery.isArray( value ) ) {
return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );//设置选中状态
}
}
};
if ( !jQuery.support.checkOn ) {
//有的话做处理,没有不做处理 //获取单选框和复选框的value值时绝大多数浏览器返回的都是on,有些是空的,
jQuery.valHooks[ this ].get = function( elem ) {
// Support: Webkit
// "" is returned instead of "on" if a value isn't specified
return elem.getAttribute("value") === null ? "on" : elem.value;
};
}
});

jQuery07源码 (3803 , 4299) attr() prop() val() addClass()等 : 对元素属性的操作的更多相关文章

  1. jquery13 attr() prop() val() addClass()等 : 对元素属性的操作

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  2. jquery之 css()方法。用法类似的有attr(),prop(),val()

    [注]attr(),prop(),val()的用法结构和css()一致,可参考 css()函数用于设置或返回当前jQuery对象所匹配的元素的css样式属性值. 该函数属于jQuery对象(实例).如 ...

  3. jQuery.attributes源码分析(attr/prop/val/class)

    回顾 有了之前的几篇对于jQuery.attributes相关的研究,是时候分析jQuery.attr的源码了 Javascript中的attribute和property分析 attribute和p ...

  4. jquery源码解析:attr,prop,attrHooks,propHooks详解

    我们先来看一下jQuery中有多少个方法是用来操作元素属性的. 首先,看一下实例方法: 然后,看下静态方法(工具方法): 静态方法是内部使用的,我们外面使用的很少,实例方法才是对外的. 接下来,我们来 ...

  5. jQuery源码-jQuery.fn.attr与jQuery.fn.prop

    jQuery.fn.attr.jQuery.fn.prop的区别 假设页面有下面这么个标签,$('#ddd').attr('nick').$('#ddd').prop('nick')分别会取得什么值? ...

  6. 一个由正则表达式引发的血案 vs2017使用rdlc实现批量打印 vs2017使用rdlc [asp.net core 源码分析] 01 - Session SignalR sql for xml path用法 MemCahe C# 操作Excel图形——绘制、读取、隐藏、删除图形 IOC,DIP,DI,IoC容器

    1. 血案由来 近期我在为Lazada卖家中心做一个自助注册的项目,其中的shop name校验规则较为复杂,要求:1. 英文字母大小写2. 数字3. 越南文4. 一些特殊字符,如“&”,“- ...

  7. Vue2.0源码思维导图-------------Vue 构造函数、原型、静态属性和方法

    已经用vue有一段时间了,最近花一些时间去阅读Vue源码,看源码的同时便于理解,会用工具画下结构图. 今天把最近看到总结的结构图分享出来.希望可以帮助和其他同学一起进步.当然里边可能存在一些疏漏的,或 ...

  8. 曹工说Spring Boot源码(27)-- Spring的component-scan,光是include-filter属性的各种配置方式,就够玩半天了.md

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  9. jQuery源码解析资源便签

    最近开始解读jQuery源码,下面的链接都是搜过来的,当然妙味课堂 有相关的一系列视频,长达100多期,就像一只蜗牛慢慢爬, 至少品读三个框架,以后可以打打怪,自己造造轮子. 完全理解jQuery源代 ...

随机推荐

  1. Dictionaries

    A dictionary is like a list, but more general. In a list, the indices have to be integers; in a dict ...

  2. windows, fast-rcnn CPU版本的安装配置

    一:安装准备 1:caffe的安装配置,本人用的是happynear大神的caffe版本,具体链接https://github.com/happynear/caffe-windows,编译时需要用到p ...

  3. RMAN备份脚本

      单机环境全备   export ORACLE_BASE=/oracle export ORACLE_HOME=$ORACLE_BASE/product/10.2.0/db_1 export ORA ...

  4. js利用点击事件做一个简单的计算器

    先放一个样式图: 源代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"&g ...

  5. 洛谷3964 [TJOI2013]松鼠聚会

    题目描述 草原上住着一群小松鼠,每个小松鼠都有一个家.时间长了,大家觉得应该聚一聚.但是草原非常大,松鼠们都很头疼应该在谁家聚会才最合理. 每个小松鼠的家可以用一个点x,y表示,两个点的距离定义为点( ...

  6. [笔记-图论]Bellman-Ford

    用于求可带负权的单源有向图 优化后复杂度O(nm) 如果图中存在负环,就不存在最小路 这种情况下,就一定会有一个顶点被松弛多于n-1次,Bellman-Ford可直接判断出来 我在网上看到SPFA,发 ...

  7. Spring MVC框架一个实例的手动实现

    文件结构: SpringMVC05 // 应用程序名 ----index.html // 欢迎文件,主目录下的文件可以被URL直接访问到 ----WEB-INF // 这个目录下的文件将被保护起来不能 ...

  8. echarts 绑定事件重复执行问题。

    网上所有,先调用.off 方法后再调用.on 绑定事件. 无效果,查看api未发现off方法,于是采用,先删除原先元素,后重新生成的方式. 场景描述. 用户查询时,每次结果都对应一张饼图.该张饼图绑定 ...

  9. python Web抓取(一)[没写完]

    需要的模块: python web抓取通过: webbrowser:是python自带的,打开浏览器获取指定页面 requests:从因特网上下载文件和网页 Beautiful Soup:解析HTML ...

  10. Raphaeljs入门到精通(一)

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <t ...