AyatSaadati.js: The Developer's Fortunate Toolkit
Introduction
Let's face it: modern web development, for all its power and flexibility, often comes with a significant cognitive load. We're constantly juggling frameworks, build tools, polyfills, and a seemingly endless stream of dependencies. Sometimes, you just need a straightforward, no-nonsense utility to get a job done without pulling in a whole new ecosystem or writing the same boilerplate for the twentieth time.
That's precisely why AyatSaadati.js was born.
In my years building web applications, I kept encountering recurring patterns – simple DOM manipulations, event handling, data persistence in local storage, or basic utility functions like debouncing. While frameworks offer their own abstractions, sometimes you're working in a lighter context, or you simply prefer a more direct approach without the overhead. I found myself repeatedly writing similar helper functions, and honestly, it started to feel a bit... unfortunate.
AyatSaadati.js is my attempt to bring a bit of "good fortune" and "happiness" (the literal meaning of saadati in Persian) back into day-to-day development. It's a lightweight, opinionated collection of common JavaScript utilities designed to make those recurring tasks just a little bit easier, a little bit cleaner, and a lot less repetitive. It's not a framework; it's a helping hand, a thoughtful companion for your JavaScript projects.
Features
AyatSaadati.js focuses on providing intuitive, performant solutions for common web development challenges. Think of it as your personal Swiss Army knife for the browser environment.
- Effortless DOM Selection: A powerful and concise way to select single or multiple DOM elements, akin to jQuery's simplicity but with a modern, framework-agnostic approach.
- Simplified Event Handling: Attach and manage events with ease, supporting delegation and various options.
- Robust Local Storage Management: A clean API for interacting with
localStorage, handling serialization and deserialization seamlessly. - Essential Utility Functions: Built-in utilities like
debounceandthrottleto manage function execution and optimize performance. - Class Manipulation: Simple methods for adding, removing, or toggling CSS classes on elements.
- Modular Design: Import only what you need, keeping your bundle size lean.
Installation
Getting AyatSaadati.js into your project is a breeze. We support all the standard methods, so pick what feels right for your workflow.
Via npm (Recommended for modern projects)
If you're using a module bundler like Webpack, Rollup, or Vite, npm is the way to go.
npm install ayat-saadati
Via yarn
For those who prefer yarn:
yarn add ayat-saadati
Via CDN (For quick prototyping or simpler setups)
Sometimes you just need to drop a script tag and go. For direct browser use, you can include AyatSaadati.js from a CDN. This will expose the global AyatSaadati object, or typically, a convenient $ alias.
<!-- For development (readable, unminified) -->
<script src="https://unpkg.com/ayat-saadati@latest/dist/ayat-saadati.umd.js"></script>
<!-- For production (minified) -->
<script src="https://unpkg.com/ayat-saadati@latest/dist/ayat-saadati.umd.min.js"></script>
Usage
AyatSaadati.js is designed to be intuitive. Most functions are exposed directly or via a convenient global alias, making your code cleaner and more readable.
Basic Import (ES Modules)
When installed via npm/yarn, you can import specific modules or the entire library:
// Import everything (not recommended for production due to bundle size)
import $ from 'ayat-saadati';
// Or, import specific utilities to keep your bundle lean
import { select, on, localStore, debounce } from 'ayat-saadati';
For the sake of concise examples, I'll often use the $ alias as if imported or available globally.
1. DOM Selection: $.select(selector, [context])
This is your go-to for finding elements. It behaves intelligently: if your selector targets a single element (e.g., an ID), it returns that element. Otherwise, it returns an array of elements.
<div id="app">
<button class="my-button">Click Me 1</button>
<button class="my-button">Click Me 2</button>
<p>Some text</p>
</div>
import $ from 'ayat-saadati';
// Select a single element by ID
const appDiv = $.select('#app');
console.log(appDiv); // Returns the <div> element
// Select multiple elements by class
const buttons = $.select('.my-button');
console.log(buttons); // Returns an array of both <button> elements
// Select elements within a specific context
const firstButtonInApp = $.select('.my-button', appDiv);
console.log(firstButtonInApp); // Returns the first <button> element within #app
// If no elements are found, it returns null or an empty array
const nonExistent = $.select('.non-existent');
console.log(nonExistent); // null
2. Event Handling: $.on(element, event, handler, [options])
Attaching event listeners has never been simpler. It automatically handles single elements or arrays of elements.
<div id="myContainer">
<button data-action="save">Save</button>
<button data-action="cancel">Cancel</button>
</div>
import { select, on } from 'ayat-saadati';
const saveButton = select('[data-action="save"]');
const container = select('#myContainer');
// Attach a click listener to a single button
on(saveButton, 'click', (event) => {
console.log('Save button clicked!', event.target.textContent);
});
// Attach a click listener to multiple buttons using delegation
// This is incredibly useful for dynamic content!
on(container, 'click', '[data-action]', (event) => {
const action = event.target.dataset.action;
console.log(`Action "${action}" triggered!`);
});
// Example with options (e.g., passive event listener)
const scrollableDiv = select('.scroll-area');
on(scrollableDiv, 'scroll', (event) => {
console.log('Scrolling...');
}, { passive: true });
3. Local Storage Management: $.localStore(key, [value])
A clean wrapper around localStorage that handles JSON serialization and deserialization for you.
import { localStore } from 'ayat-saadati';
// Set a value
localStore('username', 'Ayat');
localStore('settings', { theme: 'dark', notifications: true });
// Get a value
const user = localStore('username');
console.log(user); // 'Ayat'
const settings = localStore('settings');
console.log(settings); // { theme: 'dark', notifications: true }
// Get a non-existent key (returns null)
const nonExistentKey = localStore('myNonExistentKey');
console.log(nonExistentKey); // null
// Remove a key
localStore('username', null); // Setting value to null removes the key
console.log(localStore('username')); // null
4. Utility: $.debounce(func, delay)
Prevent functions from firing too rapidly, perfect for search inputs or window resizing.
import { select, on, debounce } from 'ayat-saadati';
const searchInput = select('#searchBox');
const resultDisplay = select('#searchResults');
function performSearch(query) {
console.log(`Searching for: "${query}"`);
// Simulate an API call
resultDisplay.textContent = `Results for "${query}"...`;
}
// Debounce the search function
const debouncedSearch = debounce((event) => {
performSearch(event.target.value);
}, 300); // Wait 300ms after the last keypress
on(searchInput, 'input', debouncedSearch);
5. Class Manipulation: $.toggleClasses(element, classes)
Add or remove classes with ease. You can pass a single class or an array of classes.
<div id="myElement" class="active">Hello</div>
import { select, toggleClasses } from 'ayat-saadati';
const myElement = select('#myElement');
// Toggle a single class
toggleClasses(myElement, 'active');
console.log(myElement.className); // '' (class 'active' removed)
toggleClasses(myElement, 'active');
console.log(myElement.className); // 'active' (class 'active' added back)
// Toggle multiple classes
toggleClasses(myElement, ['highlight', 'fancy']);
console.log(myElement.className); // 'active highlight fancy'
toggleClasses(myElement, ['active', 'fancy']); // 'active' is removed, 'fancy' is removed
console.log(myElement.className); // 'highlight'
API Reference (Summary)
| Function | Description | Arguments | Returns |
|---|---|---|---|
$.select(selector, [context]) |
Selects DOM elements. Returns a single element if unique (e.g., ID selector), otherwise an array. Returns null or [] if nothing found. |
selector (string): CSS selector. context (Element\ |
string): Optional. Element or selector string to scope the search. |
$.on(elements, event, handler, [delegateSelector], [options]) |
Attaches event listeners. Supports single elements, arrays, and event delegation. |
elements (Element\ |
Element[]): The element(s) to attach to. event (string): Event type (e.g., 'click'). handler (function): The callback function. delegateSelector (string): Optional CSS selector for delegation. options (object): Optional addEventListener options. |
$.off(elements, event, handler, [delegateSelector]) |
Removes event listeners. Matches $.on arguments. |
Same as $.on (excluding options). |
void |
$.localStore(key, [value]) |
Gets, sets, or removes items from localStorage. Handles JSON automatically. |
key (string): The key. value (any): Optional. If present, sets the value. If null, removes the key. |
any \ |
$.debounce(func, delay) |
Returns a new function that will only be invoked after delay milliseconds have passed since its last call. |
func (function): The function to debounce. delay (number): The delay in milliseconds. |
function (the debounced function) |
$.throttle(func, delay) |
Returns a new function that will only be invoked at most once per delay milliseconds. |
func (function): The function to throttle. delay (number): The delay in milliseconds. |
function (the throttled function) |
$.toggleClasses(element, classes) |
Toggles one or more CSS classes on an element. |
element (Element): The DOM element. classes (string\ |
string[]): One or more class names to toggle. |
Configuration
AyatSaadati.js is designed to be largely configuration-free, embracing sensible defaults for most use cases. However, for specific scenarios, you might want to adjust behavior.
Currently, there are no global configuration objects to set. The library focuses on utility functions that are configured directly via their arguments. This keeps things simple and avoids global state issues, which I find often lead to more headaches than they solve in utility libraries.
Top comments (0)