アプリ版:「スタンプのみでお礼する」機能のリリースについて

現在のURLに/aaa/bbb/または/ddd/というパスが含まれていた場合、特定の要素(class)を非表示にする、というJSのコードを教えてほしいです。

いろいろ調べて自分なりに以下のコードを書いてみたのですが
上手く動作せずに困っています。初心者です。

if (location.pathname.includes('/aaa/bbb/') || location.pathname.includes('/ddd/')) {
const elements = document.querySelectorAll('.btn active');
for (let i = 0; i < elements.length; i++) {
elements[i].style.display = 'none';
}
}

特定の要素という部分というのは、
以下のようなボタンに付与されているクラスを消したいという意図になります。

<div class="btn">●●●</div>

↓ 一定の距離をスクロールするとactiveが付与されてボタンが表示される

<div class="btn active">●●●</div>

A 回答 (2件)

こんにちは



すでに適切な回答がされていますが・・

>上手く動作せずに困っています。初心者です。
とのことですので。

一番の原因は、既に指摘にある通りセレクタの指定と思われます。
ご提示のスクリプトの「 .btn active 」は「btnクラスを持つ要素の子要素でactiveという名称の要素」を意味することになります。(多分、そのような要素は存在しないでしょう)
「両方のクラスを持っている要素」を指定したければ「 .btn.active 」とすることが必要です。

ただし、この場合は「スクリプトを実行した際に、両方のクラスを有する要素」だけが対象になります。
>一定の距離をスクロールするとactiveが付与されて~
とありますが、その後に、他の要素や当該要素に再度activeクラスが付されることを防止するものではありません。
ですので、もしかすると質問者様の意図するところとは違っているかもしれません。
もしも、「btnクラスの要素は表示させないようにする」のであれば、対象は「 .btn 」ということになりそうです。

また、スクリプトを実行しているタイミングが不明ですけれど、ブラウザがHTMLの解釈を終えた時点で実行していないと、そもそも要素の取得ができません。
具体的には、当該<script>タグを</body>の直前に置いておくか、あるいはaddEventListener()などでDOM解釈終了後に実行するように指定しておくなどです。
他にも方法はありますが、bodyの閉じタグの直前に置くのが簡単と思います。

一方で、
>以下のようなボタンに付与されているクラスを消したい~
ご提示のスクリプトの
>elements[i].style.display = 'none';
は、クラスを削除するのではなく、要素のスタイル属性で「非表示」に設定するものです。
文言通り、「クラスを削除」したいのであれば、
 elements[i].classList.remove('active');
などとする必要があります。
あるいは、「非表示」設定ではなく、要素そのものをDOMから削除してしまうのであれば、
 elements[i].remove();
で可能です。

このあたりについて、質問者様の意図に合うように修正なされば、ご希望のようになるものと思います。



以下は、直接ご質問とは関係ありませんが、ついでながら・・・
・要素リストではforEachを使えますので、全部の要素をループするのなら、forループで改め行わなくても直接ループすることも可能です。
 document.querySelectorAll(~~).forEach(
  // 個々の要素の処理
 );
のような要領です。

・includesで文字列の有無を判定していますが、対象が複数になると面倒ですよね。
 (ご例示の場合は、ふたつなので、たいしたことはありませんが・・)
No1様が配列に設定しておいて繰り返す方法を示していらっしゃいますが、正規表現を利用する方法も考えられるでしょう。
 if( /\/(aaa\/bbb|ddd)\//.test(location.pathname))
とすることで、ご提示の条件判断と同様の判定が可能です。
(「/」のエスケープで「¥/」となっている関係で少々視認性が悪いですが、強力な手段として利用できると思います)


仮に「条件に合致したら、.btn要素を全部非表示設定にする」ので良ければ、上記を反映して記述すると
if( /\/(aaa\/bbb|ddd)\//.test(location.pathname))
document.querySelectorAll('.btn').forEach( e => {
e.style.display = 'none';
});
のようなスクリプトでも動作すると思います。
(</body>の直前に記述することに関しては同様です)
    • good
    • 0
この回答へのお礼

ご丁寧にありがとうございます。
早速、ご提案いただいたコードで試してみたのですが、
全ページのボタンが非表示になってしまいまして、まだ解決できておりません。度々で申し訳ありませんがご教授いただけないでしょうか。

実際に記述したコード
if( /\/(campaign_page\/seminar|forms)\//.test(location.pathname))
document.querySelectorAll('.bottom_btn').forEach( e => {
e.style.display = 'none';
});


デベロッパーツールのconsoleで確認したところ、
Uncaught SyntaxError: Invalid or unexpected tokenというエラーが表示されており、下記の記述に誤りがあるような指摘が返ってきました。

/\/(campaign_page\/seminar|forms)\//.test(location.pathname)

どこか間違っている部分があるのでしょうか?
また.testという部分はlocation.pathnameで取得した値を格納する変数という理解であってますでしょうか。

お礼日時:2023/05/10 14:58

querySelectorAll で使用するセレクター文法には、


特有の癖が有るのでお気を付けください。

誤: '.btn active' ← 空白は "子孫コンビネーター" と見なされる
正: '.btn.active'

参考)
https://developer.mozilla.org/ja/docs/Learn/CSS/ …

ご質問にある「~するとactiveが付与されて」ならば、
'.btn.active' だけを対象にしても中途半端になりますので、
もうすこし一般化して以下のように処理しては如何でしょうか。

<style>
/* .btn.active より優先されるルールを定義 */
.btn.active.inact { display: none; }
</style>
<script>
var ボタン消去 = elem => elem.classList.toggle("inact", true);
var 候補 = ["/aaa/bbb/", "/ddd/"];
var 削除条件 = 候補.some(x => location.pathname.includes(x));
if (削除条件) document.querySelectorAll('.btn').forEach(ボタン消去);
</script>
    • good
    • 0
この回答へのお礼

ご丁寧に回答いただきありがとうございます。
ご提案いただいたコードでも試してみたいと思います。

お礼日時:2023/04/27 23:31

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!