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

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

ただいまの
回答率

90.42%

  • PHP

    21853questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • JavaScript

    18061questions

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

  • jQuery

    7269questions

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

既に定義済のclickイベントの前にチェック処理を追加したい(jQuery Bootpag)

解決済

回答 2

投稿

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

ms5025

score 162

前提・実現したいこと

■やりたいこと
既に定義済のclickイベントの前に独自のチェックファンクションを差し込み、
チェック不可なら定義済のclickイベントは起こさないようにしたい

■内容
現在jQuery Bootpagを使用してwebページのページング処理を行っています。
ページには商品画像、商品名、商品数(セレクトボックス)が列挙されており
1ページに表示できるmax商品数が決まっている、よくある画面です。
ページ切り替え時、ajaxで次ページのデータを取得しています。

今回、ページ切り替え時にセレクトボックスの値が選択されている場合、
「現在選択されている商品はクリアされますが次ページへ遷移してもいいか?」といった
ようなconfirmダイアログを表示する仕様が追加となりました。
キャンセルが押下されればそのままステイ、OKが押下されると次ページ遷移します。

発生している問題・エラーメッセージ

今まではjquery.bootpagの次ページ遷移処理(クリックされたページの<liタグにactiveクラスが追加されるような処理)が行われた後、
次ページを読み混むajax処理(自作のclickイベント①)が走って動いていました。

今回上記の仕様を追加するにあたり、
自作のclickイベント①側から、confirmダイアログでキャンセルが押下された場合、
jquery.bootpagの次ページ遷移clickイベントをキャンセルしたいのですが
jquery.bootpagの次ページ遷移処理が先に走る為、うまくいきません

jsの読み込み順序を変えても、jquery.bootpagのclickイベントのほうが先に走るようです。

↓ 自作のclickイベント①

  
    // ページャーがクリックされたら
    $('.bootpag').on('click', function (event, num) {

     // okなら次のページ取得
        var num = $(this).find('.active').data('lp');
        // データ取得して次ページ表示
        dispPage(num);

    });

以下がgitに上がってるjquery.bootpagのソースの一部です。

