GANCHIKU.com

DOM検索効率化のメソッド群を作ってみた。

というわけで、もういっちょ。考えていたDOM検索効率を考えたメソッド群を作ってみた。

ええと、prototype.jsのElementオブジェクトにaddMethodsしていることからもわかるようにprototype.js必須っす。ええと、私の使っているprototype.jsは、1.5.1ね。script.aculo.us(v1.7.1_beta3)と一緒に使っているので。

document.getElementsByClassNameAndTagName = function(className, parentElement, tagName) {
  if (Prototype.BrowserFeatures.XPath) {
     return $(parentElement).getElementsByClassName(className);
  } else {
    var children = $(parentElement).getElementsByTagName(tagName || '*');
    var elements = [], child;
    for (var i = 0, length = children.length; i < length; i++) {
      child = children[i];
      if (Element.hasClassName(child, className))
        elements.push(Element.extend(child));
    }
    return elements;
  }
}

Element.addMethods({
  getElementsByClassNameAndTagName: function(element, className, tagName) {
    return document.getElementsByClassNameAndTagName(className, element, tagName);
  },

  nextElement: function(element) {
    do {
      element = element.nextSibling;
    } while (element && element.nodeType != 1);
    return $(element);
  },

  previousElement: function(element) {
    do {
      element = element.previousSibling;
    } while (element && element.nodeType != 1);
    return $(element);
  },

  firstChildElement: function(element) {
    var child = element.firstChild;
    while (child && child.nodeType != 1) {
      child = child.nextSibling;
    }
    return $(child);
  },

  lastChildElement: function(element) {
    var child = element.lastChild;
    while (child && child.nodeType != 1) {
      child = child.previousSibling;
    }
    return $(child);
  },

  childElements: function(element) {
    var children = [];
    var child = element.firstChild;
    while (child) {
      if (child.nodeType == 1) {
        children.push($(child));
      }
      child = child.nextSibling;
    }
    return children;
  },

  childElement: function(element, index) {
    var nodeIndex = 0;
    var child = element.firstChild;
    while (child) {
      if (child.nodeType == 1 && index == nodeIndex++) {
          return $(child);
      }
      child = child.nextSibling;
    }
    return null;
  },

  cleanWhitespaceRecursive: function(element) {
    var f = function(element) {
      var child = $(element).cleanWhitespace().firstChild;
      while (child) {
        if (child.nodeType == 1) {
          f(child);
        }
        child = child.nextSibling;
      }
    };
    f(element);
    return element;
  }
});

nextElement, previousElementはそのまんま。textNodeはすっ飛ばして、elementNodeだけを見ている。firstChildElementとlastChildElementはfirstElementとlastElementって命名しようかと思ったけど、childだということを意識したかったのでちょいと冗長だけど、これで堪忍してや。で、意味もそのまんま。textNodeをすっ飛ばして最初や最後のelementNodeを返す。

childElementsは、前回のポストの結果を考慮してfirstChildとnextSiblingを採用。elementNodeの配列を返す。childElementは、index指定でelementNodeを返す。本当は、こんな感じでchildElementsメソッドの返す配列のindexを返す方がすっきりしていていいんだけどなぁ。

  childElement: function(element, index) {
     return $(element).childElements()[index];
  },

しかし、それだとnextSiblingを全て見てまわってしまうので、遅くなりそうなので、不採用。

cleanWhitespaceRecursiveはついでの産物。今回作成したものとは関係がないのだけども、一応。HTMLコーダにじかにHTMLを書かれるとwhitespaceが入ってしまい、困るので再帰的に消してみることにした。JavaScriptで再帰をするときってやっぱり、ローカル変数に関数をぶちこんで、それを何度も呼び出す方がいいのかな、と思ったので、自分自身を何度も呼び出すような方は不採用。
自分自身を呼び出すのは、こんな感じか。

  cleanWhitespaceRecursive: function(element) {
    element = $(element);
    var child = element.cleanWhitespace().fistChild;
    while (child) {
      if (child.nodeType == 1) {
        child.cleanWhitespaceRecursive();
      }
      child = child.nextSibling;
    }
    return element;
  }

どっちがいいんだろうなぁ。。。

で、本当は、オプションで、$指定で返すか、そのままのelementを返すかを指定できるようにするかで迷ったのだけど、prototype.jsと一緒に使うことを前提としているので、$で返すようにした。これもパフォーマンスに関係してくるんだけど、まぁ、その辺は考慮中。

つーか、また後で追記したり、ソース修正するかもしれん。名前はなんでもよかったのだけど、domx.jsとしよう。

< !DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

  
    
    
    
    
    
    
    

  
  

ソースはここ。

domx.js
ライセンスは適当っす。自己責任で使ってちょ。

で、上のソースを動かす形にしたデモもここに置いておく。domx demo

うーん。そろそろjQuery使ってみようかなぁ。。。onReadyとか便利そうだし。。。インデントがタブなのが非常に嫌なので、敬遠しているのだけど。。。

全然関係ないが、ここ二日ほど愛知県図書館で開発をしている。なかなか良いね。ホットスポットもあるみたいだけど、契約をしていないのでインターネットにつなげない。でも、そのおかげで効率がいいよん。インターネットがあるとダラダラしちゃって、ダミだ。

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Shin Ohno 2003-2012