2つのjQuery UI Spinnerウィジェットを連動させ、
2つのスピナーの大小関係が逆転しないようにしていた時にはまったメモ
step値で上下する値として無効な値を入力した後、min の値を設定すると
もう一方のスピナーの値を上下させると数値が変な値で上下してしまう。
発生した事象
from: val: 0.0 min: 0.0 max: 50.0
to : val: 50.0 min: 0.0 max: 50.0
step: 0.5
- from を0.2 にする
- to のmin fromの値で更新する (大小関係のチェックは省略)
- to を1ステップ分下げる
- to が 49.7 になり、以降0.5ずつ上下する
原因
jQueryUI.Spinner の stepUp,stepDown の仕様をよく読むと
If the resulting value is above the max, below the min, or results in a step mismatch, the value will be adjusted to the closest valid value
訳:結果の値が最大値よりも大きく、最小値よりも小さいか、またはステップの不一致が生じた場合、値は最も近い有効値に調整されます。
つまり、min,maxを設定する際に近似値丸めをしていなかったことが原因のようです。
修正
で、toのminの値をfromの値に変更する前に以下のコードで近似値に丸めて正常な値になりました。
function approximationRound(spinnerID, stepStr) {
var resolution = getNumberOfDecimalPlaces(stepStr), step = Number.parseFloat(stepStr);
var num = Number(document.getElementById(spinnerID).value);
var val = num.toFixed(resolution);
var commaIdx = val.indexOf('.');
var retval = num;
var mod = 0;
if (commaIdx !== -1) {
mod = (val.substr(0, commaIdx + resolution + 1) % step);
} else {
mod = (val % step);
}
if (mod === 0) {
retval = num;
} else if ((step / 2) <= mod) {
retval = num + (step - mod);
} else {
retval = num - mod;
}
return retval.toFixed(resolution);
};
function getNumberOfDecimalPlaces(str) {
var idx = str.indexOf('.');
return (idx !== -1) ? str.replace(/.*\./, '').length : 0;
}
修正
- マイナスの値に対応していないので修正する