tl;dr - To speed up loading a large HTML table on the client, start with the table CSS set to display: none;.
Once the document is ready, set it back to display: table;.
This reduced my client-side render time from 60 seconds to 6 seconds on a table with ~400,000 cells.
For those unfamiliar with the meeting, it’s an annual gathering of Free/Libre software projects and artists.
There’s an amazing community of users, developers, and hackers that attend every year to talk about all sorts of cool topics like fonts, photography, painting, performance, and many other things that start with the letter “p” (printing? pontificating? pixls?).
The “pixls” is a bit of a joke, but in reality I’m cautiously optimistic that we’ll get a chance to assemble quite a few pixls.us nerds there.
Friends from both darktable, RawTherapee, and many more actually live in or near Saarbrücken and I am super excited to see them!
Wanting to help the organizers, out I took a stab at designing a website for them.
They use Wordpress for the site, so I had to figure out theming in Wordpress, but I had some fun doing it.
In the end they didn’t use what I cooked up, but I personally really liked it.
Rather than let it languish in obscurity, I figured I would at least share it here:
I made some decent progress on the overall design before I realized it wasn’t going to be used, so there’s still some rough edges that needed to be finished.
I also generated a static version of the site I had setup on my host (no need for yet another Wordpress site hanging around the internet).
This is one of those cases where I kind of liked the overall course the design was taking and will keep it in mind to cannibalize for future projects.
Being a part of a community of smart folks means that inevitably there will be personality clashes.
I was reminded of this recently, and found myself needing to remember to be empathetic.
darix was kind enough to link me this wonderful post from Jeff Bigler over twenty years ago that is still quite relevant today:
All people have a “tact filter”, which applies tact in one direction to everything that passes through it. Most “normal people” have the tact filter positioned to apply tact in the outgoing direction. Thus whatever normal people say gets the appropriate amount of tact applied to it before they say it. This is because when they were growing up, their parents continually drilled into their heads statements like, “If you can’t say something nice, don’t say anything at all!”
“Nerds,” on the other hand, have their tact filter positioned to apply tact in the incoming direction. Thus, whatever anyone says to them gets the appropriate amount of tact added when they hear it. This is because when nerds were growing up, they continually got picked on, and their parents continually drilled into their heads statements like, “They’re just saying those mean things because they’re jealous. They don’t really mean it.”
When normal people talk to each other, both people usually apply the appropriate amount of tact to everything they say, and no one’s feelings get hurt. When nerds talk to each other, both people usually apply the appropriate amount of tact to everything they hear, and no one’s feelings get hurt. However, when normal people talk to nerds, the nerds often get frustrated because the normal people seem to be dodging the real issues and not saying what they really mean. Worse yet, when nerds talk to normal people, the normal people’s feelings often get hurt because the nerds don’t apply tact, assuming the normal person will take their blunt statements and apply whatever tact is necessary.
So, nerds need to understand that normal people have to apply tact to everything they say; they become really uncomfortable if they can’t do this. Normal people need to understand that despite the fact that nerds are usually tactless, things they say are almost never meant personally and shouldn’t be taken that way. Both types of people need to be extra patient when dealing with someone whose tact filter is backwards relative to their own.
Unless you know me well personally, you may not realize that I’m a nerd for ghost stories.
That particular topic is for another time, though.
This post is to celebrate the spooky season with one of my favorite ghost stories, Smee by A.M. Burrage.
Set during a Christmas Eve, it’s a delightful look at an innocent game of hide-and-seek called “Smee” (a portmanteau of “It’s” and “Me”) that includes an unexpected player for the evening.
As with the best short ghost stories, the supernatural is casual and softly haunting; not as vulgar jump scares or “gotcha!” moments of cheap thrills. (The best of this post-facto type of uneasiness is likely Afterward by Edith Wharton.)
With deference to Dieter Rams (and courtesy of Vitsoe), his 10 principles for good design.
This list is worth revisiting every now and then.
Good design is innovative
The possibilities for innovation are not, by any means, exhausted. Technological development is always offering new opportunities for innovative design. But innovative design always develops in tandem with innovative technology, and can never be an end in itself.
Good design makes a product useful
A product is bought to be used. It has to satisfy not only functional, but also psychological and aesthetic criteria. Good design emphasizes the usefulness of a product whilst disregarding anything that could detract from it.
Good design is aesthetic
The aesthetic quality of a product is integral to its usefulness because products we use every day affect our person and our well-being. But only well-executed objects can be beautiful.
Good design makes a product understandable
It clarifies the product’s structure. Better still, it can make the product talk. At best, it is self-explanatory.
Good design is unobtrusive
Products fulfilling a purpose are like tools. They are neither decorative objects nor works of art. Their design should therefore be both neutral and restrained, to leave room for the user’s self-expression.
Good design is honest
It does not make a product more innovative, powerful or valuable than it really is. It does not attempt to manipulate the consumer with promises that cannot be kept.
Good design is long-lasting
It avoids being fashionable and therefore never appears antiquated. Unlike fashionable design, it lasts many years – even in today’s throwaway society.
Good design is thorough down to the last detail
Nothing must be arbitrary or left to chance. Care and accuracy in the design process show respect towards the user.
Good design is environmentally-friendly
Design makes an important contribution to the preservation of the environment. It conserves resources and minimizes physical and visual pollution throughout the lifecycle of the product.
Good design is as little design as possible
Less, but better – because it concentrates on the essential aspects, and the products are not burdened with non-essentials.
Much to the chagrin of my friend darix, I run an Ubuntu server at home for various things like Nextcloud and Plex.
(Chagrin because it’s not openSUSE… yet.)
I had installed the previous Long Term Support (LTS) version, 16.04 because I just need the thing to run and be solid.
The time had come for a new LTS release and I figured I might as well sit down and get upgraded to 18.04.
Mostly you hear from people when things go wrong, and this time I thought it’d be nice to say something from a positive view.
I upgraded over SSH and everything went super smoothly. Awesome!
There was one small hiccup with SSH not being enabled when I rebooted the first time but it was quickly sorted out.
The funnier part was some weird news updates being shown in my Message of the Day (motd) when I logged into the machine.
(update: user @Qwxlea@tuxspace.net on Mastodon found this LWN article about it by Jake Edge back in 2017.)
I think I’ve seen a few people calling them “ads”, but really what happens is the motd scripts pull news from a URL to show you. Here’s what mine looked like:
Welcome to Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-32-generic x86_64)
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 913G 745G 122G 86% /
* Read about Ubuntu updates for L1 Terminal Fault Vulnerabilities
* Check out 6 great IDEs now available on Ubuntu. There may even be
something worthwhile there for those crazy EMACS fans ;)
* Canonical Livepatch is available for installation.
- Reduce system reboots and improve kernel security. Activate at:
0 packages can be updated.
0 updates are security updates.
The issue some folks have is with the first couple of bullet points (and a bit.ly link? Really?).
Taking a look in /etc/update-motd.d/50-motd-news and right at the top of the file Dustin was kind enough to tell us he insisted on transparency for this:
# This program could be rewritten in C or Golang for faster performance.
# Or it could be rewritten in Python or another higher level language
# for more modularity.
# However, I've insisted on shell here for transparency!
# - Dustin
Remove the News
Also at the top of that file is the clue on fixing this for your installation.
The key is to modify the file /etc/default/motd-news and change ENABLED=1 to ENABLED=0:
# Enable/disable the dynamic MOTD news service
# This is a useful way to provide dynamic, informative
# information pertinent to the users and administrators
# of the local system
I was outlining some ideas for an article I want to write concerning online privacy and connections to the recent Facebook fiasco.
Part of the outline had me talking about the “middleman” layer that many big services like Facebook and Google created through their free offerings like ads, webfonts, comments, and social sharing options.
I started mentioning this in a post from last year.
I won’t go into that detail here (yet), but something that really struck home for me was the use of Google Analytics.
For those not in the know, Google Analytics is a way to track users on a website for reporting and insights.
We used to do this manually by analyzing the logs from the webserver.
It can even show this data in real time. Which is, as my friend Alex Prokoudine points out: “just jerking off” (*at least for small projects like this blog).
What this really boils down to is (and I’ll cover this in more depth in the article I alluded to): I’ve given Google direct access to all of my users and their browsing habits on my site.
It’s insidious because it’s dead-simple to set up, and it gives you a nice little jolt of satisfaction watching your traffic flowing in (trickling, in my case).
This is not exactly news to many, but I figured it might be for a few people.
If it helps raise awareness in even one person of what’s really going on then I’d say this post has done its job.
I’d rather not give Google a hand tracking users across the entire web.
There is a Free Software option for user analytics that we use over on PIXLS.US called Matomo (previously, Piwik) that I will continue to use here.
This means that I control all of the data and don’t allow any middleman to see what you’re up to (well, me and one of the pixls sysadmins, andabata, who runs the service for us).
I will also start manually analyzing my server logs offline when I need more accurate statistics to look at.
Stay tuned for something a little more in-depth where I ramble on more about tracking and the sneaky middle layer of snooping that these services have built up in the name of convenience and apathy.
I got the bug recently to finally do something that’s been annoying me for some time: set up a dark theme for this website that is user selectable and that will persist.
Normally I prefer the white background (default) that I originally designed but I understand that some prefer a dark background.
When it’s in the evening and I want to write/edit a new post (like I’m doing right now) so do I.
When it’s daytime, though, I prefer to be back on the white background.
The Dark (Style)
Creating a dark version of the site is relatively easy.
I originally styled things sparingly here to keep it light and simple.
With plenty of thanks to past-Pat for being proactive there aren’t many rules to change to make a dark theme work.
Here they are:
That’s pretty much it.
I set the body background-color and color to dark versions (the hr:after is for the new horizontal rules I added a few days ago).
The headings are slightly brighter than the body text (just like how they’re slightly darker in the light theme) and the code blocks use a darker background.
The link text colors were tweaked from looking at the Solarized color scheme by Ethan Schoonover so they were already on the path to being used in either light or dark versions and didn’t need modification.
I went with a more neutral dark gray background vs. the slightly blue-tinted Solarized background because I didn’t want the background to clash with any photos I share.
Applying the Styles
The application of these styles was pretty straightforward.
I had all of the main styles for the site load first (in the document <head>), where I set the dark theme as part of my default styles.
Immediately after these default styles, I added a new <style> element that actually set the colors to the light theme version.
The pseudo code for my styles now looks like this:
As an aside, while looking around at others works to see if I was missing something, I came across an awesome method for creating a dark version of a website.
It’s in the blog post A Theme Switcher over on the Inclusive Components site and it’s an elegant use of the invert filter.
The post is well worth a read, but the general gist is to use the invert filter to invert all of the colors on a site.
They explicitly give a background color to the :root html element, and then trickle it down to all other elements on the page through the * selector (so you don’t end up with white text on a white background).
A little selector magic to avoid images and videos and you have a very tersely implemented theme inversion!
I attach an event listener to a link on the page (see the “Theme” button in my header).
Targeting the lightcss style element, we can toggle it through the disabled attribute.
This might seem odd if you’ve done this before.
Normally you’d probably consider setting the dark/light rules and applying them to a class.
Then you’d toggle them by adding/removing the classes.
While this works great, it tends to be slightly problematic when used for applying stored user preferences…
The Persistence of Memory
This allows me to remember what theme the user wants.
This could be done with cookies as well but many folks might have them turned off for security reasons.
This helps get around the problem of using a class to switch styles.
If the setting is for the dark theme, it needs to be applied before the page has a chance to load (and show a flash of the white theme).
Using the disabled attribute we can set (well, unset) these styles before the page has a chance to render.
Give It a Try
That was a mouthful.
Well, go ahead and give it a try if you’d like!
In my header under my name and main site links you should now find a “THEME” link that will swap things around for you. Let me know if anything seems wonky.
This post is a little more esoteric, but in the spirit of helping others from the future we’re gonna dive into this.
I picked up an Amazon Kindle Paperwhite over a year ago, and I have been tearing through books at an alarming rate.
In the course of finding more books to read I did what I’ve always done for as long as I can remember: visit my local library.
Side note: Please, please, please support your local libraries. It’s like supporting net-neutrality in meatspace!
I immediately ran into a bit of a disconnect between my rapidly advancing digital life and the reality of digital books.
The problem lies in how we can borrow and checkout digital books. Currently, there are mainly two big systems in place for digital library lending, Bibliotheca’s CloudLibrary and Rakuten Overdrive.
As is often the case in modern computing, anything not Apple or Microsoft is relegated to the rubbish bin.
As a Linux user, this is not ideal for me.
Neither of these software solutions have a Linux option.
Wine Is Not an Emulator
Luckily for Linux users, there’s the project to run Windows applications on various POSIX-compliant operating systems: Wine.
I won’t go into using CloudLibrary, as it’s not the focus of this post.
It actually installs just fine all on it’s own in Wine so it’s a non-issue.
Overdrive is the real problem here. Rather, it’s use of Adobe Digital Editions (ADE) as the means for checking out books. (The actual interface for Overdrive at the library is a website.) For other purposes that I won’t go into here right now, I need to be able to use an older version of ADE. Specifically ADE 2.0.1.
I spent some time researching if the application would work over at the App Database for Wine.
The instructions there didn’t really work for me, but there were some other posts in places like the MobileRead wiki where I was able to gain some more insights as well.
Overall it took a good few hours of searching and playing to finally arrive at a working installation of ADE 2.0.1 with Wine on Linux.
If you’re still reading this far I can only assume that you need to get this installed as well. Let’s do it!
I have successfully installed ADE 2.0.1 on a fresh installation of Ubuntu 18.04.
You’ll need to be comfortable in your shell to do this, no graphical installer for these steps (sorry).
To start, you’ll need a couple of downloads for later:
I just downloaded these directly into my home directory for easy reference later.
You’ll also need to install Wine. I just went ahead and used the package from my distro: wine-3.0 (Ubuntu 3.0-1ubuntu1).
You’ll also want a helper script for setting things up automatically in Wine called winetricks, and I also needed cabextract to be able to extract files from a Windows .cab file.
Wine installs everything into it’s own directories that you tell it to (referred to as a prefix). You can easily tell it which prefix to use by setting this in your shell before you run a command.
In my examples below I will be installing ADE into it’s own prefix in my home directory called ~/.adewine.
Set up a new 32-bit prefix with Wine. You need to setup a fresh install into it’s own prefix, and tell Wine to make it a 32-bit environment:
$ WINEPREFIX=~/.adewine WINEARCH=win32 winecfg
You can also tell Wine to use this prefix for all subsequent commands:
$ export WINEPREFIX=~/.adewine
Now you need to install corefonts and windowscodecs: