A Good Format (Part 1)
Added 2021-09-27 15:22:42 +0000 UTCHey all, hope you’ve been well. There’s been plenty of work that’s been completed and some that’s still not quite production-ready but, to change things up, I’m not going to give an overview at this time. Instead, I want to talk about a single specific addition. It is my hope to provide insight into the process of things and how even something that’s sensibly-planned and competently-executed can still take a lot of time.
By the time you read this, the latest wave of changes will be live on the site. What is probably going to be most noticeable for the majority of users is the addition of formatting tools in the post box. This is something that I wished to include for some time now as, for whatever reason, the internet at large remains incapable of reading instructions.
The first step in creating the new tool was figuring out the concept of what I was doing. Essentially, a series of clickable buttons that affect other input fields, preserving their data will adding formatting tags. Forums of all sorts have these and they are often either part of the (generic) software itself or a third-party solution that has been integrated. Clearly, as the effects are client-side, the best way to go would be to use Javascript; since the ready-made solutions would require not only adaptation to our strange imageboard format but also would necessitate importing libraries to run it, I figured that doing something from scratch would be better.
With the basic idea locked in, I created a simple test page locally with a textarea element and a few buttons above it. Apart from some basic styling, there wasn’t a need for any fancy visuals. The first options were the most basic: Bold, Italic, Strikethrough, Underline. As those worked in a similar way, a quick function that read their “type”, found where the cursor position was and inserted content was not much work at all.
As the W3 standard of the web is huge (over 115 million words), searching up properties of things or methods that can be applied is all but inevitable for any web dev. I found and looked up things like setRangeText (and how selectionStart works on a textarea element) and added to the complexity of that basic function by including cases where the text is selected. So now, after some time and effort, clicking on those buttons while text is selected causes the selected text to be saved, input inserted before and after it. Progress!
That might have been sorted but the question of THP’s other text-formatting features remained unsolved. Something likewise simple, like the text separator or coinflip, did not need a closing tag (eg: [/i]). So adding a parameter to the extant function gave me the ability to control the output. So far, so good, but in terms of functionality there remained a bunch of rather special cases: setting colors, rolling dice, flipping coins and inserting timers. I wished to have them all included if at all possible.
While something like a color picked can leverage the in-built browser tools, it does have its caveats. For one, it is its own type of input element and not just a “dumb” button. It does not react to the “click” event in the same way and what you want to watch out for there is the “input” event when the user selects something. So, to make things at least look consistent, the actual input is hidden and a dummy button was placed; it needs an extra instruction to cause a “click” event for the input which, in turn, calls to our now-growing insertion function when input is selected and passes on its current value.
I found that during testing that the “input” event would not always fire, depending on the browser. What was happening was that, if a new (non-default) value was not selected, it would do nothing. So I had to add an extra step, when the button that “clicks” it is pressed, that set the default color to something unlikely to be chosen. And, even though I’m getting ahead of myself a little, later on I also noticed that some browsers (mostly chromium-based) fired their input events on every click of the actual color selection area. As spamming entries into a text box was not really ideal but dropping support outright for popular browsers impractical, I had to add a little workaround that limits the event to only once every couple of seconds at most. It feels long enough that users can play around with the color wheel without it being too long as to frustrate them when there seems to be no input after clicking.
The last two things that needed to be added were the dice roll and timer buttons. They worked mostly the same, requiring user input and a message that showed users how to format things. Requiring only a single tag, they could reuse most of the other code but a new parameter was needed to our versatile function. It borrows from our color input, too, and inserts a “=” before the tag is closed. It displays short instructions when clicked, formatting things in a human-readable way and requires inputting text into a field to work properly. All easy to do, in theory, and I can’t complain it was too difficult.
I had been working incrementally. Still, because of the nature of development, code can get unwieldy fast as there’s usually a lot of debug lines that get commented out or things that are just tried out during the process that are subsequently discarded. Making things coherent and simplifying code as much as possible is pretty important. I had all these buttons that worked but I wanted the code base to be maintainable so I spent a fair amount of time optimizing and making sure that there was no superfluous code. In terms of actual lines of code, this initial prototype numbered at fewer than 50. Not bad at all.
Modern CSS has less-stupid tools that help with making sure things look good. Creating a grid to place elements was overkill, so the versatile flex property made sure that all the buttons were aligned, of similar sizes and whatnot. Every browser/OS renders buttons and input boxes in its own way and there is no real standard to speak of. You can force specific styling with much care but that road leads to madness; if you expect to have a space where users can set their own colors or be zoomed in or out on a page, things can quickly break. Less is more in this context and just specifying things like minimum widths and margins was enough.
There were other issues with the buttons themselves. Many might understand that “B” on a button might mean bold in context. Verbose descriptions when you hover over text help but cannot be counted upon—especially for mobile users. And, anyhow, how the hell do you make a “dice” or “spoiler” button with text? You could just write it out but that makes the buttons larger and would look horrible on smaller screens, likely breaking the flow of other elements. Incidentally, I hid some of the lesser-used options by default and made a button that, when clicked, shows the rest of the available tools. I think that that’s an elegant way to keep things manageable.
So I thought about having icons. Unicode has more than 120 thousand symbols now and surely some of those might be useful. There are multiple problems with that solution: 1) You might not find an unambiguously clear symbol that can be understood, 2) Not everyone may have the fonts installed to see all the many symbols, 3) Even if they do, things like emoji are rendered differently depending on the font set and device.
How do other forums handle it? Well, some just abuse CSS to place transparent images and align things just so. I automatically discarded that because it’s a pain to maintain, especially when you’re serving to other screen sizes. Custom fonts and scripts exist to “expand” unicode but this introduces the problem of bloat—depending on external libraries is something I’d prefer not to do as they slow down load times—as well as relying on premade symbols that may not fit my needs exactly.
What to do, then?
There was only one real answer to my problem. I just didn’t know where to start nor how. I’d end up making my own font and picking my own symbols to include in it. No bloat, tailor-made to THP’s needs and I wouldn’t have to depend on licenses and terms imposed by others.
Learning about that part of the process will have to wait as I think this post has gotten long and unwieldy enough. Expect a followup soon and do enjoy the new features that have been added to THP. Until next time, take it easy!
Comments
Shit, at this rate, I might not even have to write the THP Manual™️ — though it's a big presumption those who need it most would bother reading, so...
Benjamin Oist
2021-09-27 20:18:35 +0000 UTC