「jquery ui spinner」と打ち込むだけで候補にあがる「change event」

すなわちよくあるしつもんてことだ。

そもそも「変更イベントに逐一反応する」ことの是非は今は問わない。やりたいとして。

もともと単なる <input type="text"> を使って、しかも数値をあてにするフィールドなのにバリデートもサボってた状態から、「バリデート問題も操作性問題も、スピナー使っちゃえば一発っしょ」と Spinner に乗り換えたと。ラクチンだねっ、と喜んでいたわけだけれど。

スピンボタンとカーソルキー操作(PGUP/PGDNも)って、change はトリガーしてくれんのね。いつものごとく StackOverflow よりめぼしい解2つ:

1 $('.ui-spinner-button').click(function() {
2     $(this).siblings('input').change();
3 });

いっけんするとめっちゃクールに見えるけどこれは「多分目的のことと違う」。わかるよね。ボタンにしか反応してないもん、カーソルキー操作に反応しない。もう一つの方がワタシには良さげだ(※2018-02-28追記参照):

ワタシのヤツの場合
 1 $(".posint-spinner").spinner({
 2     min: 0,
 3     spin: function(event, ui) {
 4         $(this).change();
 5     }
 6 });
 7 $(".posnut-spinner").spinner({
 8     min: 1,
 9     spin: function(event, ui) {
10         $(this).change();
11     }
12 });
13 // (多くのスピナーを一気に作りたかったので種類別に class をつけてそれに対してやってる。)

一応。「「変更イベントに逐一反応する」ことの是非」について。最初から真剣にそうすべきかどうか悩むべし、というほどのものではないけれど、半々くらいの確率で「適用ボタンのような明示的なユーザ操作をトリガーにした方が快適」ということが起こる。UI 実装(設計)経験豊富な人には釈迦に説法だけどな。

「使い勝手」についてもそうだけれど、「性能問題」を発火しちゃうことも多いのでね、余計に注意。特に開発初期なんかは圧倒的に「「変更イベントに逐一反応する」方が快適で良い」ように感じちゃうんで、大抵ついつい安直にそうしちゃうんだけど、「単体テスト」程度の浅いフェーズで使ってるデータ量のつもりで「現実のデータ量」に適用して初めて青ざめる、なんてのは良くあることですわよ。


2018-02-28追記

これ、ダメ…
 1 $(".posint-spinner").spinner({
 2     min: 0,
 3     spin: function(event, ui) {
 4         $(this).change();
 5     }
 6 });
 7 $(".posnut-spinner").spinner({
 8     min: 1,
 9     spin: function(event, ui) {
10         $(this).change();
11     }
12 });
13 // (多くのスピナーを一気に作りたかったので種類別に class をつけてそれに対してやってる。)

いっけんするとそれっぽく動くんだけれど、以下で破綻:

ワンテンポ遅れた値しか取れんの
1 $(".posnut-spinner").on("change", function () {
2     // popularity-min-thr は class でなくてコントロールの実際の id
3     console.log($("#popularity-min-thr").val());
4 });

うーん。StackOverflow 回答でこれで困ってるようなことは誰も言ってない気がするが…。とりあえず:

苦しい肉
 1 $(".posint-spinner").spinner({
 2     min: 0,
 3     spin: function(event, ui) {
 4         let _this = this;
 5         setTimeout(function () {
 6             $(_this).change();
 7         }, 20);
 8     }
 9 });
10 $(".posnut-spinner").spinner({
11     min: 1,
12     spin: function(event, ui) {
13         let _this = this;
14         setTimeout(function () {
15             $(_this).change();
16         }, 20);
17     }
18 });
19 // (多くのスピナーを一気に作りたかったので種類別に class をつけてそれに対してやってる。)

一応これで目的のものにはなるが、当然こんなん「下手すりゃイタチごっこ」。どうしりゃぁいいんでせうか。

と、再度 StackOverflow を見てみると、やたら低 voting で目立たない「正解」が眠ってた。うげ…。結果、「change をトリガー」という発想なんかせずに、これだけ:

受ける方が spinstop を受ければいいだけ
 1 $(".posint-spinner").spinner({
 2     min: 0,
 3     // spin ハンドラなんぞいらん
 4 });
 5 $(".posnut-spinner").spinner({
 6     min: 1,
 7     // spin ハンドラなんぞいらん
 8 });
 9 // (多くのスピナーを一気に作りたかったので種類別に class をつけてそれに対してやってる。)
10 $(".posnut-spinner").on("spinstop", function () {
11     // popularity-min-thr は class でなくてコントロールの実際の id
12     console.log($("#popularity-min-thr").val());
13 });
14 $(".posnut-spinner").on("change", function () {
15     // popularity-min-thr は class でなくてコントロールの実際の id
16     console.log($("#popularity-min-thr").val());
17 });


Related Posts