From caf6ca78bace4340061f83b2fd6b75b8d58aefad Mon Sep 17 00:00:00 2001 From: David Thomas Date: Mon, 31 Aug 2015 09:50:51 -0400 Subject: [PATCH 1/2] updates to support range list usage only --- demo/index.html | 75 ++++------------------------ dist/rzslider.css | 86 ++++++++++++++++++++++++++------ rzslider.js | 123 +++++++++++++++++++++++++++++++++++++--------- 3 files changed, 180 insertions(+), 104 deletions(-) diff --git a/demo/index.html b/demo/index.html index 486e5d1..7445493 100644 --- a/demo/index.html +++ b/demo/index.html @@ -4,7 +4,7 @@ - AngularJS Touch Slider + AngularJS Touch Slider - Range List Fork @@ -14,70 +14,25 @@
-

AngularJS Touch Slider

+

AngularJS Touch Slider - Range List Fork

-

Min/max slider example

- Value:
{{ slider_data | json }}
- - -
- -
-

Min/max slider example

+

Min/max slider example with Range List

Value:
{{ priceSlider | json }}


-
- -
-

Currency slider example

- - Value: {{ priceSlider2 | json }} -
-
-

One value slider example

- - Value: {{ priceSlider3 | json }} - -
- -
-

Alphabet slider example

- Value: {{ alphabetTranslate(letter) }} - -
@@ -90,26 +45,14 @@

Alphabet slider example

