Directly ported Progress bar widget from dashing to pydashie. Included example sampler and widget in the included examples
This commit is contained in:
parent
d0bccd1c49
commit
87b4cbc9ac
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,7 @@ def run(app, xyzzy):
|
||||
HotnessSampler(xyzzy, 3),
|
||||
BuzzwordsSampler(xyzzy, 2), # 10
|
||||
ConvergenceSampler(xyzzy, 1),
|
||||
ProgressBarsSampler(xyzzy, 5),
|
||||
]
|
||||
|
||||
try:
|
||||
|
@ -65,3 +65,19 @@ class ConvergenceSampler(DashieSampler):
|
||||
if len(self.items) > 10:
|
||||
self.items.popleft()
|
||||
return {'points': list(self.items)}
|
||||
|
||||
|
||||
class ProgressBarsSampler(DashieSampler):
|
||||
def __init__(self, *args, **kwargs):
|
||||
DashieSampler.__init__(self, *args, **kwargs)
|
||||
|
||||
def name(self):
|
||||
return 'progress_bars'
|
||||
|
||||
def sample(self):
|
||||
random_progress = []
|
||||
|
||||
for i in range(5):
|
||||
random_progress.append({'name': "Project %d" % i, 'progress': random.randint(0, 100)})
|
||||
|
||||
return {'title': "Progress Bars Title", 'progress_items': random_progress}
|
@ -40,6 +40,7 @@ def javascripts():
|
||||
#'widgets/clock/clock.coffee',
|
||||
'widgets/number/number.coffee',
|
||||
'widgets/hotness/hotness.coffee',
|
||||
'widgets/progress_bars/progress_bars.coffee',
|
||||
]
|
||||
nizzle = True
|
||||
if not nizzle:
|
||||
|
@ -63,7 +63,9 @@
|
||||
<div data-id="comments" data-view="comments" data-title="Comments"></div>
|
||||
</li>
|
||||
|
||||
|
||||
<li data-row="4" data-col="2" data-sizex="2" data-sizey="1">
|
||||
<div data-id="progress_bars" data-view="ProgressBars" data-title="Project Bars"></div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
5
pydashie/widgets/progress_bars/attribution
Normal file
5
pydashie/widgets/progress_bars/attribution
Normal file
@ -0,0 +1,5 @@
|
||||
Direct port of the Progress Bars Widget from Shopify's Dashie Widget Challenge to pydashie
|
||||
|
||||
All attribution to mdirienzo -
|
||||
|
||||
https://gist.github.com/mdirienzo/6716905
|
200
pydashie/widgets/progress_bars/progress_bars.coffee
Normal file
200
pydashie/widgets/progress_bars/progress_bars.coffee
Normal file
@ -0,0 +1,200 @@
|
||||
class Dashing.ProgressBars extends Dashing.Widget
|
||||
|
||||
@accessor 'title'
|
||||
|
||||
ready: ->
|
||||
@drawWidget( @get('progress_items') )
|
||||
|
||||
onData: (eventData) ->
|
||||
@drawWidget(eventData.progress_items)
|
||||
|
||||
drawWidget: (progress_items) ->
|
||||
container = $(@node)
|
||||
rowsContainer = container.find('.rows-container')
|
||||
|
||||
if progress_items.length == 0
|
||||
rowsContainer.empty()
|
||||
else
|
||||
# Float value used to scale the rows to use the entire space of the widget
|
||||
rowHeight = 100 / progress_items.length
|
||||
counter = 0
|
||||
@clearIntervals()
|
||||
|
||||
# Add or move rows for each project. Checks first if the row already exists.
|
||||
progress_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+" .inner-progress-bar")
|
||||
if elem.length
|
||||
@animateProgressBarContent(elem[0], parseFloat(elem[0].style.width),
|
||||
parseFloat(item.progress), 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 = 100 / progress_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 progress and text)
|
||||
#
|
||||
# @item - object representing an item and it's progress
|
||||
# /
|
||||
createRow = (item) ->
|
||||
|
||||
row = ( $("<div/>")
|
||||
.attr("class", "row " + item.name.replace(/\W+/g, "_") ) )
|
||||
|
||||
rowContent = ( $("<div/>")
|
||||
.attr("class", "row-content") )
|
||||
|
||||
projectName = ( $("<div/>")
|
||||
.attr("class", "project-name")
|
||||
.text(item.name)
|
||||
.attr("title", item.name) )
|
||||
|
||||
outerProgressBar = ( $("<div/>")
|
||||
.attr("class", "outer-progress-bar") )
|
||||
|
||||
innerProgressBar = $("<div/>")
|
||||
.attr("class", "inner-progress-bar")
|
||||
.text("0%")
|
||||
innerProgressBar.css("width", "0%")
|
||||
|
||||
# Put it all together.
|
||||
outerProgressBar.append(innerProgressBar)
|
||||
rowContent.append(projectName)
|
||||
rowContent.append(outerProgressBar)
|
||||
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.
|
||||
# /
|
||||
animateProgressBarContent: (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) * 25
|
||||
|
||||
numberOfSteps = duration / stepInterval
|
||||
valueIncrement = endpointDifference / numberOfSteps
|
||||
|
||||
interval = setInterval(
|
||||
->
|
||||
currentValue += valueIncrement
|
||||
if Math.abs(currentValue - from) >= Math.abs(endpointDifference)
|
||||
setProgressBarValue(element, to)
|
||||
clearInterval(interval)
|
||||
else
|
||||
setProgressBarValue(element, currentValue)
|
||||
stepInterval)
|
||||
|
||||
@addInterval(interval)
|
||||
|
||||
#***/
|
||||
# Sets the text and width of the element in question to the specified value
|
||||
# after making sure it is bounded between [0-100]
|
||||
#
|
||||
# @element - element to be set
|
||||
# @value - the numeric value to set the element to. This can be a float.
|
||||
# /
|
||||
setProgressBarValue = (element, value) ->
|
||||
if (value > 100)
|
||||
value = 100
|
||||
else if (value < 0)
|
||||
value = 0
|
||||
element.textContent = Math.floor(value) + "%"
|
||||
element.style.width = value + "%"
|
||||
|
||||
#***/
|
||||
# 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)
|
4
pydashie/widgets/progress_bars/progress_bars.html
Normal file
4
pydashie/widgets/progress_bars/progress_bars.html
Normal file
@ -0,0 +1,4 @@
|
||||
<h1 class="title" data-bind="title"></h1>
|
||||
|
||||
<div class="rows-container">
|
||||
</div>
|
99
pydashie/widgets/progress_bars/progress_bars.scss
Normal file
99
pydashie/widgets/progress_bars/progress_bars.scss
Normal file
@ -0,0 +1,99 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// Sass declarations
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// row-size is a magic number used for scaling. It will make things bigger
|
||||
// or smaller but always in proportion with each other. Feel free to change
|
||||
// this to reflect your personal needs.
|
||||
$row-size: 0.7em;
|
||||
|
||||
$blue: #2db4d4;
|
||||
$white: #ffffff;
|
||||
$base-color: $blue;
|
||||
|
||||
$base-color-dark: darken($base-color, 10%);
|
||||
$base-color-light: lighten($base-color, 10%);
|
||||
$base-color-lighter: lighten($base-color, 25%);
|
||||
$base-color-lightest: lighten($base-color, 35%);
|
||||
|
||||
$text-color: $base-color-lightest;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Widget-project-completion styles
|
||||
// ----------------------------------------------------------------------------
|
||||
.widget.widget-progress-bars {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
position:relative;
|
||||
background-color: $base-color;
|
||||
vertical-align: baseline;
|
||||
|
||||
* {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: $text-color;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.rows-container {
|
||||
height: 85%;
|
||||
width:100%;
|
||||
color: $text-color;
|
||||
font-size: $row-size;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.row {
|
||||
height:0%;
|
||||
width:100%;
|
||||
vertical-align: middle;
|
||||
display:table;
|
||||
transition-property: height;
|
||||
transition-duration: 0.3s;
|
||||
transition-timing-function: linear;
|
||||
}
|
||||
|
||||
.row-content {
|
||||
padding-left: 5px;
|
||||
display:table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.project-name {
|
||||
display:inline-block;
|
||||
width:35%;
|
||||
padding-right: $row-size;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
text-overflow: ellipsis;
|
||||
overflow:hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.outer-progress-bar {
|
||||
display:inline-block;
|
||||
width: 65%;
|
||||
vertical-align: middle;
|
||||
border: ($row-size / 3) solid $base-color-dark;
|
||||
border-radius: 2 * $row-size;
|
||||
background-color: $base-color-lighter;
|
||||
|
||||
.inner-progress-bar {
|
||||
background-color: $base-color-dark;
|
||||
border-radius: $row-size / 2;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
.zebra-stripe {
|
||||
background-color: $base-color-light;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user