Commit dcf2a518 authored by Taddeüs Kroes's avatar Taddeüs Kroes

Initial commit

parents
*.swp
.sass-cache
guide.js
style.css
ALL := style.css guide.js
.PHONY: all clean
all: $(ALL)
%.js: %.coffee
coffee --compile --output $(@D) $<
%.css: %.sass
sass $< $@
clean:
rm -f $(ALL)
#
# Config
#
HOUR_WIDTH = 200
SCROLL_MULTIPLIER = HOUR_WIDTH
CHANNELS =
'1': name: 'Nederland 1'
'2': name: 'Nederland 2'
'3': name: 'Nederland 3'
'4': name: 'RTL 4'
'5': name: 'E&eacute;n'
'6': name: 'Canvas'
'18': name: 'NGC'
'24': name: 'Film 1 Premium'
'29': name: 'Discovery'
'31': name: 'RTL 5'
'34': name: 'Veronica'
'36': name: 'SBS6'
'37': name: 'NET 5'
'46': name: 'RTL 7'
'91': name: 'Comedy Central'
'92': name: 'RTL 8'
'435': name: '24 Kitchen'
'438': name: 'TLC'
'440': name: 'FOX'
#
# Utils
#
tosecs = (date) -> date.getHours() * 60 + date.getSeconds()
now = -> tosecs(new Date())
time2px = (seconds) -> HOUR_WIDTH / 3600 * seconds
#
# Models & collections
#
Channel = Backbone.Model.extend(
defaults: ->
id: null
name: 'Some channel'
visible: true
initialize: (attrs, options) ->
@programs = []
)
Progam = Backbone.Model.extend(
defaults: ->
title: 'Some program'
start: null
end: null
)
ChannelList = Backbone.Collection.extend(
model: Channel
comparator: 'id'
initialize: (models, options) ->
_.each(CHANNELS, (props, id) => @add(_.extend({id: id}, props)))
@fetchVisible()
#@loadPrograms(0)
fetchVisible: ->
visible = if localStorage.hasOwnProperty('channels') \
then localStorage.getItem('channels').split(',') else @pluck('id')
@setVisible(visible)
saveVisible: ->
selected = (c.id for c in @channels if c.visible)
localStorage.setItem('channels', selected.join(','))
setVisible: (visible, save=false) ->
for id in visible
@findWhere(id: id).set(visible: true)
for id in _.difference(@pluck('id'), visible)
@findWhere(id: id).set(visible: false)
@saveVisible() if save
loadPrograms: (day, callback) ->
$.get(
'http://www.tvgids.nl/json/lists/programs.php'
channels: @pluck('id').join(','), day: day
(channels) ->
_.each channels, (id, programs) ->
channel = Channels.findWhere(id: id)
channel.programs = (new Program(p) for p in programs)
callback() if callback
'json'
)
)
#
# Views
#
ChannelView = Backbone.View.extend(
tagName: 'div'
className: 'channel'
#template: _.template($('#channel-template').html())
initialize: ->
$el.text(@model.title)
render: ->
$el.toggle(@model.visible)
)
ProgramView = Backbone.View.extend(
tagName: 'div'
className: 'program'
initialize: ->
$el.text(@model.title)
render: ->
# TODO: set highlight to past/present/future
)
AppView = Backbone.View.extend(
el: $('#guide')
initialize: ->
@listenTo(Channels, 'add', @addChannel)
@listenTo(Channels, 'reset', => Channels.each(@addChannel, @))
@listenTo(Channels, 'all', @render)
@setDay(0, => @updateIndicator())
#setInterval(=> @updateIndicator(), 3600000 / HOUR_WIDTH)
setDay: (day, callback) ->
Channels.loadPrograms(@day = day, callback)
addChannel: (channel) ->
view = new ChannelView(model: channel)
@$('.channels').append(view.render().el)
updateIndicator: ->
@$('.indicator').css('left', time2px(now()) + 'px')
render: ->
hidden
@$('.channel')
)
#
# Main
#
Channels = new ChannelList()
App = new AppView()
<!doctype html>
<html>
<head>
<title>TV gids</title>
<link href="style.css" type="text/css" rel="stylesheet">
</head>
<body>
<div id="guide" class="guide">
<div class="timeline">
<div class="hour"><span class="label">00:00</span></div>
<div class="hour"><span class="label">01:00</span></div>
<div class="hour"><span class="label">02:00</span></div>
<div class="hour"><span class="label">03:00</span></div>
<div class="hour"><span class="label">04:00</span></div>
<div class="hour"><span class="label">05:00</span></div>
<div class="hour"><span class="label">06:00</span></div>
<div class="hour"><span class="label">07:00</span></div>
<div class="hour"><span class="label">08:00</span></div>
<div class="hour"><span class="label">09:00</span></div>
<div class="hour"><span class="label">10:00</span></div>
<div class="hour"><span class="label">11:00</span></div>
<div class="hour"><span class="label">12:00</span></div>
<div class="hour"><span class="label">13:00</span></div>
<div class="hour"><span class="label">14:00</span></div>
<div class="hour"><span class="label">15:00</span></div>
<div class="hour"><span class="label">16:00</span></div>
<div class="hour"><span class="label">17:00</span></div>
<div class="hour"><span class="label">18:00</span></div>
<div class="hour"><span class="label">19:00</span></div>
<div class="hour"><span class="label">20:00</span></div>
<div class="hour"><span class="label">21:00</span></div>
<div class="hour"><span class="label">22:00</span></div>
<div class="hour"><span class="label">23:00</span></div>
</div>
<div class="indicator"></div>
<div class="channels"></div>
</div>
<script src="lib/jquery-1.10.2.min.js" type="text/javascript"></script>
<script src="lib/jquery.mousewheel.js" type="text/javascript"></script>
<script src="lib/underscore-min.js" type="text/javascript"></script>
<script src="lib/backbone-min.js" type="text/javascript"></script>
<script src="lib/json2.js" type="text/javascript"></script>
<script type="text/template" id="program-template">
<div class="program">
<%= title %>
</div>
</script>
<script src="guide.js" type="text/javascript"></script>
</body>
</html>
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
/*! Copyright (c) 2013 Brandon Aaron (http://brandon.aaron.sh)
* Licensed under the MIT License (LICENSE.txt).
*
* Version: 3.1.9
*
* Requires: jQuery 1.2.2+
*/
(function (factory) {
if ( typeof define === 'function' && define.amd ) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS style for Browserify
module.exports = factory;
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
slice = Array.prototype.slice,
nullLowestDeltaTimeout, lowestDelta;
if ( $.event.fixHooks ) {
for ( var i = toFix.length; i; ) {
$.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
}
}
var special = $.event.special.mousewheel = {
version: '3.1.9',
setup: function() {
if ( this.addEventListener ) {
for ( var i = toBind.length; i; ) {
this.addEventListener( toBind[--i], handler, false );
}
} else {
this.onmousewheel = handler;
}
// Store the line height and page height for this particular element
$.data(this, 'mousewheel-line-height', special.getLineHeight(this));
$.data(this, 'mousewheel-page-height', special.getPageHeight(this));
},
teardown: function() {
if ( this.removeEventListener ) {
for ( var i = toBind.length; i; ) {
this.removeEventListener( toBind[--i], handler, false );
}
} else {
this.onmousewheel = null;
}
},
getLineHeight: function(elem) {
return parseInt($(elem)['offsetParent' in $.fn ? 'offsetParent' : 'parent']().css('fontSize'), 10);
},
getPageHeight: function(elem) {
return $(elem).height();
},
settings: {
adjustOldDeltas: true
}
};
$.fn.extend({
mousewheel: function(fn) {
return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
},
unmousewheel: function(fn) {
return this.unbind('mousewheel', fn);
}
});
function handler(event) {
var orgEvent = event || window.event,
args = slice.call(arguments, 1),
delta = 0,
deltaX = 0,
deltaY = 0,
absDelta = 0;
event = $.event.fix(orgEvent);
event.type = 'mousewheel';
// Old school scrollwheel delta
if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; }
if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; }
if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; }
if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }
// Firefox < 17 horizontal scrolling related to DOMMouseScroll event
if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
deltaX = deltaY * -1;
deltaY = 0;
}
// Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
delta = deltaY === 0 ? deltaX : deltaY;
// New school wheel delta (wheel event)
if ( 'deltaY' in orgEvent ) {
deltaY = orgEvent.deltaY * -1;
delta = deltaY;
}
if ( 'deltaX' in orgEvent ) {
deltaX = orgEvent.deltaX;
if ( deltaY === 0 ) { delta = deltaX * -1; }
}
// No change actually happened, no reason to go any further
if ( deltaY === 0 && deltaX === 0 ) { return; }
// Need to convert lines and pages to pixels if we aren't already in pixels
// There are three delta modes:
// * deltaMode 0 is by pixels, nothing to do
// * deltaMode 1 is by lines
// * deltaMode 2 is by pages
if ( orgEvent.deltaMode === 1 ) {
var lineHeight = $.data(this, 'mousewheel-line-height');
delta *= lineHeight;
deltaY *= lineHeight;
deltaX *= lineHeight;
} else if ( orgEvent.deltaMode === 2 ) {
var pageHeight = $.data(this, 'mousewheel-page-height');
delta *= pageHeight;
deltaY *= pageHeight;
deltaX *= pageHeight;
}
// Store lowest absolute delta to normalize the delta values
absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
if ( !lowestDelta || absDelta < lowestDelta ) {
lowestDelta = absDelta;
// Adjust older deltas if necessary
if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
lowestDelta /= 40;
}
}
// Adjust older deltas if necessary
if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
// Divide all the things by 40!
delta /= 40;
deltaX /= 40;
deltaY /= 40;
}
// Get a whole, normalized value for the deltas
delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
// Add information to the event object
event.deltaX = deltaX;
event.deltaY = deltaY;
event.deltaFactor = lowestDelta;
// Go ahead and set deltaMode to 0 since we converted to pixels
// Although this is a little odd since we overwrite the deltaX/Y
// properties with normalized deltas.
event.deltaMode = 0;
// Add event and delta to the front of the arguments
args.unshift(event, delta, deltaX, deltaY);
// Clearout lowestDelta after sometime to better
// handle multiple device types that give different
// a different lowestDelta
// Ex: trackpad = 3 and mouse wheel = 120
if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
return ($.event.dispatch || $.event.handle).apply(this, args);
}
function nullLowestDelta() {
lowestDelta = null;
}
function shouldAdjustOldDeltas(orgEvent, absDelta) {
// If this is an older event and the delta is divisable by 120,
// then we are assuming that the browser is treating this as an
// older mouse wheel event and that we should divide the deltas
// by 40 to try and get a more usable deltaFactor.
// Side note, this actually impacts the reported scroll distance
// in older browsers and can cause scrolling to be slower than native.
// Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
}
}));
This diff is collapsed.
This diff is collapsed.
$indicator-color: red
$timeline-height: 30px
$hour-width: 200px
$channel-height: 40px
html, body
width: 100%
height: 100%
overflow: hidden
margin: 0
padding: 0
.guide
width: 100%
overflow-x: scroll
height: 100%
position: relative
.timeline
height: $timeline-height
width: 24 * $hour-width
.hour
float: left
width: $hour-width
height: $timeline-height
//.label
// width: 50px
// margin-left: -25px
// text-align: center
.indicator
position: absolute
width: 1px
height: 100%
top: 0
background-color: $indicator-color
.channel
position: relative
.program
position: absolute
height: $channel-height - 2px
border: 1px solid white
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment