Skip to content

Instantly share code, notes, and snippets.

@IFEOMA2005
Forked from toddq/README.md
Last active August 29, 2015 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IFEOMA2005/aedc1479665735e9b0f5 to your computer and use it in GitHub Desktop.
Save IFEOMA2005/aedc1479665735e9b0f5 to your computer and use it in GitHub Desktop.

##Description A Dashing widget that overlays a scrolling news ticker on the bottom of your Dashboard.

This widget is a little different, in that it doesn't occupy a typical space in the Dashing grid, but instead overlays the bottom of the dashboard. If it doesn't have any data, it will be hidden. If you send it an array of Strings, it will scroll through them either vertically or horizontally. Our office uses it on our dashboards to occasionally flash important notices or reminders in an eye catching fashion, most of the time it is not displayed.

See http://widget-challenge.herokuapp.com/vertical-ticker and http://widget-challenge.herokuapp.com/horizontal-ticker for a live demo.

##Screenshots

##Dependencies jQuery Transit

Put jquery.transit.js in your assets/javascripts/ directory to use CSS3 animations (the default). Or change @CSS_ANIMATION to false in ticker.coffee and jQuery's animate() will be used instead.

##Usage To install this widget, copy ticker.html, ticker.scss, and ticker.coffee in to the widgets/ticker directory. Optionally, copy the ticker.rb file into your jobs folder for example usage.

To include the widget on a dashboard, add the following snippet to your dashboard layout file BETWEEN the closing ul tag and closing div tag with the class gridster like this:

    </ul>
    <div data-id="ticker" data-view="Ticker" style="display: none;" ></div>
</div>

By default, items will scroll vertically, pausing for 10 seconds on each item. You also have the option of a continuous horizontal scrolling animation if you specify:

<div data-id="ticker" data-view="Ticker" data-scroll_orientation="horizontal" style="display: none;" ></div>

The widget is not displayed by default, and will only display if it has content. You send it an array of any number of Strings, and it will rotate through them. If you send it an empty array, it will hide itself again.

curl -d '{ "auth_token": "YOUR_AUTH_TOKEN", "items": ["Hello World!", "Well Hello Yourself!"] }' http://localhost:3030/widgets/ticker

