ウェブページ内の位置を特定

目次

idを使って位置を特定する(getElementById)

次の例は、その下に示すように、id="ex01"というidがついています。

例:ex01というidを持つp要素です

例:のhtmlでの記述
<p id="ex01">ex01というidを持つp要素です</p>

これをjavascriptから位置を特定するためには、次のようにします。

document.getElementById("ex01");

特定しただけでは、なにも嬉しくないので、この要素の値を変更してみます。

文字列の変更のキモはこれです。

document.getElementById("ex01").firstChild.nodeValue = "例:1111111111111"; //とか

プログラムの全体は次のようになっています。

scriptはhead部に書く方が好ましいのですが、ここではbody部に一緒に書いています。

<p>
<button type="button" onclick="chgex011()">111..に</button>
<button type="button" onclick="chgex012()">222..に</button>
<button type="button" onclick="chgex01b()">元に戻す</button></p>
<script>
function chgex011(){
  var target = document.getElementById("ex01");
  target.firstChild.nodeValue = "例:1111111111111";
}
function chgex012(){
  var target = document.getElementById("ex01");
  target.firstChild.nodeValue = "例:2222222222222";
}
function chgex01b(){
  var target = document.getElementById("ex01");
  target.firstChild.nodeValue = "例:ex01というidを持つp要素です";
}
</script>

.firstChild.nodeValueを使う条件

上で説明した .firstChild.nodeValue を使う方法は、getElementById()で得られるエレメントノードに変更したい文字列だけが入っていることを想定しています。もし、最初は空にしておきたいなら、半角スペースをいれるか、そこで改行しておかないとテキストノードがない状態になるのでうまくいきません。

一般的にjavascriptで文字列を表示したい場合は次のようなタグを作っておいてidで場所を特定し、そこに表示するということで十分でしょう。

<p id="result">結果はここに表示されます</p>

初期状態で空白にしたければ、スペースを入れます。

<td>計算結果:</td><td id="sum"> </td>

計算結果が数値であっても、自動的に文字列にして入れてくれます。

変更したい文字列が文章の一部の場合

もしも、.firstChild.nodeValueで変更したい文字列が文章の一部だった場合は、その部分をspanタグで囲み、idをつければよいのです。

ここの説明はgetElementById()の説明ですが、.firstChild.nodeValue の.firstChild(=最初の子)と.nodeValue(ノードの値)についても少し説明もしておきます。

一般のタグの中に文字列があるとブラウザは

エレメントノード(span)
文章中の <span id="ex02">

ex02というidを持つspan要素です

</span> 文章は続きます...

テキスト

firstChild(テキストノード)

という解釈をします。

javascriptを使って説明しておきましょう。


文章中の<span id="ex02">ex02というidを持つspan要素です</span>文章は続きます...

タグ名を使って位置を特定する(getElementsByTagName)

ページの中から指定するタグのノードを探して配列にして返してくれるメソッドです。

document.getElementsByTagName("p")

使ってみましょう。pタグの文字列の前に■番号■を加えます。

文字の追加をしているので、元に戻すのが面倒です。ページの再読込を使っています。location.reload()です。

プログラムは次のようになっています。

parrayがエレメントノードがオブジェクトとして格納される配列で、配列の要素数はparray.lengthで得られます。parray[0]で最初のノードにアクセスできます。

firstChildがテキストノードならfirstChild.nodeValueで文字列を得ることができます。これに"■番号■"を前に加えてテキストノードに戻します。テキストノードでなければ値はnullになりますから、"**番号**"からテキストノードを作って後ろに追加します。

<p><button type="button" onclick="allps()">p要素に■番号■を加えます</button></p>
<p><button type="button" onclick="location.reload();">元に戻す(reload)</button></p>
<script>
function allps(){
  var parray = document.getElementsByTagName("p");
  for(var i=0;parray.length>i;i++){
    var tmp = parray[i].firstChild.nodeValue;
    if (tmp!==null){ 
         parray[i].firstChild.nodeValue = "■"+i+"■"+tmp;
     }else{
         parray[i].appendChild(document.createTextNode(" **"+i+"**"));
     }
  }
}
</script>

