amatriain/feedbunch

View on GitHub
FeedBunch-app/app/assets/javascripts/ng-services/ng-HighlightedSidebarLinkSvc.js.coffee

Summary

Maintainability
Test Coverage
########################################################
# AngularJS service for the currently highlighted link in the sidebar.
########################################################

angular.module('feedbunch').service 'highlightedSidebarLinkSvc',
['$rootScope', '$filter', 'animationsSvc', 'findSvc', 'openFolderSvc',
($rootScope, $filter, animationsSvc, findSvc, openFolderSvc)->

  # Media query to enable highlighting only in screens wider than a tablet's
  md_min_media_query = 'screen and (min-width: 992px)'

  #---------------------------------------------
  # PRIVATE CONSTANTS
  #---------------------------------------------
  START = 'start'
  FEED = 'feed'
  FOLDER = 'folder'

  #---------------------------------------------
  # PRIVATE FUNCTION: Highlight a single link in the sidebar.
  # Receives as argument a jquery object for the highlighted link.
  #---------------------------------------------
  single_highlighted_link = (link)->
    $("#sidebar a.highlighted-link").removeClass 'highlighted-link'
    link.addClass 'highlighted-link'

  #---------------------------------------------
  # PRIVATE FUNCTION: Set the currently highlighted link.
  # Receives as arguments:
  # - id: if the selected link is the "Start" link, the START constant is passed here.
  # If it's a feed link, it's the feed ID. If it's a folder's "Read all subscriptions" link, it's the folder ID.
  # - type: optional argument. If the id argument is START, this argument will be ignored. Otherwise, it takes the value
  # FEED or FOLDER to indicate if the ID passed corresponds to a feed or a folder.
  #---------------------------------------------
  set = (id, type=null)->
    # Do not enable highlighting in smartphone and tablet-sized screens
    enquire.register md_min_media_query, ->
      if id == START
        $rootScope.highlighted_sidebar_link = {id: id, type: null}
        start_link = $('#start-page')
        single_highlighted_link start_link
      else if type == FEED
        $rootScope.highlighted_sidebar_link = {id: id, type: type}
        feed_link = $("#folders-list a[data-feed-id=#{id}]")
        single_highlighted_link feed_link
      else if type == FOLDER
        $rootScope.highlighted_sidebar_link = {id: id, type: type}
        folder_link = $("#folders-list #feeds-#{id} a[data-feed-id='all']")
        single_highlighted_link folder_link

  #---------------------------------------------
  # PRIVATE FUNCTION: returns an array with the links in the sidebar, in the same order they are visible.
  # Each link is represented by an object with these attributes:
  # - id: the value START if it's the "Start" link, or the ID of the feed or folder if it's a feed or folder link
  # - type: either FEED or FOLDER if it's a feed or folder link, or null if it's the "Start" link
  #---------------------------------------------
  sidebar_links = ->
    links = []
    links.push {id: START, type: null}

    no_folder_feeds = findSvc.find_folder_feeds 'none'
    ordered_feeds = $filter('orderBy') no_folder_feeds, 'title'
    links.push {id: 'all', type: FOLDER}
    if ordered_feeds && ordered_feeds?.length > 0
      for feed in ordered_feeds
        links.push {id: feed.id, type: FEED}

    ordered_folders = $filter('orderBy') $rootScope.folders, 'title'
    if ordered_folders? && ordered_folders?.length > 0
      for folder in ordered_folders
        folder_feeds = findSvc.find_folder_feeds folder
        # The "All subscriptions" link for a folder is visible only if there is more than 1 feed in it
        links.push {id: folder.id, type: FOLDER} if folder_feeds?.length > 1
        ordered_feeds = $filter('orderBy') folder_feeds, 'title'
        if ordered_feeds && ordered_feeds?.length > 0
          for feed in ordered_feeds
            links.push {id: feed.id, type: FEED}

    return links

  #---------------------------------------------
  # PRIVATE FUNCTION: find the index of the passed link in the array of sidebar links.
  # A simple .indexOf search won't work because the passed link object is not actually in the array,
  # rather an object with the same attribute values is in the array.
  #
  # The objects representing links have two attributes:
  # - id: the feed or folder ID if it's a feed or folder link; or START if it's the "Start" link
  # - type: FEED or FOLDER if it's a feed or folder link; or null if it's the "Start" link
  #---------------------------------------------
  link_index = (link_object, sidebar_links)->
    array_links = $filter('filter') sidebar_links, (l)->
      return l.id == link_object.id && l.type == link_object.type

    array_link = array_links[0] if array_links?.length == 1
    index = sidebar_links.indexOf array_link
    return index

  service =

    #---------------------------------------------
    # Unset highlighting (no sidebar link is highlighted)
    #---------------------------------------------
    unset: ->
      $("#sidebar a.highlighted-link").removeClass 'highlighted-link'
      delete $rootScope.highlighted_sidebar_link

    #---------------------------------------------
    # Set the "start" link in the sidebar as the currently highlighted one
    #---------------------------------------------
    reset: ->
      set START

    #---------------------------------------------
    # Highlight the link for the passed feed
    #---------------------------------------------
    set_feed: (feed)->
      set feed.id, FEED

    #---------------------------------------------
    # Highlight the link for the passed folder
    #---------------------------------------------
    set_folder: (folder)->
      if folder == 'all'
        id = 'all'
      else
        id = folder.id
      set id, FOLDER

    #---------------------------------------------
    # Get the currently highlighted link.
    # It returns an object with two attributes:
    # - id: the ID of the feed or folder, if the highlighted link corresponds to a link or folder; or "start" if
    # the highlighted link is the "Start" link
    # - type: either "feed" or "folder" if the highlighted link is a feed or folder; or null if the highlighted link
    # is the "Start" link
    #---------------------------------------------
    get: ->
      return $rootScope.highlighted_sidebar_link

    #---------------------------------------------
    # Highlight the next link (below current one).
    #---------------------------------------------
    next: ->
      # Do not enable highlighting in smartphone and tablet-sized screens
      enquire.register md_min_media_query, ->
        links = sidebar_links()
        index = link_index $rootScope.highlighted_sidebar_link, links
        if index >= 0 && index < (links.length - 1)
          next_link = links[index + 1]
          set next_link.id, next_link.type

          # Open folder if necessary
          if next_link.type == FOLDER
            folder_id = next_link.id
          else if next_link.type == FEED
            feed = findSvc.find_feed next_link.id
            folder_id = feed.folder_id

          # The "all" folder is a bit special, it cannot be opened/closed
          if folder_id? && folder_id != 'all' && folder_id != 'none'
            folder = findSvc.find_folder folder_id
            openFolderSvc.set folder

          animationsSvc.sidebar_scroll_down next_link

    #---------------------------------------------
    # Highlight the previous link (above current one)
    #---------------------------------------------

    previous: ->
      # Do not enable highlighting in smartphone and tablet-sized screens
      enquire.register md_min_media_query, ->
        links = sidebar_links()
        index = link_index $rootScope.highlighted_sidebar_link, links
        if index > 0 && index < links.length
          previous_link = links[index - 1]
          set previous_link.id, previous_link.type

          # Open folder if necessary
          if previous_link.type == FOLDER
            folder_id = previous_link.id
          else if previous_link.type == FEED
            feed = findSvc.find_feed previous_link.id
            folder_id = feed.folder_id

          # The "all" folder is a bit special, it cannot be opened/closed
          if folder_id? && folder_id != 'all' && folder_id != 'none'
            folder = findSvc.find_folder folder_id
            openFolderSvc.set folder

          animationsSvc.sidebar_scroll_up previous_link

  return service
]