次のようにリンクを書くことで、クリックで id="hoge" とあるタグのところが表示されるようになります。
<a href="#hoge">id="hoge" とあるタグのところへ</a>
長くスクロールするページの場合、このリンクがあれば「目次」として使えて便利です。
でもこの目次を手作業で作るのは面倒なのでjavascriptにさせようというわけです。
htmlではh2タグにidが記述されている。
headにjavascriptがあり、onloadで実行されるようにする。
h2タグのidをリンクに、h2の内容をリンク文字列にする
<h2 id="chap01">第一章</h2>
⬇
<a href="#chap01">第一章</a>
olとして加える
<ol> <li><a href="#chap01">第一章</a></li> <li><a href="#chap02">第二章</a></li> <li><a href="#chap03">第三章</a></li> <li><a href="#chap04">第四章</a></li> </ol>
window.onload = function() { … } と書くことで、ページが読み込まれたときに実行されます。
window.onload = function() { var emth2s = document.getElementsByTagName("h2"); var emtol = document.createElement("ol"); emth2s[0].parentNode.insertBefore(emtol,emth2s[0]); for(var i=0;emth2s.length>i;i++){ var idval = emth2s[i].getAttribute("id"); 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 に入れます。
h2要素の中のテキストノードからテキストを取り出して textval に入れます。
<h2 id="chap01">第一章</h2> なら、 idval = "chap01"; textval = "第一章"; とすることです。
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を増やしています。内容は関係ありません
WWWコンソーシアム(W3C),DOMの標準化。 1997年に策定作業が開始され, 1998年に「DOM Level 1」勧告 大幅に機能の強化を図った「DOM Level 2」が2003年1月に勧告 「DOM Level 3」が2004年4月に勧告
W3C DOMは,プログラミング言語に依存しない規定として策定されています。実際には,JAVA,PHP,Perlといったなじみのプログラミング言語でも,書き方に違いはあるものの,W3C DOMをサポート
最もシェアが高いInternet Explorerが,W3C DOMの準拠が遅れているため,完全には同じコードで済ますことはできません。しかし,W3C DOMとほぼ同じことがInternet Explorerでも独自の方法で利用することが可能です。
var list = document.getElementsByTagName('a'); var elm = list.item(1); alert(elm.href); var elm = list[1]; alert(elm.href);
run
未対応のブラウザが誤動作をするのを防ぐため
if (!document.getElementsByTagName) return false; if (!document.getElementById) return false; if (!document.getElementById("hoge")) return false;
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したところに落ち着く。