Skip to content

Commit

Permalink
highlight current inquiry username in page
Browse files Browse the repository at this point in the history
doesn't yet work on Firefox, but they're working on it
  • Loading branch information
ornicar committed Jan 20, 2025
1 parent 0fe754b commit b2404d1
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 2 deletions.
2 changes: 1 addition & 1 deletion app/views/mod/inquiry.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ object inquiry:
)

def apply(in: lila.mod.Inquiry)(using ctx: Context) =
div(id := "inquiry")(
div(id := "inquiry", data("username") := in.user.user.username)(
i(title := "Costello the Inquiry Octopus", cls := "costello"),
div(cls := "meat")(
userLink(in.user.user, withPerfRating = in.user.perfs.some, params = "?mod"),
Expand Down
68 changes: 68 additions & 0 deletions ui/common/src/highlight.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* Ported to typescript from https://github.com/marmelab/highlight-search-term/blob/main/src/index.js */

export const highlightSearchTerm = (search: string, selector: string): void => {
const highlightName = 'lichess-highlight';

console.log(search, CSS.highlights, highlightName);

if (!CSS.highlights) return; // disable feature on Firefox as it does not support CSS Custom Highlight API

// remove previous highlight
CSS.highlights.delete(highlightName);
if (!search) {
// nothing to highlight
return;
}
// find all text nodes containing the search term
const ranges: AbstractRange[] = [];
try {
const elements = document.querySelectorAll<HTMLElement>(selector);
Array.from(elements).map(element => {
getTextNodesInElementContainingText(element, search).forEach(node => {
node.parentElement && ranges.push(...getRangesForSearchTermInElement(node.parentElement, search));
});
});
} catch (error) {
console.error(error);
}
if (ranges.length === 0) return;
// create a CSS highlight that can be styled with the ::highlight(search) pseudo-element
const highlight = new Highlight(...ranges);
CSS.highlights.set(highlightName, highlight);
};

const getTextNodesInElementContainingText = (element: HTMLElement, text: string) => {
const lowerCaseText = text.toLowerCase();
const nodes = [];
const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
let node;
while ((node = walker.nextNode())) {
if (node.textContent?.toLowerCase().includes(lowerCaseText)) {
nodes.push(node);
}
}
return nodes;
};

const getRangesForSearchTermInElement = (element: HTMLElement, search: string) => {
const ranges: AbstractRange[] = [];
const lowerCaseSearch = search.toLowerCase();
if (element.childNodes.length === 0) return ranges;
// In some frameworks like React, when combining static text with dynamic text, the element may have multiple Text child nodes.
// To avoid errors, we must find the child node that actually contains the search term.
const childWithSearchTerm = Array.from(element.childNodes).find(node =>
node.textContent?.toLowerCase().includes(lowerCaseSearch),
);
if (!childWithSearchTerm) return ranges;
const text = childWithSearchTerm.textContent?.toLowerCase() || '';
let start = 0;
let index;
while ((index = text.indexOf(lowerCaseSearch, start)) >= 0) {
const range = new Range();
range.setStart(childWithSearchTerm, index);
range.setEnd(childWithSearchTerm, index + search.length);
ranges.push(range);
start = index + search.length;
}
return ranges;
};
5 changes: 5 additions & 0 deletions ui/mod/css/_inquiry.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ body.no-inquiry {
}
}

*::highlight(lichess-highlight) {
background-color: yellow;
color: black;
}

#inquiry {
height: 48px;
background: #484541;
Expand Down
5 changes: 4 additions & 1 deletion ui/mod/src/mod.inquiry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import { formToXhr } from 'common/xhr';
import { expandMentions } from 'common/richText';
import { storage } from 'common/storage';
import { alert } from 'common/dialog';
import { highlightSearchTerm } from 'common/highlight';

site.load.then(() => {
const noteStore = storage.make('inquiry-note');
const usernameNoteStore = storage.make('inquiry-note-user');
const username = $('#inquiry .meat > .user-link').text().split(' ')[0];
const username = $('#inquiry').data('username');
if (username !== usernameNoteStore.get()) noteStore.remove();
usernameNoteStore.set(username);
const noteTextArea = $('#inquiry .notes').find('textarea')[0] as HTMLTextAreaElement;
Expand Down Expand Up @@ -114,4 +115,6 @@ site.load.then(() => {
const username = $(this).parents('tr').find('td:first-child .user-link').text().split(' ')[0];
addToNote(`Alt: @${username}`);
});

setTimeout(() => highlightSearchTerm(username, '#main-wrap .user-link'), 500);
});

0 comments on commit b2404d1

Please sign in to comment.