Overriding the browser's "find in page" keyboard shortcut

Hi, I’m a fan of Discourse, from a small community that is talking about migrating from vBulletin5. One person was opposed to Discourse because “Hijacking Ctrl+f is evil” and after seeing what they meant, I have to agree. There is a serious usability issue with how Discourse currently handles Ctrl+f, which is the browser’s shortcut for “Find text within this page”.

The problem

  • Some of the time, Ctrl+f works as it should and Discourse uses the browser’s builtin find function so that the page scrolls to the first hit immediately as you type. Ctrl+G takes you to the next hit.
    • Life is good.
  • Some of the time Ctrl+f doesn’t work and instead shows a list of results from a database search.
    • It does not scroll the page to the first hit as the user types.
    • The search phrase is only highlighted if it happens to be on the screen already.
    • It does not allow searching for terms that are too short, such as “UX”.
    • It does not accept Ctrl+g to show the next hit.
    • It does show results for irrelevant topics that Ctrl+f would not have shown if it couldn’t find the term on the page.
  • Why this breaks is completely invisible to the users, but it is extremely frustrating. They feel the ability to search within a page has been taken away with no explanation.
  • It does not help to tell them that hitting Ctrl+f twice will do a browser search as that would fail to find posts that actually exist.

The root cause

This is not a cosmetic issue, but a fundamental usability problem that Discourse will need to fix at the root: the illusion that an entire conversation is actually in the browser’s DOM, when instead it is loaded dynamically.

When there are more than twenty posts in a topic, Discourse sends posts to the browser only as needed. You could view a thread of over a 1000 posts with almost no load on the server because most of the DOM is just empty stubs. That’s a brilliant idea, but it’s also what causes Ctrl+f to mysteriously break.

I’m not suggesting getting rid of the illusion, as I think it is worthwhile. Discourse was right to jettison the old way of splitting up conversations into arbitrary pages with 40 or so posts each.

Discourse just needs to do better at making the illusion seamless.

Solutions

To be honest, I don’t know the best solution to this, but I have some thoughts that I hope will be helpful.

Knowingly breaking the illusion

First, here are some simple ideas that are reasonable if Discourse is going to break the illusion by switching to a database search,

  1. Let the user know what’s going on. Put a little note where the browser’s find box would normally appear with an apology and explanation.
  • “We’re sorry, but this topic has 1002 posts in it, but your browser only has 7 of them loaded so Find in Page probably won’t work. If you want to try anyway, hit Ctrl+f again.”
  1. Let the user have some control. When a user hits Ctrl+f, show a button so that users can manually load the text from all of topic’s posts into the DOM.
  • If that is deemed impossible due to the limit of 100 posts cached in the browser at one time, then show a button that will let user’s fall back to the old way of viewing topics: broken up by page.
  • “Click here to view this topic in a way which works with Ctrl+f: [Page 1] [2] [3] [4] [5] [6] [7] [8] [9] […] [>>]”
  1. Increase the default cutoff from 20 posts to 100 posts. This might not be too difficult to change as Discourse is already able to cache that many posts in the DOM.

Repairing the illusion

Of course, those ideas are ugly and I think of them as only stop gaps. Eventually, the best solution would be for Discourse to implement Ctrl+f in a way that works the way people expect. Replicating in Discourse what the browser does for interactively searching would be very much worth it, but I imagine it would be difficult.

However, but there might be a (relatively) simple solution.

Do not prune text from the DOM

I believe the best solution for Discourse is to only remove media objects from the posts, not text. Then, there would be no need to “hijack ctrl+f” and replace it with a database search.

Find in Page only searches for text, so there is no need for the browser to have the entire DOM loaded to be able to search it. Text is incredibly lightweight to send, especially if the HTTP server has gzip compression turned on. Text also does not take up much memory in a web browser.

You all will know this better than me, but I have some guesses:

  • Average post size: 5 KiB of text
  • Average topic length: 50 replies.
  • Average text to transfer: 250 KiB which seems reasonable.

Of course, every byte matters for responsiveness. If my estimates are off and the size of the text is an issue, filling in the DOM with text could be done as a background process after the important parts of the page have been sent. If the DOM hasn’t been completely populated with text at the point when the user hits Ctrl+f, a meter can appear, letting the user know to wait and showing the progress as the text trickles in.

Thank you

While it is a serious problem that ctrl+f breaks the illusion Discourse creates, I’m impressed with the amazing work the Discourse devs did in creating that illusion in the first place. I am confident they will eventually find the right fix for this, too.

Thank you for taking the time to consider my suggestions.

Sincerely,

Mx. F.N.

2 Likes

I share your sense that the UX is frustrating here and surprising here. Similar for me is the awkwardness of trying to scroll up and down in a simple 30 topic thread. It’s the one thing about Discourse that embarrasses me.

I do wonder if the balance between good ux in small-medium threads vs not breaking in large threads is quite right. In my project, very large threads are unlikely to be all that much of an issue so it’s frustrating to have ux undermined by their needs.

I remember reading that the real issue constraining the current approach was rendering time on Android. If that’s the case, it seems a shame to hobble all devices based on the limitations of some.

I’d love to know if it’s reasonably possible for a developer to customise:
(1) number of topics per chunk (e.g. vary per device)
(2) keeping already rendered topics visible, rather than the current unloading of them (which makes scrolling back to top clunky)

I appreciate this is a really complex area with no good solutions that a lot of toil has already gone into.

1 Like