idとname



0   名前: Java夫 : 2007/05/18(金) 23:11  ID:gdO6X011 sub-9g
valueを得るときなどに用いられるidとnameの違いって何でしょうか?
どちらでも取得できますよね?

1   名前: 匿名 : 2007/05/18(金) 23:11  ID:2uGmwJft sub-Ds
まず、このサイトの過去ログを検索するだけでもいろいろな違いが
事例付きでわかる。IDとNAMEを併用したときの動作など重要なこ
とがぞろぞろ書いてある。ここの読者はすでに学習済み。


2   名前: 匿名 : 2007/05/18(金) 23:11  ID:5P4ENa.7 sub-Cz
とりあえず、以下を読んで HTML、XHTML の基礎文法を復習のこと。
http://www.asahi-net.or.jp/%7Esd5a-ucd/rec-html401j/struct/links.html#h-12.2.3
http://www.asahi-net.or.jp/%7Esd5a-ucd/rec-html401j/struct/objects.html#adef-name-IMG
http://www.asahi-net.or.jp/%7Esd5a-ucd/rec-html401j/interact/forms.html#adef-name-FORM
http://www.asahi-net.or.jp/%7Esd5a-ucd/rec-html401j/interact/forms.html#control-name
http://www.doraneko.org/webauth/xhtml10/20000126/Overview.html#h-4.10

その上で、以下を参照。
http://www2u.biglobe.ne.jp/%7Eoz-07ams/prog/dom-ref/HTML/HTMLCollection.html#HTMLCollection-namedItem
http://www2u.biglobe.ne.jp/%7Eoz-07ams/prog/dom-ref/HTML/HTMLDocument.html#HTMLDocument-images
http://www2u.biglobe.ne.jp/%7Eoz-07ams/prog/dom-ref/HTML/HTMLDocument.html#HTMLDocument-getElementsByName
http://www2u.biglobe.ne.jp/%7Eoz-07ams/prog/dom-ref/Core/Document.html#Document-getElementById

読んだ上で、分からなければもう一度聞いて下さい。

なお、JavaScript と Java を同じものだと思っているのなら、以下を熟読して考えを改めれ。
http://developer.mozilla.org/ja/docs/Core_JavaScript_1.5_Guide:JavaScript_Overview

3   名前: 匿名 : 2007/05/18(金) 23:11  ID:5P4ENa.7 sub-Cz
なお、Opera 9.5 では、getElementById() が name 属性を検索するバグが修正されるとのこと。
http://kuruman.org/diary/2007/05/09/kestrel-peregrine

4   名前: 匿名 : 2007/05/18(金) 23:11  ID:eKwtY88/ sub-Cz
先走ってまとめておく。ツッコミ歓迎。



まず、id 属性と name 属性は HTML で定義されているのですから、HTML のルールを確認します。

(a). 要素を識別するための name 属性は、HTML 4.0 で汎用的な id 属性が導入されたために、XHTML 1.0 で廃止予定となり、XHTML 1.1 で廃止されました。a、applet、form、frame、iframe、img、map 要素の name 属性が該当します。

(b). meta、param、およびフォームコントロール(button、input、object、select、textarea)など、特殊な役割を担う要素の name 属性は存続します。

だから、互換性を考慮するなら (a) の要素には name 属性と id 属性を並記しろと、昔からマトモな HTML 解説には書かれています(かつ、さらに慎重な人は大文字だけを使う)。まあ、HTML 4.0 から 10 年経った現在、id 属性に対応していないブラウザはほとんどありません。少なくとも、今どき a、form、img 要素に id 属性ではなく name 属性しか書いていないようなサンプルは、窓から投げ捨てて構いません

# ただし、HTML5 で (a) の name 属性のいくつかは復活する可能性がある。



次に DOM のルールを確認します。

(A). DOM1-HTML、DOM2-Core の Document.getElementById() は、ドキュメント中の id 属性(より厳密には ID 型の属性)を探し、指定値を持つ要素を返します。なお、IE は getElementById() で name 属性も探しますが、この動作を信用してはいけません。DHTML 時代の遺物です。

(B). DOM-HTML の document.images、document.forms など(つまり HTMLCollection.namedItem())は以下のルールに従います。
HTML ドキュメントでは、まず id 属性を検索し、それで見つからなければ(name 属性を持つ要素ならば)name 属性を探す。
XHTML ドキュメントでは id 属性のみを検索する。

# ただし、この記述は HTML 4.01: 18.2.2 の「name 属性を優先する」という記述と矛盾し、特に document.forms[0].elements はブラウザごとに複雑な状況になっている。もっとも、フォームコントロールはデータ送信の際に name 属性を必要とするため、name 属性を優先してくれた方が何かと便利ではある。

(C). DOM-HTML の HTMLDocument.getElementsByName() は以下のルールに従います。
HTML ドキュメントでは name 属性を持つ全要素を探す。
XHTML ドキュメントではフォームコントロールのみ検索する。



まあ、難しいことを考えたくなければ、一部の例外を除き、今どきフォームコントロール以外で name 属性なんぞ使ってはいけない、と覚えた方がマシです。と言うか、HTML のルールをきちんと知っていれば、ピンと来るはずです。

5   名前: 匿名 : 2007/05/18(金) 23:11  ID:eKwtY88/ sub-Cz
>>4
(B) の document.images、document.forms などに関して補足。

# なお、DOM-HTML の ECMAScript Language Binding に従い、
# document.images.item (0) は document.images[0] と等価、
# document.images.namedItem ('img1') は document.images['img1'] と等価
# であることに留意。

<p><img src="" alt="" name="img1" id="img2"></p>
<p><img src="" alt="" name="img2" id="img1"></p>

<form name="form1" id="form2"></form>
<form name="form2" id="form1"></form>

<script type="text/javascript">

document.images['img1'];  // ??
document.forms['form1'];  // ??

</script>

IE 6.0:
・document.images.namedItem() は、まず id を探し、見つかった最初の要素を返す。見つからなければ name を探し、見つかった最初の要素を返す。
・document.forms.namedItem() は、name または id を持つ全要素の HTMLCollection を返す。その namedItem() の戻り値も、name または id を持つ全要素の HTMLCollection を返す。それゆえ、個々の要素への参照は item(0)、item(1)([0]、[1])のように行う。

Firefox 1.5:
・namedItem() は、name であれ id であれ、最初に見つかった要素を返す。

Opera 9.0:
・namedItem() は、name または id を持つ全要素の HTMLCollection を返す。その namedItem() も、name または id を持つ要素の HTMLCollection となる。それゆえ、個々の要素への参照は item(0)、item(1)([0]、[1])のように行う。

Safari 2.0:
・namedItem() は、name または id を持つ全要素の配列(length を持つが Array ではない)を返す。それゆえ、個々の要素への参照は [0]、[1] のように行う。

従って、同じ書き方をしても、1 つの要素を返す場合と、要素のコレクションを返す場合があることに注意。例えば、document.forms['form1'].length が、Firefox では form 要素内のコントロール数を返すのに対し、それ以外では form 要素の個数を返すことになる。もっとも、このような状況に陥った時点で、そもそも HTML 的に不正なわけだが(理由は後述)。



次に、フォームコントロールの場合。
<form action="">
  <p>
    <input name="input1" id="input2">
    <input name="input2" id="input1">
  </p>
</form>

<script type="text/javascript">

document.forms[0].elements['input1'];  // ??

</script>

IE 6.0:
・document.forms と同じ。

Firefox 1.5:
・name または id を持つ全要素の NodeList を返す。それゆえ、個々の要素への参照は item(0)、item(1)([0]、[1])のように行う。

Opera 9.0:
・document.images、document.forms と同じ。

Safari 2.0:
・document.images、document.forms と同じ。

[/span]

従って、フォームコントロールを namedItem() で参照しようとすると、ほとんどのブラウザで name 属性と id 属性が一緒くたに扱われることに注意。例えば、ラジオボタンを扱う際や、label 要素を使用するときの id 属性の付け方に気を付けよう。



実際のところ、DOM-HTML 勧告に従って namedItem() を実装しているブラウザはほとんどない(IE がかろうじて)。まあ、この辺は DOM0 との互換性のため、ほとんど後付けだし。

