zoukankan      html  css  js  c++  java
  • jQuery attributes(下)

    前文对属性的设置、读取、删除方法做了分解,本文继续对jQuery attributes模块分解。

    jQuery.fn.addClass

    /************************************
     *    value: 字符串或者是函数,字符串可以通过空格分隔className
     */
    jQuery.fn.addClass = function( value ) {
        var classes, elem, cur, clazz, j,
            i = 0,
            len = this.length,
            proceed = typeof value === "string" && value;
    
        //如果value是函数
        if ( jQuery.isFunction( value ) ) {
            //则对所有元素迭代运行addClass
            return this.each(function( j ) {
                jQuery( this ).addClass( value.call( this, j, this.className ) );
            });
        }
    
        //如果value是字符串
        if ( proceed ) {
            // 对value字符串分割成数组
            classes = ( value || "" ).match( core_rnotwhite ) || [];
    
            //遍历元素
            for ( ; i < len; i++ ) {
                elem = this[ i ];
                //如果节点是元素,则获取原来的className
                cur = elem.nodeType === 1 && ( elem.className ?
                    ( " " + elem.className + " " ).replace( rclass, " " ) :    //替换掉换行符制表符等
                    " "
                );
    
                //如果cur不为false,即节点是元素
                if ( cur ) {
                    j = 0;
                    //遍历classes组装成新的className应有的值
                    while ( (clazz = classes[j++]) ) {
                        if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
                            cur += clazz + " ";
                        }
                    }
                    //对className赋值,去掉头尾空白
                    elem.className = jQuery.trim( cur );
    
                }
            }
        }
    
        return this;
    };

    添加class的实现上还是比较简单的,利用elem.className来赋值。需要注意:

    var rclass = /[\t\r\n]/g;

    jQuery.fn.removeClass

    jQuery.fn.removeClass = function( value ) {
        var classes, elem, cur, clazz, j,
            i = 0,
            len = this.length,
            //参数是否正确
            proceed = arguments.length === 0 || typeof value === "string" && value;
    
        //如果value是函数
        if ( jQuery.isFunction( value ) ) {
            //则对所有元素迭代运行removeClass
            return this.each(function( j ) {
                jQuery( this ).removeClass( value.call( this, j, this.className ) );
            });
        }
        
        //如果参数正确
        if ( proceed ) {
            //分隔value成为class字符串数组
            classes = ( value || "" ).match( core_rnotwhite ) || [];
    
            //遍历
            for ( ; i < len; i++ ) {
                elem = this[ i ];
                // 获取className并进行预处理
                cur = elem.nodeType === 1 && ( elem.className ?
                    ( " " + elem.className + " " ).replace( rclass, " " ) :
                    ""
                );
    
                //如果是元素
                if ( cur ) {
                    j = 0;
                    //遍历所有class字符串
                    while ( (clazz = classes[j++]) ) {
                        // 寻找是否有对应的字符串
                        while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
                            //有则去掉
                            cur = cur.replace( " " + clazz + " ", " " );
                        }
                    }
                    //给className赋值,并去掉头尾空格
                    elem.className = value ? jQuery.trim( cur ) : "";
                }
            }
        }
    
        return this;
    };

    删除class的实现和addClass非常像,只是通过indexOf和replace来替换掉需要删除的class。

    jQuery.fn.toggleClass

    jQuery.fn.toggleClass = function( value, stateVal ) {
        var type = typeof value,
            isBool = typeof stateVal === "boolean";
    
        //(⊙o⊙)…不说了,大家懂得
        if ( jQuery.isFunction( value ) ) {
            return this.each(function( i ) {
                jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
            });
        }
    
        //遍历所有元素
        return this.each(function() {
            //如果value是字符串
            if ( type === "string" ) {
                var className,
                    i = 0,
                    self = jQuery( this ),
                    state = stateVal,
                    //将value转成classNames字符串数组
                    classNames = value.match( core_rnotwhite ) || [];
    
                //遍历
                while ( (className = classNames[ i++ ]) ) {
                    //stateVal是布尔量,则直接设置为stateVal,否则判断元素是否不存在该className
                    state = isBool ? state : !self.hasClass( className );
                    //如果该className不存在则添加,否则删除
                    self[ state ? "addClass" : "removeClass" ]( className );
                }
    
            // 如果value的类型是undefined或者boolean
            } else if ( type === "undefined" || type === "boolean" ) {
                //如果元素的className存在
                if ( this.className ) {
                    // 将其存入缓存
                    jQuery._data( this, "__className__", this.className );
                }
    
                //对className赋值,为空或者缓存中的值
                this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
            }
        });
    };

    为了实现jQuery.fn.toggleClass还是花了很大功夫的。

    缓存的利用使得toggleClass操作更加方便,而不需要记录以前是那些class。

    jQuery.fn.hasClass

    jQuery.fn.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;
    };

    这个函数通过indexOf来寻找className是否存在。

    jQuery.fn.val

    jQuery.fn.val = function( value ) {
        var hooks, ret, isFunction,
            elem = this[0];
    
        //如果没有参数
        if ( !arguments.length ) {
            //如果元素存在
            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;
                }
    
                //如果没得到钩子,则通过elem.value来返回值
                ret = elem.value;
    
                //如果ret是字符串
                return typeof ret === "string" ?
                    // 将回车符替换
                    ret.replace(rreturn, "") :
                    // 如果ret是空的,则返回"",否则返回ret
                    ret == null ? "" : ret;
            }
    
            return;
        }
    
        //value是否是函数
        isFunction = jQuery.isFunction( value );
    
        //遍历所有元素
        return this.each(function( i ) {
            var val,
                self = jQuery(this);
    
            if ( this.nodeType !== 1 ) {
                return;
            }
    
            //如果value是函数,则转成参数
            if ( isFunction ) {
                val = value.call( this, i, self.val() );
            } else {
                val = value;
            }
    
            // 将null/undefined当成""
            if ( val == null ) {
                val = "";
            // 将数字转成字符串
            } else if ( typeof val === "number" ) {
                val += "";
            //如果是数组,则遍历数组
            } else if ( jQuery.isArray( val ) ) {
                val = jQuery.map(val, function ( value ) {
                    return value == null ? "" : value + "";
                });
            }
    
            //获取相应钩子
            hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
    
            // 如果钩子无法设置,则使用通常的设置方法
            if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
                this.value = val;
            }
        });
    };
  • 相关阅读:
    Java 的类加载顺序
    单链表之一元多项式求和C++实现
    顺序线性表之大整数求和C++实现
    线性表之单链表C++实现
    NOIP 2009 潜伏者
    JDOJ 2782: 和之和
    浅谈前、中、后缀表达式
    CF13B Letter A
    洛谷 P5015 标题统计
    NOIP 2013 转圈游戏
  • 原文地址:https://www.cnblogs.com/justany/p/2867800.html
Copyright © 2011-2022 走看看