├── LICENSE
├── README.md
├── bower.json
├── build.sh
├── demo
├── index.html
└── js
│ └── app.js
├── dist
├── angular-slidezilla.min.js
└── angular-slidezilla.min.js.map
└── src
├── angular-slidezilla.css
└── angular-slidezilla.js
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Lenny
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Angular Slidezilla
2 | ========================
3 |
4 | Angular Slidezilla is a pure angular slider directive which makes it incredibly simple to have reliable sliders in angular.
5 |
6 | Talk is cheap: [See THE DEMO here](http://itslenny.github.io/angular-slidezilla/).
7 |
8 | ##Why Slidezilla?
9 |
10 | There are several other angular slider directives. Most of them depend on jQuery and/or are really glitchy or don't have the features I wanted. So I created my own and I needed a unique name for the plugin and this was the first thing that popped in my head.
11 |
12 |
13 | ##Installation
14 |
15 | Dependencies: Angular
16 |
17 | Download and include angular-slidezilla.js and pretty-slidezilla.css
18 |
19 | Create an angular app and inject angular-slidezilla. That's about it.
20 |
21 | **bower**
22 | ```bash
23 | bower install angular-slidezilla
24 | ```
25 |
26 | ##Usage
27 |
28 | **basic**
29 | ```html
30 |
31 | ```
32 | controller:
33 | ```js
34 | //set slider value as a number to have 1 slider
35 | //all properties default values
36 | $scope.slider1 = {val:5};
37 | ```
38 |
39 | **static**
40 | ```html
41 |
42 | ```
43 | controller:
44 | ```js
45 | //set slider value as a number to have 1 slider
46 | // properties defined in html
47 | $scope.slider2 = {val:-7};
48 | ```
49 |
50 | **dynamic**
51 | ```html
52 |
53 | ```
54 | controller:
55 | ```js
56 | //set slider value as a number to have 1 slider
57 | // properties defined below
58 | $scope.slider3 = {
59 | val:5.5,
60 | min: 0,
61 | max: 10,
62 | step: 0.5
63 | };
64 | ```
65 |
66 | **range**
67 | ```html
68 |
69 | ```
70 | controller:
71 | ```js
72 | //set value as an array to have 2 sliders
73 | $scope.slider4 = { val:[5,20] };
74 | ```
75 |
76 | ##Configuration
77 |
78 |
79 |
80 |
81 | Name
82 | Values
83 | Description
84 | Default
85 |
86 |
87 | min
88 | variable or number (float)
89 | Min value of slider.
90 | 0
91 |
92 |
93 | max
94 | variable or number (float)
95 | Max value of slider
96 | 100
97 |
98 |
99 | step
100 | variable or number (float)
101 | Step value of slider. Slider will increment by this value.
102 | 5
103 |
104 |
105 |
106 |
107 |
108 | ##Customization
109 |
110 | Simply modify angular-slidezilla.css
111 |
112 |
113 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-slidezilla",
3 | "main": [
4 | "dist/angular-slidezilla.min.js",
5 | "dist/angular-slidezilla.min.js.map",
6 | "src/angular-slidezilla.css"
7 | ],
8 | "ignore": [
9 | "source",
10 | "spec",
11 | ".bowerrc",
12 | ".gitignore",
13 | ".jshintignore",
14 | ".jshintrc",
15 | "bower.json",
16 | "gruntfile.js",
17 | "package.json",
18 | "README.md",
19 | "build.sh"
20 | ],
21 | "dependencies": {
22 | "angular": "~1.2.13"
23 | }
24 | }
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #creates minified version and source map
4 | #requires uglifyjs -- npm install uglifyjs -g
5 |
6 | PROJECT_NAME=angular-slidezilla
7 |
8 | uglifyjs ./src/${PROJECT_NAME}.js --comments --source-map ./dist/${PROJECT_NAME}.min.js.map --source-map-url ${PROJECT_NAME}.min.js.map --output ./dist/${PROJECT_NAME}.min.js
9 |
10 |
11 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Angular Slidezilla
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 | This is the demo of Angular Slidezilla: a simple slider directive.
20 |
21 | View source on this page to see the various options available (also available in the github repo).
22 |
23 | For more information and full documents see
Github
24 |
25 |
26 |
27 |
Basic
28 |
29 |
30 | Value: {{slider1.val}}
31 |
32 |
33 |
Static
34 |
35 |
36 | Value: {{slider2.val}}
37 |
38 |
39 |
Dynamic
40 |
41 | Value: {{slider3.val}}
42 |
43 | Min: {{slider3.min}}
44 |
45 | Max: {{slider3.max}}
46 |
47 | Step: {{slider3.step}}
48 |
49 |
50 |
51 |
52 |
53 |
Range
54 |
55 |
56 | Values: {{slider4.val}}
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/demo/js/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var myApp = angular.module('myapp', ['angular-slidezilla'])
4 |
5 | myApp.controller('sliderdemo', ['$scope',function($scope){
6 |
7 | //set slider value as a number to have 1 slider
8 | //all properties default values
9 | $scope.slider1 = {val:5};
10 |
11 | //set slider value as a number to have 1 slider
12 | // properties defined in html
13 | $scope.slider2 = {val:-7};
14 |
15 | //set slider value as a number to have 1 slider
16 | // properties defined below
17 | $scope.slider3 = {
18 | val:5.5,
19 | min: 0,
20 | max: 10,
21 | step: 0.5
22 | };
23 |
24 | //set value as an array to have 2 sliders
25 | $scope.slider4 = { val:[5,20] };
26 |
27 | }]);
28 |
--------------------------------------------------------------------------------
/dist/angular-slidezilla.min.js:
--------------------------------------------------------------------------------
1 | /* @preserve
2 | *
3 | * angular-slidezilla
4 | * https://github.com/itslenny/angular-slidezilla
5 | *
6 | * Version: 0.1.3 - 02/21/2015
7 | * License: MIT
8 | */
9 | "use strict";angular.module("angular-slidezilla",[]).constant("angularSlidezillaConfig",{min:0,max:100,step:5}).controller("AngularSlidezillaController",["angularSlidezillaConfig","$scope",function(angularSlidezillaConfig,$scope){$scope.min=angularSlidezillaConfig.min||0;$scope.max=angularSlidezillaConfig.max||100;$scope.step=angularSlidezillaConfig.step||5}]).directive("slider",function(){return{scope:{model:"=ngModel"},restrict:"E",require:["ngModel"],controller:"AngularSlidezillaController",link:function(scope,element,attrs,ctrls){if(attrs.min){scope.min=scope.$parent.$eval(attrs.min);scope.$parent.$watch(attrs.min,function(newVal){scope.min=newVal;ctrls[0].$render()})}if(attrs.max){scope.max=scope.$parent.$eval(attrs.max);scope.$parent.$watch(attrs.max,function(newVal){scope.max=newVal;ctrls[0].$render()})}if(attrs.step){scope.step=scope.$parent.$eval(attrs.step);scope.$parent.$watch(attrs.step,function(newVal){scope.step=newVal;ctrls[0].$render()})}var handles=element[0].querySelectorAll(".slider-handle");var track=element[0].querySelector(".slider-track");var selection=element[0].querySelector(".slider-selection");var dragging=false;ctrls[0].$render=function(){var hPos1,hPos2;clampModelValue();ctrls[0].$setViewValue(scope.model);if(typeof scope.model=="number"){hPos1=0;hPos2=100/(scope.max-scope.min)*(scope.model-scope.max)+100;angular.element(handles[0]).css("margin-left",hPos2+"%");angular.element(handles[1]).addClass("hidden")}else{hPos1=100/(scope.max-scope.min)*(scope.model[0]-scope.max)+100;hPos2=100/(scope.max-scope.min)*(scope.model[1]-scope.max)+100;angular.element(handles[0]).css("margin-left",hPos1+"%");angular.element(handles[1]).css("margin-left",hPos2+"%").removeClass("hidden")}angular.element(selection).css("margin-left",hPos1+"%").css("width",hPos2-hPos1+1+"%")};angular.element(track).bind("mousedown",function(e){e.preventDefault();if(dragging)return;var newVal=scope.model;var offsetX=e.offsetX||e.layerX;if(typeof newVal=="number"){if(offsetX>handles[0].offsetLeft){newVal+=scope.step}else{newVal-=scope.step}}else{if(e.target==track&&offsetXhandles[1].offsetLeft){newVal[1]+=scope.step}else{if(e.target==selection&&offsetX>e.target.offsetWidth/2){newVal[1]-=scope.step}else{newVal[0]+=scope.step}}}scope.$apply(function(){scope.model=newVal;ctrls[0].$render()})});angular.element(handles).bind("mousedown",function(e){e.preventDefault();dragging={sx:e.clientX-e.target.offsetLeft,sy:e.clientY-e.target.offsetTop,w:e.target.offsetWidth,h:e.target.offsetHeight,element:e.target,index:e.target==handles[0]?0:1,container:e.target.parentElement.getBoundingClientRect()};angular.element(document).bind("mousemove",mousemove);angular.element(document).bind("mouseup",mouseup)});function mousemove(e){if(!dragging)return;dragging.y=e.clientY-dragging.sy;dragging.x=e.clientX-dragging.sx;if(dragging.x<0){dragging.x=0}else if(dragging.x>dragging.container.right-dragging.container.left){dragging.x=dragging.container.right-dragging.container.left}var percentVal=Math.max(0,Math.min(100,parseInt(dragging.x/(dragging.container.right-dragging.container.left)*100)));var normalizedVal=percentVal/100*(scope.max-scope.min)+scope.min;normalizedVal=parseFloat(normalizedVal.toFixed(3));var rounded=roundToStep(normalizedVal,scope.step);scope.$apply(function(){var setMVal=scope.model;if(typeof setMVal=="number"){setMVal=rounded}else{setMVal[dragging.index]=rounded}scope.model=setMVal;ctrls[0].$render()})}function mouseup(e){angular.element(document).unbind("mousemove",mousemove);angular.element(document).unbind("mouseup",mouseup);dragging=false}function roundToStep(val,step){return val>=0?val+step/2-(val+step/2)%step:val-step/2-(val+step/2)%step}function clampModelValue(){if(typeof scope.model=="number"){if(scope.model>scope.max){scope.model=scope.max}else if(scope.modelscope.model[1]){cv1=scope.model[0];cv0=scope.model[1];scope.model[0]=cv0;scope.model[1]=cv1}if(scope.model[0]>scope.max){cv0=scope.max}else if(scope.model[0]scope.max){cv1=scope.max}else if(scope.model[1] ',replace:true}});
10 | //# sourceMappingURL=angular-slidezilla.min.js.map
--------------------------------------------------------------------------------
/dist/angular-slidezilla.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"./dist/angular-slidezilla.min.js","sources":["./src/angular-slidezilla.js"],"names":["angular","module","constant","min","max","step","controller","angularSlidezillaConfig","$scope","directive","scope","model","restrict","require","link","element","attrs","ctrls","$parent","$eval","$watch","newVal","$render","handles","querySelectorAll","track","querySelector","selection","dragging","hPos1","hPos2","clampModelValue","$setViewValue","css","addClass","removeClass","bind","e","preventDefault","offsetX","layerX","offsetLeft","target","offsetWidth","$apply","sx","clientX","sy","clientY","offsetTop","w","h","offsetHeight","index","container","parentElement","getBoundingClientRect","document","mousemove","mouseup","y","x","right","left","percentVal","Math","parseInt","normalizedVal","parseFloat","toFixed","rounded","roundToStep","setMVal","unbind","val","cv0","cv1","template","replace"],"mappings":"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"}
--------------------------------------------------------------------------------
/src/angular-slidezilla.css:
--------------------------------------------------------------------------------
1 | .slider {
2 | display: inline-block;
3 | vertical-align: middle;
4 | position: relative;
5 | }
6 | .slider.slider-horizontal {
7 | width: 210px;
8 | height: 20px;
9 | }
10 | .slider.slider-horizontal .slider-track {
11 | height: 10px;
12 | width: 100%;
13 | margin-top: -5px;
14 | top: 50%;
15 | left: 0;
16 | }
17 | .slider.slider-horizontal .slider-selection {
18 | height: 100%;
19 | top: 0;
20 | bottom: 0;
21 | }
22 | .slider.slider-horizontal .slider-handle {
23 | margin-left: -10px;
24 | margin-top: -5px;
25 | }
26 | .slider.slider-horizontal .slider-handle.triangle {
27 | border-width: 0 10px 10px 10px;
28 | width: 0;
29 | height: 0;
30 | border-bottom-color: #0480be;
31 | margin-top: 0;
32 | }
33 | .slider.slider-vertical {
34 | height: 210px;
35 | width: 20px;
36 | }
37 | .slider.slider-vertical .slider-track {
38 | width: 10px;
39 | height: 100%;
40 | margin-left: -5px;
41 | left: 50%;
42 | top: 0;
43 | }
44 | .slider.slider-vertical .slider-selection {
45 | width: 100%;
46 | left: 0;
47 | top: 0;
48 | bottom: 0;
49 | }
50 | .slider.slider-vertical .slider-handle {
51 | margin-left: -5px;
52 | margin-top: -10px;
53 | }
54 | .slider.slider-vertical .slider-handle.triangle {
55 | border-width: 10px 0 10px 10px;
56 | width: 1px;
57 | height: 1px;
58 | border-left-color: #0480be;
59 | margin-left: 0;
60 | }
61 | .slider input {
62 | display: none;
63 | }
64 | .slider .tooltip-inner {
65 | white-space: nowrap;
66 | }
67 | .slider-track {
68 | position: absolute;
69 | cursor: pointer;
70 | background-color: #f7f7f7;
71 | background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);
72 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));
73 | background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);
74 | background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);
75 | background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);
76 | background-repeat: repeat-x;
77 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);
78 | -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
79 | -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
80 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
81 | -webkit-border-radius: 4px;
82 | -moz-border-radius: 4px;
83 | border-radius: 4px;
84 | }
85 | .slider-selection {
86 | position: absolute;
87 | background-color: #f7f7f7;
88 | background-image: -moz-linear-gradient(top, #f9f9f9, #f5f5f5);
89 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f9f9f9), to(#f5f5f5));
90 | background-image: -webkit-linear-gradient(top, #f9f9f9, #f5f5f5);
91 | background-image: -o-linear-gradient(top, #f9f9f9, #f5f5f5);
92 | background-image: linear-gradient(to bottom, #f9f9f9, #f5f5f5);
93 | background-repeat: repeat-x;
94 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9', endColorstr='#fff5f5f5', GradientType=0);
95 | -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
96 | -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
97 | box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
98 | -webkit-box-sizing: border-box;
99 | -moz-box-sizing: border-box;
100 | box-sizing: border-box;
101 | -webkit-border-radius: 4px;
102 | -moz-border-radius: 4px;
103 | border-radius: 4px;
104 | }
105 | .slider-handle {
106 | position: absolute;
107 | width: 20px;
108 | height: 20px;
109 | background-color: #0e90d2;
110 | background-image: -moz-linear-gradient(top, #149bdf, #0480be);
111 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));
112 | background-image: -webkit-linear-gradient(top, #149bdf, #0480be);
113 | background-image: -o-linear-gradient(top, #149bdf, #0480be);
114 | background-image: linear-gradient(to bottom, #149bdf, #0480be);
115 | background-repeat: repeat-x;
116 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);
117 | -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
118 | -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
119 | box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
120 | opacity: 0.8;
121 | border: 0px solid transparent;
122 | }
123 | .slider-handle.round {
124 | -webkit-border-radius: 20px;
125 | -moz-border-radius: 20px;
126 | border-radius: 20px;
127 | }
128 |
129 | .slider-handle.hidden{
130 | display: none;
131 | }
--------------------------------------------------------------------------------
/src/angular-slidezilla.js:
--------------------------------------------------------------------------------
1 | /* @preserve
2 | *
3 | * angular-slidezilla
4 | * https://github.com/itslenny/angular-slidezilla
5 | *
6 | * Version: 0.1.3 - 02/21/2015
7 | * License: MIT
8 | */
9 |
10 | 'use strict';
11 |
12 | //init module
13 | angular.module('angular-slidezilla', [])
14 |
15 | //config
16 | .constant('angularSlidezillaConfig', {
17 | min:0,
18 | max:100,
19 | step:5
20 | })
21 |
22 | //controller
23 | .controller('AngularSlidezillaController', ['angularSlidezillaConfig','$scope', function(angularSlidezillaConfig,$scope) {
24 | //set default scope values
25 | $scope.min=angularSlidezillaConfig.min || 0;
26 | $scope.max=angularSlidezillaConfig.max || 100;
27 | $scope.step=angularSlidezillaConfig.step || 5;
28 | }])
29 |
30 | //slider directive
31 | .directive('slider', function () {
32 | return {
33 | scope: {
34 | 'model':'=ngModel'
35 | },
36 | restrict: 'E',
37 | require: ['ngModel'],
38 | controller: 'AngularSlidezillaController',
39 | link: function (scope, element, attrs, ctrls) {
40 | //process attributes and watch for changes
41 | if(attrs.min){
42 | scope.min = scope.$parent.$eval(attrs.min);
43 | scope.$parent.$watch(attrs.min, function(newVal) {
44 | scope.min = newVal;
45 | ctrls[0].$render();
46 | });
47 | }
48 | if(attrs.max){
49 | scope.max = scope.$parent.$eval(attrs.max);
50 | scope.$parent.$watch(attrs.max, function(newVal) {
51 | scope.max = newVal;
52 | ctrls[0].$render();
53 | });
54 | }
55 | if(attrs.step){
56 | scope.step = scope.$parent.$eval(attrs.step);
57 | scope.$parent.$watch(attrs.step, function(newVal) {
58 | scope.step = newVal;
59 | ctrls[0].$render();
60 | });
61 | }
62 |
63 | //init dom objects
64 | var handles = element[0].querySelectorAll('.slider-handle');
65 | var track = element[0].querySelector('.slider-track');
66 | var selection = element[0].querySelector('.slider-selection');
67 |
68 | //drag state variable
69 | var dragging=false;
70 |
71 | //// model -> UI ////////////////////////////////////
72 | ctrls[0].$render = function () {
73 | var hPos1,hPos2;
74 | //ensure model value is in range
75 | clampModelValue();
76 | //update view value
77 | ctrls[0].$setViewValue(scope.model);
78 | //update display to match model value
79 | if(typeof scope.model == 'number'){ // 25/75 = x / 100
80 | hPos1 = 0;
81 | hPos2 = 100 / (scope.max - scope.min) * (scope.model - scope.max) + 100;
82 | angular.element(handles[0]).css('margin-left',hPos2+'%');
83 | angular.element(handles[1]).addClass('hidden');
84 | }else{
85 | hPos1 = 100 / (scope.max - scope.min) * (scope.model[0] - scope.max) + 100;
86 | hPos2 = 100 / (scope.max - scope.min) * (scope.model[1] - scope.max) + 100;
87 | angular.element(handles[0]).css('margin-left',hPos1+'%');
88 | angular.element(handles[1]).css('margin-left',hPos2+'%').removeClass('hidden');
89 | }
90 | angular.element(selection).css('margin-left',hPos1+'%').css('width',(hPos2-hPos1+1)+'%');
91 | };
92 |
93 |
94 | //// ui->model ////////////////////////////////////
95 |
96 | //bind mouse down event (track) - increment by step
97 | angular.element(track).bind('mousedown', function(e) {
98 | e.preventDefault();
99 | if(dragging) return;
100 | var newVal=scope.model;
101 | var offsetX = e.offsetX || e.layerX;
102 |
103 | if(typeof newVal == 'number') {
104 | if (offsetX > handles[0].offsetLeft) {
105 | newVal += scope.step;
106 | } else {
107 | newVal -= scope.step;
108 | }
109 | }else{
110 | if(e.target == track && offsetX < handles[0].offsetLeft) {
111 | newVal[0] -= scope.step;
112 | }else if(e.target == track && offsetX > handles[1].offsetLeft) {
113 | newVal[1] += scope.step;
114 | }else{
115 | if(e.target == selection && offsetX > e.target.offsetWidth/2){
116 | newVal[1] -= scope.step;
117 | }else{
118 | newVal[0] += scope.step;
119 | }
120 | }
121 | }
122 | scope.$apply(function () {
123 | scope.model=newVal;
124 | ctrls[0].$render();
125 | });
126 | });
127 |
128 | // Bind mousedown event (drag handles) -- start drag
129 | angular.element(handles).bind('mousedown', function(e) {
130 | e.preventDefault();
131 | //store data about currently dragging handle
132 | dragging={
133 | sx: e.clientX - e.target.offsetLeft,
134 | sy: e.clientY - e.target.offsetTop,
135 | w: e.target.offsetWidth,
136 | h: e.target.offsetHeight,
137 | element: e.target,
138 | index: e.target==handles[0] ? 0 : 1,
139 | container: e.target.parentElement.getBoundingClientRect()
140 | };
141 |
142 | //listen for movement / mouse up
143 | angular.element(document).bind('mousemove', mousemove);
144 | angular.element(document).bind('mouseup', mouseup);
145 | });
146 |
147 | // mousemove event (document) -- update drag handle to position
148 | function mousemove(e) {
149 | if(!dragging) return;
150 | dragging.y = e.clientY - dragging.sy;
151 | dragging.x = e.clientX - dragging.sx;
152 | //contain drag within track
153 | if (dragging.x < 0) {
154 | dragging.x = 0;
155 | } else if (dragging.x > dragging.container.right - dragging.container.left) {
156 | dragging.x = dragging.container.right - dragging.container.left;
157 | }
158 |
159 | //compute slider value based on handle position
160 | var percentVal = Math.max(0,Math.min(100,parseInt((dragging.x / (dragging.container.right - dragging.container.left))*100)));
161 | var normalizedVal = ((percentVal/100)*(scope.max - scope.min))+scope.min;
162 | normalizedVal = parseFloat(normalizedVal.toFixed(3));
163 | var rounded = roundToStep(normalizedVal,scope.step);
164 | //pass value to model
165 | scope.$apply(function () {
166 | var setMVal=scope.model;
167 | if(typeof setMVal == 'number') {
168 | setMVal=rounded;
169 | }else{
170 | setMVal[dragging.index]=rounded;
171 | }
172 | scope.model=setMVal;
173 | ctrls[0].$render();
174 | });
175 | }
176 |
177 | // mouse up event (document) -- stop drag
178 | function mouseup(e) {
179 | angular.element(document).unbind('mousemove', mousemove);
180 | angular.element(document).unbind('mouseup', mouseup);
181 | dragging=false;
182 | }
183 |
184 |
185 | //// helpers ////////////////////////////////////
186 |
187 | //rounds value to step
188 | function roundToStep(val,step){
189 | return (val >= 0 ) ? val + step/2 - (val+step/2) % step : val - step/2 - (val+step/2) % step;
190 | }
191 |
192 | //clamps model values. Keeps sliders within track and keeps them in index order
193 | function clampModelValue(){
194 | if(typeof scope.model == 'number'){
195 | if(scope.model > scope.max){
196 | scope.model=scope.max;
197 | }else if(scope.model < scope.min){
198 | scope.model=scope.min;
199 | }
200 | }else{
201 | var cv0,cv1;
202 | if(scope.model[0] > scope.model[1]){
203 | cv1 = scope.model[0];
204 | cv0 = scope.model[1];
205 | scope.model[0] = cv0;
206 | scope.model[1] = cv1;
207 | }
208 | if(scope.model[0] > scope.max){
209 | cv0 = scope.max;
210 | }else if(scope.model[0] < scope.min){
211 | cv0 = scope.min;
212 | }
213 | if(scope.model[1] > scope.max){
214 | cv1 = scope.max;
215 | }else if(scope.model[1] < scope.min){
216 | cv1 = scope.min;
217 | }
218 | if(cv0 || cv1){
219 | scope.model=[cv0 || scope.model[0],cv1 || scope.model[1]];
220 | }
221 | }
222 | }
223 | },
224 | template:'',
225 | replace: true
226 | };
227 | });
--------------------------------------------------------------------------------