<!DOCTYPE html>
<html ng-app="angularjs-starter">
<head lang="en">
<meta charset="utf-8">
<title>Custom Plunker</title>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.0/css/bootstrap-combined.min.css"
rel="stylesheet">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.min.js"></script>
<link rel="stylesheet" href="style.css">
<script>
document.write('<base href="' + document.location + '" />');
</script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<h1>AngularJS UI-slider</h1>
<hr>
<p>Price: <input ng-model="search.price_min"/> Input / Output</p>
<slider min="10" max="200" value="search.price_min"></slider>
<hr>
<p>Amount: <input ng-model="search.amount"/> Input / Output</p>
<slider min="0" max="10000" step="1000" value="search.amount"></slider>
<hr>
<p>Days: <input ng-model="search.days"/> Input / Output</p>
<slider min="0" max="30" step="5" value="search.days"></slider>
<hr>
</body>
</html>
var app = angular.module('angularjs-starter', []);
app.controller('MainCtrl', function($scope) {
$scope.search = { price_min : '', amount : 1000, days: 5 };
});
/* Slider
Input with default values:
-min=0 // Min slider value
-max=100 // Max slider value
-step=1 // Steps
Output / Input
-value // Default value @min
example:
<slider min="0" max="100" step="5" value="scope.form.slider_value"></slider>
*/
app.directive('slider', ['$document',function($document) {
// Move slider handle and range line
var moveHandle = function(elem, posX) {
$(elem).find('.handle').css("left",posX +'%');
$(elem).find('.range').css("width",posX +'%');
};
return {
template: '<div class="slider horizontal">'+
'<div class="range"></div>'+
'<a class="handle" ng-mousedown="mouseDown($event)"></a>'+
'</div>',
replace: true,
restrict: 'E',
scope:{
value:"="
},
link: function postLink(scope, element, attrs) {
// Initilization
var dragging = false;
var startPointX = 0;
var xPosition = 0;
var settings = {
"min" : (typeof(attrs.min) !== "undefined" ? parseInt(attrs.min,10) : 0),
"max" : (typeof(attrs.max) !== "undefined" ? parseInt(attrs.max,10) : 100),
"step" : (typeof(attrs.step) !== "undefined" ? parseInt(attrs.step,10) : 1)
};
if ( typeof(scope.value) == "undefined" || scope.value === '' )
scope.value = settings.min;
// Track changes only from the outside of the directive
scope.$watch('value', function() {
if (dragging) return;
xPosition = ( scope.value - settings.min ) / (settings.max - settings.min ) * 100;
if(xPosition < 0) {
xPosition = 0;
} else if(xPosition > 100) {
xPosition = 100;
}
moveHandle(element,xPosition);
});
// Real action control is here
scope.mouseDown = function($event) {
dragging = true;
startPointX = $event.pageX;
// Bind to full document, to make move easiery (not to lose focus on y axis)
$document.on('mousemove', function($event) {
if(!dragging) return;
//Calculate handle position
var moveDelta = $event.pageX - startPointX;
xPosition = xPosition + ( (moveDelta / element.outerWidth()) * 100 );
if(xPosition < 0) {
xPosition = 0;
} else if(xPosition > 100) {
xPosition = 100;
}
else {
// Prevent generating "lag" if moving outside window
startPointX = $event.pageX;
}
scope.value = Math.round((((settings.max - settings.min ) * (xPosition / 100))+settings.min)/settings.step ) * settings.step;
scope.$apply();
// Move the Handle
moveHandle(element,xPosition);
});
$document.mouseup(function(){
dragging = false;
$document.unbind('mousemove');
$document.unbind('mousemove');
});
};
}
};
}]);
/* CSS goes here */
.slider {
position: relative;
text-align: left;
border: 1px solid gray;
height: 0.6em;
}
.slider .handle {
position: absolute;
z-index: 2;
width: 1.2em;
height: 1.2em;
background-color: gray;
}
.handle {
top: -0.3em;
margin-left: -0.6em;
}
.slider .range {
position: absolute;
z-index: 1;
display: block;
font-size: .7em;
background-color: red;
top: 0;
height: 100%;
}