jQuery07源码 (3803 , 4299) attr() prop() val() addClass()等 : 对元素属性的操作
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()等 : 对元素属性的操作的更多相关文章
- jquery13 attr() prop() val() addClass()等 : 对元素属性的操作
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...
- jquery之 css()方法。用法类似的有attr(),prop(),val()
[注]attr(),prop(),val()的用法结构和css()一致,可参考 css()函数用于设置或返回当前jQuery对象所匹配的元素的css样式属性值. 该函数属于jQuery对象(实例).如 ...
- jQuery.attributes源码分析(attr/prop/val/class)
回顾 有了之前的几篇对于jQuery.attributes相关的研究,是时候分析jQuery.attr的源码了 Javascript中的attribute和property分析 attribute和p ...
- jquery源码解析:attr,prop,attrHooks,propHooks详解
我们先来看一下jQuery中有多少个方法是用来操作元素属性的. 首先,看一下实例方法: 然后,看下静态方法(工具方法): 静态方法是内部使用的,我们外面使用的很少,实例方法才是对外的. 接下来,我们来 ...
- jQuery源码-jQuery.fn.attr与jQuery.fn.prop
jQuery.fn.attr.jQuery.fn.prop的区别 假设页面有下面这么个标签,$('#ddd').attr('nick').$('#ddd').prop('nick')分别会取得什么值? ...
- 一个由正则表达式引发的血案 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. 一些特殊字符,如“&”,“- ...
- Vue2.0源码思维导图-------------Vue 构造函数、原型、静态属性和方法
已经用vue有一段时间了,最近花一些时间去阅读Vue源码,看源码的同时便于理解,会用工具画下结构图. 今天把最近看到总结的结构图分享出来.希望可以帮助和其他同学一起进步.当然里边可能存在一些疏漏的,或 ...
- 曹工说Spring Boot源码(27)-- Spring的component-scan,光是include-filter属性的各种配置方式,就够玩半天了.md
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- jQuery源码解析资源便签
最近开始解读jQuery源码,下面的链接都是搜过来的,当然妙味课堂 有相关的一系列视频,长达100多期,就像一只蜗牛慢慢爬, 至少品读三个框架,以后可以打打怪,自己造造轮子. 完全理解jQuery源代 ...
随机推荐
- BZOJ 3083 树链剖分+倍增+线段树
思路: 先随便选个点 链剖+线段树 1操作 就直接改root变量的值 2操作 线段树上改 3操作 分成三种情况 1.new root = xx 整个子树的min就是ans 2. lca(new roo ...
- 单表的更新UPDATE和删除记录DELETE(二十六)
当把记录写成功之后,也许我们还会如下操作.比如,记录在书写的过程中字段是错误的.或者,我们想改下字段值.那么,我们需要update关键字. update分为单表更新和多表更新. 一.UPDATE语句 ...
- Framework3.5安装(Windows8.1)
在用到Android逆向助手,使用时提示安装Framework3.5,Windows7都有Framework3.5,Windows8却没有,联网更新就算了,这龟速更新得多久.但是问题总还是要解决,随便 ...
- http://www.open-open.com/lib/tag/ReactiveCocoa
http://www.open-open.com/lib/tag/ReactiveCocoa
- centos 安装 aria2 webui 实现网页下载
centos aria2 webui 安装aria2 安装 rpmforge源 wget http://repository.it4i.cz/mirrors/repoforge/redhat/el6/ ...
- 记intel杯比赛中各种bug与debug【其三】:intel chainer的安装与使用
现在在训练模型,闲着来写一篇 顺着这篇文章,顺利安装上intel chainer 再次感谢 大黄老鼠 intel chainer 使用 头一次使用chainer,本以为又入了一个大坑,实际尝试感觉非常 ...
- [Codeforces 816A]Karen and Morning
题目大意:给你一个时间(hh:mm),求最少经过多少分钟才能使这个时间变成回文. 解题思路:模拟,先判断0的情况,然后每过1分钟判断一次即可. C++ Code: #include<cstdio ...
- shell中处理用户输入
1.使用命令行参数 在shell执行的时候命令行中输入的所有参数可以赋值给一些特殊变量,这些变量成为位置变量参数. 包括: $0返回脚本名称.$1为第一个参数.$2为第二个参数 ...$9第九个参数 ...
- php异常处理的深入
引出 如果你调一个类,调用时数据验证时报了个错,你会以什么方式返回 数组,布尔值? 数组这个可以带错误原因回来,那布尔值呢? 返回了个 false, 报错时把错误放在类变量里?还是专门用一个获取错误的 ...
- mod_php模式原理探析
1.PHP与Apache工作模式 在传统的LAMP架构中,PHP与Apache交互时,至少有两种方式『运行PHP』: 使用CGI:Apache发送请求至php-cgi进程,php-cgi进程调用PHP ...