Reddit

« Examples

Code

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# Main reddit view
class Reddit extends Backbone.View

  # Template sets up the container and renders the two sub-templates
  @template = new Gunther.Template (ui) ->
    @e 'div.row.reddit-app', ->
      @e 'div.col-lg-4.col-md-4', -> @subTemplate postOverview, ui
      @boundElement 'div.col-lg-8.col-md-8', ui, 'selected', ui, postView

  # Constructor
  initialize: () ->
    @model = new UI

  # Keep track of the size the element should be in the  UI
  onWindowResize: () ->
    @model.set 'height', document.documentElement.clientHeight - ($ '.reddit-app').offset().top - 30

  # Render
  render: () ->
    Reddit.template.renderInto @el, @model

    # Keep track of window size
    ($ window).on 'resize', (e) => do @onWindowResize
    do @onWindowResize

# Thumbnail template
thumbTemplate = new Gunther.Template (post) ->

  # Thumb URL (or self/default)
  thumb = (post.get 'thumbnail')

  isUrl = (thumb.substr 0, 4) is 'http'

  if isUrl
    @e "img.img-thumbnail", ->
      @attr 'src', thumb
      @attr 'alt', post.get 'title'

# Post details
postDetails = new Gunther.Template (post, ui) ->

  @e 'div.post-details', ->

    @toggleClass 'visited', post, 'visited'

    @e 'strong.text-primary.post-title', -> @t post.get 'title'
    @e 'br'
    @e 'strong', -> @t post.get 'author'
    @t ' in '
    @e 'strong', -> @t "#{post.get 'subreddit'} "

# Overview of posts
postOverview = new Gunther.Template (ui) ->

  @e 'div.post-overview', ->

    frontPage = ui.get 'frontPage'

    @boundCss 'height', ui, 'height', () => "#{ui.get 'height'}px"

    @e 'table.table.reddit', ->
      @e 'thead', ->
      @list 'tbody', frontPage, new Gunther.Template (post) ->
        @e 'tr', ->
          @on 'click', (e) ->
            # Select current post
            ui.set 'selected', post

          # Toggle selected/active state on row
          @toggleClass 'active', ui, 'selected', (selectedPost) ->
            selectedPost? and selectedPost.cid is post.cid

          # Thumb and post details cells
          @e 'td.thumb', -> @subTemplate thumbTemplate, post, ui
          @e 'td.details', -> @subTemplate postDetails, post, ui

# Showing a single post's image
postView = new Gunther.Template (selectedPost, ui) ->
  return if selectedPost is null

  @e 'div.post-viewer', ->
    # Show some details
    @e 'p.post-details', ->
      @e 'strong', -> @t selectedPost.get 'title'

      @e 'br'

      d = new Date (selectedPost.get 'created_utc') * 1000

      @e 'span.text-muted', ->
        @t " posted at #{do d.toLocaleString} by #{selectedPost.get 'author'} in #{selectedPost.get 'subreddit'} "
        @e 'i.fa.fa-thumbs-up'
        @t " #{selectedPost.get 'score'} "
        @e 'i.fa.fa-chevron-up'
        @t " #{selectedPost.get 'ups'} "
        @e 'i.fa.fa-chevron-down'
        @t " #{selectedPost.get 'downs'} "

        @e 'a', ->
          @attr 'href', 'http://reddit.com' + selectedPost.get 'permalink'
          @attr 'target', '_blank'
          @e 'i.fa.fa-comments'
          @t " #{selectedPost.get 'num_comments'} "

    @e 'hr'

    # Figure out URL to "real" image
    url = (selectedPost.get 'url').substr 7
    url = "i.#{url}.jpg" unless (url.substr 0, 2) is 'i.'
    url = "http://#{url}"

    # Show the actual image with a height matching the UI's
    @e 'img', ->
      # Maximum  height for the image
      maxHeight = (ui.get 'height') - 40

      @attr 'src', url
      @on 'load', (e) ->
        ($ e.target).css 'height', maxHeight if @height > maxHeight

window.Reddit = Reddit

Models

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# Post
class Post extends Backbone.Model

  # Constructor
  initialize: () ->

    @set visited: false

# Front page
class FrontPage extends Backbone.Collection

  # Front page is a collection of posts
  model: Post

  url: 'http://www.reddit.com/.json?limit=50&jsonp=?'

  # override backbone synch to force a jsonp call
  sync: (method, model, options) ->
    params = _.extend
      type:     'GET',
      dataType:   'jsonp',
      url:      model.url,
      processData:  false
    , options

    # Make the request.
    return $.ajax params

  # Sync method result parser
  parse: (response) ->
    for item in response.data.children

      # Only use imgur posts (it's all anyone ever looks at, right?)
      continue unless item.data.domain is 'i.imgur.com' or item.data.domain is 'imgur.com'

      # Skip albums
      continue if (item.data.url.substr 0, 19) is 'http://imgur.com/a/'

      @add item.data

# UI Class
class UI extends Backbone.Model

  # Constructor
  initialize: ->

    # Set core properties
    @set
      selected: null
      frontPage: new FrontPage
      height: 0
      width: 0

    # When a post is selected, set it as visited
    @on 'change:selected', () ->
      return unless (@get 'selected')?

      (@get 'selected').set 'visited', true

    # Fetch front page
    do (@get 'frontPage').fetch

window.FrontPage = FrontPage
window.UI = UI