Allow navigating through userlist results from keyboard

This commit is contained in:
Jérémie Astori 2017-12-16 13:58:56 -05:00
parent 25517f3ad7
commit 649d60c119
No known key found for this signature in database
GPG Key ID: B9A4F245CD67BDE8
3 changed files with 53 additions and 2 deletions

View File

@ -1921,7 +1921,8 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */
.context-menu-item:hover, .context-menu-item:hover,
.textcomplete-item:hover, .textcomplete-item:hover,
.textcomplete-menu .active { .textcomplete-menu .active,
#chat .users .user.active {
background-color: #f6f6f6; background-color: #f6f6f6;
transition: none; transition: none;
} }

View File

@ -10,6 +10,7 @@ const constants = require("./constants");
const condensed = require("./condensed"); const condensed = require("./condensed");
const JoinChannel = require("./join-channel"); const JoinChannel = require("./join-channel");
const helpers_parse = require("./libs/handlebars/parse"); const helpers_parse = require("./libs/handlebars/parse");
const Userlist = require("./userlist");
const chat = $("#chat"); const chat = $("#chat");
const sidebar = $("#sidebar"); const sidebar = $("#sidebar");
@ -117,7 +118,9 @@ function renderChannel(data) {
renderChannelMessages(data); renderChannelMessages(data);
if (data.type === "channel") { if (data.type === "channel") {
renderChannelUsers(data); const users = renderChannelUsers(data);
Userlist.handleKeybinds(users.find(".search"));
} }
if (historyObserver) { if (historyObserver) {
@ -173,6 +176,8 @@ function renderChannelUsers(data) {
if (search.val().length) { if (search.val().length) {
search.trigger("input"); search.trigger("input");
} }
return users;
} }
function renderNetworks(data, singleNetwork) { function renderNetworks(data, singleNetwork) {

View File

@ -2,6 +2,7 @@
const $ = require("jquery"); const $ = require("jquery");
const fuzzy = require("fuzzy"); const fuzzy = require("fuzzy");
const Mousetrap = require("mousetrap");
const templates = require("../views"); const templates = require("../views");
@ -13,6 +14,9 @@ chat.on("input", ".users .search", function() {
const names = parent.find(".names-original"); const names = parent.find(".names-original");
const container = parent.find(".names-filtered"); const container = parent.find(".names-filtered");
// Input content has changed, reset the potential selection
parent.find(".user").removeClass("active");
if (!value.length) { if (!value.length) {
container.hide(); container.hide();
names.show(); names.show();
@ -34,3 +38,44 @@ chat.on("input", ".users .search", function() {
names.hide(); names.hide();
container.html(templates.user_filtered({matches: result})).show(); container.html(templates.user_filtered({matches: result})).show();
}); });
exports.handleKeybinds = function(input) {
Mousetrap(input.get(0)).bind(["up", "down"], (_e, key) => {
const userlists = input.closest(".users");
let users;
// If input field has content, use the filtered list instead
if (input.val().length) {
users = userlists.find(".names-filtered .user");
} else {
users = userlists.find(".names-original .user");
}
// Find which item in the array of users is currently selected, if any.
// Returns -1 if none.
const activeIndex = users.toArray()
.findIndex((user) => user.classList.contains("active"));
// Now that we know which user is active, reset any selection
userlists.find(".user").removeClass("active");
// Mark next/previous user as active.
if (key === "down") {
// If no users or last user were marked as active, mark the first one.
users.eq((activeIndex + 1) % users.length).addClass("active");
} else {
// If no users or first user was marked as active, mark the last one.
users.eq(Math.max(activeIndex, 0) - 1).addClass("active");
}
});
// When pressing Enter, open the context menu (emit a click) on the active
// user
Mousetrap(input.get(0)).bind("enter", () => {
const user = input.closest(".users").find(".user.active");
if (user.length) {
user.click();
}
});
};