属性の取得と変更

最も有名なのは画像の入れ替え

[1]〜[6]のボタンを押すと、旗をあげます。[all down] で全員おろします。

flag flag flag flag flag flag
1 2 3 4 5 6
all down

プログラム

<table id="reds1">
.....省.....
<td><span class="b" onclick="redon(5)">5</span></td>
<td><span class="b" onclick="redon(6)">6</span></td>
</tr>
<tr><td colspan=6><span onclick="redoffall()">all off</span></td></tr>
</table>
<script>
function redon(n){
   var reds = document.getElementById("reds1");
   var redsimgs = reds.getElementsByTagName("img");
   redsimgs[n-1].src = "images/redon.png";
}
function redoffall(){
   var reds = document.getElementById("reds1");
   var redsimgs = reds.getElementsByTagName("img");
   for(var i=0;redsimgs.length>i;i++){
      redsimgs[i].src = "images/redof.png";
   }
}
</script>

ポイントはこれです。

imgElement.src = "fileName";

こちらも同じです。

imgElement.setAttribute("src","fileName");

これはもともとタグの中に、

<img src="fileName">

の様に 「属性=値」 と書いてある部分をjavascriptから変更しようというものです。

属性の値を調べる

[1]〜[6]のボタンを押すと、旗を上げているときには下げ、下げているときには上げます。[交代] で全員反転させます。現在の属性の値を調べて動作を変えています。

flag flag flag flag flag flag
1 2 3 4 5 6
交代 all down all up

プログラム

<table id="reds2">
.....省.....
<td><span class="b" onclick="redsw(5)">5</span></td>
<td><span class="b" onclick="redsw(6)">6</span></td>
</tr>
<tr>
<td colspan=6><span onclick="redswall()">交代</span>
<span onclick="redoffall2('off')">all down</span>
<span onclick="redoffall2('on' )">all up</span></td>
</tr>
</table>
<script>
function redsw(n){
   var reds = document.getElementById("reds2");
   var redsimgs = reds.getElementsByTagName("img");
   var redsfile = redsimgs[n-1].getAttribute("src");
   if (redsfile=="images/redof.png"){
      redsimgs[n-1].src = "images/redon.png";
   }else if(redsfile=="images/redon.png"){
      redsimgs[n-1].src = "images/redof.png";
   }
}
function redswall(){
   var reds = document.getElementById("reds2");
   var redsimgs = reds.getElementsByTagName("img");
   for(var i=0;redsimgs.length>i;i++){
      var redsfile = redsimgs[i].getAttribute("src");
      if (redsfile=="images/redof.png"){
         redsimgs[i].src = "images/redon.png";
      }else if(redsfile=="images/redon.png"){
         redsimgs[i].src = "images/redof.png";
      }
   }
}
function redoffall2(onof){
   var reds = document.getElementById("reds2");
   var redsimgs = reds.getElementsByTagName("img");
   var redsfile = "images/redof.png";
   if(onof=="on") redsfile = "images/redon.png";
   for(var i=0;redsimgs.length>i;i++){
      redsimgs[i].src = redsfile;
   }
}
</script>

ポイントはこれです。

value = imgElement.getAttribute("src");

こちらも同じはずですが、srcではこれはうまく行きません(ブラウザに依存するかもしれません)。

value = imgElement.src;

取得におけるsrcとgetAttributeの違い

実際で比べてみましょう。

flagsrcの値の取得

取得方法
.src
.getAttribute("src")

.getAttribute("src")では相対的なURLが、.srcでは完全なURLが得られるという違いのようです。

imgElement.srcはimgElementの持つ属性の中でsrcという名前の属性の値を直接読み書きするもの。getAttribute("src")はそのsrc属性を読むためのメソッドです。javascriptの操作で書き換えたものが表示されるわけですから、いつもhtmlファイルに書かれたものを値として返しているのではなく、htmlファイルから読んでメモリ中に読み込んだ属性を変更して、現在の値を返していると考えられます。

すると、絶対URLをsrcに覚えていてメソッドでは相対値に加工して返していると考えるのが妥当ですが、setAttibute()の代わりにsrcを使うときには相対値を使うことが可能ですので、属性の読み書き時にも加工が入っている可能性はあります。

srcとgetAttributeのを比較するプログラム

<p class="reds"><img src="images/redon.png" id="reds3"><span class="b" onclick="srcof('reds3')">srcの値の取得</span></p>
<div class="table">
<table>
<tr><th>取得方法</th><th>値</th></tr>
<tr>
<td>.src</td>
<td id="testsrc"> </td>
</tr>
<tr>
<td>.getAttribute("src")</td>
<td id="testget"> </td>
</tr>
</table>
</div>
<script>
function srcof(id){
   var reds = document.getElementById(id);
   document.getElementById("testsrc").firstChild.nodeValue=reds.src;
   document.getElementById("testget").firstChild.nodeValue=reds.getAttribute("src");
}
</script>

