★ wanayoo — archive 1999 https://github.com/bkeepers/github-notifications/pull/45Nouvelle recherche | Portail wanayoo
Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add keyboard shortcuts n/p to navigate comment list #45

Merged
merged 8 commits into from

1 participant

Brandon Keepers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 24, 2013
  1. Merge remote-tracking branch 'origin/master' into create-comments

    authored
    * origin/master:
      Avoid fetching subscription status multiple times
      Reuse same collection for paginating comments
      Don't attempt to fetch subject for unsupported types
Commits on Dec 25, 2013
  1. use scrollIntoView plugin

    authored
  2. Don't loop selections

    authored
This page is out of date. Refresh to see the latest.
11 app/css/sections/conversation.styl
View
@@ -7,6 +7,16 @@
animation: fadein 0.3s;
background: #fff;
overflow: hidden;
+ border: 1px solid transparent;
+
+ &:focus {
+ outline: none;
+ }
+
+ &.selected {
+ border: 1px solid #51a7e8;
+ box-shadow: inset 0 1px 2px rgba(0,0,0,.075), 0 0 3px rgba(81,167,232,.5);
+ }
a {
text-decoration: none;
@@ -78,7 +88,6 @@
float: right;
margin-left: 18px;
-
a {
font-weight: bold;
color: inherit;
3  app/js/collections/comments.coffee
View
@@ -1,5 +1,2 @@
class app.Collections.Comments extends Backbone.Collection
model: app.Models.Comment
-
- initialize: (options) ->
- @url = options.url
3  app/js/lib/backbone-selectable.coffee
View
@@ -18,3 +18,6 @@ _.extend Backbone.Collection.prototype,
_.extend Backbone.Model.prototype,
select: ->
@collection.select(@) if @collection
+
+ isSelected: ->
+ @collection && @collection.selected == @
4 app/js/models/subject.coffee
View
@@ -5,6 +5,10 @@ class app.Models.Subject extends Backbone.Model
initialize: ->
@url = @get('url')
+ @comments = new app.Collections.Comments
+ @on 'change', ->
+ @comments.add @ if @get('body_html')
+ @comments.url = @get('comments_url')
toJSON: ->
_.extend super, octicon: @octicon
8 app/js/views/banner.coffee
View
@@ -1,6 +1,10 @@
class app.Views.Banner extends app.Views.Comment
- events: {} # clear out events
-
initialize: (options) ->
@template = options.template
super
+
+ events: {} # clear out events
+
+ # Don't select banner
+ selected: null
+ unselected: null
33 app/js/views/comment.coffee
View
@@ -2,15 +2,23 @@ class app.Views.Comment extends Backbone.View
template: JST['app/templates/comment.us']
className: 'conversation-comment'
+ keyboardEvents:
+ 'space': 'toggle'
+
events:
'click .conversation-meta': 'toggle'
+ 'focusin': 'select'
+ 'focusout': 'unselect'
initialize: (options) ->
@notification = options.notification
+ @listenTo @model, 'selected', @selected
+ @listenTo @model, 'unselected', @unselected
render: =>
@$el.html @template(@model.toJSON())
@$el.addClass if @unread() then 'expanded' else 'collapsed'
+ @$el.attr('tabindex', 0) # Make it focusable
app.trigger 'render', @
@
@@ -18,5 +26,26 @@ class app.Views.Comment extends Backbone.View
last_read_at = @notification.get('last_read_at')
!last_read_at || moment(last_read_at) < moment(@model.get('created_at'))
- toggle: ->
- @$el.toggleClass('collapsed expaneded')
+ # Only bind keyboard events if model is selected
+ bindKeyboardEvents: ->
+ super if @model.isSelected()
+
+ toggle: (e) ->
+ e.preventDefault()
+ @$el.toggleClass('collapsed expanded')
+
+ selected: ->
+ @bindKeyboardEvents()
+ @$el.addClass('selected')
+ @$el.scrollIntoView(20)
+
+ unselected: ->
+ @unbindKeyboardEvents()
+ @$el.removeClass('selected')
+
+ select: ->
+ @model.collection.select @model
+
+ # Unselect model
+ unselect: ->
+ @model.collection.select null
20 app/js/views/comments.coffee
View
@@ -1,24 +1,26 @@
class app.Views.Comments extends Backbone.View
- initialize: (options) ->
- @collection = new app.Collections.Comments(url: options.url)
- @listenTo @collection, 'add', @addComment
- @listenTo @collection, 'reset', @addAllComments
- @collection.fetch().done(@scroll).done(@paginate)
+ initialize: ->
+ @listenTo @collection, 'add', @add
+ @listenTo @collection, 'reset', @addAll
+ @fetch()
+ @addAll()
+
+ fetch: (url = @collection.url) ->
+ @collection.fetch(reset: false, remove: false).done(@scroll).done(@paginate)
paginate: (data, options, xhr) =>
- if link = @nextLink(xhr.getResponseHeader("Link"))
- @collection.fetch(url: link)
+ @fetch(link) if link = @nextLink(xhr.getResponseHeader("Link"))
nextLink: (header) =>
return unless header
links = _.map header.split(/\s*,\s*/), (link) => new app.Models.Link(link)
_.find links, (link) -> link.rel == 'next'
- addComment: (comment) ->
+ add: (comment) ->
view = new app.Views.Comment(model: comment, notification: @model)
@$el.append(view.render().el)
- addAllComments: ->
+ addAll: ->
@collection.each(@add, @)
scroll: =>
1  app/js/views/commit.coffee
View
@@ -1,3 +1,2 @@
class app.Views.Commit extends app.Views.Subject
banner: JST['app/templates/commit.us']
- isInitialComment: false
9 app/js/views/notification.coffee
View
@@ -21,11 +21,4 @@ class app.Views.Notification extends Backbone.View
@scrollIntoView()
scrollIntoView: =>
- scroller = @$el.closest('.content')
-
- change = if (topOffset = @$el.position().top) < 0
- topOffset
- else if (bottomOffset = topOffset + @$el.height() - scroller.height()) > 0
- bottomOffset
-
- scroller.scrollTop scroller.scrollTop() + change if change
+ @$el.scrollIntoView(100)
31 app/js/views/subject.coffee
View
@@ -2,9 +2,9 @@ class app.Views.Subject extends Backbone.View
template: JST['app/templates/subject.us']
className: 'subject content loading'
- # Is the model also the initial comment? This is true for Issues and
- # PullRequests, but not for Commits
- isInitialComment: true
+ keyboardEvents:
+ 'n': 'selectNext'
+ 'p': 'selectPrevious'
@for: (model) ->
app.Views[model.constructor.name] || app.Views.Subject
@@ -16,10 +16,6 @@ class app.Views.Subject extends Backbone.View
@bannerView = new app.Views.Banner(model: @model, notification: @notification, template: @banner)
@listenTo @model, 'change', @bannerView.render
- if @isInitialComment
- @initialCommentView = new app.Views.Comment(model: @model, notification: @notification)
- @listenTo @model, 'change', @initialCommentView.render
-
@listenTo @model, 'change', @loadComments
@render()
@@ -29,13 +25,24 @@ class app.Views.Subject extends Backbone.View
@$el.html @template()
app.trigger 'render', @
@$('.comments').append(@bannerView.el) if @banner
- @$('.comments').append(@initialCommentView.el) if @isInitialComment
loadComments: ->
- if url = @model.get('comments_url')
- @comments = new app.Views.Comments(model: @notification, url: url, el: @$('.comments'))
- @comments.collection.on 'sync', @loaded
- @$el.append new app.Views.CreateComment(collection: @comments.collection).el
+ if url = @model.comments.url
+ @comments = new app.Views.Comments(collection: @model.comments, model: @notification, el: @$('.comments'))
+ @model.comments.on 'sync', @loaded
+ @$el.append new app.Views.CreateComment(collection: @model.comments).el
loaded: =>
@$el.removeClass('loading')
+
+ selectNext: ->
+ comment = if @model.comments.selected
+ @model.comments.next()
+ else
+ @model.comments.first()
+
+ @model.comments.select comment if comment
+
+ selectPrevious: ->
+ if comment = @model.comments.prev()
+ @model.comments.select comment
3  bower.json
View
@@ -10,7 +10,8 @@
"moment": "~2.1.0",
"mousetrap": "~1.4.5",
"backbone.mousetrap": "https://github.com/elasticsales/backbone.mousetrap.git",
- "backbone.localStorage": "~1.1.6"
+ "backbone.localStorage": "~1.1.6",
+ "jQuery.scrollIntoView": "https://github.com/Arwid/jQuery.scrollIntoView.git"
},
"devDependencies": {
"primer": "https://github.com/github/primer.git"
1  config/files.coffee
View
@@ -30,6 +30,7 @@ module.exports = require(process.env["LINEMAN_MAIN"]).config.extend "files",
"vendor/bower/mousetrap/mousetrap.js",
"vendor/bower/backbone.mousetrap/backbone.mousetrap.js",
"vendor/bower/backbone.localStorage/backbone.localStorage.js",
+ "vendor/bower/jQuery.scrollIntoView/jquery.scrollIntoView.js",
"vendor/js/**/*.js"
]
app: ["app/js/**/*.js"]
Something went wrong with that request. Please try again.