JavaScript 再入門(その27) ドキュメントのHTML属性の操作

ドキュメントのHTML属性の操作

HTML 属性とは、タグに付けられた補足情報です。
id / class / name 等は属性 (Attribute) と呼びます。

<タグ 属性1="属性値1" 属性2="属性値2 属性値3">

HTML 属性へのアクセスには、標準属性についてはプロパティが用意されています。
非標準属性へのアクセスは、getAttribute / setAttribute を利用します。


属性の取得

<a href="https://sakura-system.com" id="a1" class="atag-class abc-class" name="atag-anchor" target="_BLANK" something="hogehoge" >リンク</a>

この a タグの属性をプロパティで取得してみましょう。

	const a = document.querySelector('a') ;			// aタグの要素を取得
	console.log( a.href ) ;							// https://sakura-system.com
	console.log( a.id ) ;							// a1
	console.log( a.className ) ;					// atag-class abc-class
	console.log( a.name ) ;							// atag-anchor
	console.log( a.target ) ;						// _BLANK
	console.log( a.something ) ;					// undefined *** (非標準属性 something)
	console.log( a.getAttribute('something') );		// hogehoge (非標準属性 something)

属性 something は非標準属性なので、プロパティではアクセスできませんので、undefined が返ります。
しかし、非標準属性は getAttribute メソッドにてアクセスすることができます。

class については注意が必要です。class 属性のプロパティは、className になります。


属性の設定

標準属性は、属性プロパティに値を代入することで、属性値を変更することもできます。
非標準属性は setAttribute メソッドにて設定することができます。

	const a = document.querySelector('a') ;			// aタグの要素を取得
	a.id = 'a2' ;									// id 属性の設定
	a.setAttribute( 'something' , 'hoge' ) ;		// something 属性の設定 (非標準属性)
	console.log( a.id ) ;							// a2
	console.log( a.getAttribute('something') );		// hoge (非標準属性 something)

標準属性については、プロパティを使用することが推奨されています。

MDN element.setAttribute のドキュメントに以下の記述があります。

setAttribute() を使ってある属性、XUL や HTML の特別な値、および HTML の選択領域の変更は、属性がデフォルト値を特定している場合に一貫性の無い動作となります。現在の値にアクセスしたり、変更したりするにはプロパティを使用すべきです。具体例として、 elt .setAttribute(‘value’, val ) の代わりに elt .value を使用します。

指定された要素の属性の値を設定します。属性が既に存在する場合は値が更新され、そうでない場合は指定された名前と値で新しい属性が追加されます。
developer.mozilla.org

属性の削除

属性の削除は、 removeAttribute を使用します。
プロパティや setAttribute を使用して null に設定するのではなく、removeAttribute を使用します。

	const a = document.querySelector('a') ;			// aタグの要素を取得
	a.removeAttribute( 'id' ) ;
	a.removeAttribute( 'something' ) ;
// <a href="https://sakura-system.com" class="atag-class abc-class" name="atag-anchor" target="_BLANK">リンク</a>

属性の切替

属性の切替は、toggleAttribute を使用します。
toggleAttribute は、属性が存在する場合は削除し、存在しない場合は追加します。

<html>
	<head>
		<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
		<style type="text/css">
			main { text-align: center; }
		</style>
	</head>
	<body>
		<main id="contents_id" class="contents_class">
			<p id="p_id" class="p_class">JavaScript 再入門</p>
			<div>
				<input id="inp" type="text"></input>
				<button id="btn" type="button">ボタン</button>
			</div>
		</main>
	</body>
<script>
	const btn = document.querySelector('#btn') ;	// ボタン要素の取得
	const inp = document.querySelector('#inp') ;	// インプット要素を取得
	btn.addEventListener('click', () => {
		inp.toggleAttribute( 'disabled' ) ;			// ボタンをクリックする度にinputタグが入力可/不可と切り替わる
	}) ;
</script>
</html>

ボタンをクリックすると、インプットエリアの入力可/入力不可と切り替わります。
input タグの disabled 属性 を切り替えることにより、入力可/入力不可と切り替えています。