その他の属性

html要素の属性はタグに「属性名=値」と書いてあるものです。

ちなみに、html4の時代は値が半角英数字のみで構成されるときは""が不要でした。xhtmlになったときに必ず""でくくるとされました。colspan="3"などは""でくくるのに抵抗を感じたものです。html5になって元に戻りましたが、習慣とは恐ろしいもので""がないと落ち着かなくなっています。

よく使われる属性には、title, alt, class, style, onclickなど, href, disabled, checked, selected などがあります。

javascriptから使いたくなるのは、styleとそれよりスマートなclass、onclickなどイベントハンドラの設定、そしてそれに関係してdisabled

class属性の変更

class属性の用途は大半がcssでスタイルを設定するためでしょう。javascriptで文字色や背景色を変更したいという場合、style属性の変更と考えがちですが、設定項目が多い場合は、classで予めスタイルを設定しておいてclassの値を変更する方が便利です。

空と山と木の絵例として、画像をフロートにするのをあげてみます。左にフロートさせるときには右にmarginをとり左は0にして文字に合わせます。右のときは逆になります。

画像は文字と同じ扱いです。大きな画像は大きな文字が一つ混ざっているかの様に配置されます。文字と同じですから、ベースラインに合わせられます。つまり、yやpの下にはみ出る部分が画像の下に出るように配置されます。日本語の文字はyやpの下の部分も使って文字を配置しますから、画像はすこし上に配置されるように見えます。これは vertical-align:bottom の指定をすると回避できます。このページではそれを指定しています。

将来的に lang="ja" であればこれがデフォルトということになるかもしれませんが、今の所ブラウザは欧米の文章作法に合わせられています。

さて、プロートの効果を出すために、いらない説明も加えていますが、試してみましょう。

プログラムです。

leftではプロパティによる設定。rightはメソッド(=setAttribute)による設定です。どちらも同じです。わざと両方使ってみました。プロパティはclassが言語の予約語であるため、classNameにしなければなりません。

<p><img src="images/skymtrr13.jpg" id="threetreeimg">例として、... </p>
<p class="crearf">
<button type="button" onclick="setfloatl()">float:left</button>
<button type="button" onclick="setfloatr()">float:right</button>
<button type="button" onclick="resetfloat()">non float</button>
</p>
<script>
function setfloatl(){
   var imgf = document.getElementById("threetreeimg");
   imgf.className="leftimg";
}
function setfloatr(){
   var imgf = document.getElementById("threetreeimg");
   imgf.setAttribute("class","rightimg");
}
function resetfloat(){
   var imgf = document.getElementById("threetreeimg");
   imgf.removeAttribute("class");
}
</script>

cssは予め書いてあります。

.leftimg{
  float:left;
  margin:0 0.5em 0.5em 0;
}
.rightimg{
  float:right;
  margin:0 0 0.5em 0.5em;
}
.clearf{
  clear:both;
}

class属性の読み取りと変更

class属性の読み取りはあまり使うことがないかもしれません。classがスペース区切りの文字列となる作為的な例を試してみます。

「くだもの」は果物と書きますから果実ということです。りんごみかん、の他レモンメロンいちごスイカも果実です。さらに、なすびきゅうりピーマンなど普通には「やさい」と呼ばれているものですが果実です。野菜という文字からは果実とは違うものを指すはずですが、私達の感覚的な分類はそうなっていません。

(1) 各品目のclass属性の値を書き出します

結果はここに表示されます。

プロパティ,メソッドとも結果は同じです。

(2) classの書き換えにより背景色をつけてみます。次の性質に合致するものに背景色をつけます。

各品目のclassにはkaj,swt,treの単語がスペース区切りで入っています。それぞれ 果実、甘い、木本 を表す記号です。「りんご」は3つ共合致しますから、"kaj swt tree" というclassになっています。javascript内で "kaj swt tree" と "swt" を比較しても一致することはありませんので、"swt" が含まれているものという判断をするときには、.indexOf("swt")などで調べる必要があります。

