Commit 4a4f7d06 authored by Valentin Hervieu's avatar Valentin Hervieu

Merge pull request #100 from coxm/draggable-bar

Draggable range
parents 4b1ddca6 e4a7295d
......@@ -106,6 +106,10 @@ $scope.priceSlider = {
> When set to true slider is used in presentation mode. No handle dragging.
**rz-slider-draggable-range**
> When set to true and using a range slider, the range can be dragged by the selection bar.
**rz-slider-translate**
> Custom translate function. Use this if you want to translate values displayed on the slider. For example if you want to display dollar amounts instead of just numbers do this:
......
......@@ -80,6 +80,23 @@
rz-slider-tpl-url="rzSliderTpl.html"></rzslider>
</article>
<article>
<h2>Draggable range example</h2>
Value: <pre>{{ priceSlider | json }}</pre>
<input type="text" ng-model="priceSlider.min"/><br/>
<input type="text" ng-model="priceSlider.max"/><br/>
<rzslider
rz-slider-draggable-range="true"
rz-slider-floor="priceSlider.floor"
rz-slider-ceil="priceSlider.ceil"
rz-slider-model="priceSlider.min"
rz-slider-high="priceSlider.max"
rz-slider-step="5"
rz-slider-tpl-url="rzSliderTpl.html"></rzslider>
</article>
</div>
</body>
......
......@@ -54,7 +54,6 @@ rzslider span.rz-bar {
rzslider span.rz-bar.rz-selection {
z-index: 1;
width: 0;
background: #0db9f0;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
......
/*! jusas-angularjs-slider - v0.1.24 - (c) Rafal Zajac <rzajac@gmail.com>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com>, https://github.com/rzajac/angularjs-slider.git - 2015-08-12 */
rzslider{position:relative;display:inline-block;width:100%;height:4px;margin:30px 0 15px 0;vertical-align:middle}rzslider span{position:absolute;display:inline-block;white-space:nowrap}rzslider span.rz-base{width:100%;height:100%;padding:0}rzslider span.rz-bar-wrapper{left:0;width:100%;height:32px;padding-top:16px;margin-top:-16px;box-sizing:border-box}rzslider span.rz-bar{left:0;z-index:0;width:100%;height:4px;background:#d8e0f3;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider span.rz-bar.rz-selection{z-index:1;width:0;background:#0db9f0;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider span.rz-pointer{top:-14px;z-index:2;width:32px;height:32px;cursor:pointer;background-color:#0db9f0;-webkit-border-radius:16px;-moz-border-radius:16px;border-radius:16px}rzslider span.rz-pointer:after{position:absolute;top:12px;left:12px;width:8px;height:8px;background:#fff;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;content:''}rzslider span.rz-pointer:hover:after{background-color:#fff}rzslider span.rz-pointer.rz-active:after{background-color:#451aff}rzslider span.rz-bubble{top:-32px;padding:1px 3px;color:#55637d;cursor:default}rzslider span.rz-bubble.rz-selection{top:16px}rzslider span.rz-bubble.rz-limit{color:#55637d}
\ No newline at end of file
/*! jusas-angularjs-slider - v0.1.25 - (c) Rafal Zajac <rzajac@gmail.com>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com>, https://github.com/rzajac/angularjs-slider.git - 2015-08-19 */
rzslider{position:relative;display:inline-block;width:100%;height:4px;margin:30px 0 15px 0;vertical-align:middle}rzslider span{position:absolute;display:inline-block;white-space:nowrap}rzslider span.rz-base{width:100%;height:100%;padding:0}rzslider span.rz-bar-wrapper{left:0;width:100%;height:32px;padding-top:16px;margin-top:-16px;box-sizing:border-box}rzslider span.rz-bar{left:0;z-index:0;width:100%;height:4px;background:#d8e0f3;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider span.rz-bar.rz-selection{z-index:1;background:#0db9f0;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px}rzslider span.rz-pointer{top:-14px;z-index:2;width:32px;height:32px;cursor:pointer;background-color:#0db9f0;-webkit-border-radius:16px;-moz-border-radius:16px;border-radius:16px}rzslider span.rz-pointer:after{position:absolute;top:12px;left:12px;width:8px;height:8px;background:#fff;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;content:''}rzslider span.rz-pointer:hover:after{background-color:#fff}rzslider span.rz-pointer.rz-active:after{background-color:#451aff}rzslider span.rz-bubble{top:-32px;padding:1px 3px;color:#55637d;cursor:default}rzslider span.rz-bubble.rz-selection{top:16px}rzslider span.rz-bubble.rz-limit{color:#55637d}
\ No newline at end of file
/*! jusas-angularjs-slider - v0.1.24 - (c) Rafal Zajac <rzajac@gmail.com>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com>, https://github.com/rzajac/angularjs-slider.git - 2015-08-12 */
angular.module("rzModule",[]).run(["$templateCache",function(a){"use strict";var b='<span class="rz-bar-wrapper"><span class="rz-bar"></span></span><span class="rz-bar rz-selection"></span><span class="rz-pointer"></span><span class="rz-pointer"></span><span class="rz-bubble rz-limit"></span><span class="rz-bubble rz-limit"></span><span class="rz-bubble"></span><span class="rz-bubble"></span><span class="rz-bubble"></span>';a.put("rzSliderTpl.html",b)}]).value("throttle",function(a,b,c){"use strict";var d,e,f,g=Date.now||function(){return(new Date).getTime()},h=null,i=0;c=c||{};var j=function(){i=c.leading===!1?0:g(),h=null,f=a.apply(d,e),d=e=null};return function(){var k=g();i||c.leading!==!1||(i=k);var l=b-(k-i);return d=this,e=arguments,0>=l?(clearTimeout(h),h=null,i=k,f=a.apply(d,e),d=e=null):h||c.trailing===!1||(h=setTimeout(j,l)),f}}).factory("RzSlider",["$timeout","$document","$window","throttle",function(a,b,c,d){"use strict";var e=function(a,b,c){this.scope=a,this.attributes=c,this.sliderElem=b,this.range=void 0!==c.rzSliderHigh&&void 0!==c.rzSliderModel,this.handleHalfWidth=0,this.alwaysShowBar=!!c.rzSliderAlwaysShowBar,this.maxLeft=0,this.precision=0,this.step=0,this.tracking="",this.minValue=0,this.maxValue=0,this.hideLimitLabels=!!c.rzSliderHideLimitLabels,this.presentOnly="true"===c.rzSliderPresentOnly,this.valueRange=0,this.initHasRun=!1,this.customTrFn=this.scope.rzSliderTranslate()||function(a){return String(a)},this.deRegFuncs=[],this.fullBar=null,this.selBar=null,this.minH=null,this.maxH=null,this.flrLab=null,this.ceilLab=null,this.minLab=null,this.maxLab=null,this.cmbLab=null,this.init()};return e.prototype={init:function(){var b,e,f,g=angular.bind(this,this.calcViewDimensions),h=this;this.initElemHandles(),this.calcViewDimensions(),this.setMinAndMax(),this.precision=void 0===this.scope.rzSliderPrecision?0:+this.scope.rzSliderPrecision,this.step=void 0===this.scope.rzSliderStep?1:+this.scope.rzSliderStep,a(function(){h.updateCeilLab(),h.updateFloorLab(),h.initHandles(),h.presentOnly||h.bindEvents()}),f=this.scope.$on("reCalcViewDimensions",g),this.deRegFuncs.push(f),angular.element(c).on("resize",g),this.initHasRun=!0,b=d(function(){h.setMinAndMax(),h.updateLowHandle(h.valueToOffset(h.scope.rzSliderModel)),h.updateSelectionBar(),h.range&&h.updateCmbLabel()},350,{leading:!1}),e=d(function(){h.setMinAndMax(),h.updateHighHandle(h.valueToOffset(h.scope.rzSliderHigh)),h.updateSelectionBar(),h.updateCmbLabel()},350,{leading:!1}),this.scope.$on("rzSliderForceRender",function(){h.resetLabelsValue(),b(),h.range&&e(),h.resetSlider()}),f=this.scope.$watch("rzSliderModel",function(a,c){a!==c&&b()}),this.deRegFuncs.push(f),f=this.scope.$watch("rzSliderHigh",function(a,b){a!==b&&e()}),this.deRegFuncs.push(f),this.scope.$watch("rzSliderFloor",function(a,b){a!==b&&h.resetSlider()}),this.deRegFuncs.push(f),f=this.scope.$watch("rzSliderCeil",function(a,b){a!==b&&h.resetSlider()}),this.deRegFuncs.push(f),this.scope.$on("$destroy",function(){h.minH.off(),h.maxH.off(),h.fullBar.off(),h.selBar.off(),angular.element(c).off("resize",g),h.deRegFuncs.map(function(a){a()})})},resetSlider:function(){this.setMinAndMax(),this.calcViewDimensions(),this.updateCeilLab(),this.updateFloorLab()},resetLabelsValue:function(){this.minLab.rzsv=void 0,this.maxLab.rzsv=void 0},initHandles:function(){this.updateLowHandle(this.valueToOffset(this.scope.rzSliderModel)),this.range&&(this.updateHighHandle(this.valueToOffset(this.scope.rzSliderHigh)),this.updateCmbLabel()),this.updateSelectionBar()},translateFn:function(a,b,c){c=void 0===c?!0:c;var d=String(c?this.customTrFn(a):a),e=!1;(void 0===b.rzsv||b.rzsv.length!==d.length||b.rzsv.length>0&&0===b.rzsw)&&(e=!0,b.rzsv=d),b.text(d),e&&this.getWidth(b)},setMinAndMax:function(){this.scope.rzSliderFloor?this.minValue=+this.scope.rzSliderFloor:this.minValue=this.scope.rzSliderFloor=0,this.scope.rzSliderCeil?this.maxValue=+this.scope.rzSliderCeil:this.scope.rzSliderCeil=this.maxValue=this.range?this.scope.rzSliderHigh:this.scope.rzSliderModel,this.scope.rzSliderStep&&(this.step=+this.scope.rzSliderStep),this.valueRange=this.maxValue-this.minValue},initElemHandles:function(){angular.forEach(this.sliderElem.children(),function(a,b){var c=angular.element(a);switch(b){case 0:this.fullBar=c;break;case 1:this.selBar=c;break;case 2:this.minH=c;break;case 3:this.maxH=c;break;case 4:this.flrLab=c;break;case 5:this.ceilLab=c;break;case 6:this.minLab=c;break;case 7:this.maxLab=c;break;case 8:this.cmbLab=c}},this),this.selBar.rzsl=0,this.minH.rzsl=0,this.maxH.rzsl=0,this.flrLab.rzsl=0,this.ceilLab.rzsl=0,this.minLab.rzsl=0,this.maxLab.rzsl=0,this.cmbLab.rzsl=0,this.hideLimitLabels&&(this.flrLab.rzAlwaysHide=!0,this.ceilLab.rzAlwaysHide=!0,this.hideEl(this.flrLab),this.hideEl(this.ceilLab)),this.range===!1&&(this.cmbLab.remove(),this.maxLab.remove(),this.maxH.rzAlwaysHide=!0,this.maxH[0].style.zIndex="-1000",this.hideEl(this.maxH)),this.range===!1&&this.alwaysShowBar===!1&&(this.maxH.remove(),this.selBar.remove())},calcViewDimensions:function(){var a=this.getWidth(this.minH);this.handleHalfWidth=a/2,this.barWidth=this.getWidth(this.fullBar),this.maxLeft=this.barWidth-a,this.getWidth(this.sliderElem),this.sliderElem.rzsl=this.sliderElem[0].getBoundingClientRect().left,this.initHasRun&&(this.updateCeilLab(),this.initHandles())},updateCeilLab:function(){this.translateFn(this.scope.rzSliderCeil,this.ceilLab),this.setLeft(this.ceilLab,this.barWidth-this.ceilLab.rzsw),this.getWidth(this.ceilLab)},updateFloorLab:function(){this.translateFn(this.scope.rzSliderFloor,this.flrLab),this.getWidth(this.flrLab)},callOnChange:function(){this.scope.rzSliderOnChange&&this.scope.rzSliderOnChange()},updateHandles:function(a,b){return this.callOnChange(),"rzSliderModel"===a?(this.updateLowHandle(b),this.updateSelectionBar(),void(this.range&&this.updateCmbLabel())):"rzSliderHigh"===a?(this.updateHighHandle(b),this.updateSelectionBar(),void(this.range&&this.updateCmbLabel())):(this.updateLowHandle(b),this.updateHighHandle(b),this.updateSelectionBar(),void this.updateCmbLabel())},updateLowHandle:function(a){var b=Math.abs(this.minH.rzsl-a);this.minLab.rzsv&&1>b||(this.setLeft(this.minH,a),this.translateFn(this.scope.rzSliderModel,this.minLab),this.setLeft(this.minLab,a-this.minLab.rzsw/2+this.handleHalfWidth),this.shFloorCeil())},updateHighHandle:function(a){this.setLeft(this.maxH,a),this.translateFn(this.scope.rzSliderHigh,this.maxLab),this.setLeft(this.maxLab,a-this.maxLab.rzsw/2+this.handleHalfWidth),this.shFloorCeil()},shFloorCeil:function(){var a=!1,b=!1;this.minLab.rzsl<=this.flrLab.rzsl+this.flrLab.rzsw+5?(a=!0,this.hideEl(this.flrLab)):(a=!1,this.showEl(this.flrLab)),this.minLab.rzsl+this.minLab.rzsw>=this.ceilLab.rzsl-this.handleHalfWidth-10?(b=!0,this.hideEl(this.ceilLab)):(b=!1,this.showEl(this.ceilLab)),this.range&&(this.maxLab.rzsl+this.maxLab.rzsw>=this.ceilLab.rzsl-10?this.hideEl(this.ceilLab):b||this.showEl(this.ceilLab),this.maxLab.rzsl<=this.flrLab.rzsl+this.flrLab.rzsw+this.handleHalfWidth?this.hideEl(this.flrLab):a||this.showEl(this.flrLab))},updateSelectionBar:function(){this.setWidth(this.selBar,Math.abs(this.maxH.rzsl-this.minH.rzsl)),this.setLeft(this.selBar,this.range?this.minH.rzsl+this.handleHalfWidth:0)},updateCmbLabel:function(){var a,b;this.minLab.rzsl+this.minLab.rzsw+10>=this.maxLab.rzsl?(this.customTrFn?(a=this.customTrFn(this.scope.rzSliderModel),b=this.customTrFn(this.scope.rzSliderHigh)):(a=this.scope.rzSliderModel,b=this.scope.rzSliderHigh),this.translateFn(a+" - "+b,this.cmbLab,!1),this.setLeft(this.cmbLab,this.selBar.rzsl+this.selBar.rzsw/2-this.cmbLab.rzsw/2),this.hideEl(this.minLab),this.hideEl(this.maxLab),this.showEl(this.cmbLab)):(this.showEl(this.maxLab),this.showEl(this.minLab),this.hideEl(this.cmbLab))},roundStep:function(a){var b=this.step,c=+((a-this.minValue)%b).toFixed(3),d=c>b/2?a+b-c:a-c;return d=d.toFixed(this.precision),+d},hideEl:function(a){return a.css({opacity:0})},showEl:function(a){return a.rzAlwaysHide?a:a.css({opacity:1})},setLeft:function(a,b){return a.rzsl=b,a.css({left:b+"px"}),b},getWidth:function(a){var b=a[0].getBoundingClientRect();return a.rzsw=b.right-b.left,a.rzsw},setWidth:function(a,b){return a.rzsw=b,a.css({width:b+"px"}),b},valueToOffset:function(a){return(a-this.minValue)*this.maxLeft/this.valueRange},offsetToValue:function(a){return a/this.maxLeft*this.valueRange+this.minValue},bindEvents:function(){this.minH.on("mousedown",angular.bind(this,this.onStart,this.minH,"rzSliderModel")),this.range&&this.maxH.on("mousedown",angular.bind(this,this.onStart,this.maxH,"rzSliderHigh")),this.fullBar.on("mousedown",angular.bind(this,this.onStart,this.minH,"rzSliderModel")),this.fullBar.on("mousedown",angular.bind(this,this.onMove,this.fullBar)),this.selBar.on("mousedown",angular.bind(this,this.onStart,this.minH,"rzSliderModel")),this.selBar.on("mousedown",angular.bind(this,this.onMove,this.selBar)),this.minH.on("touchstart",angular.bind(this,this.onStart,this.minH,"rzSliderModel")),this.range&&this.maxH.on("touchstart",angular.bind(this,this.onStart,this.maxH,"rzSliderHigh")),this.fullBar.on("touchstart",angular.bind(this,this.onStart,this.minH,"rzSliderModel")),this.fullBar.on("touchstart",angular.bind(this,this.onMove,this.fullBar)),this.selBar.on("touchstart",angular.bind(this,this.onStart,this.minH,"rzSliderModel")),this.selBar.on("touchstart",angular.bind(this,this.onMove,this.selBar))},onStart:function(a,c,d){var e,f,g=this.getEventNames(d);d.stopPropagation(),d.preventDefault(),""===this.tracking&&(this.calcViewDimensions(),this.tracking=c,a.addClass("rz-active"),e=angular.bind(this,this.onMove,a),f=angular.bind(this,this.onEnd,e),b.on(g.moveEvent,e),b.one(g.endEvent,f))},onMove:function(a,b){var c,d,e,f;if(c="clientX"in b?b.clientX:void 0===b.originalEvent?b.touches[0].clientX:b.originalEvent.touches[0].clientX,d=this.sliderElem.rzsl,e=c-d-this.handleHalfWidth,0>=e){if(0===a.rzsl)return;f=this.minValue,e=0}else if(e>=this.maxLeft){if(a.rzsl===this.maxLeft)return;f=this.maxValue,e=this.maxLeft}else f=this.offsetToValue(e),f=this.roundStep(f),e=this.valueToOffset(f);this.positionTrackingHandle(f,e)},positionTrackingHandle:function(a,b){this.range&&("rzSliderModel"===this.tracking&&a>=this.scope.rzSliderHigh?(this.scope[this.tracking]=this.scope.rzSliderHigh,this.updateHandles(this.tracking,this.maxH.rzsl),this.tracking="rzSliderHigh",this.minH.removeClass("rz-active"),this.maxH.addClass("rz-active"),this.scope.$apply()):"rzSliderHigh"===this.tracking&&a<=this.scope.rzSliderModel&&(this.scope[this.tracking]=this.scope.rzSliderModel,this.updateHandles(this.tracking,this.minH.rzsl),this.tracking="rzSliderModel",this.maxH.removeClass("rz-active"),this.minH.addClass("rz-active"),this.scope.$apply())),this.scope[this.tracking]!==a&&(this.scope[this.tracking]=a,this.updateHandles(this.tracking,b),this.scope.$apply())},onEnd:function(a,c){var d=this.getEventNames(c).moveEvent;this.minH.removeClass("rz-active"),this.maxH.removeClass("rz-active"),b.off(d,a),this.scope.$emit("slideEnded"),this.tracking=""},getEventNames:function(a){var b={moveEvent:"",endEvent:""};return a.touches||void 0!==a.originalEvent&&a.originalEvent.touches?(b.moveEvent="touchmove",b.endEvent="touchend"):(b.moveEvent="mousemove",b.endEvent="mouseup"),b}},e}]).directive("rzslider",["RzSlider",function(a){"use strict";return{restrict:"E",scope:{rzSliderFloor:"=?",rzSliderCeil:"=?",rzSliderStep:"@",rzSliderPrecision:"@",rzSliderModel:"=?",rzSliderHigh:"=?",rzSliderTranslate:"&",rzSliderHideLimitLabels:"=?",rzSliderAlwaysShowBar:"=?",rzSliderPresentOnly:"@",rzSliderOnChange:"&"},templateUrl:function(a,b){return b.rzSliderTplUrl||"rzSliderTpl.html"},link:function(b,c,d){return new a(b,c,d)}}}]);
\ No newline at end of file
/*! jusas-angularjs-slider - v0.1.25 - (c) Rafal Zajac <rzajac@gmail.com>, Jussi Saarivirta <jusasi@gmail.com>, Angelin Sirbu <angelin.sirbu@gmail.com>, https://github.com/rzajac/angularjs-slider.git - 2015-08-19 */
angular.module("rzModule",[]).run(["$templateCache",function(a){"use strict";var b='<span class="rz-bar-wrapper"><span class="rz-bar"></span></span><span class="rz-bar-wrapper"><span class="rz-bar rz-selection"></span></span><span class="rz-pointer"></span><span class="rz-pointer"></span><span class="rz-bubble rz-limit"></span><span class="rz-bubble rz-limit"></span><span class="rz-bubble"></span><span class="rz-bubble"></span><span class="rz-bubble"></span>';a.put("rzSliderTpl.html",b)}]).value("throttle",function(a,b,c){"use strict";var d,e,f,g=Date.now||function(){return(new Date).getTime()},h=null,i=0;c=c||{};var j=function(){i=c.leading===!1?0:g(),h=null,f=a.apply(d,e),d=e=null};return function(){var k=g();i||c.leading!==!1||(i=k);var l=b-(k-i);return d=this,e=arguments,0>=l?(clearTimeout(h),h=null,i=k,f=a.apply(d,e),d=e=null):h||c.trailing===!1||(h=setTimeout(j,l)),f}}).factory("RzSlider",["$timeout","$document","$window","throttle",function(a,b,c,d){"use strict";var e=function(a,b,c){this.scope=a,this.attributes=c,this.sliderElem=b,this.range=void 0!==c.rzSliderHigh&&void 0!==c.rzSliderModel,this.dragRange=this.range&&"true"===c.rzSliderDraggableRange,this.dragging={active:!1,value:0,difference:0,offset:0,lowDist:0,highDist:0},this.handleHalfWidth=0,this.alwaysShowBar=!!c.rzSliderAlwaysShowBar,this.maxLeft=0,this.precision=0,this.step=0,this.tracking="",this.minValue=0,this.maxValue=0,this.hideLimitLabels=!!c.rzSliderHideLimitLabels,this.presentOnly="true"===c.rzSliderPresentOnly,this.valueRange=0,this.initHasRun=!1,this.customTrFn=this.scope.rzSliderTranslate()||function(a){return String(a)},this.deRegFuncs=[],this.fullBar=null,this.selBar=null,this.minH=null,this.maxH=null,this.flrLab=null,this.ceilLab=null,this.minLab=null,this.maxLab=null,this.cmbLab=null,this.init()};return e.prototype={init:function(){var b,e,f,g=angular.bind(this,this.calcViewDimensions),h=this;this.initElemHandles(),this.calcViewDimensions(),this.setMinAndMax(),this.precision=void 0===this.scope.rzSliderPrecision?0:+this.scope.rzSliderPrecision,this.step=void 0===this.scope.rzSliderStep?1:+this.scope.rzSliderStep,a(function(){h.updateCeilLab(),h.updateFloorLab(),h.initHandles(),h.presentOnly||h.bindEvents()}),f=this.scope.$on("reCalcViewDimensions",g),this.deRegFuncs.push(f),angular.element(c).on("resize",g),this.initHasRun=!0,b=d(function(){h.setMinAndMax(),h.updateLowHandle(h.valueToOffset(h.scope.rzSliderModel)),h.updateSelectionBar(),h.range&&h.updateCmbLabel()},350,{leading:!1}),e=d(function(){h.setMinAndMax(),h.updateHighHandle(h.valueToOffset(h.scope.rzSliderHigh)),h.updateSelectionBar(),h.updateCmbLabel()},350,{leading:!1}),this.scope.$on("rzSliderForceRender",function(){h.resetLabelsValue(),b(),h.range&&e(),h.resetSlider()}),f=this.scope.$watch("rzSliderModel",function(a,c){a!==c&&b()}),this.deRegFuncs.push(f),f=this.scope.$watch("rzSliderHigh",function(a,b){a!==b&&e()}),this.deRegFuncs.push(f),this.scope.$watch("rzSliderFloor",function(a,b){a!==b&&h.resetSlider()}),this.deRegFuncs.push(f),f=this.scope.$watch("rzSliderCeil",function(a,b){a!==b&&h.resetSlider()}),this.deRegFuncs.push(f),this.scope.$on("$destroy",function(){h.minH.off(),h.maxH.off(),h.fullBar.off(),h.selBar.off(),angular.element(c).off("resize",g),h.deRegFuncs.map(function(a){a()})})},resetSlider:function(){this.setMinAndMax(),this.calcViewDimensions(),this.updateCeilLab(),this.updateFloorLab()},resetLabelsValue:function(){this.minLab.rzsv=void 0,this.maxLab.rzsv=void 0},initHandles:function(){this.updateLowHandle(this.valueToOffset(this.scope.rzSliderModel)),this.range&&(this.updateHighHandle(this.valueToOffset(this.scope.rzSliderHigh)),this.updateCmbLabel()),this.updateSelectionBar()},translateFn:function(a,b,c){c=void 0===c?!0:c;var d=String(c?this.customTrFn(a):a),e=!1;(void 0===b.rzsv||b.rzsv.length!==d.length||b.rzsv.length>0&&0===b.rzsw)&&(e=!0,b.rzsv=d),b.text(d),e&&this.getWidth(b)},setMinAndMax:function(){this.scope.rzSliderFloor?this.minValue=+this.scope.rzSliderFloor:this.minValue=this.scope.rzSliderFloor=0,this.scope.rzSliderCeil?this.maxValue=+this.scope.rzSliderCeil:this.scope.rzSliderCeil=this.maxValue=this.range?this.scope.rzSliderHigh:this.scope.rzSliderModel,this.scope.rzSliderStep&&(this.step=+this.scope.rzSliderStep),this.valueRange=this.maxValue-this.minValue},initElemHandles:function(){angular.forEach(this.sliderElem.children(),function(a,b){var c=angular.element(a);switch(b){case 0:this.fullBar=c;break;case 1:this.selBar=c;break;case 2:this.minH=c;break;case 3:this.maxH=c;break;case 4:this.flrLab=c;break;case 5:this.ceilLab=c;break;case 6:this.minLab=c;break;case 7:this.maxLab=c;break;case 8:this.cmbLab=c}},this),this.selBar.rzsl=0,this.minH.rzsl=0,this.maxH.rzsl=0,this.flrLab.rzsl=0,this.ceilLab.rzsl=0,this.minLab.rzsl=0,this.maxLab.rzsl=0,this.cmbLab.rzsl=0,this.hideLimitLabels&&(this.flrLab.rzAlwaysHide=!0,this.ceilLab.rzAlwaysHide=!0,this.hideEl(this.flrLab),this.hideEl(this.ceilLab)),this.range===!1&&(this.cmbLab.remove(),this.maxLab.remove(),this.maxH.rzAlwaysHide=!0,this.maxH[0].style.zIndex="-1000",this.hideEl(this.maxH)),this.range===!1&&this.alwaysShowBar===!1&&(this.maxH.remove(),this.selBar.remove()),this.dragRange&&(this.selBar.css("cursor","move"),this.selBar.addClass("rz-draggable"))},calcViewDimensions:function(){var a=this.getWidth(this.minH);this.handleHalfWidth=a/2,this.barWidth=this.getWidth(this.fullBar),this.maxLeft=this.barWidth-a,this.getWidth(this.sliderElem),this.sliderElem.rzsl=this.sliderElem[0].getBoundingClientRect().left,this.initHasRun&&(this.updateCeilLab(),this.initHandles())},updateCeilLab:function(){this.translateFn(this.scope.rzSliderCeil,this.ceilLab),this.setLeft(this.ceilLab,this.barWidth-this.ceilLab.rzsw),this.getWidth(this.ceilLab)},updateFloorLab:function(){this.translateFn(this.scope.rzSliderFloor,this.flrLab),this.getWidth(this.flrLab)},callOnChange:function(){this.scope.rzSliderOnChange&&this.scope.rzSliderOnChange()},updateHandles:function(a,b){return this.callOnChange(),"rzSliderModel"===a?(this.updateLowHandle(b),this.updateSelectionBar(),void(this.range&&this.updateCmbLabel())):"rzSliderHigh"===a?(this.updateHighHandle(b),this.updateSelectionBar(),void(this.range&&this.updateCmbLabel())):(this.updateLowHandle(b),this.updateHighHandle(b),this.updateSelectionBar(),void this.updateCmbLabel())},updateLowHandle:function(a){var b=Math.abs(this.minH.rzsl-a);this.minLab.rzsv&&1>b||(this.setLeft(this.minH,a),this.translateFn(this.scope.rzSliderModel,this.minLab),this.setLeft(this.minLab,a-this.minLab.rzsw/2+this.handleHalfWidth),this.shFloorCeil())},updateHighHandle:function(a){this.setLeft(this.maxH,a),this.translateFn(this.scope.rzSliderHigh,this.maxLab),this.setLeft(this.maxLab,a-this.maxLab.rzsw/2+this.handleHalfWidth),this.shFloorCeil()},shFloorCeil:function(){var a=!1,b=!1;this.minLab.rzsl<=this.flrLab.rzsl+this.flrLab.rzsw+5?(a=!0,this.hideEl(this.flrLab)):(a=!1,this.showEl(this.flrLab)),this.minLab.rzsl+this.minLab.rzsw>=this.ceilLab.rzsl-this.handleHalfWidth-10?(b=!0,this.hideEl(this.ceilLab)):(b=!1,this.showEl(this.ceilLab)),this.range&&(this.maxLab.rzsl+this.maxLab.rzsw>=this.ceilLab.rzsl-10?this.hideEl(this.ceilLab):b||this.showEl(this.ceilLab),this.maxLab.rzsl<=this.flrLab.rzsl+this.flrLab.rzsw+this.handleHalfWidth?this.hideEl(this.flrLab):a||this.showEl(this.flrLab))},updateSelectionBar:function(){this.setWidth(this.selBar,Math.abs(this.maxH.rzsl-this.minH.rzsl)),this.setLeft(this.selBar,this.range?this.minH.rzsl+this.handleHalfWidth:0)},updateCmbLabel:function(){var a,b;this.minLab.rzsl+this.minLab.rzsw+10>=this.maxLab.rzsl?(this.customTrFn?(a=this.customTrFn(this.scope.rzSliderModel),b=this.customTrFn(this.scope.rzSliderHigh)):(a=this.scope.rzSliderModel,b=this.scope.rzSliderHigh),this.translateFn(a+" - "+b,this.cmbLab,!1),this.setLeft(this.cmbLab,this.selBar.rzsl+this.selBar.rzsw/2-this.cmbLab.rzsw/2),this.hideEl(this.minLab),this.hideEl(this.maxLab),this.showEl(this.cmbLab)):(this.showEl(this.maxLab),this.showEl(this.minLab),this.hideEl(this.cmbLab))},roundStep:function(a){var b=this.step,c=+((a-this.minValue)%b).toFixed(3),d=c>b/2?a+b-c:a-c;return d=d.toFixed(this.precision),+d},hideEl:function(a){return a.css({opacity:0})},showEl:function(a){return a.rzAlwaysHide?a:a.css({opacity:1})},setLeft:function(a,b){return a.rzsl=b,a.css({left:b+"px"}),b},getWidth:function(a){var b=a[0].getBoundingClientRect();return a.rzsw=b.right-b.left,a.rzsw},setWidth:function(a,b){return a.rzsw=b,a.css({width:b+"px"}),b},valueToOffset:function(a){return(a-this.minValue)*this.maxLeft/this.valueRange},offsetToValue:function(a){return a/this.maxLeft*this.valueRange+this.minValue},getEventX:function(a){return"clientX"in a?a.clientX:void 0===a.originalEvent?a.touches[0].clientX:a.originalEvent.touches[0].clientX},bindEvents:function(){var a,b,c;this.dragRange?(a="rzSliderDrag",b=this.onDragStart,c=this.onDragMove):(a="rzSliderModel",b=this.onStart,c=this.onMove),this.minH.on("mousedown",angular.bind(this,this.onStart,this.minH,"rzSliderModel")),this.range&&this.maxH.on("mousedown",angular.bind(this,this.onStart,this.maxH,"rzSliderHigh")),this.fullBar.on("mousedown",angular.bind(this,this.onStart,this.minH,"rzSliderModel")),this.fullBar.on("mousedown",angular.bind(this,this.onMove,this.fullBar)),this.selBar.on("mousedown",angular.bind(this,b,this.minH,a)),this.selBar.on("mousedown",angular.bind(this,c,this.selBar)),this.minH.on("touchstart",angular.bind(this,this.onStart,this.minH,"rzSliderModel")),this.range&&this.maxH.on("touchstart",angular.bind(this,this.onStart,this.maxH,"rzSliderHigh")),this.fullBar.on("touchstart",angular.bind(this,this.onStart,this.minH,"rzSliderModel")),this.fullBar.on("touchstart",angular.bind(this,this.onMove,this.fullBar)),this.selBar.on("touchstart",angular.bind(this,b,this.minH,a)),this.selBar.on("touchstart",angular.bind(this,c,this.selBar))},onStart:function(a,c,d){var e,f,g=this.getEventNames(d);d.stopPropagation(),d.preventDefault(),""===this.tracking&&(this.calcViewDimensions(),this.tracking=c,a.addClass("rz-active"),e=angular.bind(this,this.dragging.active?this.onDragMove:this.onMove,a),f=angular.bind(this,this.onEnd,e),b.on(g.moveEvent,e),b.one(g.endEvent,f))},onMove:function(a,b){var c,d,e,f=this.getEventX(b);if(c=this.sliderElem.rzsl,d=f-c-this.handleHalfWidth,0>=d){if(0===a.rzsl)return;e=this.minValue,d=0}else if(d>=this.maxLeft){if(a.rzsl===this.maxLeft)return;e=this.maxValue,d=this.maxLeft}else e=this.offsetToValue(d),e=this.roundStep(e),d=this.valueToOffset(e);this.positionTrackingHandle(e,d)},onDragStart:function(a,b,c){var d=this.getEventX(c)-this.sliderElem.rzsl-this.handleHalfWidth;this.dragging={active:!0,value:this.offsetToValue(d),difference:this.scope.rzSliderHigh-this.scope.rzSliderModel,offset:d,lowDist:d-this.minH.rzsl,highDist:this.maxH.rzsl-d},this.minH.addClass("rz-active"),this.maxH.addClass("rz-active"),this.onStart(a,b,c)},onDragMove:function(a,b){var c,d,e,f,g=this.getEventX(b)-this.sliderElem.rzsl-this.handleHalfWidth;if(g<=this.dragging.lowDist){if(a.rzsl===this.dragging.lowDist)return;e=this.minValue,c=0,f=this.dragging.difference,d=this.valueToOffset(f)}else if(g>=this.maxLeft-this.dragging.highDist){if(a.rzsl===this.dragging.highDist)return;f=this.maxValue,d=this.maxLeft,e=this.maxValue-this.dragging.difference,c=this.valueToOffset(e)}else e=this.offsetToValue(g-this.dragging.lowDist),e=this.roundStep(e),c=this.valueToOffset(e),f=e+this.dragging.difference,d=this.valueToOffset(f);this.positionTrackingBar(e,f,c,d)},positionTrackingBar:function(a,b,c,d){this.scope.rzSliderModel=a,this.scope.rzSliderHigh=b,this.updateHandles("rzSliderModel",c),this.updateHandles("rzSliderHigh",d),this.scope.$apply()},positionTrackingHandle:function(a,b){this.range&&("rzSliderModel"===this.tracking&&a>=this.scope.rzSliderHigh?(this.scope[this.tracking]=this.scope.rzSliderHigh,this.updateHandles(this.tracking,this.maxH.rzsl),this.tracking="rzSliderHigh",this.minH.removeClass("rz-active"),this.maxH.addClass("rz-active"),this.scope.$apply()):"rzSliderHigh"===this.tracking&&a<=this.scope.rzSliderModel&&(this.scope[this.tracking]=this.scope.rzSliderModel,this.updateHandles(this.tracking,this.minH.rzsl),this.tracking="rzSliderModel",this.maxH.removeClass("rz-active"),this.minH.addClass("rz-active"),this.scope.$apply())),this.scope[this.tracking]!==a&&(this.scope[this.tracking]=a,this.updateHandles(this.tracking,b),this.scope.$apply())},onEnd:function(a,c){var d=this.getEventNames(c).moveEvent;this.minH.removeClass("rz-active"),this.maxH.removeClass("rz-active"),b.off(d,a),this.scope.$emit("slideEnded"),this.tracking="",this.dragging.active=!1},getEventNames:function(a){var b={moveEvent:"",endEvent:""};return a.touches||void 0!==a.originalEvent&&a.originalEvent.touches?(b.moveEvent="touchmove",b.endEvent="touchend"):(b.moveEvent="mousemove",b.endEvent="mouseup"),b}},e}]).directive("rzslider",["RzSlider",function(a){"use strict";return{restrict:"E",scope:{rzSliderFloor:"=?",rzSliderCeil:"=?",rzSliderStep:"@",rzSliderPrecision:"@",rzSliderModel:"=?",rzSliderHigh:"=?",rzSliderDraggable:"@",rzSliderTranslate:"&",rzSliderHideLimitLabels:"=?",rzSliderAlwaysShowBar:"=?",rzSliderPresentOnly:"@",rzSliderOnChange:"&"},templateUrl:function(a,b){return b.rzSliderTplUrl||"rzSliderTpl.html"},link:function(b,c,d){return new a(b,c,d)}}}]);
\ No newline at end of file
......@@ -17,7 +17,7 @@ angular.module('rzModule', [])
.run(['$templateCache', function($templateCache) {
'use strict';
var template = '<span class="rz-bar-wrapper"><span class="rz-bar"></span></span>' + // 0 The slider bar
'<span class="rz-bar rz-selection"></span>' + // 1 Highlight between two handles
'<span class="rz-bar-wrapper"><span class="rz-bar rz-selection"></span></span>' + // 1 Highlight between two handles
'<span class="rz-pointer"></span>' + // 2 Left slider handle
'<span class="rz-pointer"></span>' + // 3 Right slider handle
'<span class="rz-bubble rz-limit"></span>' + // 4 Floor label
......@@ -115,6 +115,27 @@ function throttle(func, wait, options) {
*/
this.range = attributes.rzSliderHigh !== undefined && attributes.rzSliderModel !== undefined;
/**
* Whether to allow draggable range
*
* @type {boolean} Set to true for draggable range slider
*/
this.dragRange = this.range && attributes.rzSliderDraggableRange === 'true';
/**
* Values recorded when first dragging the bar
*
* @type {Object}
*/
this.dragging = {
active: false,
value: 0,
difference: 0,
offset: 0,
lowDist: 0,
highDist: 0
};
/**
* Half of the width of the slider handles
*
......@@ -510,6 +531,13 @@ function throttle(func, wait, options) {
this.maxH.remove();
this.selBar.remove();
}
// If using draggable range, use appropriate cursor for this.selBar.
if (this.dragRange)
{
this.selBar.css('cursor', 'move');
this.selBar.addClass('rz-draggable');
}
},
/**
......@@ -852,6 +880,26 @@ function throttle(func, wait, options) {
// Events
/**
* Get the X-coordinate of an event
*
* @param {Object} event The event
* @returns {number}
*/
getEventX: function(event)
{
/* http://stackoverflow.com/a/12336075/282882 */
//noinspection JSLint
if('clientX' in event)
{
return event.clientX;
}
return event.originalEvent === undefined ?
event.touches[0].clientX
: event.originalEvent.touches[0].clientX;
},
/**
* Bind mouse and touch events to slider handles
*
......@@ -859,19 +907,34 @@ function throttle(func, wait, options) {
*/
bindEvents: function()
{
var barTracking, barStart, barMove;
if (this.dragRange)
{
barTracking = 'rzSliderDrag';
barStart = this.onDragStart;
barMove = this.onDragMove;
}
else
{
barTracking = 'rzSliderModel';
barStart = this.onStart;
barMove = this.onMove;
}
this.minH.on('mousedown', angular.bind(this, this.onStart, this.minH, 'rzSliderModel'));
if(this.range) { this.maxH.on('mousedown', angular.bind(this, this.onStart, this.maxH, 'rzSliderHigh')); }
this.fullBar.on('mousedown', angular.bind(this, this.onStart, this.minH, 'rzSliderModel'));
this.fullBar.on('mousedown', angular.bind(this, this.onMove, this.fullBar));
this.selBar.on('mousedown', angular.bind(this, this.onStart, this.minH, 'rzSliderModel'));
this.selBar.on('mousedown', angular.bind(this, this.onMove, this.selBar));
this.selBar.on('mousedown', angular.bind(this, barStart, this.minH, barTracking));
this.selBar.on('mousedown', angular.bind(this, barMove, this.selBar));
this.minH.on('touchstart', angular.bind(this, this.onStart, this.minH, 'rzSliderModel'));
if(this.range) { this.maxH.on('touchstart', angular.bind(this, this.onStart, this.maxH, 'rzSliderHigh')); }
this.fullBar.on('touchstart', angular.bind(this, this.onStart, this.minH, 'rzSliderModel'));
this.fullBar.on('touchstart', angular.bind(this, this.onMove, this.fullBar));
this.selBar.on('touchstart', angular.bind(this, this.onStart, this.minH, 'rzSliderModel'));
this.selBar.on('touchstart', angular.bind(this, this.onMove, this.selBar));
this.selBar.on('touchstart', angular.bind(this, barStart, this.minH, barTracking));
this.selBar.on('touchstart', angular.bind(this, barMove, this.selBar));
},
/**
......@@ -899,7 +962,7 @@ function throttle(func, wait, options) {
pointer.addClass('rz-active');
ehMove = angular.bind(this, this.onMove, pointer);
ehMove = angular.bind(this, this.dragging.active ? this.onDragMove : this.onMove, pointer);
ehEnd = angular.bind(this, this.onEnd, ehMove);
$document.on(eventNames.moveEvent, ehMove);
......@@ -915,20 +978,8 @@ function throttle(func, wait, options) {
*/
onMove: function (pointer, event)
{
var eventX, sliderLO, newOffset, newValue;
/* http://stackoverflow.com/a/12336075/282882 */
//noinspection JSLint
if('clientX' in event)
{
eventX = event.clientX;
}
else
{
eventX = event.originalEvent === undefined ?
event.touches[0].clientX
: event.originalEvent.touches[0].clientX;
}
var eventX = this.getEventX(event),
sliderLO, newOffset, newValue;
sliderLO = this.sliderElem.rzsl;
newOffset = eventX - sliderLO - this.handleHalfWidth;
......@@ -955,6 +1006,92 @@ function throttle(func, wait, options) {
this.positionTrackingHandle(newValue, newOffset);
},
/**
* onDragStart event handler
*
* Handles dragging of the middle bar.
*
* @param {Object} pointer The jqLite wrapped DOM element
* @param {string} ref One of the refLow, refHigh values
* @param {Event} event The event
* @returns {undefined}
*/
onDragStart: function(pointer, ref, event)
{
var offset = this.getEventX(event) - this.sliderElem.rzsl - this.handleHalfWidth;
this.dragging = {
active: true,
value: this.offsetToValue(offset),
difference: this.scope.rzSliderHigh - this.scope.rzSliderModel,
offset: offset,
lowDist: offset - this.minH.rzsl,
highDist: this.maxH.rzsl - offset
};
this.minH.addClass('rz-active');
this.maxH.addClass('rz-active');
this.onStart(pointer, ref, event);
},
/**
* onDragMove event handler
*
* Handles dragging of the middle bar.
*
* @param {jqLite} pointer
* @param {Event} event The event
* @returns {undefined}
*/
onDragMove: function(pointer, event)
{
var newOffset = this.getEventX(event) - this.sliderElem.rzsl - this.handleHalfWidth,
newMinOffset, newMaxOffset,
newMinValue, newMaxValue;
if (newOffset <= this.dragging.lowDist)
{
if (pointer.rzsl === this.dragging.lowDist) { return; }
newMinValue = this.minValue;
newMinOffset = 0;
newMaxValue = this.dragging.difference;
newMaxOffset = this.valueToOffset(newMaxValue);
}
else if (newOffset >= this.maxLeft - this.dragging.highDist)
{
if (pointer.rzsl === this.dragging.highDist) { return; }
newMaxValue = this.maxValue;
newMaxOffset = this.maxLeft;
newMinValue = this.maxValue - this.dragging.difference;
newMinOffset = this.valueToOffset(newMinValue);
}
else
{
newMinValue = this.offsetToValue(newOffset - this.dragging.lowDist);
newMinValue = this.roundStep(newMinValue);
newMinOffset = this.valueToOffset(newMinValue);
newMaxValue = newMinValue + this.dragging.difference;
newMaxOffset = this.valueToOffset(newMaxValue);
}
this.positionTrackingBar(newMinValue, newMaxValue, newMinOffset, newMaxOffset);
},
/**
* Set the new value and offset for the entire bar
*
* @param {number} newMinValue the new minimum value
* @param {number} newMaxValue the new maximum value
* @param {number} newMinOffset the new minimum offset
* @param {number} newMaxOffset the new maximum offset
*/
positionTrackingBar: function(newMinValue, newMaxValue, newMinOffset, newMaxOffset)
{
this.scope.rzSliderModel = newMinValue;
this.scope.rzSliderHigh = newMaxValue;
this.updateHandles('rzSliderModel', newMinOffset);
this.updateHandles('rzSliderHigh', newMaxOffset);
this.scope.$apply();
},
/**
* Set the new value and offset to the current tracking handle
......@@ -964,7 +1101,7 @@ function throttle(func, wait, options) {
*/
positionTrackingHandle: function(newValue, newOffset)
{
if (this.range)
if(this.range)
{
/* This is to check if we need to switch the min and max handles*/
if (this.tracking === 'rzSliderModel' && newValue >= this.scope.rzSliderHigh)
......@@ -1015,6 +1152,8 @@ function throttle(func, wait, options) {
this.scope.$emit('slideEnded');
this.tracking = '';
this.dragging.active = false;
},
/**
......@@ -1059,6 +1198,7 @@ function throttle(func, wait, options) {
rzSliderPrecision: '@',
rzSliderModel: '=?',
rzSliderHigh: '=?',
rzSliderDraggable: '@',
rzSliderTranslate: '&',
rzSliderHideLimitLabels: '=?',
rzSliderAlwaysShowBar: '=?',
......
......@@ -69,7 +69,6 @@ rzslider span.rz-bar {
}
rzslider span.rz-bar.rz-selection {
width: 0%;
z-index: 1;
background: @barFillColor;
.rounded(@barHeight/2);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment