Skip to content

Instantly share code, notes, and snippets.

@11111000000
Created March 15, 2014 01:55
Show Gist options
  • Save 11111000000/9560749 to your computer and use it in GitHub Desktop.
Save 11111000000/9560749 to your computer and use it in GitHub Desktop.
Angular range directive (LiveScript)
angular.module \app.directives .directive \myrange, [
\$compile
\$timeout
\$parse
\$log
($compile, $timeout, $parse, $log)->
restrict: \A
require: \ngModel
templateUrl: \myrange-template
replace: true
scope: {}
priority: 1
#scope:
#model: \=ngModel
link: !($scope,element,$attrs,$ngModel)->
debug = off
log = $log.instance from: \myrange
if not $attrs.max?
log "ERROR: max range undefined"
return
STEP = parseFloat($attrs.step) or 1
MIN = parseFloat($attrs.min) or 0
MAX = $attrs.max |> parseFloat
ITEMS = [ MIN to MAX by STEP ]
if abs( STEP - Math.floor(STEP) ) > 0
ITEMS = ITEMS |> map -> it |> toFixedOrInt 2
if (last ITEMS) != MAX
ITEMS.push MAX
#
# PARSE & FORMAT
#
$ngModel.$parsers.push ->
it |> ->
| $attrs.suffix? and it? => it |> strWithSuffix
| _ => "#{it}"
$ngModel.$formatters.push ->
it |> ->
| not it? or not it => void
| (it |> $.trim) == '' => void
| $attrs.suffix? => it |> strWithoutSuffix |> parseFloat
| otherwise => it |> $.trim |> parseFloat
$ngModel.$render = ->
debug and log \$render, $ngModel.$viewValue, $ngModel.$modelValue, $attrs.ngModel
$scope.item = $ngModel.$viewValue
[ elRange, elDragger] =
[ element.find \.range
element.find \.range>.dragger ]
draggerSize = -> elDragger |> (.width!)
rangeSize = -> elRange.width! - draggerSize! - 2
keepInside = -> it |> between 0, $scope.rangeSize
strWithSuffix = ->
_=
| not it? => ''
| it? and $attrs.suffix? => "#{it}#{$attrs.suffix or ''}"
| _ => "#it"
strWithoutSuffix = ->
it |> ->
| it? => "#{it}" |> -> ($attrs.suffix `it.replace` '') |> $.trim
| _ => ''
coord2item = ->
| (it <= 0) => head ITEMS
| (it >= $scope.rangeSize) => last ITEMS
| _ => ITEMS[ div it, ($scope.rangeSize / ITEMS.length) ]
val2item = ->
isNum = angular.isNumber
_ =
| isNum and +val > +ITEMS[* - 2] => ITEMS[* - 1]
| isNum and +val < +ITEMS[1] => ITEMS[0]
| isNum and val not in ITEMS => ITEMS.indexOf minimum [abs((+x) - (+val)) for x in ITEMS]
| _ => ((ITEMS.indexOf val) or 0) * ($scope.rangeSize / ITEMS.length)
item2coord = (val)->
val = +val
#
nears = [abs((+x) - (+val)) for x in ITEMS]
nearIndex = nears.indexOf minimum nears
isNum = val |> angular.isNumber
_ =
| isNum and val > ITEMS[* - 2] => $scope.rangeSize
| isNum and val < ITEMS[1] => 0
| isNum and not (val in ITEMS) => nearIndex * ($scope.rangeSize / ITEMS.length)
| val in ITEMS => ((ITEMS.indexOf val) or 0) * ($scope.rangeSize / ITEMS.length)
| _ => 0
dragTimeout = void
$scope <<<<
text: ''
noInput: !!$attrs.noInput?
draggerDragStart: ($event,drag)->
debug and log \draggerDragStart
$event.preventDefault!
draggerDrag: ($event,drag)->
debug and log \draggerDrag
offsetX = drag.offsetX |> keepInside
item = offsetX |> coord2item
if not dragTimeout
$scope.item = item
else
elDragger.css left : item |> item2coord
$timeout.$cancel dragTimeout
dragTimeout := $timeout ->
$scope.item = item
dragTimeout := void
, 100
$event.preventDefault!
draggerDragEnd: ($event,drag)->
debug and log \draggerDragEnd
offsetX = drag.offsetX |> keepInside
$scope.item = drag.offsetX |> coord2item
$event.preventDefault!
rangeClick: ($event)->
debug and log \rangeClick, $event
if $ $event.target .is elRange
value = (($event.offsetX - draggerSize!/2)) |> keepInside |> coord2item
offsetX = value |> item2coord
$scope.item = value
keyup: ($event)->
current = $scope.item or ITEMS[0]
#normal = ($scope.text |> strWithoutSuffix |> parseFloat |> between MIN, MAX)
next =
| $event.which is 38 => ((current |> parseFloat) + STEP) |> toFixedOrInt(2) |> between MIN, MAX
| $event.which is 40 => ((current |> parseFloat) - STEP) |> toFixedOrInt(2) |> between MIN, MAX
| otherwise => void
if next?
$scope.text = next |> strWithSuffix
yes
$scope.$watch \text, ->
if it? and it and it !== $ngModel.$modelValue
$scope.item = (it |> strWithoutSuffix |> parseFloat |> between(MIN, MAX) |> toFixedOrInt(2))
$scope.$watch \item, (value)->
$scope.rangeSize = rangeSize! if not $scope.rangeSize
#log.log $scope.rangeSize
if value?
coord = (value |> item2coord)
elDragger.css (left : coord + \px)
$scope.text = value |> strWithSuffix
value |> $ngModel.$setViewValue
else
elDragger.css (left : 0px)
, on
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment