2011-08-08 67 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>