深入浏览器兼容 细数jQuery Hooks 属性篇

关于钩子:http://www.cnblogs.com/aaronjs/p/3387906.html

本章的目的很简单,通过钩子函数更细节的了解浏览器差异与处理方案,

版本是2.0.3所以不兼容ie6.7.8,所以对应了钩子会少很多。。

总的来说钩子在.attr().prop().val() and .css() 四种操作中会涉及

 

属性操作的钩子

propFix

propHooks

attrHooks

valHooks

 


jQuery.propFix  中的对象

深入浏览器兼容 细数jQuery Hooks 属性篇

 

源码部分

1:保留值属性名字修正

jQuery.propFix: {
    for   :  "htmlFor",
   class  :  "className"
},
  • 由于class属于JavaScript保留值,因此当我们要操作元素的class属性值时,直接使用obj.getAttribute('class')和obj.setAttribute('class', 'value')可能会遭遇浏览器兼容性问题,W3C DOM标准为每个节点提供了一个可读写的className属性,作为节点class属性的映射,标准浏览器的都提供了这一属性的支持,因此,可以使用e.className访问元素的class属性值,也可对该属性进行重新斌值。而IE和Opera中也可使用e.getAttribute('className')和e.setAttribute('className', 'value')访问及修改class属性值。相比之下,e.className是W3C DOM标准,仍然是兼容性最强的解决办法。
  • 同理htmlFor用于读取label标签的for属性

 

测试demo,通过class与className修改元素的属性


 

 

2:与表单操作相关:

反转下,让钩子适配用伪代码匹配,目测应该是为了兼容开发者输入大小写格式不正确

比如输入错误格式:cellpadding

如果jQuery.propFix 转成cellPadding ,驼峰写法了

深入浏览器兼容 细数jQuery Hooks 属性篇
jQuery.each([
        "tabIndex",
        "readOnly",
        "maxLength",
        "cellSpacing",
        "cellPadding",
        "rowSpan",
        "colSpan",
        "useMap",
        "frameBorder",
        "contentEditable"
    ], function() {
        jQuery.propFix[ this.toLowerCase() ] = this;
    });
深入浏览器兼容 细数jQuery Hooks 属性篇

tabIndex 属性可设置或返回按钮的 tab 键控制次序

readonly 属性规定输入字段为只读。

maxlength 属性规定输入字段的最大长度,以字符个数计。

cellspacing 属性规定单元格之间的空间

cellpadding 属性规定单元边沿与其内容之间的空白。

rowspan 属性规定单元格可横跨的行数。

colspan 属性规定单元格可横跨的列数。

 

HTML <img> 标签的

usemap 属性将图像定义为客户端图像映射

frameBorder 属性设置或返回是否显示框架周围的边框。

contenteditable 属性规定是否可编辑元素的内容。

 

值得一提的是这个方法用的比较巧妙了,收集所有的合集名,然后在每一个上下文回调中把每一个名字传递到propFix方法,key转成小写,value保存正确写法

jQuery.propFix[ this.toLowerCase() ] = this;

 


jQuery.propHooks 属性方法

关于tabIndex属性

http://www.w3help.org/zh-cn/causes/SD2021

深入浏览器兼容 细数jQuery Hooks 属性篇
propHooks: {
    tabIndex: {
        get: function( elem ) {
            return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ?
                elem.tabIndex :
                -1;
        }
    }
}
深入浏览器兼容 细数jQuery Hooks 属性篇

 

深入浏览器兼容 细数jQuery Hooks 属性篇
// 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 Hooks 属性篇

 


jQuery.attrHooks 方法

深入浏览器兼容 细数jQuery Hooks 属性篇
attrHooks: {
    type: {
        set: function( elem, value ) {
            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
                var val = elem.value;
                elem.setAttribute( "type", value );
                if ( val ) {
                    elem.value = val;
                }
                return value;
            }
        }
    }
},
深入浏览器兼容 细数jQuery Hooks 属性篇

 


jQuery.valHooks 方法

根据 JQuery api文档 的描述,.val() 函数有两种用法,分别用来获取或设置元素的值,这里只介绍获取值的方法。

文档里面说 .val 主要是用于获取元素的value,比如 inputselect 和 textarea等,

什么是元素的value?”

用 select 标签为例,如下的代码:

测试代码

深入浏览器兼容 细数jQuery Hooks 属性篇
<select id="choise">
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
  <option value="4">Four</option>
</select>
深入浏览器兼容 细数jQuery Hooks 属性篇

这里的option有2个值,一个是value = 1 另一个则是 text = One

option 真正的 value 应该是其 value 属性中的值,而不是 option 标签中间所包含的内容

在 w3school 的文档中对 option 的 value 属性的做了如下定义:

The value attribute specifies the value to be sent to a server when a form is submitted.
The content between the opening <option> and closing </option> tags is what the browsers will display in a drop-down list. However, the value of the value attribute is what will be sent to the server when a form is submitted.
Note: If the value attribute is not specified, the content will be passed as the value instead.

这一点对于所有可以拥有 value 属性的标签都是相同的,即在对一个元素调用 .val() 函数时,首先取其 value 属性的值,如果没有的话,再使用其 text 值。

 

那么接下来就要引入我们的valHooks,针对option,select的处理

深入浏览器兼容 细数jQuery Hooks 属性篇
option,select

对于val方法的取值部分

深入浏览器兼容 细数jQuery Hooks 属性篇
if ( elem ) {
    hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];

    if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
        return ret;
    }

    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;
}
深入浏览器兼容 细数jQuery Hooks 属性篇

通过jQuery.valHooks匹配对应的钩子处理方法

深入浏览器兼容 细数jQuery Hooks 属性篇

 

节点属性的差异对比:

select : 创建单选或多选菜单

  1. type:"select-one"
  2. tagName: "SELECT"
  3. value: "111"
  4. textContent: "↵ Single↵ Single2↵"

option : 元素定义下拉列表中的一个选项

  1. tagName: "OPTION"
  2. value: "111"
  3. text: "Single"
  4. textContent: "Single"

radio : 表单中的单选按钮

  1. type: "radio"
  2. value: "11111"

checkbox : 选择框

  1. type: "checkbox"
  2. value: "11111"

 

根据对比select的节点type是'select-one’与其余几个还不同,所以jQuery在适配的时候采用优先查找type,否则就找nodeName的策略

hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];

 

如果钩子匹配到了,并且还存在get方法,那么就要调用这个方法了,如果有返回值就返回当前的这个最终值

if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
    return ret;
}

 

那么具体的兼容问题就会跑到对应的钩子方法中处理了

深入浏览器兼容 细数jQuery Hooks 属性篇
// Loop through all the selected options
                    for ( ; i < max; i++ ) {
                        option = options[ i ];

                        // 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();

                            // We don't need an array for one selects
                            if ( one ) {
                                return value;
                            }

                            // Multi-Selects return an array
                            values.push( value );
                        }
                    }
深入浏览器兼容 细数jQuery Hooks 属性篇

通过selectedIndex 属性可设置或返回下拉列表中被选选项的索引号

通过递归select中的所有option

在包装jQuery( option ).val()

从而调用option的钩子方法get ,

深入浏览器兼容 细数jQuery Hooks 属性篇
get: function( elem ) {
                    // attributes.value is undefined in Blackberry 4.7 but
                    // uses .value. See #6932
                    var val = elem.attributes.value;
                    return !val || val.specified ? elem.value : elem.text;
                }
深入浏览器兼容 细数jQuery Hooks 属性篇

elem.attributes.value返回对应的option的val值

所以这里就兼容的默认返回val,否则就返回text的内容了

 


radio,checkbox

深入浏览器兼容 细数jQuery Hooks 属性篇
// Radios and checkboxes getter/setter
    jQuery.each([ "radio", "checkbox" ], function() {
        jQuery.valHooks[ this ] = {
            set: function( elem, value ) {
                if ( jQuery.isArray( value ) ) {
                    return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
                }
            }
        };
        if ( !jQuery.support.checkOn ) {
            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;
            };
        }
    });
深入浏览器兼容 细数jQuery Hooks 属性篇

本文转自艾伦 Aaron博客园博客,原文链接:http://www.cnblogs.com/aaronjs/p/3434830.html,如需转载请自行联系原作者
上一篇:SSIS常用的包—发送Email任务


下一篇:Wix 安装部署教程(十三) -- 多语言安装包