2011-08-08 74 views
3

我只想将一些jQuery方法映射到其正常的Javascript DOM方法;将jQuery转换为常规Javascript映射

例如

prev() 
next() 
before() 
after() 

如果您可以将jQuery/Javascript映射到类似的DOM操作方法,那将会非常好。

+5

你为什么不只是看jQuery的来源? – jondavidjohn

+1

(其来源是https://github.com/jquery/jquery/blob/master/src/transing。js,但是它的确是一个大脑弯曲者,并且其声明仍然坚定地“jQuery”,通过本地DOM方法)。 – Matt

+0

完整功能中的方法?例如。 'prev'和'next'带选择器... –

回答

4

这些jQuery方法都没有在基于纯DOM的JS中精确的1对1模拟。如果他们这样做了,那么jQuery就不需要实现自己的方法来完成这些任务。

您可以使用elem.previousSiblingelem.nextSibling获取元素的上一个和下一个兄弟。例如,与此HTML结构:

<ul> 
    <li>First</li> 
    <li id="second">Second</li> 
</ul> 

你会使用这个JS:

var elem = document.getElementById("second"); 
var p = elem.previousSibling; 
alert(p.nodeType); 

在这种情况下,第二LI的前一个兄弟是第一LI。相反,前面的兄弟是两个LI标签之间的空白空间。这样做的目的是,除了实际的HTML元素外,您还可以操作文档中的任何文本节点。 nextSibling属性的工作原理完全相同。

这在理论上很好,但在实际使用中它或多或少是一种痛苦,因为你很少或从不真正需要操纵文档中的空白。要解决问题,请通过检查nodeType的兄弟进行迭代。如果nodeType为1,那么它是一个文本节点,因此跳到下一个,直到找到其nodeType不是1的节点。

您可能会发现博客文章Finding HTML elements using Javascript nextSibling and previousSibling有帮助。只需避免使用扩展Object.prototype的技术 - 通过这样做很容易打破对象上的对象循环。

至于before()after(),DOM相当于insertBefore()insertBefore()在您想要的目标之后的兄弟上运行。但是,您不能只是将一些HTML添加到这些内容中,并期望它能够正常工作。相反,您必须手动创建每个元素,属性和值作为DOM节点,然后插入它们。例如:

var welcomingDiv; 

function sayHi(){ 
    welcomingDiv = document.createElement("div"); 
    welcomingDiv.innerHTML = "Welcome, and be amazed!"; 


    target = document.getElementById("a-tag-someplace"); 
    document.body.insertBefore(welcomingDiv, target); 
} 

这会在任何标签的ID为“a-tag-someplace”之前将其插入到您的文档中。即使这是一种欺骗,因为innerHTML不是官方JS标准的一部分。如果你做得很好,你必须创建一个文本节点并将它附加到你新创建的DIV中。

简而言之:jQuery让生活变得更简单。没有一个很好的理由,不要重新发明轮子。

+0

很好的答案。 +1 – Matt

3
prev() - previousSibling, its a property 
next() - nextSibling, its a property 
before() - insertBefore, 
after() - There is no insertAfter method but we implement it using insertBefore 
+0

我相信它们实际上是$(node.previousSibling)et。人。是? – cwallenpoole

+0

+1请注意,“之后”可以通过使用“insertBefore”(如上所述)或者在父元素上使用“appendChild”来实现,以便在最后一个同级之后添加内容。 – maerics

+0

@cwallenpoole - 那是正确的。 – ShankarSangoli

0

以下是TreeWalker(play with it at jsbin.com)的JavaScript实现。

<html> 
<head></head> 
<body> 
    <script> 
     var NodeFilter = { 
      FILTER_ACCEPT: 1, 
      FILTER_REJECT: 2, 
      FILTER_SKIP: 3, 
      SHOW_ALL: -1, 
      SHOW_ELEMENT: 1, 
      SHOW_ATTRIBUTE: 2, 
      SHOW_TEXT: 4, 
      SHOW_CDATA_SECTION: 8, 
      SHOW_ENTITY_REFERENCE: 16, 
      SHOW_ENTITY: 32, 
      SHOW_PROCESSING_INSTRUCTIONS: 64, 
      SHOW_COMMENT: 128, 
      SHOW_DOCUMENT: 256, 
      SHOW_DOCUMENT_TYPE: 512, 
      SHOW_DOCUMENT_FRAGMENT: 1024, 
      SHOW_NOTATION: 2048 
     }; 

     var TreeWalker = function (root, whatToShow, filter, expandEntityReferences) { 
      this.root = root; 
      this.whatToShow = whatToShow; 
      this.filter = filter; 
      this.expandEntityReferences = expandEntityReferences; 
      this.currentNode = root; 
      this.NodeFilter = NodeFilter; 
     }; 

     TreeWalker.prototype.parentNode = function() { 
      var testNode = this.currentNode; 

      do { 
       if (
        testNode !== this.root && 
        testNode.parentNode && 
        testNode.parentNode !== this.root 
       ) { 
        testNode = testNode.parentNode; 
       } else { 
        return null; 
       } 
      } while (this._getFilteredStatus(testNode) !== this.NodeFilter.FILTER_ACCEPT); 
      (testNode) && (this.currentNode = testNode); 

      return testNode; 
     }; 

     TreeWalker.prototype.firstChild = function() { 
      var testNode = this.currentNode.firstChild; 

      while(testNode) { 
       if(this._getFilteredStatus(testNode) === this.NodeFilter.FILTER_ACCEPT) { 
        break; 
       } 
       testNode = testNode.nextSibling; 
      } 
      (testNode) && (this.currentNode = testNode); 

      return testNode; 
     }; 

     TreeWalker.prototype.lastChild = function() { 
      var testNode = this.currentNode.lastChild; 

      while (testNode) { 
       if(this._getFilteredStatus(testNode) === this.NodeFilter.FILTER_ACCEPT) { 
        break; 
       } 
       testNode = testNode.previousSibling; 
      } 
      (testNode) && (this.currentNode = testNode); 

      return testNode; 
     }; 

     TreeWalker.prototype.nextNode = function() { 
      var testNode = this.currentNode; 

      while (testNode) { 
       if (testNode.childNodes.length !== 0) { 
        testNode = testNode.firstChild; 
       } else if (testNode.nextSibling) { 
        testNode = testNode.nextSibling; 
       } else { 
        while (testNode) { 
         if (testNode.parentNode && testNode.parentNode !== this.root) { 
          if (testNode.parentNode.nextSibling) { 
           testNode = testNode.parentNode.nextSibling; 
           break; 
          } else { 
           testNode = testNode.parentNode; 
          } 
         } 
         else return null; 
        } 
       } 
       if (testNode && this._getFilteredStatus(testNode) === this.NodeFilter.FILTER_ACCEPT) { 
        break; 
       } 
      } 
      (testNode) && (this.currentNode = testNode); 

      return testNode; 
     }; 

     TreeWalker.prototype.previousNode = function() { 
      var testNode = this.currentNode; 

      while (testNode) { 
       if (testNode.previousSibling) { 
        testNode = testNode.previousSibling; 
        while (testNode.lastChild) { 
         testNode = testNode.lastChild; 
        } 
       } 
       else { 
        if (testNode.parentNode && testNode.parentNode !== this.root) { 
         testNode = testNode.parentNode; 
        } 
        else testNode = null; 
       } 
       if (testNode && this._getFilteredStatus(testNode) === this.NodeFilter.FILTER_ACCEPT) { 
        break; 
       } 
      } 
      (testNode) && (this.currentNode = testNode); 

      return testNode; 
     }; 

     TreeWalker.prototype.nextSibling = function() { 
      var testNode = this.currentNode; 

      while(testNode) { 
       (testNode.nextSibling) && (testNode = testNode.nextSibling); 
       if(this._getFilteredStatus(testNode) === this.NodeFilter.FILTER_ACCEPT) { 
        break; 
       } 
      } 
      (testNode) && (this.currentNode = testNode); 

      return testNode; 
     }; 

     TreeWalker.prototype.previousSibling = function() { 
      var testNode = this.currentNode; 

      while(testNode) { 
       (testNode.previousSibling) && (testNode = testNode.previousSibling); 
       if(this._getFilteredStatus(testNode) == this.NodeFilter.FILTER_ACCEPT) { 
        break; 
       } 
      } 
      (testNode) && (this.currentNode = testNode); 

      return testNode; 
     }; 

     TreeWalker.prototype._getFilteredStatus = function (node) { 
      var mask = ({ 
        /* ELEMENT_NODE */ 1: this.NodeFilter.SHOW_ELEMENT, 
        /* ATTRIBUTE_NODE */ 2: this.NodeFilter.SHOW_ATTRIBUTE, 
        /* TEXT_NODE */ 3: this.NodeFilter.SHOW_TEXT, 
        /* CDATA_SECTION_NODE */ 4: this.NodeFilter.SHOW_CDATA_SECTION, 
        /* ENTITY_REFERENCE_NODE */ 5: this.NodeFilter.SHOW_ENTITY_REFERENCE, 
        /* ENTITY_NODE */ 6: this.NodeFilter.SHOW_PROCESSING_INSTRUCTION, 
        /* PROCESSING_INSTRUCTION_NODE */ 7: this.NodeFilter.SHOW_PROCESSING_INSTRUCTION, 
        /* COMMENT_NODE */ 8: this.NodeFilter.SHOW_COMMENT, 
        /* DOCUMENT_NODE */ 9: this.NodeFilter.SHOW_DOCUMENT, 
        /* DOCUMENT_TYPE_NODE */ 10: this.NodeFilter.SHOW_DOCUMENT_TYPE, 
        /* DOCUMENT_FRAGMENT_NODE */ 11: this.NodeFilter.SHOW_DOCUMENT_FRAGMENT, 
        /* NOTATION_NODE */ 12: this.NodeFilter.SHOW_NOTATION 
       })[node.nodeType]; 

      return (
       (mask && (this.whatToShow & mask) == 0) ? 
        this.NodeFilter.FILTER_REJECT : 
        (this.filter && this.filter.acceptNode) ? 
         this.filter.acceptNode(node) : 
         this.NodeFilter.FILTER_ACCEPT 
      ); 
     }; 

     if (!document.createTreeWalker) { 
      document.createTreeWalker = function (root, whatToShow, filter, expandEntityReferences) { 
       return new TreeWalker(root, whatToShow, filter, expandEntityReferences); 
      }; 
     } 

     window.onload = function() { 
      var walker = document.createTreeWalker(document.getElementById('rootNodeDiv'), NodeFilter.SHOW_ELEMENT, null, false); 

      alert('currentNode: ' + walker.currentNode.id + ': firstChild: '  + walker.firstChild().id); 
      alert('currentNode: ' + walker.currentNode.id + ': nextNode: '  + walker.nextNode().id); 
      alert('currentNode: ' + walker.currentNode.id + ': lastChild: '  + walker.lastChild().id); 
      alert('currentNode: ' + walker.currentNode.id + ': parentNode: '  + walker.parentNode().id); 
      alert('currentNode: ' + walker.currentNode.id + ': previousNode: ' + walker.previousNode().id); 
      alert('currentNode: ' + walker.currentNode.id + ': nextSibling: '  + walker.nextSibling().id); 
      alert('currentNode: ' + walker.currentNode.id + ': previousSibling: ' + walker.previousSibling().id); 
     }; 
    </script> 
    <div id="parentNodeDiv"> 
     <div id="rootNodeDiv"> 
      <span id="previousNodeDiv"></span> 
      <span id="span01"> 
       <p id="span01p01">&nbsp;</p> 
       <p id="span01p02">&nbsp;</p> 
      </span> 
      <span id="span02"></span> 
      <span id="span03"> 
       <p id="span02p01">&nbsp;</p> 
      </span> 
      <span id="span04"></span> 
      <span id="span05"></span> 
     </div> 
    </div> 
</body>