Videos

    🎥 I’ve released a video tutorial on how to use and configure the Sidebar For Tiny Theme. This walks through the process of creating and using a custom Micro.blog theme to configure the sidebar with custom HTML. Hope others find it useful.

    Picnic train, now boarding. 🚂

    Photo Bucket Update: More On Galleries

    Spent a bit more time working on Photo Bucket this last week1, particularly around galleries. They’re progressing quite well. I’m made some strides in getting two big parts of the UI working now: adding and removing images to galleries, and re-ordering gallery items via drag and drop.

    I’ll talk about re-ordering first. This was when I had to bite the bullet and start coding up some JavaScript. Usually I’d turn to Stimulus for this but I wanted to give HTML web components a try. And so far, they’ve been working quite well.

    The gallery page is generated server-side into the following HTML:

    <main>
      <pb-draggable-imageset href="/_admin/galleries/1/items" class="image-grid">
        <pb-draggable-image position="0" item-id="7">
          <a href="/_admin/photos/3">
            <img src="/_admin/img/web/3">
          </a>
        </pb-draggable-image>
            
        <pb-draggable-image position="1" item-id="4">
          <a href="/_admin/photos/4">
            <img src="/_admin/img/web/4">
          </a>
        </pb-draggable-image>
            
        <pb-draggable-image position="2" item-id="8">
          <a href="/_admin/photos/1">
            <img src="/_admin/img/web/1">
          </a>
        </pb-draggable-image>        
      </pb-draggable-imageset>
    </main>
    

    Each <pb-draggable-image> node is a direct child of an <pb-draggable-imageset>. The idea is that the user can rearrange any of the <pb-draggable-image> elements within a single <pb-draggable-imageset> amongst themselves. Once the user has moved an image onto to another one, the image will signal its new position by firing a custom event. The containing <pb-draggable-imageset> element is listening to this event and will respond by actually repositioning the child element and sending a JSON message to the backend to perform the move in the database.

    A lot of this was based on the MDN documentation for drag and drop and it follows the examples quite closely. I did find a few interesting things though. My first attempt at this was to put it onto the <pb-draggable-image> element, but I wasn’t able to get any drop events when I did. Moving the draggable attribute onto the <a> element seemed to work. I not quite sure why this is. Surely I can’t think of any reason as to why it wouldn’t work. It may had something else, such as how I was initialising the HTTP components.

    Speaking of HTML components, there was a time where the custom component’s connectedCallback method was being called before the child <a> elements were present in the DOM. This was because I had the <script> tag in the the HTML head and configured to be evaluated during parsing. Moving it to the end of the body and loading it as a module fixed that issue. Also I found that moving elements around using element.before and element.after would actually call connectedCallback and disconnectedCallback each time, meaning that any event listeners registered within connectedCallback would need to be de-registered, otherwise events would be handled multiple times. This book-keeping was slightly annoying, but it worked.

    Finally, there was moving the items with the database. I’m not sure how best to handle this, but I have that method that seems to work. What I’m doing is tracking the position of each “gallery item” using a position field. This field would be 1 for the first item, 2 for the next, and so on for each item in the gallery. The result of fetching items would just order using this field, so as long as they’re distinct, they don’t need to be a sequence incrementing by 1, but I wanted to keep this as much as possible.

    The actual move involves two update queries. The first one will update the positions of all the items that are to shift left or right by one to “fill the gap”. The way it does this is that when an item is moved from position X to position Y, the value of position between X and Y would be changed by +1 if X > Y, or by –1 if Y > X. This is effectively the same as setting position X to X + 1, and so on, but done using one UPDATE statement. The second query just sets the position of item X to Y.

    So that’s moving gallery items. I’m not sure how confident I am with this approach, but I’ve been testing this, both manually and by writing unit tests. It’s not quite perfect yet: I’m still finding bugs (I found some while coming up with these screencasts). Hopefully, I’ll be able to get to the bottom of them soon.

    The second bit of work was to actually add and remove images in the gallery themselves. This, for the moment, is done using a “gallery picker” which is available in the image details. Clicking “Gallery” while viewing an image will show the list of galleries in the system, with toggles on the left. The galleries an image already belongs to is enabled, and the user can choose the galleries they want the image to be in by switching the toggles on and off. These translate to inserts and remove statements behind the scenes.

    The toggles are essentially just HTML and CSS, and a bulk of the code was taken from this example, with some tweaks. They look good, but I think I may need to make them slightly smaller for mouse and keyboard.

    I do see some downside with this interaction. First, it reverses the traditional idea of adding images to a gallery: instead of doing that, your selecting galleries for an image. I’m not sure if this would be confusing for others (it is modelled on how Google Photos works). Plus, there’s no real way to add images in bulk. Might be that I’ll need to add a way to select images from the “Photos” section and have a dialog like this to add or remove them all from a gallery. I think this would go far in solving both of these issues.

    So that’s where things are. Not sure what I’ll work on next, but it may actually be import and export, and the only reason for this is that I screwed up the base model and will need to make some breaking changes to the DB schema. And I want to have a version of export that’s compatible with the original schema that I can deploy to the one and only production instance of Photo Bucket so that I can port the images and captions over to the new schema. More on this in the future, I’m sure.


    1. Apparently I’m more than happy to discuss work in progress, yet when it comes to talking about something I’ve finished, I freeze up. 🤷 ↩︎

    Photo Bucket Galleries and Using the HTML Popover API

    Spent a bit more on Photo Bucket this evening. Tonight I started working on galleries, which’ll work more or less like albums.

    At the moment you can create a gallery and add a photo to it. Most of the work so far has been backend so the UI is pretty rough. Eventually you’ll be able to do things like rearrange photos within galleries, but for the moment they’ll just be added to the end.

    I did need to add some modals to the UI, such as the New Gallery model that’s shown for the gallery name. This gave me the opportunity to try out the new popover API. And yeah, it does exactly what it says on the tin: add the popover attribute to an element and it becomes a working popover (at least in the latest version of Vivaldi). Must say it’s impressive that this is now possible with HTML alone.

    The initial version of the modals used a <div> for the popover target. And while that worked, there were some small annoyances. First was that the form within the popover didn’t get focus when the popover was displayed. It would be nice to click “New” and start typing out the gallery name. But this is a small thing that’s easily solvable with JavaScript, so it’s no big deal.

    The second, slightly larger one, was that dismissing the popover by clicking outside of it will not eat the input. If you were to click a sidebar link while the New Gallery model is opened, you’ll end up on that newly selected page. I’m not a fan of this. Dismissing the popover feels like its own user gesture, and I fear the user accidentally activating things when all they’re trying to do is dismiss the popover (it’s not in place now, but I am planning to dim the background when the Create Gallery modal is visible).

    Fortunately, there’s a simple solution to this. It turns out that replacing the <div> element with a <dialog> element would solves both problems. It works seamlessly with the new popover attributes, yet showing the dialog will give focus to the form, and will eat the click when the user dismisses it.

    Perfect. Looks like I’ve delayed the need for JavaScript a little longer (it will come eventually; it always will).

    Working on one of the admin sections of the project I was alluding to yesterday. Here’s a screencast of how it’s looking so far.

    The styling and layout is not quite final. I’m focusing more on functionality, and getting layout and whitespace looking good always takes time. But compared to how it looked before I started working on it this morning, I think it’s a good start.

    In the end it took significantly more time to write about it then to actually do it, but the dot product approach seems to work.

    🎥 Elm Connections #7: Deploying

    In which I round out the series by deploying Clonections to Netlify.

    🎥 Elm Connections #6: Fetching And JSON Decoding Puzzles

    In which I use Elm’s HTTP client and JSON decoder to fetch puzzles from an external resource.

    🎥 Elm Connections #5: Option Shuffling

    In which I use Elm’s random number generator to shuffle the options.

    🎥 Elm Connections #4: Styling

    In which I put away Elm for a bit to make the playfield look good (or at least, better than it was).

    🎥 Elm Connections #3: Group Matching

    In which I work on “categories”, the model and logic that deals with the groups the player is to “connect”, plus find my way with how sets work in Elm.

    🎥 Elm Connections #2: Starting The Playfield

    In which I continue work on a Connections clone in Elm by starting work on the playfield.

    🎥 Elm Connections #1: First Steps

    In which I record video of me building a Connections (or Conlextions) clone in Elm (while at the same time, have a go at editing video).

    Making some progress in learning Elm for building frontends. Started working on a Connections clone, which I’m calling “Clonections”. This is what I’ve got so far:

    It’s been fun using Elm to build this. So far I’m liking the language. Of course, now I’ll have to come up with puzzles for this. 😐

    I realise I’ve been posting a lot about Ivy, and not a whole lot about Archie. So to even the scales a little, here’s a video of Archie receiving a head scratch this morning.

    🥛🦜

    Should state that both vessels hold ordinary tap water.

    Also got a bit of train spotting in as well. I parked at Kyneton station in the hope of seeing a train go by. Wish I could say my timing was strategic but in truth I was just lucky.

    This conversation with @Gaby got my creative juices flowing so I though I’d put together a small video tutorial for using the GLightbox plugin by @jsonbecker. There have been a few updates with the plugin so how I use it might be slightly out of date. Either way, please enjoy.

    Success! Managed to get a Go app built, signed, and notarised all from within a GitHub Action. It even cross-compiles to ARM, which is something considering that it’s using SDL. Here’s the test app being downloaded and launched in a VM (ignore the black window, the interesting part is the title).

    I won’t lie to you. I got some pretty strong vibes of the Birds at this point in my walk.

Older Posts →