Created
April 15, 2023 13:05
-
-
Save bennadel/1b9f65d5b5eb44f29cf56d980c0c35db to your computer and use it in GitHub Desktop.
Revisions
-
bennadel created this gist
Apr 15, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,44 @@ <cfmodule template="./tags/page.cfm"> <cfoutput> <!--- Parent controller. ---> <form data-controller="form"> <!--- The textarea controller has methods for manipulating the text value in low-level ways so that the complexity of text manipulation doesn't have to leak up and out into the form itself. This also increases the ability to reuse the text formatting practices in different places. ---> <textarea data-controller="textarea" data-form-target="textarea" ></textarea> <!--- These buttons ask the FORM to apply different formatting styles (which will turn around and ask the textarea controller to apply the formatting). ---> <button type="button" data-action="form##applyFormatting" data-form-command-param="bold"> Bold </button> <button type="button" data-action="form##applyFormatting" data-form-command-param="italic"> Italic </button> <button type="button" data-action="form##applyFormatting" data-form-command-param="strikethrough"> Strike-Through </button> </form> </cfoutput> </cfmodule> This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,101 @@ // Import core modules. import { Application } from "@hotwired/stimulus"; import { Controller } from "@hotwired/stimulus"; // ----------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------- // export class FormController extends Controller { static targets = [ "textarea" ]; // --- // PUBLIC METHODS. // --- /** * I apply the given formatting command event to the nested textarea. */ applyFormatting( event ) { this.application // Stimulus gives us the ability to extract a Controller instance from a given // element. However, since a given element can have any number of controllers // attached to it, we have to provide an IDENTIFIER that tells Stimulus which // controller to extract. In this case, we're looking for the one with the // "textarea" identifier. I'm OK with the tight-coupling here because we are // explicitly deferring work to another controller. .getControllerForElementAndIdentifier( this.textareaTarget, "textarea" ) // Then, once we have the controller instance, we can invoke methods on it // like we would with any other JavaScript object. .formatSelection( event.params.command ) ; } } export class TextareaController extends Controller { /** * I apply the given style command to the currently-selected text. */ formatSelection( style ) { switch ( style ) { case "bold": this.wrapSelection( "**" ); break; case "italic": this.wrapSelection( "_" ); break; case "strikethrough": this.wrapSelection( "~~" ); break; default: throw( new Error( `Unsupported text format: ${ style }` ) ); break; } } // --- // PRIVATE METHODS. // --- /** * I wrap the current selection in the given prefix/suffix markers. */ wrapSelection( prefix, suffix = prefix ) { var value = this.element.value; var start = this.element.selectionStart; var end = this.element.selectionEnd; var wrappedValue = ( value.slice( 0, start ) + prefix + value.slice( start, end ) + suffix + value.slice( end ) ); this.element.value = wrappedValue; this.element.selectionStart = ( start + prefix.length ); this.element.selectionEnd = ( end + prefix.length ); this.element.focus(); } } // ----------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------- // 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( "form", FormController ); Stimulus.register( "textarea", TextareaController );