`

javascript CSS Selector engine.

阅读更多

CSS selecotor engine is a relative , new developement in the world of javascript but they've taken the world of libraries by storms.

 

 

The premise behind the engie is that eyo ucan feed it in a CSS selecor (for example "div >span") and will return all the DOM elements that match the selector on the page. 

 

 

There are three way to implement a CSS selector engine, they are

 

 

  • W3C selector APIs
  • XPath 
  • Pure DOM  

 

Selector API 

 

 

First it is the Selecotr API. 

 

QuerySelector

QuerySelecotAll

 

 

Below shows the API that you can use to query the CSS selector engine.

 

for simplicity all the test cases and the .js file are embedded in the following file.

 

 

/**************************************
*@Summary
* cssselectorapi.js
*
* CSS selector api has the api which featured by the api called querySelectorAll and querySelector
*
* querySelectorAlll:  Accepts a CSS selector string and returns a static NodeList of all elements found by the selector
*  querySelector: Accepts a CSS selector string and returns the first element found (or null if no matching element is found).
* @Usage
*   
* @TODO:
* test it 
***************************************/

(function () {
  var count = 1;
  this.rootedQuerySelectorAll = function (elem, query) {
    var oldId = elem.id;
    elem.id = "rooted" + (count++);

    try {
      // is this the reason why the element-rooted query will be turned into some rooted queries?
      // still not quite sure about this point.
      alert("the new id is = " + "#" + elem.id + " " + query);
      return elem.querySelectorAll("#" + elem.id + " " + query);
    }
    catch (e) {
      throw e;
    }
    finally {
      elem.id = oldId;
    }
  };
})();
 

 

below is the test html file.

 

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript" src="../unit.js"></script>
    <script type="text/javascript" src="cssselectorapi.js"></script>
    <script type="text/javascript">
      window.onload = function () {
        test("test the CSS selector api ", function () {
          var divs = document.querySelectorAll("body > div");
          assert(divs.length === 2, "Two divs found using a CSS selector.");

          // from the test result, it seems that some of querySelecotr based on the 
          // relative - not rooted, will have different behaviors, as in IE, the following is not 
          // displayed on the IE screen
          var b = document.getElementById("test").querySelector("b:only-child");
          assert(b, "The body element was found relateive to another element");
        });

        test("test the CSS selector on element-rooted query with CSS query API", function () {
          var b = document.getElementById("test").querySelector("div b");
          var blist = document.getElementById("test").querySelectorAll("div b");

          assert(b, "Only the last part of selector matters");
          assert(blist.length === 1, "it returns elements which shall not be returned");
        });


        test("test the CSS selector on element-rooted queries into rooted queries", function () {
          var b = rootedQuerySelectorAll(document.getElementById("test"), "div b");
          assert(b.length === 0, "The selector is now rooted properly.");
        });
      };
    </script>
    <style> 
      #results li.pass { color: Green }
      #results li.fail { color: Red}
    </style>
</head>
<body>
<div id="test">
  <b> hello </b>, I'm a ninja
</div>
<div id="test2"></div>

<ul id="results" />
</body>
</html>

 

 

 

Let me explain something point about the test.

 

 

1.  var divs = document.querySelectorAll("body > div");

          assert(divs.length === 2, "Two divs found using a CSS selector.");

          // from the test result, it seems that some of querySelecotr based on the 
          // relative - not rooted, will have different behaviors, as in IE, the following is not 
          // displayed on the IE screen
          var b = document.getElementById("test").querySelector("b:only-child");
          assert(b, "The body element was found relateive to another element");
 

 this is how you use the CSS selector api, it give the first impression of how the CSS Selector API is used.  

 

 

as explained in the docs, there are different behavior across different browers. and the difference comes as called by the book of ninja is "Selector APIs is more closely capitulates to the existing CSS selecotr engine implementation rathar thant the implementation that were first created by JavaScript engine".

 

 

2. there is know issue access element-rooted query. 

 

 

        test("test the CSS selector on element-rooted query with CSS query API", function () {
          var b = document.getElementById("test").querySelector("div b");
          var blist = document.getElementById("test").querySelectorAll("div b");

          assert(b, "Only the last part of selector matters");
          assert(blist.length === 1, "it returns elements which shall not be returned");
        });
 

 

the problem is that with the element rooted query, only the last part of query is important. so even if there is no 'div' under the div element, it still return a item doing the query 

 

3. to work around the issue, you have the following. 

 

 

(function () {
  var count = 1;
  this.rootedQuerySelectorAll = function (elem, query) {
    var oldId = elem.id;
    elem.id = "rooted" + (count++);

    try {
      // is this the reason why the element-rooted query will be turned into some rooted queries?
      // still not quite sure about this point.
      alert("the new id is = " + "#" + elem.id + " " + query);
      return elem.querySelectorAll("#" + elem.id + " " + query);
    }
    catch (e) {
      throw e;
    }
    finally {
      elem.id = oldId;
    }
  };
})();
 

 

maybe the most interesting part of the workaround is to construct a new ID that is composed of a leading '#rooted', and one unique number to make the id different each call, and last the header is appended to the real query . Now could not figure out how this is possible, but it seems a possibility.

 

 

XPath based impl

 

 

 

 

 

DOM basded Impl

 

DOM basd impl is the most compliant way of impl for CSS selector engine. it has the following benefit.

 

 

  • works on old browsers, such as IE 6 and 7
  • backward compatibility 
  • For speed (some of the selectors are faster in pure DOM ) 

following is one of DOM based CSS selector function .

 

 

 

 

/**************************************
*@Summary
* cssselectordom.js
*  this is one implementation uses the DOM model to implements the CSS selector API.
*  
* 
* @Usage
*   
* @TODO:
* test it 
***************************************/

function find(selector, root) {
  root = root || document;

  var parts = selector.split(" "),
           query = parts[0],
           rest = parts.slice(1).join(" "),
           elems = root.getElementsByTagName(query),
           results = [];

  for (var i = 0; i < elems.length; i++) {
    if (rest) {
      results = results.concat(find(rest, elems[i]));
    }
    else {
      results.push(elems[i]);
    }
  }

  return results;
}
 

 

and below is the code that test it .

 

 

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <!--
     this demonstrate the use of the selector  based on the dom object model , which uses the getElementsByTagName(query) and others. 
    
     -->
     <script type="text/javascript" src="cssselectordom.js"></script>
     <script type="text/javascript" src="../unit.js"></script>
     <script type="text/javascript" >
       window.onload = function () {

         test("Test the CSS selector based implementation based on DOM", function () {
           var divs = find("div");
           assert(divs.length === 2, "Correct number of divs found");
           
           var divs = find("div", document.body);
           assert(divs.length === 2, "Correct number of divs found in the body");

           var divs = find("body div");
           assert(divs.length === 2, "Correct number of divs found in the body");

           var spans = find("div span");
           assert(spans.length === 2, "A duplicate span was found.");
         });
       };
     </script>

     <style type="text/css">
       #results li.fail{ color: Red}
       #results li.pass{color: Green}
     </style>
</head>
<body>

<div>
  <div>
    <span>Span</span>
  </div>
</div>
<ul id="results"></ul>
</body>
</html>

 

 

 

maybe the most interesting part of the workaround is to construct a new ID that is composed of a leading '#rooted', and one unique number to differentiate in each all of the method.

 

 

there is an alternative impl of the find method, this time it use getElementsByTagNames, and it will compare the parent's node until there is a match. 

 

here is the code. 

 

function bottomupFind(selector, root) {
  root = root || document;

  var parts = selector.split(" "),
  query = parts[parts.length - 1],

  rest = parts.slice(0, -1).join(" ").toUpperCase(),
  elems = root.getElementsByTagName(query),
  results = [];

  for (var i = 0; i < elems.length; i++) {
    if (rest) {
      var parent = elems[i].parentNode;
      while (parent && parent.nodeName != rest) { // you may differentiate the difference between the name and the nodeName properties
        parent = parent.parentNode;
      }
      if (parent) {
        results.push(elems[i]);
      }
    } else {
      results.push(elems[i]);
    }
  }
  return results;
}
 

 

and below is the test suite. 

 

         test("Test the CSS selector with a bottom up DOM impl", function () {
           var divs = bottomupFind("div");
           assert(divs.length === 2, "Corrent number of divs found.");

           var divs = bottomupFind("div", document.body);
           assert(divs.length === 2, "Corrent number of divs found.");

           var divs = bottomupFind("body div");
           assert(divs.length === 2, "Correct of vis found in body");

           var spans = bottomupFind("div span");
           assert(spans.length === 1, "No duplicate span was found");

         });
 

 

 

 

 

分享到:
评论

相关推荐

    query:queryJS是一个Javascript CSS Selector engine,小巧而功能强大,压缩后2k左右,可以很轻松的集成到代码当中

    query Javascript CSS Selector engine query是一个javascript css selector engine,小巧而功能强大,压缩后2k左右,可以很轻松的集成到代码当中。 支持浏览器 IE6+、Firefox、Chrome、Safari、Opera 联系作者 ...

    关于query Javascript CSS Selector engine

    query是一个javascript css selector engine,小巧而功能强大,压缩后2k左右,可以很轻松的集成到代码当中。支持浏览器 IE6+、Firefox、Chrome、Safari、Opera 选择器query(selector[,context]) div #intro div#...

    SelectorEngineJS:JavaScript 函数将返回给定 CSS 选择器的 DOM 元素

    创建一个 JavaScript 选择器引擎(即一个 JavaScript 函数,它将返回给定 CSS 选择器的 DOM 元素)。 您不能使用 JavaScript 库或 document.querySelector/document.querySelectorAll。 您应该只修改和提交 Answer...

    jquery 表单验证

    &lt;link rel="stylesheet" href="path/to/validationEngine.jquery.css" type="text/css"/&gt; &lt;script src="path/to/jquery.validationEngine.js" type="text/javascript" charset="utf-8"&gt; ``` #### 3.2 初始化验证...

    tiny-css-selector-engine:关于构建一个简单的 CSS 选择器引擎的技术测试

    CSS 选择器引擎测试 这个项目是一个用纯 Javascript 创建 CSS 选择器引擎的测试。 不允许使用document.querySelector()/document.querySelectorAll() 。

    jQuery左右切换动画幻灯片轮播特效.zip

    `engine1`可能是实现轮播功能的核心JavaScript文件。在jQuery中,实现左右切换的动画效果主要依赖于`.animate()`函数。这个函数允许开发者自定义元素的CSS属性(如left, opacity等)以实现平滑的动画过渡。通过...

    jquery表单验证插件

    其中,`selector`是用于选择元素的CSS选择器,`action`则是对这些元素执行的操作,如`click()`、`append()`等。 **二、表单验证的重要性** 表单验证能实时检查用户输入,防止无效数据提交,例如:邮箱格式错误、...

    Jets.js:原生CSS搜索引擎

    Jets.js通过提供一种快速的本地搜索机制,使得开发者能够以JavaScript执行高性能的CSS查询,从而提升了这一过程的效率。 首先,我们来了解一下CSS搜索引擎的重要性。在大型项目中,CSS选择器可能变得非常复杂,尤其...

    jquery 自动完成 Autocomplete

    在 `facebook_searchengine` 文件中,可能包含了一个模拟 Facebook 搜索功能的示例。这个示例可能会使用到上述的 Autocomplete 特性,通过输入用户的用户名或关键词,实时从服务器获取匹配结果,并显示在输入框下方...

    35个Google开源项目

    13. **Selector Shell**:这是一个基于浏览器的CSS测试工具,帮助开发者检查CSS在不同浏览器中的表现。 14. **Google Feed Server**:这是一个开源的Atom发布服务,基于Apache Abdera框架,可快速为各种数据源配置...

    令人头晕的是:〜简单的快速CSS选择器引擎〜

    特征: 完全实现CSS3和CSS4选择器jQuery扩展的部分实现相当不错的表现用法从获取Dizzle并像这样使用它: &lt; script src =" https://cdn.jsdelivr.net/npm/dizzle/dist/dizzle.umd.min.js " &gt; &lt;/ script &gt;...

    jQuery1.2API

    This function accepts a string containing a CSS selector which is then used to match a set of elements. The core functionality of jQuery centers around this function. Everything in jQuery is based ...

    webscrap:网页的信息选择器

    Selector引擎如Puppeteer(Node.js)和Selenium(多语言支持)则提供更高级的功能,它们可以模拟浏览器行为,执行JavaScript,处理动态加载的内容。例如,Puppeteer可以使用`page.$eval()`来运行页面上的选择器,并...

    jquery搜索引擎切换特效代码

    这里,`#search-engine` 是容器,`#search-input` 是输入框,`#engine-selector` 包含了不同搜索引擎的按钮,每个按钮通过 `data-engine` 属性标识对应的搜索引擎。 **二、CSS样式** 为了让界面看起来更美观,我们...

    重庆大学web开发技术-王成良-学堂在线解析

    * 选择器(selector) * 属性(property) * 值(value) * 单位(unit) 第三章:JavaScript基础 在本章中,教授介绍了JavaScript的基本概念和使用方法,包括变量、数据类型、操作符、控制结构等。学生将学习如何...

    scrapy-0.24文档

    - **Engine(引擎)**:负责调度请求和响应,协调整个框架的工作流程。 - **Scheduler(调度器)**:接收引擎发送的请求,并按照特定策略进行排队等待执行。 - **Downloader(下载器)**:负责实际的HTTP请求,...

    精通Scrapy网络爬虫_爬虫_scrapy_

    5. **Selector(选择器)**:Scrapy内置了XPath和CSS选择器,用于从HTML或XML文档中提取数据。选择器可以帮助我们快速定位和提取网页中的元素。 6. **Settings(设置)**:Scrapy项目的配置文件可以定制爬虫的行为...

    Weboldal

    CSS规则通常包含选择器(selector)和声明块(declaration block),如`.header {color: blue; font-size: 18px;}`,这将使所有类为`.header`的元素的字体颜色变为蓝色,字体大小为18像素。 【HTML与CSS的关联】 ...

Global site tag (gtag.js) - Google Analytics