(function ($, window) {

    $.fn.bootpag = function (options) {

        var $owner = this,
                settings = $.extend({
                    total: 0,
                    page: 1,
                    maxVisible: null,
                    leaps: true,
                    href: 'javascript:void(0);',
                    hrefVariable: '{{number}}',
                    firstLastUse: false,
                    first: '<span aria-hidden="true">&larr;</span>',
                    last: '<span aria-hidden="true">&rarr;</span>',
                    wrapClass: 'pagination',
                    activeClass: 'active',
                    disabledClass: 'disabled',
                    nextClass: 'next',
                    prevClass: 'prev',
                    lastClass: 'last',
                    firstClass: 'first'
                },
                        $owner.data('settings') || {},
                        options || {});

        if (settings.total <= 0)
            return this;

        if (!$.isNumeric(settings.maxVisible) && !settings.maxVisible) {
            settings.maxVisible = parseInt(settings.total, 10);
        }


        settings.next = '&raquo;次';
        settings.prev = '&laquo;前';

//        settings.next = '&raquo;';
//        settings.prev = '&laquo;';
//        settings.first = '&laquo;最初';
//        settings.last = '&raquo;最後';

        $owner.data('settings', settings);

        function renderPage($bootpag, page) {
            page = parseInt(page, 10);
            var lp,
                    maxV = settings.maxVisible == 0 ? 1 : settings.maxVisible,
                    step = settings.maxVisible == 1 ? 0 : 1,
                    vis = Math.floor((page - 1) / maxV) * maxV,
                    $page = $bootpag.find('li');
            settings.page = page = page < 0 ? 0 : page > settings.total ? settings.total : page;
            $page.removeClass(settings.activeClass);
            lp = page - 1 < 1 ? 1 :
                    settings.leaps && page - 1 >= settings.maxVisible ?
                    Math.floor((page - 1) / maxV) * maxV : page - 1;

            if (settings.firstLastUse) {
                $page
                        .first()
                        .toggleClass(settings.disabledClass, page === 1);
            }

            var lfirst = $page.first();
            if (settings.firstLastUse) {
                lfirst = lfirst.next();
            }

            lfirst
                    .toggleClass(settings.disabledClass, page === 1)
                    .attr('data-lp', lp)
                    .find('a').attr('href', href(lp));

            var step = settings.maxVisible == 1 ? 0 : 1;

            lp = page + 1 > settings.total ? settings.total :
                    settings.leaps && page + 1 <= settings.total - settings.maxVisible ?
                    vis + settings.maxVisible + step : page + 1;

            var llast = $page.last();
            if (settings.firstLastUse) {
                llast = llast.prev();
            }

            llast
                    .toggleClass(settings.disabledClass, page === settings.total)
                    .attr('data-lp', lp)
                    .find('a').attr('href', href(lp));

            $page
                    .last()
                    .toggleClass(settings.disabledClass, page === settings.total);


            var $currPage = $page.filter('[data-lp=' + page + ']');

            var clist = "." + [settings.nextClass,
                settings.prevClass,
                settings.firstClass,
                settings.lastClass].join(",.");
            if (!$currPage.not(clist).length) {
                var d = page <= vis ? -settings.maxVisible : 0;
                $page.not(clist).each(function (index) {
                    lp = index + 1 + vis + d;
                    $(this)
                            .attr('data-lp', lp)
                            .toggle(lp <= settings.total)
                            .find('a').html(lp).attr('href', href(lp));
                });
                $currPage = $page.filter('[data-lp=' + page + ']');
            }
            $currPage.not(clist).addClass(settings.activeClass);
            $owner.data('settings', settings);
        }

        function href(c) {

            return settings.href.replace(settings.hrefVariable, c);
        }

        return this.each(function () {

            var $bootpag, lp, me = $(this),
                    p = ['<ul class="', settings.wrapClass, ' bootpag">'];

            if (settings.firstLastUse) {
                p = p.concat(['<li data-lp="1" class="', settings.firstClass,
                    '"><a href="', href(1), '">', settings.first, '</a></li>']);
            }
            if (settings.prev) {
                p = p.concat(['<li data-lp="1" class="', settings.prevClass,
                    '"><a href="', href(1), '">', settings.prev, '</a></li>']);
            }
            for (var c = 1; c <= Math.min(settings.total, settings.maxVisible); c++) {
                p = p.concat(['<li data-lp="', c, '"><a href="', href(c), '">', c, '</a></li>']);
            }
            if (settings.next) {
                lp = settings.leaps && settings.total > settings.maxVisible
                        ? Math.min(settings.maxVisible + 1, settings.total) : 2;
                p = p.concat(['<li data-lp="', lp, '" class="',
                    settings.nextClass, '"><a href="', href(lp),
                    '">', settings.next, '</a></li>']);
            }
            if (settings.firstLastUse) {
                p = p.concat(['<li data-lp="', settings.total, '" class="last"><a href="',
                    href(settings.total), '">', settings.last, '</a></li>']);
            }
            p.push('</ul>');
            me.find('ul.bootpag').remove();
            me.append(p.join(''));
            $bootpag = me.find('ul.bootpag');
       
      //★★★ページャーでページをクリックしたらここが先に走るようです
            me.find('li').click(function paginationClick() {

                var me = $(this);
                if (me.hasClass(settings.disabledClass) || me.hasClass(settings.activeClass)) {
                    return;
                }
                var page = parseInt(me.attr('data-lp'), 10);
                $owner.find('ul.bootpag').each(function () {
                    renderPage($(this), page);
                });
                return;
                $owner.trigger('page', page);
            });
            renderPage($bootpag, settings.page);
        });
    }

})(jQuery, window);

ページャーのhtmlです
classにactiveがついているのが現在のページです

<p id="demo_top" class="demo_top">
    <ul class="pagination bootpag">
        <li data-lp="1" class="firszt">
            <a href="javascript:void(0);">«</a>
        </li>
        <li data-lp="2" class="prev">
            <a href="javascript:void(0);">«前</a>
        </li>
        <li data-lp="1" class="">
            <a href="javascript:void(0);">1</a>
        </li>
        <li data-lp="2" class="">
            <a href="javascript:void(0);">2</a>
        </li>
        <li data-lp="3" class="active">
            <a href="javascript:void(0);">3</a>
        </li>
        <li data-lp="4" class="next">
            <a href="javascript:void(0);">»次</a>
        </li>
        <li data-lp="78" class="last">
            <a href="javascript:void(0);">»</a>
        </li>
    </ul>
</p>

試したこと

現在のページをhiddenで退避しておき、チェック処理がfalseの場合、
現在のページを再度activeに再度設定しなおすというのも考えたのですがせっかくjquery.bootpagのjsで一括設定しているのにわざわざ手動でclass切り替えをするのもどうなんだろうと思い質問してみました。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+3

的外れかもしれませんが、document.addEventListenerで処理をいれると
jQueryより先に処理がされます

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
$(function(){
  $('.bootpage').on('click',function(){
    console.log($(this).text());
  });
});
</script>
<script>
document.addEventListener('click',function(e){
  e.stopPropagation();
  var t=e.target;
  if(t.classList.contains("bootpage")){
    console.log('check');
    $(t).trigger('click');
  }
},true);
</script>
<div class="bootpage">test1</div>
<div class="bootpage">test2</div>
<div class="bootpage">test3</div>


上記の通りcheckは2度走りますが、jQueryは1度だけ実行されます
うまく使えばclick前のチェック処理につかえるかもしれません

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/01/15 11:24

    ありがとうございます!こちらの方法でclickイベント前にチェックを差し込むことができました!
    jqueryにあまり詳しくなくて困っていました。ありがとうございます。

    なぜか.classList.containsが使えなくて、以下の方法にしたのですが
    書き方としておかしい所があればまたコメントでもいいのでご指摘いただけますか?

    document.addEventListener('click', function (e) {

    e.stopPropagation();
    var t = e.target;
    var node = t.parentNode.parentNode;

    if ($(node).hasClass('bootpag')) {

    // 選択中商品チェック
    if (checkSelectItem())
    {
    $(t).trigger('click');

    }
    }
    }, true);

    キャンセル

  • 2019/01/15 11:26

    ああ、確かにそうですね
    jQuery自体は読み込んでいるので、hasClassで十分だと思います

    キャンセル

  • 2019/01/15 13:35

    ありがとうございます!助かりました!ただこのやり方で既存のチェックボックスが動かなくなってしまいました。
    どうやら
    $(t).trigger('click');
    でチェックボックスの値がクリックで変わる前の値がとれてしまい、
    それでチェックボックスのon/ofが正常に動かなくなってしまったようで・・・

    キャンセル

  • 2019/01/15 13:40

    e.stopPropagation()をif節の中にいれてください
    そうすれば関係ないタグに影響を与えなくなるでしょう

    キャンセル

  • 2019/01/15 13:47

    ありがとうございます。はい、そう思ってif文内に入れてみたんですが、それでも上記のとおり、チェックボックスの値がとれません。。。

    キャンセル

  • 2019/01/15 13:48

    キャッシュもちゃんと削除しました

    キャンセル

  • 2019/01/15 13:51

    命題のソースでは判断できません

    当初言われていた.bootpageとも内容が違うようです
    チェックボックスはどこにあって、どう動作するのが正しいのかも
    再度命題に追記してください

    キャンセル

  • 2019/01/15 13:52

    了解しました。ありがとうございます。

    キャンセル

+1

バブリングフェーズではなく、キャプチャフェーズでイベントを捕まえれば、先に実行できるかもしれません。ただ、jQueryを介したイベントの設定では難しいかと思います。
DOMイベントのキャプチャ/バブリングを整理する 〜 JSおくのほそ道 #017 - Qiita

また、検証していませんが、jQueryのイベント実行順は、内部で変更することが可能なようですね。
jQuery のイベントハンドラの順番を入れ替える - Qiita
記事中にもあるように『jQuery の内部用 API を使うので将来動かなくなる』可能性はあると思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/01/11 12:24

    ありがとうございます。
    jQuery のイベントハンドラの順番を入れ替える - Qiita
    は私も拝見しました。
    しかしこれをするぐらいなら 「試したこと」に書いてある
    現在のページをhiddenで退避しておく案のほうがいいのかなと個人的には思うですが
    どうなのでしょうか・・・

    キャンセル

  • 2019/01/11 12:30

    そうかもしれませんね。
    私なら、useCapture を試すと思います。

    キャンセル

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

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

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

  • PHP

    21853questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • JavaScript

    18061questions

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

  • jQuery

    7269questions

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