質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

3回答

5132閲覧

Js特定の要素にフォーカス移動する

ryooma

総合スコア3

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2021/02/28 00:16

編集2021/02/28 10:07

jsでキーを押す度に特定の要素にフォーカス移動させたい

以下の方法で試した結果、最初の「id="txt1"」を飛ばして2個目の「id="txt1"」に飛んでくれましたが、引き続きエンターキーを押しても3、個目4個目の「id="txt1"」に飛んでくれません。

js

1function keydown(e){ 2 if (e.keyCode === 13){ 3var obj = document.getElementById("txt1").nextElementSibling.focus(); 4 5 } 6}; 7 8window.onkeydown = keydown;

html

1<body> 2 <input type="text" /> 3 <input type="checkbox" /> 4 <input type="text" /> 5 <input type="radio" /> 6 7<input type="text" id="txt1" value="1234567890"> 8<input type="text" id="txt1" value="1234567890"> 9<input type="text" id="txt2" value="1234567890"> 10 11<input type="text" class="LC20lb" value="1234567890"> 12<input type="text" class="LC20lb" value="1234567890"> 13 14<a href=""><h3 class="LC20lb"><span>BELIEVE</span></h3></a> 15<a href=""><h3 class="LC20lb"><span>BELIEVE</span></h3></a> 16<a href=""><h3 id="txt1"><span>BELIEVE</span></h3></a> 17<a href=""><h3 class="LC20lb"><span>BELIEVE</span></h3></a> 18<a href=""><h3 class="LC20lb"><span>BELIEVE</span></h3></a> 19</body>

Classの要素を獲得して移動して欲しかったのですが

document.getElementsByClassName

では反応してくれず、ID獲得にしています。
Class要素でも獲得してフォーカス移動はできるのでしょうか。

なお、先ほど「引き続きエンターキーを押しても」と書きましたが。

var obj = document.getElementById("txt1").nextElementSibling.focus();

を消して

js

1var obj = document.activeElement; 2obj.nextElementSibling.focus();

にしたところ、どんどん飛んでくれましたが「特定の要素」ではなく「全要素」に飛んでくれました。

1番参考にしたサイトのUrlをなくしてしまいました。。。
次に参考にしてたサイトです
参考2サイト

もしかしたらIF文だけでは実現できないことをしようとしている。
とかでなければいいのですが。

補足・修正がありましたら追記します。

追記:どうしても達成したいこと

html

1<a href=""><h3 class="LC20lb"><span>BELIEVE</span></h3></a> 2<a href=""><h3 class="LC20lb"><span>BELIEVE</span></h3></a> 3 4<a href=""><h3 id="txt1"><span>BELIEVE</span></h3></a> 5<a href=""><h3 class="LC20lb"><span>BELIEVE</span></h3></a> 6 7<input type="text" id="txt2" value="1234567890"> 8<a href=""><h3 class="LC20lb"><span>BELIEVE</span></h3></a>

上記の要素の中からtxt1やtxt2などにフォーカスせずに
Jsでクラス名LC20lbを指定して
キーを押す旅に連続で飛べるようにしたい。

試してみたこと

js

1function keydown(e){ 2 if (e.keyCode === 13){ 3 4var = obj document.querySelectorAll ('.LC20lb')[1].parentNode; 5obj.nextElementSibling.focus(); 6 7 } 8}; 9 10window.onkeydown = keydown;

やはりとんでくれません。
何が間違っているのでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

window.onkeydown

JavaScript

1window.onkeydown = keydown;

window.onkeydown はどこで [Enter] キーを押下しても反応します。
考えられる対策は二通り。

  • keydownイベントハンドラ処理で event.target を読んで <input type="text"> だった場合にのみ処理されるように変更
  • <input type="text"> にkeydownイベントハンドラを指定する

次のfocus対象ノードを検出する

JavaScript

1var obj = document.activeElement; 2obj.nextElementSibling.focus();

にしたところ、どんどん飛んでくれましたが「特定の要素」ではなく「全要素」に飛んでくれました。

二通りの解決手段。

  • nextElementSibling を while 文で <input type="text"> がくるまで繰り返す
  • 親ノードから querySelectorAll()input:focus~input[type=text]

実装例

HTML

1<form id="hoge" action="test.php"> 2 <input type="text" name="a" /><br> 3 <input type="checkbox" name="c1" /><br> 4 <input type="text" name="b" /><br> 5 <input type="checkbox" name="c2" /><br> 6 <input type="text" name="c" /><br> 7 <input type="text" name="d" /><br> 8 <input type="text" name="e" /><br> 9</form> 10<script> 11document.getElementById('hoge').addEventListener('keydown', function handleKeydown (event) { 12var input = event.target; 13 14if (event.code !== 'Enter' || input.tagName !== 'INPUT' || input.type !== 'text') return; 15 16var nextInput = input.form.querySelector('input:focus~input[type=text]'); 17 18if (nextInput) nextInput.focus(); 19}, false); 20</script>

HTML

1<h2>getElementsByClassName() ver</h2> 2<form id="sample1" action="test.php"> 3 <input class="focusable" type="text" name="a" /><br> 4 <input type="checkbox" name="c1" /><br> 5 <input class="focusable" type="text" name="b" /><br> 6 <input type="checkbox" name="c2" /><br> 7 <input class="focusable" type="text" name="c" disabled /><br> 8 <input class="focusable" type="text" name="d" /><br> 9 <input class="focusable" type="text" name="e" /><br> 10</form> 11<script> 12document.getElementById('sample1').addEventListener('keydown', function handleKeydown (event) { 13 const input = event.target; 14 15 if (event.code !== 'Enter' || input.tagName !== 'INPUT' || input.type !== 'text') return; 16 17 const targets = document.getElementsByClassName('focusable'); 18 let i = Array.prototype.indexOf.call(targets, input), nextInput; 19 20 while (nextInput = targets[++i], nextInput && nextInput.disabled); 21 22 if (nextInput) nextInput.focus(); 23}, false); 24</script> 25 26<h2>querySelectorAll() ver</h2> 27<form id="sample2" action="test.php"> 28 <input class="focusable" type="text" name="a" /><br> 29 <input type="checkbox" name="c1" /><br> 30 <input class="focusable" type="text" name="b" /><br> 31 <input type="checkbox" name="c2" /><br> 32 <input class="focusable" type="text" name="c" disabled /><br> 33 <input class="focusable" type="text" name="d" /><br> 34 <input class="focusable" type="text" name="e" /><br> 35</form> 36<script> 37document.getElementById('sample2').addEventListener('keydown', function handleKeydown (event) { 38 const input = event.target; 39 40 if (event.code !== 'Enter' || input.tagName !== 'INPUT' || input.type !== 'text') return; 41 42 const nextInput = input.form.querySelector('.focusable:focus~.focusable:enabled'); 43 44 if (nextInput) nextInput.focus(); 45}, false); 46</script>

Re: ryooma さん

投稿2021/02/28 05:00

編集2021/02/28 12:21
think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ryooma

2021/02/28 06:17

ありがたいです 参考にさせていただきます。 追加で質問させてください。 m.ts10806さんからもらった回答で getElementsByClassNameは複数形として指定・使用することができるという事がわかりました。 getElementsByClassNameでの使用を考えてたので本当によかったです。 では この場合、think49さんから与えられた2つの選択肢の内、後者は >/ nextElementSibling を while 文で <input type="text"> がくるまで繰り返す >/ 親ノードから querySelectorAll() で input:focus+input[type=text] getElementsByClassNameにも適応できますか? また、わたしの初頭のコードでは処理が1回で終わっていたから、先に進めなかった という認識で大丈夫でしょうか。
think49

2021/02/28 07:11

> getElementsByClassNameにも適応できますか? 親ノードから getElementsByClassName() を使用し、event.target の次の要素ノードを探せば実装可能です。 が、querySelectorAll() の方が数段シンプルに実装出来ると思います。 > また、わたしの初頭のコードでは処理が1回で終わっていたから、先に進めなかった 現在、focusされている要素ノードがどこか分からないはずですが、document.getElementById("txt1") がfocusされていると決め打ちしているので、実装がおかしいです。 window.onkeydownで全体処理にするなら、event.target を確認するのは必須でしょう。
think49

2021/02/28 07:17

また、これは要件の問題ですが、[Enter] キーの挙動を変更すると、 - [Enter] キー押下でIME変換の確定入力不可 - [Enter] キー押下でsubmit送信不可 というデフォルトの挙動を阻害する問題があります。 キー操作を変更する場合は、既存のショートカットキーと衝突しないキーを使用するのが望ましいと私は思います。
babu_babu_baboo

2021/02/28 08:14 編集

次に移動する要素がなんらかの事情で表示されていない場合、移動できませんよ。 (初めてのツッコミ!返り討ちなんぬことを…) 何らかの事情その2 disabled とか、type=number とか他多数、移動できません。 どうでもよいのは readOnly か…
ryooma

2021/02/28 09:35

think49 ひと通り調べてきましたが やはりどこも インプット要素でのフォーカス移動しかないみたいです。 多分 getElementsByClassName() でクラス要素だけをフォーカスさせるのに多少複雑な仕組みにしなければならないということなのでしょうか 少なくても不可能ではないそうですが、先は長そうです。 <a href=""><h3 class="LC20lb"><span>BELIEVE</span></h3></a>だけを フォーカスさせることができたらいいのですが。 質問に追記を加えてきます。
babu_babu_baboo

2021/02/28 09:46

document.querySelectorAll ('.LC20lb')[1].parentNode.focus();
ryooma

2021/02/28 10:08

参考にしてみましたが、とべませんでした。
babu_babu_baboo

2021/02/28 10:15

フォーカスが移るんだからイベント発火したら?
think49

2021/02/28 11:59

@ryooma > やはりどこも インプット要素でのフォーカス移動しかないみたいです。 何のコード掲示もなく、そういわれてもアドバイスしようがないのですが…。 「私に実装して欲しい」という依頼でしょうか。 親記事に追記しました。
think49

2021/02/28 12:04

@ryooma > <a href=""><h3 class="LC20lb"><span>BELIEVE</span></h3></a>だけを focus可能な要素は <a href=""> であって、<h3 class="LC20lb">はfocus可能ではありません。 tabindex属性を付与しているならともかく、h3要素はfocus不可能な要素です。 https://momdo.github.io/html/interaction.html#focusable-area focus可能な要素に class="LC20lb" を付与する実装がスマートだと思いますが…。
think49

2021/02/28 12:08 編集

@ryooma 一応確認ですが、<a href=""> のhref属性値はサンプル故に空値なだけで本番コードには有意な値が入っているのですよね? もしも、focus可能にするためだけに <a href=""> を使用しているのならセマンティクス的に正しくない為、tabindex属性を使用するべきです。
ryooma

2021/02/28 12:19

>focus可能な要素は <a href=""> であって、<h3 class="LC20lb">はfocus可能ではありません。 tabindex属性を付与しているならともかく、h3要素はfocus不可能な要素です。 >もしも、focus可能にするためだけに <a href=""> を使用しているのならセマンティクス的に正しくない為、tabindex属性を使用するべきです。 なるほど(;_;)そこでしたか。 心が痛みます、無知すぎて。 たすかりました。 もう一度チャレンジしてみます。
ryooma

2021/02/28 12:21

>一応確認ですが... はい、わたしはフォーカス可能にするためにAタグでH3を囲っていました。
think49

2021/02/28 13:29 編集

@babu_babu_baboo さん > 次に移動する要素がなんらかの事情で表示されていない場合、移動できませんよ。 @babu_babu_baboo さんの回答を読んで可視性についても考慮しましたが、実際のところ、input要素で不可視にするなら、<input type="hidden"> でマークアップする実装を私はするので、可視性は考慮しないことにしました。 なお、@babu_babu_baboo さんの回答コードで考慮されていないケースがいくつかあります。 - <input type=hidden> が不可視要素に入っていない - ネガティブマージンやpositionで画面領域外に位置する要素 - 親/祖先要素が不可視な要素 おそらく、他にもあると思いますが、不可視になる機能を一つ一つ潰していくのは骨が折れます。 確認した中では getBoundingClientRect() の値を確認するのが現実解な気がしました。 https://drafts.csswg.org/cssom-view/#extension-to-the-element-interface https://jsfiddle.net/8fg7Lqwt/1/ 懸念される問題は - 0,0座標に内容が空のspan要素があると誤検出する - visibility: hidden; opacity: 0; は独自処理が必要 ところで、opacity: 0 は視認不可能なだけで存在はしているので、focus可能が正解に思えるのですが、どうでしょう? <input type=text> で文字入力は可能でした。 > 何らかの事情その2 disabled とか、type=number とか他多数、移動できません。 :enabled は考慮すべきでしたので、修正しました。 type=numberは要件未確認で見切り発車したのが根本的問題だと思っていて、focus可能な要素の要件が質問文には明確に書かれていないのですよね。 私や@babu_babu_baboo さんからすると、tabキーのフォーカス移動を連想しますが、ラジオボタン/チェックボックスをスキップしていることから明らかに独自の要件を持っています。 不明箇所は質問者本人に任せてアドバイスだけするつもりでしたが、コード有回答が寄せられたので、独断と偏見で要件を補完してコードを書いたのが現状になります。 > if (/^(INPUT|TEXTAREA|SELECT|BUTTON)$/.test (node.tagName)) ところで、ネイティブのtabキーフォーカス移動をエミュレーションする場合、他にもfocus可能な要素がいくつかあります。 https://momdo.github.io/html/interaction.html#focusable-area - details要素内の最初のsummary要素 - tabindex属性を持つ要素 - iframe要素 - <a href>
babu_babu_baboo

2021/02/28 14:00

フォーカスの移動は、先日自分のために書いたものだから「俺様仕様」なんだよね。form 要素の中でマウスを使わずに入力を終えるためのもの。 opacity は意図的に消しているのだからフォーカスさせないかなぁ。 >親/祖先要素が不可視な要素 ちゃんと見てよ!対処してます。 hidden 属性は、change イベントが反応しないので意外と不便です。 tabIndex属性を持つものとの混在は迷うよね。なので-1だけ採用しました。 質問者は置き去りにするけど、複数の form がある場合それぞれを巡回させられるとか、未変換文字がある状態での移動だとか、思いついたまま書いたんだよね。自分的にはこの辺が妥当なレベルかなと。
babu_babu_baboo

2021/02/28 23:40

<input type=hidden>は、ノードフィルターで弾かれます。
think49

2021/03/01 07:04

@babu_babu_baboo さん > >親/祖先要素が不可視な要素 > ちゃんと見てよ!対処してます。 ごめんなさい。e = e.parentNodeで見てましたね。 > 質問者は置き去りにするけど、 質問者も私のコメントに対して都合のいい部分だけ返答しているのでお互い様だと思ってます。 数打てばあたる戦術(説明の大部分は伝わらない)を質問者に対して続けるだけで終わるのは精神的にきついので、回答者同士の掛け合い程度は許して頂きたいのが本心。 > 複数の form がある場合それぞれを巡回させられるとか、未変換文字がある状態での移動だとか、思いついたまま書いたんだよね。 私もformを跨いだfocus移動はしない要件を勝手に作って書いてました。 あと、私が実装するなら、ショートカットキーの設定変更、機能のOn/Offが簡単に出来るようにするかも。
ryooma

2021/03/01 14:00 編集

think49さん >何のコード掲示もなく、そういわれてもアドバイスしようがないのですが…。 いえ質問時にコードは提示しているはずですが、あそこじゃなくて? というか「コード提示」という言い方が何を指してるのかわかりませんが私からthink49さんに質問するときにということですか? 初頭の質問で間違いなく書いているんで、ちょっと答えられないです・・・ >「私に実装して欲しい」という依頼でしょうか。 いつそんなこと言ったんでしょうかw 書いてくれるんですか? 嬉しいですねぜひ書いてください。 ちなみに調べた限りではAタグにフォーカスしようとしてる人が一人もいないので 参考にしようにも参考になる材料がないため、進展ができず質問しているわけで それで方法があればいいんですけどなければ無いでそう言ってくれれば済む話で、 いちいち皮肉を書かなくてもいいと思います というか >私に実装して欲しい」という依頼でしょうか。 とかの皮肉を書くくらいならコードを書いてくれ。 あなたの捉え方曰く{コード提示すれば話が終わるから提示しろって質問者に言って欲しいんだけど、はやくい言えやー}ってことならね。 わたしは、そういうの良くないと思いますし。 自ぶんの学習にもならないと思ってるのでヒントを一つ一つ調べてやっていくつもりですが 話を早く終わらせたいならどうぞ、提示してくださいな。ベストアンサーにしてさしあげますよ せっかくすばらしい選択肢やヒントをくれた人が余計な一言で全部崩壊してます リアルで鬱憤が溜まってるのかなんなのかわかりませんが 質問者を対象にストレス発散はやめてくれたまえ 捌け口にしないでくれたまえ あとthink49さんに対して言っていたbabu_babu_babooさんも >次に移動する要素がなんらかの事情で表示されていない場合、移動できませんよ。 >(初めてのツッコミ!返り討ちなんぬことを…) ここで余計な一言(初めてのツッコミ!返り討ちなんぬことを…) とか言うから叩かれるんですぅ いちいちなにかと余計なことを書かないと回答できないんですか?!あなたたちは... 何をそう揉めてるのかわかりませんが 新しい単語が出てくるたびに調べてるんでもうすこしまってくださいな笑 別に誰が悪いとかないと思いますけど、てか十中八九私が悪いんですけどね たぶん、単語を知らないから!一つ一つ時間かけまくってるせいだと思うけど think49さんのコメでも >質問者も私のコメントに対して都合のいい部分だけ てbabu_babu_babooに言いましたけど、無視してないよってちょっと専門用語調べるのに時間くれへん? 部屋に時限爆弾でも置いてるんか? ノードとかイベント発火とかを凡人にパ!っと言って「あーそうですか!」なんてならないから普通に考えて!察して、相手は凡人だって思って対応してくれへん? m.ts10806さんを見てください! 要件以外の余計な一言は何も言ってないですよ。 素晴らしすぎません?! 見習ってくださいな とりあえず指摘された場所一生懸命辞書引いてるんで あともう30年まってください。
babu_babu_baboo

