接着上篇讲,上一篇发出来以后,有朋友看过以后,对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字符与界面元素的对应关系图:
最后再附上代码一份。
相关推荐
通过`sDom`属性可以控制页面上元素的布局和显示顺序。例如: ```javascript $(document).ready(function(){ $('#example').dataTable({ "sDom": '<"top"fli>rt<"bottom"p><"clear">' }); }); ``` `sDom`的值由...
stm32+esp8266+mqtt/onenet智能家居
Android开发不用存储权限进行拍照,得到拍照后的图片效果。有一点难度,关键是存储路径的定义。
j
反向Lora提高画面细节。
小秘书(凤凰电话管理系统)【纽曼声卡版小秘书】,主要用来做为来电自动录音功能。
基于SpringBoot的疫情居家检测管理系统,系统包含三种角色:管理员、用户、医生,主要功能如下。 【用户功能】 1. 首页:获取系统信息。 2. 论坛:参与居民讨论和分享信息。 3. 公告:查看社区发布的各类公告。 4. 医保信息:了解医疗保障相关信息。 5. 个人中心:管理个人信息,查看预约和就诊历史。 【管理员功能】 1. 首页:查看系统整体。 2. 个人中心:管理管理员的个人信息。 3. 管理员管理:维护系统管理员的账户信息。 4. 医生管理:添加、编辑和删除医生信息。 5. 用户管理:查看和管理系统用户的信息。 6. 预约管理:审核和管理用户对医生的预约服务。 7. 就诊历史管理:查看和管理用户的就诊历史记录。 8. 健康信息管理:记录和查看用户的健康信息。 9. 药品管理:管理系统内的药品种类。 10. 药品入库管理:记录和管理药品的入库情况。 11. 药品使用管理:记录和管理药品的使用情况。 12. 医保信息管理:管理医保相关信息。 13. 论坛管理:审核和回复用户在论坛上的帖子。 14. 公告管理:发布、编辑和管理公告信息。 15. 基础数据管理:管理系统的基础数据。 16. 轮播图信息:管理系统首页的轮播图展示。 【医生功能】 1. 首页:查看医生个人信息。 2. 个人中心:管理医生的个人信息。 3. 预约管理:查看和管理用户对医生的预约服务。 4. 就诊历史管理:查看和管理用户的就诊历史记录。 5. 健康信息管理:记录和查看用户的健康信息。 6. 药品管理:管理系统内的药品种类。 7. 药品入库管理:记录和管理药品的入库情况。 8. 药品使用管理:记录和管理药品的使用情况。 9. 医保信息管理:管理医保相关信息。 10. 论坛管理:审核和回复用户在论坛上的帖子。 11. 公告管理:发布、编辑和管理公告信息。 12. 轮播图信息:管理系统首页的轮播
基于python的Opencv项目实战.zip
鸿蒙开发画廊效果功能,中间大,两边小的浏览效果,难度不小,进行了一定的封装。很好看的画廊效果
win32汇编环境,网络编程入门之十九
linux
【HD-RK3576-PI】定制用户升级固件
内容概要:本文是关于大规模L1正则化线性分类优化方法和软件比较的补充材料,由台湾大学计算机科学系的研究团队撰写。文章详细介绍了GLMNET算法的核心公式推导及其具体实现步骤,包括如何计算L¯j(0; X˜),以及如何维护关键变量以减少计算量。此外,文中对比了多种求解器(如CDN、IPM、TRON等)在不同数据集上的性能,涵盖达到特定停止准则所需时间、迭代次数及每次迭代的平均成本。研究结果显示,在大多数数据集上,CDN方法表现最优,但在极严格的条件下,IPM方法表现更好。对于L1和L2正则化的逻辑回归,文中指出L1正则化在某些数据类型上可能提供更好的准确性,但训练时间较长,因此推荐先尝试L2正则化用于分类任务,而L1正则化更适合特征选择。 适合人群:对机器学习算法尤其是正则化技术有一定了解的数据科学家和研究人员。 使用场景及目标:①需要进行大规模线性分类问题的优化;②比较不同优化方法和工具包在实际应用中的效果;③理解L1和L2正则化在逻辑回归中的区别及其适用情况。 其他说明:本文提供了详细的数学推导和实验结果分析,有助于深入理解各种优化方法的工作原理及其优劣。读者可以通过这些内容选择最适合自身需求的算法和工具包。
西电A测或通院微控温度仿真控制系统的proteus文件
华为ONT使能2.0工具
basalt_top
无极调速数控车床主轴箱装配CAD图.rar
乳液涂料生产流程图.rar