Skip to main content
Ben Nadel at cf.Objective() 2014 (Bloomington, MN) with: Jin Park
Ben Nadel at cf.Objective() 2014 (Bloomington, MN) with: Jin Park

Disabling Turbo Drive In A Subdirectory Of Your ColdFusion Application

By on

As is the expectation, moving from theory into practice always reveals new trials and truths about a given topic. Or, as Mike Tyson put it: "Everyone has a plan until they get punched in the mouth." Migrating my ColdFusion blog over to using Hotwire is no different. I'm hitting all kinds of edge-cases that I need to adapt to; one of which is that I have loads of old demos that I've built over the years. These demos are not Hotwire compatible; and, I don't intend to update them anytime soon. As such, I needed a way to progammatically disable Turbo Drive on any link that points to one of these demos.

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

When you - as the user - perform an action within a Hotwire application, a whole host of events get fired. One of these events, turbo:click, is fired anytime a user clicks on a Turbo-Drive-eligible link. We can hook into this event and call .preventDefault() on it. This will cancel the Turbo Drive enhancement and allow the link to fall through to the browser's native default behavior.

On my blog, all of these old demos are stored in a subdirectory named, resources. This means that I can use the turbo:click event to inspect each link, look for the /resources/ path segment, and then globally prevent Hotwire from managing those links.

I'm going to add this into my main JavaScript bundle:

// Import core modules.
import * as Turbo from "@hotwired/turbo";

// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //

document.documentElement.addEventListener(
	"turbo:click",
	function handleClick( event ) {

		// For the demo, we're going to allow any URL with [force=true] to be consumed by
		// Turbo Drive, regardless of where it is pointing to.
		if ( event.detail.url.includes( "force=true" ) ) {

			return;

		}

		// As we migrate an old site over to use Hotwire Turbo Drive, there may be a whole
		// host of links that point to old pages that are NOT NOW and WILL NEVER BE
		// compatible with the Turbo Drive requirements. We can hook into the Turbo Drive
		// events and prevent Hotwire from managing these archaic links.
		if ( event.detail.url.includes( "/resources/" ) ) {

			console.group( "Detected 'Resources' Subdirectory" );
			console.log( "URL:", event.detail.url );
			console.log( "Preventing default." );
			console.groupEnd();
			// Cancel this event to let the click fall through to the browser as normal
			// link navigation.
			event.preventDefault();

		}

	}
);

For the purposes of this demo, I have a guard statement for the force=true escape hatch. But, any other link that contains the /resources/ substring is going to bypass Hotwire and be treated as a normal link.

To see this in action, I've created a ColdFusion page that links to one of these /resources/ demos. This page has two links: one with and one without the force=true override.

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

		<h2>
			About This Site
		</h2>

		<p>
			Copy copy copy....
		</p>

		<p>
			Check out this really old demo:
		</p>

		<ul>
			<li>
				<a href="resources/old-demo/index.htm?force=true">Old Demo (force)</a>
			</li>
			<li>
				<a href="resources/old-demo/index.htm">Old Demo</a>
			</li>
		</ul>

	</cfoutput>
</cfmodule>

This "old demo" does nothing but include a <style> tag in the <head>. This is an important point because Turbo Drive works, in part, by merging <head> content as you navigate around an application. Which means, the <style> tag defined in the demo will end up corrupting the rest of the Hotwire application if Turbo Drive is used to load this old demo:

<!doctype html>
<html>
<head>
	<!---
		CAUTION: Turbo Drive merges the contents of the HEAD on page navigation. If we're
		not careful, this WILL clobber the styles of the root site when the user navigates
		back to the root of the site.
	--->
	<style type="text/css">
		body {
			background-color: #212121 ;
			color: #f0f0f0 ;
		}
		a {
			color: inherit ;
		}
	</style>
</head>
<body>

	<h1>
		Really Old Demo
	</h1>

	<p>
		Copy copy copy....
	</p>

	<p>
		<a href="../../index.htm">Back to root</a>
	</p>

</body>
</html>

First, let's take a look at what happens if we navigate to the old demo using the force=true flag. This will allow Turbo Drive to manage the application visit:

Navigating to the old demo turns the background black. Then, navigating back to the main app leaves the background black.

As you can see, when we enter the old demo, the embedded <style> tag turns the screen black, which is expected. However, when we then navigate back to the main application, the black screen persists! This is because that embedded <style> tag has become a permanent part of the <head> and bleeds over to the main app.

Now, let's navigate to the old demo and allow our global turbo:click event handler to intervene:

Navigating to the old demo turns the background black. Then, navigating back to the main app turns the background back to white.

As you can see, this time our global event handler detected the /resources/ subdirectory, prevented Turbo Drive from effecting the page change, and allowed a full page refresh to take place on navigation. This keeps the /resources/ directory free from the Hotwire framework. Which, in turn, prevents the demos from corrupting the long-running process created by the Turbo Drive context.

Why Not Just Use [data-turbo="false"] On Links?

Hotwire Turbo Drive gives us a myriad ways in which to change the behavior of links within the application. You might wonder why I don't just apply the data-turbo attribute to the links that point to demos. The reason this is a non-starter is because these links are all over the place, embedded within static content as well as years of database-driven content. Instead of doing my best to find and modify all these links, I can handle the behavior modification in a single, global choke-point and know that I've taken care of the problem.

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