Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created April 10, 2023 12:25
Show Gist options
  • Save bennadel/84da1c22818a3b866b7a134d14013a03 to your computer and use it in GitHub Desktop.
Save bennadel/84da1c22818a3b866b7a134d14013a03 to your computer and use it in GitHub Desktop.
Listen For Stimulus Custom Events Outside Of Hotwire
<cfscript>
emojis = [
{
name: "Grinning Face",
hex: "1F600"
},
{
name: "Heart",
hex: "2764 FE0F"
},
{
name: "Fire",
hex: "1F525"
}
];
</cfscript>
<cfmodule template="./tags/page.cfm">
<cfoutput>
<div id="myDiv">
<p>
<input id="myInput" type="text" autofocus />
</p>
<p>
<cfloop item="emoji" array="#emojis#">
<button
data-controller="emoji"
data-action="emoji##emitEmoji"
data-hex="#encodeForHtmlAttribute( emoji.hex )#">
#encodeForHtml( emoji.name )#
</button>
</cfloop>
</p>
</div>
<!--- LEGACY LOGIC. --->
<script type="text/javascript">
// Even though our Emoji controller is a Stimulus controller, the events that
// it emits are still native DOM (Document Object Model) events. Which means,
// we can create "bridge" code that glues our legacy logic and our Hotwire
// logic together as we migrate a legacy application. In this case, I'm going
// to listen for the custom event, "emoji" (from the "emoji" controller), and
// then use it to insert the desired emoji into the input using the following
// legacy logic.
myDiv.addEventListener(
"emoji:emoji",
( event ) => {
console.group( "Emoji Event" );
console.log( "Glyph:", event.detail.emoji );
console.log( "Hex:", event.detail.hex );
console.log( "Codepoints:", event.detail.codepoints );
console.groupEnd();
// Legacy logic to insert emoji in input.
var insertAt = myInput.selectionEnd;
var nextSelectionAt = ( insertAt + event.detail.emoji.length );
myInput.value = (
myInput.value.slice( 0, insertAt ) +
event.detail.emoji +
myInput.value.slice( insertAt )
);
myInput.focus();
myInput.selectionStart = myInput.selectionEnd = nextSelectionAt;
}
);
</script>
</cfoutput>
</cfmodule>
// Import core modules.
import { Application } from "@hotwired/stimulus";
import { Controller } from "@hotwired/stimulus";
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
export class EmojiController extends Controller {
/**
* I emit the "emoji" event for the associated hex-encoded code-points.
*/
emitEmoji( event ) {
var codepoints = event.target.dataset.hex
.split( " " )
.map(
( hex ) => {
return( parseInt( hex, 16 ) );
}
)
;
this.dispatch(
"emoji",
{
detail: {
emoji: String.fromCodePoint( ...codepoints ),
hex: event.target.dataset.hex,
codepoints: codepoints
}
}
);
}
}
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
window.Stimulus = Application.start();
// When not using the Ruby On Rails asset pipeline / build system, Stimulus doesn't know
// how to map controller classes to data-controller attributes. As such, we have to
// explicitly register the Controllers on Stimulus startup.
Stimulus.register( "emoji", EmojiController );
<button
data-controller="emoji"
data-action="emoji#emitEmoji"
data-hex="2764 FE0F">
Red Heart
</button>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment