イベントについて

Posted コメントするカテゴリー: javascript

イベントについて

イベントについてまとめていきます。
javascriptは非同期のイベントドリブン型のイベント処理を行います。
主にブラウザ上でユーザの何らかの操作がされた時、イベントが生成されます。
また、画面操作以外にもブラウザ上のドキュメントがロードされた時のイベントや、
ユーザのマウス操作、フォームの操作等にもイベントを生成しています。

webアプリケーションでは、イベントが発生した時の処理をまとめて関数として作成し、
それを登録して処理を行います。

イベントタイプについて

イベントタイプは発生したイベントの種類を示します。
Event.typeとして書き、Eventインタフェースの読み取り専用プロパティ「type」を示します。
発生したイベントの種別を表します。
例として

keydown    // キーが最初に押された時
keypress   // キーが押された時(Ctrl、Alt、Shiftを除く)
keyup      // キーを離した時

mousedown  // マウスを押下した時
mouseup    // マウスを離した時
click      // マウスをクリックした時

等があります。

イベントターゲット、イベントハンドラ、イベントオブジェクトについて

イベントが発生したオブジェクトや関連するオブジェクトをイベントターゲットといいます。
「何」に対して、「どのような」イベントが発生したのかを定義する為、イベントターゲットとイベントは組み合わせて考えます(実装します)

イベントハンドラはイベントを処理する関数です。
イベントタイプとイベントターゲットを指定してイベントハンドラ関数をブラウザに登録してプログラムします。
指定したターゲット上でイベントが発生するとイベントハンドラが呼び出されます。

イベントオブジェクトはイベントが発生し、イベントハンドラが呼び出された時に一番目の引数に発生したイベント情報が格納されたオブジェクトが渡ります。
このオブジェクトのことをイベントオブジェクトと呼びます。
例えば、キーボードを押したときに発生するイベントに対しては、イベントオブジェクトを継承したキーボードイベントオブジェクト(KeyboardEventオブジェクト)が渡されます。
このオブジェクトにはユーザが押下したキー情報があり、プロパティを指定して参照することができます。
例えば

KeyboardEvent.altKey
KeyboardEvent.code
KeyboardEvent.ctrlKey

等があり、altKeyはAltキーが押下されている場合はtrue(Boolean)を返し、
codeは押下されたキーのキーコードを返し、
ctrlKeyはCtrキーが押下されている場合はtrue(Boolean)を返す
という動きになります。

また、マウス操作の場合には、イベントオブジェクトを継承したマウスイベントオブジェクト情報が格納されたオブジェクトが渡ります。
このマウスオブジェクトにはマウスポインタの座標が含まれたり、マウスボタンの状態も含まれています。

イベント伝播

イベント伝播を理解するには、「バブリング」と「キャプチャリング」の2通りの考え方があります。

イベント伝播 : バブリングについて

まずバブリングと呼ばれる考え方は、「イベント伝播はイベントが発生した際、どの要素にイベントが発生するかを決定する処理」と言えます。
HTMLDOM構造の中で発生したイベントはその要素の親要素へイベントが伝播していきます。
単一のDOM構造では、ユーザ操作したオブジェクト(要素)に対してイベントが発生しますが、
深くネストされたDOM構造では、ユーザが操作したオブジェクト(要素)の親要素にもイベントが発生します。
またその親要素自体もネストされていれば、親要素の親要素にもイベントが発生します。
このようにして、イベントが上の階層へ伝わっていくことをイベントバブリング(単にバブリング)と呼びます。

また、意図的に子要素のみでイベントを処理し、バブリングをさせない方法もあります。
「Event.bubbles」プロパティがfalseになっているとバブリングをせず、その要素のみでイベントが発生します。

イベント伝播 : キャプチャリングについて

次にキャプチャリングについてですが、イベントのバブリングとは逆に、ネストされたDOM構造の子要素で発生したイベントに対して、
Documentオブジェクト、html要素、body要素、div要素…と、DOMツリー構造の子、孫、その孫…という順番にイベントが伝播していくことを言います。

実際にはイベントリスナーの登録の際に、その要素がキャプチャリングの対象とするかを指定して呼び出します(デフォルトはfalseになっています)。
もし、キャプチャリングの対象とした場合は、目的の孫要素にイベント伝播が到達する前に、その上の階層のDOM要素で登録したイベントを呼ぶことができます。

以降の投稿では、これらのイベントについて、深く掘り下げて試していきます。

javascriptの命令で画面をスクロールさせる

Posted コメントするカテゴリー: javascript

javascriptの命令で画面をスクロールさせる

スクロールの設定について、試します。
以前の投稿(https://propansystem.net/blog/2022/04/26/post-7753/)では、スクロール位置を取得しましたが、
今回は、スクロールをjavascript側から設定する方法です。

スクロールを設定するメソッドは次のものがあります。
scrollTo()
scrollBy()

scrollToメソッドはスクロールの初期位置を設定します。
また、scrollByメソッドは、現在のスクロール位置から加算して、スクロール位置を設定します。

実際に次のようなサンプルを書いて試してみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1" style="width: 5000px; height: 5000px;">
	<div style="position:fixed; top:10px;">
		<div>X座標:<span id="x1"></span></div>
		<div>Y座標:<span id="y1"></span></div>
	</div>
</div>

<script type="text/javascript">
// ウィンドウ取得
let window_test = window;

// スクロールされたらメソッド「output_log_scroll」を呼ぶ
window.addEventListener('scroll', output_log_scroll);

// スクロール位置を強制指定
scrollTo(100, 200);

// スクロールの現在位置から、座標を加算する(この場合は、500, 700の位置になる)
scrollBy(400, 500);

// スクロール位置(X座標、Y座標)を出力する
function output_log_scroll()
{
	// x座標出力用の要素を取得
	let x1 = document.getElementById("x1");
	let y1 = document.getElementById("y1"); 

	// 要素を更新する
	x1.innerHTML = window_test.pageXOffset;
	y1.innerHTML = window_test.pageYOffset;

	console.log("window pageXOffset -> " + window_test.pageXOffset);
	console.log("window pageYOffset -> " + window_test.pageYOffset);
}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

上記のソースと、実際にブラウザでアクセスしてみるとわかりますが、
最初のscrollToメソッドで「横方向に100、縦方向に200」のスクロール位置を決定していますが、
次のscrollByメソッドで「横方向に400、縦方向に500」のスクロール位置を決定していので
結果的に「横方向に500、縦方向に700」のスクロール位置になっていることがわかります。

動的にスクロール位置を変更する

次に、スクロール位置を動的に変更してみます。
実際の開発では利用機会はほとんどありませんが、ここでは実験的な意味をこめてサンプルを書いてみます。

サンプルHTMLは次のように書きました。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1" style="width: 5000px; height: 5000px;">
	<div style="position:fixed; top:10px;">
		<div>X座標:<span id="x1"></span></div>
		<div>Y座標:<span id="y1"></span></div>
	</div>
</div>

<script type="text/javascript">
// ウィンドウ取得
let window_test = window;

// スクロールされたらメソッド「output_log_scroll」を呼ぶ
window.addEventListener('scroll', output_log_scroll);

// 50ミリ秒ごとに、スクロール値を加算していく
setInterval(function() {scrollBy(10, 25)}, 50);

// スクロール位置(X座標、Y座標)を出力する
function output_log_scroll()
{
	// x座標出力用の要素を取得
	let x1 = document.getElementById("x1");
	let y1 = document.getElementById("y1");

	// 要素を更新する
	x1.innerHTML = window_test.pageXOffset;
	y1.innerHTML = window_test.pageYOffset;

	console.log("window pageXOffset -> " + window_test.pageXOffset);
	console.log("window pageYOffset -> " + window_test.pageYOffset);
}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test2.html)

画面にアクセスしてみると、50ミリ秒ごとに

scrollBy(10, 25)

を実行して、スクロール位置が変化することがわかります。

ただし、画面上にあるdivタグ

<div id="test1" style="width: 5000px; height: 5000px;">
	<div style="position:fixed; top:10px;">
		<div>X座標:<span id="x1"></span></div>
		<div>Y座標:<span id="y1"></span></div>
	</div>
</div>

は、もともと幅、高さが5000pxのサイズを指定している為、スクロール位置がそれ以上になると、見た目の変化は止まります。

では、スクロールの加算が止まったあとは、setIntervalの命令はどうなるか、ログを入れて試してみます。

setInterval(function() {scrollBy(10, 25)}, 50);

let scroll_counter = 0;
setInterval(function() {
	scroll_counter++;
	console.log('scroll_counter -> ' + scroll_counter);
	scrollBy(10, 25)
}, 50);

という形で書き換えて実行してみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1" style="width: 5000px; height: 5000px;">
	<div style="position:fixed; top:10px;">
		<div>X座標:<span id="x1"></span></div>
		<div>Y座標:<span id="y1"></span></div>
	</div>
</div>

<script type="text/javascript">
// ウィンドウ取得
let window_test = window;
let scroll_counter = 0;

// スクロールされたらメソッド「output_log_scroll」を呼ぶ
window.addEventListener('scroll', output_log_scroll);

// 50ミリ秒ごとに、スクロール値を加算していく
setInterval(function() {
	scroll_counter++;
	console.log('scroll_counter -> ' + scroll_counter);
	scrollBy(10, 25)
}, 50);

// スクロール位置(X座標、Y座標)を出力する
function output_log_scroll()
{
	// x座標出力用の要素を取得
	let x1 = document.getElementById("x1");
	let y1 = document.getElementById("y1"); 

	// 要素を更新する
	x1.innerHTML = window_test.pageXOffset;
	y1.innerHTML = window_test.pageYOffset;

	console.log("window pageXOffset -> " + window_test.pageXOffset);
	console.log("window pageYOffset -> " + window_test.pageYOffset);
}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test3.html)

実際に画面アクセスして開発者ツールでログを確認すると、スクロールの動きが止まってもscrollByの命令は実行され続けています。
サンプルとして実験的に書いたプログラムなので、実際の開発ではこのようなことはしませんが、スクロールメソッドとその挙動を確認する為に試してみました。

要素の大きさ、位置の取得する

Posted コメントするカテゴリー: javascript

要素の大きさ、位置の取得

要素の大きさや、位置を取得する方法を試してみます。

ここでは、要素の大きさや位置を getBoundingClientRect() を使って取得します。
このメソッドで取得できる値は、ビューポート座標での要素位置になります。

実際に下記のサンプルを書いて動作させてみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div>
	<div>ウィンドウサイズ(getBoundingClientRect) :<span id="x1"></span></div>
</div>

<script type="text/javascript">
// ウィンドウ取得
let window_test = window;

//ロード時に一度呼ぶ
output_log_resize();

// リサイズされたらメソッド「output_log_resize」を呼ぶ
window.addEventListener('resize', output_log_resize);

// スクロール位置(X座標、Y座標)を出力する
function output_log_resize()
{
	let x1 = document.getElementById("x1");
	let cr = x1.getBoundingClientRect();
	console.log("cr -> " + cr);

	// オブジェクトの内容を確認する
	for(var key in cr){
		console.log(key + " : " + cr[key]);
	}

	// 要素を更新する
	x1.innerHTML = cr;

	console.log("window cr -> " + cr);
}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

上記URLにアクセスして、ウィンドウの幅や高さを変えたタイミングで開発者ツールのログには、
以下のように出力されます。

cr -> [object DOMRect]
x : 8
y : 8
width : 884
height : 24
top : 8
right : 892
bottom : 32
left : 8
toJSON : function toJSON() { [native code] }
window cr -> [object DOMRect]

また、上記の出力を確認した後、ウィンドの幅や高さを変更してみました。
すると、以下の出力に変わりました。

cr -> [object DOMRect]
x : 8
y : 8
width : 1073
height : 24
top : 8
right : 1081
bottom : 32
left : 8
toJSON : function toJSON() { [native code] }
window cr -> [object DOMRect]

ブラウザの幅に応じて、divタグの幅も変わっていることがわかります。
ただし、ブラウザの幅と高さを変更しても、divタグの縦方向には広がらない為、
高さを合わらず数値は変化しないこともわかります。

また、この出力で特徴的なのが「DOMRect」というオブジェクトが返ることです。
DOMRectは矩形を管理する機能を備えたインターフェイスで、
単独で新規のDOMRectオブジェクトを生成する時は次のように記載します。

let domRect = new DOMRect(0, 0, 100, 100);

引数はそれぞれ、x座標、y座標、幅、高さ、を表し、
newで生成すると、引数で指定した大きさのDOMRectオブジェクトを生成されます。

今回のサンプルでは「getBoundingClientRect」メソッドを使って、

	let x1 = document.getElementById("x1");
	let cr = x1.getBoundingClientRect();

の箇所で、画面上のDOM要素「x1」のHTMLDOMを基準として、
要素の寸法と、ビューポートに対しての相対位置情報を取得していることが確認できます。

ウィンドウの幅と高さを取得する

Posted コメントするカテゴリー: javascript

ウィンドウサイズの取得

javascriptでウィンドウサイズを取得する方法を試してみます。

ウィンドウサイズの取得は、windowオブジェクトのinnerWidth、innerHeightプロパティを使います。

innerWidthはウィンドウの内部の幅を取得し、
innerHeightはウィンドウの内部の高さを取得します。

実際に下記のサンプルを書いて動作させてみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div>
	<div>ウィンドウサイズ X軸:<span id="x1"></span></div>
	<div>ウィンドウサイズ Y軸:<span id="y1"></span></div>
	</div>
</div>

<script type="text/javascript">
// ウィンドウ取得
let window_test = window;

// リサイズされたらメソッド「output_log_resize」を呼ぶ
window.addEventListener('resize', output_log_resize);

// スクロール位置(X座標、Y座標)を出力する
function output_log_resize()
{
	// x座標出力用の要素を取得
	let x1 = document.getElementById("x1");
	let y1 = document.getElementById("y1");

	// 要素を更新する
	x1.innerHTML = window_test.innerWidth;
	y1.innerHTML = window_test.innerHeight;

	console.log("window pageXOffset -> " + window_test.pageXOffset);
	console.log("window pageYOffset -> " + window_test.pageYOffset);
}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

アクセスしてウィンドウの幅や高さを変えたタイミングでウィンドウ内部の幅と高さを取得できています。
ただし、このプロパティは読み取り専用なので、ウィンドウの幅を変更することはできないので、
ウィンドウサイズを変更するには別なメソッドを使う必要があります。

スクロール座標の取得

Posted コメントするカテゴリー: javascript

スクロール座標の取得

javascriptでの要素の位置を取得する方法を試してみます。

今回はスクロールバーの位置を取得してみます。

まず、要素の位置(座標)の取得の前に、座標の考え方として、
次の考えがあります。

横方向の X座標はウィンドウの左上を0とし、右方向に増える。
縦方向の Y座標はウィンドウの左上を0とし、下方向に増える。

また、javascriptではドキュメントを基に決定する方法と、
ウィンドウ(他のビューポート含む)を基に決定する方法があります。

css等ではビューポートを基準として座標を決定していますが、
javascriptではどちらの方法で取得するか、メソッドによって決まります。

上記を踏まえて、スクロールバーの座標位置を取得してみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1" style="width: 5000px; height: 5000px;">
	<div style="position:fixed; top:10px;">
		<div>X座標:<span id="x1"></span></div>
		<div>Y座標:<span id="y1"></span></div>
	</div>
</div>

<script type="text/javascript">
// ウィンドウ取得
let window_test = window;

// スクロールされたらメソッド「output_log_scroll」を呼ぶ
window.addEventListener('scroll', output_log_scroll);

// スクロール位置(X座標、Y座標)を出力する
function output_log_scroll()
{
	// x座標出力用の要素を取得
	let x1 = document.getElementById("x1");
	let y1 = document.getElementById("y1");

	// 要素を更新する
	x1.innerHTML = window_test.pageXOffset;
	y1.innerHTML = window_test.pageYOffset;

	console.log("window pageXOffset -> " + window_test.pageXOffset);
	console.log("window pageYOffset -> " + window_test.pageYOffset);
}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

上記のソースと、実際にブラウザでアクセスしてみるとわかりますが、
一つの大きなdiv要素を用意し、上下にスクロールを出しています。

また、自分自身のwindowオブジェクトを取得する為に、windowオブジェクトを定義しています。

そしてそこでwindowオブジェクトのプロパティ「pageXOffset」と「pageYOffset」を取得し、
画面とコンソールログに出力しています。

画面出力の為に各divタブにはcssを指定していますが、取得結果を表示する為に描画位置を固定しています。

DocumentFragment

Posted コメントするカテゴリー: javascript

DocumentFragment

DocumentFragmentは通常のノードとは少し違い、複数のノードをまとめて持つことができます。

また、単独で存在し、使用することができます。

DocumentFragmentのノードは、parentNodeを持つことがなくnullになります。
子ノードを持つことができるので、そのノードは操作することができます。

DocumentFragmentを使った実例を使って、どんな動きをするのかを確認してみます。

まずは、DocumentFragmentを作成してみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="p1" name="p1name">
	<div id="c1" name="c1name">c1text</div>
	<div id="c2" name="c2name">c2text</div>
	<div id="c3" name="c3name">c3text</div>
</div>

<script type="text/javascript">
// DocumentFragmentを作成する
let frag = document.createDocumentFragment();

console.log(frag);

</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

出力結果ですが、コンソールログには以下のように出力されます。

DocumentFragment []
​
baseURI: "https://propansystem.net/blogsample/js/040/test1.html"
​
childElementCount: 0
​
childNodes: NodeList []
​
children: HTMLCollection { length: 0 }
​
firstChild: null
​
firstElementChild: null
​
isConnected: false
​
lastChild: null
​
lastElementChild: null
​
nextSibling: null
​
nodeName: "#document-fragment"
​
nodeType: 11
​
nodeValue: null
​
ownerDocument: HTMLDocument https://propansystem.net/blogsample/js/040/test1.html
​
parentElement: null
​
parentNode: null
​
previousSibling: null
​
textContent: ""
​
<prototype>: DocumentFragmentPrototype { getElementById: getElementById(), querySelector: querySelector(), querySelectorAll: querySelectorAll(), … }

これは内容が空のDocumentFragmentノードが生成されたことを表します。

また、DocumentFragmentノードを作成しただけでは、まだHTMLドキュメントには何も影響を及ぼさないです。

別な方法だと、オブジェクトのコンストラクタを使用してnewすることもできます。

let frag = new DocumentFragment();

上記のように書くと同じノード「frag」が生成されます。

DocumentFragmentを使ってノードを生成する

では次にDocumentFragmentを使ってHTMLドキュメントに対してノードを追加してみます。

先ほどのHTMLサンプルに次のコードを追記しました。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="p1" name="p1name">
	<div id="c1" name="c1name">c1text</div>
	<div id="c2" name="c2name">c2text</div>
	<div id="c3" name="c3name">c3text</div>
</div>

<script type="text/javascript">
// DocumentFragmentを作成する
let frag = document.createDocumentFragment();

// 子ノードを作成する
let c4 = document.createElement('c4');
let c5 = document.createElement('c5');
let c6 = document.createElement('c6');

frag.append(c4);
frag.append(c5);
frag.append(c6);

console.log(frag);

</script>

</body>
</html>

サーバ上のHTMLはこちら(test2.html)

出力結果は以下のようになります。

DocumentFragment(3) [ c4, c5, c6 ]
​
baseURI: "https://propansystem.net/blogsample/js/040/test2.html"
​
childElementCount: 3
​
childNodes: NodeList(3) [ c4, c5, c6 ]
​
children: HTMLCollection { 0: c4, 1: c5, length: 3, … }
​
firstChild: <c4>
​
firstElementChild: <c4>
​
isConnected: false
​
lastChild: <c6>
​
lastElementChild: <c6>
​
nextSibling: null
​
nodeName: "#document-fragment"
​
nodeType: 11
​
nodeValue: null
​
ownerDocument: HTMLDocument https://propansystem.net/blogsample/js/040/test2.html
​
parentElement: null
​
parentNode: null
​
previousSibling: null
​
textContent: ""
​
<prototype>: DocumentFragmentPrototype { getElementById: getElementById(), querySelector: querySelector(), querySelectorAll: querySelectorAll(), … }

ここでは、DocumentFragmentノードに対して、c4、c5、c6の子ノードが追加されたことがわかります。

では次にDocumentFragmentを他のノードに追加してみます。
先ほどの例のHTMLを使い、「p1」のノードに対して、fragを追加してみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="p1" name="p1name">
	<div id="c1" name="c1name">c1text</div>
	<div id="c2" name="c2name">c2text</div>
	<div id="c3" name="c3name">c3text</div>
</div>

<script type="text/javascript">
// DocumentFragmentを作成する
let frag = document.createDocumentFragment();

// 子ノードを作成する
let c4 = document.createElement('div');
let c5 = document.createElement('div');
let c6 = document.createElement('div');

// 作成した子ノードに、HTMLタグとテキストをセットする
c4.appendChild(document.createTextNode('c4text'));
c5.appendChild(document.createTextNode('c5text'));
c6.appendChild(document.createTextNode('c6text'));

frag.append(c4);
frag.append(c5);
frag.append(c6);

console.log(frag);

// Elementノードを取得
let p1 = document.getElementById("p1");

// p1のノードにDocumentFragmentを追加する
p1.append(frag);

</script>

</body>
</html>

サーバ上のHTMLはこちら(test3.html)

出力結果についてですが、まず、console.logは以下のようになります。

DocumentFragment(3) [ div, div, div ]
​
baseURI: "https://propansystem.net/blogsample/js/040/test3.html"
​
childElementCount: 0
​
childNodes: NodeList []
​
children: HTMLCollection { length: 0 }
​
firstChild: null
​
firstElementChild: null
​
isConnected: false
​
lastChild: null
​
lastElementChild: null
​
nextSibling: null
​
nodeName: "#document-fragment"
​
nodeType: 11
​
nodeValue: null
​
ownerDocument: HTMLDocument https://propansystem.net/blogsample/js/040/test3.html
​
parentElement: null
​
parentNode: null
​
previousSibling: null
​
textContent: ""
​
<prototype>: DocumentFragmentPrototype { getElementById: getElementById(), querySelector: querySelector(), querySelectorAll: querySelectorAll(), … }

次に、画面上のHTMLソースは以下のようになります。(bodyタグ内だけの抜粋です)

<div id="p1" name="p1name">
	<div id="c1" name="c1name">c1text</div>
	<div id="c2" name="c2name">c2text</div>
	<div id="c3" name="c3name">c3text</div>
	<div>c4text</div>
	<div>c5text</div>
	<div>c6text</div>
</div>

どうゆう動作になったかというと、上の結果からもわかるとおり、
DocumentFragmentノードそのものは、元のp1の親ノードには影響を及ぼさず、もともとp1が持っていた
子ノードにも影響を及ぼさずに、DocumentFragmentにappendした子ノード「c4」「c5」「c6」だけがp1のノードに追加されています。

上記のような動きをするので、DocumentFragmentは一時的なDOMツリーを生成し、
そこに子ノードを追加してひとまとめにして、他の親ノードに対してまとめた子ノードを追加する。
といった場面で使えると言えます。

ノードの置換について

Posted コメントするカテゴリー: javascript

ノードの置換について

ノードの置換について試してみます。
一つ前の投稿でノードの削除をやりましたが、今回は削除するノードを置き換える動きです。
こちらも削除と同様に親ノードからたどって子ノードを指定し、そのノードを置き換えます。

実際にサンプルを用意して、ノードの置換をしてみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">
		<div id="p2" name="p2name">p2text</div>
		<div id="p3" name="p3name">p3text</div>
		<div id="p4" name="p4name">p4text</div>
		<div id="p5" name="p5name">p5text</div>
		<div id="p6" name="p6name">p6text</div>
	</div>
</div>

<script type="text/javascript">
// Elementノードを取得
let p1 = document.getElementById("p1");
let p2 = document.getElementById("p2");
let p3 = document.getElementById("p3");
let p4 = document.getElementById("p4");
let p5 = document.getElementById("p5");
let p6 = document.getElementById("p6");

// テスト用のノードを生成
let tn1 = document.createTextNode(" _TextNode1_ ");

// 取得した親ノード「p1」の子ノード「p4」を「tn1」に置換する
p1.replaceChild(tn1, p4);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

出力結果は次のようになります。
 ※…アクセスした画面のHTMLソースを抜粋

<div id="p1" name="p1name">
	<div id="p2" name="p2name">p2text</div>
	<div id="p3" name="p3name">p3text</div>
	 _TextNode1_ 
	<div id="p5" name="p3name">p5text</div>
	<div id="p6" name="p3name">p6text</div>
</div>

親ノードからたどり、4つめのノードが、生成した「_TextNode1_」ノードに置き換わっています。

注意が必要なのは、置き換える内容は、ノードでなければ動作はしません。
例えば

p1.replaceChild('test', p4);

という書き方でノードの「p4」を置き換えようとしても、第一引数に単純な文字列を指定しているので、関数が動作しません。
第一引数には「createElement」や「createTextNode」で生成した要素を指定することで、ノードの置換が可能になります。

ノードの削除について

Posted コメントするカテゴリー: javascript

ノードの削除について

ノードの削除について試してみます。
削除時の注意としては、削除する命令は親ノードに対して行い、
削除したい子ノードの何番目を削除するのかを指定します。

実際にサンプルを用意して、ノードの削除を試してみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">
		<div id="p2" name="p2name">p2text</div>
		<div id="p3" name="p3name">p3text</div>
		<div id="p4" name="p3name">p4text</div>
	</div>
</div>

<script type="text/javascript">
// Elementノードを取得
let p1 = document.getElementById("p1");
let p2 = document.getElementById("p2");
let p3 = document.getElementById("p3");
let p4 = document.getElementById("p4");

// 取得した親ノード「p1」の子ノード「p3」を削除
p1.removeChild(p3);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

出力結果は次のようになります。
 ※…アクセスした画面のHTMLソースを抜粋

<div id="p1" name="p1name">
		<div id="p2" name="p2name">p2text</div>
		
		<div id="p4" name="p3name">p4text</div>
	</div>

上記のjavascriptを実行した結果、子ノードの

<div id="p3" name="p3name">p3text</div>

が削除されていることがわかります。

また、親ノードから辿って子ノードの指定ができれば削除ができるので、
次のような書き方も可能です。

p3.parentNode.removeChild(p3);

上記の場合は、p3の子ノードから辿り、いったんparentNodeメソッドを使って、p3の親ノードをみて、
その後にremoveChildメソッドを使っています。

少し変則的ですが、下記のような書き方もできます。

p3.parentNode.removeChild(p2);

この場合は、p3の子ノードからparentNodeでp1を参照し、その後に子ノードである「p2」を削除しています。

出力結果は、

<div id="p1" name="p1name">
		
		<div id="p3" name="p3name">p3text</div>
		<div id="p4" name="p3name">p4text</div>
	</div>

という結果になります。

ノードの挿入について

Posted コメントするカテゴリー: javascript

ノードの挿入について

前回の投稿ではノードを作成しましたが、今回は、作成したノードを
HTMLドキュメントに挿入する方法を試してみます。

実際にサンプルを用意して、ノードの挿入を試してみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">p1text</div>
</div>

<script type="text/javascript">
// ID「test1」のノードを作成
let tn1 = document.createTextNode(" _TextNode1_ ");
console.log("tn1 -> " + tn1);

// Elementノードを取得
let p1 = document.getElementById("p1");

// 取得したノード「p1」に「tn1」を挿入
p1.appendChild(tn1);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

出力結果は次のようになります。
 ※…HTMLソースを抜粋

<div id="test1">
	<div id="p1" name="p1name">p1text _TextNode1_ </div>
</div>

また、appendChild()メソッドの他、insertBefore()メソッドもあります。
insertBeforeメソッドは、appendChildとは違い、挿入する位置が「前」になります。

具体的に次のようなサンプルを書いて、試してみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">p1text</div>
	<div id="p2" name="p2name">p2text</div>
	<div id="p3" name="p3name">p3text</div>
	<div id="p4" name="p3name">p4text</div>
</div>

<script type="text/javascript">
// ID「test1」のノードを作成
let tn1 = document.createTextNode(" _TextNode1_ ");
console.log("tn1 -> " + tn1);

// Elementノードを取得
let p1 = document.getElementById("p1");
let p2 = document.getElementById("p2");
let p3 = document.getElementById("p3");
let p4 = document.getElementById("p4");

// 取得したノード「p2」の前に「tn1」を挿入
p1.insertBefore(tn1, p2);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test2.html)

上記を実行し結果、「_TextNode1_」は画面上にどう出力されるか試してみました。

結果、予想とは違い、

console出力上では、以下のエラーメッセージが出ました。

tn1 -> [object Text]
test2.html:26 Uncaught DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.
    at https://propansystem.net/blogsample/js/037/test2.html:26:4

出力されたエラーメッセージを読むと、

「新しいノードが挿入される前のノードは、このノードの子ではありません。」

という意味になり、insertBeforeはノードの子要素に対しての命令であることがわかります。

エラー内容を踏まえて、上記のサンプルを書き変えて、次のようにしてみました。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">
		<div id="p2" name="p2name">p2text</div>
		<div id="p3" name="p3name">p3text</div>
		<div id="p4" name="p3name">p4text</div>
	</div>
</div>

<script type="text/javascript">
// ID「test1」のノードを作成
let tn1 = document.createTextNode(" _TextNode1_ ");
console.log("tn1 -> " + tn1);

// Elementノードを取得
let p1 = document.getElementById("p1");
let p2 = document.getElementById("p2");
let p3 = document.getElementById("p3");
let p4 = document.getElementById("p4");

// 取得したノード「p2」の前に「tn1」を挿入
p1.insertBefore(tn1, p2);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test3.html)

htmlにアクセスすると、画面には

_TextNode1_
p2text
p3text
p4text

という結果が出力されます。

「id=”p2″」のノードの前に、新規作成した「_TextNode1_」のノードが挿入されていることがわかります。

さらに、「ノード「p3」の前に「tn1」を挿入」したパターンも試してみます。

htmlは以下のようにしました。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">
		<div id="p2" name="p2name">p2text</div>
		<div id="p3" name="p3name">p3text</div>
		<div id="p4" name="p3name">p4text</div>
	</div>
</div>

<script type="text/javascript">
// ID「test1」のノードを作成
let tn1 = document.createTextNode(" _TextNode1_ ");
console.log("tn1 -> " + tn1);

// Elementノードを取得
let p1 = document.getElementById("p1");
let p2 = document.getElementById("p2");
let p3 = document.getElementById("p3");
let p4 = document.getElementById("p4");

// 取得したノード「p3」の前に「tn1」を挿入
p1.insertBefore(tn1, p3);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test4.html)

出力結果は、以下のようになります。

p2text
_TextNode1_
p3text
p4text

insertBeforeメソッドの第2引数を「id=”p3″」にしたため、
新規作成した「_TextNode1_」のノードが

<div id="p3" name="p3name">p3text</div>

の前に挿入されていることがわかります。

ノードの作成について

Posted コメントするカテゴリー: javascript

ノードの作成について

HTMLに対して、javascriptで動的にノード(Node型)を作成する方法があります。

Node型はツリー構造にすることができ、そのツリー構造内で新たにノードを挿入したり削除することができます。
また、置き換えることもできます。

実際にサンプルを用意して、ノードの作成を試してみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">p1text</div>
</div>

<script type="text/javascript">
// ID「test1」のノードを作成
let tn1 = document.createTextNode("test1");

console.log("tn1 -> " + tn1);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

出力結果は次のようになります。

tn1 -> [object Text]

上記の結果、テキストオブジェクトが生成されていることがわかります。

では、このテキストオブジェクトの中身を展開して、一つづつ出力してみます。
上記のHTMLファイル内に次のように追記します。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">p1text</div>
</div>

<script type="text/javascript">
// ID「test1」のノードを作成
let tn1 = document.createTextNode("test1");

console.log("tn1 -> " + tn1);

// オブジェクトの内容を確認する
for(var key in tn1){
	console.log(key + " : " + tn1[key]);
}

</script>

</body>
</html>

サーバ上のHTMLはこちら(test2.html)

結果は次のようになります。

wholeText : test1
assignedSlot : null
splitText : function splitText() { [native code] }
data : test1
length : 5
previousElementSibling : null
nextElementSibling : null
after : function after() { [native code] }
appendData : function appendData() { [native code] }
before : function before() { [native code] }
deleteData : function deleteData() { [native code] }
insertData : function insertData() { [native code] }
remove : function remove() { [native code] }
replaceData : function replaceData() { [native code] }
replaceWith : function replaceWith() { [native code] }
substringData : function substringData() { [native code] }
nodeType : 3
nodeName : #text
baseURI : https://propansystem.net/blogsample/js/036/test1.html
isConnected : false
ownerDocument : [object HTMLDocument]
parentNode : null
parentElement : null
childNodes : [object NodeList]
firstChild : null
lastChild : null
previousSibling : null
nextSibling : null
nodeValue : test1
textContent : test1
ELEMENT_NODE : 1
ATTRIBUTE_NODE : 2
TEXT_NODE : 3
CDATA_SECTION_NODE : 4
ENTITY_REFERENCE_NODE : 5
ENTITY_NODE : 6
PROCESSING_INSTRUCTION_NODE : 7
COMMENT_NODE : 8
DOCUMENT_NODE : 9
DOCUMENT_TYPE_NODE : 10
DOCUMENT_FRAGMENT_NODE : 11
NOTATION_NODE : 12
DOCUMENT_POSITION_DISCONNECTED : 1
DOCUMENT_POSITION_PRECEDING : 2
DOCUMENT_POSITION_FOLLOWING : 4
DOCUMENT_POSITION_CONTAINS : 8
DOCUMENT_POSITION_CONTAINED_BY : 16
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 32
appendChild : function appendChild() { [native code] }
cloneNode : function cloneNode() { [native code] }
compareDocumentPosition : function compareDocumentPosition() { [native code] }
contains : function contains() { [native code] }
getRootNode : function getRootNode() { [native code] }
hasChildNodes : function hasChildNodes() { [native code] }
insertBefore : function insertBefore() { [native code] }
isDefaultNamespace : function isDefaultNamespace() { [native code] }
isEqualNode : function isEqualNode() { [native code] }
isSameNode : function isSameNode() { [native code] }
lookupNamespaceURI : function lookupNamespaceURI() { [native code] }
lookupPrefix : function lookupPrefix() { [native code] }
normalize : function normalize() { [native code] }
removeChild : function removeChild() { [native code] }
replaceChild : function replaceChild() { [native code] }
addEventListener : function addEventListener() { [native code] }
dispatchEvent : function dispatchEvent() { [native code] }
removeEventListener : function removeEventListener() { [native code] }

createTextNode を実行することにより、HTMLドキュメント内に新規のテキストノードを一つ作成されたことがわかります。

この他、ノードにはcloneNode()メソッドがあり、引数のノードをコピーする機能があります。

書き方は以下のように書きます。

cloneNode(元ノード, true)

第2引数でtrueを指定すると、再帰的に元ノードの全てのノードがコピー
されます。
falseを指定すると、元ノードのみがコピーされます。

Textノードについて

Posted コメントするカテゴリー: javascript

Textノードについて

Textノードについて、調べてみます。

あるHTMLドキュメントに対して、要素のコンテンツを取得する際、Textノードとして取得し、処理する場面があります。
また、Textノード自身がさらにTextノード(子要素)を持ち、その子要素のTextノードがさらにTextノード(孫要素)をもつ場合があります。

ここでは要素のコンテンツを取得する方法としてtextContent()の動きを確かめてみます。

以下のサンプルを用意して、試してみました。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">p1text</div>
</div>

<script type="text/javascript">
// ID「p1」のオブジェクトを取得
let p1 = document.getElementById("p1");

// 取得したオブジェクトのattributesを確認
console.log("p1 -> " + p1.textContent);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

出力結果は次のようになります。

p1 -> p1text

もう少し詳しく試してみると、
textContent()関数は、divタグ内のHTML要素を除く内容を取得します。

例えば、下記のように「p1text」に対してHTMLタグがあった場合でも、

<div id="test1">
	<div id="p1" name="p1name"><b>p1text</b></div>
</div>

出力結果は

p1 -> p1text

という形で出力されます。

では次に、元のHTMLファイルを以下のように変更します。
「p1text」の後にさらにdivタグを入れ子にして要素を作ります。
そして先ほどの例のようにtextContent関数を試してみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">p1text<div id="p2" name="p2name">p2text</div></div>
</div>

<script type="text/javascript">
// ID「p1」のオブジェクトを取得
let p1 = document.getElementById("p1");

// 取得したオブジェクトのattributesを確認
console.log("p1 -> " + p1.textContent);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test2.html)

出力結果は

p1 -> p1textp2text

という形になります。
サンプルの文字列の例がよくないですが、p1タグの内容を取得すると、その入れ子にした中のp2タグの内容も取得していることがわかります。

innerHTMLプロパティについて

Posted コメントするカテゴリー: javascript

innerHTMLプロパティについて

innerHTMLプロパティについて調べてみます。

innerHTMLプロパティはHTML5から標準化されたプロパティで、Elementノード、Documentノードで定義されています。
innerHTMLプロパティを使うと、マークアップを含んだ文字列形式で要素のコンテンツが返ります。
また、outerHTMLプロパティも同様に標準化されています。
こちらはHTMLドキュメント内のタグ情報(コンテンツの開始タグ、終了タグ)も含んだ形でマークアップ文字列が返ります。
outerHTMLはElementノードのみ定義されています。

また、HTML5で標準化されたメソッドとしてinsertAdjacentHTML()があります。
こちらはinnerHTMLプロパティと使用する場面で切り分けて使用します。

先ほどinnerHMTLプロパティは値を取得(マークアップを含んだ文字列形式で要素のコンテンツが返る)と書きましたが
innerHTMLプロパティは値を代入することもできます。

ただ、innerHTMLプロパティで値を代入すると、HTMLドキュメントのイベントが破壊されます。
javascriptのイベントが破壊されては困る場面でinsertAdjacentHTML()メソッドを使って、
HTMLドキュメント内の要素にDOMを追加することが可能になります。

以下、実際にHTMLドキュメントを使って試してみます。

HTMLドキュメントの要素を、innerHTMLを使ってプレーンテキストで取得する

HTMLドキュメントの要素を、プレーンテキストで取得する方法を、
実際に試してみました。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">p1text</div>
	<input class="form1" id="fp1" type="text" name="test1">
	<div id="p2">p2text
		<div id="c1">c1text</div>
		<div id="c2">c2text</div>
		<div id="c3">c3text</div>
	</div>
	<div id="p3" name=3>p3text
		<div id="d1">d1text</div>
		<div id="d2">d2text</div>
		<div id="d3">d3text</div>
		<div id="d4">d4text</div>
	</div>
</div>

<script type="text/javascript">
// ID「p1」のオブジェクトを取得
let p1 = document.getElementById("p1");

// 取得したオブジェクトのattributesを確認
console.log("p1 -> " + p1.textContent);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

出力結果は次のようになります。

p1 -> p1text

HTMLドキュメントの要素を、innerHTMLを使って内容を書き変える

では次に、innerHTMLを使って、

<div id="p1" name="p1name">p1text</div>

の内容を更新してみます。

先ほどのHTMLを以下のように変更しました。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">p1text</div>
	<input class="form1" id="fp1" type="text" name="test1">
	<div id="p2">p2text
		<div id="c1">c1text</div>
		<div id="c2">c2text</div>
		<div id="c3">c3text</div>
	</div>
	<div id="p3" name=3>p3text
		<div id="d1">d1text</div>
		<div id="d2">d2text</div>
		<div id="d3">d3text</div>
		<div id="d4">d4text</div>
	</div>
</div>

<script type="text/javascript">
// ID「p1」のオブジェクトを取得
let p1 = document.getElementById("p1");

// innerHTMLを使って内容を書き換える
p1.innerHTML = 'p1 text update !';

// 取得したオブジェクトのattributesを確認
console.log("p1 -> " + p1.textContent);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test2.html)

出力結果は次のようになります。

p1 -> p1 text update !

HTMLドキュメントの内容が書き変わったので(厳密に言うと、代入したタイミングでイベントも破棄されています)、
ログ出力には最初の例(test1.html)とは異なった値が出力されました。

HTMLドキュメントの要素を、textContentを使って内容を書き変える

では、textContentを使って、HTMLドキュメントの内容を変更してみます。

先ほどのHTMLを以下のようにさらに変更しました。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">p1text</div>
	<input class="form1" id="fp1" type="text" name="test1">
	<div id="p2">p2text
		<div id="c1">c1text</div>
		<div id="c2">c2text</div>
		<div id="c3">c3text</div>
	</div>
	<div id="p3" name=3>p3text
		<div id="d1">d1text</div>
		<div id="d2">d2text</div>
		<div id="d3">d3text</div>
		<div id="d4">d4text</div>
	</div>
</div>

<script type="text/javascript">
// ID「p1」のオブジェクトを取得
let p1 = document.getElementById("p1");

// textContentを使って内容を書き換える
p1.textContent = 'p1 text update (textContent) !';

// 取得したオブジェクトのattributesを確認
console.log("p1 -> " + p1.textContent);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test3.html)

出力結果は次のようになります。

p1 -> p1 text update (textContent) !

今回確かめたように、innerHTMLとtextContentを使って、HTMLドキュメントを書き変えましたが、
どちらもコンテンツの更新はできることがわかりました。

textContentとinnerHTMLの違いについて

上記のサンプルから、textContentとinnerHTMLはどちらもHTMLドキュメントを書き変える(代入する)ことができます。
動きだけを見ると両社には違いはありませんが、
textContentプロパティは指定した要素のTextノードを全て連携した値です。
innerTextプロパティはscript要素のコンテンツを返さず、空白は取り除かれ、table (テーブル要素)は読み出し専用プロパティになる。という点が異なります。

ElementオブジェクトのAttrオブジェクトについて

Posted コメントするカテゴリー: javascript

ElementオブジェクトのAttrオブジェクトについて

ElementオブジェクトのAttrについて調べてみます。

ElementオブジェクトはHTML/XMLを内包したオブジェクトです。
Elementオブジェクトは親のインターフェイスの「Node型」、その親インターフェイスである「EventTarget型」のプロパティを継承しています。

そのNode型にはattributesプロパティが定義されています。
このattributesプロパティは要素の属性を表すリスト(配列のようなもの)「NamedNodeMap」を参照します。
このattributesプロパティのNamedNodeMapに対しては数値(インデックス)を使ってアクセス可能です。
また、数値(インデックス)ではなく属性名でもアクセス可能です。

実際にどんな挙動になるのか、試してみました。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<input class="form1" id="p1" type="text" name="test1">
</div>

<script type="text/javascript">
// ID「p1」のオブジェクトを取得
let test1 = document.getElementById("p1");

// 取得したオブジェクトのattributesを確認
console.log("test1 -> " + test1.attributes);

// 取得したオブジェクトのattributesの最初の要素を確認
console.log("test2 -> " + test1.attributes[0]);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

出力結果は次のようになります。

test1 -> [object NamedNodeMap]
test2 -> [object Attr]

取得したオブジェクトに対してattributesプロパティを調べると、
「NamedNodeMapオブジェクト」を参照していることがわかります。

また、attributesオブジェクトにインデックスを指定すると「Attrオブジェクト」を参照しています。

AttrオブジェクトはNode型の派生です。
Attrオブジェクトはnameプロパティとvalueプロパティがあり、属性の名前と値が格納されています。
試しに、先ほどのHTMLドキュメントに追記して、次のようなHTMLを用意しました。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<input class="form1" id="p1" type="text" name="test1">
</div>

<script type="text/javascript">
// ID「p1」のオブジェクトを取得
let test1 = document.getElementById("p1");

// 取得したオブジェクトのattributesを確認
console.log("test1 -> " + test1.attributes);

// 取得したオブジェクトのattributesの最初の要素を確認
console.log("test2 -> " + test1.attributes[0]);

// 取得オブジェクトの最初の要素のname属性とvalue属性を出力
console.log("test3_name -> " + test1.attributes[0].name);
console.log("test3_value -> " + test1.attributes[0].value);

// 取得オブジェクトの2番目の要素のname属性とvalue属性を出力
console.log("test4_name -> " + test1.attributes[1].name);
console.log("test4_value -> " + test1.attributes[1].value);

// 取得オブジェクトの3番目の要素のname属性とvalue属性を出力
console.log("test5_name -> " + test1.attributes[2].name);
console.log("test5_value -> " + test1.attributes[2].value);

// 取得オブジェクトの4番目の要素のname属性とvalue属性を出力
console.log("test6_name -> " + test1.attributes[3].name);
console.log("test6_value -> " + test1.attributes[3].value);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test2.html)

このHTMLドキュメントにアクセスすると、ログには次のように出力されます。

test1 -> [object NamedNodeMap]
test2 -> [object Attr]
test3_name -> class
test3_value -> form1
test4_name -> id
test4_value -> p1
test5_name -> type
test5_value -> text
test6_name -> name
test6_value -> test1

test3以降、ドキュメント内の

<input class="form1" id="p1" type="text" name="test1">

に対しての、
属性の名前と値を順に取得できていることがわかります。

では、さらにHTMLに追記して、下記のような記述を試してみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<input class="form1" id="p1" type="text" name="test1">
</div>

<script type="text/javascript">
// ID「p1」のオブジェクトを取得
let test1 = document.getElementById("p1");

// 取得したオブジェクトのattributesを確認
console.log("test1 -> " + test1.attributes);

// 取得したオブジェクトのattributesの最初の要素を確認
console.log("test2 -> " + test1.attributes[0]);

// 取得オブジェクトの最初の要素のname属性とvalue属性を出力
console.log("test3_name -> " + test1.attributes[0].name);
console.log("test3_value -> " + test1.attributes[0].value);

// 取得オブジェクトの2番目の要素のname属性とvalue属性を出力
console.log("test4_name -> " + test1.attributes[1].name);
console.log("test4_value -> " + test1.attributes[1].value);

// 取得オブジェクトの3番目の要素のname属性とvalue属性を出力
console.log("test5_name -> " + test1.attributes[2].name);
console.log("test5_value -> " + test1.attributes[2].value);

// 取得オブジェクトの4番目の要素のname属性とvalue属性を出力
console.log("test6_name -> " + test1.attributes[3].name);
console.log("test6_value -> " + test1.attributes[3].value);

// 取得オブジェクトの5番目の要素のname属性とvalue属性を出力
console.log("test7_name -> " + test1.attributes[4].name);
console.log("test7_value -> " + test1.attributes[4].value);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test3.html)

存在しないはずの5番目の要素にアクセスする書き方をしてみました。

出力結果は、次のようになります。

test1 -> [object NamedNodeMap]
test2 -> [object Attr]
test3_name -> class
test3_value -> form1
test4_name -> id
test4_value -> p1
test5_name -> type
test5_value -> text
test6_name -> name
test6_value -> test1
Uncaught TypeError: Cannot read properties of undefined (reading 'name')
    at test1.html:43

もともと、ドキュメント内の

<input class="form1" id="p1" type="text" name="test1">

には、
要素が4つしかない為、5つめの要素にアクセスした為に

Cannot read properties of undefined

というエラーになりました。
余談ですが、存在しない要素にアクセスするとどうなるかを試しました。
実際のプログラムでは起こりえない(実装しない)ことですが、内部構造を理解する意味でも色々と試してみるとよいかもしれません。

データセット属性について

Posted コメントするカテゴリー: javascript

データセット属性について

データセット属性について試してみます。

データセット属性はHTMLドキュメントに対して、標準外の属性を定義し、その定義した属性を
javascript側で取得し使用することができます。

実際にどんな挙動になるのか、以下かんたんなHTMLドキュメントのサンプルを書いて試してみました。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name" data-testdata1="aaa" data-testdata2="bbb" data-testdata3="ccc">p1text</div>
</div>

<script type="text/javascript">
// ID「p1」の要素を取得
let test1 = document.getElementById("p1");

// 取得した内容を確認
console.log("test1 -> " + test1);

// 取得したデータセット属性の値を確認
console.log("testdata1 -> " + test1.dataset.testdata1);
console.log("testdata2 -> " + test1.dataset.testdata2);
console.log("testdata3 -> " + test1.dataset.testdata3);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

実行した結果は

test1 -> [object HTMLDivElement]
testdata1 -> aaa
testdata2 -> bbb
testdata3 -> ccc

という結果になります。

HTMLドキュメントとして定義した

<div id="p1" name="p1name" data-testdata1="aaa" data-testdata2="bbb" data-testdata3="ccc">p1text</div>

という箇所の「data-testdata1=”aaa”」の部分がデータセット属性になります。

データセット属性を取得するときは

test1.dataset.testdata1

というように、「(取得した)DOMオブジェクト.dataset.定義名」という、データセットプロパティを使用し、値を取得します。

データセット属性に値をセットする

上記のサンプルではデータセット属性の値を取得しましたが、その反対に値をデータセット属性に対してセットすることもできます。
以下のサンプルで試してみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name" data-testdata1="aaa" data-testdata2="bbb" data-testdata3="ccc">p1text</div>
</div>

<script type="text/javascript">
// hasAttributeで「name属性」の有無を取得
let test1 = document.getElementById("p1");
test1.dataset.testdata1 = "ddd";
</script>

</body>
</html>

サーバ上のHTMLはこちら(test2.html)

上記の画面にアクセスすると、データセット属性に値を代入された後のHTMLドキュメントになっていることがわかります。

具体的には、以下のHTMLソースになっていることを確認しました。(ブラウザの開発者ツールで確認)

<html lang="ja"><head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name" data-testdata1="ddd" data-testdata2="bbb" data-testdata3="ccc">p1text</div>
</div>

<script type="text/javascript">
// ID「p1」の要素を取得
let test1 = document.getElementById("p1");

// データセット属性のtestdata1に対して値を代入
test1.dataset.testdata1 = "ddd";
</script>

</body>
</html>

javascript実行前は「data-testdata1=”aaa”」でしたが、実行後に「data-testdata1=”ddd”」という値に書き変わっています。

データセット属性の注意点

データセット属性についての注意点をまとめます。

・属性名は小文字で記述する必要あり
・HTMLのDOM構造として使用し、見た目には影響を及ぼさない
・属性名にハイフンが含まれる場合は、アクセス時(マップ時)にキャメルケースを使用する

hasAttribute()、removeAttribute()について

Posted コメントするカテゴリー: javascript

hasAttribute()、removeAttribute()について

前回の投稿で使用したHTMLドキュメントをもとに、hasAttributeとremoveAttributeのメソッドを調べてみます。

HTMLドキュメントは前回投稿した以下のものを用意しました。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">p1text</div>
	<div id="p2">p2text
		<div id="c1">c1text</div>
		<div id="c2">c2text</div>
		<div id="c3">c3text</div>
	</div>
	<div id="p3" name=3>p3text
		<div id="d1">d1text</div>
		<div id="d2">d2text</div>
		<div id="d3">d3text</div>
		<div id="d4">d4text</div>
	</div>
</div>

<script type="text/javascript">
// hasAttributeで「name属性」の有無を取得
let test1 = document.getElementById("p1").hasAttribute("name");
console.log("test1 -> " + test1);

// hasAttributeで「names属性」の有無を取得
let test2 = document.getElementById("p1").hasAttribute("names");
console.log("test2 -> " + test2);

// 一旦「name属性」を削除する
let test3 = document.getElementById("p1").removeAttribute("name");
console.log("test3 -> " + test3);

// 改めて「name属性」の有無を取得する
let test4 = document.getElementById("p1").hasAttribute("name");
console.log("test4 -> " + test4);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test1.html)

上記の出力結果は

test1 -> true
test2 -> false
test3 -> undefined
test4 -> false

となります。

test1では、

<div id="p1" name="p1name">p1text</div>

というHTMLドキュメント構造から、trueが返りました。
test2では、「names」属性は元々定義されていないのでfalseが返りました。
test3では、removeAttributeメソッドが実行され、その結果、返値の出力としてundefinedになりました。(これは言語仕様としてundefinedが返る為です)
test4では、一度test3のremoveAttributeメソッドが実行された為、改めてname属性を取得しても、存在しない為、falseが返りました。

また、上記のjavascriptが実行された後、HTMLドキュメントからは該当のname属性のDOMが削除されています。

最初は

<div id="p1" name="p1name">p1text</div>

というDOM構造でしたが、実行後は

<div id="p1">p1text</div>

というDOM構造になっています。

非標準のHTML属性について

Posted コメントするカテゴリー: javascript

非標準のHTML属性について

前回の投稿ではHTMLElementオブジェクトについて調べてみましたが、
HTMLElementオブジェクトは必ずしも標準のHTML属性(DOM標準)だけにあるものではなく、非標準(DOM非標準)のHTML属性も扱うことができます。

また、Element型には要素の取得として、getAttribute()メソッドが使え、
要素の設定として、setAttribute()メソッドが使えます。

例えば、とあるHTMLに対して、要素の取得や設定を行うには、次のように書きます。

HTMLドキュメントは以下のものを用意しました。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">p1text</div>
	<div id="p2">p2text
		<div id="c1">c1text</div>
		<div id="c2">c2text</div>
		<div id="c3">c3text</div>
	</div>
	<div id="p3" name=3>p3text
		<div id="d1">d1text</div>
		<div id="d2">d2text</div>
		<div id="d3">d3text</div>
		<div id="d4">d4text</div>
	</div>
</div>

</body>
</html>

サーバ上のHTMLはこちら(test1)

上記のHTMLドキュメントに対し、getAttributeメソッドを試してみます。
getAttributeはElementのメソッド(インターフェイス)で、要素の指定した属性の値を返します。

let test1 = document.getElementById("p1").getAttribute("className");
console.log("test1 -> " + test1);

出力結果は

test1 -> p1name

になります。

ここで注意が必要な点は、値は全て文字列として取得されることです。

例えば、id=”p3″のdivタグに対して、同様にgetAttributeでname属性を取得してみます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>テストHTML</title>
</head>
<body>

<div id="test1">
	<div id="p1" name="p1name">p1text</div>
	<div id="p2">p2text
		<div id="c1">c1text</div>
		<div id="c2">c2text</div>
		<div id="c3">c3text</div>
	</div>
	<div id="p3" name=3>p3text
		<div id="d1">d1text</div>
		<div id="d2">d2text</div>
		<div id="d3">d3text</div>
		<div id="d4">d4text</div>
	</div>
</div>

