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

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

ただいまの
回答率

90.76%

  • jQuery

    6342questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • パラメータ

    20questions

    関数やプログラム実行時に与える設定値をパラメータと呼びます。

グロナビのリンクがパラメーター付きURLの場合にクラスカレントを正常に動作させたい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 724

hogeta

score 1

前提・実現したいこと

カレント切替について相談があります。
下記サイトのjqueryを参考にグロナビのリンクにカレントクラスをつけました。
参考URL:https://d-suga.com/1935

しかし、うまくカレントされない箇所があります。
それはパラメーターで制御しているページです。
システムの仕様上、一つのファイルをパラメーターで切り替えて利用しています。

URLの後ろにパラメーターが付いているものはカレントしない

例)
スタンダード:hoge.html←どのページを開いてもこのリストにカレントが付く
Aタイプ  :hoge.html?A=1
Bタイプ  :hoge.html?B=1
Cタイプ  :hoge.html?C=1

この場合Aタイプ、Bタイプ、Cタイプのページを表示してもスタンダードページのリンクにカレントが付いてしまいます。

該当のソースコード

$(function(){
    $('#gNav li a').each(function(){
        var $href = $(this).attr('href');
        if(location.href.match($href)) {
            $(this).addClass('current');
        } else {
            $(this).removeClass('current');
        }
    });
});

試したこと

いろいろなカレントのスクリプトを探してみましたがパラメーターに対応しているものが無いので質問させていただきました。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

スタンダード:hoge.html
Aタイプ  :hoge.html?A=1
Bタイプ  :hoge.html?B=1
Cタイプ  :hoge.html?C=1

ちょっと質問を勘違いしていたみたなので、回答を書き直します。
下記のような場合で、「現在hoge.htmlの時」にすべてのナビゲーションリンクでMatchしてしまうのを解決したいということでしょうか?

■現在hoge.htmlの時

 ナビリンク       match()                      結果     一致    
 hoge.html       location.href.match($href)   Match    完全一致 
 hoge.html?A=1   location.href.match($href)   Match    前方一致 
 hoge.html?B=1   location.href.match($href)   Match    前方一致 
 hoge.html?C=1   location.href.match($href)   Match    前方一致 

■現在hoge.html?A=1の時

 ナビリンク       match()                      結果     一致    
 hoge.html       location.href.match($href)   ×               
 hoge.html?A=1   location.href.match($href)   Match    完全一致 
 hoge.html?B=1   location.href.match($href)   ×               
 hoge.html?C=1   location.href.match($href)   ×               

■現在hoge.html?B=1の時

 ナビリンク       match()                      結果     一致    
 hoge.html       location.href.match($href)   ×               
 hoge.html?A=1   location.href.match($href)   ×               
 hoge.html?B=1   location.href.match($href)   Match    完全一致 
 hoge.html?C=1   location.href.match($href)   ×               

■現在hoge.html?C=1の時

 ナビリンク       match()                      結果     一致    
 hoge.html       location.href.match($href)   ×               
 hoge.html?A=1   location.href.match($href)   ×               
 hoge.html?B=1   location.href.match($href)   ×               
 hoge.html?C=1   location.href.match($href)   Match    完全一致 

正規表現で完全一致するようにします。このとき、正規表現のメタ文字をエスケープしてからRegExp()で正規表現オブジェクトを作成します。

もうちょっとかしこい方法があるかもしれませんが、とりあえず下記でいかがでしょうか。
正規表現のメタ文字エスケープ.replace()部分は関数にしたほうがいいかもしれません。

$(function(){
    $('#gNav li a').each(function(){
        var $href = new RegExp('^'+ $(this).attr('href').replace(/([.*+?^=!:${}()|[\]\/\\])/g, "\\$1") +'$', 'i');
        if(location.href.match($href)) {
            $(this).addClass('current');
        } else {
            $(this).removeClass('current');
        }
    });
});

 追記

hoge.html?A=1などのクエリストリングありの時に、マッチしないというコメントを頂いたので追記しておきます。

多分考えられる原因は、他のクエリまたはハッシュが入っているということだと思います。下記の「&他のクエリ=1#ハッシュ」がなければ、普通に完全一致します。

■ページ
http://ドメイン/hoge.html?A=1&他のクエリ=1#ハッシュ

■ナビのリンク
http://ドメイン/hoge.html?A=1

JavaScriptでURLをパースしようとすると結構めんどくさいです。今回はクエリストリングをパースできる関数を作成してからクエリストリングを比較する方針にします。

下記コードはハッシュの違いを無視します。また、相対パスは考慮していません。

