A few sneak peeks into Hey.com technology (IV - Turbolinks frames continued)
Tags: rails, ruby, webdev, javascript
Published: 2020-06-21 12:09:12

> _**Update as of Dec 2020**: now that the Hey support code has been extracted and officially released under the name **[Hotwire](https://hotwire.dev/)**, we know that this article actually speaks about the **[Turbo Frames](https://turbo.hotwire.dev/handbook/frames)**. Basecamp renamed and polished a few things but the principles stay the same as described here._

In the [previous post](https://dev.to/borama/a-few-sneak-peeks-into-hey-com-technology-iii-turbolinks-frames-5e4a), I looked into the new feature of Turbolinks - the Frames. We saw that they allow you to download any page area content automatically from the server with a separate async request upon main page load.

But that’s not all! Often it is convenient to load a page area from the server not right after the main content loads, but some time later, **when the user requests it**. It’s all the **menus, submenus, popup windows, overlays, alerts and more** we’re talking about here! There are usually many of them on a typical site with users to log in and get their job done… The distinct quality of these elements is that **they are not needed often**, that’s why they are hidden from the main content view in the first place! And Turbolinks frames allow the browser to be unaware of them until specifically requested by the user.

> Again, this is usually a good thing as it can **greatly lighten and speed up your pages**. Why load all the stuff that you need just once a day? On the other hand, I think this approach makes your users **more dependent on a stable network connection**. I guess this might be a part of the problem with the Hey web that its _offline_ experience is not particularly great (however, note that the mobile app works offline nicely, we’re talking about the _web_ here). AFAIK, the Hey team is looking into this matter so we’ll see what they come with later on…

### Loading page parts interactively

Hey.com uses this technique quite heavily, let’s take a look at the contact page, for example: the main menu, my profile menu, the action to edit the contact name as well as the settings buttons underneath, all these elements are (re-)loaded freshly from the server when I click on them:

![Turbolinks frames on contacts page](https://dev-to-uploads.s3.amazonaws.com/i/a4tylkbawgabr6bmimow.png)

In the Network developer tool it looks like this (note that the requests were not simultaneous but sequential, as I clicked on the elements, one after another):

![Turbolinks frames on contacts page - Network](https://dev-to-uploads.s3.amazonaws.com/i/bue89aq8cppiyhhpirxs.png)

All responses to these requests are pure HTML and note that all of them are cached as I’ve already visited them a few minutes ago.

How does this work? In the [previous post](https://dev.to/borama/a-few-sneak-peeks-into-hey-com-technology-iii-turbolinks-frames-5e4a) we learned that these updates are handled by the **new Turbolinks custom element called `turbolinks-frame`**. It watches its `src` attribute for changes and when such change occurs, it visits the `src` URL via AJAX and replaces its own content with the server response.

So, all we have to do, is **alter the given element’s `src` attribute** somehow to update the corresponding part of the web page. There are many ways to do it but all the usual ones are dependent on JS code (if you use Stimulus, you can e.g. find and update the element in a Stimulus controller).

Nice, but does the new Turbolinks provide a way to do the same without having to write any JavaScript at all? Well, **of course it does!** Let’s take a look at the main menu in Hey, for example. 

When we reload the page to have it fresh and clean and use the Page inspector Element picker tool in Dev tools to show what’s inside the HEY logo, we’ll see something like this:

![Main Hey menu in Dev tools](https://dev-to-uploads.s3.amazonaws.com/i/8o7qu371z1np4w96gb9b.png)

So, again, we have the `turbolinks-frame` custom element here but this time it’s not empty, it contains a link. And this link has a `data-turbolinks-frame` attribute with the value equal to the HTML id of the Turbolinks frame element. This must mean something!

If we search through the JS sources for `"data-turbolinks-frame"`, we’ll find, among other results, the `shouldInterceptNavigation` in the `FrameController` class that supports the frame element. This method returns `true` if it finds a `data-turbolinks-frame` attribute in the link and tells Turbolinks whether it should leave the link up to normal Turbolinks processing (i.e. visit the URL) or intercept it and handle differently (i.e. trigger update of that page part).

If the frame element decides to intercept the click event, the code eventually gets to the `linkClickIntercepted` method, which **just updates the `src` attribute of the frame element**:

![linkClickIntercepted method](https://dev-to-uploads.s3.amazonaws.com/i/ahayupl39643jk0wruft.png)

As we’ve seen before, this change is noticed by the browser and leads to an AJAX call to the server followed by an update of the frame element’s content with the response.

Once the Hey main menu frame element is loaded, it is much more complex than before and it gets linked to a few Stimulus controllers that further define it’s behavior − open up the popup menu, activate live search, etc…

![Main Hey menu](https://dev-to-uploads.s3.amazonaws.com/i/hapkculv7n27reo51bv6.png)

### Summary and notes

I’m pretty sure that most of what we talked about here, is a too low-level stuff, that you won’t need to deal with at all once they release the new Turbolinks. The Basecamp / Hey team will **definitely come with some nice helpers / DSL** that will make this pattern a breeze.

Also, clicking links for sure is not the only way to trigger the updates. I’ve seen in the source code that Turbolinks supports also forms associated with frame elements, so a form submit can trigger a partial page update, again without needing custom JS. But of course, as we said, it can be easily triggered from JS code, too.

Overall, it seems to me that the Turbolinks frames feature is a **successor of the [Rails UJS library](https://github.com/rails/rails-ujs)**, that, among other things, allowed to issue an AJAX request triggered by an interactive event and [process the result somehow](https://dev.to/nejremeslnici/migrating-from-jquery-ujs-to-rails-ujs-k9m#watch-out-for-proper-ajax-data-type), without needing much JS code. 

However the new Turbolinks frames are both more radical (normally they expect only HTML on the wire) and more opinionated (they simply replace the frame element content with the response). This alone, I guess, will cover most of the partial page update use cases, while still not touching _any_ custom JS code! And if you need something more complex, you can always “sprinkle” your HTML with Stimulus attributes and put that JS code into controllers.

_Next, we’ll take a short peek into some new syntactic sugar in the Stimulus controllers, stay tuned!_