Fossil User Forum

Quickfilter
Login

Quickfilter

Quickfilter

(1) By Jörgen Kosche (jkosche) on 2025-03-26 17:27:07 [link] [source]

I made a small feature I call quickfilter. It is simply an input field, which as you type into it filters a list of items to only show the ones matching the typed text. I added it to the ticket reports and to repolist.

It is on the branch quickfilter.

As I think a filter is unneeded for just a few items, I only show it with >5 items.

Limitations:

  • it's just JS without AJAX, so can only find things shown
  • it expect the items in rows in a table

It can be easily included, I just didn't think it fit other sites.

You need an input field with the quickfilter-id:

<input type="text" id="quickfilter" placeholder="filter list..." style="display: none">

Mark the table with the items with the class filterlist. The above input-field is hidden by default (display: none), but the code will display it once the list more than five items.

The JS-code is included either in C-Code with:

style_quickfilter();
or in HTML with:
<script>%s(builtin_text("quickfilter.js"))</script>

What do you think?

(2) By Florian Balmer (florian.balmer) on 2025-03-26 18:54:31 in reply to 1 [link] [source]

To me, this looks like "bells and whistles" that don't add new value.

The web browser's search function is available by hotkey Ctrl+F and highlights the matched text, so I think it's a faster and visually easier way to jump between page elements.

(3) By Jörgen Kosche (jkosche) on 2025-03-26 19:12:05 in reply to 2 [link] [source]

I like the browsers CTRL+F. This filter adds a bit more value to me, as it shrinks down the list visibly, which makes it much easier to visually comprehend it. At least in my opinion.

(4) By Florian Balmer (florian.balmer) on 2025-03-27 06:04:57 in reply to 3 [link] [source]

This filter adds a bit more value to me, as it shrinks down the list ...

This may work if you (and all your users) are disciplined enough to add keywords to the ticket title, possibly surrounded by some specific delimiters than can be added to the filter input to simulate some kind of keyword search.

But I don't see how this would be of any help with the Fossil of SQLite ticket lists with their "random" ticket titles.

Also, the search box showing up only if there's more than 5 items may be confusing (as changing UI may always be confusing), and it's of no help with a task like "review and fix all tickets on a certain subject", as once there's less than a total of 5 tickets in the list, the filter doesn't work, any more.

Plus, I really don't see any use to filter the repository list. And, using the filter, the repolist table is resized according to the visible contents (or only the column headers if nothing is matched), and I think resizing and jumping UI elements are a very bad experience!

Overall, I think this just adds clutter to the UI.

(5) By Jörgen Kosche (jkosche) on 2025-03-30 13:58:33 in reply to 4 [link] [source]

I think we generally disagree on the usefulness of the feature. That is fine. I understand your point about clutter.

So I changed the code that it is now opt-in. On ticket reports you have to activate it on each report by editing the report. On the repolist it is enabled with the FOSSIL_REPOLIST_QUICKFILTER environment variable. It is off by default in each case.

As we disagree about the usefulness others might as well, so giving them the option to decide on a case-by-case basis seems prudent.

(6) By Florian Balmer (florian.balmer) on 2025-03-30 19:42:52 in reply to 5 [link] [source]

For that matter, I also disagree strongly about adding even more options and environment variables (aka "feature creep" causing "maintenance burden") for something without a striking usability gain and not actively supported by more user votes and the project leaders.

I don't think everything has to land on trunk, and quite a few of my favorite features, which I think are indispensable, have been rejected, and that's okay, so they remain in my private Fossil build.

But I'm not one of the project leaders ...

(7) By Jörgen Kosche (jkosche) on 2025-03-30 20:47:19 in reply to 6 [link] [source]

I haven't put it up for merging to trunk yet, so far I asked for feedback which you gave me. Thank you for that.

If this is vetoed for inclusion I am fine with using it in my own personal build. Still I want to improve it as much as possible.

(8) By Stephan Beal (stephan) on 2025-03-31 14:12:32 in reply to 6 [link] [source]

... not actively supported by more user votes and the project leaders.

FWIW, Richard responded favorably to it in chat last week (/chat message #22191), and it seems like a useful feature to me.

(9) By Florian Balmer (florian.balmer) on 2025-03-31 15:15:54 in reply to 8 [link] [source]

That's fine!

I just responded to "what do you think?" and summarized the various aspects why I don't like it (to me, the benefit still seems more than questionable, and the changing/jumping UI is a no-go), without knowing this has already been waved through.

(10) By DB (ACB) on 2025-04-02 07:35:36 in reply to 1 [link] [source]

First, I am generally not a fan of JavaScript, especially since it's overused where HTML and CSS already can do the job.

But I really like this. I built src:a6ac88cbb00 and thought it was great. I've not yet built the latest, however. But that you did the first part in ~ 8 hours1 is far better than I could do! ;-)

In fact I wanted to use it on the /timeline to figure out which commit added the (nice) change to strip CR's from committed files, and was disappointed I couldn't.

I have a repo containing files which are downloaded from the Internet and sometimes some of them have those needless CRs in them. I was surprised one day when my commit script wanted to add a bunch of *-original files to them and was hoping I could quickly narrow it down.

The downside with using built-in browser searching on the page is it's not the most user-friendly by causing the page to jump around a lot.

But narrowing down row items of a long list is definitely beneficial client side behavior. I'm sure Phil and his clients would want it, when it comes to having over 1,000 repos!

So my only nit-pick is the naming is kind of generic, and brand sounding. "quickfilter" is a tiny bit vague. I've not yet thought up a replacement, but something to do with client side, tables, and JS would be where I would head.

Thank you Jörgen.


  1. ^ tl;dr "...eight hours passed between the fossil branch new operation and the first fossil commit on the branch" is pointed out.

(11) By pjm (PhilMaker) on 2025-04-02 22:37:21 in reply to 10 [link] [source]

G'day,

Quickfilter seems to be a very useful addition, the repos in our system are named using a hyphen separated list of keywords similarly to some document control systems. For example device-wtg-enercon-e30 so I'd certainly vote for quickfilter going into trunk.

Perhaps it would be worthwhile to add the project-description and maybe hide login-groups if they aren't used. Searching thru the project-description would be worthwhile and even reordering things so its:

project-name - project-description - fossil file - login groups

I'll write the changes up shortly, but any initial thoughts/observations.

(12) By Jörgen Kosche (jkosche) on 2025-04-03 11:58:49 in reply to 11 [link] [source]

Thanks for the feedback. Yeah, the project names you show seem very searchable and if you indeed have >1000 repositories I can think that a filter might be helpful.

I added the description to the repolist. Without any reordering and not dropping the login-group. Having the description might indeed be improving the value of the quickfilter, as it searches everything that is there in the table, but not more. Displaying this additional information can make it much more useful.

I did add it on a different branch though: repolist-description. Even though it can improve the quickfilter, it is basically a different thing.

Also to consider: descriptions can be much longer than the title. This is not inherently bad and my repolists actually had already some projects with longer descriptions, and the list does not broken. Using a repo as default style can help with the presentation though (repolist-skin setting). I have to think about if adding the description should be changed a bit, but the commit is there at least, you can build it if you want to test it out.

(13) By Jörgen Kosche (jkosche) on 2025-04-03 12:05:29 in reply to 10 [link] [source]

I've not yet built the latest, however.

Since then I made it opt-in. On the ticket reports you have a new checkbox to activate the quickfilter for that report. On the repolist use the environment-variable FOSSIL_REPOLIST_QUICKFILTER (can be set in the CGI script with setenv: FOSSIL_REPOLIST_QUICKFILTER on).

I probably want to make a few more adjustments, but we will see.

But that you did the first part in ~ 8 hours is far better than I could do!

Well, I prototyped it in a HTML-file with inline Javascript to check how it works. That I still needed 8 hours after creating the branch is because I was surprised by fossils use of Content Security Policy (which is a good thing). I needed some time to figure out what happened here and how it was made in other areas fossil uses Javascript.

So my only nit-pick is the naming is kind of generic, and brand sounding. "quickfilter" is a tiny bit vague.

If you come up with a better name, let me know.

(14) By Stephan Beal (stephan) on 2025-04-03 12:26:54 in reply to 12 [link] [source]

... if you indeed have >1000 repositories I can think that a filter might be helpful.

FWIW, if someone has 1000 repos in repolist mode then "they're doing it wrong."

When fossil serves a repolist it has to sqlite3_open() every single repository and pull some data from them, so every single hit on that repolist opens and queries 1000 databases.

For large repolists, a statically-generated list is the way to go, plus it gives the user full control over the layout, page title, repo ordering/grouping, JavaScript, etc. Here's an example for my own projects - that's generated from a bash script.

0.02€ and all that.

(15) By pjm (PhilMaker) on 2025-04-03 21:29:58 in reply to 14 [link] [source]

Stephan,

The static generation thing we use for various documents, typically running them markdown for things like KeyWordInContext and information based on our conventions. We typically don't do any JavaScript but as you say it work well.

But still I think the quickfilter list seems to be workable when pushed to ridiculous levels, e.g. for 1000+ repos it takes around 3.6s and since the page is cached this feels fast enough.

The static generators we are using also do things like a Situation Report across all local repos showing tickets, changes, extras, licenses etc via markdown. As you say stephan thats the right way.

(16) By Jörgen Kosche (jkosche) on 2025-04-04 19:40:47 in reply to 1 [link] [source]

I added the functionality, that the found matches will be highlighted.

(17) By DB (ACB) on 2025-04-24 21:12:31 in reply to 16 [link] [source]

Another addition I like!

Unfortunately this isn't in trunk yet and I've not gotten around to patching it in each time I build fossil, but the only thing I'd say I missed was an X button at the far right of the input field. In order to clear out the contents.

Regarding the variable name...I've peered into fossil's /src on occasion and it's clear there are a number of naming conventions. I looked at the Fossil Developer How-To, and specifically Coding Style. However, when I searched for a document or section on variable naming conventions, I didn't find one.

It's very possible I'm making too much out of this, but I was thinking perhaps there was a convention to put "ux" or "ui" on the variable name to indicate it was specific to the GUI.

I didn't mean to detract from your work.

(18) By DB (ACB) on 2025-04-24 21:47:03 in reply to 6 [link] [source]

I hope you haven't given up on the Word-wrap for web UI diffs branch, it's been awhile since it was synced with trunk.

Now that I know a bit more, and have created a bunch of wiki pages, it sure would come in handy since extremely long lines are difficult to compare.

Hopefully I can build it soon and try it out, and revisit the thread to see what people said.

(19) By Jörgen Kosche (jkosche) on 2025-04-25 00:09:08 in reply to 17 [link] [source]

Another addition I like!

Thanks.

Unfortunately this isn't in trunk yet

Yes, sorry for that. I am a bit reluctant because of the pushback the feature got. And now with the th1-taint I didn't wanted to butt in, as that is a big change of high importance. So I don't want to distract with the quickfilter.

But I should ask if people want to merge it, so I should make a thread about that soon.

the only thing I'd say I missed was an X button at the far right of the input field. In order to clear out the contents.

I changed input-type to search, which adds this behaviour on chromium-based browsers. Sadly not on firefox though.

Regarding the variable name...

Do you refer to the environment variable to enable it for the repolist? I was naming it similar to FOSSIL_REPOLIST_TITLE, which now is also accompinied by FOSSIL_REPOLIST_SHOW. See env opts

(20) By DB (ACB) on 2025-04-25 23:27:59 in reply to 19 [link] [source]

I changed input-type to search,

Very good.

Regarding the variable name...

Do you refer to the environment variable to enable it for the repolist?

No.

I was naming it similar to FOSSIL_REPOLIST_TITLE, which now is also accompanied by FOSSIL_REPOLIST_SHOW. See env opts

Yes, clearly the naming there fits.

I was reading the code. At first I thought there may be an existing convention for variable names targeting the GUI. That was mainly to avoid a possible naming conflict if drh or someone else came up with a feature more internal to fossil where "quickfilter" seemed appropriate. But as a user-facing description of the feature, I think it's very good.

After reading the quickfilter.js file I got a tiny confused for a moment because I read the code before the comments, then thought about replacing all the 'list' parts with 'rows' since that's what's being filtered. i.e. filterlist becomes filterrows. But I think I was probably being too picky.

You're right, the placeholder text using the word "list" is more appropriate than "rows" I think, since from a user's perspective, they're not seeing the HTML of the page, and even though it's technically a <table> it's still also a list of <tr>'s.

This is where I stopped before I decided I was taking too much liberty with your work and perhaps ignorantly stomping on things. I didn't touch any of the other files.

Index: src/quickfilter.js
==================================================================
--- src/quickfilter.js
+++ src/quickfilter.js
@@ -1,21 +1,20 @@
-/* Javascript code that will enable quick filtering of items in tables.
+/* Javascript code to enable quick filtering of rows in HTML tables.
 **
 ** Add an input field with the id 'quickfilter' as follows:
 **   <input type="text" id="quickfilter" placeholder="filter list...">
-** Mark the table with the filter items with the class 'filterlist'.
-** The table is expected to have a tbody around the rows that are
-** filtered (to avoid filtering the header).
+** Mark the table to filter with the class 'filterrows'.
+** Only rows within the table's tbody are filtered. 
 **
 ** The user can type to filter the table for elements matching the typed text.
 */
 
 quickfilter.addEventListener('input', function(){
   const quickfilter = document.getElementById('quickfilter');
-  const filterlist = document.querySelectorAll('.filterlist tbody tr');
+  const filterrows = document.querySelectorAll('.filterrows tbody tr');
   const filter = quickfilter.value.toLowerCase().trim();
-  for(row of filterlist){
+  for(row of filterrows){
     const orig = row.innerHTML;
     const cleaned = orig.replaceAll("<mark>", "").replaceAll("</mark>", "");
     if(filter===''){
       row.innerHTML = cleaned;
       row.style.display = 'table-row';

I still don't know enough about how things have reached their current state, so please take what I say with a grain of salt. :-)

The only other thing I can imagine people asking about someday, is their desire to filter more than one <table> on the page, each with its own criterion. ;-) But that would have to be on a modified fossil since I don't yet know of any pages with multiple tables.

(21) By Jörgen Kosche (jkosche) on 2025-04-26 09:43:48 in reply to 20 [link] [source]

I was reading the code. At first I thought there may be an existing convention for variable names targeting the GUI. That was mainly to avoid a possible naming conflict if drh or someone else came up with a feature more internal to fossil where "quickfilter" seemed appropriate. But as a user-facing description of the feature, I think it's very good.

After reading the quickfilter.js file I got a tiny confused for a moment because I read the code before the comments, then thought about replacing all the 'list' parts with 'rows' since that's what's being filtered. i.e. filterlist becomes filterrows. But I think I was probably being too picky.

Ah, I see.

Well, I have no authority on how naming conventions are in fossil, I am new at hacking away here. So someone with more seniority or authority could tell us about the appropriate naming.

I thought for a moment we could take sorttable.js as reference, but there the variable is for the tbody and named accordingly and the rows are only selected in the loop. I prefer foreach loops, as I think they make the intent more clear, but that is personal preference. Looking at sorttable, the naming seems to lean more on the HTML structure. Again my personal style would be more about the concepts, which is why I probably chose list over rows. But filterrows is an actual good name: the plural indicates that it is a list and the row part indicates what it is about. I think about it for a moment, but I might use that name change.

Again, if someone with more familiarity with the conventions of the projects wants to chime in, please do so.

(22.1) By Stephan Beal (stephan) on 2025-04-29 09:16:53 edited from 22.0 in reply to 21 [link] [source]

Well, I have no authority on how naming conventions are in fossil... Again, if someone with more familiarity with the conventions of the projects wants to chime in, please do so.

In the C code we have what amounts to set conventions, but in the JS code... We don't really have any, especially for "mini-features" which have a tiny scope, like the JS which handles clicking of two points in the timeline to /vdiff those two versions. Most of the larger-scope JS code, e.g. /wikiedit and /pikchrshow, were authored by me so definitely have my fingerprints all over them in terms of their structure and style, but we're really not generally picky about style in the JS code.

There's a rarely-spoken implicit rule in most FOSS work: "the one who writes the code decides how it's written."

I prefer foreach loops, as I think they make the intent more clear, but that is personal preference.

Much of the older JS code, like sorttable.js, was written in a "pre-HTML5 style." Back then, niceties like for-of and document.querySelector() weren't available, and nobody's felt the need to go modernize them because, as a many-year housemate of mine liked to put it, "it's doing it's thingie!" meaning "if it ain't broke, don't fix it."1 Feel free to do so, though :).

All that said: with the exception of fossil pages which are very specifically JS applications2 we try to ensure that fossil doesn't need JS to function, but we don't shy away from using it to provide quality-of-life improvements.


  1. ^ That was primarily her justification for never running upgrades on any of her devices.
  2. ^ /wikiedit, /fileedit, /pikchrshow, /chat, and (if i can ever find the energy to do it) the /forum!

(23) By anonymous on 2025-04-30 12:50:18 in reply to 21 [link] [source]

I use the following one line, it cover 90% of my need (but it has its small problem).

<input type="search" placeholder="quick search" 
onchange="[...document.querySelectorAll('table')].map(e=> [...e.tBodies[0].rows]).flat().forEach( e=> e.hidden = value.split(' ').every(v => e.textContent.includes(v)))"
>

(24.1) By DB (ACB) on 2025-05-03 03:45:11 edited from 24.0 in reply to 21 [source]

Jörgen, I continue to be glad for this contribution/branch.1 Please forgive me if I sounded offensive or superior, it wasn't my intention.

Thanks to drh for merging trunk into your branch to keep it up to date.

If I may be so bold as to update my adjustments.

  • Used "filterable" as the CSS class name since "sortable" is the class designating the table as capable of being sorted. i.e. <table class='sortable filterable'>, i.e. match the conjugation in use. What a CSS author/troubleshooter/hacker is more likely to expect.
  • Traded in another variable name which I think will make it much easier for non-JS programmers to learn from, extend, and contribute to your code.
  • A few more tweaks in the comment section.

I don't know much about JavaScript naming conventions, I write mostly shell scripts.

Hi Stephan,

There's a rarely-spoken implicit rule in most FOSS work: "the one who writes the code decides how it's written."

I respect this. I mean no offense. I feel confident Jörgen speaks and writes more languages than I do. :-)

I'm someone who would like to read and write JS some day, but who knows HTML/CSS, and also thinks about the high school students I taught in a computer lab way back when.

Jörgen, I thank you for your thoughtful consideration of what I wrote and being amenable to it. I think my changes would help a person dealing with the HTML/CSS files and a person with that level of knowledge looking at fossil's code to see how it works. This is me on both counts, just trying to make it more approachable to people like me, even those less knowledgable.

I looked at the last line in the comment and thought about wrapping greater-than and less-than signs around table, but the line is already 80 chars, so... In fact I struggled to rewrite it to give it more context, but it turned out to be on the verbose side, so didn't include it. As with any of my suggestions, you are welcome to use them, modify them, or disregard them. :-)2

Index: src/quickfilter.js
==================================================================
--- src/quickfilter.js
+++ src/quickfilter.js
@@ -1,21 +1,21 @@
-/* Javascript code that will enable quick filtering of items in tables.
+/* JavaScript code to enable quick filtering of rows in HTML <tables>.
+**
+**  * Add an <input> field with the id 'quickfilter' as follows:
+**      <input type="text" id="quickfilter" placeholder="filter list...">
+**  * Mark the <table> to filter with the class 'filterable'.
 **
-** Add an input field with the id 'quickfilter' as follows:
-**   <input type="text" id="quickfilter" placeholder="filter list...">
-** Mark the table with the filter items with the class 'filterlist'.
-** The table is expected to have a tbody around the rows that are
-** filtered (to avoid filtering the header).
+** Only rows within the <table>'s <tbody> are filtered.
 **
 ** The user can type to filter the table for elements matching the typed text.
 */
 
 quickfilter.addEventListener('input', function(){
   const quickfilter = document.getElementById('quickfilter');
-  const filterlist = document.querySelectorAll('.filterlist tbody tr');
+  const rowsToFilter = document.querySelectorAll('.filterable tbody tr');
   const filter = quickfilter.value.toLowerCase().trim();
-  for(row of filterlist){
+  for(row of rowsToFilter){
     const orig = row.innerHTML;
     const cleaned = orig.replaceAll("<mark>", "").replaceAll("</mark>", "");
     if(filter===''){
       row.innerHTML = cleaned;
       row.style.display = 'table-row';


  1. ^ I use it as my fossil ui but also tend to run the latest version as fossil server.
  2. ^
    • +** On the webpage, as text is entered in the quickfilter <input> field,
    • +** <table> rows not containing the text are hidden,
    • +** while the matched text is highlighted for visibility.

(25) By Jörgen Kosche (jkosche) on 2025-05-10 18:20:26 in reply to 24.1 [link] [source]

Sorry for the late reaction. I was preoccupied elsewhere. I took your suggestion to call the css-class to mark tables as filterable, as you correctly pointed out it is sortable for sorttable.js. I did use your previous suggestion for the variable name though (filterrows).