gentelella
Version:
Gentellela Admin is a free to use Bootstrap admin template
525 lines (446 loc) • 14.4 kB
text/coffeescript
# Request Animation Frame Polyfill
# CoffeeScript version of http://paulirish.com/2011/requestanimationframe-for-smart-animating/
do () ->
vendors = ['ms', 'moz', 'webkit', 'o']
for vendor in vendors
if window.requestAnimationFrame
break
window.requestAnimationFrame = window[vendor + 'RequestAnimationFrame']
window.cancelAnimationFrame = window[vendor + 'CancelAnimationFrame'] or window[vendor + 'CancelRequestAnimationFrame']
browserRequestAnimationFrame = null
lastId = 0
isCancelled = {}
if not requestAnimationFrame
window.requestAnimationFrame = (callback, element) ->
currTime = new Date().getTime()
timeToCall = Math.max(0, 16 - (currTime - lastTime))
id = window.setTimeout(() ->
callback(currTime + timeToCall)
, timeToCall)
lastTime = currTime + timeToCall
return id
# This implementation should only be used with the setTimeout()
# version of window.requestAnimationFrame().
window.cancelAnimationFrame = (id) ->
clearTimeout(id)
else if not window.cancelAnimationFrame
browserRequestAnimationFrame = window.requestAnimationFrame
window.requestAnimationFrame = (callback, element) ->
myId = ++lastId
browserRequestAnimationFrame(() ->
if not isCancelled[myId]
callback()
, element)
return myId
window.cancelAnimationFrame = (id) ->
isCancelled[id] = true
String.prototype.hashCode = () ->
hash = 0
if this.length == 0
return hash
for i in [0...this.length]
char = this.charCodeAt(i)
hash = ((hash << 5) - hash) + char
hash = hash & hash # Convert to 32bit integer
return hash
secondsToString = (sec) ->
hr = Math.floor(sec / 3600)
min = Math.floor((sec - (hr * 3600))/60)
sec -= ((hr * 3600) + (min * 60))
sec += ''
min += ''
while min.length < 2
min = '0' + min
while sec.length < 2
sec = '0' + sec
hr = if hr then hr + ':' else ''
return hr + min + ':' + sec
formatNumber = (num) ->
return addCommas(num.toFixed(0))
updateObjectValues = (obj1, obj2) ->
for own key, val of obj2
obj1[key] = val
return obj1
mergeObjects = (obj1, obj2) ->
out = {}
for own key, val of obj1
out[key] = val
for own key, val of obj2
out[key] = val
return out
addCommas = (nStr) ->
nStr += ''
x = nStr.split('.')
x1 = x[0]
x2 = ''
if x.length > 1
x2 = '.' + x[1]
rgx = /(\d+)(\d{3})/
while rgx.test(x1)
x1 = x1.replace(rgx, '$1' + ',' + '$2')
return x1 + x2
cutHex = (nStr) ->
if nStr.charAt(0) == "#"
return nStr.substring(1,7)
return nStr
class ValueUpdater
animationSpeed: 32
constructor: (addToAnimationQueue=true, =true) ->
if addToAnimationQueue
AnimationUpdater.add(@)
update: (force=false) ->
if force or !=
if and
.clearRect(0, 0, .width, .height)
diff = -
if Math.abs(diff / ) <= 0.001
=
else
= + diff /
return true
return false
class BaseGauge extends ValueUpdater
displayScale: 1
setTextField: (textField) ->
= if textField instanceof TextRenderer then textField else new TextRenderer(textField)
setMinValue: (, updateStartValue=true) ->
if updateStartValue
=
for gauge in or []
gauge.displayedValue =
setOptions: (options=null) ->
= mergeObjects(, options)
if
.el.style.fontSize = options.fontSize + 'px'
if .angle > .5
.options.angle = .5
return @
configDisplayScale: () ->
prevDisplayScale =
if .highDpiSupport == false
delete
else
devicePixelRatio = window.devicePixelRatio or 1
backingStorePixelRatio =
.webkitBackingStorePixelRatio or
.mozBackingStorePixelRatio or
.msBackingStorePixelRatio or
.oBackingStorePixelRatio or
.backingStorePixelRatio or 1
= devicePixelRatio / backingStorePixelRatio
if != prevDisplayScale
width = .G__width or .width
height = .G__height or .height
.width = width *
.height = height *
.style.width = "#{width}px"
.style.height = "#{height}px"
.G__width = width
.G__height = height
return @
class TextRenderer
constructor: () ->
# Default behaviour, override to customize rendering
render: (gauge) ->
.innerHTML = formatNumber(gauge.displayedValue)
class AnimatedText extends ValueUpdater
displayedValue: 0
value: 0
setVal: (value) ->
= 1 * value
constructor: (, =false) ->
= 1 * .innerHTML
if
= 0
render: () ->
if
textVal = secondsToString(.toFixed(0))
else
textVal = addCommas(formatNumber())
.innerHTML = textVal
AnimatedTextFactory =
create: (objList) ->
out = []
for elem in objList
out.push(new AnimatedText(elem))
return out
class GaugePointer extends ValueUpdater
displayedValue: 0
value: 0
options:
strokeWidth: 0.035
length: 0.1
color: "#000000"
constructor: () ->
= .ctx
= .canvas
super(false, false)
setOptions: (options=null) ->
updateObjectValues(, options)
= .height * .length
= .height * .strokeWidth
= .maxValue
= .minValue
= .animationSpeed
.angle = .options.angle
render: () ->
angle = .getAngle.call(@, )
centerX = .width / 2
centerY = .height * 0.9
x = Math.round(centerX + * Math.cos(angle))
y = Math.round(centerY + * Math.sin(angle))
startX = Math.round(centerX + * Math.cos(angle - Math.PI/2))
startY = Math.round(centerY + * Math.sin(angle - Math.PI/2))
endX = Math.round(centerX + * Math.cos(angle + Math.PI/2))
endY = Math.round(centerY + * Math.sin(angle + Math.PI/2))
.fillStyle = .color
.beginPath()
.arc(centerX, centerY, , 0, Math.PI*2, true)
.fill()
.beginPath()
.moveTo(startX, startY)
.lineTo(x, y)
.lineTo(endX, endY)
.fill()
class Bar
constructor: () ->
updateValues: (arrValues) ->
= arrValues[0]
= arrValues[1]
= arrValues[2]
render: () ->
if
.text(formatNumber())
if == 0
= * 2
valPercent = ( / ) * 100
avgPercent = ( / ) * 100
$(".bar-value", ).css({"width": valPercent + "%"})
$(".typical-value", ).css({"width": avgPercent + "%"})
class Gauge extends BaseGauge
elem: null
value: [20] # we support multiple pointers
maxValue: 80
minValue: 0
displayedAngle: 0
displayedValue: 0
lineWidth: 40
paddingBottom: 0.1
percentColors: null,
options:
colorStart: "#6fadcf"
colorStop: undefined
gradientType: 0 # 0 : radial, 1 : linear
strokeColor: "#e0e0e0"
pointer:
length: 0.8
strokeWidth: 0.035
angle: 0.15
lineWidth: 0.44
fontSize: 40
limitMax: false
constructor: () ->
super()
= null
if typeof G_vmlCanvasManager != 'undefined'
= window.G_vmlCanvasManager.initElement()
= .getContext('2d')
= [new GaugePointer(@)]
setOptions: (options=null) ->
super(options)
= .height * (1 - ) * .lineWidth # .2 - .7
= .height * (1 - ) -
.clearRect(0, 0, .width, .height)
for gauge in
gauge.setOptions(.pointer)
gauge.render()
return @
configPercentColors: () ->
= null;
if (.percentColors != undefined)
= new Array()
for i in [0..(.percentColors.length-1)]
rval = parseInt((cutHex(.percentColors[i][1])).substring(0,2),16)
gval = parseInt((cutHex(.percentColors[i][1])).substring(2,4),16)
bval = parseInt((cutHex(.percentColors[i][1])).substring(4,6),16)
[i] = { pct: .percentColors[i][0], color: { r: rval, g: gval, b: bval } }
set: (value) ->
if not (value instanceof Array)
value = [value]
# check if we have enough GaugePointers initialized
# lazy initialization
if value.length > .length
for i in [0...(value.length - .length)]
.push(new GaugePointer(@))
# get max value and update pointer(s)
i = 0
max_hit = false
for val in value
if val >
= * 1.1
max_hit = true
[i].value = val
[i++].setOptions({maxValue: , angle: .angle})
= value[value.length - 1] # TODO: Span maybe??
if max_hit
unless .limitMax
AnimationUpdater.run()
else
AnimationUpdater.run()
getAngle: (value) ->
return (1 + .angle) * Math.PI + ((value - ) / ( - )) * (1 - .angle * 2) * Math.PI
getColorForPercentage: (pct, grad) ->
if pct == 0
color = [0].color;
else
color = [.length - 1].color;
for i in [0..(.length - 1)]
if (pct <= [i].pct)
if grad == true
# Gradually change between colors
startColor = [i - 1]
endColor = [i]
rangePct = (pct - startColor.pct) / (endColor.pct - startColor.pct) # How far between both colors
color = {
r: Math.floor(startColor.color.r * (1 - rangePct) + endColor.color.r * rangePct),
g: Math.floor(startColor.color.g * (1 - rangePct) + endColor.color.g * rangePct),
b: Math.floor(startColor.color.b * (1 - rangePct) + endColor.color.b * rangePct)
}
else
color = [i].color
break
return 'rgb(' + [color.r, color.g, color.b].join(',') + ')'
getColorForValue: (val, grad) ->
pct = (val - ) / ( - )
return ;
render: () ->
# Draw using canvas
w = .width / 2
h = .height * (1 - )
displayedAngle =
if
.render(@)
.lineCap = "butt"
if .customFillStyle != undefined
fillStyle = .customFillStyle(@)
else if != null
fillStyle =
else if .colorStop != undefined
if .gradientType == 0
fillStyle = this.ctx.createRadialGradient(w, h, 9, w, h, 70);
else
fillStyle = this.ctx.createLinearGradient(0, 0, w, 0);
fillStyle.addColorStop(0, .colorStart)
fillStyle.addColorStop(1, .colorStop)
else
fillStyle = .colorStart
.strokeStyle = fillStyle
.beginPath()
.arc(w, h, , (1 + .angle) * Math.PI, displayedAngle, false)
.lineWidth =
.stroke()
.strokeStyle = .strokeColor
.beginPath()
.arc(w, h, , displayedAngle, (2 - .angle) * Math.PI, false)
.stroke()
for gauge in
gauge.update(true)
class BaseDonut extends BaseGauge
lineWidth: 15
displayedValue: 0
value: 33
maxValue: 80
minValue: 0
options:
lineWidth: 0.10
colorStart: "#6f6ea0"
colorStop: "#c0c0db"
strokeColor: "#eeeeee"
shadowColor: "#d5d5d5"
angle: 0.35
constructor: () ->
super()
if typeof G_vmlCanvasManager != 'undefined'
= window.G_vmlCanvasManager.initElement()
= .getContext('2d')
getAngle: (value) ->
return (1 - .angle) * Math.PI + ((value - ) / ( - )) * ((2 + .angle) - (1 - .angle)) * Math.PI
setOptions: (options=null) ->
super(options)
= .height * .lineWidth
= .height / 2 - /2
return @
set: (value) ->
= value
if >
= * 1.1
AnimationUpdater.run()
render: () ->
displayedAngle =
w = .width / 2
h = .height / 2
if
.render(@)
grdFill = .createRadialGradient(w, h, 39, w, h, 70)
grdFill.addColorStop(0, .colorStart)
grdFill.addColorStop(1, .colorStop)
start = - / 2
stop = + / 2
.strokeStyle = .strokeColor
.beginPath()
.arc(w, h, , (1 - .angle) * Math.PI, (2 + .angle) * Math.PI, false)
.lineWidth =
.lineCap = "round"
.stroke()
.strokeStyle = grdFill
.beginPath()
.arc(w, h, , (1 - .angle) * Math.PI, displayedAngle, false)
.stroke()
class Donut extends BaseDonut
strokeGradient: (w, h, start, stop) ->
grd = .createRadialGradient(w, h, start, w, h, stop)
grd.addColorStop(0, .shadowColor)
grd.addColorStop(0.12, ._orgStrokeColor)
grd.addColorStop(0.88, ._orgStrokeColor)
grd.addColorStop(1, .shadowColor)
return grd
setOptions: (options=null) ->
super(options)
w = .width / 2
h = .height / 2
start = - / 2
stop = + / 2
._orgStrokeColor = .strokeColor
.strokeColor =
return @
window.AnimationUpdater =
elements: []
animId: null
addAll: (list) ->
for elem in list
AnimationUpdater.elements.push(elem)
add: (object) ->
AnimationUpdater.elements.push(object)
run: () ->
animationFinished = true
for elem in AnimationUpdater.elements
if elem.update()
animationFinished = false
if not animationFinished
AnimationUpdater.animId = requestAnimationFrame(AnimationUpdater.run)
else
cancelAnimationFrame(AnimationUpdater.animId)
window.Gauge = Gauge
window.Donut = Donut
window.BaseDonut = BaseDonut
window.TextRenderer = TextRenderer