Skip to main content
Ben Nadel at CFUNITED 2010 (Landsdown, VA) with: Ryan Jeffords and Doug Boude
Ben Nadel at CFUNITED 2010 (Landsdown, VA) with: Ryan Jeffords ( @ryanjeffords ) Doug Boude ( @dougboude )

Exploring The Turbo Drive Navigation Progress Bar In Lucee CFML

By on

When you enable Turbo Drive in a Hotwire application, Turbo Drive intercepts native link clicks and form submissions and then re-implements them using the browser's fetch() API. If a fetch() call takes longer than 500ms to complete (a configurable default), Hotwire will render a progress bar at the top of the window. The progress bar is a simple <div> element that can be lightly styled using CSS. I just wanted to take a quick look at how the progress bar works in a ColdFusion application.

View this code in my ColdFusion + Hotwire Demos project on GitHub.

To test Hotwire's progress bar functionality, I created a small ColdFusion application with three pages:

  • index.cfm - loads instantly.
  • products.cfm - sleeps between 1-5 seconds before rendering.
  • about.cfm - sleeps 25-seconds before rendering.

These pages - and their embedded sleep() commands - give me enough time to look at the DOM (Document Object Model) while the progress bar is being rendered. Here's my about.cfm page, which does the most sleeping:

<cfscript>

	sleep( 25000 ); // 25-seconds.

</cfscript>
<cfmodule template="./tags/page.cfm">
	<cfoutput>

		<h1>
			ColdFusion + Hotwire Navigation Progress Bar Demo
		</h1>

		<p>
			<a href="index.htm">Home</a> -
			<a href="products.htm">Products</a> -
			<a href="about.htm"><strong>About</strong></a>
		</p>

		<!--- ... truncated, filler copy ... --->

	</cfoutput>
</cfmodule>

The sleep( 25000 ) function call is the only thing of note in this template - the rest of the template is just navigation links and filler copy. And, if I load this app and then navigate to the about.cfm page, we get the following page output:

As you can see, the Turbo Drive progress bar is implemented as an empty div element with position: fixed. It's injected in between the <head> and <body> tags. And, to be honest, I didn't even know that you could put DOM content in between those two elements. I'm sure that works to side-step display and z-index issues that might occur if placed inside the body tag.

ASIDE: Turbo Drive is using a z-index of 2,147,483,647. This is the largest value that can fit inside a 32-bit signed integer. According to this post by Tan Li Hau, the CSS specification doesn't mention any limit on z-index; however, the z-index value is often stored as a 32-bit signed integer, making the Turbo Drive z-index value the highest possible value.

The .turbo-progress-bar CSS class definition is defined in a <style> tag that is prepended to the <head> tag as the first child. This means, from a cascading and specificity standpoint, overriding the progress bar style is extremely easy. All you have to do is define your own .turbo-progress-bar property block. For example, I changed the background to pink:

.turbo-progress-bar {
	background-color: #ec005a ;
}

And, when I re-render the page and navigate to about.cfm, I get pink!

The Turbo Drive progress bar rendered as pink.

Hotwire's Turbo Drive feels like such an elegant drop-in solution to progressively enhance a ColdFusion application. I love all this attention to detail that the Basecamp team put into this stuff.

Turbo Drive Cancels Irrelevant fetch() Calls

Unrelated to the Turbo Drive progress bar functionality, I noticed something interesting as I was playing around with slow-loading pages: pending navigation fetch() calls are aborted if the user initiates a new navigation. For example, if I load this ColdFusion application and then click the About section a few times before it has a chance to load, here's what we see in the Chrome Dev Tools Network activity:

Network tab showing two fetch calls being canceled and a third one still pending.

As you can see, the two prior navigation calls have been aborted, leaving only the most recent navigation still in progress. The ColdFusion requests are almost certainly still being processed on the server-side; but, at least this approach reduces the number of open network connections on the client-side. Again, lots of great attention to detail in the Hotwire framework.

Want to use code from this post? Check out the license.

Reader Comments

Post A Comment — I'd Love To Hear From You!

Post a Comment

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel