--- title: jQuery UI Slider で、ハンドルの数を増減したい話 tags: JavaScript jQuery jquery.ui slider author: MarioninC slide: false --- ## 前書き そもそも、[ここ](https://stackoverflow.com/questions/19348528/jquery-ui-slider-how-to-add-values)の回答を転記、加工して、動作を確認しただけです。 なぜ書き直したかといいますと、2013年の回答と、現在のバージョンが異なるから、 サンプルページが動作していなかったため、 そして、日本語での参考にできる記事がなかったため、検索性を考えて、転記しておこうということです。 ということなので、話はタイトルで分かったから、早くという人は[本家](https://stackoverflow.com/questions/19348528/jquery-ui-slider-how-to-add-values)からコピーしたほうが早いです。元のままでもちゃんと動きました。 もしくは、[本番](#本番)へどうぞ。 ## 何がしたいか [jQuery UIのSlider](https://jqueryui.com/slider/)という機能、ハンドル(値を持てる箇所)を複数指定する場合 ```js $('#slider').slider({ min : 0, max : 50, values : [0,10,20,30,40,50] }); ``` こんな感じで、指定してあげると、6つのハンドルができます。 11.PNG このハンドルを、操作するには、 ```js $('#slider').slider('option',{ 'values' : [5,15,25,35,45,50] }); ``` こんな感じで、指定すれば、ハンドルを操作することができます。 12.PNG では、ハンドルの数を変化させたい場合は、 ```js // 増やす? $('#slider').slider('option',{ 'values' : [0,15,10,20,30,40,50] }); // 減らす? $('#slider').slider('option',{ 'values' : [0,10,20,30,40] }); ``` **これだと、動かないです。** エラーは起きないのですが、 `values`は初期化したとき作られた、ハンドルは操作できますが、 後からハンドルの数の変動はできない仕様になっています。 今回は、これを、jQuery UI の拡張という手を使って、sliderにmethodを追加して解決しました。 #本番 前書きが長くなりましたが、 では本番です。 ## 環境 * Chrome 80.0.3987.132 * jQuery 3.3.1 * jQuery UI 1.12.1 いずれも、2020/03/05時点で最新版 ## コード ```haml
``` こんな感じです。上のソースはjQuery UIだけダウンロードしてきて、そのままコピペすれば動くはずです。 ### 簡単に説明 ```js // jQuery UI slider の拡張 $.widget('my-namespace.slider', $.ui.slider, { addValue: function(val) { this.options.values.push(val); this._refresh(); }, removeValue: function() { this.options.values.pop(); this._refresh(); } }); ``` の部分で、sliderを拡張しています。`addValue`と、`removeValue`を追加しています。 大切なのは、`this._refresh()`だけです。 `this._refresh()`は、sliderの初期化時に、処理される部分で、一度sliderを破棄してから、作り直しています。 あとは、ボタンのイベントリスナーからそれぞれのメソッドを呼び出します。 ```js // ボタンのイベントリスナー $('#add_btn').on('click', function(event) { $('#slider').slider('addValue',slider_handles[slider_handles.length-1]+10); }); $('#remove_btn').on('click', function(event) { $('#slider').slider('removeValue'); }); ``` 追加する方のイベントリスナーでは、新しいハンドルの場所をしてしなくてはいけないので、 サンプルとしては、とりあえず、今ある一番最後のハンドルの+10の位置に追加しています。 ## 注意書き ### 元のsliderをオーバーライトして使ってる話 `$.widget('my-namespace.slider', $.ui.slider, {});`の部分は、 `$.ui.slider`を継承して、`my-namespace.slider`を新しく作っています。 今回は、そのまま同じ名前の、sliderを使っているので、何も気にせず、拡張されていますが、 この方法を使うと、拡張部分をコピーし忘れてソースコード中からほかのプログラムにコピペすると、動かないので、 `$.widget('my-namespace.custom_slider', $.ui.slider, {});`のように、 新しい名前を付けて使うのが普通見たいです。ただ、その場合、`$(selector).slider();`で書いているところをすべて、 `$(slector).custom_slider();`に書き換えて使ってください。 散々コードを書いてしまった後で、追加するようなときは、今回のようにすると、そのまま使えます。 ### 配列をグローバルに置いている話 ハンドルの値をしまっている配列をグローバルに置いてるのは、今回わかりやすくするために置いただけで、 `$('#slider').slider('values');`に取得してあげれば、素直に配列で返ってくるので、グローバルを汚したくない人はこちらがいいかも。 ### ないのに削除したり、もう入らないのに追加できる話 `remove`では、配列の中に1つもなくても、実行できています。 `add`では、値がはみ出ても追加できています。 実際に使うときはアラート出すなりして、それぞれ工夫してください。 ## 余談 ### 要は`this._refresh()` `this._refresh();`だけで動くんだったら、refreshメソッドだけ拡張すればいい気もする。 今回私は、1行ずつの追加削除でよかったけれど、複数行扱うときは、そのほうがいい気がする。 ### `array.pop()`だけでは不満なら 頭から消したかったり、指定して削除したかったり、することもあるかも、と思った。今のところない。 実装が必要になったら、更新するかもしれない。 ### 本家が実装してくれればいいのに お願いします。 ## 最後に サンプルとして投稿しているコードは実際に使ったものを抽象化しているものです。 動作は保証しませんが、問題があれば、教えていただければ修正するかもしれません。 この投稿のコード権利を主張しませんので、適当にコピペして使って大丈夫です。 質問とか、適当こいてんじゃないよみたいなことがあれば、コメントいただければ。