jquery.dataTable.js 使用详解 二、sDom布局源码解析

dataTable是怎么利用aDom实现布局的,提出了疑问。由于很久以前看的源码,当时也没有跟他解释的很清楚,于是又重新梳理了一下源码,在这里做一下笔记。

首先看一下示例的实际效果:
在这里插入图片描述

源码中实现布局的方法是_fnAddOptionsHtml(),形参是oSettings

下面看_fnAddOptionsHtml()源码:


    function _fnAddOptionsHtml ( oSettings )  
    {  
        /* 
         * Create a temporary, empty, div which we can later on replace with what we have generated 
         * we do it this way to rendering the 'options' html offline - speed :-) 
         * 作者说:这里先创建一个临时的空div,后面会被完整的内容替换掉 
         */  
        var nHolding = $('<div></div>')[0];  
        /* 
         * 把上面生成的临时div插入到绑定dataTable插件的元素前面 
         * 这里的oSettings.nTable,追溯源码,发现是this,也就是绑定插件的对象 
         * 例如:$("#mainTable").dataTable({....});   oSettings.nTable 就是 id为mainTable的 
         */  
        oSettings.nTable.parentNode.insertBefore( nHolding, oSettings.nTable );  
        /*  
         * All DataTables are wrapped in a div 
         * 作者说:创建一个div作为根节点,将所有的元素都包裹进去,以<table>的id拼接'_wrapper' 
         */  
        oSettings.nTableWrapper = $('<div id="'+oSettings.sTableId+'_wrapper" class="'+oSettings.oClasses.sWrapper+'" role="grid"></div>')[0];  
        oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;  
      
        /* Track where we want to insert the option  
         * 将oSettings.nTableWrapper赋给变量nInsertNode,跟踪我们想插入的元素 
         */  
        var nInsertNode = oSettings.nTableWrapper;  
          
        /* Loop over the user set positioning and place the elements as needed */  
        /* 
         * 前方高能,重头戏开始了!!! 
         * 分割aDom,得到字符数组 
         * 示例中我们的aDom属性值为<lf>rt<lpi><"clear"> 
         */  
        var aDom = oSettings.sDom.split('');  
        var nTmp, iPushFeature, cOption, nNewNode, cNext, sAttr, j;  
        /* 
         * 迭代字符数组 
         */  
        for ( var i=0 ; i<aDom.length ; i++ )  
        {  
            iPushFeature = 0;  
            cOption = aDom[i];  
            /* 
             * 如果当前字符是'<'执行以下操作 
             */  
            if ( cOption == '<' )  
            {  
                /* New container div  
                 * 创建一个空div 
                 */  
                nNewNode = $('<div></div>')[0];  
                  
                /* Check to see if we should append an id and/or a class name to the container  
                 * 看看是否要给div添加id属性或者class属性 
                 * 如果<符号后面是'或"就要给div添加属性 
                 */  
                cNext = aDom[i+1];  
                if ( cNext == "'" || cNext == '"' )  
                {  
                    sAttr = "";  
                    j = 2;  
                    while ( aDom[i+j] != cNext )  
                    {  
                        sAttr += aDom[i+j];  
                        j++;  
                    }  
                      
                    /* Replace jQuery UI constants */  
                    if ( sAttr == "H" )  
                    {  
                        sAttr = oSettings.oClasses.sJUIHeader;  
                    }  
                    else if ( sAttr == "F" )  
                    {  
                        sAttr = oSettings.oClasses.sJUIFooter;  
                    }  
                      
                    /* The attribute can be in the format of "#id.class", "#id" or "class" This logic 
                     * breaks the string into parts and applies them as needed 
                     * 如果字符串里面有#号,就给div加上id属性,如果字符串里面有.号,就给div加上class属性 
                     */  
                    if ( sAttr.indexOf('.') != -1 )  
                    {  
                        var aSplit = sAttr.split('.');  
                        nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);  
                        nNewNode.className = aSplit[1];  
                    }  
                    else if ( sAttr.charAt(0) == "#" )  
                    {  
                        nNewNode.id = sAttr.substr(1, sAttr.length-1);  
                    }  
                    else  
                    {  
                        nNewNode.className = sAttr;  
                    }  
                      
                    i += j; /* Move along the position array */  
                }  
                /* 
                 * 将处理完成后的div放入根节点,并对根节点变量重新赋值为新创建的div 
                 */  
                nInsertNode.appendChild( nNewNode );  
                nInsertNode = nNewNode;  
            }  
            else if ( cOption == '>' )  
            {  
                /* End container div  
                 * 这里标识一个div的闭合  
                 */  
                nInsertNode = nInsertNode.parentNode;  
            }  
            else if ( cOption == 'l' && oSettings.oFeatures.bPaginate && oSettings.oFeatures.bLengthChange )  
            {  
                /* Length  
                 * 如果当前字符为l,则表示为dataTable增加可以操作每页显示行数的下来框 
                 * 前置条件为bLengthChange和bPaginate配置为true,即允许分页并且允许用户选择每页显示行数 
                 * 将在_fnFeatureHtmlFilter函数中创建class="mainTable_length"的元素,并且放入上面创建的div中 
                 */  
                nTmp = _fnFeatureHtmlLength( oSettings );  
                iPushFeature = 1;  
            }  
            else if ( cOption == 'f' && oSettings.oFeatures.bFilter )  
            {  
                /* Filter  
                 * 如果当前字符为f,则表示为dataTable增加跨行搜索框 
                 * 前置条件为bFilter配置为true,即启用内置搜索,可跨行搜索 
                 * 将在_fnFeatureHtmlFilter函数中创建class="dataTables_filter"的元素,并且放入上面创建的div中 
                 */  
                nTmp = _fnFeatureHtmlFilter( oSettings );  
                iPushFeature = 1;  
            }  
            else if ( cOption == 'r' && oSettings.oFeatures.bProcessing )  
            {  
                /* pRocessing  
                 * 如果当前字符为r,则表示为dataTable增加数据加载进度效果 
                 * 前置条件为bProcessing配置为true,即显示加载时进度条 
                 * 将在_fnFeatureHtmlProcessing函数中创建class="dataTables_processing"的元素,并且放入上面创建的div中 
                 */  
                nTmp = _fnFeatureHtmlProcessing( oSettings );  
                iPushFeature = 1;  
            }  
            else if ( cOption == 't' )  
            {  
                /* Table  
                 * 这就是table实体了,将在_fnFeatureHtmlTable函数中创建table元素,table的属性、样式将沿用html代码中的定义 
                 */  
                nTmp = _fnFeatureHtmlTable( oSettings );  
                iPushFeature = 1;  
            }  
            else if ( cOption ==  'i' && oSettings.oFeatures.bInfo )  
            {  
                /* Info  
                 * 如果当前字符为i,则表示为dataTable增加表格相关信息,例如翻页信息等。 
                 * 前置条件为bInfo配置为true,即显示表格相关信息 
                 * 将在_fnFeatureHtmlInfo函数中创建class="dataTables_info"的元素,并且放入上面创建的div中 
                 * */  
                nTmp = _fnFeatureHtmlInfo( oSettings );  
                iPushFeature = 1;  
            }  
            else if ( cOption == 'p' && oSettings.oFeatures.bPaginate )  
            {  
                /* Pagination  
                 * 如果当前字符为p,则表示为dataTable增加分页功能。 
                 * 前置条件为bPaginate配置为true,即开启分页功能 
                 * 将在_fnFeatureHtmlPaginate函数中创建分页所需的元素,并且放入上面创建的div中  
                 * */  
                nTmp = _fnFeatureHtmlPaginate( oSettings );  
                iPushFeature = 1;  
            }  
            else if ( DataTable.ext.aoFeatures.length !== 0 )  
            {  
                /* Plug-in features */  
                var aoFeatures = DataTable.ext.aoFeatures;  
                for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )  
                {  
                    if ( cOption == aoFeatures[k].cFeature )  
                    {  
                        nTmp = aoFeatures[k].fnInit( oSettings );  
                        if ( nTmp )  
                        {  
                            iPushFeature = 1;  
                        }  
                        break;  
                    }  
                }  
            }  
              
            /* Add to the 2D features array */  
            if ( iPushFeature == 1 && nTmp !== null )  
            {  
                if ( typeof oSettings.aanFeatures[cOption] !== 'object' )  
                {  
                    oSettings.aanFeatures[cOption] = [];  
                }  
                oSettings.aanFeatures[cOption].push( nTmp );  
                nInsertNode.appendChild( nTmp );  
            }  
        }  
          
        /* Built our DOM structure - replace the holding div with what we want  
         * 将上面的临时div换成我们最后生成的div 
         */  
        nHolding.parentNode.replaceChild( oSettings.nTableWrapper, nHolding );  
    }  

