<!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%;
}