app.controller('MainCtrl', function($scope) { $scope.priceSlider = { - min: 100, - max: 400, - ceil: 500, - floor: 0 + min: 1, + max: 3, + rangeList: ['0%', '50%', '75%', '90%', '100%' ] }; - $scope.priceSlider2 = 150; - $scope.priceSlider3 = 250; - $scope.translate = function(value) { - return '$' + value; - }; - - var alphabetArray = 'abcdefghijklmnopqrstuvwxyz'.split(''); - $scope.letter = 5; - $scope.letterMax = alphabetArray.length - 1; - $scope.alphabetTranslate = function(value) - { - return alphabetArray[value].toUpperCase(); + return $scope.priceSlider.rangeList[value]; }; $scope.slider_data = {value: 1}; diff --git a/dist/rzslider.css b/dist/rzslider.css index 73684c5..b43a74d 100644 --- a/dist/rzslider.css +++ b/dist/rzslider.css @@ -15,8 +15,8 @@ rzslider { position: relative; display: inline-block; width: 100%; - height: 4px; - margin: 30px 0 15px 0; + height: 25px; + margin: 10px 0 15px 0; vertical-align: middle; } @@ -45,8 +45,8 @@ rzslider span.rz-bar { left: 0; z-index: 0; width: 100%; - height: 4px; - background: #d8e0f3; + height: 8px; + background: none; -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; @@ -55,17 +55,17 @@ rzslider span.rz-bar { rzslider span.rz-bar.rz-selection { z-index: 1; width: 0; - background: #0db9f0; + background: rgb(0, 91, 142); -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; } rzslider span.rz-pointer { - top: -14px; + top: -12px; z-index: 2; - width: 32px; - height: 32px; + /*width: 32px; + height: 32px;*/ cursor: pointer; background-color: #0db9f0; -webkit-border-radius: 16px; @@ -75,15 +75,15 @@ rzslider span.rz-pointer { rzslider span.rz-pointer:after { position: absolute; - top: 12px; - left: 12px; - width: 8px; - height: 8px; + top: 11px; + width: 10px; + height: 10px; background: #ffffff; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; content: ''; + border: thin rgb(87, 88, 86) solid; } rzslider span.rz-pointer:hover:after { @@ -91,11 +91,12 @@ rzslider span.rz-pointer:hover:after { } rzslider span.rz-pointer.rz-active:after { - background-color: #451aff; + background-color: rgb(0, 91, 142); } rzslider span.rz-bubble { - top: -32px; + display: none; + top: 15px; padding: 1px 3px; color: #55637d; cursor: default; @@ -107,4 +108,59 @@ rzslider span.rz-bubble.rz-selection { rzslider span.rz-bubble.rz-limit { color: #55637d; -} \ No newline at end of file + left: -10px; +} + +rzslider span.rz-bubble.rz-limit:nth-child(2){ + margin-left: 20px; +} + +rzslider .rz-pips-container { + position: relative; + top: 4px; + width: 100%; + border-left: thin rgb(87, 88, 86) solid; + border-right: thin rgb(87, 88, 86) solid; + border-top: thin rgb(87, 88, 86) solid; + height: 10px; + display: block; +} + +.rzSlider-pip-mark { + position: absolute; + border-left: thin rgb(87, 88, 86) solid; + display: block; + width: 5px; + height: 10px; +} + +.rzSliderValueContainer { + color: #3A3F44; +} + +.rzSliderValueContainer div:first-child { + float: left; +} + +.rzSliderValueContainer div:last-child { + float: right; +} + +.rzSliderSetValue { + color: white; +} + +.rz-pip-labels{ + position: relative; + display: block; + width: 100%; +} + +.rz-pip-labels span { + position: absolute; + top: 3px; + display: block; + width: 100px; + text-align: center; + font-size: 12px; +} diff --git a/rzslider.js b/rzslider.js index 1646831..f28fc09 100644 --- a/rzslider.js +++ b/rzslider.js @@ -1,7 +1,12 @@ /** - * Angular JS slider directive + * Customized Staffer Slider, Forked from Angular JS slider directive * - * (c) Rafal Zajac + * Fork by David Thomas + * http://github.com/rzajac/angularjs-slider + * + * Version: v1.0.0 + * + * Original by (c) Rafal Zajac * http://github.com/rzajac/angularjs-slider * * Version: v0.1.21 @@ -24,7 +29,9 @@ angular.module('rzModule', []) '' + // 5 Ceiling label '' + // 6 Label above left slider handle '' + // 7 Label above right slider handle - ''; // 8 Range label when the slider handles are close ex. 15 - 17 + '' + // 8 Range label when the slider handles are close ex. 15 - 17 + '' + // pip marks + ''; // pip mark labels $templateCache.put('rzSliderTpl.html', template); }]) @@ -171,6 +178,13 @@ function throttle(func, wait, options) { */ this.maxValue = 0; + /** + * Pixels to adjust the display of slider handles + * + * @type {number} + */ + this.sliderHandleOffset = -4; + /** * Hide limit labels * @@ -206,7 +220,9 @@ function throttle(func, wait, options) { * * @type {function} */ - this.customTrFn = this.scope.rzSliderTranslate() || function(value) { return String(value); }; + this.customTrFn = this.scope.rzSliderTranslate() || function(value) { + return String(this.scope.rzSliderRangeList[value]); + }; /** * Array of de-registration functions to call on $destroy @@ -251,6 +267,9 @@ function throttle(func, wait, options) { this.precision = this.scope.rzSliderPrecision === undefined ? 0 : +this.scope.rzSliderPrecision; this.step = this.scope.rzSliderStep === undefined ? 1 : +this.scope.rzSliderStep; + // build pips + this.addPips(); + $timeout(function() { self.updateCeilLab(); @@ -273,7 +292,7 @@ function throttle(func, wait, options) { thrLow = throttle(function() { self.setMinAndMax(); - self.updateLowHandle(self.valueToOffset(self.scope.rzSliderModel)); + self.updateLowHandle(self.valueToOffset(self.scope.rzSliderModel) + self.sliderHandleOffset); self.updateSelectionBar(); if(self.range) @@ -286,7 +305,7 @@ function throttle(func, wait, options) { thrHigh = throttle(function() { self.setMinAndMax(); - self.updateHighHandle(self.valueToOffset(self.scope.rzSliderHigh)); + self.updateHighHandle(self.valueToOffset(self.scope.rzSliderHigh) + self.sliderHandleOffset); self.updateSelectionBar(); self.updateCmbLabel(); }, 350, { leading: false }); @@ -371,11 +390,11 @@ function throttle(func, wait, options) { */ initHandles: function() { - this.updateLowHandle(this.valueToOffset(this.scope.rzSliderModel)); + this.updateLowHandle(this.valueToOffset(this.scope.rzSliderModel) + this.sliderHandleOffset); if(this.range) { - this.updateHighHandle(this.valueToOffset(this.scope.rzSliderHigh)); + this.updateHighHandle(this.valueToOffset(this.scope.rzSliderHigh) + this.sliderHandleOffset); this.updateCmbLabel(); } @@ -416,24 +435,34 @@ function throttle(func, wait, options) { */ setMinAndMax: function() { - if(this.scope.rzSliderFloor) - { - this.minValue = +this.scope.rzSliderFloor; - } - else - { + // range list functionality + if(this.scope.rzSliderRangeList && this.scope.rzSliderRangeList.length > 0){ + // always set min value to 0 to equal the first element of array this.minValue = this.scope.rzSliderFloor = 0; - } + // always set max value to the last item of the array + this.maxValue = this.scope.rzSliderCeil = this.scope.rzSliderRangeList.length - 1; - if(this.scope.rzSliderCeil) - { - this.maxValue = +this.scope.rzSliderCeil; - } - else - { - this.scope.rzSliderCeil = this.maxValue = this.range ? this.scope.rzSliderHigh : this.scope.rzSliderModel; + }else{ + if(this.scope.rzSliderFloor) + { + this.minValue = +this.scope.rzSliderFloor; + } + else + { + this.minValue = this.scope.rzSliderFloor = 0; + } + + if(this.scope.rzSliderCeil) + { + this.maxValue = +this.scope.rzSliderCeil; + } + else + { + this.scope.rzSliderCeil = this.maxValue = this.range ? this.scope.rzSliderHigh : this.scope.rzSliderModel; + } } + if(this.scope.rzSliderStep) { this.step = +this.scope.rzSliderStep; @@ -442,6 +471,49 @@ function throttle(func, wait, options) { this.valueRange = this.maxValue - this.minValue; }, + /** + * Add pips to the slider bar + * + * @returns {undefined} + */ + addPips: function() + { + // how many pips? as many as are in array + var pips = this.scope.rzSliderRangeList; + var str = '', labelStr = '', tempVal = 0, tempLength = 0;; + var maxVal = this.maxLeft - 15; + // Left offset of pip lables, in Pixels + var pipLabelOffset = 50; + var pipMiddleLabelOffset = -3; + var pipFirstLabelOffset = (pipLabelOffset) * -1; + var pipLastLabelOffset = this.maxLeft - pipLabelOffset; + + // Handle very long labels for first/last strings + pipFirstLabelOffset = pips[0].length < 6 ? pipFirstLabelOffset : pipFirstLabelOffset + 10; + pipLastLabelOffset = pips[pips.length - 1].length < 6 ? pipLastLabelOffset : pipLastLabelOffset - 10; + + // first label + labelStr = ''+pips[0]+''; + // last label + labelStr += ''+pips[pips.length-1]+''; + + if(this.scope.rzShowMidLabels !== false){ + for(var x = 1; x < pips.length-1; x++){ + str += ''; + // middle labels + //tempLength = 2 * pips.[x] + tempVal = this.roundStep(this.valueToOffset(x)) - pipLabelOffset - pipMiddleLabelOffset; + labelStr += ''+pips[x]+'' + } + } + + this.sliderElem.find('rz-pips-container').html(str); + + var pipLabelTar = this.sliderElem.find('rz-pip-labels'); + + pipLabelTar.html(labelStr); + + }, /** * Set the slider children to variables for easy access * @@ -822,6 +894,9 @@ function throttle(func, wait, options) { */ valueToOffset: function(val) { + // support array index values + // if value is negative count from end of list + val = (val < 0) ? this.scope.rzSliderRangeList.length + (val -1) : val; return (val - this.minValue) * this.maxLeft / this.valueRange; }, @@ -936,7 +1011,7 @@ function throttle(func, wait, options) { else { newValue = this.offsetToValue(newOffset); newValue = this.roundStep(newValue); - newOffset = this.valueToOffset(newValue); + newOffset = this.valueToOffset(newValue) + this.sliderHandleOffset; } this.positionTrackingHandle(newValue, newOffset); }, @@ -1044,6 +1119,8 @@ function throttle(func, wait, options) { rzSliderStep: '@', rzSliderPrecision: '@', rzSliderModel: '=?', + rzSliderRangeList: '=', + rzShowMidLabels: '=', rzSliderHigh: '=?', rzSliderTranslate: '&', rzSliderHideLimitLabels: '=?', From 083207f5e37370a3285ce219bfcb67adef6d8cb4 Mon Sep 17 00:00:00 2001 From: David Thomas Date: Mon, 31 Aug 2015 10:39:35 -0400 Subject: [PATCH 2/2] updating documentation for range list slider fork --- README.md | 174 ++++++++---------------------------------------- demo/index.html | 21 ++---- 2 files changed, 36 insertions(+), 159 deletions(-) diff --git a/README.md b/README.md index e85c3a8..61f9d7a 100644 --- a/README.md +++ b/README.md @@ -1,174 +1,58 @@ -## AngularJS slider directive with no external dependencies +## AngularJS slider directive - Range List Fork -Slider directive implementation for AngularJS, without any dependencies. +This is a fork of the original AngularJS slider directive by rzajac found here: https://github.com/rzajac/angularjs-slider -- Mobile friendly -- Fast -- Well documented -- Customizable -- Simple to use -- Compatibility with jQuery Lite, ie. with full jQuery ( Thanks Jusas! https://github.com/Jusas) +This repository is only stable for use as a Range List slider as detailed below. This fork is not verified to work with other variations of the slider directive documented in the original repository. -## Reporting issues -Make sure the report is accompanied by a reproducible demo. The ideal demo is created by forking [our standard jsFiddle](http://jsfiddle.net/pq7yr6d6/), adding your own code and stripping it down to an absolute minimum needed to demonstrate the bug. +This repository only offers one alternate use of the slider directive and is not meant to be merged back into the original library. +## Range List Slider -## Examples +The Range List Slider version of the slider directive provides one new use case offering the following features/changes: -[http://rzajac.github.io/angularjs-slider/](http://rzajac.github.io/angularjs-slider/) + - adds new rz-slider-range-list attribute which provides an array of strings representing custom values to be used as steps in slider + - adds slider pips with labels - customizable for labeling every step or only first/last step + - moves slider labels below to align with pips + - removes use of ceil and floor values, instead using first and last array positions from rz-slider-range-list + - sets the step value to 1 to correspond with each item in rz-slider-range-list array -### Single slider +## Example ```javascript // In your controller -$scope.priceSlider = 150; -``` - -```html -
- -
-``` - -Above example would render a slider from 0 to 150. If you need floor and ceiling values use `rz-slider-floor` and `rz-slider-ceil` attributes. - -```html -
- - - - - - -
-``` - -### Range slider - -```javascript -// In your controller -$scope.priceSlider = { - min: 100, - max: 180, - ceil: 500, - floor: 0 +$scope.rangeSlider = { + min: 1, + max: 3, + rangeList: ['0%', '50%', '75%', '90%', '100%' ] }; ``` ```html + rz-slider-model="rangeSlider.min" + rz-slider-high="rangeSlider.max" + rz-slider-range-list="rangeSlider.rangeList" + rz-slider-tpl-url="rzSliderTpl.html"> ``` ## Directive attributes -**rz-slider-model** - -> Model for low value slider. If only _rz-slider-model_ is provided single slider will be rendered. - -**rz-slider-high** - -> Model for high value slider. Providing both _rz-slider-high_ and _rz-slider-model_ will render range slider. - -**rz-slider-floor** - -> Minimum value for a slider. - -**rz-slider-ceil** - -> Maximum value for a slider. - -**rz-slider-step** - -> slider step. - -**rz-slider-precision** - -> The precision to display values with. The `toFixed()` is used internally for this. - -**rz-slider-hide-limit-labels** +**rz-slider-range-list** -> Set to true to hide min / max labels +> Array of strings representing custom values for slider range. Min/Max values correspond to items in array while translations display string value of items in array. -**rz-slider-always-show-bar** - -> Set to true to always show selection bar - -**rz-slider-present-only** - -> When set to true slider is used in presentation mode. No handle dragging. - -**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: - -```javascript -// In your controller - -$scope.priceSlider = { - min: 100, - max: 180, - ceil: 500, - floor: 0 -}; - -$scope.translate = function(value) -{ - return '$' + value; -} -``` - -```html - -``` - -## Slider events - -To force slider to recalculate dimensions broadcast **reCalcViewDimensions** event from parent scope. This is useful for example when you use slider inside a widget where the content is hidden at start - see the "Sliders into modal" example [on the demo site](http://rzajac.github.io/angularjs-slider/). - -You can also force redraw with **rzSliderForceRender** event. - -At the end of each "slide" slider emits `slideEnded` event. - -```javascript -$scope.$on("slideEnded", function() { - // user finished sliding a handle -}); -``` - -## Project integration - -```html - - +**rz-slider-model** - -``` +> Model for low value slider. Corresponds to an item in rz-slider-range-list array -## Browser support +**rz-slider-high** -I use Slider on couple of my projects and it's being tested on desktop versions of Chrome, Firefox, Safari, IE 9/10. -Slider is also tested on Android and iPhone using all browsers available on those platforms. +> Model for low value slider. Corresponds to an item in rz-slider-range-list array -## Disclaimer +**rz-show-mid-labels** -This project is based on [https://github.com/prajwalkman/angular-slider](https://github.com/prajwalkman/angular-slider). It has been rewritten from scratch in JavaScript - (the original source was written in CoffeeScript). +> boolean value to determine if middle pip labels are displayed. Use when lables are very long strings +and you only want the cieling and floor values displayed. Defaults to "true" if value is omitted. Set to "false" to turn off middle pip labels. ## License diff --git a/demo/index.html b/demo/index.html index 7445493..deed6b9 100644 --- a/demo/index.html +++ b/demo/index.html @@ -19,17 +19,15 @@

AngularJS Touch Slider - Range List Fork

Min/max slider example with Range List

- Value:
{{ priceSlider | json }}
+ Value:
{{ rangeSlider | json }}
-
-
+ Min: {{ rangeSlider.rangeList[rangeSlider.min] }} +
Max: {{ rangeSlider.rangeList[rangeSlider.max] }}
@@ -44,17 +42,12 @@

Min/max slider example with Range List

app.controller('MainCtrl', function($scope) { - $scope.priceSlider = { + $scope.rangeSlider = { min: 1, max: 3, rangeList: ['0%', '50%', '75%', '90%', '100%' ] }; - $scope.translate = function(value) - { - return $scope.priceSlider.rangeList[value]; - }; - $scope.slider_data = {value: 1}; });