|
class Dashing.StarRatings extends Dashing.Widget |
|
|
|
@accessor 'title' |
|
@accessor 'max' |
|
@accessor 'min' |
|
|
|
|
|
ready: -> |
|
node = $(@node) |
|
@max = parseInt node.data "max" |
|
@min = parseInt node.data "min" |
|
@drawWidget( @get('items') ) |
|
|
|
|
|
onData: (eventData) -> |
|
@drawWidget(eventData.items) |
|
|
|
|
|
drawWidget: (star_items) -> |
|
container = $(@node) |
|
rowsContainer = container.find('.rows-container') |
|
|
|
if !star_items |
|
rowsContainer.empty() |
|
else |
|
# Float value used to scale the rows to use the entire space of the widget |
|
rowHeight = 100 / star_items.length |
|
counter = 0 |
|
@clearIntervals() |
|
|
|
# Add or move rows for each project. Checks first if the row already exists. |
|
star_items.forEach (item) => |
|
normalizedItemName = item.name.replace(/\W+/g, "_") |
|
referenceRow = rowsContainer.children().eq(counter) |
|
existingRow = rowsContainer.find("."+normalizedItemName) |
|
|
|
if existingRow.length |
|
if referenceRow.attr("class").indexOf(normalizedItemName) == -1 |
|
existingRow.detach().insertBefore(referenceRow) |
|
existingRow.hide().fadeIn(1200) |
|
else |
|
row = createRow(item) |
|
if referenceRow.length |
|
row.insertBefore(referenceRow) |
|
else |
|
rowsContainer.append(row) |
|
row.hide().fadeIn(1200) |
|
|
|
elem = rowsContainer.find("."+normalizedItemName+" .full-stars") |
|
if elem.length |
|
@animateBarContent(elem[0], parseFloat(elem[0].style.width), |
|
parseFloat(item.value), 1000) |
|
++counter |
|
|
|
# Remove any nodes that were not in the new data, these will be the rows |
|
# at the end of the widget. |
|
currentNode = rowsContainer.children().eq(counter-1) |
|
while currentNode.next().length |
|
currentNode = currentNode.next() |
|
currentNode.fadeOut(100, -> $(this).remove() ) |
|
|
|
# Set the height after rows were added/removed. |
|
rows = rowsContainer.children() |
|
percentageOfTotalHeight = 90 / star_items.length |
|
applyCorrectedRowHeight(rows, percentageOfTotalHeight) |
|
|
|
applyZebraStriping(rows) |
|
|
|
|
|
#***/ |
|
# Create a JQuery row object with the proper structure and base |
|
# settings for the item passed in. |
|
# |
|
# The Row DOM Hierarchy: |
|
# Row |
|
# Row Content (here so we can use vertical alignment) |
|
# Project Name |
|
# Outer Bar Container (The border and background) |
|
# Inner Bar Container (The value and text) |
|
# |
|
# @item - object representing an item and it's value |
|
# / |
|
createRow = (item) -> |
|
|
|
row = ( $("<div/>") |
|
.attr("class", "row " + item.name.replace(/\W+/g, "_") ) ) |
|
# .attr("class", item.name.replace(/\W+/g, "_") ) ) |
|
# .attr("id", item.name.match(/[[\w]*(?:.*)]/ ) ) ) |
|
|
|
rowContent = ( $("<div/>") |
|
.attr("class", "row-content") ) |
|
|
|
projectName = ( $("<div/>") |
|
.attr("class", "project-name") |
|
.text(item.name) |
|
.attr("title", item.name) ) |
|
|
|
ratings = $("<div/>") |
|
.attr("class", "ratings") |
|
emptyStars = $("<div/>") |
|
.attr("class", "empty-stars") |
|
fullStars = $("<div/>") |
|
.attr("class", "full-stars") |
|
fullStars.css("width", "0%") |
|
|
|
# Put it all together. |
|
rowContent.append(projectName) |
|
ratings.append(emptyStars) |
|
ratings.append(fullStars) |
|
rowContent.append(ratings) |
|
row.append(rowContent) |
|
|
|
return row |
|
|
|
|
|
#***/ |
|
# Does calculations for the animation and sets up the javascript |
|
# interval to perform the animation. |
|
# |
|
# @element - element that is going to be animated. |
|
# @from - the value that the element starts at. |
|
# @to - the value that the element is going to. |
|
# @baseDuration - the minimum time the animation will perform. |
|
# / |
|
animateBarContent: (element, from, to, baseDuration) -> |
|
endpointDifference = (to-from) |
|
|
|
if endpointDifference != 0 |
|
currentValue = from |
|
|
|
# Every x milliseconds, the function should run. |
|
stepInterval = 16.667 |
|
|
|
# Change the duration based on the distance between points. |
|
duration = baseDuration + (Math.abs(endpointDifference) * 2500)/(@max - @min) |
|
|
|
numberOfSteps = duration / stepInterval |
|
valueIncrement = endpointDifference / numberOfSteps |
|
local_max = @max |
|
local_min = @min |
|
interval = setInterval( |
|
-> |
|
currentValue += valueIncrement |
|
if Math.abs(currentValue - from) >= Math.abs(endpointDifference) |
|
setBarValue(element, to, local_min, local_max) |
|
clearInterval(interval) |
|
else |
|
setBarValue(element, currentValue, local_min, local_max) |
|
stepInterval) |
|
|
|
@addInterval(interval) |
|
|
|
#***/ |
|
# Sets the text and width of the element in question to the specified value |
|
# after making sure it is bounded between min and max |
|
# |
|
# @element - element to be set |
|
# @value - the numeric value to set the element to. This can be a float. |
|
# / |
|
setBarValue = (element, value, minValue, maxValue) -> |
|
if (value > maxValue) |
|
value = maxValue |
|
else if (value < minValue) |
|
value = minValue |
|
#element.textContent = Math.floor(value) |
|
element.style.width = (((value - minValue) * 100)/(maxValue - minValue)) + "%" |
|
|
|
#***/ |
|
# Applies a percentage-based row height to the list of rows passed in. |
|
# |
|
# @rows - the elements to apply this height value to |
|
# @percentageOfTotalHeight - The height to be applied to each row. |
|
# / |
|
applyCorrectedRowHeight = (rows, percentageOfTotalHeight) -> |
|
height = percentageOfTotalHeight + "%" |
|
for row in rows |
|
row.style.height = height |
|
|
|
#***/ |
|
# Adds a class to every other row to change the background color. This |
|
# was done mainly for readability. |
|
# |
|
# @rows - list of elements to run zebra-striping on |
|
# / |
|
applyZebraStriping = (rows) -> |
|
isZebraStripe = false |
|
for row in rows |
|
# In case elements are moved around, we don't want them to retain this. |
|
row.classList.remove("zebra-stripe") |
|
if isZebraStripe |
|
row.classList.add("zebra-stripe") |
|
isZebraStripe = !isZebraStripe |
|
|
|
#***/ |
|
# Stops all javascript intervals from running and clears the list. |
|
#/ |
|
clearIntervals: -> |
|
if @intervalList |
|
for interval in @intervalList |
|
clearInterval(interval) |
|
@intervalList = [] |
|
|
|
#***/ |
|
# Adds a javascript interval to a list so that it can be tracked and cleared |
|
# ahead of time if the need arises. |
|
# |
|
# @interval - the javascript interval to add |
|
#/ |
|
addInterval: (interval) -> |
|
if !@intervalList |
|
@intervalList = [] |
|
@intervalList.push(interval) |
|
|