diff --git a/www/css/cytube.css b/www/css/cytube.css index 719340cd..5159f72d 100644 --- a/www/css/cytube.css +++ b/www/css/cytube.css @@ -880,3 +880,7 @@ body.tv #controlsrow, body.tv #playlistrow { display: none; } + +.emote-suggest-item { padding: 3px 8px; cursor: pointer; display: flex; align-items: center; gap: 7px; font-size: 13px; color: #c8c8c8; } +.emote-suggest-item img { width: 24px; height: 24px; object-fit: contain; flex-shrink: 0; } +.emote-suggest-item:hover, .emote-suggest-item.active { background: #3a3f44; color: #fff; } diff --git a/www/js/ui.js b/www/js/ui.js index a9c84d22..b7ded81b 100644 --- a/www/js/ui.js +++ b/www/js/ui.js @@ -165,9 +165,78 @@ function chatTabComplete(chatline) { chatline.setSelectionRange(result.newPosition, result.newPosition); } +/* emote autocomplete */ +var EMOTE_SUGGEST_IDX = 0; +function emoteLastWord() { + var words = $("#chatline").val().split(" "); + return words[words.length - 1].toLowerCase(); +} +function emoteAccept() { + var item = $("#emote-suggestions .active"); + if (!item.length) item = $("#emote-suggestions").children().first(); + if (!item.length) return; + var words = $("#chatline").val().split(" "); + words[words.length - 1] = item.data("name") + " "; + $("#chatline").val(words.join(" ")); + $("#emote-suggestions").hide(); +} +function emoteRefresh() { + var partial = emoteLastWord(); + var popup = $("#emote-suggestions"); + if (partial.length < 2 || !CHANNEL.emotes || !CHANNEL.emotes.length) { popup.hide(); return; } + var matches = CHANNEL.emotes.filter(function(e) { + return e.name.toLowerCase().indexOf(partial) === 0; + }).slice(0, 8); + if (!matches.length) { popup.hide(); return; } + popup.empty(); + matches.forEach(function(e) { + $("
").addClass("emote-suggest-item") + .data("name", e.name) + .html('' + e.name) + .appendTo(popup); + }); + popup.children().first().addClass("active"); + EMOTE_SUGGEST_IDX = 0; + var cl = $("#chatline"), off = cl.offset(); + popup.css({ left: off.left, width: cl.outerWidth() }).show(); + popup.css("top", off.top - popup.outerHeight() - 2); +} +$("#chatline").on("input", emoteRefresh); +$(document).on("mousedown", function(e) { + if (!$(e.target).closest("#emote-suggestions, #chatline").length) + $("#emote-suggestions").hide(); +}); +$(document).on("mousedown", "#emote-suggestions .emote-suggest-item", function() { + EMOTE_SUGGEST_IDX = $(this).index(); + $("#emote-suggestions .active").removeClass("active"); + $(this).addClass("active"); + emoteAccept(); + $("#chatline").focus(); +}); +$("body").append(''); + $("#chatline").on('keydown', function(ev) { + var open = $("#emote-suggestions").is(":visible"); + if (open) { + if (ev.keyCode == 27) { // Escape + $("#emote-suggestions").hide(); + ev.preventDefault(); return false; + } else if (ev.keyCode == 9 || (ev.keyCode == 39 && this.selectionStart === this.value.length)) { // Tab or right arrow at end + emoteAccept(); + ev.preventDefault(); return false; + } else if (ev.keyCode == 38 || ev.keyCode == 40) { // Up/down navigate + var items = $("#emote-suggestions").children(); + items.eq(EMOTE_SUGGEST_IDX).removeClass("active"); + EMOTE_SUGGEST_IDX = ev.keyCode == 38 + ? (EMOTE_SUGGEST_IDX - 1 + items.length) % items.length + : (EMOTE_SUGGEST_IDX + 1) % items.length; + items.eq(EMOTE_SUGGEST_IDX).addClass("active")[0].scrollIntoView({ block: "nearest" }); + ev.preventDefault(); return false; + } + } // Enter/return if(ev.keyCode == 13) { + $("#emote-suggestions").hide(); if (CHATTHROTTLE) { return; }