Actually only scroll the entry to top when using keyboard shortcuts, when clicking the entry, check the visibility of the entry. This is what google reader does.

This commit is contained in:
Athou
2013-06-05 12:24:04 +02:00
parent ae9dcd2a90
commit 2b8f7cf221
3 changed files with 37 additions and 38 deletions

View File

@@ -7,12 +7,6 @@ module.run(['$rootScope', function($rootScope) {
$rootScope.$on('emitNextEntry', function(event, args) { $rootScope.$on('emitNextEntry', function(event, args) {
$rootScope.$broadcast('nextEntry', args); $rootScope.$broadcast('nextEntry', args);
}); });
$rootScope.$on('emitFocusPreviousEntry', function(event, args) {
$rootScope.$broadcast('focusPreviousEntry', args);
});
$rootScope.$on('emitFocusNextEntry', function(event, args) {
$rootScope.$broadcast('focusNextEntry', args);
});
$rootScope.$on('emitMark', function(event, args) { $rootScope.$on('emitMark', function(event, args) {
// args.entry - the entry // args.entry - the entry
$rootScope.$broadcast('mark', args); $rootScope.$broadcast('mark', args);
@@ -487,13 +481,6 @@ function($scope, $http, $state, $stateParams, $route, $location,
$scope.$emit('emitNextEntry'); $scope.$emit('emitNextEntry');
}; };
$scope.focusPreviousEntry = function() {
$scope.$emit('emitFocusPreviousEntry');
};
$scope.focusNextEntry = function() {
$scope.$emit('emitFocusNextEntry');
};
$scope.refresh = function() { $scope.refresh = function() {
if($stateParams._type == 'feed'){ if($stateParams._type == 'feed'){
FeedService.refresh({ FeedService.refresh({
@@ -783,13 +770,13 @@ function($scope, $stateParams, $http, $route, $window, EntryService, SettingsSer
}; };
$scope.isOpen = SettingsService.settings.viewMode == 'expanded'; $scope.isOpen = SettingsService.settings.viewMode == 'expanded';
$scope.entryClicked = function(entry, event) {
var openEntry = function(entry, event) {
if (event && event.which === 3) { if (event && event.which === 3) {
// right click // right click
return; return;
} }
$scope.navigationMode = 'click';
if (!event || (!event.ctrlKey && event.which != 2)) { if (!event || (!event.ctrlKey && event.which != 2)) {
if ($scope.current != entry || SettingsService.settings.viewMode == 'expanded') { if ($scope.current != entry || SettingsService.settings.viewMode == 'expanded') {
$scope.isOpen = true; $scope.isOpen = true;
@@ -800,21 +787,25 @@ function($scope, $stateParams, $http, $route, $window, EntryService, SettingsSer
$scope.mark(entry, true); $scope.mark(entry, true);
} }
$scope.current = entry; $scope.current = entry;
if(event) { if (event) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
} }
} else { } else {
$scope.mark(entry, true); $scope.mark(entry, true);
} }
}
$scope.entryClicked = function(entry, event) {
$scope.navigationMode = 'click';
openEntry(entry, event);
}; };
$scope.bodyClicked = function(entry, event) { $scope.bodyClicked = function(entry, event) {
if (SettingsService.settings.viewMode == 'expanded' && $scope.current != entry) { if (SettingsService.settings.viewMode == 'expanded' && $scope.current != entry) {
$scope.entryClicked(entry, event); $scope.entryClicked(entry, event);
} }
}; };
$scope.noop = function(event) { $scope.noop = function(event) {
if (!event.ctrlKey && event.which != 2) { if (!event.ctrlKey && event.which != 2) {
event.preventDefault(); event.preventDefault();
@@ -859,21 +850,20 @@ function($scope, $stateParams, $http, $route, $window, EntryService, SettingsSer
var openNextEntry = function(event) { var openNextEntry = function(event) {
var entry = getNextEntry(); var entry = getNextEntry();
if (entry) { if (entry) {
$scope.entryClicked(entry, event); openEntry(entry, event);
} }
}; };
var openPreviousEntry = function(event) { var openPreviousEntry = function(event) {
var entry = getPreviousEntry(); var entry = getPreviousEntry();
if (entry) { if (entry) {
$scope.entryClicked(entry, event); openEntry(entry, event);
} }
}; };
var focusNextEntry = function(event) { var focusNextEntry = function(event) {
var entry = getNextEntry(); var entry = getNextEntry();
if (entry) { if (entry) {
$scope.navigationMode = 'click';
$scope.current = entry; $scope.current = entry;
} }
}; };
@@ -881,7 +871,6 @@ function($scope, $stateParams, $http, $route, $window, EntryService, SettingsSer
var focusPreviousEntry = function(event) { var focusPreviousEntry = function(event) {
var entry = getPreviousEntry(); var entry = getPreviousEntry();
if (entry) { if (entry) {
$scope.navigationMode = 'click';
$scope.current = entry; $scope.current = entry;
} }
}; };
@@ -898,35 +887,41 @@ function($scope, $stateParams, $http, $route, $window, EntryService, SettingsSer
Mousetrap.bind('j', function(e) { Mousetrap.bind('j', function(e) {
$scope.$apply(function() { $scope.$apply(function() {
$scope.navigationMode = 'keyboard';
openNextEntry(e); openNextEntry(e);
}); });
}); });
Mousetrap.bind('n', function(e) { Mousetrap.bind('n', function(e) {
$scope.$apply(function() { $scope.$apply(function() {
$scope.navigationMode = 'keyboard';
focusNextEntry(e); focusNextEntry(e);
}); });
}); });
Mousetrap.bind('k', function(e) { Mousetrap.bind('k', function(e) {
$scope.$apply(function() { $scope.$apply(function() {
$scope.navigationMode = 'keyboard';
openPreviousEntry(e); openPreviousEntry(e);
}); });
}); });
Mousetrap.bind('p', function(e) { Mousetrap.bind('p', function(e) {
$scope.$apply(function() { $scope.$apply(function() {
$scope.navigationMode = 'keyboard';
focusPreviousEntry(e); focusPreviousEntry(e);
}); });
}); });
Mousetrap.bind('o', function(e) { Mousetrap.bind('o', function(e) {
$scope.$apply(function() { $scope.$apply(function() {
$scope.navigationMode = 'keyboard';
if ($scope.current) { if ($scope.current) {
$scope.entryClicked($scope.current, e); openEntry($scope.current, e);
} }
}); });
}); });
Mousetrap.bind('enter', function(e) { Mousetrap.bind('enter', function(e) {
$scope.$apply(function() { $scope.$apply(function() {
$scope.navigationMode = 'keyboard';
if ($scope.current) { if ($scope.current) {
$scope.entryClicked($scope.current, e); openEntry($scope.current, e);
} }
}); });
}); });
@@ -979,17 +974,13 @@ function($scope, $stateParams, $http, $route, $window, EntryService, SettingsSer
}); });
$scope.$on('previousEntry', function(event, args) { $scope.$on('previousEntry', function(event, args) {
$scope.navigationMode = 'keyboard';
openPreviousEntry(); openPreviousEntry();
}); });
$scope.$on('nextEntry', function(event, args) { $scope.$on('nextEntry', function(event, args) {
$scope.navigationMode = 'keyboard';
openNextEntry(); openNextEntry();
}); });
$scope.$on('focusPreviousEntry', function(event, args) {
focusPreviousEntry();
});
$scope.$on('focusNextEntry', function(event, args) {
focusNextEntry();
});
$scope.$on('markAll', function(event, args) { $scope.$on('markAll', function(event, args) {
$scope.markAll(args.olderThan); $scope.markAll(args.olderThan);
}); });

View File

@@ -124,7 +124,8 @@ module.directive('onScrollMiddle', function() {
}); });
/** /**
* Scrolls to the element if the value is true * Scrolls to the element if the value is true and the attribute is not fully visible,
* unless the attribute scroll-to-force is true
*/ */
module.directive('scrollTo', [ '$timeout', function($timeout) { module.directive('scrollTo', [ '$timeout', function($timeout) {
return { return {
@@ -133,6 +134,9 @@ module.directive('scrollTo', [ '$timeout', function($timeout) {
scope.$watch(attrs.scrollTo, function(value) { scope.$watch(attrs.scrollTo, function(value) {
if (!value) if (!value)
return; return;
var force = scope.$eval(attrs.scrollToForce);
// timeout here to execute after dom update
$timeout(function() { $timeout(function() {
var docTop = $(window).scrollTop(); var docTop = $(window).scrollTop();
var docBottom = docTop + $(window).height(); var docBottom = docTop + $(window).height();
@@ -140,12 +144,16 @@ module.directive('scrollTo', [ '$timeout', function($timeout) {
var elemTop = $(element).offset().top; var elemTop = $(element).offset().top;
var elemBottom = elemTop + $(element).height(); var elemBottom = elemTop + $(element).height();
var offset = parseInt(attrs.scrollToOffset, 10); if (!force && (elemTop > docTop) && (elemBottom < docBottom)) {
var scrollTop = $(element).offset().top + offset; // element is entirely visible
$('html, body').animate({ return;
scrollTop : scrollTop } else {
}, 0); var offset = parseInt(attrs.scrollToOffset, 10);
var scrollTop = $(element).offset().top + offset;
$('html, body').animate({
scrollTop : scrollTop
}, 0);
}
}); });
}); });
} }

View File

@@ -14,8 +14,8 @@
<div infinite-scroll="loadMoreEntries()" infinite-scroll-disabled="busy || !settingsService.settings.readingMode" infinite-scroll-distance="1" id="feed-accordion" <div infinite-scroll="loadMoreEntries()" infinite-scroll-disabled="busy || !settingsService.settings.readingMode" infinite-scroll-distance="1" id="feed-accordion"
ng-class="{'expanded' : settingsService.settings.viewMode == 'expanded' }"> ng-class="{'expanded' : settingsService.settings.viewMode == 'expanded' }">
<div ng-show="message && errorCount > 10">${view.error_while_loading_feed} : {{message}}</div> <div ng-show="message && errorCount > 10">${view.error_while_loading_feed} : {{message}}</div>
<div ng-repeat="entry in entries" class="entry" scroll-to="navigationMode == 'click' && current == entry" <div ng-repeat="entry in entries" class="entry" scroll-to="navigationMode != 'scroll' && current == entry"
scroll-to-offset="-58" on-scroll-middle="onScroll(entry)" scroll-to-force="navigationMode == 'keyboard'" scroll-to-offset="-58" on-scroll-middle="onScroll(entry)"
ng-class="{unread: entry.read == false, current: current==entry, open: isOpen, closed: !isOpen}"> ng-class="{unread: entry.read == false, current: current==entry, open: isOpen, closed: !isOpen}">
<a href="{{entry.url}}" target="_blank" class="entry-heading" ng-click="noop($event)" ng-mouseup="entryClicked(entry, $event)"> <a href="{{entry.url}}" target="_blank" class="entry-heading" ng-click="noop($event)" ng-mouseup="entryClicked(entry, $event)">
<span class="feed-name visible-desktop"> <span class="feed-name visible-desktop">