From 1c048042ed5f5c9ce8696fe010a45b9e2eb22771 Mon Sep 17 00:00:00 2001 From: Adam Coldrick Date: Mon, 18 Feb 2019 19:09:42 +0000 Subject: [PATCH] Remember scroll offset of lanes when refreshing board view When the board object in the board detail view is reloaded (which is quite a regular occurrence to help prevent stale data being used), the scroll position of lanes is lost. This is a minor inconvenience for small boards with only a few cards and a short distance to scroll, but is frustrating for large boards with many cards per lane, since it can be hard to find the old scroll location. The issue is compounded by long load times of large boards making it seem like the lane scrollbars reset with no apparent reason. This commit solves this issue by adding support to remember the scroll position of each lane when updating the board object, and re-scrolling the newly rendered lanes to the correct position. Change-Id: I75a6703b2f43bed8cdc4643f6a103f95e1fa61ae --- .../controller/board_detail_controller.js | 5 +++ src/app/boards/service/board_helper.js | 42 ++++++++++++++++++- .../board_contents/kanban_lane_contents.html | 3 +- .../kanban_lane_contents_static.html | 3 +- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/app/boards/controller/board_detail_controller.js b/src/app/boards/controller/board_detail_controller.js index 1d623ce5..756a22a9 100644 --- a/src/app/boards/controller/board_detail_controller.js +++ b/src/app/boards/controller/board_detail_controller.js @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2016 Codethink Limited + * Copyright (c) 2019 Adam Coldrick * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain @@ -22,6 +23,8 @@ angular.module('sb.board').controller('BoardDetailController', BoardHelper, DueDate, $document, User, $q, moment) { 'use strict'; + $scope.board = new Board(); + /** * Load the board. If onlyContents is true then assume $scope.board * is a board and reload its contents. @@ -35,6 +38,7 @@ angular.module('sb.board').controller('BoardDetailController', }; }); Board.get(params, function(board) { + var offsets = BoardHelper.recordLaneScrollbars($scope.board); $scope.board = board; $scope.owners = []; $scope.users = []; @@ -44,6 +48,7 @@ angular.module('sb.board').controller('BoardDetailController', angular.forEach(board.users, function(id) { $scope.users.push(User.get({id: id})); }); + BoardHelper.scrollLanes(board, offsets); }); } diff --git a/src/app/boards/service/board_helper.js b/src/app/boards/service/board_helper.js index 33aafe3e..636515b6 100644 --- a/src/app/boards/service/board_helper.js +++ b/src/app/boards/service/board_helper.js @@ -18,7 +18,7 @@ * A service to help with use of a kanban board. */ angular.module('sb.board').factory('BoardHelper', - function($document, $window, Worklist) { + function($document, $window, $timeout, Worklist) { 'use strict'; /** @@ -73,9 +73,47 @@ angular.module('sb.board').factory('BoardHelper', }); } + /** + * Function to record scrollbar positions for the lanes of a board. + * + * This is used to track where a user has scrolled each lane to before + * refreshing the board UI. It returns a mapping of lane IDs to scroll + * offsets which can later be used to re-scroll to the correct point. + */ + function recordLaneScrollbars(board) { + var scrollbars = {}; + angular.forEach(board.lanes, function(lane) { + var elem = $document[0].getElementById('lane-' + lane.id); + if (!!elem) { + scrollbars[lane.id] = elem.scrollTop; + } + }); + return scrollbars; + } + + /** + * Function to scroll lanes to a previously recorded position. + * + * Takes a board and a mapping of lane IDs to scroll offsets as + * produced by `recordLaneScrollbars` and scrolls the corresponding + * lane containers by the given offsets. + */ + function scrollLanes(board, scrollbars) { + angular.forEach(board.lanes, function(lane) { + $timeout(function() { + var elem = $document[0].getElementById('lane-' + lane.id); + if (!!elem) { + elem.scrollTop = scrollbars[lane.id]; + } + }); + }); + } + return { maybeScrollContainer: scrollFunction, - moveCard: moveCard + moveCard: moveCard, + recordLaneScrollbars: recordLaneScrollbars, + scrollLanes: scrollLanes }; } ); diff --git a/src/app/boards/template/board_contents/kanban_lane_contents.html b/src/app/boards/template/board_contents/kanban_lane_contents.html index a0ee00ad..31001836 100644 --- a/src/app/boards/template/board_contents/kanban_lane_contents.html +++ b/src/app/boards/template/board_contents/kanban_lane_contents.html @@ -15,7 +15,8 @@ -->
+ class="kanban-lane-contents" + id="lane-{{ lane.id }}">
-
+