npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

oberry

v1.4.0

Published

A lightweight and modern jQuery alternative for DOM manipulation, user interactions, and reactive data binding

Readme

oBerry

oberry License downloads npm bundle size Tests Lint

Overview

oBerry is a lightweight and modern JQuery alternative designed to simplify the manipulation of HTML elements, handling user interactions and binding reactive data to HTML content.

So... why oBerry?

| | oBerry | jQuery | | -------------------------- | --------------------------------- | ------------------------------ | | Bundle size | ~6 KB (2 KB gzipped) | ~90 KB (30 KB gzipped) | | API style | jQuery-like, modern ES modules | jQuery-style, legacy-friendly | | Reactivity | ✅ Built-in reactive data binding | ❌ Not built-in | | TypeScript support | ✅ Full type definitions | ❌ Limited (community typings) | | Plugin system | ✅ Simple Plugin API | ✅ $.fn plugin interface | | DOM manipulation | ✅ Yes, full API | ✅ Yes, full API | | Event handling | ✅ Yes, with typed callbacks | ✅ Yes | | Modern build support | ✅ ESM / tree-shakable | ❌ UMD only | | Legacy browser support | ❌ Modern browsers only | ✅ IE9+ | | Learning curve | Low | Low |

Features

  • 🚀 Lightweight - Minimal footprint
  • 🎯 jQuery-like API - Familiar syntax for easy migration
  • ⚡ Reactive Data Binding - Built-in reactivity system
  • 📦 TypeScript Support - Full type definitions included
  • 🎨 Comprehensive DOM Manipulation - Full suite of element manipulation methods
  • 🔄 Flexible Content Insertion - Multiple ways to add content to elements

Installation

npm install oberry

Quick start

  1. Using with a bundler (e.g. Vite, Webpack)
import { $, $ref } from 'oberry';

// Select and manipulate elements
$('.my-button')
  .class('active')
  .on('click', () => console.log('Clicked!'));

// Reactive data binding
const message = $ref('Hello World');
$('#output').bind(message);

// Update reactive value
message('Hello!');
  1. Using via CDN
import { $, $ref } from 'https://cdn.skypack.dev/oberry';

// Select and manipulate elements
$('.my-button')
  .class('active')
  .on('click', () => console.log('Clicked!'));

// Reactive data binding
const message = $ref('Hello World');
$('#output').bind(message);

// Update reactive value
message('Hello!');

API Reference

Element selection

// CSS selector
$('.class-name');
$('#element-id');
$('div');

// HTML Element
$(document.getElementById('myElement'));

// NodeList or Array of elements
$(document.querySelectorAll('.items'));

DOM Manipulation

Class Management

$('.element')
  .class() // Get the array of classes
  .class('old-class', 'remove') // Remove a class
  .class('new-class', 'add'); // Add a class
  .class('toggled-class', 'toggle') // Toggle a class
  .class('toggled-class another-class') // Add multiple classes (seperated by space)
  .hasClass('my-class') // Check if element has class

if you don't specify the mode it will toggle the class by default:

$('.element').class('this-will-toggle-a-class');

ID Management

// Get ID of first element
const elementId = $('.element').id();

// Set ID for all elements
$('.element').id('new-id');

Element Testing and Matching

// Check if element matches selector
$('.element').is('.active'); // Returns boolean

// Filter out elements that match selector
$('.elements').not('.disabled'); // Returns wrapper with non-matching elements

Styling

$('.element').css({
  color: 'red',
  fontSize: '16px',
  backgroundColor: '#f0f0f0',
});

Content Manipulation

$('.element')
  .html('<p>New HTML content</p>')
  .text('Plain text content')
  .html() // Returns HTML of first element
  .text(); // Returns text of first element

Content insertion

// Append content to elements
$('.element').append('<p>Appended content</p>');
$('.element').append(document.createElement('div'));
$('.element').append($('.other-element'));

// Prepend content to elements
$('.element').prepend('<p>Prepended content</p>');
$('.element').prepend(document.createElement('div'));
$('.element').prepend($('.other-element'));

// Insert content after elements
$('.element').after('<p>Content after</p>');
$('.element').after(document.createElement('div'));
$('.element').after($('.other-element'));

// Insert content before elements
$('.element').before('<p>Content before</p>');
$('.element').before(document.createElement('div'));
$('.element').before($('.other-element'));

Element Removal

// Remove all elements from DOM
$('.element').remove();

Form Values

