2017-12-16 03:37:19 +00:00
|
|
|
"use strict";
|
|
|
|
|
|
|
|
const $ = require("jquery");
|
|
|
|
const fuzzy = require("fuzzy");
|
2017-12-16 18:58:56 +00:00
|
|
|
const Mousetrap = require("mousetrap");
|
2017-12-16 03:37:19 +00:00
|
|
|
|
|
|
|
const templates = require("../views");
|
|
|
|
|
|
|
|
const chat = $("#chat");
|
|
|
|
|
|
|
|
chat.on("input", ".users .search", function() {
|
|
|
|
const value = $(this).val();
|
|
|
|
const parent = $(this).closest(".users");
|
|
|
|
const names = parent.find(".names-original");
|
|
|
|
const container = parent.find(".names-filtered");
|
|
|
|
|
2017-12-16 18:58:56 +00:00
|
|
|
// Input content has changed, reset the potential selection
|
|
|
|
parent.find(".user").removeClass("active");
|
|
|
|
|
2017-12-16 03:37:19 +00:00
|
|
|
if (!value.length) {
|
|
|
|
container.hide();
|
|
|
|
names.show();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const fuzzyOptions = {
|
|
|
|
pre: "<b>",
|
|
|
|
post: "</b>",
|
|
|
|
extract: (el) => $(el).text(),
|
|
|
|
};
|
|
|
|
|
|
|
|
const result = fuzzy.filter(
|
|
|
|
value,
|
|
|
|
names.find(".user").toArray(),
|
|
|
|
fuzzyOptions
|
|
|
|
);
|
|
|
|
|
|
|
|
names.hide();
|
|
|
|
container.html(templates.user_filtered({matches: result})).show();
|
|
|
|
});
|
2017-12-16 18:58:56 +00:00
|
|
|
|
2017-12-16 19:26:09 +00:00
|
|
|
chat.on("mouseenter", ".users .user", function() {
|
|
|
|
// Reset any potential selection, this is required in cas there is already a
|
|
|
|
// nick previously selected by keyboard
|
|
|
|
$(".users .user").removeClass("active");
|
|
|
|
|
|
|
|
$(this).addClass("active");
|
|
|
|
});
|
|
|
|
|
|
|
|
chat.on("mouseleave", ".users .user", function() {
|
|
|
|
// Reset any potential selection
|
|
|
|
$(".users .user").removeClass("active");
|
|
|
|
});
|
|
|
|
|
2017-12-16 18:58:56 +00:00
|
|
|
exports.handleKeybinds = function(input) {
|
|
|
|
Mousetrap(input.get(0)).bind(["up", "down"], (_e, key) => {
|
|
|
|
const userlists = input.closest(".users");
|
2017-12-16 20:27:26 +00:00
|
|
|
let userlist;
|
2017-12-16 18:58:56 +00:00
|
|
|
|
|
|
|
// If input field has content, use the filtered list instead
|
|
|
|
if (input.val().length) {
|
2017-12-16 20:27:26 +00:00
|
|
|
userlist = userlists.find(".names-filtered");
|
2017-12-16 18:58:56 +00:00
|
|
|
} else {
|
2017-12-16 20:27:26 +00:00
|
|
|
userlist = userlists.find(".names-original");
|
2017-12-16 18:58:56 +00:00
|
|
|
}
|
|
|
|
|
2017-12-16 20:27:26 +00:00
|
|
|
const users = userlist.find(".user");
|
|
|
|
|
2017-12-16 18:58:56 +00:00
|
|
|
// 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");
|
|
|
|
}
|
2017-12-16 20:27:26 +00:00
|
|
|
|
|
|
|
// Adjust scroll when active item is outside of the visible area
|
|
|
|
const userlistHeight = userlist.height();
|
|
|
|
const userlistScroll = userlist.scrollTop();
|
|
|
|
const active = $(".user.active");
|
|
|
|
const activeTop = active.position().top;
|
|
|
|
const activeHeight = active.height();
|
|
|
|
|
|
|
|
if (activeTop > userlistHeight - activeHeight) {
|
|
|
|
userlist.scrollTop(userlistScroll + activeTop - userlistHeight + activeHeight);
|
|
|
|
} else if (activeTop < 0) {
|
|
|
|
userlist.scrollTop(userlistScroll + activeTop - activeHeight);
|
|
|
|
}
|
2017-12-16 18:58:56 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
// 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) {
|
2017-12-16 20:40:46 +00:00
|
|
|
const clickEvent = new $.Event("click");
|
|
|
|
const userOffset = user.offset();
|
|
|
|
clickEvent.pageX = userOffset.left;
|
|
|
|
clickEvent.pageY = userOffset.top + user.height();
|
|
|
|
user.trigger(clickEvent);
|
2017-12-16 18:58:56 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|