2021/03/01 14:08 編集

ryooma さん 勘違いしないで欲しいことが1つ。 think49 君は僕のお友達。お互いを高めあおうとしている数少ない親友なのだよ。なので気分を害されたのなら謝ります。ごめんなさい。 回答を控えるというのは、この質問にではなくて全体に対してです。 仕事もあるしね…。 文章だけでは伝わらないこともあるのは、百も承知だと思います。 回答者側も質問者のレベルを計っているときがある。 喰いついてきた人にはとことん答えてくれる人なのだから、そこは免じてほしい。 そのおかげで私のレベルはちょっとだけ進歩するのです。 私も think49 君から指摘を受けて、先に提示したプログラムを検討しています。普通の人よりプログラムを書くスピードは速いと思いますが、あれこれ構成を考えている時間が長くなっています。 普段であれば、回答しても無反応とかすぐに締め切ってしまう質問者がいます。回答しようと思ったのに…と無駄になること多数。仕切らなきゃ質問に答えているよ! 実は根が良い奴なんだよ!わかっておくれ!
ryooma

2021/03/01 14:07

ああ、よかったー(;_;) babu_babu_babooさんたちはお友達どうしだったんですね びっくりしたー、いあよかった喧嘩してないのなら全然、なんかもめてるように見えただけなので そういうことか 焦った(;_;) こちらこそごめんなさい。
ryooma

2021/03/01 14:10

そいうことなら どうぞ、お互い沢山語ってください(`・ω・´) またしばらくコメント等質問は遠分できないですが、それまでに Jsについて勉強してフォーカス移動できるようにしてきます。 解決したらまた追記します
babu_babu_baboo

2021/03/01 14:23

ところで、本題。 汎用性の高いプログラムを書くことはとても重要。 <input type="radio">とか type="checkbox" があったらどうする? 移動手段は[Enter]だとして、その項目を設定&解除するには? <a>タグだったら遷移する?そのときの条件をどこに記述する? とかショートカットキーとか考えて無いでしょ? そういうのをアドバイスしてくれてたんだ。(汎用性を上げるために) そういう回答が君からなかったんで…この流れ。 で、汎用性を高めることも考慮してどうしたいのか!なのだよ。 もうね、動けば良し!という回答にはうんざりしているんだよ。 彼も私も。つまり君は面倒な2人を相手にしてしまったということだ!w
ryooma

2021/03/01 21:58 編集

どうしてもgoogle chrome の拡張機能をつくりたかったんですよ 検索するとき いちいちマウスをいじって検索結果の項目をくりっくせずとも Aタグ内のH3クラスネームを指定できるなら!っておもって パソコンいじるときほとんどショートカットキーで操作してので マウスがないノートPCの指でこすってマウスカーソルを移動していちいち 検索項目をタプタプするのに疲れまして・・・ googleもF7キーでカーソルフォーカス移動機能をつけたらしいのですが 使ってみたらイマイチで。。。。 検索項目だけをフォーカスしたいのに全く関係のなところまでフォーカスされてて。。。 クラス指定すればいいじゃん!って思って。 作ろうかと。 でもAタグでクラス指定しても飛ばないので。。。たぶんなんらかの特殊な書き方をしないと行かないんだなーって感じで。今に至る。
ryooma

2021/03/01 22:02

ところでbabu_babu_babooさん! めっちゃええ人やね。 またどこかでノシ
think49

2021/03/02 08:13 編集

@ryooma さん 私のコードは2021/02/28 20:59に「親記事に追記しました」で示したつもりです。 「実装例」の下段はあなたが期待する getElementsByClassName() を使用しています。 > いえ質問時にコードは提示しているはずですが、あそこじゃなくて? 2021/02/28 18:35であなたは「ひと通り調べてきましたが、やはりどこも インプット要素でのフォーカス移動しかないみたいです。」と書いていますが、質問文にフォーカス移動しないコードが追記されているでしょうか。 期待通りに動作しないことだけは伝わりますが、コードが見えない私には原因が見当もつきません。 こちらで正常動作するコードを掲示する以外に私が出来ることはなさそうに感じました。 (あなたがどうかはわかりませんが、曖昧に情報を出して、「面倒くさいからこのコード使って」を期待する質問者は一定数います) また、私が回答で示した解決手段は採用されませんでしたので、「getElementsByClassName()を使用したコード」に何かしら拘りがあるのだと思います。 それなら、「getElementsByClassName()を使用しなければならない事情」や「getElementsByClassName()で期待通りに動作しないコード」が質問文にあってしかるべきでは? 後出しで条件が追加されて回答が徒労に終わるのは、回答者としては絶対になりたくない状況です。 > 話を早く終わらせたいならどうぞ、提示してくださいな。ベストアンサーにしてさしあげますよ 私が欲しいのはベストアンサーではありません。 回答するために「必要な情報」です。 最も良いのは「再現可能な最小限のサンプルコード」を掲示することです。 https://ja.stackoverflow.com/help/minimal-reproducible-example > ノードとかイベント発火とかを凡人にパ!っと言って「あーそうですか!」なんてならないから普通に考えて!察して、相手は凡人だって思って対応してくれへん? いやまあ、普通に考えて、「DOMノードを操作しようとしているのに、なぜノードを知らないの?ひょっとして、DOMすら知らないのでは?」と思ってしまうんですけどね。 ネット上に転がっているサンプルコードやqiitaのような参考情報をより集めてコードを作ろうとしている人は一定数いますが、「そんなことより基礎が大切でしょ。基礎を学ばずに枝葉の情報を調べてどうするの?」というのが正直な感想です。 回答をするにあたって「あなたが何を知っていて何を知らないのか」を私は全く知りません。 質問者はその既知と未知の境界を明確に分かるように質問文に含めるべきだと私は思います。 ヘルプにも似たようなことが書いてあります。 https://teratail.com/help/question-tips#questionTips2-1 例えば、getElementsByClassNameの何を知っていて何を知らないのか。 他にもコードがあれば、その人が知っている範囲がおぼろげながら見えるものです。 その上で分からない事が多すぎたり、どこから調べればいいか見当もつかない状態であれば、基礎を体系的に学んだ時間が足りていません。 課題が実力に見合っていないので、基礎勉強からやり直して課題の難易度を下げるべきだと思います。 https://teratail.com/questions/224306#reply-331229 今回の課題ならDOMの理解は必須ですが、根幹となるECMAScriptも視野に入ると思います。 https://teratail.com/questions/124923
think49

2021/03/02 06:51

> 検索するとき いちいちマウスをいじって検索結果の項目をくりっくせずとも > Aタグ内のH3クラスネームを指定できるなら!っておもって もしかして、"LDRize"
think49

2021/03/02 08:03

最も、LDRizeなら、getElementsByClassNameに拘る必要はなく、querySelectorAllでもXPathでも何でもいいはずですが…。 https://jsfiddle.net/j3ps4e8w/ それとターゲットはa要素のみとなり、質問文にあったinput要素郡に対応したコードが丸々無駄になりますね…。
ryooma

2021/03/02 18:05

え、、、う、嘘でしょ、こ、これです! これを探してました。 ふふぁあ感謝します。 ただいまはそれよりも(あとでいっぱい感動してきます) think49さんから私に投げた重要な話をしましょう。 確かに質問をしたのは 早く解決出来たらいいなと思って質問したわけで、それが「面倒くさいから質問してすませよう。」 と同等なのかわかりませんが、 「なんで基礎からやって来ないの?」今思えば言われて当然ですよね。 フォーカスを作るという過程で、JSの基礎を確実に学べる!と思ったからです。 ネットでフォーカスサンプルをコピペしたあと、思い通りの動きをしてもらうために、IF文や関数?(未だに関数という概念がはっきりわかっていませんが)関数など 基本だ!って思える部分は調べたうえで弄りました。が 早めに問題解決をしたい私はもっとヒントが出てくる場所、 テラテイルで質問してみよう!ってなった次第で、それを 「ただひたすら回答を待つ優柔不断な質問者」と捉えるか捉えないかはthink49さん次第ですけど、すくなからず私は努力してたつもりでした。 「楽な道を選んだ」と言われれば多分否定できません。 質問している時点で楽を取ったのは間違いないので。 >回答するために「必要な情報」です。 >で、汎用性を高めることも考慮してどうしたいのか!なのだよ。 >もうね、動けば良し!という回答にはうんざりしているんだよ。 それゆえに 回答者のお二人に求められてた物を提示できなかったのも上記に書いた経緯ゆえのものかと。 私に求められていた情報提示ができる身のレベルであれば そうしたかったんですけど。 けして回答者を「代行屋」として扱っているわけではないことを ここで説明しておきたかった。 だから「ごめんなさい」としか。 これがJS1年目2年目くらい弄ってた私だったら 全く違った状況でお二人から回答を得られたかもしれません。 最終的には「何でフォーカスしたいのか」を元々から説明した結果think49さんから私が求めてたLDRize?機能、情報がでてきたので、無いものと思っていたものが出てきたのでびっくりしましたが、よかったです。 このLDRize?作った人がつけた名前なのかな、 をつかってこれからさらにJsの基礎とLDRizeの解析、実装をしてみたいと思います。 ご迷惑をおかけしました。
ryooma

2021/03/02 18:16

動きました!w think49さん babu_babu_babooさん ありがとう!
think49

2021/03/07 06:19 編集

@ryooma さん > このLDRize?作った人がつけた名前なのかな、 LDRizeの名前は「Livedoor Reader」と同様のショートカットキーを割り当てた事に由来します。 どちらが先か知りませんが、"rize" は "AutoPagerize" に影響されている可能性があります。 なお、SITEINFOのリンク指定(link)はXPathで書かれており、@ryooma さんの着眼点(<h3 class="LC20lb">)とは別の場所にマッチさせています。 http://wedata.net/items/28431 https://wikiwiki.jp/958/LDRize#yb803dce Autopagerizeもそうですが、将来的に変更されにくい意味のある名前(class="g")にマッチさせるようXPathを指定する事が多いです。 「前方互換性」が重視されているのでしょう。 > ネットでフォーカスサンプルをコピペしたあと、思い通りの動きをしてもらうために、IF文や関数?(未だに関数という概念がはっきりわかっていませんが)関数など 基本だ!って思える部分は調べたうえで弄りました。が どのように調べたのか分かりませんが、少なくとも、質問文に書かれたコードについて十分に理解するだけの調査を行ったとは思えない状況でした。 例えば、nextElementSibling について調べれば「ノード」という単語は必ず出てくるはずですし、onkeydown を調べれば「イベント」というキーワードは出てきたはずです。 「ならば、それらの単語についても調べて理解しているはず」というのがコードを読んで回答者が質問者に期待する事です。 キーワードが分からない質問者に考えられる状況は私の経験上、2通りあります。 A. 調べたものの分からないキーワードは飛ばし読みして何となくイメージが出来た(本人は理解したつもりだが、実は理解できてない) B. どこかのサンプルコードをコピペしていてコードそのものの意味は理解してない 回答が理解できないのは「質問文に書かれたコードの理解が不十分だから」だと私は考えます。 ボトムアップ型の学習がいけないとはいいませんが、分からない事が出来たときにトップダウン式に学習して解決できるだけの下積みは必要です。 型/スコープ/反復処理/関数/配列/オブジェクト/プロトタイプを理解しないとDOMを理解するのは難しいと思います(飛ばしてDOMに入る人は結構いますが、必ずどこかで躓きます)。 https://jsprimer.net/ https://uhyohyo.net/javascript/index.html --- それから、事後対応にも問題を感じていて、「回答で分からない箇所」の共有がされていないのが気になりました。 初めから十分に理解したコードを載せて質問するのが最良ですが、後から質問を修正する方向性もあるでしょう。 最も、追加質問が多量に来るようなら、質問するための前提知識が足りなかったという結論にはなります。
think49

2021/03/07 06:36

古いですが、書籍をお勧めしておきます。 『DOM Scripting 標準ガイドブック ~やさしく学ぶ、JavaScriptとDOMによるWebデザイン~』 『WebクリエイティブのためのDOM Scripting』 https://gist.github.com/think49/689d7d1e5c5fd0c5ca266e4c66b0b35e#%E6%9B%B8%E7%B1%8D 私がDOMの基礎を理解するために読んだ本はこの2冊だけです。 最新APIには対応していませんが、基礎を押さえるには十分だと思います。 残りはDevelopper Toolsで使えそうなプロパティ/メソッドを探して調べれば、大体網羅できます。
guest

0

idは同一ページ内に唯一のものでなければいけません。
これはHTMLのルールです。
そもそもidentityですしね。

唯一であると保証されてないといけないので、同一ページ内に複数あるとJavaScriptは特定ができない、動作保証されません。
それは、メソッド名にも表れています。
getElementById
getElementsByClassName
後者には「s」があり複数形となっています。

まずはこの問題を解消してください。

投稿2021/02/28 00:21

m.ts10806

総合スコア80850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2021/02/28 05:10

補足ありがとうございます。 あくまで「行きたいところは示せない」という意図がありました
guest

0

前回の回答があまりにも適当過ぎたので書き直しました。
think49 さんからの指摘で、summary などに対応しました。

js

1<!DOCTYPE html><title></title><meta charset="utf-8"> 2<style> 3 a:focus, datalist:focus, input:focus { 4 background: rgba(255,0,0,.2); 5 } 6</style> 7 8<body> 9<nav> 10 <p>最初に[Tab]でフォーカスを移動した場合テストできる<br> 11 <a href="#C">ABC</a> 12 <a href="#C">DEF</a> 13 <a href="#A">GHI</a><br> 14</nav> 15 16<form> 17 <p>フォーム内のアンカータグを移動する<br> 18 <a href="#C">ABC</a> 19 <a href="#C">DEF</a> 20 <a href="#A">GHI</a> 21 22 <p>通常の INPUT要素<br> 23 1.<input name="d0" value=""> 24 2.<input name="d1" value=""> 25 26 <p>表示されていない要素<br> 27 1.<input type="hidden" name="d2"> 28 2.<input type="hidden" name="d2" style="display:none;"> 29 3.<input type="hidden" name="d2" style="visibility:hidden;"> 30 4.<input type="hidden" name="d2" style="opacity: 0;"> 31 32 <p>INPUT[type=radio]要素の場合<br> 33 <label>1.<input type="radio" name="d3" value="1">abc</label> 34 <label>2.<input type="radio" name="d3" value="2">def</label> 35 <label>3.<input type="radio" name="d3" value="3">ghi</label> 36 37 <p>INPUT[type=checkbox]要素の場合<br> 38 <label><input type="checkbox" name="d4" value="1">abc</label> 39 <label><input type="checkbox" name="d4" value="2">def</label> 40 <label><input type="checkbox" name="d4" value="3">ghi</label><br> 41 42 <p>SELECT要素<br> 43 <select name="d5"><option value="">-- <option value="1">abc <option value="2">def</select> 44 45 <p>TEXTAREA要素<br> 46 <textarea name="d6" cols="80" rows="5"> 47 改行すると、その行の最初のインデントが継続されます 48 改行せずに移動する場合は[Ctrl]+[Enter]、設定で逆の動作をします 49 改行すると、その行の最初のインデントが継続されます 50 </textarea> 51 52 <p>DATALIST要素にSUMMARYがある場合<br> 53 <details> 54 <summary>Summary OPEN1</summary> 55 <ol><li>abc <li>def <li>ghi</ol> 56 </details> 57 <details open> 58 <summary>Summary OPEN2</summary> 59 <ol><li>abc <li>def <li>ghi</ol> 60 </details> 61 62 <p>INPUT[type=button] / BUTTON 要素の場合<br> 63 <input type="button" value="フォームの移動を無効にする" onclick="F.disabled=true"> 64 <input type="button" value="フォームの移動を有効にする" onclick="F.disabled=false"> 65 </p> 66 67</form> 68<script> 69 70/* 71 [Enter] 要素を次に移動する 72 [Shift]+[Enter] 前に移動する 73 [Ctrl]+[Enter]: 作用する 74*/ 75 76class ExEnter { 77 78 constructor (root = document.documentElement, option = { }) { 79 const 80 filter = this.filter.bind (this), 81 Nfilter = NodeFilter.SHOW_ELEMENT; 82 83 this.root = root; 84 this.walker = root.ownerDocument.createTreeWalker (root, Nfilter, filter, true); 85 this.option = Object.assign ({ }, this.constructor.defaultOption, option); 86 87 //IME日本語入力中で未変換文字があり Enterが押されたことを感知するには 88 //keypress イベントがが実行されないことを利用する 89 this.imeFlag = null; //ime 90 this.disabled = false; //機能停止用 91 } 92 93 94 //ルートの中の最初の要素を返す 95 get firstElement () { 96 this.walker.currentNode = this.root; 97 return this.walker.firstChild (); 98 } 99 100 101 //ルートの最後の要素を返す 102 get lastElement () { 103 this.walker.currentNode = this.root; 104 return this.walker.lastChild (); 105 } 106 107 108 //要素を移動する 109 move (target, direction = false) { 110 if (this.disabled) 111 return; 112 113 const 114 walker = this.walker, 115 isLoop = this.option.loop; 116 117 walker.currentNode = target; 118 let e = (direction) 119 ? walker.previousNode () || (isLoop ? this.lastElement: null) 120 : walker.nextNode () || (isLoop ? this.firstElement: null); 121 122 if (e) e.focus (); 123 } 124 125 126 //TreeWalker用のフィルター関数(要.bind(this)) 127 filter (node) { 128 const 129 accept = NodeFilter.FILTER_ACCEPT, 130 skip = NodeFilter.FILTER_SKIP; 131 132 switch (node.nodeName) { 133 case 'INPUT' : case 'TEXTAREA' : case 'SELECT' : case 'BUTTON' : 134 if (node.disabled) break; 135 if (node.readOnly) break; 136 if (this.option.tabIndex && ('-1' === node.getAttribute ('tabIndex'))) break; 137 if (isHide (node)) break; 138 return accept; 139 140 case 'A' : //href = '#...' で始まるもののみ対象とする 141 if (this.option.anchor) { 142 let href = node.getAttribute ('href'); 143 if (href) 144 if (! href.indexOf ('#')) 145 return accept; 146 } 147 break; 148 149 case 'SUMMARY' : 150 return accept; 151 } 152 return skip; 153 154 //__ 155 //祖先の要素が隠された状態にあるか? 156 function isHide (node) { 157 const chks = ['display', 'visibility', 'opacity', 'height', 'width']; 158 159 for (let e = node; e !== document.body; e = e.parentNode) { 160 let cs = getComputedStyle (e, null); 161 let [d, v, o, h, w] = chks.map (p=> cs.getPropertyValue (p)); 162 if ( 163 'none' === d || 'hidden' === v || 0 == parseFloat (o) || 164 ! ('auto' === h || 0 < parseInt (h, 10)) || 165 ! ('auto' === w || 0 < parseInt (w, 10)) 166 ) return true; 167 } 168 return false; 169 } 170 } 171 172 173 //_____ 174 175 //[CTRL]が押されていれば、適用させる 176 apply (e, sw, prev) { 177 let stay = false, tag = e.nodeName; 178 179 if ('TEXTAREA' === tag && !prev) { 180 if (sw ^ this.option.textarea) { 181 this.constructor.insertCRLF (e, this.option.autoIndent); 182 stay = true; 183 } 184 } 185 else if (sw) { 186 stay = this.option.stay; 187 switch (tag) { 188 case 'SUMMARY' : 189 let parent = e.parentNode; 190 parent.hasAttribute ('open') 191 ? parent.removeAttribute ('open') 192 : parent.setAttribute ('open', ''); 193 break; 194 195 case 'A' : 196 fireEvent (e); 197 break; 198 199 case 'INPUT' : 200 switch (e.type) { 201 case 'radio': case 'checkbox' : 202 e.checked = !e.checked; 203 break; 204 205 case 'button' : case 'submit' : case 'reset' : 206 fireEvent (e); 207 break; 208 } 209 break; 210 } 211 } 212 //値が有効か? 213 if (this.option.invalidStop && e.checkValidity) 214 stay = ! e.checkValidity (); 215 216 return stay; 217 218 //__ 219 220 function fireEvent (e) { 221 let event = document.createEvent ('MouseEvents'); 222 event.initEvent ('click', false, true); 223 e.dispatchEvent (event); 224 return event; 225 } 226 } 227 228 229 //_____ 230 231 //イベントハンドラ(各typeによって分岐) 232 handleEvent (event) { 233 this[event.type + 'Handler'].call (this, event); 234 } 235 236 //キーアップハンドラ 237 keyupHandler (event) { 238 let { code, shiftKey, ctrlKey, target: e } = event; 239 if ('Enter' !== code) return; 240 if (! this.imeFlag) //IMEの動作で未変換中の文字があると判断してスルー 241 return event.preventDefault (); 242 this.imeFlag = null; 243 if (! this.apply (e, ctrlKey, shiftKey)) 244 this.move (e, shiftKey); 245 } 246 247 //キープレスハンドラ 248 keypressHandler (event) { 249 let { target: { nodeName: n, type: t }, code } = event; 250 if ('Enter' == code) 251 if (/^(submit|reset|button|textarea)$/.test (t) || 'SUMMARY' === n || 'A' == n) 252 event.preventDefault (); 253 this.imeFlag = true;//未変換文字がある場合の対処として 254 } 255 256 //________ 257 258 //インスタンスの作成 259 static create (root = document.documentElement, option = { }) { 260 let obj = new this (root, option); 261 root.addEventListener ('keyup', obj, false); 262 root.addEventListener ('keypress', obj, false); 263 return obj; 264 } 265 266 //textarea要素に改行を挿入する 267 static insertCRLF (t, autoIndent = false, start = t.selectionStart || 0) { 268 let 269 str = '\n', 270 value = t.value, 271 first = value.slice (0, start), 272 last = value.slice (start).replace (/^([\t\u3000\u0020]+)/, ''); 273 274 if (autoIndent) { 275 let spc = /(?:\n|^)([\t\u3000\u0020]+).*$/.exec (first); 276 if (spc) str += spc[1]; 277 } 278 279 t.value = first + str + last; 280 t.selectionStart = t.selectionEnd = start + str.length; 281 } 282 283 284 285 //初期設定オプション値 286 static defaultOption = { 287 stay: true, //true: radio,checkbox,submit,button,summary を作用させた後も留まる 288 loop: true, //要素を巡回する 289 tabIndex: true, //tabIndex="-1" を有効にする 290 anchor: true, //アンカータグを有効にする(但し href属性の値が "#"から始まる場合) 291 textarea: true, //true:テキストエリア内では改行する, false:次に移動する(改行は、[Ctrl]+[Enter]) 292 autoIndent: true, //textarea要素内でのオートインデントを行う 293 invalidStop: false,//要素の値が不正な場合でも移動する 294 }; 295} 296 297const 298 nav = ExEnter.create (document.querySelector ('nav')), 299 F = ExEnter.create (document.querySelector ('form')); 300 301</script> 302 303

js

1<a href="#"><h3 class="LC20lb"><span>BELIEVE</span></h3></a> 2<a href="#"><h3 class="LC20lb"><span>BELIEVE</span></h3></a> 3<a href="#"><h3 class="LC20lb"><span>BELIEVE</span></h3></a> 4<a href="#"><h3 class="LC20lb"><span>BELIEVE</span></h3></a> 5 6 7<script> 8const walker = document.createTreeWalker (document.body, NodeFilter.SHOW_ELEMENT, filter, true); 9 10function filter (node) { 11 return 'A' === node.nodeName 12 ? NodeFilter.FILTER_ACCEPT 13 : NodeFilter.FILTER_SKIP; 14} 15 16function handler ({ ctrlKey, key, target: e }, n) { 17 (ctrlKey && 'ArrowDown' === key) && 18 (walker.currentNode = document.activeElement, n = walker.nextNode (), n && n.focus ()); 19} 20 21document.addEventListener ('keydown', handler, true);

投稿2021/02/28 06:20

編集2021/03/05 09:23
babu_babu_baboo

総合スコア616

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ryooma

2021/02/28 07:12

ちょっと・・・とは、、、 さすがに予想外でした・・・すばらしいです。 とくに // ルートの中の最初の要素を返す // ルートの最後の要素を返す // 要素を移動する の欄はとても参考になります! いろいろ書き換えたりするかもしれませんが 興味深いのでお借りします。 なおHTMLの記載なのですが、 インプットのテキストタイプとかではなく <a href=""><h3 class="LC20lb"><span>BELIEVE</span></h3></a> <a href=""><h3 class="LC20lb"><span>BELIEVE</span></h3></a> <a href=""><h3 class="LC20lb"><span>BELIEVE</span></h3></a> <a href=""><h3 class="LC20lb"><span>BELIEVE</span></h3></a> このように記載した場合はどこかで特別大きく書き換えを行わなきゃだめだよ! てきなことがありましたらご指摘ねがいます。 極力自分で考えて自力で書いて達成させてみたいので ちょっとした ヒント、だけでも大丈夫です。 貴重なお時間をありがとうございました。
babu_babu_baboo

2021/02/28 07:20

treeWalker の filter 関数を弄る。 要素がアンカータグならクリックイベント発火。 [CTRL]+[Enter] と [Enter] の移動での挙動の差異… 後からそう言われてもね。
babu_babu_baboo

2021/02/28 11:22

>旅に連続で飛べるようにしたい 今更ながら、どんな旅なのか具体的に!
ryooma

2021/02/28 11:39

旅。。。度
ryooma

2021/02/28 11:39

そうですね。 自由な旅に飛びたいです。
think49

2021/02/28 13:51

@babu_babu_baboo さん 大体、私の回答へのコメントで指摘しましたが、二点だけ。 <body> を省略しないのはなぜでしょう? 前々から <html>, <head> を省略しながら、<body> を省略してないのが気になっていました。 「使っているsnippetに <body> が入っていて修正してないだけ」という気もしますが、ショートコーダーらしからぬ書き方に見えてしまって…。 > this.walker = document.createTreeWalker (root, NodeFilter.SHOW_ELEMENT, this.filter, true); TreeWalkerも悪くはありませんが、Symbol.iterator で iterable にしておくと for-of や Spread 要素を使えるようになって、いろいろと便利ですよ。 何となく、そのほうが @babu_babu_baboo さんが好む書き方になるような気がします。
babu_babu_baboo

2021/02/28 23:46 編集

<body>の省略な件 いつだったか忘れたけど、師匠が抜くな!と言っていたような…いつ頃だったかは忘れた。 >ショートコーダーらしからぬ いやいや、これでも助長的に書いてますよ!見た人が「?」ってなる一歩手前程度に。 変数名も明示的だし、「1文字単位で削るのは翻訳機に任せればいい!」これも師匠のお言葉。 論理的な部分を如何に簡素化し短くするか!を、いつも頭の隅に置いていますよ。 TreeWalker は、filter 関数を切り替えたい時があるので、現状のままかな? 先だって、テキストノードの取得の件でわざわざ古い方式で回答したら TreeWalker の回答が優良だった。基礎も判らずにそっちかよ!とか。 愚痴を言えばキリがないね。 それと、なんだか私の回答が浮いている感じなのでちょっと休みます。 (コード読まないやつ多すぎ!) ちょい変なこと聞くけど、自分の書いていたコードを見てくれていたようだけど、ちょっとは(俺)進歩した?
ryooma

2021/03/01 12:02

babu_babu_babooさん 一日開けて来たら、、、なんかもめてる感じになってますけど 別にbabu_babu_babooさんのコードは浮いてないですよ 無視してたわけではなくずっといじってみくらべていました! 最終的に以下の結果になりました <a href="" id="lco"><h3 class="LC20lb"><span>BELIEVE</span></h3></a> <a href="" id="lco"><h3 class="LC20lb"><span>BELIEVE</span></h3></a> <a href="" id="lco"><h3 class="LC20lb"><span>BELIEVE</span></h3></a> <a href="" id="lco"><h3 class="LC20lb"><span>BELIEVE</span></h3></a> function keydown(e){ if (event.key === 'ArrowDown' && event.ctrlKey){ var obj = document.getElementById("lco").focus(); } }; window.onkeydown = keydown; やはり一回しか飛んでくれず、それを回避するにはイベント発火させろという意見でしたが イベントというのを調べてもなかなか。。ピンと来なくて いままた考えてる次第です CSSしかいじってなかった私からしたら何もかもが初めてなので。。。 お手柔らかにお願いします(;_;)
ryooma

2021/03/01 12:47

あ!そうだった >idは同一ページ内に唯一のものでなければいけません。 これはHTMLのルールです。 ってm.ts10806さんにいわれてましたね だから一回しか飛ばないのかな。 クラスにしたらしたで、何も反応しないんですけどね。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問