@@ -12,145 +12,170 @@ angular.module('ui.bootstrap-slider', [])
1212 value : "=" ,
1313 ngModel : '=' ,
1414 range :'=' ,
15- sliderid :'=' ,
16- formater :'&' ,
15+ sliderid : '=' ,
16+ formater : '&' ,
1717 onStartSlide : '&' ,
1818 onStopSlide : '&' ,
1919 onSlide : '&'
2020 } ,
2121 link : function ( $scope , element , attrs , ngModelCtrl , $compile ) {
22+ var ngModelDeregisterFn , ngDisabledDeregisterFn ;
23+
2224 initSlider ( ) ;
2325
2426 function initSlider ( ) {
25- $ . fn . slider . constructor . prototype . disable = function ( ) {
26- this . picker . off ( ) ;
27- } ;
28-
29- $ . fn . slider . constructor . prototype . enable = function ( ) {
30- this . picker . on ( ) ;
31- } ;
32-
3327 var options = { } ;
34- if ( $scope . sliderid ) options . id = $scope . sliderid ;
35- if ( $scope . min ) options . min = parseFloat ( $scope . min ) ;
36- if ( $scope . max ) {
37- options . max = parseFloat ( $scope . max ) ;
38- }
39-
4028
41- if ( attrs . step ) options . step = parseFloat ( $scope . step ) ;
42- if ( attrs . precision ) options . precision = parseFloat ( attrs . precision ) ;
43- if ( attrs . orientation ) options . orientation = attrs . orientation ;
44- if ( $scope . value ) {
45- if ( angular . isNumber ( $scope . value ) || angular . isArray ( $scope . value ) ) {
46- options . value = $scope . value ;
47- } else if ( angular . isString ( $scope . value ) ) {
48- if ( attrs . value . indexOf ( "[" ) === 0 ) {
49- options . value = angular . fromJson ( $scope . value ) ;
50- } else {
51- options . value = parseFloat ( $scope . value ) ;
52- }
53- }
29+ function setOption ( key , value , defaultValue ) {
30+ options [ key ] = value || defaultValue ;
5431 }
55- if ( $scope . range ) {
56- options . range = $scope . range === true ;
32+ function setFloatOption ( key , value , defaultValue ) {
33+ options [ key ] = value ? parseFloat ( value ) : defaultValue ;
5734 }
58-
59- if ( attrs . selection ) options . selection = attrs . selection ;
60- if ( attrs . tooltip ) options . tooltip = attrs . tooltip ;
61- if ( attrs . tooltipseparator ) options . tooltip_separator = attrs . tooltipseparator ;
62- if ( attrs . tooltipsplit ) options . tooltip_split = attrs . tooltipsplit === 'true' ;
63- if ( attrs . handle ) options . handle = attrs . handle ;
64- if ( attrs . reversed ) options . reversed = attrs . reversed === 'true' ;
65- if ( attrs . enabled ) options . enabled = attrs . enabled === 'true' ;
66- if ( attrs . naturalarrowkeys ) options . natural_arrow_keys = attrs . naturalarrowkeys === 'true' ;
67- if ( attrs . formater ) options . formater = $scope . $eval ( $scope . formater ) ;
68-
69- if ( options . range && ! options . value ) {
70- options . value = [ 0 , 0 ] ; // This is needed, because of value defined at $.fn.slider.defaults - default value 5 prevents creating range slider
35+ function setBooleanOption ( key , value , defaultValue ) {
36+ options [ key ] = value ? value + '' === 'true' : defaultValue ;
37+ }
38+ function getArrayOrValue ( value ) {
39+ return ( angular . isString ( value ) && value . indexOf ( "[" ) === 0 ) ? angular . fromJson ( value ) : value ;
7140 }
7241
73- var slider = $ ( element . find ( ".slider-input" ) [ 0 ] ) . slider ( options ) ;
74- slider . slider ( 'destroy' ) ;
75- slider = $ ( element . find ( ".slider-input" ) [ 0 ] ) . slider ( options ) ;
76-
77- var updateEvent ;
78- if ( angular . isString ( attrs . updateevent ) ) {
79- // check if array of event names
80- if ( attrs . updateevent . indexOf ( "[" ) === 0 ) {
81- updateEvent = angular . fromJson ( attrs . updateevent ) ;
42+ setOption ( 'id' , $scope . sliderid ) ;
43+ setOption ( 'orientation' , attrs . orientation , 'horizontal' ) ;
44+ setOption ( 'selection' , attrs . selection , 'before' ) ;
45+ setOption ( 'handle' , attrs . handle , 'round' ) ;
46+ setOption ( 'tooltip' , attrs . tooltip , 'show' ) ;
47+ setOption ( 'tooltipseparator' , attrs . tooltipseparator , ':' ) ;
48+
49+ setFloatOption ( 'min' , $scope . min , 0 ) ;
50+ setFloatOption ( 'max' , $scope . max , 10 ) ;
51+ setFloatOption ( 'step' , $scope . step , 1 ) ;
52+ var strNbr = options . step + '' ;
53+ var decimals = strNbr . substring ( strNbr . lastIndexOf ( '.' ) + 1 ) ;
54+ setFloatOption ( 'precision' , attrs . precision , decimals ) ;
55+
56+ setBooleanOption ( 'tooltip_split' , attrs . tooltipsplit , false ) ;
57+ setBooleanOption ( 'enabled' , attrs . enabled , true ) ;
58+ setBooleanOption ( 'naturalarrowkeys' , attrs . naturalarrowkeys , false ) ;
59+ setBooleanOption ( 'reversed' , attrs . reversed , false ) ;
60+
61+ setBooleanOption ( 'range' , $scope . range , false ) ;
62+ if ( options . range ) {
63+ if ( angular . isArray ( $scope . value ) ) {
64+ options . value = $scope . value ;
65+ }
66+ else if ( angular . isString ( $scope . value ) ) {
67+ options . value = getArrayOrValue ( $scope . value ) ;
68+ if ( ! angular . isArray ( options . value ) ) {
69+ var value = parseFloat ( $scope . value ) ;
70+ if ( isNaN ( value ) ) value = 5 ;
71+
72+ if ( value < $scope . min ) {
73+ value = $scope . min ;
74+ options . value = [ value , options . max ] ;
75+ }
76+ else if ( value > $scope . max ) {
77+ value = $scope . max ;
78+ options . value = [ options . min , value ] ;
79+ }
80+ else {
81+ options . value = [ options . min , options . max ] ;
82+ }
83+ }
8284 }
8385 else {
84- // if only single event name in string
85- updateEvent = [ attrs . updateevent ] ;
86+ options . value = [ options . min , options . max ] ; // This is needed, because of value defined at $.fn.slider.defaults - default value 5 prevents creating range slider
8687 }
88+ $scope . ngModel = options . value ; // needed, otherwise turns value into [null, ##]
8789 }
8890 else {
89- // default to slide event
90- updateEvent = [ 'slide' ] ;
91+ setFloatOption ( 'value' , $scope . value , 5 ) ;
9192 }
9293
93- angular . forEach ( updateEvent , function ( sliderEvent ) {
94- slider . on ( sliderEvent , function ( ev ) {
95- ngModelCtrl . $setViewValue ( ev . value ) ;
96- $timeout ( function ( ) {
97- $scope . $apply ( ) ;
98- } ) ;
99- } ) ;
100- } ) ;
101-
102- // Event listeners
103- var sliderEvents = {
104- slideStart : 'onStartSlide' ,
105- slide : 'onSlide' ,
106- slideStop : 'onStopSlide'
107- } ;
108-
109- angular . forEach ( sliderEvents , function ( sliderEventAttr , sliderEvent ) {
110- slider . on ( sliderEvent , function ( ev ) {
111-
112- if ( $scope [ sliderEventAttr ] ) {
113- var invoker = $parse ( attrs [ sliderEventAttr ] ) ;
114- invoker ( $scope . $parent , { $event : ev , value : ev . value } ) ;
115-
116- $timeout ( function ( ) {
94+ if ( $scope . formater ) options . formater = $scope . $eval ( $scope . formater ) ;
95+
96+ var slider = element . find ( ".slider-input" ) . eq ( 0 ) ;
97+ // check if slider jQuery plugin exists
98+ if ( $ . fn . slider ) {
99+ // adding methods to jQuery slider plugin prototype
100+ $ . fn . slider . Constructor . prototype . disable = function ( ) {
101+ this . picker . off ( ) ;
102+ } ;
103+ $ . fn . slider . Constructor . prototype . enable = function ( ) {
104+ this . picker . on ( ) ;
105+ } ;
106+
107+ // destroy previous slider to reset all options
108+ slider . slider ( options ) ;
109+ slider . slider ( 'destroy' ) ;
110+ slider . slider ( options ) ;
111+
112+ // everything that needs slider element
113+ var updateEvent = getArrayOrValue ( attrs . updateevent ) ;
114+ if ( angular . isString ( updateEvent ) ) {
115+ // if only single event name in string
116+ updateEvent = [ updateEvent ] ;
117+ }
118+ else {
119+ // default to slide event
120+ updateEvent = [ 'slide' ] ;
121+ }
122+ angular . forEach ( updateEvent , function ( sliderEvent ) {
123+ slider . on ( sliderEvent , function ( ev ) {
124+ ngModelCtrl . $setViewValue ( ev . value ) ;
125+ $timeout ( function ( ) {
117126 $scope . $apply ( ) ;
118- } ) ;
119- }
120- } ) ;
121- } ) ;
122-
123-
124- if ( angular . isDefined ( attrs . ngDisabled ) ) {
125- $scope . $watch ( attrs . ngDisabled , function ( value ) {
126- if ( value ) {
127- slider . slider ( 'disable' ) ;
128- } else {
129- slider . slider ( 'enable' ) ;
130- }
131- } ) ;
127+ } ) ;
128+ } ) ;
129+ } ) ;
130+
131+ // Event listeners
132+ var sliderEvents = {
133+ slideStart : 'onStartSlide' ,
134+ slide : 'onSlide' ,
135+ slideStop : 'onStopSlide'
136+ } ;
137+ angular . forEach ( sliderEvents , function ( sliderEventAttr , sliderEvent ) {
138+ slider . on ( sliderEvent , function ( ev ) {
139+
140+ if ( $scope [ sliderEventAttr ] ) {
141+ var invoker = $parse ( attrs [ sliderEventAttr ] ) ;
142+ invoker ( $scope . $parent , { $event : ev , value : ev . value } ) ;
143+
144+ $timeout ( function ( ) {
145+ $scope . $apply ( ) ;
146+ } ) ;
147+ }
148+ } ) ;
149+ } ) ;
150+
151+ // deregister ngDisabled watcher to prevent memory leaks
152+ if ( angular . isFunction ( ngDisabledDeregisterFn ) ) {
153+ ngDisabledDeregisterFn ( ) ;
154+ ngDisabledDeregisterFn = null ;
155+ }
156+ if ( angular . isDefined ( attrs . ngDisabled ) ) {
157+ ngDisabledDeregisterFn = $scope . $watch ( attrs . ngDisabled , function ( value ) {
158+ if ( value ) {
159+ slider . slider ( 'disable' ) ;
160+ }
161+ else {
162+ slider . slider ( 'enable' ) ;
163+ }
164+ } ) ;
165+ }
166+ // deregister ngModel watcher to prevent memory leaks
167+ if ( angular . isFunction ( ngModelDeregisterFn ) ) ngModelDeregisterFn ( ) ;
168+ ngModelDeregisterFn = $scope . $watch ( 'ngModel' , function ( value ) {
169+ slider . slider ( 'setValue' , value ) ;
170+ } ) ;
132171 }
172+ }
133173
134-
135- $scope . $watch ( 'ngModel' , function ( value ) {
136- slider . slider ( 'setValue' , value ) ;
174+ var watchers = [ 'min' , 'max' , 'step' , 'range' ] ;
175+ angular . forEach ( watchers , function ( prop ) {
176+ $scope . $watch ( prop , function ( ) {
177+ initSlider ( ) ;
137178 } ) ;
138- } ;
139-
140- $scope . $watch ( 'max' , function ( value ) {
141- initSlider ( ) ;
142- } ) ;
143-
144- $scope . $watch ( 'min' , function ( value ) {
145- initSlider ( ) ;
146- } ) ;
147-
148- $scope . $watch ( 'step' , function ( value ) {
149- initSlider ( ) ;
150- } ) ;
151-
152- $scope . $watch ( 'range' , function ( value ) {
153- initSlider ( ) ;
154179 } ) ;
155180 }
156181 } ;
0 commit comments