前書き
そもそも、ここの回答を転記、加工して、動作を確認しただけです。
なぜ書き直したかといいますと、2013年の回答と、現在のバージョンが異なるから、
サンプルページが動作していなかったため、
そして、日本語での参考にできる記事がなかったため、検索性を考えて、転記しておこうということです。
ということなので、話はタイトルで分かったから、早くという人は本家からコピーしたほうが早いです。元のままでもちゃんと動きました。
もしくは、本番へどうぞ。
何がしたいか
jQuery UIのSliderという機能、ハンドル(値を持てる箇所)を複数指定する場合
$('#slider').slider({
min : 0,
max : 50,
values : [0,10,20,30,40,50]
});
このハンドルを、操作するには、
$('#slider').slider('option',{
'values' : [5,15,25,35,45,50]
});
こんな感じで、指定すれば、ハンドルを操作することができます。
では、ハンドルの数を変化させたい場合は、
// 増やす?
$('#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時点で最新版
コード
<!DOCTYPE html>
<html lang="ja-jp">
<head>
<title></title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="./css/jquery-ui.min.css">
<link rel="stylesheet" type="text/css" href="./css/jquery-ui.structure.min.css">
<style type="text/css">
#slider {
width: 500px;
margin: 50px
}
</style>
</head>
<body>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" crossorigin="anonymous"></script>
<script src="./js/jquery-ui.min.js"></script>
<div id="slider"></div>
<div><button id="add_btn">追加</button><button id="remove_btn">削除</button></div>
<script type="text/javascript">
// ハンドルの配列
var slider_handles = [0,10,20,30,40,50];
$(function(){
// 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の初期化
$('#slider').slider({
min : 0,
max : 100,
values : slider_handles
});
// ボタンのイベントリスナ
$('#add_btn').on('click', function(event) {
// 一番最後にあるハンドルに+10した場所に新しく作る
$('#slider').slider('addValue',slider_handles[slider_handles.length-1]+10);
});
$('#remove_btn').on('click', function(event) {
// ハンドルを1つ削除
$('#slider').slider('removeValue');
});
});
</script>
</body>
</html>
こんな感じです。上のソースはjQuery UIだけダウンロードしてきて、そのままコピペすれば動くはずです。
簡単に説明
// 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を破棄してから、作り直しています。
あとは、ボタンのイベントリスナーからそれぞれのメソッドを呼び出します。
// ボタンのイベントリスナー
$('#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()
だけでは不満なら
頭から消したかったり、指定して削除したかったり、することもあるかも、と思った。今のところない。
実装が必要になったら、更新するかもしれない。
本家が実装してくれればいいのに
お願いします。
最後に
サンプルとして投稿しているコードは実際に使ったものを抽象化しているものです。
動作は保証しませんが、問題があれば、教えていただければ修正するかもしれません。
この投稿のコード権利を主張しませんので、適当にコピペして使って大丈夫です。
質問とか、適当こいてんじゃないよみたいなことがあれば、コメントいただければ。