1.判断文档是否是XML文档

var isXML = function(elem){

  var documentElement = elem && (elem.ownerDocument || elem).documentElement;  

  return documentElement ? documentElement.nodeName !=="HTML" : false;

}

看懂以上代码,需要先了解这两个的区别:

ownerDocument返回的是某个元素的根节点文档对象(即document对象)
而documentElement 返回的就是文档根节点。(html文档就是html,xml文档就是最外面的节点元素)

因此,如果传入函数中的元素属于html文档,那么documentElement = document.documentElement = html,因此html元素的nodeName == "HTML" (会默认变成大写)。

如果传入的的元素是XML文档,那么documentElement = document.documentElement = 最外面的节点元素,它不可能是html(html文档),所以就返回true。

这是jQuery中的方法,但是这不严谨:因为XML的根节点可能是HTML标签。(但谁这么无聊去那样创建xml呢)

有一种更严谨的方法:

var isXML = function(doc){

    //xml文档创建元素时,传入小写的字母,取它的nodeName时就是小写。而HTML文档,不管传入的是小写还是大写,取它的nodeName时,都会是大写

  return doc.createElement("p").nodeName !== doc.createElement("P").nodeName;

}

2.判定两个节点的关系

nodeA.compareDocumentPosition(nodeB)返回的结果:           //标准浏览器支持,低版本浏览器不支持

0:  元素一致

1:  节点在不同的文档(或有一个节点在文档之外)

2:  节点B在节点A之前

4:  节点A在节点B之前

8:  节点B包含节点A

16:  节点A包含节点B

32:  浏览器的私有使用

当然,两个元素的位置关系可能满足以上两种情况,比如:A包含B,并且A在B的前面,这时就返回16+4=20.

为了兼容低版本浏览器,可以用IE的私有属性sourceIndex处理,sourceIndex会根据元素的位置从上到下,从左到右依次加1,比如HTML标签的sourceIndex为0,HEAD标签为1,BODY标签为2,HEAD的第一个子元素为3...,如果元素不在DOM树中,就返回-1.

3.节点排序

为了让选择器引擎搜索到的结果集与原生API结果一样,我们需要让元素节点按它们在DOM树出现的顺序排序。

(1)在IE以及Opera早期版本,可以使用sourceIndex进行排序。标准浏览器可以使用compareDocumentPosition判断,来排序。

(2)标准浏览器的Range对象有一个compareBoundaryPoints方法,它能迅速的得到两个元素的前后顺序。要兼容旧版本浏览器和XML文档,可以使用nextSibling等DOM API来处理。(所谓"Range",是指HTML文档中的任意一段内容。一个Range的起始点和结束点位置可以任意,甚至起始点和结束点可以是一样的(也就是空Range)。最常见的Range是用户文本选择范围(user text selection)。当用户选择了页面上的某一段文字后,你就可以把这个选择转为Range。当然,你也可以直接用程序定义Range。)

(3)我们用选择器引擎选择好了之后,用document.getElementsByTagName("*")得到所有元素节点,这时它们肯定是排好序的。我们依次为它们添加一个类似sourceIndex的自定义属性,值为它的索引值。然后再去匹配选择器引擎选择好的结果,就可以排序了。

这里有一个tip跟大家说下:数组原生的sort方法,每个浏览器使用的排序算法都不一样。但是当它传入一个比较函数时,不管内部使用的是哪种排序算法,都需要多次比对,非常耗时。

这里讲一下经常会出现的面试题:对元素节点进行排序。我们可以把元素节点附在String对象数组中,比如:[{"0":元素1},{"1":元素2},{"2":元素3}],对这个数组逆序,然后根据数组的顺序取元素,元素节点就逆序了。

4.切割器

切割器就是对用户的选择符进行切割,这个步骤就像编译原理的词法分析,拆分出有用的符号出来。

比如:对于".td1,div a,body"这种选择符字符串,我们必须使用正则将它分解成以下数组:[".td1",",","div"," ","*",",","body"]。

然后就可以根据这个数组中的每项进行元素的创建和过滤了。最终去重排序,得到用户想要的元素。

这里主要用来正则表达式来处理字符串,需要强大的正则表达式基础,适合深入研究正则的人。

加油!

第十一课:js操作选择器的通用函数的更多相关文章

  1. js介绍,js三种引入方式,js选择器,js四种调试方式,js操作页面文档DOM(修改文本,修改css样式,修改属性)

    js介绍 js运行编写在浏览器上的脚本语言(外挂,具有逻辑性) 脚本语言:运行在浏览器上的独立的代码块(具有逻辑性) 操作BOM 浏览器对象盒子 操作DOM 文本对象 js三种引入方式 (1)行间式: ...

  2. js闭包 选择器 面向对象 事件 操作页面

    闭包js函数的嵌套定义,定义在内部的函数 就称之为闭包为什么使用闭包: 1.一个函数要使用另一个函数的局部变量 2.闭包会持久化包裹自身的函数的局部变量 3.解决循环绑定 function outer ...

  3. DOM操作相关案例 模态对话框,简易留言板,js模拟选择器hover,tab选项卡,购物车案例

    1.模态框案例 需求: 打开网页时有一个普通的按钮,点击当前按钮显示一个背景图,中心并弹出一个弹出框,点击X的时候会关闭当前的模态框 代码如下: <!DOCTYPE html> <h ...

  4. js进阶 11-18 jquery中操作选择器的方法有哪些

    js进阶 11-18 jquery中操作选择器的方法有哪些 一.总结 一句话总结:add().addBack().end() 1.add()方法是干嘛的,举一例? 将add()方法后选择器选择的jqu ...

  5. 前端(十二)—— JavaScript基础操作:if语句、for循环、while循环、for...in、for...of、异常处理、函数、事件、JS选择器、JS操作页面样式

    JavaScript基础操作 一.分支结构 1.if语句 if 基础语法 if (条件表达式) { 代码块; } // 当条件表达式结果为true,会执行代码块:反之不执行 // 条件表达式可以为普通 ...

  6. 第十四课:js操作节点的插入,复制,移除

    节点插入 appendChild方法,insertBefore方法是常用的两个节点插入方法,具体实现,请看js高级程序设计,或者自行百度. 这里提一下面试时经常会问到的问题,插入多个节点时,你是怎么插 ...

  7. 原生js操作DOM基础-笔记

    原文参考http://mp.weixin.qq.com/s?__biz=MzU3MDA0NTMzMA==&mid=2247485490&idx=1&sn=15197b4b53e ...

  8. NeHe OpenGL教程 第三十一课:加载模型

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  9. NeHe OpenGL教程 第十一课:飘动的旗帜

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

随机推荐

  1. [学习嵌入式开发板]iTOP-4412实现NFS网络文件系统

    本文转自迅为:http://www.topeetboard.com 学习平台:iTOP-4412开发板 本文讲解如何在 iTOP-4412 开发板上实现 NFS 网络文件系统. 我们使用的软硬件环境是 ...

  2. NOIP2008 普及组T2 排座椅 解题报告-S.B.S

    题目描述 上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情.不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的D对同学上课时会交头接耳.同学 ...

  3. 翻译《Writing Idiomatic Python》(一):if语句、for循环

    开篇废话 这是在美国Amazon上评价很不错的一本书,其实严格来说这可能不算书,而是一本小册子.就像书名一样,里面的内容主要是用一些例子讲述地道的Python的代码是怎样写的.书中把很多例子用不良风格 ...

  4. python实现虚拟茶话会

    这个项目目的是编写一个聊天服务器,该聊天服务器的功能有: 服务器能同时接收来自不同用户的连接 允许用户同时操作 能够解释命令,例如,say或者logout命令 服务器容易扩展 这个项目里面我们会使用到 ...

  5. python如何控制数据库?

    http://www.w3cschool.cc/python/python-mysql.html 通过利用MySQLdb可以操作数据库 实例: 以下实例链接Mysql的TESTDB数据库: # enc ...

  6. 保存带有emoji的文本报错解决方案

    今天偶然遇到一个错误,就是保存文本的时候带有了emoji表情,报错了 java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x8A\ ...

  7. A*寻路初探 GameDev.net

    A*寻路初探 GameDev.net MulinB按:经典的智能寻路算法,一个老外写的很透彻很清晰,很容易让人理解神秘的A*算法.以下是一个中文翻译版. A*寻路初探 GameDev.net 作者: ...

  8. Z路径覆盖

    Z路径覆盖是路径覆盖的一个变体.路径覆盖是白盒测试最为典型的问题.着眼于路径分析的测试可称为路径测试.完成路径测试的理想情况是做到路径覆盖.对于比较简单的小程序实现路径覆盖是可能做到的.但是如果程序中 ...

  9. maven总结1

     环境:win7   maven版本:apache-maven-3.1.1-bin.zip maven安装 1.确定已经正确安装jdk,若未安装需要先安装jdk 2.http://maven.apac ...

  10. Android Studio中提示:Project SDK is not defined

    Android Studio中提示:Project SDK is not defined 2015 年 4 月 1 日 下午 9:04crifan已有2209人围观我来说几句 [背景] 之前用Andr ...