最后附上一张,aDom字符与界面元素的对应关系图:
在这里插入图片描述

1、指数名称:北京大学数字普惠金融指数 2、课题组:本指数北京大学数字金融研究中心蚂蚁科技集团研究院组成的联合课题组负责编制,课题组顾问包括北京大学数字金融研究中心主任黄益平,蚂蚁集团研究院院长李振华。第一期指数2011-2015)课题组成员主要包括:郭峰、孔涛、王靖一、张勋、程志云、阮方圆、孙涛、王芳。第二期到第六期指数(2016-2023)课题组成员主要包括:郭峰、王靖一、程志云、李勇国、王芳。课题组也获得了北京大学蚂蚁集团多位同事的技术支持。 3、指数属性:这套指数包括数字普惠金融指数,以及数字金融覆盖广度数字金融使用深度以及普惠金融数字化程度;此外使用深度指数中还包含支付、信贷、保险、信用、投资、货币基金等业务分类指数;但由于监管公司数据安全审核等方面的原因,2019-2023的信用货币基金分指数,没有对外公布。 4、指数范围:中国内地31个省(直辖市、自治区,简称“省”)、337个地级以上城市(地区、自治州、盟等,简称“城市”),以及约2800个县(县级市、旗、市辖区等,简称“县域”);部分地区数据存在缺失;港澳台地区数据暂未包括。 5、时间跨度:省级城市级指数时间跨度为2011-2023,县域指数时间跨度为2014-2023。 6、地区代码说明:在2011-2023期间,中国部分地区进行了“撤地设市”“县(市)改区”等改革,调整了地区名称行政区划代码,但并不影响本指数统计;本表中城市代码同时保留了20142018两个版本,县域名称行政区划代码则以2014底的代码为准,以方便使用者合并其他经济社会数据进行分析。 7、引用说明:欢迎各界人士使用指数,如有使用本数据,请注明所用数据为“北京大学数字普惠金融指数”;同时烦请按照以下文献引用方式引用我们的成果:郭峰、王靖一、王芳、孔涛、张勋、程志云,《测度中国数字普惠金融发展: 指数编制与空间特征》,《经济学季刊》,2020第19卷第4期,第1401-1418页。 8、指数包括: index_aggregate(数字金融发展总指数), coverage_breadth(数字金融覆盖广度指数,二级维度3-1), usage_depth(数字金融使用深度指数,二级维度3-2), payment(电子支付指数),insurance(网络保险指数), monetary_fund,investment(网络投资指数), credit(网络信贷指数), credit_investigation, digitization_level(普惠金融数字化程度指数,二级维度3-3)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值