リクエスト詳細
🐛 バグ報告
対応完了
対象アプリ: CrossCraft クロスワードパズルメーカー
list.php のクリア状態表示でquerySelectorがcard内ではなくdocument全体を参照しバグが発生
1. 不具合の内容
pages/list.php のJavaScript内で、各パズルカードのクリア状態を表示しようとしているが、以下のコードにバグがある。
```javascript
const state = document.querySelector('.cleared-state'); // ← card 内ではなく document 全体から取得
const item = cleared.find(function(c){ return c.code === code; });
if (item) {
card.querySelector('.cleared-state').innerHTML = ...;
}
```
`state` 変数は `document.querySelector('.cleared-state')` で宣言されており、カード内要素ではなくページ上の **最初の `.cleared-state` 要素** を常に参照している(しかもその後 `state` は使われず `card.querySelector` を使っているため `state` 変数自体は完全に無意味な行となっている)。
これにより:
- `state` という変数の宣言・代入が毎ループで最初のカードの要素を上書き参照し続ける(意味のない処理)
- さらに重大なのは、`forEach` ループ内で `const state = ...` と **`const` で宣言しているにもかかわらず** ループ内で再宣言しているため、**厳格モード(または一部のブラウザ)では実行時エラーになる可能性がある**
- クリア済みパズルが複数ある場合、意図通りに各カードへバッジが表示されないケースが生じる
2. 根拠・発生条件
list.php 抜粋:
```javascript
document.querySelectorAll('.puzzle-card').forEach(function(card) {
const code = card.dataset.code;
const state = document.querySelector('.cleared-state'); // ← ここが問題
const item = cleared.find(function(c){ return c.code === code; });
if (item) {
card.querySelector('.cleared-state').innerHTML =
'<span class="cleared-badge">✓ クリア ' + escH(item.time || '') + '</span>';
}
});
```
`const state` は `function` スコープではなくブロックスコープだが、`forEach` のコールバック関数内で毎回 `const` 宣言されるため問題は起きないが、`state` 変数が全く使われず `document.querySelector` を無駄に呼び出している。実際の表示処理は `card.querySelector` で行われているため、**`localStorage` にクリア記録があっても `item.time` が空文字の場合にバッジ内容が「✓ クリア 」となる**(末尾スペース)ほか、`card.querySelector('.cleared-state')` が `null` を返した場合(HTMLに `.cleared-state` 要素がない等)に `Cannot set properties of null` の **JavaScriptエラーが発生し、以降のカードへのクリア表示が全て停止する**。
実際、HTMLテンプレート側を見ると `<div class="cleared-state" style="margin-top:6px"></div>` は各カード内に存在するが、`const state = document.querySelector('.cleared-state')` はページ内の最初の要素を取得しており、この変数が誤って使われた場合は最初のカードだけにクリアバッジが集中する潜在バグとなる。
3. 期待動作
- 各 `.puzzle-card` 内の `.cleared-state` 要素に対して、そのカードのコードに対応するクリア記録があれば正しくバッジを表示する
- エラーが発生せず全カードが正常に処理される
4. 修正方針
不要な `const state = document.querySelector('.cleared-state');` 行を削除し、以下のように修正する:
```javascript
document.querySelectorAll('.puzzle-card').forEach(function(card) {
const code = card.dataset.code;
const item = cleared.find(function(c){ return c.code === code; });
if (item) {
const stateEl = card.querySelector('.cleared-state');
if (stateEl) {
stateEl.innerHTML =
'<span class="cleared-badge">✓ クリア ' + escH(item.time || '') + '</span>';
}
}
});
```
`card.querySelector('.cleared-state')` の結果を `null` チェックしてから `innerHTML` を設定することで、要素が存在しない場合のエラーも防ぐ。
pages/list.php のJavaScript内で、各パズルカードのクリア状態を表示しようとしているが、以下のコードにバグがある。
```javascript
const state = document.querySelector('.cleared-state'); // ← card 内ではなく document 全体から取得
const item = cleared.find(function(c){ return c.code === code; });
if (item) {
card.querySelector('.cleared-state').innerHTML = ...;
}
```
`state` 変数は `document.querySelector('.cleared-state')` で宣言されており、カード内要素ではなくページ上の **最初の `.cleared-state` 要素** を常に参照している(しかもその後 `state` は使われず `card.querySelector` を使っているため `state` 変数自体は完全に無意味な行となっている)。
これにより:
- `state` という変数の宣言・代入が毎ループで最初のカードの要素を上書き参照し続ける(意味のない処理)
- さらに重大なのは、`forEach` ループ内で `const state = ...` と **`const` で宣言しているにもかかわらず** ループ内で再宣言しているため、**厳格モード(または一部のブラウザ)では実行時エラーになる可能性がある**
- クリア済みパズルが複数ある場合、意図通りに各カードへバッジが表示されないケースが生じる
2. 根拠・発生条件
list.php 抜粋:
```javascript
document.querySelectorAll('.puzzle-card').forEach(function(card) {
const code = card.dataset.code;
const state = document.querySelector('.cleared-state'); // ← ここが問題
const item = cleared.find(function(c){ return c.code === code; });
if (item) {
card.querySelector('.cleared-state').innerHTML =
'<span class="cleared-badge">✓ クリア ' + escH(item.time || '') + '</span>';
}
});
```
`const state` は `function` スコープではなくブロックスコープだが、`forEach` のコールバック関数内で毎回 `const` 宣言されるため問題は起きないが、`state` 変数が全く使われず `document.querySelector` を無駄に呼び出している。実際の表示処理は `card.querySelector` で行われているため、**`localStorage` にクリア記録があっても `item.time` が空文字の場合にバッジ内容が「✓ クリア 」となる**(末尾スペース)ほか、`card.querySelector('.cleared-state')` が `null` を返した場合(HTMLに `.cleared-state` 要素がない等)に `Cannot set properties of null` の **JavaScriptエラーが発生し、以降のカードへのクリア表示が全て停止する**。
実際、HTMLテンプレート側を見ると `<div class="cleared-state" style="margin-top:6px"></div>` は各カード内に存在するが、`const state = document.querySelector('.cleared-state')` はページ内の最初の要素を取得しており、この変数が誤って使われた場合は最初のカードだけにクリアバッジが集中する潜在バグとなる。
3. 期待動作
- 各 `.puzzle-card` 内の `.cleared-state` 要素に対して、そのカードのコードに対応するクリア記録があれば正しくバッジを表示する
- エラーが発生せず全カードが正常に処理される
4. 修正方針
不要な `const state = document.querySelector('.cleared-state');` 行を削除し、以下のように修正する:
```javascript
document.querySelectorAll('.puzzle-card').forEach(function(card) {
const code = card.dataset.code;
const item = cleared.find(function(c){ return c.code === code; });
if (item) {
const stateEl = card.querySelector('.cleared-state');
if (stateEl) {
stateEl.innerHTML =
'<span class="cleared-badge">✓ クリア ' + escH(item.time || '') + '</span>';
}
}
});
```
`card.querySelector('.cleared-state')` の結果を `null` チェックしてから `innerHTML` を設定することで、要素が存在しない場合のエラーも防ぐ。
💬 返信 (3)
🛠 開発を開始しました (バグ修正 (crosscraft))
ご要望ありがとうございます。AI 開発ワーカーが実装を開始します。
通常 5〜30 分で Pull Request を作成し、レビュー後にリリースされます。
ご要望ありがとうございます。AI 開発ワーカーが実装を開始します。
通常 5〜30 分で Pull Request を作成し、レビュー後にリリースされます。
📝 開発が完了しました
ご要望いただいた内容の実装が完了し、最終チェック段階に入りました。
レビュー (自動) → リリース、の流れで進みます。
もう少々お待ちください。
ご要望いただいた内容の実装が完了し、最終チェック段階に入りました。
レビュー (自動) → リリース、の流れで進みます。
もう少々お待ちください。
✅ リリース完了のお知らせ
ご要望いただいた「CrossCraft クロスワードパズルメーカー」を実装し、リリースいたしました。
【ご利用方法】
ダッシュボード: https://www.aiapps.jp/?action=dashboard
アプリ詳細: https://www.aiapps.jp/apps/show.php?slug=crosscraft
デモ環境は 1 時間以内に自動構築されます:
https://www.aiapps.jp/demo/crosscraft/
ご利用ありがとうございます!
ご要望いただいた「CrossCraft クロスワードパズルメーカー」を実装し、リリースいたしました。
【ご利用方法】
ダッシュボード: https://www.aiapps.jp/?action=dashboard
アプリ詳細: https://www.aiapps.jp/apps/show.php?slug=crosscraft
デモ環境は 1 時間以内に自動構築されます:
https://www.aiapps.jp/demo/crosscraft/
ご利用ありがとうございます!
Echo
Iris