2011-08-08 5 views
3

jQueryメソッドのいくつかを通常のJavascript DOMメソッドにマッピングしたいだけです。従来のJavascriptマッピングへのjQuery

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

同様のDOM操作方法にjQuery/Javascriptのマッピングを提供できるのは本当に素晴らしいことです。

+5

なぜあなただ​​けのjQueryのソースを見てませんか? – jondavidjohn

+1

(ソースはhttps://github.com/jquery/jquery/blob/master/src/traversingです。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); 

をこの場合、第2のLIの前の兄弟がいない最初のLI です。代わりに、前の兄弟は2つの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)らであると信じています。 al。はい? – cwallenpoole

+0

+1最後の兄弟の後にコンテンツを追加する場合の親要素の "insertBefore"、または前述の "appendChild"を使用して "after"を実装できることに注意してください。 – maerics

+0

@cwallenpoole - thats correct。 – 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>