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源代 ...
随机推荐
- laravel中的数据迁移和数据填充
laravel中的数据迁移和数据填充 标签(空格分隔): php 生成迁移文件两种方式: 1 新建一个表的迁移文件 php artisan make:migration create_students ...
- python 中的property
""" property() 的第一个参数是 getter 方法,第二个参数是 setter 方法 xx = property(a,b) @property #用于指示g ...
- 四、YOLO-V1原理与实现(you only look once)
可以看成图像分类与定位的结合,给定一张图片,目标检测系统要能够识别出图片的目标并给出其位置,由于图片中目标数是不定的,且要给出目标的精确位置,目标检测相比分类任务更复杂.目标检测的一个实际应用场景就是 ...
- windows server 打开 FTP 服务器上的文件夹时发生错误。请检查是否有权限访问该文件夹。
解决方案1: 打开高级安全windows防火墙,设置出入站规则. 然后,再打开windows防火墙界面,点击左上角“允许程序或功能通过windows防火墙”,勾选上设置的出入站名称和FTP服务器. 如 ...
- docker安装cloudera manager,切换cloudera-scm用户报错can not open session
在root帐号下su - cloudera-scm报错can not open session 在网上搜,大概是说ulimit超过限制之类,搞了很久才找到/etc/security/limits.d/ ...
- mysql---union的使用方法
union的作用非常easy用来合并两条sql的结果集 语法: SQL1 UNION SQL2 现有一张价格表 要求:求出价格低于2000和价格高于3000的商品.不能用or和not between- ...
- 參加北京bluemix云计算大会偶记
我就不写散文了.博客也要轻量化. 记录心路历程吧. 这是一次ibm的技术大会.也是传道大会,洗脑大会.会议主题看起来非常多,占领了北京国际饭店的三层,作为一个老ibm bp感受非常多. 1.北京的创业 ...
- linux中的硬连接和软连接
linux中的硬连接和软连接 linux中的硬连接和软连接 背景 连接 硬连接 软连接 example reference 背景 linux中的文件主要分3块, - 真正的数据 - 索引节点号(ino ...
- rman数据库恢复;关键/非重要文件、影像副本、控制文件、还原点、非归档、增量、新数据库、灾难性回复
运行全然恢复:在 ARCHIVELOG 模式下 丢失了系统重要数据文件: 假设某个数据文件丢失或损坏.且该文件属于 SYSTEM 或 UNDO 表空间,请运行下面步骤: 1. 实例可能会也可能不会自己 ...
- thinkphp里面使用原生php
thinkphp里面使用原生php Php代码可以和标签在模板文件中混合使用,可以在模板文件里面书写任意的PHP语句代码 ,包括下面两种方式: 使用php标签 例如: {php}echo 'Hello ...