cssは「含まれているかどうか」の判断をします。span.swt{background-color:#ffc;}とすると class="kaj swt tree" も#ffcになります。ただし、これではjavascriptで切り替えることはできませんし、3つを含むときは最後に指定した色になります。

そこで、spanの親のp要素のclassをjavascriptで kaj swt tree に切り替えることで色を変えます。

p.kaj span.kaj{ background-color:#fcc; }
p.swt span.swt{ background-color:#ff9; }
p.tre span.tre{ background-color:#cfc; }

spanのclassは固定ですが、pのclassを換えることで色が変わります。

(1)のプログラム

<p>
<button type="button" onclick="fruitprop()">プロパティで</button>
<button type="button" onclick="fruitmeth()">メソッドで</button>
<button type="button" onclick="fruitpreclear()">元に戻す</button>
</p>
<script>
function fruitprop(){
   var fruitsp = document.getElementById("fruits");
   var spans = fruitsp.getElementsByTagName("span");
   var classtrsprop = ".className(プロパティ)で\n";
   for(var i=0;spans.length>i;i++){
      classtrsprop += spans[i].firstChild.nodeValue +" : ";
      classtrsprop += spans[i].className+"\n";  //firstChild.nodeValue imgs[i].src = redsfile;
   }
   var preelm = document.getElementById("preelm");
   preelm.firstChild.nodeValue=classtrsprop;
}
function fruitmeth(){
   var fruitsp = document.getElementById("fruits");
   var spans = fruitsp.getElementsByTagName("span");
   var classtrsmeth = ".getAttribute('class')(メソッド)で\n";
   for(var i=0;spans.length>i;i++){
      classtrsmeth += spans[i].firstChild.nodeValue +" : ";
      classtrsmeth += spans[i].getAttribute("class")+"\n";  
   }
   var preelm = document.getElementById("preelm");
   preelm.firstChild.nodeValue=classtrsmeth;
}
function fruitpreclear(){
   var preelm = document.getElementById("preelm");
   preelm.firstChild.nodeValue="結果はここに表示されます。";
}
</script>

(2)のプログラム

<p>
<button type="button" onclick="fruitbgc('kaj')">果実(赤)</button>
<button type="button" onclick="fruitbgc('swt')">甘い(黄)</button>
<button type="button" onclick="fruitbgc('tre')">木本(緑)</button>
</p>
<script>
function fruitbgc(flg){
   var fruitsp = document.getElementById("fruits");
   fruitsp.setAttribute("class",flg);
}
</script>

class属性からindexOf()で分類

.indexOf("swt")などで分類します。

果実なら果物、甘い果実なら果物、木になるのなら果物という3つの分類方法について、納得できるものかどうかを確認します。

合致するもの 結果はここに
合致しないもの   表示されます

プログラムです

<p>
<button type="button" onclick="fruitspick('kaj')">果実</button>
<button type="button" onclick="fruitspick('swt')">甘い</button>
<button type="button" onclick="fruitspick('tre')">木本</button>
</p>
<script>
function fruitspick(kind){
  var fruitsp = document.getElementById("fruits");
  var spans = fruitsp.getElementsByTagName("span");
  var inc = "";
  var exc = "";
  for(var i=0;spans.length>i;i++){
    if (spans[i].getAttribute("class").indexOf(kind)>=0){
       inc += spans[i].firstChild.nodeValue +" ";
    }else{
       exc += spans[i].firstChild.nodeValue +" ";
    }
  }
  var fruits2tbl = document.getElementById("fruits2");
  var frutstds = fruits2tbl.getElementsByTagName("td");
  frutstds[1].firstChild.nodeValue=inc;
  frutstds[3].firstChild.nodeValue=exc;
  if(kind=='kaj'){
    frutstds[0].firstChild.nodeValue="果実である";
    frutstds[2].firstChild.nodeValue="果実ではない";
  }
  else if(kind=='swt'){
    frutstds[0].firstChild.nodeValue="甘い";
    frutstds[2].firstChild.nodeValue="甘くはない";
  }
  else if(kind=='tre'){
    frutstds[0].firstChild.nodeValue="木本植物の果実";
    frutstds[2].firstChild.nodeValue="草本植物の果実";
  }
}
</script>

style属性について

cssの仕様としてタグの属性として指定する方法があります。最後に指定されることになるので、cssでは最も優先される指定です。cssは主にファイルやhead部のstyleタグの中に記述し、style属性は補助的なものです。

style属性は個々のタグにつけられた属性なのですから、今までやってきたsrc属性やclass属性と同様の方法て読み書きできます。head部のstyleタグに書かれた設定は読み書きできません。

けれども、style属性は最も優先されますから、指定したことは実際に反映されますし、再指定することで変更も可能です。

styleタグもタグですから、現代的なjavascriptからはアクセス可能になっている可能性もありますが、様々なセレクタを制御するのは困難が予想されますし、上記のclassをコントロールすることで、ほとんどの要求が満足されそうですので不要でしょう。

タグ内に書くstyle属性は次のような形になります。

style="color:#f00;background-color:#ffe;"

style属性の変更

もともとスタイルが設定されていてもいなくても新たに指定したものになります。

3つのspan要素があります。(1)スタイルタグで設定したもの(2)style属性で設定したもの、そして、(3)style属性のないものです。

下記のメソッドを使っています。

spans[i].setAttribute("style","color:#f00;background-color:#ffe;");

こちらは下記のプロパティです。

spans[i].style = "color:#009;background-color:#eef;";

style属性の指定が「全取換」になりますから、以前に指定していたものが今回指定がないと無効になります。

次のボタンは色を指定しますが、背景色の指定がなく、下線が加わっています。

スタイルタグで指定したものはなくなりませんから、通常のcssのルールで生かされます。

下記のメソッドを使っています。

spans[i].setAttribute("style","color:#f00;text-decoration:underline;");

こちらは下記のプロパティです。

spans[i].style = "color:#009;text-decoration:underline;";

プログラム

<p id="styletest" class="testtgt">3つのspan要素があります。
<span class="instyletag">(1)スタイルタグで設定したもの</span>、
<span style="color:#060;background-color:#cff;">(2)style属性で設定したもの</span>、
そして、<span>(3)style属性のないもの</span>です。</p>
<p>
<button type="button" onclick="style01()">変更(色:赤;背景:黄)</button>
</p>
<script>
function style01(){
   var stest = document.getElementById("styletest");
   var spans = stest.getElementsByTagName("span");
   for(var i=0;spans.length>i;i++){
      spans[i].setAttribute("style","color:#f00;background-color:#ffe;");
   }
}
</script>

forの内側の1行を変えて01〜04としています。

styleの個別指定

今までの指定方法ではstyle属性の指定が「全取換」になるので、前の指定がなくなりました。

属性のの変更ですから、理解できる動作です。

<span style="color:#f00;background-color:#ffe;">

style要素での設定やclass属性の変更と合わせれば、この制約はさほど支障にはなりません。

しかし、プロパティでの指定をもう一歩踏み込んで使えばcssの個々の設定を個別に独立して指定できます。昔から使えました(IEがsetAttributeに対応していないときでも使えました)ので知っていると便利なことがあります。

一括指定

element.style = "color:#f00;background-color:#ffc;text-decoration:underline";

個別指定

element.style.color ="#f00";
element.style.backgroundColor = "#ffc";
element.style.textDecoration = "underline";

背景色の設定は background-color:#fcc; などとなりますが、ハイフォンで結合されているものは、.backgroundColor とキャメル表記をしてハイフォンを排除します。

styleの個別指定の実際

さきほどと同じものを用意しました。色,背景色,線 が個別に設定されることを確認してください。

指定なし("")を選択したときだけ、スタイルタグの設定が残ります。

下の表は設定したstyle属性を読み取って表にして確認できるようにしました。

3つのspan要素があります。(1)スタイルタグで設定したもの(2)style属性で設定したもの、そして、(3)style属性のないものです。

ここまでは個別指定です。

最後の3つは個別でない指定です。

.style .style.color .style.backgroundColor .style.textDecoration
(1)
(2)
(3)

(1)〜(3)のスタイル属性を .style.xxx で読み取り、表にします。

1 2 3 4
(1)
(2)
(3)

(1)〜(3)のスタイル属性を .getAttribute("style") で読み取り、表にします。

.styleプロパティで"color:#f00;background-color:#ffe;"のような複数の設定をすることができましたが、これを読み込みに使うと、 [object CSS2Properties] というオブジェクトが返ってきます。これは普通の文字列でないのです。これを分解して中から設定を文字列として取り出すことができるかもしれませんが、今回は調べません。

.style.color や .style.backgroundColor で文字列を得ることができます。

カラーコードは十進数をコンマ区切りで並べる様式に変えられています。こちらだと透明度の表現が可能になります。

.getAttribute("style")メソッドはcssに書く background-color などそのままの文字列が返ります。;を区切り文字として切り分けて、表に書いたものです。

指定した順番になりますが、指定なし("")などを挟むと順番が変わります。

styleの個別指定に使ったプログラム

属性の読み取りに力が入っています。そもそもスタイルタグで設定しているものは読めないこともあり、余り必要のないことです。個別の設定と一括設定、属性の削除で内部がどうなっているか確認したかったというだけです。

<p id="styletest2" class="testtgt">3つのspan要素があります。
<span class="instyletag">(1)スタイルタグで設定したもの</span>、
<span style="color:#060;background-color:#cff;">(2)style属性で設定したもの</span>、
そして、<span>(3)style属性のないもの</span>です。</p>
<p>
<button type="button" onclick="style2c('#f00')">色:赤</button>
<button type="button" onclick="style2c('#90f')">色:紫</button>
<button type="button" onclick="style2c('#000')">色:黒</button>
<button type="button" onclick="style2c('')">色:指定なし("")</button>
</p>
<script>
function style2c(ncolor){
   var stest = document.getElementById("styletest2");
   var spans = stest.getElementsByTagName("span");
   for(var i=0;spans.length>i;i++){
      spans[i].style.color = ncolor;
   }
}
</script>
<p>
<button type="button" onclick="style2bc('#ffc')">背景色:黄</button>
<button type="button" onclick="style2bc('#cfc')">背景色:緑</button>
<button type="button" onclick="style2bc('transparent')">背景色:透過</button>
<button type="button" onclick="style2bc('')">背景色:指定なし("")</button>
</p>
<script>
function style2bc(ncolor){
   var stest = document.getElementById("styletest2");
   var spans = stest.getElementsByTagName("span");
   for(var i=0;spans.length>i;i++){
      spans[i].style.backgroundColor = ncolor;
   }
}
</script>
<p>
<button type="button" onclick="style2td('underline')">下線</button>
<button type="button" onclick="style2td('overline')">上線</button>
<button type="button" onclick="style2td('line-through')">取消線</button>
<button type="button" onclick="style2td('none')">なし(none)</button>
ここまでは個別指定です。
</p>
<script>
function style2td(nkind){
   var stest = document.getElementById("styletest2");
   var spans = stest.getElementsByTagName("span");
   for(var i=0;spans.length>i;i++){
      spans[i].style.textDecoration = nkind;
   }
}
</script>
<p>
<button type="button" onclick="style2cbc('p')">色:赤;背景:黄;(.style)</button>
<button type="button" onclick="style2cbc('p1')">色:緑;(.style)</button>
<button type="button" onclick="style2cbc('m')">色:青;背景:水;(.setAttr)</button>
最後の3つは個別でない指定です。
</p>
<script>
function style2cbc(pm){
   var stest = document.getElementById("styletest2");
   var spans = stest.getElementsByTagName("span");
   for(var i=0;spans.length>i;i++){
       if(pm=='p') spans[i].style = "color:#f00;background-color:#ffc;";
       if(pm=='p1') spans[i].style = "color:#0f0;";
       if(pm=='m') spans[i].setAttribute("style","color:#009;background-color:#cff;");
   }
}
</script>
<div class="table">
<table id="styleptable">
<tr>
<th></th>
<th>.style</th>
<th>.style.color</th>
<th>.style.backgroundColor</th>
<th>.style.textDecoration</th>
</tr>
<tr>
<td>(1)</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>(2)</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>(3)</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
</table>
<p><button type="button" onclick="styletblprop()">プロパティで</button>
(1)〜(3)のスタイル属性を .style.xxx で読み取り、表にします。</p>
</div>

<div class="table">
<table id="stylemtable">
<tr>
<th></th>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
</tr>
<tr>
<td>(1)</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>(2)</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>(3)</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
</table>
<p><button type="button" onclick="styletblmeth()">メソッドで</button>
(1)〜(3)のスタイル属性を .getAttribute("style") で読み取り、表にします。</p>
</div>

<script>
function styletblprop(){
   var stest = document.getElementById("styletest2");
   var spans = stest.getElementsByTagName("span");
   var styletbl = document.getElementById("styleptable");
   var trs = styletbl.getElementsByTagName("tr");
   for(var i=0;spans.length>i;i++){
      var tds = trs[i+1].getElementsByTagName("td");
      tds[1].firstChild.nodeValue = spans[i].style;
      tds[2].firstChild.nodeValue = spans[i].style.color;
      tds[3].firstChild.nodeValue = spans[i].style.backgroundColor;
      tds[4].firstChild.nodeValue = spans[i].style.textDecoration;
   }
}
function styletblmeth(){
   var stest = document.getElementById("styletest2");
   var spans = stest.getElementsByTagName("span");
   var styletbl = document.getElementById("stylemtable");
   var trs = styletbl.getElementsByTagName("tr");
   for(var i=0;spans.length>i;i++){
      var tds = trs[i+1].getElementsByTagName("td");
      var tmp = spans[i].getAttribute("style");
      if (tmp==null) continue;
      var props = tmp.split(";");
      for(var p=0;props.length>p;p++){
          tds[p+1].firstChild.nodeValue = props[p];
      }
   }
}
</script>