Say Goodbye to 80% of Your Frontend
Transform the DOM with a simple state machine modeled in JSON and remove 80% of all the nonsense. No javascript, no libraries, no transpilers, just simple, clean, efficient code.
~1.7KB!
Add It To Your Html
<!-- Include the script -->
<script src="/static/scripts/dom-x.js"></script>
<!-- Add the custom element to the body of HTML file -->
<dom-x src="[YOUR-STATE-MACHINE-CONFIG].json"></dom-x>
Click The Stoplight
<dom-x src="stoplight.json"></dom-x>
<div id="stoplight">
<div id="stoplight__red"></div>
<div id="stoplight__yellow"></div>
<div id="stoplight__green"></div>
</div>
stoplight.json
{
// the initial state
"initialState": "red",
// attach listeners
"listeners": [["#stoplight", "click", "changeState"]],
// state definitions
"states": {
// the "red" state
"red": {
// on entry, run these "transformers"
"entry": [
// add the class "active" to the red light
["addClass", "#stoplight__red", "active"],
// remove the class "active" from the green light
["removeClass", "#stoplight__green", "active"],
// dispatch the "changeState" event in 2000ms
["dispatch", "changeState", 2000]
],
// when the "changeState" event is dispatched, change the state to "yellow"
"changeState": [["state", "yellow"]]
},
// the "yellow" state
"yellow": {
"entry": [
["addClass", "#stoplight__yellow", "active"],
["removeClass", "#stoplight__red", "active"],
["dispatch", "changeState", 2000]
],
"changeState": [["state", "green"]]
},
// the "green" state
"green": {
"entry": [
["addClass", "#stoplight__green", "active"],
["removeClass", "#stoplight__yellow", "active"],
["dispatch", "changeState", 2000]
],
"changeState": [["state", "red"]]
}
}
}
In Short:
Behavior is local (no more following wires), the state is modeled (the only thing that's actually hard), less client/server coupling (it's all backend) and it's toolable (you can write your own transformers). And in the end, it's just a lot less code and complexity.
All The Things You Can Do
// Name: Append
// Desc: Append to element
// Type: [transformer: "append", selector: string, html: string];
["append", "#list", "<li>new item</li>"],
// Name: Attr
// Desc: Set an attribute
// Type: [transformer: "attr", selector: string, attr: string, value: string];
["attr", "#dialog", "open", "true"],
// Name: Add Event Listener
// Desc: Attach an event handler to trigger an action
// Type: [transformer: "addEventListener", selector: string, event: string, stateEvent:string];
["addEventListener", "#btn", "click", "changeState"],
// Name: Dispatch
// Desc: Dispatch an action
// Type: [transformer: "dispatch", action: string, delay?: number];
["dispatch", "reset", 2000],
// Name: Get
// Desc: Trigger a get request and process the result (a transformation object)
// Type: [transformer: "get", url: string, ...args: any[]];
["get", "/some/endpoint"],
// Name: History
// Desc: Update the browser history
// Type: [transformer: "history", method: string, ...args: (string | number)[]];
["history", "pushState", {}, "Record List", "/records/list"],
// Name: Location
// Desc: Update the browser location
// Type: [transformer: "location", url:string];
["location", "/records/list"],
// Name: Post
// Desc: Post selected data to endpoint and process the result (a transformation object)
// Type: [transformer: "post", url: string, ...data: [key: string, selector: string, val: "value" | "dataset" | "formData"][]];
["post", "/some/endpoint", [
["form-data", "#todoForm", "formData"]
]],
// Name: Remove attribute
// Desc: Remove an attribute
// Type: [transformer: "removeAttribute", selector: string, attr: string];
["removeAttribute", "#dialog", "open"],
// Name: Remove class
// Desc: Remove a class
// Type: [transformer: "removeClass", selector: string, className: string];
["removeClass", "#dialog", "open"],
// Name: RemoveEventListener
// Desc: Remove an event listener
// Type: [transformer: "removeEventListener", selector: string, event: string, stateEvent: string];
["removeEventListener", "#btn", "click", "changeState"],
// Name: Replace
// Desc: Replace an element
// Type: [transformer: "replace", selector: string, html: string];
["replace", "#list", "<li>updated item</li>"],
// Name: SetAttribute
// Desc: Set an attribute
// Type: [transformer: "setAttribute", selector: string, attr: string, value: string];
["setAttribute", "#dialog", "open", "true"],
// Name: State
// Desc: Change current state
// Type: [transformer: "state", state: string];
["state", "processing"],
// Name: Text content
// Desc: Set the text content of an element
// Type: [transformer: "textContent", selector: string, text: string];
["textContent", "#dialog", "Processing..."],
// Name: Wait
// Desc: Add a wait between transformations
// Type: [transformer: "wait", ms: number];
["wait", 2000],
// Name: Window
// Desc: Call a method on the window object
// Type: [transformer: "win", method: string, ...args: any[]];
["window", "alert", "Hello World!"],
Couple domx with my other library, cap ui
cap ui is a set of cut and paste ui components. The state/behavior of the components are expressed via BEM css syntax which makes Domx and cap ui a match made in heaven.
©Copyright 2024 All rights reserved. Made in the USA 🇺🇸 by Kevin Lint as a product of Lint Trap Media.