<script type="text/javascript">
let test1 = document.getElementById("p1").getAttribute("name");
console.log("test1 -> " + test1);

let test3 = document.getElementById("p3").getAttribute("name");
console.log("test3 -> " + test3);
</script>

</body>
</html>

サーバ上のHTMLはこちら(test2)

出力結果は

test1 -> p1name
test3 -> 3

となりますが、後者の「3」は文字列として取得されています。

HTML属性について

Posted コメントするカテゴリー: javascript

HTML属性について

HTMLElementオブジェクトについて調べてみます。

HTMLElementオブジェクトは、HTMLの文書構造を示すHTMLタグ等の要素をもつオブジェクトと言えます。
また、各オブジェクトにはそれぞれプロパティが定義されています。
Elementオブジェクトには、次のようなオブジェクトが定義されています。(全てではありません)

id
a
link
body
title
img

上記はHTMLの文書構造を示しますが、click、blur、forcus等といったjavascriptで使われるイベントハンドラプロパティも定義されています。

各、HTMLElementオブジェクトには、要素固有の属性が定義されています。
a には href だったり、
img には src といった属性があります。

HTML属性の命名規則について

HTML属性の命名規則については、下記のようになります。

  • HTML属性のプロパティ名は小文字で記述する (但し、大文字、小文字の区別はしない)
  • javascriptのプロパティ名は大文字と小文字を区別する
  • プロパティ名が複数の単語になる場合、2語目以降の先頭は大文字として記述する
  • HTML属性の中にはjavascirptの予約語があるので、もし同一の名前を書く場合は html という文字列を先頭に追加する
  • 上記について、class については、javascriptでは予約語になるので className という形で書く
  • HTML属性のプロパティの値について

    HTML属性のプロパティの値については、文字列になりますが、
    属性が論理値を扱う場合は、プロパティの値も論理値や数値になります。

    属性の種類について

    また、属性にはHTMLの要素ごとに指定できる属性と、全ての要素に指摘できるグローバル属性、
    javascriptを実行するイベントハンドラ属性というものがあります。

    HTML5で制定されているグローバル属性は下記の13種類あります。

    acccesskey
    class
    contenteditable
    dir
    hidden
    id
    lang
    spellcheck
    style
    tabindex
    title
    translate
    data-xxxx(カスタム)
    

    最後の「カスタム」と書いたものは、 data-xxxx の「xxxx」の部分に任意の名称を下記、
    属性として利用できるものです。

    また、イベントハンドラ属性は下記のものがあります。
    それぞれの使用用途や意味については別な投稿で調べようと思います。

    onabort
    onafterprint
    onauxclick
    onbeforeprint
    onbeforeunload
    onblur
    onblur
    oncancel
    oncanplay
    oncanplaythrough
    onchange
    onclick
    onclose
    onclose
    oncontextmenu
    oncopy
    oncuechange
    oncut
    ondblclick
    ondrag
    ondragend
    ondragenter
    ondragexit
    ondragleave
    ondragover
    ondragstart
    ondrop
    ondurationchange
    onemptied
    onended
    onerror
    onfocus
    onfocus
    onhashchange
    oninput
    oninvalid
    onkeydown
    onkeypress
    onkeyup
    onlanguagechange
    onload
    onload
    onloadeddata
    onloadedmetadata
    onloadend
    onloadstart
    onmessage
    onmessageerror
    onmousedown
    onmouseenter
    onmouseleave
    onmousemove
    onmouseout
    onmouseover
    onmouseup
    onoffline
    ononline
    onpagehide
    onpageshow
    onpaste
    onpause
    onplay
    onplaying
    onpopstate
    onprogress
    onratechange
    onreset
    onresize
    onresize
    onscroll
    onscroll
    onsecuritypolicyviolation
    onseeked
    onseeking
    onselect
    onshow
    onstalled
    onstorage
    onsubmit
    onsuspend
    ontimeupdate
    ontoggle
    onunhandledrejection
    onunload
    onvolumechange
    onwaiting
    onwheel
    

    実際には上記のイベントハンドラ属性を記述してプログラムを作るより、
    javascriptのライブラリやフレームワークを使ってイベント処理を書くことが多いので、
    参考までに覚えておくという形で大丈夫と思います。

    属性について

    Posted コメントするカテゴリー: javascript

    属性について

    属性について調べてみます。

    HTMLのDOM要素には、タグ名と属性があります。
    属性は名前と値のペアで記述します。

    属性は数多く定義されており、HTMLのソース上でよく見かける属性は、alt、href、hidden、name、src、等々ありますが、
    これらは使用する用途やタグによって書き分けられます。

    属性の書き方は

    <要素名 名前="値">
    

    かんたんな例として、aタグにリンク先を表記する例がわかりやすいと思います。

    <a href="xxxxx">リンク</a>
    

    これは 「aタグ」(要素名)に対して、「href」属性をつけて、値「xxxxx」を設定しています。

    また、属性には複数の値を付与することができます。
    サンプルとしては以下のようになります。

    <要素名 名前1="値1" 名前2="値2" 名前3="値3">
    

    この場合、一つの要素に対して、3つの属性を設定していることになります。

    nodeType、nodeValue、nodeNameについて

    Posted コメントするカテゴリー: javascript

    nodeType、nodeValue、nodeNameについて

    ノードにはnodeTypeと呼ばれるノードの種類を表すものがあります。
    nodeTypeは言語仕様では12種類指定されており、現在では非推奨のものもあります。

    値はunsigned short型で定義されています。

    以下、全12種類のnodeTypeを記載します。

    ELEMENT_NODE                 1
    ATTRIBUTE_NODE               2(非推奨)
    TEXT_NODE                    3
    CDATA_SECTION_NODE           4(非推奨)
    ENTITY_REFERENCE_NODE        5(非推奨)
    ENTITY_NODE                  6(非推奨)
    PROCESSING_INSTRUCTION_NODE  7
    COMMENT_NODE                 8
    DOCUMENT_NODE                9
    DOCUMENT_TYPE_NODE          10
    DOCUMENT_FRAGMENT_NODE      11
    NOTATION_NODE               12(非推奨)
    

    nodeTypeについての検証は行いませんが、前回の投稿でnextSiblingによる探索を試した際、
    HTMLのDOMからTextオブジェクトを取得した結果をconsole出力した結果を記載していました。
    具体的には2つの例になりますが、その時の出力結果を引用すると、

    「Textオブジェクト」の場合、nodeType は 3 が取得できていました。
    (以下の出力はnextSiblingを試した時のもの)

    c1.nextSibling -> [object Text]
    wholeText : 
             
    assignedSlot : null
    splitText : function splitText() { [native code] }
    data : 
             
    length : 3
    previousElementSibling : [object HTMLDivElement]
    nextElementSibling : [object HTMLDivElement]
    after : function after() { [native code] }
    appendData : function appendData() { [native code] }
    before : function before() { [native code] }
    deleteData : function deleteData() { [native code] }
    insertData : function insertData() { [native code] }
    remove : function remove() { [native code] }
    replaceData : function replaceData() { [native code] }
    replaceWith : function replaceWith() { [native code] }
    substringData : function substringData() { [native code] }
    nodeType : 3
    nodeName : #text
    (以下省略)
    

    また、「HTMLDivElementオブジェクト」の場合、nodeType は 1 が取得できていました。
    (以下の出力はnextSiblingを試した時のもの)

    c1.nextSibling -> [object HTMLDivElement]
    align : 
    title : 
    lang : 
    translate : true
    dir : 
    hidden : false
    accessKey : 
    draggable : false
    spellcheck : true
    autocapitalize : 
    (出力途中は省略)
    nodeType : 1
    nodeName : DIV
    

    また、nodeValueについては、Textオブジェクトに持つ内容を示し、
    nodeNameについては、そのオブジェクトが持つElementのタグ名を示します。

    nextSibling による探索

    Posted コメントするカテゴリー: javascript

    nextSibling による探索

    特定の要素からみて、最初の子要素を取得する方法の nextSibling を試してみます。
    まずは、前回と同様のHTMLを用意しました。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2">c2text</div>
    		<div id="c3">c3text</div>
    	</div>
    	<div id="p3">p3text
    		<div id="d1">d1text</div>
    		<div id="d2">d2text</div>
    		<div id="d3">d3text</div>
    		<div id="d4">d4text</div>
    	</div>
    </div>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test1)

    このHTMLに対して、idがp2のdivタグを親として、子要素をfirstChildを使って取得してみます。
    下記のようにjavascriptを追記しました。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2">c2text</div>
    		<div id="c3">c3text</div>
    	</div>
    	<div id="p3">p3text
    		<div id="d1">d1text</div>
    		<div id="d2">d2text</div>
    		<div id="d3">d3text</div>
    		<div id="d4">d4text</div>
    	</div>
    </div>
    
    <script type="text/javascript">
    	let c1 = document.getElementById("c1");
    
    	console.log("c1.nextSibling -> " + c1.nextSibling);
    	// 「c1.nextSibling」の内容を確認する
    	for(var key in c1.nextSibling){
    		console.log(key + " : " + c1.nextSibling[key]);
    	}
    
    </script>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test2)

    この結果、開発ツールのログには、以下のように出力されます。

    c1.nextSibling -> [object Text]
    wholeText : 
    		
    assignedSlot : null
    splitText : function splitText() { [native code] }
    data : 
    		
    length : 3
    previousElementSibling : [object HTMLDivElement]
    nextElementSibling : [object HTMLDivElement]
    after : function after() { [native code] }
    appendData : function appendData() { [native code] }
    before : function before() { [native code] }
    deleteData : function deleteData() { [native code] }
    insertData : function insertData() { [native code] }
    remove : function remove() { [native code] }
    replaceData : function replaceData() { [native code] }
    replaceWith : function replaceWith() { [native code] }
    substringData : function substringData() { [native code] }
    nodeType : 3
    nodeName : #text
    baseURI : https://propansystem.net/blogsample/js/026/test2.html
    isConnected : true
    ownerDocument : [object HTMLDocument]
    parentNode : [object HTMLDivElement]
    parentElement : [object HTMLDivElement]
    childNodes : [object NodeList]
    firstChild : null
    lastChild : null
    previousSibling : [object HTMLDivElement]
    nextSibling : [object HTMLDivElement]
    nodeValue : 
    		
    textContent : 
    		
    ELEMENT_NODE : 1
    ATTRIBUTE_NODE : 2
    TEXT_NODE : 3
    CDATA_SECTION_NODE : 4
    ENTITY_REFERENCE_NODE : 5
    ENTITY_NODE : 6
    PROCESSING_INSTRUCTION_NODE : 7
    COMMENT_NODE : 8
    DOCUMENT_NODE : 9
    DOCUMENT_TYPE_NODE : 10
    DOCUMENT_FRAGMENT_NODE : 11
    NOTATION_NODE : 12
    DOCUMENT_POSITION_DISCONNECTED : 1
    DOCUMENT_POSITION_PRECEDING : 2
    DOCUMENT_POSITION_FOLLOWING : 4
    DOCUMENT_POSITION_CONTAINS : 8
    DOCUMENT_POSITION_CONTAINED_BY : 16
    DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 32
    appendChild : function appendChild() { [native code] }
    cloneNode : function cloneNode() { [native code] }
    compareDocumentPosition : function compareDocumentPosition() { [native code] }
    contains : function contains() { [native code] }
    getRootNode : function getRootNode() { [native code] }
    hasChildNodes : function hasChildNodes() { [native code] }
    insertBefore : function insertBefore() { [native code] }
    isDefaultNamespace : function isDefaultNamespace() { [native code] }
    isEqualNode : function isEqualNode() { [native code] }
    isSameNode : function isSameNode() { [native code] }
    lookupNamespaceURI : function lookupNamespaceURI() { [native code] }
    lookupPrefix : function lookupPrefix() { [native code] }
    normalize : function normalize() { [native code] }
    removeChild : function removeChild() { [native code] }
    replaceChild : function replaceChild() { [native code] }
    addEventListener : function addEventListener() { [native code] }
    dispatchEvent : function dispatchEvent() { [native code] }
    removeEventListener : function removeEventListener() { [native code] }
    

    一見すると、なんらかの情報が取得できているように見えますが、注意する点として、
    子要素にテキストノードが含まれているか含まれていないかが重要になります。

    子要素にテキストノードが含まれている場合、子要素の取得方法を nextElementSibling を使って取得できます。

    上記の例では、子要素にテキストノードが含まれているので、

    nextElementSibling : [object HTMLDivElement]
    

    という形で object HTMLDivElement が取得できていることがわかります。

    では次に

    <div id="c1">c1text</div>
    

    の後の子要素の数を減らし、

    の中のテキストを取り除いて試してみます。

    HTMLは次のようにしました。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2"></div>
    	</div>
    	<div id="p3">p3text
    		<div id="d1">d1text</div>
    		<div id="d2">d2text</div>
    		<div id="d3">d3text</div>
    		<div id="d4">d4text</div>
    	</div>
    </div>
    
    <script type="text/javascript">
    	let c1 = document.getElementById("c1");
    
    	console.log("c1.nextSibling -> " + c1.nextSibling);
    	// 「c1.nextSibling」の内容を確認する
    	for(var key in c1.nextSibling){
    		console.log(key + " : " + c1.nextSibling[key]);
    	}
    
    </script>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test3)

    上記のHTMLに対して開発者ツールからconsoleを確認すると、出力結果は次のようになります。

    c1.nextSibling -> [object Text]
    wholeText : 
    		
    assignedSlot : null
    splitText : function splitText() { [native code] }
    data : 
    		
    length : 3
    previousElementSibling : [object HTMLDivElement]
    nextElementSibling : [object HTMLDivElement]
    after : function after() { [native code] }
    appendData : function appendData() { [native code] }
    before : function before() { [native code] }
    deleteData : function deleteData() { [native code] }
    insertData : function insertData() { [native code] }
    remove : function remove() { [native code] }
    replaceData : function replaceData() { [native code] }
    replaceWith : function replaceWith() { [native code] }
    substringData : function substringData() { [native code] }
    nodeType : 3
    nodeName : #text
    baseURI : https://propansystem.net/blogsample/js/026/test3.html
    isConnected : true
    ownerDocument : [object HTMLDocument]
    parentNode : [object HTMLDivElement]
    parentElement : [object HTMLDivElement]
    childNodes : [object NodeList]
    firstChild : null
    lastChild : null
    previousSibling : [object HTMLDivElement]
    nextSibling : [object HTMLDivElement]
    nodeValue : 
    		
    textContent : 
    		
    ELEMENT_NODE : 1
    ATTRIBUTE_NODE : 2
    TEXT_NODE : 3
    CDATA_SECTION_NODE : 4
    ENTITY_REFERENCE_NODE : 5
    ENTITY_NODE : 6
    PROCESSING_INSTRUCTION_NODE : 7
    COMMENT_NODE : 8
    DOCUMENT_NODE : 9
    DOCUMENT_TYPE_NODE : 10
    DOCUMENT_FRAGMENT_NODE : 11
    NOTATION_NODE : 12
    DOCUMENT_POSITION_DISCONNECTED : 1
    DOCUMENT_POSITION_PRECEDING : 2
    DOCUMENT_POSITION_FOLLOWING : 4
    DOCUMENT_POSITION_CONTAINS : 8
    DOCUMENT_POSITION_CONTAINED_BY : 16
    DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 32
    appendChild : function appendChild() { [native code] }
    cloneNode : function cloneNode() { [native code] }
    compareDocumentPosition : function compareDocumentPosition() { [native code] }
    contains : function contains() { [native code] }
    getRootNode : function getRootNode() { [native code] }
    hasChildNodes : function hasChildNodes() { [native code] }
    insertBefore : function insertBefore() { [native code] }
    isDefaultNamespace : function isDefaultNamespace() { [native code] }
    isEqualNode : function isEqualNode() { [native code] }
    isSameNode : function isSameNode() { [native code] }
    lookupNamespaceURI : function lookupNamespaceURI() { [native code] }
    lookupPrefix : function lookupPrefix() { [native code] }
    normalize : function normalize() { [native code] }
    removeChild : function removeChild() { [native code] }
    replaceChild : function replaceChild() { [native code] }
    addEventListener : function addEventListener() { [native code] }
    dispatchEvent : function dispatchEvent() { [native code] }
    removeEventListener : function removeEventListener() { [native code] }
    

    出力結果をよくみると、test2 の時の出力内容と変わりはありません。

    DIVタグの内容を

    にして取り除いたように見えますが、
    「テキストノード」の解釈が違っていた為、子要素として取得ができていました。
    これはテキストノードを空白として解釈していないということが言えます。

    では次に、HTMLを以下のように書き換えて試してみます。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div><div id="c2">c2text</div></div>
    	<div id="p3">p3text
    		<div id="d1">d1text</div>
    		<div id="d2">d2text</div>
    		<div id="d3">d3text</div>
    		<div id="d4">d4text</div>
    	</div>
    </div>
    
    <script type="text/javascript">
    	let c1 = document.getElementById("c1");
    
    	console.log("c1.nextSibling -> " + c1.nextSibling);
    	// 「c1.nextSibling」の内容を確認する
    	for(var key in c1.nextSibling){
    		console.log(key + " : " + c1.nextSibling[key]);
    	}
    
    </script>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test4)

    上記のHTMLにアクセスしてconseleを確認すると、出力結果は次のようになりました。

    c1.nextSibling -> [object HTMLDivElement]
    align : 
    title : 
    lang : 
    translate : true
    dir : 
    hidden : false
    accessKey : 
    draggable : false
    spellcheck : true
    autocapitalize : 
    contentEditable : inherit
    isContentEditable : false
    inputMode : 
    offsetParent : [object HTMLBodyElement]
    offsetTop : 80
    offsetLeft : 8
    offsetWidth : 973
    offsetHeight : 24
    style : [object CSSStyleDeclaration]
    innerText : c2text
    outerText : c2text
    onbeforexrselect : null
    onabort : null
    onblur : null
    oncancel : null
    oncanplay : null
    oncanplaythrough : null
    onchange : null
    onclick : null
    onclose : null
    oncontextmenu : null
    oncuechange : null
    ondblclick : null
    ondrag : null
    ondragend : null
    ondragenter : null
    ondragleave : null
    ondragover : null
    ondragstart : null
    ondrop : null
    ondurationchange : null
    onemptied : null
    onended : null
    onerror : null
    onfocus : null
    onformdata : null
    oninput : null
    oninvalid : null
    onkeydown : null
    onkeypress : null
    onkeyup : null
    onload : null
    onloadeddata : null
    onloadedmetadata : null
    onloadstart : null
    onmousedown : null
    onmouseenter : null
    onmouseleave : null
    onmousemove : null
    onmouseout : null
    onmouseover : null
    onmouseup : null
    onmousewheel : null
    onpause : null
    onplay : null
    onplaying : null
    onprogress : null
    onratechange : null
    onreset : null
    onresize : null
    onscroll : null
    onseeked : null
    onseeking : null
    onselect : null
    onstalled : null
    onsubmit : null
    onsuspend : null
    ontimeupdate : null
    ontoggle : null
    onvolumechange : null
    onwaiting : null
    onwebkitanimationend : null
    onwebkitanimationiteration : null
    onwebkitanimationstart : null
    onwebkittransitionend : null
    onwheel : null
    onauxclick : null
    ongotpointercapture : null
    onlostpointercapture : null
    onpointerdown : null
    onpointermove : null
    onpointerup : null
    onpointercancel : null
    onpointerover : null
    onpointerout : null
    onpointerenter : null
    onpointerleave : null
    onselectstart : null
    onselectionchange : null
    onanimationend : null
    onanimationiteration : null
    onanimationstart : null
    ontransitionrun : null
    ontransitionstart : null
    ontransitionend : null
    ontransitioncancel : null
    oncopy : null
    oncut : null
    onpaste : null
    dataset : [object DOMStringMap]
    nonce : 
    autofocus : false
    tabIndex : -1
    attachInternals : function attachInternals() { [native code] }
    blur : function blur() { [native code] }
    click : function click() { [native code] }
    focus : function focus() { [native code] }
    enterKeyHint : 
    onpointerrawupdate : null
    namespaceURI : http://www.w3.org/1999/xhtml
    prefix : null
    localName : div
    tagName : DIV
    id : c2
    className : 
    classList : 
    slot : 
    attributes : [object NamedNodeMap]
    shadowRoot : null
    part : 
    assignedSlot : null
    innerHTML : c2text
    outerHTML : <div id="c2">c2text</div>
    scrollTop : 0
    scrollLeft : 0
    scrollWidth : 973
    scrollHeight : 24
    clientTop : 0
    clientLeft : 0
    clientWidth : 973
    clientHeight : 24
    attributeStyleMap : [object StylePropertyMap]
    onbeforecopy : null
    onbeforecut : null
    onbeforepaste : null
    onsearch : null
    elementTiming : 
    onfullscreenchange : null
    onfullscreenerror : null
    onwebkitfullscreenchange : null
    onwebkitfullscreenerror : null
    children : [object HTMLCollection]
    firstElementChild : null
    lastElementChild : null
    childElementCount : 0
    previousElementSibling : [object HTMLDivElement]
    nextElementSibling : null
    after : function after() { [native code] }
    animate : function animate() { [native code] }
    append : function append() { [native code] }
    attachShadow : function attachShadow() { [native code] }
    before : function before() { [native code] }
    closest : function closest() { [native code] }
    computedStyleMap : function computedStyleMap() { [native code] }
    getAttribute : function getAttribute() { [native code] }
    getAttributeNS : function getAttributeNS() { [native code] }
    getAttributeNames : function getAttributeNames() { [native code] }
    getAttributeNode : function getAttributeNode() { [native code] }
    getAttributeNodeNS : function getAttributeNodeNS() { [native code] }
    getBoundingClientRect : function getBoundingClientRect() { [native code] }
    getClientRects : function getClientRects() { [native code] }
    getElementsByClassName : function getElementsByClassName() { [native code] }
    getElementsByTagName : function getElementsByTagName() { [native code] }
    getElementsByTagNameNS : function getElementsByTagNameNS() { [native code] }
    hasAttribute : function hasAttribute() { [native code] }
    hasAttributeNS : function hasAttributeNS() { [native code] }
    hasAttributes : function hasAttributes() { [native code] }
    hasPointerCapture : function hasPointerCapture() { [native code] }
    insertAdjacentElement : function insertAdjacentElement() { [native code] }
    insertAdjacentHTML : function insertAdjacentHTML() { [native code] }
    insertAdjacentText : function insertAdjacentText() { [native code] }
    matches : function matches() { [native code] }
    prepend : function prepend() { [native code] }
    querySelector : function querySelector() { [native code] }
    querySelectorAll : function querySelectorAll() { [native code] }
    releasePointerCapture : function releasePointerCapture() { [native code] }
    remove : function remove() { [native code] }
    removeAttribute : function removeAttribute() { [native code] }
    removeAttributeNS : function removeAttributeNS() { [native code] }
    removeAttributeNode : function removeAttributeNode() { [native code] }
    replaceChildren : function replaceChildren() { [native code] }
    replaceWith : function replaceWith() { [native code] }
    requestFullscreen : function requestFullscreen() { [native code] }
    requestPointerLock : function requestPointerLock() { [native code] }
    scroll : function scroll() { [native code] }
    scrollBy : function scrollBy() { [native code] }
    scrollIntoView : function scrollIntoView() { [native code] }
    scrollIntoViewIfNeeded : function scrollIntoViewIfNeeded() { [native code] }
    scrollTo : function scrollTo() { [native code] }
    setAttribute : function setAttribute() { [native code] }
    setAttributeNS : function setAttributeNS() { [native code] }
    setAttributeNode : function setAttributeNode() { [native code] }
    setAttributeNodeNS : function setAttributeNodeNS() { [native code] }
    setPointerCapture : function setPointerCapture() { [native code] }
    toggleAttribute : function toggleAttribute() { [native code] }
    webkitMatchesSelector : function webkitMatchesSelector() { [native code] }
    webkitRequestFullScreen : function webkitRequestFullScreen() { [native code] }
    webkitRequestFullscreen : function webkitRequestFullscreen() { [native code] }
    ariaAtomic : null
    ariaAutoComplete : null
    ariaBusy : null
    ariaChecked : null
    ariaColCount : null
    ariaColIndex : null
    ariaColSpan : null
    ariaCurrent : null
    ariaDescription : null
    ariaDisabled : null
    ariaExpanded : null
    ariaHasPopup : null
    ariaHidden : null
    ariaKeyShortcuts : null
    ariaLabel : null
    ariaLevel : null
    ariaLive : null
    ariaModal : null
    ariaMultiLine : null
    ariaMultiSelectable : null
    ariaOrientation : null
    ariaPlaceholder : null
    ariaPosInSet : null
    ariaPressed : null
    ariaReadOnly : null
    ariaRelevant : null
    ariaRequired : null
    ariaRoleDescription : null
    ariaRowCount : null
    ariaRowIndex : null
    ariaRowSpan : null
    ariaSelected : null
    ariaSetSize : null
    ariaSort : null
    ariaValueMax : null
    ariaValueMin : null
    ariaValueNow : null
    ariaValueText : null
    getAnimations : function getAnimations() { [native code] }
    getInnerHTML : function getInnerHTML() { [native code] }
    nodeType : 1
    nodeName : DIV
    baseURI : https://propansystem.net/blogsample/js/026/test4.html
    isConnected : true
    ownerDocument : [object HTMLDocument]
    parentNode : [object HTMLDivElement]
    parentElement : [object HTMLDivElement]
    childNodes : [object NodeList]
    firstChild : [object Text]
    lastChild : [object Text]
    previousSibling : [object HTMLDivElement]
    nextSibling : null
    nodeValue : null
    textContent : c2text
    ELEMENT_NODE : 1
    ATTRIBUTE_NODE : 2
    TEXT_NODE : 3
    CDATA_SECTION_NODE : 4
    ENTITY_REFERENCE_NODE : 5
    ENTITY_NODE : 6
    PROCESSING_INSTRUCTION_NODE : 7
    COMMENT_NODE : 8
    DOCUMENT_NODE : 9
    DOCUMENT_TYPE_NODE : 10
    DOCUMENT_FRAGMENT_NODE : 11
    NOTATION_NODE : 12
    DOCUMENT_POSITION_DISCONNECTED : 1
    DOCUMENT_POSITION_PRECEDING : 2
    DOCUMENT_POSITION_FOLLOWING : 4
    DOCUMENT_POSITION_CONTAINS : 8
    DOCUMENT_POSITION_CONTAINED_BY : 16
    DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 32
    appendChild : function appendChild() { [native code] }
    cloneNode : function cloneNode() { [native code] }
    compareDocumentPosition : function compareDocumentPosition() { [native code] }
    contains : function contains() { [native code] }
    getRootNode : function getRootNode() { [native code] }
    hasChildNodes : function hasChildNodes() { [native code] }
    insertBefore : function insertBefore() { [native code] }
    isDefaultNamespace : function isDefaultNamespace() { [native code] }
    isEqualNode : function isEqualNode() { [native code] }
    isSameNode : function isSameNode() { [native code] }
    lookupNamespaceURI : function lookupNamespaceURI() { [native code] }
    lookupPrefix : function lookupPrefix() { [native code] }
    normalize : function normalize() { [native code] }
    removeChild : function removeChild() { [native code] }
    replaceChild : function replaceChild() { [native code] }
    addEventListener : function addEventListener() { [native code] }
    dispatchEvent : function dispatchEvent() { [native code] }
    removeEventListener : function removeEventListener() { [native code] }
    

    先ほどの test3 の時とは明らかに異なる結果になりました。

    ポイントは、

    <div id="c1">c1text</div><div id="c2">c2text</div></div>
    

    c1のdivタグの直後に、空白も改行も含めず、終了divタグの直後に、c2のdivタグを書いた点です。

    test3の時は

    c1.nextSibling -> [object Text]
    

    という Textオブジェクト が取得できていましたが、

    test4の場合は

    c1.nextSibling -> [object HTMLDivElement]
    

    という形で、HTMLDivElementオブジェクト が取得されました。

    以上のことから、nextSiblingプロパティの使い方として、空白、改行、タブ等のテキストノードを取得している場合と、
    divタグそのものを取得している場合があるので、注意が必要です。

    では、先ほどのHTMLを次のように変更してみます。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text<div id="c1">c1text</div></div>
    	<div id="p3">p3text
    		<div id="d1">d1text</div>
    		<div id="d2">d2text</div>
    		<div id="d3">d3text</div>
    		<div id="d4">d4text</div>
    	</div>
    </div>
    
    <script type="text/javascript">
    	let c1 = document.getElementById("c1");
    
    	console.log("c1.nextSibling -> " + c1.nextSibling);
    	// 「c1.nextSibling」の内容を確認する
    	for(var key in c1.nextSibling){
    		console.log(key + " : " + c1.nextSibling[key]);
    	}
    
    </script>
    
    </body>
    </html>
    

    出力結果は次のようになります。

    c1.nextSibling -> null
    

    これはdivタグの

    c1text

    の直後に、他の子要素(兄弟要素)が存在せず、
    すぐに p2 タグの閉じたタグがある為に、このような動作になります。

    以上、nextSiblingを使う場合の動きの違いを試してみました。

    実際の開発時にはDOM要素を改行、空白、タブ等のテキストノードを記述することは多いので、
    確実に兄弟要素を取得するには、注意した上で実装するか、
    他のプロパティを使って書くとよいかと思います。

    firstChild、lastChildによる探索

    Posted コメントするカテゴリー: javascript

    firstChild、lastChildによる探索

    親要素からみて子要素をfirstChildとlastChildで取得する方法を試してみます。
    まずは、前回投稿したHTMLを少し改造して、下記のHTMLを用意しました。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2">c2text</div>
    		<div id="c3">c3text</div>
    		<div id="c4">c4text</div>
    	</div>
    	<div id="p3">p3text
    		<div id="d1">d1text</div>
    		<div id="d2">d2text</div>
    		<div id="d3">d3text</div>
    		<div id="d4">d4text</div>
    	</div>
    </div>
    </div>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test1)

    このHTMLに対して、idがp2のdivタグを親として、子要素をfirstChildを使って取得してみます。
    下記のようにjavascriptを追記しました。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2">c2text</div>
    		<div id="c3">c3text</div>
    		<div id="c4">c4text</div>
    	</div>
    	<div id="p3">p3text
    		<div id="d1">d1text</div>
    		<div id="d2">d2text</div>
    		<div id="d3">d3text</div>
    		<div id="d4">d4text</div>
    	</div>
    </div>
    
    <script type="text/javascript">
    	let p2 = document.getElementById("p2");
    	console.log("p2.firstChild -> " + p2.firstChild);
    </script>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test2)

    この結果、開発ツールのログには、以下のように出力されます。

    p2.firstChild -> [object Text]
    

    親要素のp2に対して、オブジェクトの「Text」が取得できていることがわかります。
    次に、この p2.firstChild の内容を詳しく出力してみます。
    愚直な方法ですが、for 取得できたp2.firstChildの内容を全てみてみます。

    先ほどのHTMLに追記して、下記のように変更しました。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2">c2text</div>
    		<div id="c3">c3text</div>
    		<div id="c4">c4text</div>
    	</div>
    	<div id="p3">p3text
    		<div id="d1">d1text</div>
    		<div id="d2">d2text</div>
    		<div id="d3">d3text</div>
    		<div id="d4">d4text</div>
    	</div>
    </div>
    
    <script type="text/javascript">
    	let p2 = document.getElementById("p2");
    	console.log("p2.firstChild -> " + p2.firstChild);
    
    	// 「p2.firstChild」の内容を確認する
    	for(var key in p2.firstChild){
    		console.log(key + " : " + p2.firstChild[key]);
    	}
    </script>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test3)

    ログには次のように表示されました。

    p2.firstChild -> [object Text]
    wholeText : p2text
    		
    assignedSlot : null
    splitText : function splitText() { [native code] }
    data : p2text
    		
    length : 9
    previousElementSibling : null
    nextElementSibling : [object HTMLDivElement]
    after : function after() { [native code] }
    appendData : function appendData() { [native code] }
    before : function before() { [native code] }
    deleteData : function deleteData() { [native code] }
    insertData : function insertData() { [native code] }
    remove : function remove() { [native code] }
    replaceData : function replaceData() { [native code] }
    replaceWith : function replaceWith() { [native code] }
    substringData : function substringData() { [native code] }
    nodeType : 3
    nodeName : #text
    baseURI : https://propansystem.net/blogsample/js/025/test3.html
    isConnected : true
    ownerDocument : [object HTMLDocument]
    parentNode : [object HTMLDivElement]
    parentElement : [object HTMLDivElement]
    childNodes : [object NodeList]
    firstChild : null
    lastChild : null
    previousSibling : null
    nextSibling : [object HTMLDivElement]
    nodeValue : p2text
    		
    textContent : p2text
    		
    ELEMENT_NODE : 1
    ATTRIBUTE_NODE : 2
    TEXT_NODE : 3
    CDATA_SECTION_NODE : 4
    ENTITY_REFERENCE_NODE : 5
    ENTITY_NODE : 6
    PROCESSING_INSTRUCTION_NODE : 7
    COMMENT_NODE : 8
    DOCUMENT_NODE : 9
    DOCUMENT_TYPE_NODE : 10
    DOCUMENT_FRAGMENT_NODE : 11
    NOTATION_NODE : 12
    DOCUMENT_POSITION_DISCONNECTED : 1
    DOCUMENT_POSITION_PRECEDING : 2
    DOCUMENT_POSITION_FOLLOWING : 4
    DOCUMENT_POSITION_CONTAINS : 8
    DOCUMENT_POSITION_CONTAINED_BY : 16
    DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 32
    appendChild : function appendChild() { [native code] }
    cloneNode : function cloneNode() { [native code] }
    compareDocumentPosition : function compareDocumentPosition() { [native code] }
    contains : function contains() { [native code] }
    getRootNode : function getRootNode() { [native code] }
    hasChildNodes : function hasChildNodes() { [native code] }
    insertBefore : function insertBefore() { [native code] }
    isDefaultNamespace : function isDefaultNamespace() { [native code] }
    isEqualNode : function isEqualNode() { [native code] }
    isSameNode : function isSameNode() { [native code] }
    lookupNamespaceURI : function lookupNamespaceURI() { [native code] }
    lookupPrefix : function lookupPrefix() { [native code] }
    normalize : function normalize() { [native code] }
    removeChild : function removeChild() { [native code] }
    replaceChild : function replaceChild() { [native code] }
    addEventListener : function addEventListener() { [native code] }
    dispatchEvent : function dispatchEvent() { [native code] }
    removeEventListener : function removeEventListener() { [native code] }
    

    p2.firstChildの要素にアクセスし、テキストオブジェクトの内容が列挙されて出力されました。
    出力内容の中の「data」プロパティをみると、「data : p2text」と表示されていることから、

    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2">c2text</div>
    		<div id="c3">c3text</div>
    		<div id="c4">c4text</div>
    	</div>
    

    上記の部分の 「

    p2text 」の要素が取得されていることがわかります。
    id 「p2」に対しての一番最初の要素としてp2textという文字列(テキストオブジェクトのdata)が出力されています。

    では次に「lastChild」の場合はどうなるか、試してみます。
    1つ前のHTMLを以下のように書き換えて画面にアクセスしてみます。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2">c2text</div>
    		<div id="c3">c3text</div>
    		<div id="c4">c4text</div>
    	</div>
    	<div id="p3">p3text
    		<div id="d1">d1text</div>
    		<div id="d2">d2text</div>
    		<div id="d3">d3text</div>
    		<div id="d4">d4text</div>
    	</div>
    </div>
    
    <script type="text/javascript">
    	let p2 = document.getElementById("p2");
    	console.log("p2.lastChild -> " + p2.lastChild);
    
    	// 「p2.lastChild」の内容を確認する
    	for(var key in p2.lastChild){
    		console.log(key + " : " + p2.lastChild[key]);
    	}
    </script>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test4)

    ログには次のように表示されました。

    p2.lastChild -> [object Text]
    wholeText : 
    	
    assignedSlot : null
    splitText : function splitText() { [native code] }
    data : 
    	
    length : 2
    previousElementSibling : [object HTMLDivElement]
    nextElementSibling : null
    after : function after() { [native code] }
    appendData : function appendData() { [native code] }
    before : function before() { [native code] }
    deleteData : function deleteData() { [native code] }
    insertData : function insertData() { [native code] }
    remove : function remove() { [native code] }
    replaceData : function replaceData() { [native code] }
    replaceWith : function replaceWith() { [native code] }
    substringData : function substringData() { [native code] }
    nodeType : 3
    nodeName : #text
    baseURI : https://propansystem.net/blogsample/js/025/test4.html
    isConnected : true
    ownerDocument : [object HTMLDocument]
    parentNode : [object HTMLDivElement]
    parentElement : [object HTMLDivElement]
    childNodes : [object NodeList]
    firstChild : null
    lastChild : null
    previousSibling : [object HTMLDivElement]
    nextSibling : null
    nodeValue : 
    	
    textContent : 
    	
    ELEMENT_NODE : 1
    ATTRIBUTE_NODE : 2
    TEXT_NODE : 3
    CDATA_SECTION_NODE : 4
    ENTITY_REFERENCE_NODE : 5
    ENTITY_NODE : 6
    PROCESSING_INSTRUCTION_NODE : 7
    COMMENT_NODE : 8
    DOCUMENT_NODE : 9
    DOCUMENT_TYPE_NODE : 10
    DOCUMENT_FRAGMENT_NODE : 11
    NOTATION_NODE : 12
    DOCUMENT_POSITION_DISCONNECTED : 1
    DOCUMENT_POSITION_PRECEDING : 2
    DOCUMENT_POSITION_FOLLOWING : 4
    DOCUMENT_POSITION_CONTAINS : 8
    DOCUMENT_POSITION_CONTAINED_BY : 16
    DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 32
    appendChild : function appendChild() { [native code] }
    cloneNode : function cloneNode() { [native code] }
    compareDocumentPosition : function compareDocumentPosition() { [native code] }
    contains : function contains() { [native code] }
    getRootNode : function getRootNode() { [native code] }
    hasChildNodes : function hasChildNodes() { [native code] }
    insertBefore : function insertBefore() { [native code] }
    isDefaultNamespace : function isDefaultNamespace() { [native code] }
    isEqualNode : function isEqualNode() { [native code] }
    isSameNode : function isSameNode() { [native code] }
    lookupNamespaceURI : function lookupNamespaceURI() { [native code] }
    lookupPrefix : function lookupPrefix() { [native code] }
    normalize : function normalize() { [native code] }
    removeChild : function removeChild() { [native code] }
    replaceChild : function replaceChild() { [native code] }
    addEventListener : function addEventListener() { [native code] }
    dispatchEvent : function dispatchEvent() { [native code] }
    removeEventListener : function removeEventListener() { [native code] }
    

    p2.firstChildの取得の時と同様に、要素内の値を「data」のプロパティで取得できるかと思いましたが、
    p2.lastChildの場合は、実際には何も取得はされず、空白(厳密にいうとソース内のタブ文字列)が出力されています。

    では、p2.lastChildはどこの何を取得しようとしているのか、もう少し詳しく調べてみます。

    先ほどのHTMLを変更して、次のHTMLを設置しました。

    の要素の最後に「p2text2」という文字列を記述してみました。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2">c2text</div>
    		<div id="c3">c3text</div>
    		<div id="c4">c4text</div>
    		p2text2
    	</div>
    	<div id="p3">p3text
    		<div id="d1">d1text</div>
    		<div id="d2">d2text</div>
    		<div id="d3">d3text</div>
    		<div id="d4">d4text</div>
    	</div>
    </div>
    
    <script type="text/javascript">
    	let p2 = document.getElementById("p2");
    	console.log("p2.lastChild -> " + p2.lastChild);
    
    	// 「p2.lastChild」の内容を確認する
    	for(var key in p2.lastChild){
    		console.log(key + " : " + p2.lastChild[key]);
    	}
    </script>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test5)

    今度は、出力結果は次のようになります。

    p2.lastChild -> [object Text]
    wholeText : 
    		p2text2
    	
    assignedSlot : null
    splitText : function splitText() { [native code] }
    data : 
    		p2text2
    	
    length : 12
    previousElementSibling : [object HTMLDivElement]
    nextElementSibling : null
    after : function after() { [native code] }
    appendData : function appendData() { [native code] }
    before : function before() { [native code] }
    deleteData : function deleteData() { [native code] }
    insertData : function insertData() { [native code] }
    remove : function remove() { [native code] }
    replaceData : function replaceData() { [native code] }
    replaceWith : function replaceWith() { [native code] }
    substringData : function substringData() { [native code] }
    nodeType : 3
    nodeName : #text
    baseURI : https://propansystem.net/blogsample/js/025/test5.html
    isConnected : true
    ownerDocument : [object HTMLDocument]
    parentNode : [object HTMLDivElement]
    parentElement : [object HTMLDivElement]
    childNodes : [object NodeList]
    firstChild : null
    lastChild : null
    previousSibling : [object HTMLDivElement]
    nextSibling : null
    nodeValue : 
    		p2text2
    	
    textContent : 
    		p2text2
    	
    ELEMENT_NODE : 1
    ATTRIBUTE_NODE : 2
    TEXT_NODE : 3
    CDATA_SECTION_NODE : 4
    ENTITY_REFERENCE_NODE : 5
    ENTITY_NODE : 6
    PROCESSING_INSTRUCTION_NODE : 7
    COMMENT_NODE : 8
    DOCUMENT_NODE : 9
    DOCUMENT_TYPE_NODE : 10
    DOCUMENT_FRAGMENT_NODE : 11
    NOTATION_NODE : 12
    DOCUMENT_POSITION_DISCONNECTED : 1
    DOCUMENT_POSITION_PRECEDING : 2
    DOCUMENT_POSITION_FOLLOWING : 4
    DOCUMENT_POSITION_CONTAINS : 8
    DOCUMENT_POSITION_CONTAINED_BY : 16
    DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 32
    appendChild : function appendChild() { [native code] }
    cloneNode : function cloneNode() { [native code] }
    compareDocumentPosition : function compareDocumentPosition() { [native code] }
    contains : function contains() { [native code] }
    getRootNode : function getRootNode() { [native code] }
    hasChildNodes : function hasChildNodes() { [native code] }
    insertBefore : function insertBefore() { [native code] }
    isDefaultNamespace : function isDefaultNamespace() { [native code] }
    isEqualNode : function isEqualNode() { [native code] }
    isSameNode : function isSameNode() { [native code] }
    lookupNamespaceURI : function lookupNamespaceURI() { [native code] }
    lookupPrefix : function lookupPrefix() { [native code] }
    normalize : function normalize() { [native code] }
    removeChild : function removeChild() { [native code] }
    replaceChild : function replaceChild() { [native code] }
    addEventListener : function addEventListener() { [native code] }
    dispatchEvent : function dispatchEvent() { [native code] }
    removeEventListener : function removeEventListener() { [native code] }
    

    p2.lastChild のdataプロパティにある「p2text2」という文字列が出力されていることがわかります。

    ただし、上記の例の場合、半ば強引に値を取得するようにHTMLを記述したので、
    実際には厳密な仕様を把握していません。

    仕様上は、p2のノードのうち、最後の子ノードを取得するのがlastChildで、子ノードがない場合はnullを取得する。という仕様になります。

    このあたりは実際のコーディングやHTML側のDOMの状態に応じて注意して実装する必要がありそうです。

    childNodesによる探索

    Posted コメントするカテゴリー: javascript

    childNodesによる探索

    親要素からみて子要素(childNodes)を取得する方法を試してみます。

    まずは、下記のHTMLを用意しました。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2">c2text</div>
    		<div id="c3">c3text</div>
    		<div id="c4">c4text</div>
    	</div>
    	<div id="p3">p3text</div>
    </div>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test1)

    このHTMLに対して、idがp2のdivタグを親として、子要素をchildNodesを使って取得してみます。

    まずは、下記のようにjavascriptを追記しました。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2">c2text</div>
    		<div id="c3">c3text</div>
    		<div id="c4">c4text</div>
    	</div>
    	<div id="p3">p3text</div>
    </div>
    
    <script type="text/javascript">
    	let p2 = document.getElementById("p2");
    	console.log("p2.childNodes -> " + p2.childNodes);
    </script>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test2)

    この結果、開発ツールのログには、以下のように出力されます。

    p2.childNodes -> [object NodeList]
    

    親要素のp2に対して、NodeListが取得できていることがわかります。

    次に、この p2.childNodes の内容を詳しく出力してみます。
    先ほどのHTMLに追記して、下記のように変更しました。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2">c2text</div>
    		<div id="c3">c3text</div>
    		<div id="c4">c4text</div>
    	</div>
    	<div id="p3">p3text</div>
    </div>
    
    <script type="text/javascript">
    	let p2 = document.getElementById("p2");
    	console.log("p2.childNodes -> " + p2.childNodes);
    	console.log("p2.childNodes -> " + p2.childNodes[0]);
    </script>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test3)

    ログには次のように表示されました。

    p2.childNodes -> [object NodeList]
    p2.childNodes -> [object Text]
    

    p2.childNodesの1つ目の要素にアクセスし、そのオブジェクトの内容が [object Text] であることがわかりました。

    それでは、さらに追記して下記のように変更しました。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2">c2text</div>
    		<div id="c3">c3text</div>
    		<div id="c4">c4text</div>
    	</div>
    	<div id="p3">p3text</div>
    </div>
    
    <script type="text/javascript">
    	let p2 = document.getElementById("p2");
    
    	// divタグ「p2」の childNodes を出力
    	console.log("p2.childNodes -> " + p2.childNodes);
    
    	// childNodesを配列とみたてて各要素にアクセスする
    	console.log("p2.childNodes 0 -> " + p2.childNodes[0]);
    	console.log("p2.childNodes 1 -> " + p2.childNodes[0]['data']);
    
    	// 「p2.childNodes」の内容を確認する
    	for(var key in p2.childNodes[0]){
    		console.log(key + " : " + p2.childNodes[0][key]);
    	}
    </script>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test4)

    ログには次のように表示されました。

    2.childNodes -> [object NodeList]
    p2.childNodes 0 -> [object Text]
    p2.childNodes 1 -> p2text
    
    wholeText : p2text
    
    assignedSlot : null
    splitText : function splitText() { [native code] }
    data : p2text
    
    length : 5
    previousElementSibling : null
    nextElementSibling : [object HTMLDivElement]
    after : function after() { [native code] }
    appendData : function appendData() { [native code] }
    before : function before() { [native code] }
    deleteData : function deleteData() { [native code] }
    insertData : function insertData() { [native code] }
    remove : function remove() { [native code] }
    replaceData : function replaceData() { [native code] }
    replaceWith : function replaceWith() { [native code] }
    substringData : function substringData() { [native code] }
    nodeType : 3
    nodeName : #text
    baseURI : https://propansystem.net/blogsample/js/024/test4.html
    isConnected : true
    ownerDocument : [object HTMLDocument]
    parentNode : [object HTMLDivElement]
    parentElement : [object HTMLDivElement]
    childNodes : [object NodeList]
    firstChild : null
    lastChild : null
    previousSibling : null
    nextSibling : [object HTMLDivElement]
    nodeValue : p2text
    		
    textContent : p2text
    		
    ELEMENT_NODE : 1
    ATTRIBUTE_NODE : 2
    TEXT_NODE : 3
    CDATA_SECTION_NODE : 4
    ENTITY_REFERENCE_NODE : 5
    ENTITY_NODE : 6
    PROCESSING_INSTRUCTION_NODE : 7
    COMMENT_NODE : 8
    DOCUMENT_NODE : 9
    DOCUMENT_TYPE_NODE : 10
    DOCUMENT_FRAGMENT_NODE : 11
    NOTATION_NODE : 12
    DOCUMENT_POSITION_DISCONNECTED : 1
    DOCUMENT_POSITION_PRECEDING : 2
    DOCUMENT_POSITION_FOLLOWING : 4
    DOCUMENT_POSITION_CONTAINS : 8
    DOCUMENT_POSITION_CONTAINED_BY : 16
    DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 32
    appendChild : function appendChild() { [native code] }
    cloneNode : function cloneNode() { [native code] }
    compareDocumentPosition : function compareDocumentPosition() { [native code] }
    contains : function contains() { [native code] }
    getRootNode : function getRootNode() { [native code] }
    hasChildNodes : function hasChildNodes() { [native code] }
    insertBefore : function insertBefore() { [native code] }
    isDefaultNamespace : function isDefaultNamespace() { [native code] }
    isEqualNode : function isEqualNode() { [native code] }
    isSameNode : function isSameNode() { [native code] }
    lookupNamespaceURI : function lookupNamespaceURI() { [native code] }
    lookupPrefix : function lookupPrefix() { [native code] }
    normalize : function normalize() { [native code] }
    removeChild : function removeChild() { [native code] }
    replaceChild : function replaceChild() { [native code] }
    addEventListener : function addEventListener() { [native code] }
    dispatchEvent : function dispatchEvent() { [native code] }
    removeEventListener : function removeEventListener() { 
    

    p2.childNodes 1 -> p2text と表示されている行から、 p2.childNodes[0][‘data’] を出力すると、

    タグのテキスト情報「p2text」を取得していることがわかります。

    では次に、div id=”c1″ の内容を取得してみます。

    先ほどのHTMLを変更して、次のHTMLを設置しました。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2">c2text</div>
    		<div id="c3">c3text</div>
    		<div id="c4">c4text</div>
    	</div>
    	<div id="p3">p3text</div>
    </div>
    
    <script type="text/javascript">
    	let p2 = document.getElementById("p2");
    
    	// divタグ「p2」の childNodes を出力
    	console.log("p2.childNodes -> " + p2.childNodes);
    
    	// childNodesを配列とみたてて各要素にアクセスする
    	console.log("p2.childNodes 0 -> " + p2.childNodes[0]);
    	console.log("p2.childNodes 0 -> " + p2.childNodes[0]['data']);
    
    	console.log("p2.childNodes 1 -> " + p2.childNodes[1]);
    	console.log("p2.childNodes 1 -> " + p2.childNodes[1].innerHTML);
    </script>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test5)

    出力結果は次のようになります。

    p2.childNodes -> [object NodeList]
    p2.childNodes 0 -> [object Text]
    p2.childNodes 0 -> p2text
    
    p2.childNodes 1 -> [object HTMLDivElement]
    p2.childNodes 1 -> c1text
    

    p2.childNodes[1] という形で、配列の1つ目にアクセスすると、

    タグにアクセスしていることがわかります。
    さらに、p2.childNodes[1].innerHTML で要素内のHTMLを取得してみると「c1text」というHTML内の値を取得できていることがわかります。

    同様に、他の要素にもアクセスしてみます。
    HTMLを次のように変更します。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2">c2text</div>
    		<div id="c3">c3text</div>
    		<div id="c4">c4text</div>
    	</div>
    	<div id="p3">p3text</div>
    </div>
    
    <script type="text/javascript">
    	let p2 = document.getElementById("p2");
    
    	// divタグ「p2」の childNodes を出力
    	console.log("p2.childNodes -> " + p2.childNodes);
    
    	// childNodesを配列とみたてて各要素にアクセスする
    	console.log("p2.childNodes 0 -> " + p2.childNodes[0]);
    	console.log("p2.childNodes 0 -> " + p2.childNodes[0]['data']);
    
    	console.log("p2.childNodes 1 -> " + p2.childNodes[1]);
    	console.log("p2.childNodes 1 -> " + p2.childNodes[1].innerHTML);
    	console.log("p2.childNodes 2 -> " + p2.childNodes[2]);
    	console.log("p2.childNodes 2 -> " + p2.childNodes[2].innerHTML);
    	console.log("p2.childNodes 3 -> " + p2.childNodes[3]);
    	console.log("p2.childNodes 3 -> " + p2.childNodes[3].innerHTML);
    	console.log("p2.childNodes 4 -> " + p2.childNodes[4]);
    	console.log("p2.childNodes 4 -> " + p2.childNodes[4].innerHTML);
    	console.log("p2.childNodes 5 -> " + p2.childNodes[5]);
    	console.log("p2.childNodes 5 -> " + p2.childNodes[5].innerHTML);
    	console.log("p2.childNodes 6 -> " + p2.childNodes[6]);
    	console.log("p2.childNodes 6 -> " + p2.childNodes[6].innerHTML);
    	console.log("p2.childNodes 7 -> " + p2.childNodes[7]);
    	console.log("p2.childNodes 7 -> " + p2.childNodes[7].innerHTML);
    	console.log("p2.childNodes 8 -> " + p2.childNodes[8]);
    	console.log("p2.childNodes 8 -> " + p2.childNodes[8].innerHTML);
    </script>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test6)

    出力結果は次のようになります。

    p2.childNodes -> [object NodeList]
    p2.childNodes 0 -> [object Text]
    p2.childNodes 0 -> p2text
    
    p2.childNodes 1 -> [object HTMLDivElement]
    p2.childNodes 1 -> c1text
    p2.childNodes 2 -> [object Text]
    p2.childNodes 2 -> undefined
    p2.childNodes 3 -> [object HTMLDivElement]
    p2.childNodes 3 -> c2text
    p2.childNodes 4 -> [object Text]
    p2.childNodes 4 -> undefined
    p2.childNodes 5 -> [object HTMLDivElement]
    p2.childNodes 5 -> c3text
    p2.childNodes 6 -> [object Text]
    p2.childNodes 6 -> undefined
    p2.childNodes 7 -> [object HTMLDivElement]
    p2.childNodes 7 -> c4text
    p2.childNodes 8 -> [object Text]
    p2.childNodes 8 -> undefined
    

    ここでわかることは、p2の要素としてchildNodesを取得した結果として、
    p2.childNodes[1].innerHTML の値は、要素c1タグの「c1text」が取得できていますが、
    p2.childNodes[2].innerHTML の値は未定義(undefined)になることです。

    p2.childNodes[3].innerHTML の値を取得して初めて、画面上の次の値である「c2text」が取得できました。
    同様に、c4textの値も、childNodesの7つ目の要素「p2.childNodes[7].innerHTML」で初めて取得できています。

    p2の要素としてchildNodesを取得する際、一見すると配列の値として順番に画面上の値が取得できそうですが、
    厳密にDOM要素の順番に要素を取得していることがわかります。

    また、「p2.childNodes[1]」の中にどんな情報が格納されているかを確かめてみます。
    HTMLを次のように変更しました。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="p1">p1text</div>
    	<div id="p2">p2text
    		<div id="c1">c1text</div>
    		<div id="c2">c2text</div>
    		<div id="c3">c3text</div>
    		<div id="c4">c4text</div>
    	</div>
    	<div id="p3">p3text</div>
    </div>
    
    <script type="text/javascript">
    	let p2 = document.getElementById("p2");
    
    	// divタグ「p2」の childNodes を出力
    	console.log("p2.childNodes -> " + p2.childNodes);
    
    	// childNodesを配列とみたてて各要素にアクセスする
    	console.log("p2.childNodes 0 -> " + p2.childNodes[0]);
    	console.log("p2.childNodes 0 -> " + p2.childNodes[0]['data']);
    
    	console.log("p2.childNodes 1 -> " + p2.childNodes[1]);
    	console.log("p2.childNodes 1 -> " + p2.childNodes[1].innerHTML);
    
    	// 「p2.childNodes[1]」の内容を確認する
    	for(var key in p2.childNodes[1]){
    		console.log(key + " : " + p2.childNodes[1][key]);
    	}
    </script>
    
    </body>
    </html>
    

    サーバ上のHTMLはこちら(test7)

    出力結果は次のようになります。

    p2.childNodes -> [object NodeList]
    p2.childNodes 0 -> [object Text]
    p2.childNodes 0 -> p2text
    
    p2.childNodes 1 -> [object HTMLDivElement]
    p2.childNodes 1 -> c1text
    align : 
    title : 
    lang : 
    translate : true
    dir : 
    hidden : false
    accessKey : 
    draggable : false
    spellcheck : true
    autocapitalize : 
    contentEditable : inherit
    isContentEditable : false
    inputMode : 
    offsetParent : [object HTMLBodyElement]
    offsetTop : 56
    offsetLeft : 8
    offsetWidth : 997
    offsetHeight : 24
    style : [object CSSStyleDeclaration]
    innerText : c1text
    outerText : c1text
    onbeforexrselect : null
    onabort : null
    onblur : null
    oncancel : null
    oncanplay : null
    oncanplaythrough : null
    onchange : null
    onclick : null
    onclose : null
    oncontextmenu : null
    oncuechange : null
    ondblclick : null
    ondrag : null
    ondragend : null
    ondragenter : null
    ondragleave : null
    ondragover : null
    ondragstart : null
    ondrop : null
    ondurationchange : null
    onemptied : null
    onended : null
    onerror : null
    onfocus : null
    onformdata : null
    oninput : null
    oninvalid : null
    onkeydown : null
    onkeypress : null
    onkeyup : null
    onload : null
    onloadeddata : null
    onloadedmetadata : null
    onloadstart : null
    onmousedown : null
    onmouseenter : null
    onmouseleave : null
    onmousemove : null
    onmouseout : null
    onmouseover : null
    onmouseup : null
    onmousewheel : null
    onpause : null
    onplay : null
    onplaying : null
    onprogress : null
    onratechange : null
    onreset : null
    onresize : null
    onscroll : null
    onseeked : null
    onseeking : null
    onselect : null
    onstalled : null
    onsubmit : null
    onsuspend : null
    ontimeupdate : null
    ontoggle : null
    onvolumechange : null
    onwaiting : null
    onwebkitanimationend : null
    onwebkitanimationiteration : null
    onwebkitanimationstart : null
    onwebkittransitionend : null
    onwheel : null
    onauxclick : null
    ongotpointercapture : null
    onlostpointercapture : null
    onpointerdown : null
    onpointermove : null
    onpointerup : null
    onpointercancel : null
    onpointerover : null
    onpointerout : null
    onpointerenter : null
    onpointerleave : null
    onselectstart : null
    onselectionchange : null
    onanimationend : null
    onanimationiteration : null
    onanimationstart : null
    ontransitionrun : null
    ontransitionstart : null
    ontransitionend : null
    ontransitioncancel : null
    oncopy : null
    oncut : null
    onpaste : null
    dataset : [object DOMStringMap]
    nonce : 
    autofocus : false
    tabIndex : -1
    attachInternals : function attachInternals() { [native code] }
    blur : function blur() { [native code] }
    click : function click() { [native code] }
    focus : function focus() { [native code] }
    onpointerrawupdate : null
    enterKeyHint : 
    namespaceURI : http://www.w3.org/1999/xhtml
    prefix : null
    localName : div
    tagName : DIV
    id : c1
    className : 
    classList : 
    slot : 
    attributes : [object NamedNodeMap]
    shadowRoot : null
    part : 
    assignedSlot : null
    innerHTML : c1text
    outerHTML : <div id="c1">c1text</div>
    scrollTop : 0
    scrollLeft : 0
    scrollWidth : 997
    scrollHeight : 24
    clientTop : 0
    clientLeft : 0
    clientWidth : 997
    clientHeight : 24
    attributeStyleMap : [object StylePropertyMap]
    onbeforecopy : null
    onbeforecut : null
    onbeforepaste : null
    onsearch : null
    elementTiming : 
    onfullscreenchange : null
    onfullscreenerror : null
    onwebkitfullscreenchange : null
    onwebkitfullscreenerror : null
    children : [object HTMLCollection]
    firstElementChild : null
    lastElementChild : null
    childElementCount : 0
    previousElementSibling : null
    nextElementSibling : [object HTMLDivElement]
    after : function after() { [native code] }
    animate : function animate() { [native code] }
    append : function append() { [native code] }
    attachShadow : function attachShadow() { [native code] }
    before : function before() { [native code] }
    closest : function closest() { [native code] }
    computedStyleMap : function computedStyleMap() { [native code] }
    getAttribute : function getAttribute() { [native code] }
    getAttributeNS : function getAttributeNS() { [native code] }
    getAttributeNames : function getAttributeNames() { [native code] }
    getAttributeNode : function getAttributeNode() { [native code] }
    getAttributeNodeNS : function getAttributeNodeNS() { [native code] }
    getBoundingClientRect : function getBoundingClientRect() { [native code] }
    getClientRects : function getClientRects() { [native code] }
    getElementsByClassName : function getElementsByClassName() { [native code] }
    getElementsByTagName : function getElementsByTagName() { [native code] }
    getElementsByTagNameNS : function getElementsByTagNameNS() { [native code] }
    hasAttribute : function hasAttribute() { [native code] }
    hasAttributeNS : function hasAttributeNS() { [native code] }
    hasAttributes : function hasAttributes() { [native code] }
    hasPointerCapture : function hasPointerCapture() { [native code] }
    insertAdjacentElement : function insertAdjacentElement() { [native code] }
    insertAdjacentHTML : function insertAdjacentHTML() { [native code] }
    insertAdjacentText : function insertAdjacentText() { [native code] }
    matches : function matches() { [native code] }
    prepend : function prepend() { [native code] }
    querySelector : function querySelector() { [native code] }
    querySelectorAll : function querySelectorAll() { [native code] }
    releasePointerCapture : function releasePointerCapture() { [native code] }
    remove : function remove() { [native code] }
    removeAttribute : function removeAttribute() { [native code] }
    removeAttributeNS : function removeAttributeNS() { [native code] }
    removeAttributeNode : function removeAttributeNode() { [native code] }
    replaceChildren : function replaceChildren() { [native code] }
    replaceWith : function replaceWith() { [native code] }
    requestFullscreen : function requestFullscreen() { [native code] }
    requestPointerLock : function requestPointerLock() { [native code] }
    scroll : function scroll() { [native code] }
    scrollBy : function scrollBy() { [native code] }
    scrollIntoView : function scrollIntoView() { [native code] }
    scrollIntoViewIfNeeded : function scrollIntoViewIfNeeded() { [native code] }
    scrollTo : function scrollTo() { [native code] }
    setAttribute : function setAttribute() { [native code] }
    setAttributeNS : function setAttributeNS() { [native code] }
    setAttributeNode : function setAttributeNode() { [native code] }
    setAttributeNodeNS : function setAttributeNodeNS() { [native code] }
    setPointerCapture : function setPointerCapture() { [native code] }
    toggleAttribute : function toggleAttribute() { [native code] }
    webkitMatchesSelector : function webkitMatchesSelector() { [native code] }
    webkitRequestFullScreen : function webkitRequestFullScreen() { [native code] }
    webkitRequestFullscreen : function webkitRequestFullscreen() { [native code] }
    ariaAtomic : null
    ariaAutoComplete : null
    ariaBusy : null
    ariaChecked : null
    ariaColCount : null
    ariaColIndex : null
    ariaColSpan : null
    ariaCurrent : null
    ariaDescription : null
    ariaDisabled : null
    ariaExpanded : null
    ariaHasPopup : null
    ariaHidden : null
    ariaKeyShortcuts : null
    ariaLabel : null
    ariaLevel : null
    ariaLive : null
    ariaModal : null
    ariaMultiLine : null
    ariaMultiSelectable : null
    ariaOrientation : null
    ariaPlaceholder : null
    ariaPosInSet : null
    ariaPressed : null
    ariaReadOnly : null
    ariaRelevant : null
    ariaRequired : null
    ariaRoleDescription : null
    ariaRowCount : null
    ariaRowIndex : null
    ariaRowSpan : null
    ariaSelected : null
    ariaSetSize : null
    ariaSort : null
    ariaValueMax : null
    ariaValueMin : null
    ariaValueNow : null
    ariaValueText : null
    getInnerHTML : function getInnerHTML() { [native code] }
    getAnimations : function getAnimations() { [native code] }
    nodeType : 1
    nodeName : DIV
    baseURI : https://propansystem.net/blogsample/js/024/test7.html
    isConnected : true
    ownerDocument : [object HTMLDocument]
    parentNode : [object HTMLDivElement]
    parentElement : [object HTMLDivElement]
    childNodes : [object NodeList]
    firstChild : [object Text]
    lastChild : [object Text]
    previousSibling : [object Text]
    nextSibling : [object Text]
    nodeValue : null
    textContent : c1text
    ELEMENT_NODE : 1
    ATTRIBUTE_NODE : 2
    TEXT_NODE : 3
    CDATA_SECTION_NODE : 4
    ENTITY_REFERENCE_NODE : 5
    ENTITY_NODE : 6
    PROCESSING_INSTRUCTION_NODE : 7
    COMMENT_NODE : 8
    DOCUMENT_NODE : 9
    DOCUMENT_TYPE_NODE : 10
    DOCUMENT_FRAGMENT_NODE : 11
    NOTATION_NODE : 12
    DOCUMENT_POSITION_DISCONNECTED : 1
    DOCUMENT_POSITION_PRECEDING : 2
    DOCUMENT_POSITION_FOLLOWING : 4
    DOCUMENT_POSITION_CONTAINS : 8
    DOCUMENT_POSITION_CONTAINED_BY : 16
    DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 32
    appendChild : function appendChild() { [native code] }
    cloneNode : function cloneNode() { [native code] }
    compareDocumentPosition : function compareDocumentPosition() { [native code] }
    contains : function contains() { [native code] }
    getRootNode : function getRootNode() { [native code] }
    hasChildNodes : function hasChildNodes() { [native code] }
    insertBefore : function insertBefore() { [native code] }
    isDefaultNamespace : function isDefaultNamespace() { [native code] }
    isEqualNode : function isEqualNode() { [native code] }
    isSameNode : function isSameNode() { [native code] }
    lookupNamespaceURI : function lookupNamespaceURI() { [native code] }
    lookupPrefix : function lookupPrefix() { [native code] }
    normalize : function normalize() { [native code] }
    removeChild : function removeChild() { [native code] }
    replaceChild : function replaceChild() { [native code] }
    addEventListener : function addEventListener() { [native code] }
    dispatchEvent : function dispatchEvent() { [native code] }
    removeEventListener : function removeEventListener() { [native code] }
    

    keyの名前の出力部分を見てわかるとおり、[object HTMLDivElement]の一連の要素名が格納されていることがわかります。

    実際のプログラムの実装ではchildNodes内の各要素を正確に把握して、取得した要素内の[object HTMLDivElement]の値を必要に応じて取得して実装を行います。

    要素の探索

    Posted コメントするカテゴリー: javascript

    要素の探索

    ドキュメント内の要素(Element)はツリー構造になっています。
    このツリー構造の要素を探索する方法を試してみます。

    実際に下記のHTMLファイルを作成し、サーバに設置してみました。
    サンプル画面

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    </head>
    <body>
    
    <div id="test1">
    	<div id="test1_1">
    		a
    	</div>
    	<div id="test1_2">
    		b
    
    		<div id="test1_2_1">
    			b1
    		</div>
    		<div id="test1_2_2">
    			b2
    		</div>
    
    		<div id="test2_2_1">
    			id_b1
    		</div>
    		<div id="test2_2_2">
    			id_b2
    		</div>
    
    	</div>
    	<div id="test1_3">
    		b
    	</div>
    </div>
    
    <script type="text/javascript">
    
    	let test1_2_1 = document.getElementById("test1_2_1");
    
    	// オブジェクトの内容を確認する
    	for(var key in test1_2_1){
    		console.log(key + " : " + test1_2_1[key]);
    	}
    
    	console.log("test1_2_1 -> " + test1_2_1);
    	console.log("test1_2_1.parentNode -> " + test1_2_1.parentNode);
    	console.log("test1_2_1.parentElement -> " + test1_2_1.parentElement);
    
    
    </script>
    
    </body>
    </html>
    

    上記のHTMLソースには「id=”test1″」のdivタグ内にネストされた形で

    「id=”test1_1″」
    「id=”test1_2″」
    「id=”test1_3″」

    のdivタグがそれぞれあります。

    この状態でツリー構造の要素を取得する方法を試してみます。
    具体的には以下の要素取得のコードを書いてみます。

    parentNodeによる探索

    要素の「test1_2_1」に対して、「parentNode」を使って親要素を取得してみます。
    以下のように取得のtest1_2_1を取得し、取得した要素に.parentNodeを使って親要素を取得してみます。

    	let test1_2_1 = document.getElementById("test1_2_1");
    	console.log("test1_2_1.parentNode -> " + test1_2_1.parentNode);
    

    結果は、次のように出力されます。

    test1_2_1 -> [object HTMLDivElement]
    test1_2_1.parentNode -> [object HTMLDivElement]
    test1_2_1.parentElement -> [object HTMLDivElement]
    

    .parentNodeと取得しても、.parentElementと取得しても、出力内容に違いはないように見えますが、
    厳密には異なる取得方法になるので、使い分けが必要です。

    .parentNodeはidが「test1_2_1」の親ノードの「test1_2」のNodeを示します。

    また、.parentElement については、Nodeを親に持つインターフェースで、XMLで使用されます。

    HTML(DOM)のcssセレクタによる要素の選択

    Posted コメントするカテゴリー: javascript

    HTML(DOM)のcssセレクタによる要素の選択

    HTMLソース内にあるcssセレクタによる要素の選択を試してみます。
    以下のソースがある場合、HTML本文内にあるdivタグの選択をします。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    
    </head>
    <body>
     
    <div class="test">test1</div>
    <div class="test">test2</div>
    <div class="test">test3</div>
    <div class="test">test4</div>
    <div class="test">test5</div>
    
    <div id="testid">testid</div>
    
    
    <script type="text/javascript">
    
    let test_class1 = document.querySelector('.test');
    console.log("test_class1 -> " + test_class1);
    
    let test_class2 = document.querySelectorAll('test');
    console.log("test_class2 -> " + test_class2);
    
    </script>
    
    </body>
    </html>
    

    コンソールの出力は以下のようになります。

    
    test_class1 -> [object HTMLDivElement]
    
    test_class2 -> [object NodeList]
    
    

    要素の取得方法としては「querySelector」を使う場合と、「querySelectorAll」を使う場合があります。

    前者は画面内のドキュメント全体から、最初に見つかった要素を1つだけ取得し、
    後者は画面内のドキュメント全体から、該当する要素を全て取得していることがわかります。

    また、後者は [object NodeList] という出力なので、NodeListが返されていることもわかります。

    HTML(DOM)のclassによる要素の選択

    Posted コメントするカテゴリー: javascript

    HTML(DOM)のclassによる要素の選択

    HTMLソース内にあるclass名による要素の選択を試してみます。
    以下のソースがある場合、HTML本文内にあるdivタグの選択をします。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    
    </head>
    <body>
     
    <div class="test">test1</div>
    <div class="test">test2</div>
    <div class="test">test3</div>
    <div class="test">test4</div>
    <div class="test">test5</div>
    
    <script type="text/javascript">
    let test_class = document.getElementsByClassName('test');
    console.log("test_class -> " + test_class);
    </script>
    
    </body>
    </html>
    

    コンソールの出力は以下のようになります。

    test_class -> [object HTMLCollection]
    

    続いて、javascriptを下記のように書き変えて、test_classで取得できた内容を出力してみます。

    
    <script type="text/javascript">
    let test_class = document.getElementsByClassName('test');
    
    console.log("test_class -> " + test_class);
    
    Array.prototype.forEach.call(test_class, function(item) {
        console.dir(item);
    });
    
    </script>
    
    

    結果は、次のようになります。

    test_class -> [object HTMLCollection]
    test.html:21 div.test
    test.html:21 div.test
    test.html:21 div.test
    test.html:21 div.test
    test.html:21 div.test
    

    という出力になりました。

    ただし、これはブラウザの開発ツールで見た結果なので、
    「div.test」の中にはさらに詳細な情報が含まれています。

    例えば、一番上の「div.test」を展開してみると、次のような結果になります。

    div.test
    accessKey: ""
    align: ""
    ariaAtomic: null
    ariaAutoComplete: null
    ariaBusy: null
    ariaChecked: null
    ariaColCount: null
    ariaColIndex: null
    ariaColSpan: null
    ariaCurrent: null
    ariaDescription: null
    ariaDisabled: null
    ariaExpanded: null
    ariaHasPopup: null
    ariaHidden: null
    ariaKeyShortcuts: null
    ariaLabel: null
    ariaLevel: null
    ariaLive: null
    ariaModal: null
    ariaMultiLine: null
    ariaMultiSelectable: null
    ariaOrientation: null
    ariaPlaceholder: null
    ariaPosInSet: null
    ariaPressed: null
    ariaReadOnly: null
    ariaRelevant: null
    ariaRequired: null
    ariaRoleDescription: null
    ariaRowCount: null
    ariaRowIndex: null
    ariaRowSpan: null
    ariaSelected: null
    ariaSetSize: null
    ariaSort: null
    ariaValueMax: null
    ariaValueMin: null
    ariaValueNow: null
    ariaValueText: null
    assignedSlot: null
    attributeStyleMap: StylePropertyMap {size: 0}
    attributes: NamedNodeMap {0: class, class: class, length: 1}
    autocapitalize: ""
    autofocus: false
    baseURI: "https://propansystem.net/blogsample/js/021/test.html"
    childElementCount: 0
    childNodes: NodeList [text]
    children: HTMLCollection []
    classList: DOMTokenList ["test", value: "test"]
    className: "test"
    clientHeight: 24
    clientLeft: 0
    clientTop: 0
    clientWidth: 1007
    contentEditable: "inherit"
    dataset: DOMStringMap {}
    dir: ""
    draggable: false
    elementTiming: ""
    enterKeyHint: ""
    firstChild: text
    firstElementChild: null
    hidden: false
    id: ""
    innerHTML: "test1"
    innerText: "test1"
    inputMode: ""
    isConnected: true
    isContentEditable: false
    lang: ""
    lastChild: text
    lastElementChild: null
    localName: "div"
    namespaceURI: "http://www.w3.org/1999/xhtml"
    nextElementSibling: div.test
    nextSibling: text
    nodeName: "DIV"
    nodeType: 1
    nodeValue: null
    nonce: ""
    offsetHeight: 24
    offsetLeft: 8
    offsetParent: body
    offsetTop: 8
    offsetWidth: 1007
    onabort: null
    onanimationend: null
    onanimationiteration: null
    onanimationstart: null
    onauxclick: null
    onbeforecopy: null
    onbeforecut: null
    onbeforepaste: null
    onbeforexrselect: null
    onblur: null
    oncancel: null
    oncanplay: null
    oncanplaythrough: null
    onchange: null
    onclick: null
    onclose: null
    oncontextmenu: null
    oncopy: null
    oncuechange: null
    oncut: null
    ondblclick: null
    ondrag: null
    ondragend: null
    ondragenter: null
    ondragleave: null
    ondragover: null
    ondragstart: null
    ondrop: null
    ondurationchange: null
    onemptied: null
    onended: null
    onerror: null
    onfocus: null
    onformdata: null
    onfullscreenchange: null
    onfullscreenerror: null
    ongotpointercapture: null
    oninput: null
    oninvalid: null
    onkeydown: null
    onkeypress: null
    onkeyup: null
    onload: null
    onloadeddata: null
    onloadedmetadata: null
    onloadstart: null
    onlostpointercapture: null
    onmousedown: null
    onmouseenter: null
    onmouseleave: null
    onmousemove: null
    onmouseout: null
    onmouseover: null
    onmouseup: null
    onmousewheel: null
    onpaste: null
    onpause: null
    onplay: null
    onplaying: null
    onpointercancel: null
    onpointerdown: null
    onpointerenter: null
    onpointerleave: null
    onpointermove: null
    onpointerout: null
    onpointerover: null
    onpointerrawupdate: null
    onpointerup: null
    onprogress: null
    onratechange: null
    onreset: null
    onresize: null
    onscroll: null
    onsearch: null
    onseeked: null
    onseeking: null
    onselect: null
    onselectionchange: null
    onselectstart: null
    onstalled: null
    onsubmit: null
    onsuspend: null
    ontimeupdate: null
    ontoggle: null
    ontransitioncancel: null
    ontransitionend: null
    ontransitionrun: null
    ontransitionstart: null
    onvolumechange: null
    onwaiting: null
    onwebkitanimationend: null
    onwebkitanimationiteration: null
    onwebkitanimationstart: null
    onwebkitfullscreenchange: null
    onwebkitfullscreenerror: null
    onwebkittransitionend: null
    onwheel: null
    outerHTML: "<div class=\"test\">test1</div>"
    outerText: "test1"
    ownerDocument: document
    parentElement: head
    parentNode: head
    part: DOMTokenList [value: ""]
    prefix: null
    previousElementSibling: title
    previousSibling: text
    scrollHeight: 24
    scrollLeft: 0
    scrollTop: 0
    scrollWidth: 1007
    shadowRoot: null
    slot: ""
    spellcheck: true
    style: CSSStyleDeclaration {additiveSymbols: "", alignContent: "", alignItems: "", alignSelf: "", alignmentBaseline: "", …}
    tabIndex: -1
    tagName: "DIV"
    textContent: "test1"
    title: ""
    translate: true
    __proto__: HTMLDivElement
    

    これも、前回の名前で取得した時と同様、divタグをjavascript側のオブジェクトとして取得していることがわかります。

    また、メソッドもプロパティも同様に含まれているので、プログラミングをしてdivタグを操作することが可能になります。

    HTML(DOM)のタグ名(型)による要素の選択

    Posted コメントするカテゴリー: javascript

    HTML(DOM)のタグ名(型)による要素の選択

    HTMLソース内にあるタグ名による要素の選択を試してみます。
    以下のソースがある場合、HTML本文内にあるdivタグの選択をします。

    HTMLソース内にdivタグの組み合わせが一つしかない場合は、それ単一で、
    複数ある場合は、NodeListオブジェクトを取得します。

    HTMLタグは大文字でも小文字でも取得されます。(区別されない)

    実際に下記のHTMLソースをサーバ上に置き、ブラウザからアクセスして試してみます。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    
    </head>
    <body>
     
    <div>test1</div>
    <div>test2</div>
    <div>test3</div>
    <div>test4</div>
    <div>test5</div>
    
    <script type="text/javascript">
    let test_tag = document.getElementsByTagName('div');
    console.log("test_tag -> " + test_tag);
    </script>
    
    </body>
    </html>
    

    コンソールの出力は以下のようになります。

    test_tag -> [object HTMLCollection]
    

    先ほどNodeListオブジェクトと書きましたが、開発ツールで確認すると、
    HTMLCollections という値になりました。

    では、このHTMLCollectionsに対して、javascriptからアクセスしてみます。

    先ほどのHTMLソース内のjavascriptの箇所に、下記のように追記してみます。

    
    <script type="text/javascript">
    let test_tag = document.getElementsByTagName('div');
    console.log("test_tag -> " + test_tag);
    
    Array.prototype.forEach.call(test_tag, function(item) {
        console.dir(item);
    });
    
    </script>
    
    

    結果は、次のようになります。
    (ここでは便宜上console.dirを使って確認しています)

    test_tag -> [object HTMLCollection]
    test.html:21 
    div
    accessKey: ""
    align: ""
    ariaAtomic: null
    ariaAutoComplete: null
    ariaBusy: null
    ariaChecked: null
    ariaColCount: null
    ariaColIndex: null
    ariaColSpan: null
    ariaCurrent: null
    ariaDescription: null
    ariaDisabled: null
    ariaExpanded: null
    ariaHasPopup: null
    ariaHidden: null
    ariaKeyShortcuts: null
    ariaLabel: null
    ariaLevel: null
    ariaLive: null
    ariaModal: null
    ariaMultiLine: null
    ariaMultiSelectable: null
    ariaOrientation: null
    ariaPlaceholder: null
    ariaPosInSet: null
    ariaPressed: null
    ariaReadOnly: null
    ariaRelevant: null
    ariaRequired: null
    ariaRoleDescription: null
    ariaRowCount: null
    ariaRowIndex: null
    ariaRowSpan: null
    ariaSelected: null
    ariaSetSize: null
    ariaSort: null
    ariaValueMax: null
    ariaValueMin: null
    ariaValueNow: null
    ariaValueText: null
    assignedSlot: null
    attributeStyleMap: StylePropertyMap {size: 0}
    attributes: NamedNodeMap {length: 0}
    autocapitalize: ""
    autofocus: false
    baseURI: "https://propansystem.net/blogsample/js/020/test.html"
    childElementCount: 0
    childNodes: NodeList [text]
    children: HTMLCollection []
    classList: DOMTokenList [value: ""]
    className: ""
    clientHeight: 24
    clientLeft: 0
    clientTop: 0
    clientWidth: 1006
    contentEditable: "inherit"
    dataset: DOMStringMap {}
    dir: ""
    draggable: false
    elementTiming: ""
    enterKeyHint: ""
    firstChild: text
    firstElementChild: null
    hidden: false
    id: ""
    innerHTML: "test1"
    innerText: "test1"
    inputMode: ""
    isConnected: true
    isContentEditable: false
    lang: ""
    lastChild: text
    lastElementChild: null
    localName: "div"
    namespaceURI: "http://www.w3.org/1999/xhtml"
    nextElementSibling: div
    nextSibling: text
    nodeName: "DIV"
    nodeType: 1
    nodeValue: null
    nonce: ""
    offsetHeight: 24
    offsetLeft: 8
    offsetParent: body
    offsetTop: 8
    offsetWidth: 1006
    onabort: null
    onanimationend: null
    onanimationiteration: null
    onanimationstart: null
    onauxclick: null
    onbeforecopy: null
    onbeforecut: null
    onbeforepaste: null
    onbeforexrselect: null
    onblur: null
    oncancel: null
    oncanplay: null
    oncanplaythrough: null
    onchange: null
    onclick: null
    onclose: null
    oncontextmenu: null
    oncopy: null
    oncuechange: null
    oncut: null
    ondblclick: null
    ondrag: null
    ondragend: null
    ondragenter: null
    ondragleave: null
    ondragover: null
    ondragstart: null
    ondrop: null
    ondurationchange: null
    onemptied: null
    onended: null
    onerror: null
    onfocus: null
    onformdata: null
    onfullscreenchange: null
    onfullscreenerror: null
    ongotpointercapture: null
    oninput: null
    oninvalid: null
    onkeydown: null
    onkeypress: null
    onkeyup: null
    onload: null
    onloadeddata: null
    onloadedmetadata: null
    onloadstart: null
    onlostpointercapture: null
    onmousedown: null
    onmouseenter: null
    onmouseleave: null
    onmousemove: null
    onmouseout: null
    onmouseover: null
    onmouseup: null
    onmousewheel: null
    onpaste: null
    onpause: null
    onplay: null
    onplaying: null
    onpointercancel: null
    onpointerdown: null
    onpointerenter: null
    onpointerleave: null
    onpointermove: null
    onpointerout: null
    onpointerover: null
    onpointerrawupdate: null
    onpointerup: null
    onprogress: null
    onratechange: null
    onreset: null
    onresize: null
    onscroll: null
    onsearch: null
    onseeked: null
    onseeking: null
    onselect: null
    onselectionchange: null
    onselectstart: null
    onstalled: null
    onsubmit: null
    onsuspend: null
    ontimeupdate: null
    ontoggle: null
    ontransitioncancel: null
    ontransitionend: null
    ontransitionrun: null
    ontransitionstart: null
    onvolumechange: null
    onwaiting: null
    onwebkitanimationend: null
    onwebkitanimationiteration: null
    onwebkitanimationstart: null
    onwebkitfullscreenchange: null
    onwebkitfullscreenerror: null
    onwebkittransitionend: null
    onwheel: null
    outerHTML: "<div>test1</div>"
    outerText: "test1"
    ownerDocument: document
    parentElement: head
    parentNode: head
    part: DOMTokenList [value: ""]
    prefix: null
    previousElementSibling: title
    previousSibling: text
    scrollHeight: 24
    scrollLeft: 0
    scrollTop: 0
    scrollWidth: 1006
    shadowRoot: null
    slot: ""
    spellcheck: true
    style: CSSStyleDeclaration {additiveSymbols: "", alignContent: "", alignItems: "", alignSelf: "", alignmentBaseline: "", …}
    tabIndex: -1
    tagName: "DIV"
    textContent: "test1"
    title: ""
    translate: true
    __proto__: HTMLDivElement
    

    という出力になりました。
    これはHTMLCollections内の要素にアクセスしたところ、HTMLDivElementというオブジェクトが返されたことになります。

    HTML(DOM)の名前による要素の選択

    Posted コメントするカテゴリー: javascript

    HTML(DOM)の名前による要素の選択

    前回の投稿ではDOMのid要素により、javascriptから要素を取得する方法を試しましたが、
    name属性でも同様に要素を取得できるので試してみます。

    例えば、HTMLソースが以下の場合の要素「test_youso2」を取得してみます。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    
    </head>
    <body>
     
    <h3>タイトル</h3>
    <p name="test_dom2">テスト要素2</p>
    
    <script type="text/javascript">
    let test_dom2 = document.getElementsByName('test_dom2');
    console.log("test_dom2 -> " + test_dom2);
    </script>
    
    </body>
    </html>
    

    また、HTMLソース内のname属性は、そのソース内で一意である必要はなく、重複して構成されていても問題はありません。

    上記HTMLにブラウザでアクセスすると、javascriptが実行され、コンソールログにはNodeListオブジェクトが出力されます。
    NodeListオブジェクトは一見すると配列のように見えますが、配列オブジェクトとは異なります。Arrayオブジェクトではないとも言えます。
    NodeListオブジェクトでは、itemメソッドとlengthプロパティが使えます。

    itemメソッドはNodeListオブジェクトのインデックスとして作用し、lengthプロパティは、取得できたオブジェクトの個数を返します。

    要素の選択

    Posted コメントするカテゴリー: javascript

    要素の選択

    javascriptからHTML内のドキュメント要素を操作する方法を整理します。
    要素を操作するには、要素を取得してから操作をします。

    この取得する方法はプレーンなjavascriptでは次の方法があります。

    ①id属性で選択
    ②name属性で選択
    ③tag名で選択
    ④cssクラスで選択
    ⑤cssセレクタで選択

    またjavascriptで作られたライブラリ(jquery等)や、react、vue、Angular、その他のjavascriptで作られているフレームワークは、それぞれで書き方が変わってきます。

    ここでは上記の①~⑤について、試してみます。

    id属性で取得

    HTML内のソースがHTMLElement要素として書かれていて、
    タグ内にid属性を持つ場合、javascriptでは次のように要素を取得できます。

    例えば、HTMLソースが以下の場合の要素「test_youso1」を取得してみます。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>テストHTML</title>
    
    </head>
    <body>
     
    <h3>タイトル</h3>
    <p id="test_dom1">テスト要素1</p>
    
    <script type="text/javascript">
    let test_dom1 = document.getElementById('test_dom1');
    console.log("test_dom1 -> " + test_dom1);
    
    //取得した要素の文字色を青く設定
    test_dom1.style.color = 'blue';
    </script>
    
    </body>
    </html>
    

    javascriptでは、次のように要素を取得します。

    let test_dom1 = document.getElementById('test_dom1');
    console.log("test_dom1 -> " + test_dom1);
    
    //取得した要素の文字色を青く設定
    test_dom1.style.color = 'blue';
    

    また、HTMLソース内のid要素は、そのソース内で一意であることが前提になります。

    上記のHTMLを保存し、ブラウザでアクセスすると、
    「タイトル」と「テスト要素1」 (青文字に変更された文字列)が表示されます。

    ノードについて

    Posted コメントするカテゴリー: javascript

    ノードについて

    前回の投稿でDocument内の各要素をノードで表記しました。

    このノードはjavascriptの言語仕様で言うNodeオブジェクトになります。

    Nodeオブジェクトということは、プロパティやメソッドを持つので、
    プロパティとメソッドがそれぞれどのようになっているのか、調べてみます。

    前回投稿した下記のHTMLを元にノードを考えてみます。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>propansystem開発ブログ</title>
    </head>
    <body>
     
    <h1>ブログタイトル</h1>
    <p>ブログ本文内の<b>太字</b>テキストです</p>
     
    </body>
    </html>
    

    まずドキュメント全体を指し示すのがDocumentノードといい、HTML要素はElementノード、テキストを表すものはTextノードです。

    Document、Element、Textノードは、Nodeオブジェクトの派生ノードで、DocumentとElementはDOM操作において重要なDOMクラスと言えます。

    また、Nodeオブジェクトの派生型については、大きく分けてDocument型とElement型に分かれ、
    Element型は、HTMLElementオブジェクトとして画面上のHTMLタグ(ドキュメント)を表します。
    Document型は、ブラウザに読み込まれたウェブページを表します(DOMツリーのエントリポイントを表します)

    HTMLElement型について

    HTMLElementには多数の派生型があり、一般的にはHTMLタグの要素を示します。
    派生型ごとにjavascriptのプロパティが定義され、指定した要素と同じ値が格納されます。

    ノードの種類については、上で書いた
    Document、DocumentFragment、Element、の他にCaracterData(Text、Comment)、Attr等があります。

    各ノードは「属性」を持ち、子ノードは親ノードの属性を継承して参照することができます。
    Elementノードは名前/値のペアで扱えるメソッドが定義されています。

    DOMについて

    Posted コメントするカテゴリー: javascript

    DOMについて

    DOM(Document Object Model)について、掘りげて調べてみます。

    DOMはHTML、XMLのドキュメント内部のコンテンツを表現するものと言えます。

    ブラウザに表示される画面のHTML構造を見てみると、ツリー構造になっていて、
    それぞれがタグで書かれています。

    タグについては、開始タグと終了タグで内容を囲み(一部開始/終了の意味を持たない単一のタグもあります)、
    そのタグ内に内容を意味するテキストを記載します。

    また、タグの中には要素を表すノード、テキスト文字を表すノードが含まれます。

    このブログを表現しているHTMLタグを抜粋し、コンテンツ(内容)部分を全て簡易的に書いたものが下記のタグになります。

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <title>propansystem開発ブログ</title>
    </head>
    <body>
    
    <h1>ブログタイトル</h1>
    <p>ブログ本文内の<b>太字</b>テキストです</p>
    
    </body>
    </html>
    

    このHTMLの例でも、ツリー構造ととらえることが可能です。

    ツリー構造は、一番上をDocumentとして、その下にhtml、そのさらに下にhead、bodyがあり、
    bodyの下にh1、pタグがある。
    という構造をしています。

    また、それぞれのタグにはノードと呼ぶつながりがあります。
    さらに、タグには上下関係があり、一つ上のツリー(のタグ)を親ノードと呼びます。
    そのノートの直下にあるタグは子ノードと呼ばれます。

    あるノードより下にあるノードのさらに下にあるノードは子孫ノードと呼びます。
    あるノードより上にあるノードのさらに上にあるノードは祖先ノードと呼びます。

    ノードについては、さらにnodeオブジェクトとしての考え方があるので、
    nodeオブジェクトとプロパティ、メソッドについて、さらに深く調べてみます。