Skip to content

Commit

Permalink
Event passing examples. New disable/enable calls.
Browse files Browse the repository at this point in the history
  • Loading branch information
gnat committed Feb 5, 2024
1 parent 5546f06 commit a6fea83
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 33 deletions.
23 changes: 15 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Or, 🌐 use the CDN: `<script src="https://cdn.jsdelivr.net/gh/gnat/surreal/sur
* Can be any of:
* CSS selector: `".button"`, `"#header"`, `"h1"`, `"body > .block"`
* Variables: `body`, `e`, `some_element`
* Events: `event.target` will be used.
* Events: `event.currentTarget` will be used.
* Surreal selectors: `me()`,`any()`
* Adding a `start=` parameter provides a starting DOM location to select from. Default is `document`
* ▶️ `any('button', start='header').classAdd('red')`
Expand Down Expand Up @@ -129,17 +129,18 @@ See: [Quick Start](#quick-start) and [Reference](#reference) and [No Surreal Nee
<script>
// Every second animate something new.
me().on("click", async ev => {
me(ev).styles({ "transition": "background 1s" })
let el = me(ev) // Save target because async will lose it.
me(el).styles({ "transition": "background 1s" })
await sleep(1000)
me(ev).styles({ "background": "red" })
me(el).styles({ "background": "red" })
await sleep(1000)
me(ev).styles({ "background": "green" })
me(el).styles({ "background": "green" })
await sleep(1000)
me(ev).styles({ "background": "blue" })
me(el).styles({ "background": "blue" })
await sleep(1000)
me(ev).styles({ "background": "none" })
me(el).styles({ "background": "none" })
await sleep(1000)
me(ev).remove()
me(el).remove()
})
</script>
</div>
Expand Down Expand Up @@ -230,6 +231,12 @@ Looking for stuff [we recommend doing in vanilla JS](#no-surreal)?
* Wraps `removeEventListener`
* 🔗 `offAll`
* ▶️ `me().offAll()`
* 🔗 `disable`
* ▶️ `me().disable()`
* Easy alternative to `off()`. Disables click, key, submit events.
* 🔗 `enable`
* ▶️ `me().enable()`
* Opposite of `disable()`
* 🌐 `sleep`
* ▶️ `await sleep(1000, ev => { alert(ev) })`
* `async` version of `setTimeout`
Expand Down Expand Up @@ -318,7 +325,7 @@ Append / Prepend elements.

## 🔎 Technical FAQ
* Can I locally scope functions to `<script>` ?
* Recommended: Scope inside an event.
* Recommended: Scope inside an event.
* `me().on('click', ev => { /* add and call function here */ })`
* Alternative: Use `<script type="module">`
* Tradeoff: `me()` will no longer see `parentElement` so, an explicit selector is required: `me(".mybutton")`
Expand Down
62 changes: 52 additions & 10 deletions example.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
<title>Quick and Dirty Testing for Surreal</title>
<!-- ... or add as inline <script> ! -->
<script src="https://cdn.jsdelivr.net/gh/gnat/surreal/surreal.js"></script>
<link rel="stylesheet" href="tests/reset.css?11" /> <!-- NOTE: You can remove "?11" it is only for cache-busting on github. -->
<link rel="stylesheet" href="tests/reset.css?12" /> <!-- NOTE: You can remove "?11" it is only for cache-busting on github. -->
<meta http-equiv="cache-control" content="no-cache" />
</head>
<body>
<!-- Basic examples -->
<button>👁️ Click me to fade out and remove.
<script>
me().on("click", ev => { me(ev).fadeOut() })
Expand All @@ -28,8 +29,10 @@
any(".yeet.noot").classAdd('.active')
</script>
</div>
<!-- Basic async examples -->
<div id="random">I should turn grey after 2 seconds.
<script>
// Basic usage with id. Runs immediately.
(async ()=>{
me("#random").classAdd('active')
await sleep(2000)
Expand All @@ -41,21 +44,23 @@
<script>
// Now you're thinking with events!
me().on("ping", async ev => {
me(ev).styles({"background":"hotpink", "color":"purple"})
await sleep(2000)
me(ev).trigger("pong")
let el = me(ev)
me(el).styles({"background":"hotpink", "color":"purple"})
await sleep(1000)
me(el).trigger("pong")
})
me().on("pong", async ev => {
me(ev).styles({"background":"blue", "color":"#002200"})
await sleep(2000)
me(ev).trigger("ping")
let el = me(ev)
me(el).styles({"background":"blue", "color":"#002200"})
await sleep(1000)
me(el).trigger("ping")
})
me().styles({"transition":"all 2s"}).trigger("pong")
</script>
</div>
<div>I should be animated using timeline / async until finished!
<script>
// Now you're thinking with async!
// Now you're thinking with async! Runs immediately.
(async (el = me()) => {
me(el).styles({"transition": "all 2s"})
me(el).styles({"background":"#0030F7", "color":"#002200"})
Expand All @@ -67,6 +72,7 @@
me(el).styles({"background":"#00C08C", "color":"#660033"})
await sleep(2000)

// New element!
var el_new = createElement("div")
me(el_new).styles({"transition":"all 2s", "opacity":"0", "height":"0%"})
el_new.innerText = "🔥🔥🔥🔥🔥🔥"
Expand All @@ -78,9 +84,9 @@
</div>
<div>I should be surrounded by diamonds after a few seconds.
<script>
// Now you're thinking with async!
// Now you're thinking with async! Runs immediately.
(async (el = me()) => {
me(el).styles({"transition":"all 2s", "color":"#ccc"})
me(el).styles({"transition":"all 2s", "color":"#fff"})

var el_new = createElement("div")
el_new.innerText = "💎💎💎"
Expand All @@ -99,5 +105,41 @@
})()
</script>
</div>
<!-- Event examples -->
<div thick>📬 I close instantly from a child button event.
<script>
me().on("close", (ev) => { me(ev).remove() }) // Recieve "close" event.
</script>
<button class="close">✉️ Send "close"
<script>
me().on("click", (ev) => { me(ev).disabled = true; me(ev).trigger("close") })
</script>
</button>
</div>
<div thick>📭 I stay open because of <strong>stopPropagation()</strong>
<script>
me().on("close", (ev) => { me(ev).remove() }) // I will never recieve "close" event because of stopPropagation()
</script>
<div thick>📬 I close dramatically from a child button <strong>async</strong> event
<script>
me().on("close", async (ev) => {
ev.stopPropagation() // Event stops here.
let el = me(ev) // Save because event currentTarget will be lost after await
me(el).styles({"transition":"all 1s", "background":"green"})
await sleep(1000)
me(el).styles({"background":"orange"})
await sleep(1000)
me(el).styles({"opacity":"0"})
await sleep(1000)
me(el).remove()
})
</script>
<button class="close">✉️ Send "close"
<script>
me().on("click", ev => { me(ev).disable(); me(ev).trigger("close"); }) // Use disable() to stop clicking more than once.
</script>
</button>
</div>
</div>
</body>
</html>
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "surreal",
"version": "1.0.1",
"version": "1.0.2",
"description": "Surreal",
"repository": {
"type": "git",
Expand Down
34 changes: 25 additions & 9 deletions surreal.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Welcome to Surreal 1.0.1
// Welcome to Surreal 1.0.2
// Documentation: https://github.com/gnat/surreal
// Locality of Behavior (LoB): https://htmx.org/essays/locality-of-behaviour/
var $ = { // You can use a different name than "$", but you must change the reference in any plugins you use!
Expand All @@ -8,7 +8,7 @@ var $ = { // You can use a different name than "$", but you must change the refe
// Table of contents and convenient call chaining sugar. For a familiar "jQuery like" syntax. 🙂
// Check before adding new: https://youmightnotneedjquery.com/
sugar(e) {
if (e == null) { console.warn(`Cannot use "${e}". Missing a character?`) }
if (e == null) { console.warn(`Surreal: Cannot use "${e}". Missing a character?`) }

// General
e.run = (value) => { return $.run(e, value) }
Expand All @@ -28,6 +28,8 @@ var $ = { // You can use a different name than "$", but you must change the refe
e.off = (name, fn) => { return $.off(e, name, fn) }
e.offAll = (name) => { return $.offAll(e, name) }
e.off_all = e.offAll
e.disable = (name) => { return $.disable(e) }
e.enable = (name) => { return $.enable(e) }
e.trigger = (name) => { return $.trigger(e, name) }
e.halt = () => { return $.halt(e) }

Expand All @@ -54,7 +56,7 @@ var $ = { // You can use a different name than "$", but you must change the refe
// </div>
me(selector=null, start=document, warning=true) {
if (selector == null) return $.sugar(start.currentScript.parentElement) // Just local me() in <script>
if (selector instanceof Event) return $.me(selector.currentTarget) // Events return event.currentTarget
if (selector instanceof Event) return selector.currentTarget ? $.me(selector.currentTarget) : (console.warn(`Surreal: Event currentTarget is null. Please save your element because async will lose it`), null) // Events try currentTarget
if (typeof selector == 'string' && isSelector(selector, start, warning)) return $.sugar(start.querySelector(selector)) // String selector.
if ($.isNodeList(selector)) return $.me(selector[0]) // If we got a list, just take the first element.
if ($.isNode(selector)) return $.sugar(selector) // Valid element.
Expand All @@ -66,7 +68,7 @@ var $ = { // You can use a different name than "$", but you must change the refe
// Example: any('button')
any(selector, start=document, warning=true) {
if (selector == null) return $.sugar([start.currentScript.parentElement]) // Just local me() in <script>
if (selector instanceof Event) return $.any(selector.currentTarget) // Events return event.currentTarget
if (selector instanceof Event) return selector.currentTarget ? $.any(selector.currentTarget) : (console.warn(`Surreal: Event currentTarget is null. Please save your element because async will lose it`), null) // Events try currentTarget
if (typeof selector == 'string' && isSelector(selector, start, true, warning)) return $.sugar(Array.from(start.querySelectorAll(selector))) // String selector.
if ($.isNode(selector)) return $.sugar([selector]) // Single element. Convert to Array.
if ($.isNodeList(selector)) return $.sugar(Array.from(selector)) // Valid NodeList or Array.
Expand Down Expand Up @@ -152,7 +154,21 @@ var $ = { // You can use a different name than "$", but you must change the refe

offAll(e) {
if ($.isNodeList(e)) e.forEach(_ => { offAll(_) })
if ($.isNode(e)) e = e.cloneNode(true)
if ($.isNode(e)) e.parentNode.replaceChild(e.cloneNode(true), e)
return e
},

// Easy alternative to off(). Disables click, key, submit events.
disable(e) {
if ($.isNodeList(e)) e.forEach(_ => { disable(_) })
if ($.isNode(e)) e.disabled = true
return e
},

// For reversing disable()
enable(e) {
if ($.isNodeList(e)) e.forEach(_ => { enable(_) })
if ($.isNode(e)) e.disabled = false
return e
},

Expand Down Expand Up @@ -210,7 +226,7 @@ var $ = { // You can use a different name than "$", but you must change the refe

// Puts Surreal functions except for "restricted" in global scope.
globalsAdd() {
console.log(`Surreal: adding convenience globals to window`)
console.log(`Surreal: Adding convenience globals to window.`)
restricted = ['$', 'sugar']
for (const [key, value] of Object.entries(this)) {
if (!restricted.includes(key)) window[key] != 'undefined' ? window[key] = value : console.warn(`Surreal: "${key}()" already exists on window. Skipping to prevent overwrite.`)
Expand All @@ -231,11 +247,11 @@ var $ = { // You can use a different name than "$", but you must change the refe
// ⚙️ Used internally by DOM functions. Warning when selector is invalid. Likely missing a "#" or "."
isSelector(selector="", start=document, all=false, warning=true) {
if (all && start.querySelectorAll(selector) == null) {
if (warning) console.warn(`"${selector}" was not found. Missing a character? (. #)`)
if (warning) console.warn(`Surreal: "${selector}" was not found. Missing a character? (. #)`)
return false
}
if (start.querySelector(selector) == null) {
if (warning) console.warn(`"${selector}" was not found. Missing a character? (. #)`)
if (warning) console.warn(`Surreal: "${selector}" was not found. Missing a character? (. #)`)
return false
}
return true // Valid.
Expand Down Expand Up @@ -285,7 +301,7 @@ $.sugars['fade_out', 'fade_in'] = $.sugars['fadeOut', 'fadeIn']

$.globalsAdd() // Full convenience.

console.log("Loaded Surreal.")
console.log("Surreal: Loaded.")

// 🌐 Optional global helpers.
const createElement = document.createElement.bind(document)
Expand Down
25 changes: 20 additions & 5 deletions tests/reset.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ html {
body {
font-size: 2rem;
padding: 1rem;
background: #222;
color: #CCC;
background: #adadad;
color: #ccc;
}
.active {
background: hsl(345deg 100% 47%);
Expand All @@ -37,14 +37,24 @@ body > div {
padding: 1rem;
border-radius: 1rem;
}
body div[thick] {
color: #222;
margin: 2rem;
padding: 3rem;
border-radius: 1rem;
background: #eee;
}
body div[thick] div[thick] {
background: #ccc;
}
button {
cursor: pointer;
color: #fff;
padding: 2rem 3rem;
margin: 2rem;
border: none;
background: hsl(345deg 100% 47%);
border-bottom: 0.5rem solid hsl(345deg 100% 28%);
background: hsl(262deg 86% 47%);
border-bottom: 0.5rem solid hsl(262deg 86% 28%);
border-radius: 12px;
text-shadow: 0 2px #222222AA;
}
Expand All @@ -56,9 +66,14 @@ button.blue {
border: none;
border-bottom: 0.5rem solid hsl(200deg 100% 28%);
}

button.invisible {
opacity: 0.2;
background: hsl(147, 60%, 50%);
border-bottom: 0.5rem solid hsl(147 80% 28%);
}
button.close {
background: hsl(345deg 90% 40%);
border-bottom: 0.5rem solid hsl(345deg 100% 28%);
border-radius: 12px;
}

0 comments on commit a6fea83

Please sign in to comment.