diff --git a/src/filemanager.html b/src/filemanager.html index 41f2133d0..4b4de16e5 100644 --- a/src/filemanager.html +++ b/src/filemanager.html @@ -358,7 +358,7 @@ {{ 'filemanager.list.empty' | tr }} - + diff --git a/src/js/filemanager.js b/src/js/filemanager.js index e24874297..fed9a5dcd 100644 --- a/src/js/filemanager.js +++ b/src/js/filemanager.js @@ -128,6 +128,16 @@ app.controller('FileManagerController', ['$scope', '$translate', '$timeout', 'Cl return filePath; } + function sort() { + return $scope.entries.sort(function (a, b) { + if (a.fileName.toLowerCase() < b.fileName.toLowerCase()) return -1; + return 1; + }).sort(function (a, b) { + if (a.isDirectory !== b.isDirectory) return 1; + return -1; + }); + } + function openPath(path) { path = sanitize(path); @@ -196,6 +206,7 @@ app.controller('FileManagerController', ['$scope', '$translate', '$timeout', 'Cl }); $scope.entries = result.entries; + sort(); // call itself now that we know $scope.cwd = parentPath; @@ -401,6 +412,7 @@ app.controller('FileManagerController', ['$scope', '$translate', '$timeout', 'Cl }); $scope.entries = result.entries; + sort(); $scope.busy = false; }); @@ -1194,4 +1206,69 @@ app.controller('FileManagerController', ['$scope', '$translate', '$timeout', 'Cl elem[0].setSelectionRange(0, text.indexOf('.')); }); }); + + function scrollInView(element) { + if (!element) return; + + // This assumes the DOM tree being that rigid + function isVisible(ele) { + var container = ele.parentElement.parentElement.parentElement; + var eleTop = ele.offsetTop; + var eleBottom = eleTop + ele.clientHeight; + + var containerTop = container.scrollTop; + var containerBottom = containerTop + container.clientHeight; + + // The element is fully visible in the container + return ( + (eleTop >= containerTop && eleBottom <= containerBottom) || + // Some part of the element is visible in the container + (eleTop < containerTop && containerTop < eleBottom) || + (eleTop < containerBottom && containerBottom < eleBottom) + ); + } + + if (!isVisible(element)) element.scrollIntoView(); + } + + function openSelected() { + if (!$scope.selected.length) return; + + $scope.open($scope.selected[0]); + } + + function selectNext() { + var entries = sort(); + + if (!$scope.selected.length) return $scope.selected = [ entries[0] ]; + + var curIndex = $scope.entries.indexOf($scope.selected[0]); + if (curIndex !== -1 && curIndex < $scope.entries.length-1) { + var entry = entries[++curIndex]; + $scope.selected = [ entry ]; + scrollInView(document.querySelector('[entry-hashkey="' + entry['$$hashKey'] + '"]')); + } + } + + function selectPrev() { + var entries = sort(); + + if (!$scope.selected.length) return $scope.selected = [ entries.slice(-1) ]; + + var curIndex = $scope.entries.indexOf($scope.selected[0]); + if (curIndex !== -1 && curIndex !== 0) { + var entry = entries[--curIndex]; + $scope.selected = [ entry ]; + scrollInView(document.querySelector('[entry-hashkey="' + entry['$$hashKey'] + '"]')); + } + } + + window.document.addEventListener('keydown', function (event) { + $scope.$apply(function () { + if (event.key === 'ArrowDown') selectNext(); + else if (event.key === 'ArrowUp') selectPrev(); + else if (event.key === 'Enter') openSelected(); + else if (event.key === 'Backspace') $scope.goDirectoryUp(); + }); + }); }]);