スタイル属性の変更取得

HTML インラインの style 属性を変更することにより、要素のスタイルを変更することができます。

要素.style.プロパティ名 = '値' 
<html>
	<head>
		<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
		<style type="text/css">
			main { text-align: center; }
		</style>
	</head>
	<body>
		<main id="contents_id" class="contents_class">
			<p id="p_id" class="p_class">JavaScript 再入門</p>
			<div>
				<p id="p">色が変わるよ</p>
				<button id="btn" type="button">ボタン</button>
			</div>
		</main>
	</body>
<script>
	const btn = document.querySelector('#btn') ;	// ボタン要素の取得
	const p = document.querySelector('#p') ;		// 文章要素を取得
	btn.addEventListener('click', () => {
		// ボタンをクリックすると文章の文字色がランダムに変わる
		p.style.color = 'rgb(' + getRandomInt(255) + ',' + getRandomInt(255) + ',' + getRandomInt(255) + ')' ;
		// ボタンをクリックすると文章の背景色がランダムに変わる
		p.style.backgroundColor = 'rgb(' + getRandomInt(255) + ',' + getRandomInt(255) + ',' + getRandomInt(255) + ')' ;
	}) ;
	// ランダムな整数を求める
	const getRandomInt = (max) => {
		max = Math.floor(max);
		return Math.floor(Math.random() * (max));
	}
</script>
</html>

ボタンをクリックすると、文書の文字色と背景色がランダムに変わります。

文章の p タグの style属性が変わったからです。

<p id="p">色が変わるよ</p>
       ↓
<p id="p" style="color: rgb(25, 19, 141); background-color: rgb(173, 161, 214);">色が変わるよ</p>

データ属性の使用

data- で始まる属性をデータ属性と呼びます。
データ属性は要素に追加の情報を格納することができます。

<p id="p" data-storage-stock="13" data-factory-stock="5"></p>

データ属性は getAttribute でも取得できますが、dataset プロパティを使うことで容易にアクセスすることができます。
dataset オブジェクトを通して data 属性を取得するには、属性名の data- より後の部分を使用して取得します (なお、ダッシュは camelCase に変換されます)。

const p = document.querySelector('#p') ;
console.log( p.dataset.storageStock ) ;		// 13

CSS の属性セレクタからスタイルを設定することもできます。

p[data-storage-stock="0"] { color:orange ; }
p[data-storage-stock="0"][data-factory-stock="0"] { color:red ; }
CSS セレクタ備忘録
CSS セレクタ備忘録 最近年齢のせいか、いざ使おうとすると「なんだったっけな~」ってなるスタイルシートのセレクタ。 そこで、CSS セレクタをまとめて、備忘録…
sakura-system.com

データ属性を使って簡単な、商品の在庫を管理するスクリプトを作成してみます。

スクリプト仕様

  • 商品の初期在庫は、倉庫に8個、工場に3個の合計11個あります。
  • 「出荷」と「返品」「完成」の3つのボタンを作成
  • 「出荷」ボタンをクリックすると、商品の在庫を減らします。
    商品の出荷は、倉庫から優先して出荷します。
  • 「返品」ボタンをクリックすると、商品の在庫を増やします。
    商品の返品先は倉庫になります。
  • 「完成」ボタンをクリックすると、工場の在庫を増やします。
    工場の在庫は5個まで、5個以上は倉庫に在庫します。
  • 在庫数は「在庫数 n 個 (倉庫:n 工場:n)」と緑色の文字で表示します
  • 倉庫の在庫がなくなると在庫数表示の文字をオレンジ色にします。
  • 倉庫と工場の両方の在庫がなくなると、在庫表示の文字を赤色にします。
<html>
	<head>
		<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
		<style type="text/css">
			main { text-align: center; }
			button { margin-right: 0.5em; }
			.subbtn { margin: 0 2.0em ; }
			p { color:green; }
			p[data-storage-stock="0"] { color:orange ; }
			p[data-storage-stock="0"][data-factory-stock="0"] { color:red ; }
		</style>
	</head>
	<body>
		<main id="contents_id" class="contents_class">
			<h3 id="p_id" class="p_class">JavaScript 再入門</h3>
			<div>
				<p id="p" data-storage-stock="8" data-factory-stock="3"></p>	<!-- data属性で在庫数を持ちます -->
				<button id="btn" type="button">出荷</button>
				<span class="subbtn">
					<button id="btn2" type="button">返品</button>
					<button id="btn3" type="button">完成</button>
				</span>
			</div>
		</main>
	</body>
<script>
	const btn = document.querySelector('#btn') ;	// 出荷ボタン要素の取得
	const btn2 = document.querySelector('#btn2') ;	// 返品ボタン要素の取得
	const btn3 = document.querySelector('#btn3') ;	// 完成ボタン要素の取得
	const p = document.querySelector('#p') ;		// 文章要素を取得
	// 全在庫数を表示する関数
	const zaiko = () => {
		let st = +p.dataset.storageStock ;			// 倉庫の在庫数を取得
		let fc = +p.dataset.factoryStock ;			// 工場の在庫数を取得
		let sum = st + fc ;							// 全在庫数を求める
		p.innerText = '在庫数:' + sum + ' 個 (倉庫:' + st + ' 工場:' + fc + ')' ;		// 全在庫数を表示
	}
	zaiko() ;										// 在庫数の初期表示
	// 出荷ボタンクリック
	btn.addEventListener('click', () => {
		let st = +p.dataset.storageStock ;			// 倉庫の在庫数を取得
		let fc = +p.dataset.factoryStock ;			// 工場の在庫数を取得
		if ( st > 0 ) {
			--st ;									// 倉庫の在庫数を減らす
		} else if ( fc > 0 ) {
			--fc ;									// 工場の在庫数を減らす
		}
		p.dataset.storageStock = '' + st ;			// 倉庫の在庫数を設定
		p.dataset.factoryStock = '' + fc ;			// 工場の在庫数を設定
		zaiko() ;									// 在庫数の表示
	}) ;
	// 返品ボタンクリック
	btn2.addEventListener('click', () => {
		let val = +p.dataset.storageStock ;			// 倉庫の在庫数を取得
		++val ;										// 倉庫の在庫数を増やす
		p.dataset.storageStock = '' + val ;			// 倉庫の在庫数を設定
		zaiko() ;									// 在庫数の表示
	}) ;
	// 完成ボタンクリック
	btn3.addEventListener('click', () => {
		let val = +p.dataset.factoryStock ;			// 工場の在庫数を取得
		if ( val >= 5 ) {
			val = +p.dataset.storageStock ;			// 倉庫の在庫数を取得
			++val ;									// 倉庫の在庫数を増やす
			p.dataset.storageStock = '' + val ;		// 倉庫の在庫数を設定
		} else {
			++val ;									// 工場の在庫数を増やす
			p.dataset.factoryStock = '' + val ;		// 工場の在庫数を設定
		}
		zaiko() ;									// 在庫数の表示
	}) ;
</script>
</html>

出荷ボタンをクリックすると、在庫数が減って。
データ属性も減っていきます。

<p id="p" data-storage-stock="5" data-factory-stock="3">在庫数:8 個</p>

今回は、データ属性の働きを理解してもらうために、あまり使わないであろう例題でしたが、この他にもテーブルタグの行と列や、インプットタグの入力状態などアイデア次第で利用方法は広がると思います。

参考リンク

ウェブ開発を学ぶ > HTML の学習: ガイドとチュートリアル > 一般的な問題解決に HTML を使う > データ属性の使用
開発者向けのウェブ技術 > Web API > Element > Element.attributes
開発者向けのウェブ技術 > Web API > Element > Element.getAttribute()
開発者向けのウェブ技術 > Web API > Element > element.setAttribute
開発者向けのウェブ技術 > Web API > Element > Element.removeAttribute()
開発者向けのウェブ技術 > Web API > Element > Element.toggleAttribute()