ページ全体から集めるのは使いにくいので、次の使い方が必要になります。

範囲を限ってタグ名から位置を特定する

idから特定のエレメントノードを取得して、その中のノードを配列にします

var target = document.getElementById("ex03");
target.getElementsByTagName("p")

使ってみましょう。pタグの文字列の前に★番号★を加えます。

プログラムは最初の2行以外はほぼ同じです。■を★に、**を##にしただけです。

この節を <div id="ex03"> </div> で囲んであるところが大きく異なります。

<p><button type="button" onclick="allpsinex03()">p要素に★番号★を加えます</button></p>
<p><button type="button" onclick="location.reload();">元に戻す(reload)</button></p>
<script>
function allpsinex03(){
  var target = document.getElementById("ex03");
  var parray = target.getElementsByTagName("p");
  for(var i=0;parray.length>i;i++){
    var tmp = parray[i].firstChild.nodeValue;
    if (tmp!==null){ 
         parray[i].firstChild.nodeValue = "★"+i+"★"+tmp;
     }else{
         parray[i].appendChild(document.createTextNode(" ##"+i+"##"));
     }
  }
}
</script>

表やリストで活躍

ByIdのあとに、ByTagNameが活躍するのは、表やリストです。

var target = document.getElementById("ex04");
target.getElementsByTagName("td")

id="ex04"がtrについていれば、その行のtdを全部、tableについていれば表全体のtdが配列になります。

行は簡単にイメージできると思いますので、表全体をやってみましょう。

x
o o x
x o o

文字は追加ではなく入れ替えにしました。こちらの方が使用頻度が高いと思います。いままでは書き換え対象を説明文の中に設けてしまったので、入れ替えると文が通じなくなるので追加にしていたのです。

というわけで最初の x が、0 になって、色が青になります。

次は空白ですが、1 になって色が青になります。これは "<td> </td>" とタグ内にスペースだけのテキストノードがあるからです。

2 が、赤で表示されますが、これはこの場所が "<td></td>" とテキストノードがない状態にしてあるからです。.firstChild.nodeValue が使えないのですが、プログラムはその対策が打ってあってテキストノードを作って配置します。そしてそれとわかるように色を赤に設定します。

ボタンをもう一度押すと今度は全部のtdに文字が入っているので、.firstChild.nodeValue が使えます。文字を入れ替えて(入れ替えても同じ数字ですが)色を青にします。色指定をしないといつまでも赤が残るので、不要ではありますが青にします。

プログラムです。

<p><button type="button" onclick="tabletdx()">td要素に通し番号を加えます</button></p>
<p><button type="button" onclick="location.reload();">元に戻す(reload)</button></p>
<script>
function tabletdx(){
  var target = document.getElementById("ex04");
  var parray = target.getElementsByTagName("td");
  for(var i=0;parray.length>i;i++){
    if (parray[i].firstChild!==null){ 
         parray[i].firstChild.nodeValue = i;
         parray[i].style.color = "#00f";
     }else{
         parray[i].appendChild(document.createTextNode(i));
         parray[i].style.color = "#900";
     }
  }
}
</script>

表部分のhtmlの冒頭は

<table id="ex04">
<tbody>
<tr>
<td>x</td>
<td> </td>
<td></td>
</tr>
<tr>
<td>o</td>
....

クラス名を使って位置を特定する(getElementsByClassName)

目新しいものを加えてみたのですが、DOM Level3 にはなくて、Level4 からのものでした。IEでは9から対応しているようですが、もう少し様子を見たほうがいいかもしれません。

タグの種類にかかわらず class="aaa" であれば対象にします。

上の文ではspanタグとpタグでやってみましたが、bタグiタグに設けるとわかりやすいかもしれません。

var target = document.getElementById("ex05");
var aaarray = target.getElementsByClassName("aaa");

使ってみましょう。

プログラムは次のようになっています。

<p><button type="button" onclick="allclasses()">aaaクラスのテキストを[a][ ]で囲む</button></p>
<p><button type="button" onclick="location.reload();">元に戻す(reload)</button></p>
<script>
function allclasses(){
  var target = document.getElementById("ex05");
  var aaarray = target.getElementsByClassName("aaa");
  for(var i=0;aaarray.length>i;i++){
    var tmp = aaarray[i].firstChild.nodeValue;
    if (tmp!==null){ 
         aaarray[i].firstChild.nodeValue = "[a]["+tmp+"]";
     }else{
         aaarray[i].appendChild(document.createTextNode(" ##"+i+"##"));
     }
  }
}
</script>

複数のクラスの指定

classはもともとスペース区切りの文字列を与えることで複数のクラスに所属させることができます。たとえば、class="aaa bbb" と書いた要素は、aaaクラスでもあるし、bbbクラスでもあるので、getElementsByClassName("aaa")でも、getElementsByClassName("bbb")でも対象にならなければなりません。

使ってみましょう。

さらに引数にもスペース区切りの複数のクラスを書くことができます。たとえばgetElementsByClassName("aaa bbb")です。同じボタンですでに動いているはずです。

この指定は、aaaクラスであり、かつbbbクラスでもある要素が対象になります。

aaaクラスの要素と、bbbクラスである要素を両方あわせたものではありません。

また、厳密にclass="aaa bbb"と書かれている要素を意味するのではありません。class="bbb aaa"でも、class="bbb aaa ccc" でも対象になります。

少し試してみます。これは"aaa bbb"です。bbbだけの要素も入れておきます。その他にさらに"ccc bbb"も含めておきます。

プログラム

buttonタグに書かれたstyle属性は悪名高いfont属性のような使い方でおすすめできませんが、ここ限定で使っていますボタンの背景色の設定のためです。

.style.backgroundColorは.firstChild.nodeValueに変えて使いました。文字の追加より色の変化のほうがわかりやすいでしょう。

function multiclear()はクリアボタンがあると便利という発想で加えましたが、引数の扱いに使い慣れない方法を使ったので互換性が心配です。"aaa bbb"が"aaa"または"bbb"の意味でないので、このやり方が必要なのです。

'transparent'は今は対応しないブラウザはないと思いますが、透明にして親要素の色を出すようにするという指定です。

<p><button type="button" onclick="multiclasses('aaa','#fcc')" style="background-color:#fcc;">
(1) "aaa" : aaaを含むものを赤に</button></p>
<p><button type="button" onclick="multiclasses('bbb','#ccf')" style="background-color:#ccf;">
(2) "bbb" : bbbを含むものをを青に</button></p>
<p><button type="button" onclick="multiclasses('aaa bbb','#cfc')" style="background-color:#cfc;">
(3) "aaa bbb" : 両方を含むものを緑に</button></p>
<p><button type="button" onclick="multiclasses('bbb aaa','#ffa')" style="background-color:#ffa;">
(4) "bbb aaa" : 両方を含むものを黃に</button></p>
<p><button type="button" onclick="multiclear('aaa','bbb')" style="background-color:#ddd;">
(5) 両方をクリア</button></p>
<script>
function multiclasses(cl,bc){
  var target = document.getElementById("ex06");
  var aaarray = target.getElementsByClassName(cl);
  for(var i=0;aaarray.length>i;i++){
     aaarray[i].style.backgroundColor = bc;
  }
}
function multiclear(){
  var target = document.getElementById("ex06");
  for(var a=0;arguments.length>a;a++){
    var aaarray = target.getElementsByClassName(arguments[a]);
    for(var i=0;aaarray.length>i;i++){
      aaarray[i].style.backgroundColor = 'transparent';
     }
  }
}
</script>

互換性

getElementById getElementsByTagName はDOM Level 1 からの標準であり、安心して使える枯れたメソッドです。

getElementsByClassNameについては firefox 52.6.0 で動作確認しましたが、その他の検証はしていません。DOM Level 4 、及び DOM Living Standard の標準です。