Javascriptが、HTMLをコントロールする処理を
Dom操作と言います。
Dom操作は、HTMLのタグを書き換えたり、追加したり削除することで、動的なWebページをコントロールすることができます。
また、CSSの値を直接動的に変更することで、ダイナミックな表現が可能になります。
そんなDom操作の基本を覚えて、いい感じのWebサイトを作れるようになりましょう。
Javascript学習 : Dom操作編
- ページ情報 : window , document , location , navigator
- 要素(エレメント)アクセス方法 : getElement... , querySelector
- テキストの書き換え
- class処理
- nameとidについて
- attribute処理
- style処理
- form処理
- 要素の追加と削除
ページ情報 : window , document , location , navigator
インターネットブラウザのあらゆる情報を取得するために、それぞれの情報がどこに格納されているか理解しておきましょう。
window
全ての変数(定数)の親にあたるのが
windowです。
基本編の「
グローバルデータとローカルデータ : window」の箇所に書かれています。
document
documentは、HTMLのDom構造そのものです。
構造に関係
document.bodyは、dobyタグと同じ意味になり、他にもページ内の構造に依存するデータがたくさん格納されています。
document.body
- bodyタグ
document.head
- headタグ
document.links
- aタグなどのリンク要素(エレメント)を一覧で取得できます。
document.forms
- ページ内のformタグの一覧を取得でき、それぞれのform項目が格納されています。
document.images
- ページ内のimgタグの一覧が格納されています。
document.fonts
- ページ内で使われているフォントの一覧が格納されています。
document.scripts
- scriptタグの一覧が格納されています。
document.styleSheets
- linkタグやstyleタグの一覧が格納されています。
document.timeline
- ページを表示してからの秒数(msec)が確認できます。
document.cookie
- Cookieの値が格納されています。
他にも色々な情報が格納されているので、以下のリンク見てみてください。
[Javascript] documentから得られる情報
location
locationは、表示しているページのURLに関する情報が格納されています。
document.href
- ブラウザのアドレス欄に書かれているURL(URI)が全て取得できます。
> https://example.com:8080/user_page/index.html?id=100&name=taro#user
document.hash
- ハッシュ値が取得できます。
> #user
document.search
- クエリ情報が取得できます。
> ?id=100&name=taro
document.hostname
- ドメイン
> example.com
document.port
- ポート
> 8080
document.protocol
- プロトコル
> https:
document.pathname
- 階層 + ファイル名
> /user_page/index.html
document.origin
- プロトコル + ホスト + ポート
> https://example.com:8080
navigator
navigatorは、インターネットブラウザのアプリ情報が格納されています。
navigator.userAgent
- ユーザーエージェント
あなたのユーザーエージェント
navigator.language
- ユーザー環境の言語が表示されます。
あなたの言語
navigator.onLine
- 現在のブラウザがオンランの場合は、trueを返します。
あなたのオンライン状態
navigator.vendor
- 使っているブラウザのベンダー名が表示されます。
ベンダー情報
navigator.appVersion
- 使っているブラウザのバージョンが表示されます。
ブラウザバージョン
navigator.platform
- プラットフォーム(OSなど)が表示されます。
プラットフォーム
navigator.vibrate(バイブパターン)
- 端末が対応している場合、振動させることができます。
バイブ
リファレンスサイトにも詳しく書かれています。
MDN web docs
要素(エレメント)アクセス方法 : getElement... , querySelector
Dom操作をするために、それぞれの要素(エレメント)にアクセスする方法がいくつかあります。
一般的な要素取得(検索)方法
# idで検索
const elm = document.getElementById("ID")
# タグで検索
const elms = document.getElementsByTagName("タグ")
# クラスで検索
const elms = document.getElementsByClassName("クラス")
# nameで検索
const elms = document.getElementsByName("name値")
# cssセレクターで検索(1個取得)
const elm = document.querySelector("セレクター")
# cssセレクターで検索(複数選択)
const elms = document.querySelectorAll("セレクター")
getElement系の検索方法は、id検索のみ単体取得で、それ以外は複数という事に注意してください。
これは、id値はページ内でユニークでないといけないという、HTMLのルールで、idは単体しか返さないようになっています。
また、querySelector()も単体取得の場合は、一番最初に現れる(セレクターがマッチする)要素を取得するので、複数の場合は、querySelectorAll()を使うようにしましょう。
複数取得した結果は配列として処理することができます。
要素to要素検索
任意の要素以下にある、要素はdocument.の箇所を、それ以前に取得した要素にすることで下方検索することができます。
const elm = document.getElementById("article")
const links = elm.querySelectorAll("a.other-site-link")
上記は、ブログ記事内の外部リンクのみを取得するサンプルプログラムです。
テキストの書き換え
要素が抽出(検索)できるようになったら、その要素の中に書かれているテキストやHTMLを書き換えてみましょう。
サンプルHTML
この章では、次のHTMLを使ってサンプルプログラムを紹介します。
<article>
<h1>ブログリスト</h1>
<ul class='blog-lists'>
<li class='blog-item'>
<a href='http://example.com/1.html'>記事</a>
</li>
<li class='blog-item'>
<a href='http://example.com/2.html'>記事</a>
</li>
<li class='blog-item'>
<a href='http://example.com/3.html'>記事</a>
</li>
</ul>
</article>
textContent : テキストの書き換え
要素内のテキストの書き換えをしたい場合は、textContent命令を使います。
# 要素の取得
const blog_items = document.querySelectorAll("article .blog-lists .blog-item")
# 記事の先頭に番号をつける
for(const i=0; i<blog_items.length; i++){
const item = blog_items[i]
const num = i+1
item.textContent = `${num}. ${item.textContent}`
}
innerHTMLとinsertAdjacentHTML : 要素内のHTMLタグを書き換え
HTMLタグの中にHTMLタグを書き込む場合は、innerHTMLで処理します。
textContentでHTMLタグを書いても、そのまま文字として表示されるので、HTMLとして解釈するためには、この命令を使う必要があります。
# ブログ記事リストの親要素を取得
const blog_lists = document.querySelector('article .blog_lists')
# ブログの最後に新しい要素を追加する(innerHTMLの場合)
blog_lists.innerHTML += "<li class='blog-item'><a href='http://example.com/new.html'>新しい記事</a></li>"
# ブログの最後に新しい要素を追加する(insertAdjacentHTMLの場合)
const html = "<li class='blog-item'><a href='http://example.com/new.html'>新しい記事</a></li>"
blog_lists.insertAdjacentHTML("beforeend" , html)
insertAdjacentHTMLのbeforeendは、最初に指定した親要素の中の後ろ側にHTMLを挿入する処理です。
親要素の内側の上部に追加する場合は、"afterbegin"、
親要素の外側の直前に挿入する場合は、"beforebegin"、
親要素の外側の次に挿入する場合は、"afterend"、
.blog-lists要素からみたinsertAdjacentHTMLの位置早見表
<article>
{{ beforebegin }}
<ul class='blog-lists'>
{{ afterbegin }}
<li>..</li>
{{ beforeend }}
</ul>
{{ afterend }}
</article>
createElementとappendChild新しい要素を作り出す
テキストとしてHTMLタグを書く場合、テキストにミスがあると、エラーに繋がる可能性があるので、要素をタグテキストではなく、要素オブジェクトとして扱うこともできます。
しかし、1つのタグずつしか作れないので、数が多い場合は、for文などで処理できると効率的です。
# ブログ記事リストの親要素を取得
const blog_lists = document.querySelector('article .blog_lists')
# ブログitemを作成
const new_elm = document.createElement('li')
new_elm.className = 'blog-item'
new_elm.textContent = 'new 記事'
# 親要素への追加処理
blog_lists.appendChild(new_elm)
class処理
ここで言うクラス(class)は、HTMLタグ属性のクラスです。
クラス属性は、CSSとの連携や、Javascriptにおける要素へのアクセスをより効率化させる設定です。
親子の階層や、兄弟構成のグループを意識して、ページ内でクラス名を整理する必要があり、
規模が大きくなるほどその整理が重要になります。
効率的なクラス名の書き方
<div class='news'>
<ul class='items'>
<li class='item'>
<a class='link' href='https://example.com'>お知らせリンク 1</a>
</li>
</ul>
</div>
class名を見ただけで、selectorでアクセスしやすいようにするのがポイントです。
単数と複数を意識したクラス名にすると、querySelector()とquerySelectorAll()の使い分けに便利です。
また、個人的にはHTMLタグに対して、決まったクラス名を付けるようにすると、プログラミング効率がはかどります。
# Example
- ul,ol : items
- li : item
- table : datas
- tr : data
Javascriptでクラス名のセットの仕方
classは複数の設定方法があります。
・特定の要素(id="sample")にsampleというクラス名を付けるサンプルは次の通りです。
# クラス名をセットする
document.getElementById('sample').className = 'sample'
※class名をセットするときは、.classではなく、.classNameを使う事を間違えないようにしましょう。
# 属性としてセットする
document.getElementById('sample').setAttribute('class' , 'sample')
別の属性などもセットするときは、こちらの書き方で統一すると、整理されたプログラミングに見えるようになるでしょう。
# 事前に登録されたクラスがある場合
<div class='test' id='sample'></div>
# 追加
document.getElementById('sample').classList.add('sample')
実行結果> <div class='test sample' id='sample'></div>
# 削除
document.getElementById('sample').classList.remove('test')
実行結果> <div class='sample' id='sample'></div>
# 入れ替え
document.getElementById('sample').classList.toggle('sample')
実行結果> <div class='sample' id='sample'></div>
# 検索(クラス名が使われているか確認)
document.getElementById('sample').classList.contains('sample')
実行結果> true
複数使う事があるclass名は、classListを使って操作をした方がトラブルは無いはずです。
nameとidについて
HTMLの不思議な挙動のひとつに、name値とID値とハッシュ値があります。
ハッシュリンクはidとnameのどっちに有効?
urlに#をつけてその後ろの値でページ内リンクをする仕様で、id値とname値のどちらでも適用されます。
ただし、条件として、name値はaタグとセットで使われている事と、同じid値、name値がある場合は、id値のほうが優先されるという仕様になっているようです。
aタグのname値は、古い書き方で、id値の方が今時の書き方と考えても良いかもしれません。
aタグにnameをつけないのがいいかもしれませんね。
サンプルコード
<ul>
<li><a name='name-1'>1<a></li>
<li><a name='name-2'>2<a></li>
<li><a name='name-3'>3<a></li>
<li><a name='name-4'>4<a></li>
<li><a name='name-5'>5<a></li>
<li><a name='name-6'>6<a></li>
<li><a name='name-7'>7<a></li>
<li id='name-5'><a name='name-8'>8<a></li>
<li><a name='name-9'>9<a></li>
<li><a name='name-10'>10<a></li>
</ul>
<style>
li{
border:1px solid red;
height:50vh;
}
</style>
inputタグのname値はid値?
formタグ内に書かれたinputのname値とid値は、同じ扱いをされる場合があります。
<form>
<input type='text' id='test'/>
<input type='text' name='test'/>
<input type='text' name='sample'/>
</form>
<script>
const res = document.forms[0].test
console.log(res)
</script>
上記のサンプルコードでは、inputタグにid='test'とname='test'と2つのinputタグがあり、
const res = document.forms[0].test
form取得をする方式で、testという値を取得すると、id='test'のinput要素も一緒に取得されてしまいます。
このため、
inputタグにおいては、id値とname値は同じにするという、裏ルールが存在します。
結構知らない人が多いので、こうしたトラブルの元はちゃんと理解しておきましょう。
attribute処理
attribute(属性)は、HTMLというマークアップ言語の特性で利用価値が高いモノです。
idやclass以外でも、それぞれのタグの種類に応じた属性や、それに伴う機能などを覚えるために、HTMLのタグ学習はリファレンスサイトで深いところまで見るようにしましょう。
HTMLリファレンスサイト
MDN Web docs : HTML属性リファレンス
ここでは、属性の細かな説明はしません。
Javascriptを使って属性をコントロールする方法を2つ紹介します。
既に設置されているdivタグに対して、id属性でsampleを設置するサンプルです。
属性設置方法、その1
const elm = document.querySelector('div.sample')
elm.id = 'sample'
.(ドット)で属性をそのまま書けるので、非常にスッキリとしたコードになります。
属性設置方法、その2
const elm = document.querySelector('div.sample')
elm.setAttribute('id' , 'sample')
setAttributeは、属性を確実にセットできます。
data属性について
Javascriptで、HTMLタグをコントロールするのに非常に便利に使えるdata属性というのを覚えておきましょう。
通常のHTML属性は、リファレンスサイトに書いてある属性値しか使うことができません。
※使えたとしても非推奨の使い方です。
しかし、汎用性を持つために、data属性という任意属性値が許容されています。
data-sample-id="文字列"
このように、data-の後ろに、好きな文字を書くことができます。
これは、次のように、cssに書いて連動できます。
div[data-sample-id="1"]{
※css記述
}
そして、設置は、setAttributeで行えます。
style処理
HTMLタグのスタイル(style)属性は、StyleSheetの記述がそのままできます。
※beforeやafterなどの疑似要素や、アニメーションなどの記述はできません。
cssで書いたどのセレクタよりも優先順位が強くなるので、Javascriptでstyleタグでの扱いは既存のCSSの構造を意識して行う必要もあります。
※最も優先順位が高いのは、important記述になります。
HTMLで直接しているstyle属性の中身もそれぞれ変更したり削除することも可能なので、使い方を覚えると、見た目がダイナミックなホームページも作るのが楽になるでしょう。
styleの書き方
エレメントに対して、style属性がセットできますが、その下の階層にproperty(プロパティ)というcssのプロパティと同じもの(キャメルケース記述になります)がセットできます。
# 直接記述
const elm = document.querySelector("div.sample")
// マージンセット
elm.style.margin = "2px 4px 6px 8px"
// 背景色の変更
elm.style.backgroundColor = "red!important"
構文は次のとおりです。
要素 . style . プロパティ名 = StyleSheetの値
注意点としては、プロパティ名が、キャメルケース記述になるので、-(ハイフン)で繋げているプロパティは、大文字に置き換える必要があります。
background-color → backgroundColor
# setProperty記述
const elm = document.querySelector("div.sample")
// マージンセット
elm.style.setProperty("margin" , "2px 4px 6px 8px" , null)
// 背景色の変更
elm.style.setProperty("backgroundColor", "red" , "important")
setPropertyの構文
要素 . style . setProperty("プロパティ名" , "StyleSheetの値" , "優先順位(important)");
こちらの注意点は、importantがない場合は、この引数を書かなくてもいいんですが、以前とあるブラウザで、この値が無い事でエラーが出たことがあったので、自分は第三引数もnullで書くように心がけてます。
あと、先程の直接記述と違って、setProperty記述の場合は、プロパティ名が、キャメルケースではなく、ケバブケース(ハイフン繋ぎ)で書きます。
より元のStyleSheetに近い形で書けるので、書き文字数は多いですが、こちらの方がわかりやすいかもしれませんね。
form処理
入力フォームは、特殊なアプローチで処理をします。
HTMLの構造と合わせて、Javascriptでの扱いができるようになると、EFO(EntryFormOptimyzation)が難なくできるようになります。
formタグへのアクセス方法
入力項目の大元であるformタグへのアクセスは、次の様に行います。
document.forms.フォーム名(name値または、配列順番)
form name="form1"というタグで設置されていたら、次のように書きます。
const form = document.forms.form1
ページ内に検索フォームなどが設置されていると、複数のformタグが存在しているので、次のように配列番号でもアクセスできます。
const form = document.forms[1]
入力項目へのアクセス
上記でformタグにアクセスした、form変数を使って、それぞれの項目には、次のようにアクセスします。
form.項目名(inputやselectタグなど)
<input type="text" name="username">
const username = form.username.value
input項目のvalueなどの属性の値を取得したり、書き換えたりできるようになります。
同じname値に注意
radioボタンなどのように、name値が同じ項目がある場合は、formからの項目アクセスで、複数の要素が取得されます。
<form name="form1">
<input type="radio" name="gender" value="male"/>
<input type="radio" name="gender" value="female"/>
<input type="radio" name="gender" value="other"/>
</form>
上記の項目を取得すると、3つの項目が取得されます。
それぞれ、配列として処理をしていく必要があります。
const radios = document.forms.form1.gender
console.log(radios[0].value)
ちなみに、どれが選択されているかは、selected属性を調べる必要がありますが、選択されている値を取得するのは、次のようにできます。
const radios = document.forms.form1.gender
console.log(radios.value)
要素の追加と削除
Dom構造のappendChild()と、insertAdjacentHTML()だけだと、追加しかできないので、削除やその他修正をする処理も覚えましょう。
要素の削除
const elm = document.querySelector("div.sample")
elm.parentNode.removeChild(elm)
削除する要素の親要素.removeChild(削除する要素)
特定の要素の手前に要素を追加
appendChild()は、親要素の中の一番うしろに追加されてしまうので、任意の要素の手前に兄弟要素として、追加するには、次のようにします。
const new_elm = document.createElement("div")
const elm = document.querySelector("div.sample")
elm.parentNode.insertBefore(new_elm , elm)
追加する要素の親要素.insertBefore( 追加する要素 , 基準になる要素※この手前に追加される )
既存のelementをappendChildする注意点
次のような、要素がある場合、要素1を、親要素にappendChild()してみると、
新しく要素が追加されるのではなく、元あった要素が、最後に移動します。
appendChild()は、追加ではなく、要素の移動と考えたほうがいいですね。
<ul class='elements'>
<li class="item-1">要素1</li>
<li class="item-2">要素2</li>
<li class="item-3">要素3</li>
</ul>
const parent = document.querySelector('.elements')
const item_1 = parent.querySelector('.item-1')
parent.appendChild(item_1)
実行結果
・要素2
・要素3
・要素1
0 件のコメント:
コメントを投稿