### Fetch API GET Request Example
Source: https://github.com/gnat/surreal/blob/main/README.md
This snippet demonstrates how to make a GET request to a '/thing' endpoint using the Fetch API and log a success message if the response is okay. It also shows how to replace the inner HTML of the clicked element with the response text.
```javascript
me().on("click", async event => {
let e = me(event)
// EXAMPLE 1: Hit /thing endpoint.
if((await fetch("/thing")).ok) console.log("Got thing.")
// EXAMPLE 2: Get /thing endpoint and replace me()
try {
let response = await fetch('/thing')
if (response.ok) e.innerHTML = await response.text()
else console.warn('fetch(): Bad response')
}
catch (error) { console.warn(`fetch(): ${error}`) }
})
```
--------------------------------
### Install Surreal.js via NPM
Source: https://github.com/gnat/surreal/blob/main/_autodocs/configuration.md
Install the Surreal.js package using npm and then import it into your JavaScript files.
```bash
npm install @geenat/surreal
```
```javascript
import surreal from '@geenat/surreal'
```
--------------------------------
### XMLHttpRequest GET Request Example
Source: https://github.com/gnat/surreal/blob/main/README.md
This snippet shows how to make a GET request to a '/thing' endpoint using XMLHttpRequest. It includes an example for simply sending the request and another for updating the inner HTML of the clicked element with the response text upon successful completion.
```javascript
me().on("click", event => {
let e = me(event)
// EXAMPLE 1: Hit /thing endpoint.
var xhr = new XMLHttpRequest()
xhr.open("GET", "/thing")
xhr.send()
// EXAMPLE 2: Get /thing endpoint and replace me()
var xhr = new XMLHttpRequest()
xhr.open("GET", "/thing")
xhr.onreadystatechange = () => {
if (xhr.readyState == 4 && xhr.status >= 200 && xhr.status < 300) e.innerHTML = xhr.responseText
}
xhr.send()
})
```
--------------------------------
### Working with Arrays Example
Source: https://github.com/gnat/surreal/blob/main/_autodocs/README.md
Shows how to apply operations and attach event listeners to multiple elements selected by `any()`.
```javascript
any('button').classAdd('ready').on('click', handleClick)
```
--------------------------------
### Convert Between Single Element and Multiple Elements
Source: https://github.com/gnat/surreal/blob/main/_autodocs/QUICK-REFERENCE.md
Shows how to use `me()` to get a single element and `any()` to get a collection of elements. Demonstrates converting a single element to an array-like collection and vice-versa.
```javascript
// Get first button
let btn = me('button')
// Convert to array
let arr = any(btn)
// Get first from array
let first = me(any('button'))
```
--------------------------------
### Basic Class Manipulation Example
Source: https://github.com/gnat/surreal/blob/main/_autodocs/README.md
Demonstrates adding, removing, and toggling CSS classes on elements using Surreal.js.
```javascript
me('button').classAdd('active')
any('.item').classRemove('hidden')
me().classToggle('expanded')
```
--------------------------------
### Event Handling Example
Source: https://github.com/gnat/surreal/blob/main/_autodocs/README.md
Shows how to attach a click event listener to a button, disable it, and fade it out upon click.
```javascript
me('button').on('click', (e) => {
let btn = me(e)
btn.disable()
btn.fadeOut()
})
```
--------------------------------
### Selecting Element with Relative Start
Source: https://github.com/gnat/surreal/blob/main/README.md
Demonstrates selecting an element using a relative start point, specified by `me(selector, parentElement)`. This is an alternative to `me('-')` for selecting elements within a specific context.
```javascript
me('[n1]', me()).value = "hello"
```
--------------------------------
### Animation Timeline Example
Source: https://github.com/gnat/surreal/blob/main/_autodocs/README.md
Demonstrates a simple asynchronous animation sequence changing an element's background color over time.
```javascript
(async (el = me('div')) => {
el.styles({ transition: 'all 0.3s' })
el.styles({ background: 'red' })
await sleep(300)
el.styles({ background: 'blue' })
})()
```
--------------------------------
### Non-Chainable Methods Example
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Shows examples of non-chainable methods like 'remove' which end the chain, and 'attribute' which returns a value and thus ends the chain.
```javascript
me('div').remove() // void - ends chain
let value = me('input').attribute('value') // string - ends chain
```
--------------------------------
### any(selector, start, warning)
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/selectors.md
Select multiple DOM elements and return them as an array. Always returns an array (empty array if nothing matches).
```APIDOC
## any(selector, start, warning)
### Description
Select multiple DOM elements and return them as an array. Always returns an array (empty array if nothing matches).
### Method
`any(selector=null, start=document, warning=true)`
### Parameters
#### Path Parameters
- **selector** (string | Event | HTMLElement | SVGElement | NodeList | Array) - Optional - CSS selector string, Event object, HTML/SVG element, or list of elements. If null, returns array containing parent of current `
```
--------------------------------
### Chaining Methods Example
Source: https://github.com/gnat/surreal/blob/main/_autodocs/README.md
Illustrates method chaining in Surreal.js to apply multiple operations (class addition and style application) to selected elements.
```javascript
me('.card')
.classAdd('active')
.styles('background: blue')
```
--------------------------------
### Inline Styles Example (String)
Source: https://github.com/gnat/surreal/blob/main/_autodocs/README.md
Applies inline CSS styles to an element using a string.
```javascript
me('div').styles('color: red; padding: 1rem')
```
--------------------------------
### me(selector, start, warning)
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/selectors.md
Select a single DOM element, guaranteed to return one element or null. If multiple elements match, returns the first one.
```APIDOC
## me(selector, start, warning)
### Description
Select a single DOM element, guaranteed to return one element or null. If multiple elements match, returns the first one.
### Method
`me(selector=null, start=document, warning=true)`
### Parameters
#### Path Parameters
- **selector** (string | Event | HTMLElement | SVGElement | NodeList | Array) - Optional - CSS selector string, Event object, HTML/SVG element, or list of elements. If null, uses the parent element of the current `
```
#### Example 2: Select element by CSS selector
```javascript
// Select first button
me('button').classAdd('primary')
// Select element by ID
me('#header').styles('background: navy')
// Select element by class
me('.active').attribute('data-status', 'ready')
```
#### Example 3: Select element before current script
```html
```
#### Example 4: Handle event with element saving
```javascript
me().on("click", ev => {
let el = me(ev) // Extract element from event
if (!el) return // Null safety
el.classToggle('active')
})
```
#### Example 5: Search within a specific start location
```javascript
let container = me('#main')
me('button', container).classAdd('main-button')
```
#### Example 6: Silent selector failure
```javascript
// No warning if "nonexistent" doesn't exist
me("#nonexistent", document, false)?.classAdd('hidden')
```
```
--------------------------------
### jQuery Style Naming Conventions
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Examples of using jQuery-style methods for class manipulation.
```javascript
me().addClass('active')
me().removeClass('hidden')
```
--------------------------------
### Chainable Methods Example
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Illustrates a sequence of chainable methods to modify an element's class, styles, attributes, and attach an event listener.
```javascript
me('div')
.classAdd('card')
.styles('padding: 1rem')
.attribute('data-id', '123')
.on('click', handleClick)
```
--------------------------------
### Timeline Animation with Async/Await
Source: https://github.com/gnat/surreal/blob/main/example.html
This example uses async/await to create a timeline animation, changing element styles over time. It also demonstrates appending and animating a new element.
```javascript
(async (e = me()) => {
// Special case where we can save element right away.
e.styles({"transition": "all 2s"})
e.styles({"background":"#0030F7", "color":"#002200"})
await sleep(2000)
e.styles({"background":"#006BFF", "color":"#000033"})
await sleep(2000)
e.styles({"background":"#00A1FF", "color":"#005500"})
await sleep(2000)
e.styles({"background":"#00C08C", "color":"#660033"})
await sleep(2000)
// New element!
var e2 = me(createElement("div"))
e2.styles({"transition":"all 2s", "opacity":"0", "height":"0%"})
e2.innerText = "🔥🔥🔥🔥🔥🔥"
e.appendChild(e2)
await sleep(1000)
e2.styles({"opacity":"1", "height":"fit-content"})
})()
```
--------------------------------
### Immediate Timeline Animation of Styles
Source: https://github.com/gnat/surreal/blob/main/README.md
This example animates an element's background color immediately upon script execution. It uses an async IIFE with `me()`, `styles()`, `sleep()`, and `remove()`.
```html
Change color every second.
```
--------------------------------
### Camel Case Naming Conventions
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Examples of using camel case methods for class manipulation and setting class names.
```javascript
me().classAdd('active')
me().classRemove('hidden')
me().className = 'card'
```
--------------------------------
### Inline Styles Example (Object)
Source: https://github.com/gnat/surreal/blob/main/_autodocs/README.md
Applies inline CSS styles to an element using a JavaScript object.
```javascript
me('div').styles({
backgroundColor: 'blue',
borderRadius: '8px'
})
```
--------------------------------
### Attribute Management
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Demonstrates how to get, set a single, or set multiple attributes on an HTML element using Surreal.js.
```javascript
// Get attribute
let value = me('input').attribute('value')
// Set single attribute
me('form').attribute('data-submitted', true)
// Set multiple attributes
me('form').attribute({
'data-type': 'contact',
'aria-label': 'Contact form',
'novalidate': true
})
```
--------------------------------
### DOM Selection Functions
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Selects a single element or the first match, or all matching elements as an array. The 'start' and 'warning' parameters are optional.
```javascript
me(selector, start, warning) // Select 1 element or first match
any(selector, start, warning) // Select all matching elements as array
```
--------------------------------
### Chained DOM Manipulation
Source: https://github.com/gnat/surreal/blob/main/README.md
Start a chain of DOM manipulation functions using `me()` or `any()`. This is the recommended style for cleaner code.
```javascript
me().classAdd('red')
```
```javascript
any("button").classAdd('red')
```
```javascript
me().on("click", ev => me(ev).fadeOut() )
```
```javascript
any('button').on('click', ev => { me(ev).styles('color: red') })
```
```javascript
any('button').run(_ => { alert(_) })
```
```javascript
me().styles('color: red')
```
```javascript
me().styles({ 'color':'red', 'background':'blue' })
```
```javascript
me().attribute('active', true)
```
--------------------------------
### Attribute Manipulation Example (Multiple)
Source: https://github.com/gnat/surreal/blob/main/_autodocs/README.md
Sets multiple attributes on an element using an object.
```javascript
me('form').attribute({
'data-id': '123',
'novalidate': true
})
```
--------------------------------
### Custom Zoom-In Effect Implementation
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/effects.md
Example of creating a custom zoom-in effect using `styles()` and `tick()`. It sets initial styles, waits for them to apply, then animates to the final state.
```javascript
// Custom zoom-in effect
(async (el = me('div')) => {
el.styles({
transition: 'all 0.3s',
transform: 'scale(0)',
opacity: '0'
})
await tick()
el.styles({
transform: 'scale(1)',
opacity: '1'
})
})()
```
--------------------------------
### Retry Logic with Exponential Backoff
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/utilities.md
Provides an example of implementing a fetch request with retry logic, using `sleep()` for exponential backoff between retries.
```javascript
async function fetchWithRetry(url, maxRetries = 3) {
let retries = 0
while (retries < maxRetries) {
try {
let response = await fetch(url)
if (response.ok) return response
} catch (e) {
retries++
await sleep(1000 * retries) // Exponential backoff
}
}
throw new Error('Max retries exceeded')
}
```
--------------------------------
### Handle Keyboard Shortcuts
Source: https://github.com/gnat/surreal/blob/main/_autodocs/QUICK-REFERENCE.md
Listens for keyboard events on the document to trigger actions based on key combinations. This example shows how to prevent the default browser save action and send a custom save event.
```javascript
me('document').on('keydown', event => {
if (event.ctrlKey && event.key === 's') {
halt(event) // Prevent default save
me('form').send('keyboard-save')
}
})
```
--------------------------------
### Fade In Element with Limit
Source: https://github.com/gnat/surreal/blob/main/example.html
This example shows how to fade in an element with a limit on the number of times the action can be performed. It uses a simple counter to enforce the limit.
```javascript
me().on("click", ev => { // Simple way to limit number of actions. if(me(ev)?.fadeInLimit <= 1) return; else { me(ev).fadeInLimit = 1; me(ev).fadeIn() } })
```
--------------------------------
### Scoping with Block Example
Source: https://github.com/gnat/surreal/blob/main/README.md
Demonstrates how to use block scoping with curly braces `{}` to limit the scope of `let` variables and `function` declarations. This helps in managing variable lifetimes and avoiding naming conflicts.
```javascript
{ let note = "hi"; function hey(text) { alert(text) }; me().on('click', ev => { hey(note) }) }
```
--------------------------------
### Scoping with me() Block Example
Source: https://github.com/gnat/surreal/blob/main/README.md
Illustrates creating a scoped function attached to a `me()` element. This allows for custom methods to be called on specific elements, enhancing reusability and organization.
```javascript
me().hey = (name) => { alert(name) }
me().on('click', (ev) => { me(ev).hey("hi") })
```
--------------------------------
### Core API Functions
Source: https://github.com/gnat/surreal/blob/main/_autodocs/README.md
Provides functions for selecting single or multiple DOM elements. Supports optional start nodes and warnings.
```javascript
me(selector, start, warning) // Select 1 element
any(selector, start, warning) // Select many elements
```
--------------------------------
### Timeline Animation: Animate Element Styles and Remove
Source: https://github.com/gnat/surreal/blob/main/README.md
This example demonstrates animating an element's background color over time and then removing it. It uses `me()`, `on()`, `styles()`, `sleep()`, and `remove()`.
```html
I change color every second.
```
--------------------------------
### Color Manipulation Plugin Example
Source: https://github.com/gnat/surreal/blob/main/_autodocs/configuration.md
This plugin adds `randomColor` and `rainbow` methods to elements for applying random or cycling colors. Use `me()` or `any()` to select elements and then call the plugin methods.
```javascript
function pluginColors(e) {
e.randomColor = function() {
const colors = ['red', 'blue', 'green', 'purple', 'orange']
const random = colors[Math.floor(Math.random() * colors.length)]
this.styles(`color: ${random}`)
return this
}
e.rainbow = function() {
let color = 0
const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
const interval = setInterval(() => {
this.styles(`color: ${colors[color]}`)
color = (color + 1) % colors.length
}, 100)
return this
}
}
surreal.plugins.push(pluginColors)
// Now use:
me('button').randomColor()
any('.text').rainbow()
```
--------------------------------
### Custom Event Listener Example
Source: https://github.com/gnat/surreal/blob/main/_autodocs/README.md
Attaches an event listener to react to a custom 'validated' event and add a class based on the event details.
```javascript
me('form').on('validated', (e) => {
if (e.detail.success) {
me(e).classAdd('success')
}
})
```
--------------------------------
### Configuration Options
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Allows adding convenience globals to the window object and registering custom plugins.
```javascript
globalsAdd() // Add convenience globals to window
surreal.plugins // Array to register custom plugins
```
--------------------------------
### Create DOM Element with Content and Event Listener
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/utilities.md
Demonstrates creating an element, setting its text content, adding attributes, and attaching an event listener.
```javascript
let button = createElement('button')
button.textContent = 'Click Me'
me(button)
.attribute('data-id', '123')
.on('click', (ev) => { alert('Clicked!') })
me('#container').appendChild(button)
```
--------------------------------
### Internal fadeOut Mechanism Example
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/effects.md
Illustrates the internal CSS transition logic used by the `fadeOut` effect, including setting styles, waiting for the tick, and applying transition properties.
```javascript
// fadeOut internally does:
styles(e, {
transform: 'scale(1)',
transition: `all ${ms}ms ease-out`,
overflow: 'hidden'
})
await tick() // Let styles apply
styles(e, {
transform: 'scale(0.9)',
opacity: '0'
})
await sleep(ms)
// Optional: remove(e)
```
--------------------------------
### Practical Attribute Manipulation Examples
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/dom-manipulation.md
Illustrates common use cases for attribute manipulation, such as updating file inputs, managing form validation states with ARIA attributes, and setting custom data attributes for tracking.
```javascript
// Update file input with dropped files
me('#file-input').attribute('files', event.dataTransfer.files)
// Form validation - set ARIA attributes
let input = me('input')
if (isInvalid) {
input.attribute('aria-invalid', true)
input.attribute('data-error', 'Required field')
} else {
input.attribute('aria-invalid', null) // Remove
input.attribute('data-error', null)
}
// Custom data attributes for tracking
me('.modal').attribute({
'data-id': modalId,
'data-opened': new Date().toISOString(),
'aria-modal': 'true'
})
```
--------------------------------
### Get and Set Element Attributes
Source: https://github.com/gnat/surreal/blob/main/README.md
Manages element attributes. Can get, set, or remove single or multiple attributes. For multiple elements, use `any(...).run(...)` or `any(...).forEach(...)`.
```javascript
me().attribute('data-x')
```
```javascript
me().attribute('data-x', true)
```
```javascript
me().attribute({ 'data-x':'yes', 'data-y':'no' })
```
```javascript
me().attribute('data-x', null)
```
```javascript
me().attribute({ 'data-x': null, 'data-y':null })
```
--------------------------------
### Configuration
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Provides options for global configuration and extending Surreal with custom plugins.
```APIDOC
## Configuration
### `globalsAdd()`
Adds convenience global functions to the `window` object, making Surreal functions directly accessible without prefix.
### `surreal.plugins`
An array where custom plugins can be registered to extend Surreal's functionality.
```
--------------------------------
### Attribute Manipulation Example (Single)
Source: https://github.com/gnat/surreal/blob/main/_autodocs/README.md
Sets a single attribute on an element or retrieves its value.
```javascript
me('input').attribute('disabled', true)
let value = me('input').attribute('value')
```
--------------------------------
### Custom Event Dispatch Example
Source: https://github.com/gnat/surreal/blob/main/_autodocs/README.md
Sends a custom event named 'validated' with associated details.
```javascript
me('form').send('validated', { success: true })
```
--------------------------------
### Using `any()` for Bulk Operations
Source: https://github.com/gnat/surreal/blob/main/_autodocs/configuration.md
Demonstrates the efficiency of using `any()` for applying operations to multiple elements compared to iterating with `run()`.
```javascript
any('button').classAdd('primary') // Better
any('button').run(btn => { btn.classList.add('primary') }) // More code
```
--------------------------------
### Dismissible alert example
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/effects.md
Demonstrates fading out an alert element upon a button click, removing it from the DOM after 300ms.
```html
This is an important message
```
--------------------------------
### Snake Case Naming Conventions
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Examples of using snake case methods for class manipulation and removing all event listeners.
```javascript
me().class_add('active')
me().class_remove('hidden')
me().off_all()
```
--------------------------------
### Create Element with Event Handler
Source: https://github.com/gnat/surreal/blob/main/_autodocs/QUICK-REFERENCE.md
Create an element, set its text content, attach an event listener using `.on()`, and then append it to the DOM.
```javascript
let button = createElement('button')
button.textContent = 'Click Me'
me(button)
.attribute('data-id', '123')
.on('click', () => alert('Clicked!'))
me('div').appendChild(button)
```
--------------------------------
### Chainable vs. Functional Method Calls
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Demonstrates the recommended chainable method style for DOM manipulation and the alternative functional style via namespace.
```javascript
// Chainable (method style) - recommended
me('button').classAdd('active').styles('color: red')
// Functional (traditional) - also supported
classAdd(me('button'), 'active')
styles(me('button'), 'color: red')
// Via namespace
surreal.me('button').classAdd('active')
```
--------------------------------
### Get an Attribute Value
Source: https://github.com/gnat/surreal/blob/main/_autodocs/QUICK-REFERENCE.md
Use `attribute()` to retrieve the value of an element's attribute. Specify the attribute name as a string.
```javascript
let value = me('input').attribute('value')
let dataId = me('div').attribute('data-id')
```
--------------------------------
### Create Complex Form Structure
Source: https://github.com/gnat/surreal/blob/main/_autodocs/QUICK-REFERENCE.md
Demonstrates creating a form with input and submit button elements, applying attributes, and appending them to the body. Uses chaining for attribute setting and event handling.
```javascript
let form = createElement('form')
let input = createElement('input')
let button = createElement('button')
me(input).attribute('type', 'text').attribute('placeholder', 'Enter name')
me(button).attribute('type', 'submit').textContent = 'Submit'
form.appendChild(input)
form.appendChild(button)
me(form)
.classAdd('login-form')
.on('submit', handleSubmit)
me('body').appendChild(form)
```
--------------------------------
### Get Single Element Inline
Source: https://github.com/gnat/surreal/blob/main/_autodocs/QUICK-REFERENCE.md
Use `me()` to select an element directly within its HTML context, ideal for inline behavior.
```html
```
--------------------------------
### Array Iteration Methods
Source: https://github.com/gnat/surreal/blob/main/README.md
Demonstrates using standard JavaScript array methods like `forEach` and `map` on elements selected by `any()`.
```javascript
any('button')?.forEach(...)
```
```javascript
any('button')?.map(...)
```
--------------------------------
### Attributes
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/dom-manipulation.md
Get, set, or remove attributes on elements. Supports single attributes, multiple attributes via an object, and boolean attributes.
```APIDOC
## Attributes
### `attribute(name, value)` / `attr(name, value)` / `attributes(name, value)`
Get, set, or remove attributes on element(s).
#### Signature
```javascript
attribute(element, name, value) → string | null | HTMLElement | NodeList | Array
e.attribute(name, value) → string | null | HTMLElement | NodeList | Array
```
#### Parameters
- **element** (HTMLElement | NodeList | Array) - Required (method form) - The element(s) to modify. For get operations, must be a single element.
- **name** (string | object) - Required - Attribute name (string) or object of attribute name-value pairs for bulk operations.
- **value** (string | boolean | null) - Optional - Value to set. `undefined` = get operation. `null` = remove attribute. `true` = set empty attribute.
#### Return Type
- **Get operation:** `string | null` (the attribute value, null if not found)
- **Set/Remove operation:** `HTMLElement | NodeList | Array` (for chaining)
- **Null safety:** Returns empty array for multi-element get operations
#### Behavior
- **Get** (name only): Returns attribute value. Works on single elements only.
- **Set** (name + value): Sets attribute to value.
- **Remove** (name + null): Removes the attribute.
- **Bulk** (object): Sets/removes multiple attributes at once.
#### Examples
#### Single attribute - Get
```javascript
// Get an attribute (single element only)
let status = me('#status').attribute('data-status')
console.log(status) // string or null
// Safe null access
let value = me('input')?.attribute('value')
```
#### Single attribute - Set
```javascript
// Set a single attribute
me('button').attribute('data-x', 'active')
// Boolean attributes
me('input').attribute('disabled', true)
me('input').attribute('disabled', false)
// Remove by setting to null
me('button').attribute('data-temp', null)
// Alternative names
me().attr('aria-label', 'Close dialog')
me().attributes('title', 'Click to expand')
```
#### Multiple attributes - Bulk operations
```javascript
// Set multiple attributes with an object
me('form').attribute({
'data-type': 'contact',
'data-version': '2',
'aria-label': 'Contact form'
})
// Mix setting and removing
me('input').attribute({
'placeholder': 'Enter text',
'data-temp': null, // Remove data-temp
'disabled': true // Disable input
})
```
#### Multiple elements - Set/Remove
```javascript
// Set attribute on all matching elements
any('input[type="checkbox"]').attribute('data-checked', false)
// Remove attribute from all elements
any('[data-temp]').attribute('data-temp', null)
// Chain with other operations
any('button').attribute('disabled', true).styles('opacity: 0.5')
```
```
--------------------------------
### Plugin System: Create and Use Custom Method
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Illustrates how to create a custom plugin function that adds a new method 'myMethod' to Surreal.js elements, and then how to use this custom method.
```javascript
// Create custom method
function pluginCustom(e) {
e.myMethod = function(param) {
// Your code
return e // Return for chaining
}
}
surreal.plugins.push(pluginCustom)
// Use it
me('button').myMethod('value').classAdd('processed')
```
--------------------------------
### Create and Append DOM Element
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/utilities.md
Shows how to create a new DOM element using `createElement()` and append it to the document body after applying styles and classes.
```javascript
let newDiv = createElement('div')
me(newDiv).classAdd('card').styles('padding: 1rem')
me('body').appendChild(newDiv)
```
--------------------------------
### run()
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/dom-manipulation.md
Executes a callback function on each selected element. This method is chainable and allows for complex DOM operations within a callback.
```APIDOC
## run()
### Description
Executes a callback function on each selected element. This method is chainable and allows for complex DOM operations within a callback.
### Method
`run(callback)`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Parameters
- **callback** (Function) - Required - The function to execute for each element. It receives the element as its only argument.
### Request Example
```javascript
// Run function on single element
me('button').run(btn => {
btn.textContent = btn.textContent.toUpperCase()
})
// Run on multiple elements
any('li').run(li => {
console.log(li.textContent)
})
```
### Response
#### Success Response (200)
- **HTMLElement | NodeList | Array** - The element(s) for chaining.
```
--------------------------------
### Async/Await Patterns: Sequential, Tick, and Staggered Operations
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Illustrates asynchronous operations using async/await, including sequential style changes with 'tick()', waiting with 'sleep()', and staggered element activation.
```javascript
// Sequential operations
(async (el = me('div')) => {
el.styles({ opacity: '0' })
await tick() // Wait for style to apply
el.styles({ transition: 'opacity 0.3s', opacity: '1' })
})()
// Wait for completion
await sleep(1000)
// Staggered operations
for (let item of any('.item')) {
me(item).classAdd('active')
await sleep(100)
}
```
--------------------------------
### Dynamically Creating Complex Elements
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Demonstrates how to dynamically create complex HTML elements using 'createElement', then manipulate them with Surreal.js methods for styling, attributes, and appending to the DOM.
```javascript
let card = createElement('div')
me(card)
.classAdd('card')
.attribute('data-id', '123')
.styles({
padding: '1rem',
borderRadius: '8px',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
})
let title = createElement('h2')
title.textContent = 'Card Title'
card.appendChild(title)
me('body').appendChild(card)
```
--------------------------------
### Create and Style an Element
Source: https://github.com/gnat/surreal/blob/main/_autodocs/QUICK-REFERENCE.md
Use `createElement()` to create a new DOM element and then chain SurrealJS methods like `.classAdd()` and `.styles()` to configure it before appending.
```javascript
let card = createElement('div')
me(card).classAdd('card').styles({
padding: '1rem',
borderRadius: '8px',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
})
me('body').appendChild(card)
```
--------------------------------
### Integrating Surreal.js with HTMX
Source: https://github.com/gnat/surreal/blob/main/_autodocs/configuration.md
Example of using Surreal.js event listeners within an HTMX-powered button to add a success class after a request completes.
```html
```
--------------------------------
### Get Attribute Value
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/dom-manipulation.md
Retrieve the value of a specific attribute from a single element using `attribute()` or its aliases. Returns `null` if the attribute is not found.
```javascript
// Get an attribute (single element only)
let status = me('#status').attribute('data-status')
console.log(status) // string or null
// Safe null access
let value = me('input')?.attribute('value')
```
--------------------------------
### Alternatives for DOM Manipulation on Load
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/utilities.md
Compares different methods for applying classes to elements once they are ready, including script placement, optional chaining, and onloadAdd.
```javascript
// Alternative 1: Place
// Alternative 2: Use optional chaining
// me('#content')?.classAdd('loaded')
// Alternative 3: Use onloadAdd for guaranteed execution
onloadAdd(() => {
me('#content').classAdd('loaded')
})
```
--------------------------------
### run(element, f)
Source: https://github.com/gnat/surreal/blob/main/_autodocs/API-SIGNATURES.md
Executes a function on each element in a collection. This is a shorthand for `forEach` and is chainable.
```APIDOC
## run(element, f)
### Description
Executes a function on each element in a collection. This is a shorthand for `forEach` and is chainable.
### Parameters
- **element** (HTMLElement | NodeList | Array) - The element(s) to iterate over.
- **f** (Function(element)) - The function to execute for each element.
### Returns
- `HTMLElement | NodeList | Array` - The element(s) the function was run on.
```
--------------------------------
### Attribute Manipulation: attribute()
Source: https://github.com/gnat/surreal/blob/main/_autodocs/API-SIGNATURES.md
Manages element attributes. Can be used to get, set, or remove attributes, or perform bulk operations. Chainable for set/remove operations.
```typescript
// Get operation
attribute(
element: HTMLElement,
name: string,
value?: undefined
) → string | null
```
```typescript
// Set/Remove operation
attribute(
element: HTMLElement | NodeList | Array,
name: string,
value: string | boolean | null
) → HTMLElement | NodeList | Array
```
```typescript
// Bulk operation
attribute(
element: HTMLElement | NodeList | Array,
name: { [key: string]: string | boolean | null }
) → HTMLElement | NodeList | Array
```
--------------------------------
### Select Parent Element with `any()`
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/selectors.md
Use `any()` without a selector to get an array containing the parent element of the current script tag, useful when expecting an array.
```javascript
any()
```
--------------------------------
### Creating a Custom Surreal.js Plugin
Source: https://github.com/gnat/surreal/blob/main/README.md
This snippet defines a function `pluginHello` that adds a `hello` method to Surreal.js elements. It demonstrates how to extend Surreal's functionality by pushing custom plugins into the `surreal.plugins` array.
```javascript
function pluginHello(e) {
function hello(e, name="World") {
console.log(`Hello ${name} from ${e}`)
return e // Make chainable.
}
// Add sugar
e.hello = (name) => { return hello(e, name) }
}
surreal.plugins.push(pluginHello)
```
--------------------------------
### Run Function on Each Element in a Collection
Source: https://github.com/gnat/surreal/blob/main/_autodocs/QUICK-REFERENCE.md
Demonstrates iterating over a collection of elements using `forEach`, `run()`, and `map`. `run()` is a convenient alias for `forEach`, and `map()` is used when return values are needed.
```javascript
// forEach style
any('button').forEach(btn => {
btn.textContent = btn.textContent.toUpperCase()
})
// Using run()
any('button').run(btn => {
btn.textContent = btn.textContent.toUpperCase()
})
// Using map (if you need return values)
let titles = any('h2').map(h => h.textContent)
```
--------------------------------
### Return Type Rules
Source: https://github.com/gnat/surreal/blob/main/_autodocs/API-SIGNATURES.md
Explains the conventions for return types in Surreal.js methods, including chainable methods, non-chainable methods, get operations, and multi-element operations.
```typescript
- Chainable methods: Return the element(s) for continued chaining
- Non-chainable methods: Return void (end the chain)
- Get operations: Return the retrieved value (string, null, etc.)
- Multi-element methods: Work on both single elements and arrays
- Array methods: `forEach()`, `map()`, `filter()` all work on results from `any()`
```
--------------------------------
### attribute(element, name, value)
Source: https://github.com/gnat/surreal/blob/main/_autodocs/API-SIGNATURES.md
Gets, sets, or removes attributes on one or more elements. The behavior depends on the arguments provided. It can be chainable when setting or removing attributes.
```APIDOC
## attribute(element, name, value)
### Description
Gets, sets, or removes attributes on one or more elements. The behavior depends on the arguments provided. It can be chainable when setting or removing attributes.
### Parameters
- **element** (HTMLElement | NodeList | Array) - The element(s) to operate on.
- **name** (string | object) - The name of the attribute to get/set, or an object of attribute key-value pairs to set.
- **value** (string | boolean | null | undefined) - Optional - The value to set for the attribute. If `undefined`, it performs a get operation. If `null`, it removes the attribute.
### Returns
- `string | null` - If getting an attribute.
- `HTMLElement | NodeList | Array` - If setting or removing an attribute.
```
--------------------------------
### Common Parameter Types
Source: https://github.com/gnat/surreal/blob/main/_autodocs/API-SIGNATURES.md
Illustrates common parameter types used across Surreal.js functions, such as selectors, start locations, callbacks, timing, and CSS values.
```typescript
// Selectors
selector: string | Event | HTMLElement | SVGElement | NodeList | Array | null
// Start location
start: HTMLElement | Document = document
// Callback functions
f: Function(element)
handler: Function(event)
callback: Function(element)
// Timing (milliseconds)
ms: number
duration: number = 1000
// CSS
name: string // CSS class name
value: string | object | null // CSS styles or attribute value
```
--------------------------------
### Registering Custom Effects Plugin
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/effects.md
Shows how to register custom effects by defining a plugin function and pushing it to the `surreal.plugins` array. The custom effect function should return `e` for chaining.
```javascript
function pluginMyEffects(e) {
e.myEffect = function(duration) {
// Your effect code here
return e // Return for chaining if desired
}
}
surreal.plugins.push(pluginMyEffects)
```
--------------------------------
### Validate CSS selector
Source: https://github.com/gnat/surreal/blob/main/_autodocs/API-SIGNATURES.md
Returns true if the provided string is a valid CSS selector that matches elements. Optionally takes a starting element and a warning flag.
```typescript
isSelector(
selector?: string,
start?: HTMLElement | Document,
warning?: boolean
) → boolean
```
--------------------------------
### Dispatch and Listen for Custom Events
Source: https://github.com/gnat/surreal/blob/main/_autodocs/QUICK-REFERENCE.md
Use `.send()` to dispatch custom events with data and `.on()` to listen for them.
```javascript
// Dispatch event with data
me('form').send('submit-success', {
message: 'Form submitted!',
timestamp: Date.now()
})
// Listen for custom event
me('form').on('submit-success', event => {
console.log(event.detail.message)
me(event).classAdd('success')
})
```
--------------------------------
### Utilities
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
A collection of utility functions for asynchronous operations, animation frame requests, DOM creation, and managing `onload` handlers.
```APIDOC
## Utilities (5 global functions + 1 internal)
### `sleep(ms, data)`
Returns a Promise that resolves after a specified number of milliseconds `ms`. Optionally carries `data`.
### `tick()`
Returns a Promise that resolves on the next animation frame.
### `rAF(f)`
Shorthand for `requestAnimationFrame`, executing function `f` on the next animation frame.
### `rIC(f)`
Shorthand for `requestIdleCallback`, executing function `f` when the browser is idle.
### `createElement(tagName)`
Creates a new HTML element with the specified tag name. Alias: `create_element`.
### `onloadAdd(f)`
Adds a function `f` to be executed when the DOM is fully loaded. Aliases: `onload_add`, `addOnload`, `add_onload`.
```
--------------------------------
### Search within a Specific DOM Context
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/selectors.md
Limit the search scope for selectors by providing a starting element. This is useful for scoping selections within a particular container.
```javascript
let container = me('#main')
me('button', container).classAdd('main-button')
```
--------------------------------
### Select and Manipulate Elements
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Shows how to select a single element and chain methods like 'classAdd' and 'styles', or select multiple elements and attach event listeners.
```javascript
// Single element
me('button').classAdd('primary').styles('padding: 1rem')
// Multiple elements
any('button').classAdd('clickable').on('click', handleClick)
```
--------------------------------
### Saving Element References for Async Operations
Source: https://github.com/gnat/surreal/blob/main/_autodocs/api-reference/event-handling.md
Capture the element reference using `me(event)` within an event handler to use it later, for example, after an asynchronous operation completes.
```javascript
me('button').on('click', async event => {
let el = me(event) // Save element reference
el.disable()
await sleep(1000)
el.styles('background: green')
})
```
--------------------------------
### Close Element from Child Event
Source: https://github.com/gnat/surreal/blob/main/example.html
This example shows how a child element can trigger a 'close' event on its parent, which then fades out the parent. It uses event delegation and custom events.
```javascript
me().on("close", async event => {
me(event).fadeOut()
})
// Recieve "close" event.
me().on("click", event => {
me(event).disable();
me(event).send("close")
})
```
--------------------------------
### Multi-element Operations
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Demonstrates how chainable methods can be applied to multiple elements selected using 'any()', affecting all matched elements.
```javascript
// All chainable methods work on arrays too
any('button')
.classAdd('primary')
.on('click', handleClick)
.attribute('data-role', 'main')
```
--------------------------------
### Perform Asynchronous Operations with `sleep`
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Utilize `async/await` with the `sleep` utility function to introduce delays in your JavaScript execution. This example waits for 1 second before adding a class to a button.
```javascript
(async () => {
await sleep(1000)
me('button').classAdd('ready')
})()
```
--------------------------------
### Utilities Functions
Source: https://github.com/gnat/surreal/blob/main/_autodocs/README.md
Helper functions for asynchronous operations, animation frames, and DOM creation.
```APIDOC
## Utilities
### `sleep(ms, data)`
Asynchronously pauses execution for a specified duration.
### `tick()`
Waits for the next animation frame.
### `rAF(callback)`
Schedules a callback to run on the next animation frame.
### `rIC(callback)`
Schedules a callback to run during idle time (requestIdleCallback).
### `createElement(tagName)`
Creates a new DOM element with the specified tag name.
### `onloadAdd(callback)`
Adds a callback to the window.onload event chain.
```
--------------------------------
### Element Selection Types
Source: https://github.com/gnat/surreal/blob/main/_autodocs/INDEX.md
Provides examples of various selector types supported by Surreal.js, including element, class, ID, attribute, combinators, multiple selectors, and relative selectors.
```javascript
me() // Parent of current
```
--------------------------------
### Include Surreal.js via File Download
Source: https://github.com/gnat/surreal/blob/main/_autodocs/configuration.md
Include the downloaded surreal.js file in your HTML's head section.
```html
```