img 要素、form 要素に関しては、そもそも name 属性と id 属性は同一値でなければならない。だから、本来なら上記のような事態になることはありえない。だが、妥当でない HTML を扱わざるをえない場合もある(ひどいケースでは、name 属性どころか id 属性の重複を平気で行うシステムもある)ので、一応調べてみた。

まあ、今どきフォームコントロール以外で name 属性なんぞ使わない方が良い。

6   名前: NullPo : 2007/05/18(金) 23:11  ID:Z0FHbpib sub-ii
ずっと不思議に思っていたのだけど、Elementオブジェクト(っていうの?)からgetElementsByName()が使えないのはなぜなのかな。
getElementsByTagName()なら動くのに。
<script type="text/javascript">

window.onload = function()
{
  var postForm = document.getElementById("postForm");
 //ここでエラー
  var textBoxs = postForm.getElementsByName("textBox");

  textBoxs.item(0).value = "あいうえお";
}

</script>

<form action="aaa" method="post" id="postForm">
<div>
 <input type="text" name="textBox" value="">
 <input type="text" name="textBox" value="">
 <input type="text" name="textBox" value="">
 <input type="text" name="textBox" value="">
</div>
</form>


--
getElementById()でname属性検索するのはやめてほしいよね。。。

7   名前: 匿名 : 2007/05/18(金) 23:11  ID:XAAZraUD sub-Ds
意味がよく分からないが、そのアクセスでgetElementsByName()があるとどう便利
なのか理解に苦しむ。そのためにelementsというここでやかましくいわれているア
クセスの記法があるわけでしょ。フォームのアクセスではtagで拾ってtypeofで判別
した方が早い。汎用性からしても、getElementsByName()は検索が遅い気がする。

8   名前: NullPo : 2007/05/18(金) 23:11  ID:05nvWK2y sub-.G
>>7
なんで便利かどうかと置き換えてしまったのか理解に苦しむ。
なんで使えないのかな。

9   名前: 匿名 : 2007/05/18(金) 23:11  ID:eKwtY88/ sub-Cz
>>6
形式的に答えるなら、getElementsByName() は HTMLDocument のメソッドだから。

ECMAScript のネイティブオブジェクト(Object、Number、String、Array、...)の他に、DOM 実装は Node、NodeList、NamedNodeMap、Document、Element、Attr、Text、... などをホストオブジェクトとして追加する。

DOM で最も基本的なオブジェクトは Node。Node から、Document、Element、Attr、Text といったオブジェクトが派生する。従って、これらは Node のメソッド・プロパティを継承し、さらに自分自身のメソッド・プロパティを持つ。

Document と Element に固有のメソッドとして、getElementsByTagName() が定義されている。つまり、Document#getElementsByTagName() と Element#getElementsByTagName() は、実は別々に定義されている

DOM-HTML をサポートする実装は、さらに HTMLDocument、HTMLElement、HTMLCollection といったオブジェクトを追加する。HTMLDocument は Document のメソッド・プロパティを継承し、HTMLElement は Element のメソッド・プロパティを継承する。

そして、HTMLDocument は固有のメソッドとして getElementsByName() を持つ。だから、HTMLDocument を継承しないオブジェクトや、HTMLDocument にキャストされないオブジェクトが、getElementsByName() を使用することはできない。

# Firefox、Opera 上では HTMLElement.prototype を弄れるから、getElementsByName() を追加することはできる(その手法の是非はともかく)。



「なぜ使えないのか」という根本的な問いなら、長くなりそうなので、以下ものすごく端折って書く。なお、これはあくまで私の個人的な意見。

・DOM1 では、getElementById() と getElementsByName() は、共に HTMLDocument(DOM1-HTML)のメソッドであり、HTML で定義済の属性名で探す。
・DOM2 では、getElementById() が Document のメソッドとして汎用化された(DOM2-Core)。getElementById() は id 属性を探すのではなく、ID 型属性を探す

ここで、「id 属性・name 属性」と「ID 型属性・NAME 型属性」は、全くの別物であることに注意。前者は HTML という言語で定義された属性名であり、後者は言語を設計する際のデータ型。

DOM2 で、getElementById() が属性名ではなくデータ型で検索するようになった一方で、getElementsByName() の立場は揺らいだ。HTML 4.0 の name 属性の大部分は CDATA 型であり、CDATA 型の属性は他にも沢山あるのだから、name 属性だけを特別視する理由はない。さらに言えば、XML では属性値に NAME というトークンは現れない。

