こんにちは、
基本のスライダー
スライダーは簡単にいえば動きの制限されたドラッグです。
今回も、
<form class="js-slider-form" onsubmit="return false;">
<input type="text" name="slider" id="slider1o" value="0">
<div id="slider1" class="js-slider">
<div></div>
<input type="button" value="">
</div>
</form>
今回は少々手抜きで、
そして、
.js-slider{
position:relative;
width:300px;
height:20px;
}
.js-slider div{
background:#ddd;
height:3px;
border:1px inset #aaa;
position:relative;
top:12px;
font-size:0px;
}
.js-slider input{
position:absolute;
width:15px;
height:20px;
display:block;
}
さて、
(function(){
var slider = document.getElementById('slider1');
var output = document.getElementById('slider1o');
var input = slider.getElementsByTagName('input')[0];
var root = document.documentElement;
var dragging = false;
var value = output.value;// 初期位置
var width = input.clientWidth / 2;
var set_value = function (){
// つまみのサイズ(input.clientWidth)だけ位置を調整
input.style.left = (value - input.clientWidth/2) + 'px';
output.value = value;
};
set_value();
// 目盛り部分をクリックしたとき
slider.onclick = function(evt){
dragging = true;
document.onmousemove(evt);
document.onmouseup();
};
// ドラッグ開始
input.onmousedown = function(evt){
dragging = true;
return false;
};
// ドラッグ終了
document.onmouseup = function(evt){
if (dragging) {
dragging = false;
output.value = value;
}
};
document.onmousemove = function(evt){
if(dragging){
// ドラッグ途中
if(!evt){
evt = window.event;
}
var left = evt.clientX;
var rect = slider.getBoundingClientRect();
// マウス座標とスライダーの位置関係で値を決める
value = Math.round(left - rect.left - width);
// スライダーからはみ出したとき
if (value < 0) {
value = 0;
} else if (value > slider.clientWidth) {
value = slider.clientWidth;
}
set_value();
return false;
}
};
})();
主な処理はドラッグのときとほとんど変わりません。マウスダウンでドラッグを開始し、
HTML5のスライダーとの統合
さて、
HTML5の<input type="range">は前述のようなスライダーをネイティブに提供してくれます。type=rangeはOperaやChromeやSafariなどで既に実装されています。
今回はこのtype="range"になるべく合わせるように実装してみます
<div id="js-slider2">
<form class="js-slider-form" onsubmit="return false;">
<input type="range">
</form>
<form class="js-slider-form" onsubmit="return false;">
<input type="range" min="100" max="400" value="200"
style="width:300px;" >
</form>
</div>
function html5_slider(node){
var addEvent = document.addEventListener ?
function(node,type,listener){
node.addEventListener(type,listener,false);
} :
function(node,type,listener){
node.attachEvent('on'+type, listener);
}
var removeEvent = document.removeEventListener ?
function(node,type,listener){
node.removeEventListener(type,listener,false);
} :
function(node,type,listener){
node.detachEvent('on'+type, listener);
}
var dragging = false;
var slider, button, input;
var min = 0, max = 100;
var value = 0;
function set_value(){
button.style.left = (value - button.clientWidth/2) +'px';
input.value = min + value;
}
if (!node){
node = document;
}
var inputs = node.getElementsByTagName('input');
// getElementsByTagNameで取得した要素を走査中に置き換えると
// 繰り上がりされるので、繰り上がりが起きても良いように、
// 後ろから走査する
var n = inputs.length;
while (n){
n--;
var _input = inputs[n];
var type = _input.getAttribute('type');
if(type === 'range' && !('step' in _input)){
init(_input);
}
}
function init(_input){
var parent = _input.parentNode;
var _min = parseInt(_input.getAttribute('min'), 10)||0;
var _max = parseInt(_input.getAttribute('max'), 10)||100;
value = parseInt(_input.value, 10) - _min || 0;
var outer = document.createElement('div');
var inner = document.createElement('div');
var _button = document.createElement('input');
_button.type = 'button';
outer.className = 'js-slider';
outer.style.width = (_max - _min)+ 'px';
parent.insertBefore(outer, _input);
outer.appendChild(inner);
outer.appendChild(_button);
if(window.ActiveXObject){
// IEはinputのtypeをhiddenに書き換えることができない
// 少々強引だが、outerHTMLについて置換を行う
parent.removeChild(_input);
_input = document.createElement(
_input.outerHTML.replace('type=range', 'type=hidden')
);
parent.insertBefore(_input, outer.nextSbling || null);
} else {
_input.type = 'hidden';
}
button = _button;
input = _input;
set_value();
addEvent(outer,'click', function(evt){
dragging = true;
min = _min;
max = _max;
input = _input;
button = _button;
slider = outer;
mousemove(evt);
});
addEvent(_button,'mousedown', function(evt){
if(!evt){
evt = window.event;
}
dragging = true;
min = _min;
max = _max;
input = _input;
button = _button;
slider = outer;
if (evt.preventDefault){
evt.preventDefault();
} else {
evt.returnValue = false;
}
addEvent(document, 'mousemove', mousemove);
});
}
addEvent(document, 'mouseup', function(evt){
if(dragging){
dragging = false;
removeEvent(document, 'mousemove', mousemove);
input = null;
button = null;
slider = null;
}
});
function mousemove(evt){
if(!evt){
evt = window.event;
}
if(dragging){
var left = evt.clientX;
var rect = slider.getBoundingClientRect();
var width = button.clientWidth / 2;
// マウス座標とスライダーの位置関係で値を決める
value = Math.round(left - rect.left - width);
// スライダーからはみ出したとき
if (value < 0) {
value = 0;
} else if (value > slider.clientWidth) {
value = slider.clientWidth;
}
set_value();
if (evt.preventDefault){
evt.preventDefault();
} else {
evt.returnValue = false;
}
}
}
}
いくつかポイントがありますが、
また、
まとめ
今回はJavaScriptを使ったUIとしてスライダーパーツの実装方法を紹介しました。こちらもまだまだ改良の余地があるので、
次回も引き続きJavaScriptを使ったクロスブラウザなUIの実装を見ていきたいと思います。