「応用 ページ内目次をつくる」ではidの書いていない h2 要素は目次にはなりましたが、リンクは働きません。href="" に書くべき文字列が取得できないからです。
今回はidのないh2要素にjavascriptで自動的にidをつけ、それをリンクに使うことにします。
(ただしver3.5あたりのfirefoxだとidがない場合のリンク先は「#null」になります。属性がないという意味のnullをそのまま値として使ってしまっています。これは不正だと思います。もし別にid="null"があればそちらにリンクしてしまいます。)
htmlではh2タグがある。idはあってもよいしなくても良い。
headにjavascriptがあり、onloadで実行されるようにする。
h2タグのidをリンクに、h2の内容をリンク文字列にする
<h2>第一章</h2>
⬇
<a href="#auto1">第一章</a> ....... <h2 id="auto1">第一章</h2>
olとして加える
<ol> <li><a href="#auto0">第一章</a></li> <li><a href="#auto1">第二章</a></li> <li><a href="#auto2">第三章</a></li> <li><a href="#auto3">第四章</a></li> </ol>
もし、idがあるh2要素だったときはそのidを使います。これは他のページからの参照をさせたいh2には予めidをつけておくほうが便利だからです。
autoという文字列は安易な例です。htmlの作者がたまたま同じidをつけてしまうことがないように、使いそうもない文字列にしたほうがいいでしょう。
window.onload = function() { … } と書くことで、ページが読み込まれたときに実行されます。
window.onload = function() { var emth2s = document.getElementsByTagName("h2"); var emtol = document.createElement("ol"); emth2s[0].parentNode.insertBefore(emtol,emth2s[0]); var ct = 0; for(var i=0;emth2s.length>i;i++){ var idval = emth2s[i].getAttribute("id"); if (! idval ){ idval = "auto"+ct; ct=ct+1; emth2s[i].setAttribute("id",idval); } var textval = emth2s[i].firstChild.nodeValue; var textnd = document.createTextNode(textval); var emta = document.createElement("a"); emta.appendChild(textnd); emta.href = "#"+idval; var emtli = document.createElement("li"); emtli.appendChild(emta); emtol.appendChild(emtli); } }
まずページ内の h2 要素を拾って配列をつくり emth2s という名前をつけます。
新しく ol要素をつくり、emtol という名前をつけます。
最初のh2要素(emth2s[0])の前に配置(insertBefore)します。
このol要素はまだ空っぽですが、この後詰め込んでいきます。もちろん先にol要素の内容まで作って置いてから最後にinsertBeforeしてもかまいません。
forを使ってh2要素の数だけ繰り返します。
h2要素のid属性の値を idval に入れます。
idvalがnullの時や空文字列の時にidの値をautoに連番をつけたものにして、属性を設定します。
h2要素の中のテキストノードからテキストを取り出して textval に入れます。
<h2 id="chap01">第一章</h2> なら、 idval = "chap01"; textval = "第一章"; とすることです。
idがない場合は、
<h2>第一章</h2> なら、 idval = "auto0"; textval = "第一章"; とし、htmlも、 <h2 id="auto0">第一章</h2> とします。(あくまでメモリ上です。ファイルは変更されません)
textval からテキストノードを作って、textnd と名前をつけます。
a要素を作って emta と名前をつけます。
そのa要素 emta にテキストノード textnd を付け加え、
さらに href属性を付け加えます。href属性の値は idval に # 文字を加えたものにします。
<a href="#idval">textval</a> (実際には idval, textval の内容が入ります)
li要素を作って emtli と名前をつけます。
そのli要素 emtli に a要素 emta を付け加え、
そのli要素 emtli を ol要素 emtol に加えます。
<ol> <li><a href="#idval">textval</a></li> </ol>
この後は説明のためh2を増やしています。内容は関係ありません
特殊な値、プリミティブ値?
100番目の要素がないときに.item()でアクセスするとnull, 配列要素としてアクセスするとundefindとなる。
function fnc201(){ var list = document.getElementsByTagName('a'); var elm1 = list.item(100); //null alert(elm1); var elm2 = list[100]; //undefined alert(elm2); }
run
属性で title="spantitle" class="" という場合、classは空文字列、設定されていないidはnull
function fnc202(koko){ var txttitle = koko.getAttribute("title"); var txtclass = koko.getAttribute("class"); var txtid = koko.getAttribute("id"); alert("title:"+txttitle+"/ class:"+txtclass+"/ id:"+txtid); } // title:spantitle/ class:/ id:null
run <span title="spantitle" class="" onclick="fnc202(this)">
nullもundefinedも直接指定できる。
function fnc203(koko){ var msg; msg = msg + ":var_not_set_value_yet \n"; //undefined var testvar = undefined; msg += testvar + ":var_set_to_undef \n"; //undefinedにできる testvar == undefined? msg+=" testvar == undefined:true\n": msg+=" testvar == undefined:false\n"; var testvar = null; msg += testvar + ":var_set_to_null \n"; //nullにできる testvar == null? msg+=" testvar == null:true\n": msg+=" testvar == null:false\n"; testvar === null? msg+=" testvar === null:true\n": msg+=" testvar === null:false\n"; var testvar = 'null'; msg += testvar + ":var_set_to_'null' \n"; //'null'と区別できるか testvar == null? msg+=" testvar == null:true\n": msg+=" testvar == null:false\n"; testvar === null? msg+=" testvar === null:true\n": msg+=" testvar === null:false\n"; testvar == 'null'? msg+=" testvar == 'null':true\n": msg+=" testvar == 'null':false\n"; testvar === 'null'? msg+=" testvar === 'null':true\n": msg+=" testvar === 'null':false\n"; var testnul = 'null'; testvar = null; msg += "compare "+testvar+" with "+testnul+"\n"; //nullも'null'も表示は同じ testvar == testnul? msg+=" testvar == testnul:true\n": msg+=" testvar == testnul:false\n"; testvar === testnul? msg+=" testvar === testnul:true\n": msg+=" testvar === testnul:false\n"; testvar = undefined; testnul = null; msg += "compare "+testvar+" with "+testnul+"\n"; //undefined-null testvar == testnul? msg+=" testvar == testnul:true\n": msg+=" testvar == testnul:false\n"; testvar === testnul? msg+=" testvar === testnul:true\n": msg+=" testvar === testnul:false\n"; alert(msg); }
run
undefined:var_not_set_value_yet undefined:var_set_to_undef testvar == undefined:true null:var_set_to_null testvar == null:true testvar === null:true null:var_set_to_'null' testvar == null:false testvar === null:false testvar == 'null':true testvar === 'null':true compare null with null testvar == testnul:false testvar === testnul:false compare undefined with null testvar == testnul:true testvar === testnul:false
JavaScript初級者から中級者になろう
楽:技林ブログ
経済産業省による文字情報基盤整備事業
クッキー
NaNの値はNumber.NaNプロパティで取得することができます。JavaScript 1.3以降ではNumber.NaNを値に持つグローバル変数NaNが定義されていますが、グローバル変数NaNは後方互換のため、JavaScriptのプリミティブ値ではなく書き換え可能な変数として定義されています。NaNの値を取得する必要がある場合はNumber.NaNプロパティを使用してください。
alert( NaN ); // "NaN" NaN = 1; alert( NaN ); // "1" alert( Number.NaN ); // "NaN"
jsが無効にされているときを考慮して、aタグにイベントをつけている場合、jsが優先して実行されるので、js側では return false を最後に書き加えればaのリンクを無効にできる
function hoge(){ ..... ..... return false; }
逆に、js側に問題が発生したときに return true とすれば、jsの代わりに本来のaタグのリンクが有効になる。
if (!document.getElementById("hoge")) return true;
本文とjsを別ファイルで用意するとき、本文中の構造が期待通りに維持されないことが想定される。そのようなときの対策として有効。
ノードリスト(getElementsByTagNameで得られる)はArray()や[]で作られる配列とは異なりpop()やshift()は使えない
.onclickで追加する
obj.onclick = function() {......}
objはエレメントノードでないとだめなはず。ノードリストの要素でもよい。
function()は無名ファンクションといい、その場で生成する方法。
これば引数をつけられない
window.onload = functionname;
無名ファンクションを使えるが、これは()が必要。
window.onload = function(){ functionname1(); functionname2(); }
Simon Willson(http://simon.incutio.com)の方法
function addLoadEvent(func){ var oldonload = window.onload; if ( typeof window.onload != 'function'){ window.onload = func; } else { window.onload = function(){ oldonload(); func(); } } }
使い方は
addloadEvent(function1); addloadEvent(function2);
nullは言語ごとに表現が異なるのでjsではnullであると強調しておく
タイトル属性がないのはnull
var elm = document.getElementById('nulltest'); var msg = "title is null:" + (elm.getAttribute("title")===null) + "\n"; msg += "title string :" + (elm.getAttribute("title")); alert(msg);
run
タイトル属性が空文字列なのは null でなく空文字列
var elm = document.getElementById('emptyltest'); var msg = "title is null:" + (elm.getAttribute("title")===null) + "\n"; msg += "title string :" + (elm.getAttribute("title")); alert(msg);
run
タイトル属性があり、空文字列でないのは、もちろん null ではない。
var elm = document.getElementById('hastitletest'); var msg = "title is null:" + (elm.getAttribute("title")===null) + "\n"; msg += "title string :" + (elm.getAttribute("title")); alert(msg);
run
title属性がない | title="" | title="string" | |
elm.getAttribute("title")===null | true | false | false |
elm.getAttribute("title")!==null | false | true | true |
elm.getAttribute("title") | null | "" | string |
getAttribute("title")の値はgetAttribute("title")!=nullの値と異なるが、同様に使用できるという。
ternery operator
変数 = 条件 ? trueの場合 : falseの場合 ;
nodeNameはすべて大文字となる
目的のノードがtextノードなのか確認するにはnodeTypeを使う
doc.getElementsByTagName("form") | doc.form |
elm.getAttribute("src") | elm.src |
var src = elm.getAttribute("href"); | var src = elm.href; |
elm.setAttribute("src",hoge); | elm.src = hoge; |
画像を含むノードを作成しsetAttributeを試す。IEのテストになる
Chapter8 してはいけないことの説明の後、有用な使用例3つ。省略語のリスト、出典へのリンク、アクセスキー
Chapter9
要素ノードは(要素オブジェクトは)プロパティを持つ
parentNode, nextSibling, previousSibling, childNodes, firstChild, lastChild,, nodeType, nodeName,, style
このstyleはオブジェクトで、スタイル情報はstyleはオブジェクトのプロパティとして保存されている。
要素.style.プロパティ
ハイフォンを含むものはマイナスと区別するためキャメルケースとする
要素.style.color 要素.style.fontFamily /* for font-familly */
colorの値はrgb( , , )の形式に統一される
外部スタイルやstyleタグの設定はこれで読むことができない
スタイルの設定はできる
要素.style.プロパティ = 値
普通はテキストで指定するが、変数も可能
要素.style.color = "blue"; 要素.style.fontFamily = 'monospace';
適用すべき要素を特定
p.205 nextSiblingとnodeTypeを使ってh1の次の要素のスタイルを変える
反復的な指定
1行置きに背景色を変化させる
イベントによって変更
a要素以外にhoverを実現する(IEでもできる)
rows[i].onmouseover = function(){ this.style.fontWeight = "bold"; } rows[i].onmouseout = function(){ this.style.fontWeight = "normal"; }
jsでスタイルを設定するのは、構造、表現、振る舞いの3つを分けるという意味合いからは後味が悪い。
jsでclassを変更し、cssにしたがって見栄えが変わるほうがよく分離されているといえる
elm.setAttribute("class","rei");
または、
elm.className = "rei";
すでにあるクラスを上書きしてしまう。必要ならばクラスを調べて新しいクラスを半角スペースで連結することで解決できる
elm.className += " rei";
toplinkというエレメントを作って全部のh2要素に加えるつもりだったが、objectなので最後に加えた所だけに配置される。
var topstr = "topelementdefbyjavascript"; //String var targetp = document.getElementsByTagName("h1").item(0); //h1に targetp.setAttribute("id",topstr); //idをつける var items = document.getElementsByTagName("h2"); //h2タグの配列 var toptext = document.createTextNode("▲"); var toplink = document.createElement("a"); toplink.appendChild(toptext); toplink.href = "#" + topstr; //リンクのノード作成 for(var i=0;items.length>i;i++){ items[i].appendChild(toplink); //全部のh2に同じものを } //appendできない
appendChildメソッドが代入のようなコピーではないのは予想できる。参照ならばひとつのオブジェクトが複数から参照されることもあり得る。しかし本当にオブジェクトがあってどこかにappendするので最後にappendしたところに落ち着く。