🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
WordPress

WordPressは、PHPで開発されているオープンソースのブログソフトウェアです。データベース管理システムにはMySQLを用いています。フリーのブログソフトウェアの中では最も人気が高く、PHPとHTMLを使って簡単にテンプレートをカスタマイズすることができます。

JavaScript

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

jQuery

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

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

2回答

1619閲覧

jsでajaxCompleteが2回実行されてしまう

Yariii

総合スコア61

WordPress

WordPressは、PHPで開発されているオープンソースのブログソフトウェアです。データベース管理システムにはMySQLを用いています。フリーのブログソフトウェアの中では最も人気が高く、PHPとHTMLを使って簡単にテンプレートをカスタマイズすることができます。

JavaScript

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

jQuery

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

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

0クリップ

投稿2021/01/23 10:15

編集2021/01/24 14:41

WPのwooccomerceを使っています。
背景として、カートページの商品数量を変更するのに、プラス、マイナスボタンのUIを作り、
それを押す度にカート内がajax更新され、数量が反映されます。しかし僕自身ajaxの知見はほぼなく、woocommerceの仕様で実行されているに過ぎません。

1回目のクリックイベントは問題ないのですが、ajax更新後にそのUIのclickイベントが機能しなくなったので、
「ajaxComplete」を使ったクリックイベントを追記して対処したのですが、なぜかajaxCompleteの中身が2回実行されてしまいます。

以下、「商品の数量変更UI」と「カート更新ボタン」です。
カート更新ボタンはデフォルトで用意されていましたが、

php

1///数量変更UI 2 3<form class="woocommerce-cart-form" action="<?php echo esc_url( wc_get_cart_url() ); ?>" method="post"> 4 <?php do_action( 'woocommerce_before_cart_table' ); ?> 5 6 <table class="shop_table shop_table_responsive cart woocommerce-cart-form__contents" cellspacing="0"> 7 <tbody> 8 <?php do_action( 'woocommerce_before_cart_contents' ); ?> 9 10<!-- ~~~~~~~~~~~~~~略~~~~~~~~~~~~~~ --> 11 12<!-- 商品の数量変更UI --> 13<td class="product-quantity" data-title="<?php esc_attr_e( 'Quantity', 'woocommerce' ); ?>"> 14 <div class="shop__num"> 15<!-- マイナスボタン --> 16 <div type="button" class="minus shop__num__count cart__count--down">-</div> 17 <?php 18 if ( $_product->is_sold_individually() ) { 19 $product_quantity = sprintf( '1 <input class="qty" type="hidden" name="cart[%s][qty]" value="1" />', $cart_item_key ); 20 } else { 21 $product_quantity = woocommerce_quantity_input( 22 array( 23 'input_name' => "cart[{$cart_item_key}][qty]", 24 'input_value' => $cart_item['quantity'], 25 'max_value' => $_product->get_max_purchase_quantity(), 26 'min_value' => '0', 27 'product_name' => $_product->get_name(), 28 ), 29 $_product, 30 false 31 ); 32 } 33 34 echo apply_filters( 'woocommerce_cart_item_quantity', $product_quantity, $cart_item_key, $cart_item ); // PHPCS: XSS ok. 35 ?> 36<!-- プラスボタン --> 37 <div type="button" class="plus shop__num__count cart__count--up">+</div> 38 </div> 39</td> 40 41<!-- ~~~~~~~~~~~~~~略~~~~~~~~~~~~~~ --> 42 43<!-- カートの中身変更ボタン --> 44<tr> 45 <td colspan="6" class="actions"> 46 47 <?php if ( wc_coupons_enabled() ) { ?> 48 <div class="coupon"> 49 <label for="coupon_code"><?php esc_html_e( 'Coupon:', 'woocommerce' ); ?></label> <input type="text" name="coupon_code" class="input-text" id="coupon_code" value="" placeholder="<?php esc_attr_e( 'Coupon code', 'woocommerce' ); ?>" /> <button type="submit" class="button" name="apply_coupon" value="<?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?>"><?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?></button> 50 <?php do_action( 'woocommerce_cart_coupon' ); ?> 51 </div> 52 <?php } ?> 53 54 <button type="submit" class="button" name="update_cart" value="<?php esc_attr_e( 'Update cart', 'woocommerce' ); ?>"><?php esc_html_e( 'Update cart', 'woocommerce' ); ?></button> 55 56 <?php do_action( 'woocommerce_cart_actions' ); ?> 57 58 <?php wp_nonce_field( 'woocommerce-cart', 'woocommerce-cart-nonce' ); ?> 59 </td> 60</tr> 61 62<!-- ~~~~~~~~~~~~~~略~~~~~~~~~~~~~~ --> 63 64<?php do_action( 'woocommerce_after_cart_contents' ); ?> 65 </tbody> 66 </table> 67<?php do_action( 'woocommerce_after_cart_table' ); ?> 68</form> 69

以下jsです。
「初期のクリックイベント」と「ajaxロード後のクリックイベント時」を書いています。

「ajax後のクリックイベント」が2回実行されるので、
2個プラス、2個マイナスみたいになってしまいます。

javascript

1 //初期クリックイベント 2 var $cart_count = $('.shop__num'), 3 $count_now = $('.shop .qty'), 4 $count_down = $('.cart__count--down'), 5 $count_up = $('.cart__count--up'); 6 7 var step = 1; 8 var min = 1; 9 var max = 100; 10 11 $count_down.each(function(){ 12 $(this).on('click', function() { 13 console.log('-'); 14 var num = $(this).next('.quantity').find('input').val(); 15 num--; 16 if ( num < min ) { 17 num = min; 18 }; 19 $(this).next('.quantity').find('input').val(num); 20 $('[name=update_cart]').prop({'disabled': false, 'aria-disabled': false }); 21 jQuery("[name='update_cart']").trigger("click"); 22 }); 23 }); 24 25 $count_up.on('click', function() { 26 console.log('+'); 27 var num = $(this).prev('.quantity').find('input').val(); 28 num++; 29 if ( max < num ) { 30 num = max; 31 }; 32 $(this).prev('.quantity').find('input').val(num); 33 $('[name=update_cart]').prop({'disabled': false, 'aria-disabled': false }); 34 jQuery("[name='update_cart']").trigger("click"); 35 }); 36 37 //ajaxロード後のイベント 38 jQuery(document).ajaxComplete(function(){ 39 console.log('ajax!!!'); 40 var $cart_count = $('.shop__num'), 41 $count_now = $('.shop .qty'), 42 $count_down = $('.cart__count--down'), 43 $count_up = $('.cart__count--up'); 44 45 var step = 1; 46 var min = 1; 47 var max = 100; 48 49 $count_down.each(function(){ 50 $(this).on('click', function() { 51 console.log('ajax--'); 52 var num = $(this).next('.quantity').find('input').val(); 53 num --; 54 if ( num < min ) { 55 num = min; 56 }; 57 console.log('ajaxマイナスした');////1クリックでこいつが2回logされる。 58 $(this).next('.quantity').find('input').val(num); 59 $('[name=update_cart]').prop({'disabled': false, 'aria-disabled': false }); 60 jQuery("[name='update_cart']").trigger("click"); 61 }); 62 return false; 63 }); 64 65 $count_up.on('click', function() { 66 console.log('ajax++'); 67 var num = $(this).prev('.quantity').find('input').val(); 68 num ++; 69 if ( max < num ) { 70 num = max; 71 }; 72 console.log('ajaxプラスした');////1クリックでこいつが2回logされる。 73 $(this).prev('.quantity').find('input').val(num); 74 $('[name=update_cart]').prop({'disabled': false, 'aria-disabled': false }); 75 jQuery("[name='update_cart']").trigger("click"); 76 return false; 77 }); 78 }); 79

以上がコードになります、なぜ「ajaxロード後のイベント」の中身は2回実行されてしまうのでしょうか?
ご教授いただけると幸いです。(情報の不足があればおっしゃってください)

よろしくお願いします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

umau

2021/01/24 10:23

form タグと、送信処理を行っているところのスクリプトを示してもらえますか。
Yariii

2021/01/24 14:50

formタグ追記しました。送信処理は、<!--カートの中身変更ボタン-->にあるsubmitタイプのbuttonが担っているようです。
umau

2021/01/24 15:36

送信処理はプラグインがイベント追加してるのかもしれないですね。submit押下だけなら普通にformのpost処理になってAjaxじゃない事になりますし。wooccomerceを知らないので分からないですが。 送信処理側の可能性は見切れないので無視することにして、見て分かる内容で回答してみます。
guest

回答2

0

自己解決

https://johnhashim.com/posts/add-plus-and-minus-ajax-buttons-to-woocommerce-quantity-inputs/

こちらの記事を参考に解決できました。ちょっと別のアプローチです。
woocommerceのglobalフォルダに、数量変更する共通UIがあり、そこに+-ボタンを作成するイメージです。
jQueryは記事とおりfunctions.phpに追記しました。(woocommerceの場合phpでフックをかけないとjsが理想通り動かないのかな...)

投稿2021/01/25 04:43

Yariii

総合スコア61

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ajaxCompleteの中と外の2カ所でクリックイベントが付けられているので、一度ajaxCompleteの中を通るとクリックイベントが2個になります。

で、そのどちらのイベント関数も最後にupdate_cart ボタンのクリックをトリガーしています。
1クリックで2個とも実行され、2回updaete_cartがトリガー実行されてしまう、という事に思えます。

※通常、標準のaddEventListnerは同じイベントは1つしか付けれないので、clickイベントを2回付けると上書きされて1個になるんですが、jQueryのon()でのイベント追加は複数バインドが可能で、バインドした順にリスナーが呼び出されます。(jQueryが内部にリスナー関数を保持する)

ajaxComplete内でのイベント追加が不要なんじゃないでしょうか。

投稿2021/01/24 15:37

umau

総合スコア831

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Yariii

2021/01/25 04:38

ajaxロードされたあと、なぜか外側のjsイベントが効かなくなったんですよね、、なのでajaxCompleteの内側にイベント処理を追記したのですが、logを使ってコンソール確認してみるとやはり外側のクリックイベントは2回目以降は効いていないみたいです。 ちょっと全く別の代替案ですが、理想の動きにできた方法があったので、今回はこちらで解決済みにさせていただこうと思います。 ご回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問