// Get/set values for input, textarea, select elements
$('#input-field')
  .value('New value') // Sets the current value
  .value(); // Returns current value

Attributes and Data

// Get/set attributes
$('.element')
  .attr('data-id', '123') // Set attribute
  .attr('data-id'); // Get attribute

// Get/set data attributes
$('.element')
  .data('userId', '456') // Set data attribute
  .data('userId'); // Get data attribute

Element Navigation

// Get parent element (wrapped)
$('.child').parent();

// Get children of first element (wrapped)
$('.parent').children();

// Get children of all elements (wrapped)
$('.parents').allChildren();

// Get array of wrapped elements
$('.elements').getArray();

// Find descendants matching selector
$('.parent').find('.child-class');

// Find closest ancestor matching selector
$('.element').closest('.ancestor-class');

Element Filtering and Selection

// Get specific element by index
$('.elements').eq(2); // Get the 3rd element (zero-indexed)

// Get first element
$('.elements').first();

// Get last element
$('.elements').last();

// Get even-indexed elements (2nd, 4th, 6th, etc.)
$('.elements').even();

// Get odd-indexed elements (1st, 3rd, 5th, etc.)
$('.elements').odd();

// Filter elements by CSS selector
$('.elements').filter('.active');

// Filter elements by predicate function
$('.elements').filter((element, index) => {
  return element.classList.contains('highlight');
});

Element Iteration

// Iterate over each element
$('.elements').forEach(wrappedElement => {
  wrappedElement.class('processed');
});

Element Information

// Get number of elements
$('.elements').length();

// Check if selection is empty
$('.elements').isEmpty();

Visibility Control

// Hide elements (preserves original display value)
$('.element').hide();

// Show elements (restores original display value)
$('.element').show();

// Toggle visibility
$('.element').toggle();

Element Creation

import { $new } from 'oberry';

// Create new elements
const newDiv = $new('div').class('my-class').text('Hello World');

// Create new element with children
const list = $new('ul', $new('li').text('Hello, world!'));

// Create new element with multiple children
const list = $new(
  'ul',
  $new('li').text('first element'),
  $new('li').text('second element'),
  $new('li').text('third element'),
);

Event Listeners

$('.element').on('click', () => console.log('Clicked!'));
$('.element').off('click', () => console.log('Clicked!')); // Remove event listener

Reactivity

oBerry's reactivity system is built on top of alien-signals, providing efficient and fine-grained reactivity.

Reactive References

// Create reactive reference
const count = $ref(0);
const message = $ref('Hello');

// Reading values
console.log(count()); // 0
console.log(message()); // 'Hello'

// Setting values
count(42);
message('Hello World');

// Bind to DOM elements
$('#counter').bind(count); // Binds as text content
$('#message').bindHTML(message); // Binds as HTML content
$('#title').bindAttr('title', message); // Binds to attribute

Computed Values

const firstName = $ref('John');
const lastName = $ref('Doe');

// Create computed value that automatically updates
const fullName = $computed(() => {
  return `${firstName()} ${lastName()}`;
});

// Bind computed to DOM
$('#full-name').bind(fullName);

// Updates automatically when dependencies change
firstName('Jane'); // '#full-name' will show 'Jane Doe'

Effects

const count = $ref(0);

// Run side effects when reactive values change
$effect(() => {
  console.log(`Count is now: ${count()}`);
  document.title = `Count: ${count()}`;
});

count(1); // Console: 'Count is now: 1', Title updates
count(2); // Console: 'Count is now: 2', Title updates

Effect Scope

// Group multiple effects together for cleanup
const stopScope = $effectScope(() => {
  $effect(() => {
    console.log(`Count in scope: ${count()}`);
  });
});

// Stop all effects in the scope
stopScope();

Input Binding

// Two-way binding with form inputs
const name = $ref('');
$('#name-input').bindInput(name);

// The input value and ref stay in sync
name('John'); // Input shows 'John'
// User types 'Jane' -> name() returns 'Jane'

Plugins

// Create the plugin
const myPlugin = new Plugin('myPlugin', extend => {
  // Add custom method to ElementWrapper
  extend('customMethod', function (value) {
    return this.css({ backgroundColor: value });
  });

  extend('fadeIn', function (duration = 300) {
    this.css({ opacity: 0, transition: `opacity ${duration}ms` });
    setTimeout(() => this.css({ opacity: 1 }), 10);
    return this;
  });
});

// Install the plugin
use(myPlugin);

// Use the custom methods
$('.element').customMethod('red').fadeIn(500);