curl -d '{ "auth_token": "YOUR_AUTH_TOKEN", "items": [] }' http://localhost:3030/widgets/ticker
class Dashing.Ticker extends Dashing.Widget
# pixels per second
@SPEED: 70
# easing function to use for the animation
@EASING: "linear"
# Whether to use CSS3 animations. If false, jQuery animate() will be used.
@CSS_ANIMATION: true
# Number of milliseconds between jQuery animation frames. The
# default is 13, which causes this ticker to have pretty high cpu usage.
# 40 is about the highest I've gone before animations start to look bad.
# Lower numbers will cause smoother animations.
# NOTE: this will cause a change to GLOBAL jQuery animations on the page.
# Only used if CSS_ANIMATION is false.
@FX_INTERVAL: 30
# Used for vertical scrolling, the number of seconds to show an alert before
# scrolling to the next one.
@DELAY = 10
getTicker: ->
$("#news_ticker")
# should be either "vertical" or "horizontal"
getScrollOrientation: ->
if $(@node).data('scroll_orientation')
$(@node).data('scroll_orientation')
else
"vertical"
initialize: ->
return true if @initialized
if not $(".gridster.ready").length or not @getTicker().length
@log( "not ready yet..." )
return false
@log( "initializing..." )
if not Ticker.CSS_ANIMATION and @getScrollOrientation() == 'horizontal'
@log( "setting jQuery fx interval to #{Ticker.FX_INTERVAL}" )
jQuery.fx.interval = Ticker.FX_INTERVAL
$.fn.transition = $.fn.animate
@ticker = @getTicker()
# Set a width first based on the board size
@log( "setting node width to " + $(".gridster.ready").width() )
$(@node).width( $(".gridster.ready").width() )
# Wrap the ticker in some extra divs
@log( "adding wrapper divs" )
@ticker.addClass('newsticker')
@ticker.wrap('<div class="mask" />')
@ticker.parent().wrap('<div class="tickercontainer" />')
@initialized = true
ready: ->
# This is fired when the widget is done being rendered
@log("ready")
@doTicker()
onData: (data) ->
@log( "onData" )
@doTicker()
doTicker: ->
@initialize() if not @initialized
if @initialized
if @hasChanged() and @hasItems()
@resetTicker()
else if not @hasItems()
@stopTicker()
startTicker: ->
@log( "" )
@log("starting ticker")
@should_stop = false
$(@node).show()
if @getScrollOrientation() == "horizontal"
@doHorizontalScroll()
else
@doVerticalScroll()
doHorizontalScroll: ->
@log( "doing horizontal scroll" )
viewWidth = @ticker.parent().width()
@log( "viewWidth: #{viewWidth}" )
# Add a spacer between ticker elements so that only one of them is showing at once
@insertSpacers( viewWidth )
# calculate content width
@log( "calculating content width..." )
contentWidth = @contentWidth()
# set ticker width to the sum of the viewport and the content
tickerWidth = viewWidth + contentWidth
@log( "setting ticker width to #{tickerWidth}" )
@ticker.css('width', tickerWidth)
# set ticker left value to viewWidth
@ticker.css('left', viewWidth)
# then animate the left value to -contentWidth
animationSettings = { 'left': -contentWidth }
@log( "animating 'left' value from #{viewWidth} to #{-contentWidth}" )
duration = tickerWidth * 1000 / Ticker.SPEED
console.log( "duration: #{duration} ms" )
@ticker.transition animationSettings, duration, Ticker.EASING, =>
if not @should_stop
@log( "loop complete, do it again!" )
@startTicker()
doVerticalScroll: ->
@log( "doing vertical scroll" )
@itemHeight = @ticker.children('li').first().outerHeight()
contentHeight = @itemHeight * @ticker.children('li').size()
# set ticker height to the content height
@ticker.css('height', contentHeight)
# set ticker top value to @itemHeight
@ticker.css('top', @itemHeight)
@ticker.children('li').width('100%')
@nextItem()
nextItem: =>
@log( "scrolling to next item" )
animationSettings = { 'top': @ticker.position().top - @itemHeight }
duration = 1000
@ticker.transition animationSettings, duration, "linear", =>
if not @should_stop
@log( "comparing #{@ticker.position().top - 2} to #{-@ticker.outerHeight()}" )
if @ticker.position().top - 2 > -@ticker.outerHeight()
@log( "scheduling the next item" )
@scrollNext = setTimeout( @nextItem, Ticker.DELAY * 1000 )
else
@log( "loop complete, do it again!" )
@startTicker()
stopTicker: ->
@log("stopping ticker")
@should_stop = true
if @ticker
@ticker.stop( true )
clearTimeout( @scrollNext )
@ticker.removeAttr('style')
$(@node).hide()
resetTicker: ->
@stopTicker()
@startTicker()
contentWidth: ->
contentWidth = 0
for child in @ticker.children()
contentWidth += $(child).outerWidth( true )
return contentWidth
hasItems: ->
return @get('items' ) and @get('items').length > 0
hasChanged: ->
new_items = @get('items')
changed = false
if @old_items == new_items
# short circuit, they're probably both null
return false
if @old_items and not new_items
changed = true
else if new_items and not @old_items
changed = true
else if @old_items.toString() != new_items.toString()
changed = true
if changed
@log( "items changed" )
else
@log( "items the same" )
@old_items = new_items
return changed
insertSpacers: (width) ->
@log( "inserting spacers" )
@ticker.children().not(':last-child').css('margin-right', width)
log: (msg) ->
# console.log( "[ticker] #{msg}" )
return
<ul id="news_ticker">
<li data-foreach-item="items" data-bind="item | raw"></li>
</ul>
ticker_items = [
"Staff meeting today in the cafeteria today at 10am. &nbsp;&nbsp; Don't forget to give yourself 20 minutes to walk over there.",
"The Dashing Widget Challenge deadline has been moved to September 26th. &nbsp;&nbsp; Don't delay in getting your awesome widget submitted!"
]
SCHEDULER.every '10m', :first_in => 0 do
send_event( 'ticker', { :items => ticker_items } )
end
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: rgba(0, 0, 0, .6);
$text-color: #ffff00;
$border-color: #ffffff;
$border: 1px solid $border-color;
$height: 60px;
$width: 100%;
// ----------------------------------------------------------------------------
// Widget-ticker styles
// ----------------------------------------------------------------------------
.widget-ticker {
position: fixed;
bottom: 10px;
z-index: 1000;
padding: 0px !important;
width: $width;
height: $height;
color: $text-color;
background: $background-color;
/* the outer div with the border */
.tickercontainer {
border: $border;
background: $background-color;
height: $height;
margin: 0;
padding: 0;
overflow: hidden;
li {
float: left;
}
.mask {
position: relative;
left: 0px;
top: 0px;
overflow: hidden;
height: $height;
}
}
ul.newsticker {
position: relative;
list-style-type: none;
-webkit-transform: translate3d(0, 0, 0);
-webkit-backface-visibility: hidden;
-webkit-perspective: 1000;
}
ul.newsticker li {
float: left;
font-size: 20px;
font-weight: bold;
font-style: italic;
line-height: $height;
height: $height;
white-space: nowrap;
text-align: center;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment