回答編集履歴

4

sample url

2022/10/28 23:43

投稿

Cocode
Cocode

スコア2314

test CHANGED
@@ -1,4 +1,4 @@
1
- ⭐️ **動作確認用サンプル:** https://jsfiddle.net/u38mxwb0/
1
+ ⭐️ **動作確認用サンプル:** https://jsfiddle.net/2ub63Lto/
2
2
 
3
3
  ### 処理の概要
4
4
  - まずは、フォーカス可能な要素に座標番号のデータ属性をJSで動的に付与します。

3

不具合修正(重要)

2022/10/28 23:43

投稿

Cocode
Cocode

スコア2314

test CHANGED
@@ -71,12 +71,13 @@
71
71
  }
72
72
  ```
73
73
  ```javascript
74
+ const wrapper = document.querySelector('#wrapper');
74
75
  const focusableContainers = document.querySelectorAll('.focusable-container');
75
76
  const focusableItemsMap = [...focusableContainers].map(fc => [...fc.querySelectorAll('.focusable-item')]);
76
77
  const focusableItems = focusableItemsMap.flatMap(elems => elems);
77
78
 
78
79
  window.addEventListener('DOMContentLoaded', setDataCoord, false);
79
- document.addEventListener('keydown', manipulateFocus, false);
80
+ wrapper.addEventListener('keydown', manipulateFocus, false);
80
81
 
81
82
  function setDataCoord() {
82
83
  const coords = [...focusableItemsMap].flatMap((elems, x) => elems.map((_, y) => `${x}-${y}`));
@@ -106,6 +107,9 @@
106
107
  /**
107
108
  * 要素の取得
108
109
  */
110
+ // #wrapper要素を取得
111
+ const wrapper = document.querySelector('#wrapper');
112
+
109
113
  // .focusable-container要素を取得
110
114
  const focusableContainers = document.querySelectorAll('.focusable-container');
111
115
 
@@ -119,7 +123,7 @@
119
123
  * イベントリスナー設定
120
124
  */
121
125
  window.addEventListener('DOMContentLoaded', setDataCoord, false); // ページロード時
122
- document.addEventListener('keydown', manipulateFocus, false); // キーを押している間
126
+ wrapper.addEventListener('keydown', manipulateFocus, false); // キーを押している間
123
127
 
124
128
  /**
125
129
  * 座標番号(data-coord属性)を要素に付与する関数

2

コードの不具合修正(重要)

2022/10/28 23:37

投稿

Cocode
Cocode

スコア2314

test CHANGED
@@ -1,11 +1,11 @@
1
- ⭐️ **動作確認用サンプル:** https://jsfiddle.net/5u0ys7vt/
1
+ ⭐️ **動作確認用サンプル:** https://jsfiddle.net/u38mxwb0/
2
2
 
3
3
  ### 処理の概要
4
4
  - まずは、フォーカス可能な要素に座標番号のデータ属性をJSで動的に付与します。
5
5
  - 例えば、`data-coord="0-0"`を付与
6
6
  - → `<button data-coord="0-0"><span>ボタン1</span></button>`
7
7
  - JSにより自動で付与されますので、自分で考えながらHTMLに座標番号を書かなくてもいいです。
8
- - 左上を起点`(0, 0)`とすると、座標は以下の画像のようになります。
8
+ - 左上を起点として`(x=0, y=0)`とすると、各要素の座標は以下の画像の通りとなります。
9
9
  ![画面上の配置](https://ddjkaamml8q8x.cloudfront.net/questions/2022-10-29/f34c8076-c52f-461a-aca5-a96fbd81a1ee.png)
10
10
  - JavaScriptでフォーカス可能な要素を全て取得し、2次元配列に格納して、繰り返し処理で座標番号を付与しています。
11
11
  ![JSの二次元配列](https://ddjkaamml8q8x.cloudfront.net/questions/2022-10-29/440edf68-a1ba-482a-b912-f28cfce99ba9.png)
@@ -84,11 +84,11 @@
84
84
  }
85
85
 
86
86
  function manipulateFocus(event) {
87
- event.preventDefault();
88
87
  const keys = {'ArrowLeft': [-1, 0], 'ArrowRight': [1, 0], 'ArrowUp': [0, -1], 'ArrowDown': [0, 1]};
89
88
 
90
89
  for (const [key, [x, y]] of Object.entries(keys)) {
91
90
  if (event.key === key) {
91
+ event.preventDefault();
92
92
  const currentCoord = event.target.dataset.coord;
93
93
  const targetCoord = currentCoord ? currentCoord.replace(/(\d+)-(\d+)/, (_, px, py) => [Number(px) + x, Number(py) + y].join('-')) : '0-0';
94
94
  const [targetElem] = document.querySelectorAll(`[data-coord="${targetCoord}"]`);
@@ -97,7 +97,6 @@
97
97
  }
98
98
  }
99
99
  }
100
-
101
100
  ```
102
101
 
103
102
  ### コメントによる解説付きJavaScriptコード
@@ -148,8 +147,6 @@
148
147
  * 矢印キーでフォーカスを操作する関数
149
148
  */
150
149
  function manipulateFocus(event) {
151
- // デフォルトの矢印キーの動きをリセット
152
- event.preventDefault();
153
150
 
154
151
  // 矢印キーによって加算される座標値
155
152
  const keys = {'ArrowLeft': [-1, 0], 'ArrowRight': [1, 0], 'ArrowUp': [0, -1], 'ArrowDown': [0, 1]};
@@ -159,6 +156,9 @@
159
156
 
160
157
  // 押したキーとオブジェクトkeysのプロパティ名が一致するとき、
161
158
  if (event.key === key) {
159
+
160
+ // デフォルトの矢印キーの動きを停止
161
+ event.preventDefault();
162
162
 
163
163
  // 現在フォーカスしている操作ボタンの座標番号を取得
164
164
  const currentCoord = event.target.dataset.coord;

1

.forEach() -> for...of

2022/10/28 23:26

投稿

Cocode
Cocode

スコア2314

test CHANGED
@@ -1,14 +1,15 @@
1
- ⭐️ **動作確認用サンプル:** https://jsfiddle.net/yh412acx/
1
+ ⭐️ **動作確認用サンプル:** https://jsfiddle.net/5u0ys7vt/
2
2
 
3
3
  ### 処理の概要
4
4
  - まずは、フォーカス可能な要素に座標番号のデータ属性をJSで動的に付与します。
5
5
  - 例えば、`data-coord="0-0"`を付与
6
6
  - → `<button data-coord="0-0"><span>ボタン1</span></button>`
7
+ - JSにより自動で付与されますので、自分で考えながらHTMLに座標番号を書かなくてもいいです。
7
8
  - 左上を起点`(0, 0)`とすると、座標は以下の画像のようになります。
8
9
  ![画面上の配置](https://ddjkaamml8q8x.cloudfront.net/questions/2022-10-29/f34c8076-c52f-461a-aca5-a96fbd81a1ee.png)
9
10
  - JavaScriptでフォーカス可能な要素を全て取得し、2次元配列に格納して、繰り返し処理で座標番号を付与しています。
10
11
  ![JSの二次元配列](https://ddjkaamml8q8x.cloudfront.net/questions/2022-10-29/440edf68-a1ba-482a-b912-f28cfce99ba9.png)
11
- - 矢印キーを押下したら現在の座標番号を取得し、移動先の座標番号を計算し、移動先の要素にフォーカスします。
12
+ - 矢印キーを押下したら現在の座標番号を取得し、移動先の座標番号を計算します。
12
13
 
13
14
  ##### 座標計算の例
14
15
  - 例えば、現在フォーカスしている要素が「ボタン7」の場合 → 座標番号は`1-2`
@@ -23,7 +24,7 @@
23
24
  ### 完成コード例
24
25
  htmlに`.focusable-container`と`focusable-item`というclassを追加
25
26
  ```html
26
- <div id="wrapper">
27
+ <div id="wrapper">
27
28
  <div class="inner_left">
28
29
  <div class="frame_button focusable-container"> <!-- class追加 -->
29
30
  <button class="focusable-item"><span>ボタン1</span></button> <!-- class追加 -->
@@ -83,24 +84,20 @@
83
84
  }
84
85
 
85
86
  function manipulateFocus(event) {
86
- event.preventDefault();
87
+ event.preventDefault();
88
+ const keys = {'ArrowLeft': [-1, 0], 'ArrowRight': [1, 0], 'ArrowUp': [0, -1], 'ArrowDown': [0, 1]};
87
89
 
88
- const keys = {
89
- 'ArrowLeft': [-1, 0],
90
- 'ArrowRight': [1, 0],
91
- 'ArrowUp': [0, -1],
92
- 'ArrowDown': [0, 1]
93
- };
94
-
95
- Object.entries(keys).forEach(([key, [x, y]]) => {
90
+ for (const [key, [x, y]] of Object.entries(keys)) {
96
91
  if (event.key === key) {
97
92
  const currentCoord = event.target.dataset.coord;
98
93
  const targetCoord = currentCoord ? currentCoord.replace(/(\d+)-(\d+)/, (_, px, py) => [Number(px) + x, Number(py) + y].join('-')) : '0-0';
99
94
  const [targetElem] = document.querySelectorAll(`[data-coord="${targetCoord}"]`);
100
95
  if (targetElem) targetElem.focus();
96
+ return;
101
97
  }
102
- });
98
+ }
103
99
  }
100
+
104
101
  ```
105
102
 
106
103
  ### コメントによる解説付きJavaScriptコード
@@ -140,7 +137,7 @@
140
137
  // ['3-0', '3-1', '3-2', '3-3', '3-4', '3-5']
141
138
  // ]
142
139
 
143
- // 次配列化しています
140
+ // 1配列化しています
144
141
  // ['0-0', '0-1', '0-2', '0-3', '0-4', '0-5', '1-0', '1-1', '1-2', '1-3', '1-4', '1-5', '2-0', '2-1', '2-2', '2-3', '2-4', '2-5', '3-0', '3-1', '3-2', '3-3', '3-4', '3-5']
145
142
 
146
143
  // 生成した座標をデータ属性として、.focusable-itemに付与していく
@@ -155,27 +152,29 @@
155
152
  event.preventDefault();
156
153
 
157
154
  // 矢印キーによって加算される座標値
158
- const keys = {
159
- 'ArrowLeft': [-1, 0],
155
+ const keys = {'ArrowLeft': [-1, 0], 'ArrowRight': [1, 0], 'ArrowUp': [0, -1], 'ArrowDown': [0, 1]};
160
- 'ArrowRight': [1, 0],
161
- 'ArrowUp': [0, -1],
162
- 'ArrowDown': [0, 1]
163
- };
164
156
 
157
+ // オブジェクトkeysの中身を一つずつ確認
165
- Object.entries(keys).forEach(([key, [x, y]]) => {
158
+ for (const [key, [x, y]] of Object.entries(keys)) {
159
+
160
+ // 押したキーとオブジェクトkeysのプロパティ名が一致するとき、
166
161
  if (event.key === key) {
162
+
167
163
  // 現在フォーカスしている操作ボタンの座標番号を取得
168
164
  const currentCoord = event.target.dataset.coord;
169
-
165
+
170
166
  // 移動先の座標番号を計算(矢印キー押下時、何もフォーカスしていなかったら移動先の座標は'0-0')
171
167
  const targetCoord = currentCoord ? currentCoord.replace(/(\d+)-(\d+)/, (_, px, py) => [Number(px) + x, Number(py) + y].join('-')) : '0-0';
172
-
168
+
173
169
  // 移動先の要素を取得する
174
170
  const [targetElem] = document.querySelectorAll(`[data-coord="${targetCoord}"]`);
175
-
171
+
176
172
  // その座標番号を持つ要素が存在していたら、その要素をフォーカスする
177
173
  if (targetElem) targetElem.focus();
174
+
175
+ // ここで繰り返し処理を完全に終了(残りのオブジェクトの中身はチェックされないので無駄な処理を少なく!)
176
+ return;
178
177
  }
179
- });
178
+ }
180
179
  }
181
180
  ```