DOM2 における名前空間の導入に伴い、getElementsByName() を接頭辞付き要素名で検索する汎用メソッドに変更しようとする意見もあったが、まあ最終的にはそのまま残された。ただし、XHTML 1.0 においてはフォーム部品のみを検索するという制限が付いた(これだけはよく用いられるし、廃止予定でもないから)。なお、接頭辞付き要素名で検索する汎用メソッドは、getElementsByTagNameNS() と命名された。

また、特定の範囲内でノードを検索する手段として Traversal&Range モジュールが考案されたし、今ならば XPath も使える(たぶん、これが最速)。だから実際のところ、「DOM0 との互換性」以外に、name 属性にこだわる理由は何もない。

# なお、DOM-HTML に忠実なコードを書こうとすると、ラジオボタンの扱いにハマるかもしれない。まあどの道、DOM0 だってラジオボタンの値を取得するにはループを回すわけで、数行増えたところで大した手間ではないのだけど。ただでさえ HTML のフォームは使いづらいのに、フォームのオブジェクトモデルは輪をかけて使いづらい。だから、Web Forms の拡張 DOM インタフェースはもっと思い切った改良をしても良かったと個人的には思う。まあ、XForms を使えという話になるだろうが。

10   名前: NullPo : 2007/05/18(金) 23:11  ID:Z0FHbpib sub-ii
>>9
おお、詳しいご説明ありがとうございます。
よくわかりました。

document ってのはDocumentっていうオブジェクトだったんですね。

11   名前: 匿名 : 2007/05/18(金) 23:11  ID:uHvAKwDQ sub-kJ
完全に余談だけど、IDL Definitions と ECMAScript Language Binding を見ながら、実際に DOM を JavaScript で実装してみても面白い。
// Node ////////////////////
function Node () {
    this.nodeName  = arguments[0]; /*String*/
    this.nodeValue = arguments[1]; /*String*/
    this.nodeType  = arguments[2]; /*Number*/
}

Node.ELEMENT_NODE   = 1;
Node.ATTRIBUTE_NODE = 2;
Node.TEXT_NODE      = 3;

Node.prototype.insertBefore = function (newChild /*Node*/, refChild /*Node*/) {
    return newChild;
};

Node.prototype.appendChild = function (newChild /*Node*/) {
    return newChild;
};


// Document ////////////////////
function Document (nodeAttrs) {
    Node.apply (this, nodeAttrs || [ ]);
    this.doctype         = arguments[1];
    this.documentElement = arguments[2];
    this.implementation  = arguments[3];
}

Document.prototype = new Node;
Document.prototype.constructor = Document;

Document.prototype.getElementsByTagName = function (tagName /*String*/) {
    return new NodeList;
};

Document.prototype.createElement = function (tagName /*String*/) {
    return new Element (null, tagName);
};

Document.prototype.createTextNode = function (data /*String*/) {
    return new Text (null, data);
};


// HTMLDocument ////////////////////
function HTMLDocument (documentAttrs) {
    Document.apply (this, documentAttrs || [ ]);
    this.title  = arguments[1];
    this.body   = arguments[2];
    this.forms  = arguments[3];
    this.images = arguments[4];
}

HTMLDocument.prototype = new Document;
HTMLDocument.prototype.constructor = HTMLDocument;

HTMLDocument.prototype.getElementsByName = function (elementName /*String*/) {
    return new NodeList;
};

HTMLDocument.prototype.open = function () {
};

HTMLDocument.prototype.write = function (text) {
};


// ////////////////////
window.document = new HTMLDocument (...);

いっそのこと、XML パーサを書いて DOM ツリーを構築してみると良い。そうすればブラウザに依存しない DOM 操作ができる。

http://d.hatena.ne.jp/m-hiyama/20050928/1127872305
http://nanto.asablo.jp/blog/2007/03/23/1339498

12   名前: NullPo : 2007/05/18(金) 23:11  ID:05nvWK2y sub-.G
>>11
それも面白そうですねー。

まぁ、私だとNodeListをどうやって実装するかでいきなりつまずくんですが。orz

一覧へ戻る