Skip to content

Instantly share code, notes, and snippets.

@lsiv568
Last active December 18, 2015 01:59
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lsiv568/5707440 to your computer and use it in GitHub Desktop.
Save lsiv568/5707440 to your computer and use it in GitHub Desktop.
Time Slider AngularJS Directive
'use strict';
angular.module('buzzbandBackstageApp')
.directive('timeSlider', ($window) ->
updateStartTime = (span, value) ->
# set start and end times
sd = new Date(value)
startDate = sd.toLocaleDateString()
startTime = sd.toLocaleTimeString()
span.innerHTML = startDate + ':' + startTime
updateEndTime = (span, value) ->
ed = new Date(value)
endDate = ed.toLocaleDateString()
endTime = ed.toLocaleTimeString()
span.innerHTML = endDate + ':' + endTime
updateCurrentTime = (span, value) ->
cd = new Date(value)
curDate = cd.toLocaleDateString()
curTime = cd.toLocaleTimeString()
span.innerHTML = curDate + ':' + curTime
template: "<div><span>Start Time: </span><span class='startTime'></span>" +
"<input type='range'></input><span>End Time:</span><span class='endTime'></span>" +
"<div style='position: absolute' class='curTime'><span></span></div>" +
"</div>"
restrict: 'E'
scope: {
min: '='
max: '='
callback: '='
}
link: (scope, element, attrs) ->
# Grab the range input element and spans to be updated
rangeInput = element.find('input')[0]
rangeInputElement = angular.element rangeInput
spans = element.find 'span'
curTimeDiv = element.find('div')[1]
rangeInputOffset = $(rangeInput).offset()
# configure range input with provided min, max, and step values
rangeInput.min = scope.min
rangeInput.max = scope.max
rangeInput.step = attrs.step
rangeInput.value = scope.min # initialize value of slider to min value
# initialize start and end time
updateStartTime spans[1], rangeInput.min
updateEndTime spans[3], rangeInput.max
# function to move the current time div as the slider changes
moveCurTimeDiv = (curValue) ->
curPercentage = (curValue - scope.min) / (scope.max - scope.min)
curValueLocation = (rangeInput.clientWidth * curPercentage) + rangeInputOffset.left
ctdElement = angular.element curTimeDiv
ctdElement.css 'left', curValueLocation - curTimeDiv.clientWidth + 'px'
ctdElement.css 'top', rangeInput.clientHeight - curTimeDiv.clientHeight + 'px'
# when range input changes update the current time span
rangeInputElement.bind 'change', (event) ->
curValue = parseInt event.target.value
updateCurrentTime(spans[4], curValue)
moveCurTimeDiv curValue
#on mouse up call the callback bound to the scope
rangeInputElement.bind 'mouseup', (event) ->
scope.$apply ->
scope.callback.call this, parseInt(event.target.value)
scope.$watch 'min', (newValue, oldValue) ->
updateStartTime(spans[1], parseInt newValue)
rangeInput.min = scope.min # update slider when min value changes
rangeInput.value = scope.min # update slider value to be min
spans[4].innerHTML = ''
scope.$watch 'max', (newValue, oldValue) ->
updateEndTime(spans[3], parseInt newValue)
rangeInput.max = scope.max # update slider when max value changes
)
@lsiv568
Copy link
Author

lsiv568 commented Jun 4, 2013

This directive uses HTML 5 range input to create a slider for time values. Time is input as time since epoch and converted to Locale date/time strings. The current value of the slider moves with the slider.

Link to fiddle: http://jsfiddle.net/lsiv568/WJqx7/1/

There is some "funnyness" in the fiddle with the positioning of the current time value - not the case in actual app.

NOTE: for this fiddle I have used the template string. In practice, I recommend using templateUrl

Any and all feedback welcome!

@ramarajuv
Copy link

I liked the slider. I am actually looking for a two way date slider. Do you have anything handy? Thank you in advance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment