質問するログイン新規登録

回答編集履歴

2

think49さんの意見反映

2016/02/13 06:34

投稿

miyabi-sun
miyabi-sun

スコア21553

answer CHANGED
@@ -8,25 +8,111 @@
8
8
  - Bはsubmitイベントが実行されたタイミングで動作確定、つまりAの戻り値なんて関係なく実行される
9
9
 
10
10
  # 対策
11
-
12
11
  これ読んでください。
13
12
  [http://www.webcyou.com/?p=4528](http://www.webcyou.com/?p=4528)
14
13
 
15
- jQuery内では`this.stopPropagation()`で良いので、
14
+ ## jQueryを使った場合→無理
16
- プラグインAの中身を下記のように変更すれば意図通りの動作になります。
17
15
 
16
+ プラグインAの中身を下記のように変更すれば意図通りの動作になるはず…
17
+ ですが、think49さんに指摘&調査して頂いた内容により上手く動作せず、やはり確認ダイアログは表示されてしまいます。
18
+
18
- ```
19
+ ```plugin_A.js
19
20
  (function($) {
20
21
  $.fn.plugin_A = function() {
21
- this.submit(function() {
22
+ this.submit(function(event) { // ここにevent引数を用意
22
23
  if ($("input", this).val()) {
23
24
  $(".errMsg").hide();
24
25
  }else{
25
26
  $(".errMsg").show();
26
- this.stopPropagation(); // こう差込む
27
+ event.stopPropagation(); // これで良いはず…正常動作ないだと!?
27
28
  }
28
29
  return false;//ブラウザのsubmitイベントの中止
29
30
  });
30
31
  return this;
31
32
  };
32
- ```
33
+ ```
34
+
35
+ ## addEventListenerを使った場合→無理
36
+
37
+ 全く同じロジックを、addEventListnerを使って実装します。
38
+ 一度 `this.each` をかませて置くことで内部のthisはDomエレメントになるので…
39
+
40
+ ```plugin_A.js
41
+ (function($) {
42
+ $.fn.plugin_A = function() {
43
+ this.each(function() {
44
+ this.addEventListener('submit', function(event){
45
+ console.log("plugin_A submit!");
46
+ if ($("input", this).val()) {
47
+ $(".errMsg").hide();
48
+ } else {
49
+ $(".errMsg").show();
50
+ event.stopPropagation();
51
+ event.preventDefault();
52
+ return false;
53
+ }
54
+ }, false);
55
+ });
56
+ return this;
57
+ };
58
+ })(jQuery);
59
+ ```
60
+
61
+ ```plugin_B.js
62
+ (function($) {
63
+ $.fn.plugin_B = function() {
64
+ this.each(function() {
65
+ this.addEventListener('submit', function(event){
66
+ console.log('plugin_B submit!');
67
+ return confirm('送信しますか?');
68
+ }, false);
69
+ });
70
+ return this;
71
+ };
72
+ })(jQuery);
73
+ ```
74
+
75
+ はい、エラーメッセージと、確認ダイアログが出たので失敗です。
76
+
77
+ ## click -> submitのイベント伝播に変更
78
+
79
+ 更にプラグインAのネストが進んで超キモくなりましたが、
80
+ なんとか達成できました。
81
+
82
+ ```plugin_A.js
83
+ (function($) {
84
+ $.fn.plugin_A = function() {
85
+ this.each(function(){
86
+ var $self = $(this);
87
+ $self.find('button').each(function(){
88
+ this.addEventListener('click', function(event){
89
+ console.log("plugin_A submit!");
90
+ if ($("input", $self).val()) {
91
+ $(".errMsg").hide();
92
+ } else {
93
+ $(".errMsg").show();
94
+ // event.stopPropagation();
95
+ event.preventDefault();
96
+ return false;
97
+ }
98
+ }, false);
99
+ });
100
+ });
101
+ return this;
102
+ };
103
+ })(jQuery);
104
+ ```
105
+
106
+ Input要素内でEnterを押してサブミットさせたらどうなるかと思って試しましたが、
107
+ サブミットボタンをクリックした扱いになって意図どおりの動作になります。
108
+
109
+ # 結論
110
+
111
+ submit -> submit のイベント伝播を食い止める方法は不可能なようです。
112
+ click -> submit にすることで可能でした。
113
+
114
+ ---
115
+
116
+ 追記:
117
+ 誤りがあったので修正しています。
118
+ think49さんに指摘&調査していただいた内容を元に解決法を別口で記載しています。

1

調整

2016/02/13 06:34

投稿

miyabi-sun
miyabi-sun

スコア21553

answer CHANGED
@@ -1,18 +1,19 @@
1
- 質問文段階書かれている内容と動作自体は正しいで
1
+ JavaScriptに関するイベント伝播関係のミスが原因です
2
- 単純にそう書けばこうなるよねという話で…
3
2
 
4
3
  # 解説
5
4
 
6
5
  - プラグインAとBがそれぞれフォームのサブミットに対してイベント登録
7
- - プラグインAが先に登録されたので、「確認する」ボタンを押された時に先に実行される
6
+ - 「確認する」ボタンを押された時にsubmitイベントが発行される
7
+ - イベントの処理順番は登録順、つまりA→Bの順
8
- - サブミットイベントが発生しているので、プラグインAの結果によらず、プラグインBが実行される
8
+ - Bはsubmitイベントが実行されたタグで動作確定、つまりAの戻り値なんて関係なく実行される
9
9
 
10
10
  # 対策
11
11
 
12
- 手抜きでごめんなさい、これ読んでください。
12
+ これ読んでください。
13
13
  [http://www.webcyou.com/?p=4528](http://www.webcyou.com/?p=4528)
14
14
 
15
+ jQuery内では`this.stopPropagation()`で良いので、
15
- プラグインAの中身をう変更してください
16
+ プラグインAの中身を下記のよ変更すれば意図通りの動作になります
16
17
 
17
18
  ```
18
19
  (function($) {