始めに
筆者について
JavaScriptを勉強し始めて、1日目。(Java-Gold取得済み)
JavaScriptを学んでみて
文法的には、Javaと通ずるものがあると感じた(’Java’Scriptなのだからそれはそうどうやら関係ないらしい)。参考にした書籍では、長々とレガシーなJavaScriptの文法について、説明されたが、結局、ES2015によるオブジェクト指向構文が登場し、今の感想としては、結局何がJavaScriptなのかわからなくなっている。
記事の内容
「[改訂新版]JavaScript 本格入門」 Chapter6 「HTMLやXMLの文書を操作する - DOM ( Document Object Model ) -」(山田祥寛, 出版 : 技術評論社) 以降を読みながら、メモをしたものなので、内容の誤記、誤字等に関しては、ご容赦いただいたうえで、ご指摘いただけると幸いである。またやんわりとHTMLなどに関する知識がないと難解な内容に感じるかもしれない。ご容赦。
6章 HTML,XML,DOM
DOMの基本
DOMはマークアップ言語(HTML,XML)にアクセスするための標準的な仕組み、ほとんどの言語でサポートされる。W3Cによって標準化がすすめられ、1-4レベルがあり、レベルが高いほど、高度な機能を提供している。
DOMではドキュメントをドキュメントツリーとして扱う。つまり、文書に含まれる要素や属性を、テキストをそれぞれオブジェクトとみなし、その集合を文書としてとらえる。(DOM画像検索 : https://bit.ly/3c6Wpw4)
それぞれのオブジェクトをノードと呼ぶ。
クライアントサイドのJavaScript知識
要素ノードを取得
・ id値をキーに要素を取得する - getElementByldメソッド
単一の要素の取得にはこのメソッドを利用するのが自然(らしい)。
document.getElementById(id)
id:取得した要素のid値
・ タグ名をキーに要素を取得する - getElement s ByTagNameメソッド
document.getElementsyTagName(name)
name : タグ名
引数を(*)にすることで、すべての要素を取得できる。
戻り値は、HTMLCollectionオブジェクト(リスト)
HTMLCollectionのメンバーには
length リストに含まれる要素数
item(i) i番目の要素の取得
namedItem(name) idまたはname属性が一致する要素を取得
がある。
・ name属性をキーに要素を取得 getElement s ByNameメソッド
document.getElementsByName(name)
name:name属性の値
戻り値は、NodeListオブジェクト(HTMLCollectionのnamedItemが使えない版)
・ class属性をキーに要素を取得 getElement s ByClassName メソッド
document.getElementsByClassName(clazz)
clazz:class属性の値
戻り値は、HTMLCollection
・ セレクター式に合致した要素を取得 querySelector / querySelectorAll メソッド
セレクター文で検索する要素についてを指定できる
document.querySelect(selector)
selector:セレクター式
セレクターを使うことで、簡潔に複数の検索条件を指定できるので、ぜひ利用してみるといいかもしれない。
ノードウォーキング
以上のgetXxxxメソッドらは特定の要素を取得するためのメソッド
→いちいち文書全体から検索するのは無駄が多い。
ドキュメントツリーという階層構造を利用して、あるノードを起点として、そこから相対的な位置にあるノード取得することができる。=ノードウォーキング
var s = document.getElementById('food');
// id = "food"の要素を取得
var opts = s.childNodes;
// 子ノードを取得(NodeList)
ここでNodeListに含まれるのは、要素(<>で囲まれた属性、タグなどのこと)だけではない。タグ間にある改行や空白はテキストノードみなされるため、返されるノードには、要素ノードとテキストノードが含まれる可能性がある。
nodeType(node)メソッドを用いることで、ノードの種類によって、処理を分けることができる
// 要素ノードのときの処理
if(nodeType(node) === 1){
do something;
}
firstChildプロパティは、その要素の最初の子ノードを示す。
nextSiblingプロパティは次の子ノードを示す。ない場合はnullを返す。
firstElementChildプロパティは配下の子の要素を返す。
nixtElementSiblingプロパティは次の兄弟の要素を返す。
これらの返り値はElement(要素)オブジェクトのみのため、nodeTypeで検査は不要である。
イベントドリブンモデル
ブラウザ上での、クリックされた、ポインタがのったなどのイベントに応じて処理を実行するのがJavaScriptの特徴である。このようなプログラミングモデルをイベントドリブンモデル(イベント駆動モデル)という。
イベントに対応してその処理内容を定義する関数をイベントハンドラ、イベントリスナという。
イベントハンドラ、イベントリスナの定義
イベントドリブンモデルでは次の三つを定義する必要がある、
・どの要素で発生したか
・どのイベントを
・どのハンドラ/リスナに関連付けられるか。
関連付けの方法としては、JavaScriptでは
・タグ内の属性として宣言
・要素オブジェクトのプロパティとして宣言
・addEventListenerメソッドを使って宣言する(DOM Level2で定義)
がある。
タグ内属性として宣言する方法
<input type="button" value="ダイアログ表示" onclick="btn_click()" />
//<タグ名 onイベント名="JavaScriptのコード">
function btn_click(){
window.alert('ボタンがクリックされました')
}
簡単な処理であれば、htmlコード内に直接入力することもできる。
<input type="button" value="ダイアログ表示" onclick="windows.alert("ボタンがクリック")" />
要素オブジェクトのプロパティとして宣言
本来、htmlファイル内にJavaScriptのコードを記述することは好ましくない。そこで、関連付けと、
イベントハンドラそのものをJavaScriptのコード内に記述することにする。
<input type="button" value="ダイアログ表示"/>
window.onload = function(){
document.getElementBtId('btn').onclick = function() = {
window.alert('ボタンがクリックされました。')
};
};
//obj.on event = function(){statements}
obj : windowオブジェクト、または要素オブジェクト
event: イベント名 statements: イベント発生時の処理
※イベント名はすべて小文字にする必要がある。
関数オブジェクト事態を渡すこともできる(関数の呼び出しなどを渡すことができない)。
addEventListenerメソッドで宣言
以上で上げてきた二つの方法では、同一の要素に対して、複数のイベントハンドラを紐づけられない。そこでイベントリスナを用いる。
elem.addEventLitener(type, listener, capture)
elem:要素オブジェクト type:イベントの種類
listener:イベントに応じて実行するべき処理 capture:イベントの方向
<input id="btn" type="button" value="ダイアログ表示"/>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('btn').addEventListener('click', function(){
widow.alert('ボタンがクリックされました。');
}, false);
}, false);
DOMoncontentLoadedイベントリスナはコンテンツ本体がロードされたときに実行され、コンテンツ本体と画像のロードを待ってから実行するonloadより、スクリプトの開始タイミングが分けられる。
ページの初期化処理はDOMContentLoadedイベントリスナで表すのが基本(らしい)。
属性値、テキストの取得・設定
要素の属性へのアクセスは、要素ノードの同盟のプロパティとしてアクセスできる。ただ、JavaScriptとHTML での属性を示すキーワードが若干の違いがある。そのために
elem.getAttributeメソッドなどを用いるとよい。
elem.getAttribute(name)
elem.setAttribute(name, value)
elem:要素オブジェクト name:属性名 value:属性値
var url = link.getAttribute('href')
link.setAttribute('href', 'http://xxx')
これによって差異を気にすることなく、プログラミングできる。また、引数が文字列なので、取得・設定する属性を動的にスクリプトから指定できる。
elem.attributesプロパティ
その要素にあるすべての属性リストを返すプロパティ。不特定の属性を取得・設定したときに用いる。
###テキストの取得・設定
innerHTML,textContentというプロパティを利用する。
要素ノードのこれらのプロパティにアクセスすることで、その要素が持つ、テキストを取得設定できる。
テキストの設定では、前者はタグや属性をを表す文字列を渡した場合に、それをHTMLに埋め込むが、後者は、渡されたテキストをプレーンテキストとして埋め込む。
特別な事情がない場合はtextContentを用いるのが無難だろう。
取得についても、二つで挙動が異なる。
前者を用いたテキストの取得は、HTML文字列(つまりテキストエディタで書かれた文字列自体)を返すが、
後者を用いたテキスト取得は、子要素からテキストのみを取り出して返す。
セキュリティ上、外部入力された文字列がHTMLに埋め込まれることは非常にまずいので、しない。(これがクロスサイトスクリプティング:XSS)
後半に続く