$(function(){
    function getQueryString (url)
    {
        if (url !== undefined && url === '') {
            return [];
        }

        var vars = [], hash;
        var path = url === undefined ? window.location.href : $('<a href="'+ url +'"/>').get(0).href;

        if (path.indexOf('?') >= 0 && path.length != path.indexOf('?') + 1) {
            var hashes = path.indexOf('#') >= 0
                ? path.slice(path.indexOf('?') + 1, path.indexOf('#')).split('&')
                : path.slice(path.indexOf('?') + 1).split('&');

            for(var i = 0; i < hashes.length; i++) {
                hash = hashes[i].split('=');
                vars.push(hash[0]);
                vars[hash[0]] = hash[1];
            }
        }

        return vars;    
    }

    function escapeRegExp (str)
    {
        return str.replace(/([.*+?^=!:${}()|[\]\/\\])/g, "\\$1");
    }


    //現在表示ページのURLのクエリストリングをパース
    var currentURI = location.href;

    // http://ドメイン/xxx.html? 最後が?のみのURI
    if (currentURI.length == currentURI.indexOf('?') + 1) {
        currentURI = currentURI.replace('?', '');
    }

    var currentQueries = getQueryString(currentURI);

    // http://ドメイン/xxx.html#hash 最後がハッシュのみのURI
    if (currentQueries.length == 0 && currentURI.indexOf('#')) {
        currentURI = currentURI.replace(/\#.*/, '');
    }

    //console.log(currentURI, currentQueries);

    //ナビゲーションリンクからすべての.currentクラスを削除してから.currentを追加
    $('#gNav li a')
        .removeClass('current')
        .each(function(){
            var nav = $(this).attr('href');
            var navQueries = getQueryString(nav);  //ナビゲーションhrefのクエリストリングをパース

            if (currentQueries.length > 0) {
                for (var i = 0; i < currentQueries.length; i++) {
                    //最初のクエリストリングのみ調査
                    if ($.inArray(currentQueries[i], navQueries) >= 0 && 
                        currentQueries[currentQueries[i]] == navQueries[currentQueries[i]]) 
                    {
                        $(this).addClass('current');
                        return false;  //break
                    }
                }
            } else {
                if (currentURI.match(new RegExp('^'+ escapeRegExp(nav) +'$', 'i'))) {
                    $(this).addClass('current');
                    return false;  //break
                }
            }
        });
});

すべてのクエリストリングがマッチしているかを調べる場合は下記にようにすれば調べられます。

    var currentFlag = false;

    //ナビゲーションリンクからすべての.currentクラスを削除してから.currentを追加
    $('#gNav li a')
        .removeClass('current')
        .each(function(){
            var nav = $(this).attr('href');
            var navQueries = getQueryString(nav);  //ナビゲーションhrefのクエリストリングをパース

            if (currentQueries.length > 0) {
                for (var i = 0; i < currentQueries.length; i++) {
                    //すべてのクエリストリングを調査
                    if ($.inArray(currentQueries[i], navQueries) >= 0 && 
                        currentQueries[currentQueries[i]] == navQueries[currentQueries[i]]) 
                    {
                        currentFlag = true;
                    } else {
                        return true;  //continue
                    }
                }
                if (currentFlag) {
                    $(this).addClass('current');
                    return false;  //break
                }
            } else {
                if (currentURI.match(new RegExp('^'+ escapeRegExp(nav) +'$', 'i'))) {
                    $(this).addClass('current');
                    return false;  //break
                }
            }
        });

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/11 18:09

    お返事が遅くなり申し訳ありません。こちらのプログラムを試させていただきましたが、うまくいきませんでした。もう少し私の方でも調べてみたいと思います。
    ご回答ありがとうございました。

    キャンセル

  • 2017/09/12 10:06 編集

    追加のお回答ありがとうございます。

    >>「現在hoge.htmlの時」にすべてのナビゲーションリンクでMatchしてしまうのを解決したいということでしょうか?

    そのとおりです!今まではhoge.htmlにアクセスした時に他ページのリンクもカレントされてしまいました。このスクリプトを導入したらこの現象は解決できました。ありがとうございます。

    あとは
    ・現在hoge.html?A=1の時
    ・現在hoge.html?B=1の時
    ・現在hoge.html?C=1の時

    に各リンクがカレントすると完璧なんですが・・・。
    パラメータが付いた部分はif文を使い分岐処理した方がいいのでしょうか。

    if(document.URL.match("A=1")) {
    $('#gNav li a[href*="A=1"]').addClass('current');
    }

    初心者の私にもわかりやすく教えていただきありがとうございます。
    正規表現などまだまだ勉強しなければいけないことが多いので大変勉強になりました。
    丁寧なご回答ありがとうございます。

    キャンセル

  • 2017/09/12 18:31

    ありがとうございます。無事に実装することができました。
    プログラムはおくが深いです。
    何度も修正していただきありがとうございます。

    キャンセル

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

  • ただいまの回答率 90.76%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • jQuery

    6342questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • パラメータ

    20questions

    関数やプログラム実行時に与える設定値をパラメータと呼びます。