Zepto is a minimalist JavaScript library for modern browsers with a largely jQuery-compatible API
Data attribute handling and internal data storage system for associating arbitrary data with DOM elements. Provides both HTML5 data attributes and internal storage.
Work with HTML5 data-* attributes with automatic type conversion.
/**
* Get or set data attributes on elements
* @param name - Data attribute name (without 'data-' prefix)
* @param value - Value to set (if setting)
* @returns Data value (if getting) or collection (if setting)
*/
$.fn.data(name, value);
/**
* Remove data attributes from elements
* @param names - Space-separated data attribute names to remove
* @returns Original collection
*/
$.fn.removeData(names);Usage Examples:
// Set data attributes
$('.item').data('id', 123);
$('.item').data('config', {theme: 'dark', size: 'large'});
// Get data attributes
const itemId = $('.item').data('id'); // Returns 123 (number)
const config = $('.item').data('config'); // Returns object
// Data attributes in HTML
// <div class="item" data-id="456" data-active="true" data-tags='["tag1", "tag2"]'></div>
const id = $('.item').data('id'); // 456 (number)
const active = $('.item').data('active'); // true (boolean)
const tags = $('.item').data('tags'); // ['tag1', 'tag2'] (array)
// Remove data
$('.item').removeData('id config');Store arbitrary data internally without modifying DOM attributes.
/**
* Store data associated with DOM elements
* @param elem - DOM element
* @param name - Data property name
* @param value - Data value to store
* @returns Stored value
*/
$.data(elem, name, value);
/**
* Check if element has stored data
* @param elem - DOM element to check
* @returns True if element has data
*/
$.hasData(elem);
/**
* Unique property name for data storage
*/
$.expando; // Internal property name used for data storageUsage Examples:
// Store internal data
const element = document.getElementById('myElement');
$.data(element, 'widget', new MyWidget());
$.data(element, 'initialized', true);
// Retrieve internal data
const widget = $.data(element, 'widget');
const isInitialized = $.data(element, 'initialized');
// Check for data
if ($.hasData(element)) {
console.log('Element has associated data');
}
// Using with Zepto collections
$('.widget').each(function() {
const widget = $.data(this, 'instance');
if (widget) {
widget.update();
}
});Automatic conversion of data attribute values to appropriate JavaScript types.
// HTML data attributes with automatic conversion:
// data-number="42" → 42 (number)
// data-float="3.14" → 3.14 (number)
// data-boolean="true" → true (boolean)
// data-boolean="false" → false (boolean)
// data-null="null" → null
// data-json='{"key":"value"}' → {key: 'value'} (object)
// data-array='[1,2,3]' → [1, 2, 3] (array)
// data-string="hello" → "hello" (string)
// Examples:
// <div data-count="5" data-active="true" data-config='{"theme":"dark"}'></div>
const count = $('.item').data('count'); // 5 (number)
const active = $('.item').data('active'); // true (boolean)
const config = $('.item').data('config'); // {theme: 'dark'} (object)Common patterns for storing plugin and widget data.
// Plugin initialization pattern
$.fn.myPlugin = function(options) {
return this.each(function() {
const $this = $(this);
let instance = $this.data('myPlugin');
if (!instance) {
instance = new MyPlugin(this, options);
$this.data('myPlugin', instance);
}
return instance;
});
};
// Widget state management
function initializeWidget($element) {
const config = $element.data('config') || {};
const widget = {
element: $element[0],
options: $.extend({}, defaultOptions, config),
state: 'initialized'
};
$element.data('widget-instance', widget);
return widget;
}
// Data-driven configuration
$('.configurable').each(function() {
const $this = $(this);
const config = {
theme: $this.data('theme') || 'default',
size: $this.data('size') || 'medium',
enabled: $this.data('enabled') !== false
};
initializeComponent($this, config);
});Automatic cleanup and memory management for stored data.
// Data is automatically cleaned up when elements are removed
$('.widget').remove(); // Associated data is cleaned up automatically
// Manual cleanup
$('.temporary').removeData(); // Remove all data
$('.cache').removeData('cache results'); // Remove specific data
// Check for memory leaks
function checkDataLeaks() {
let elementCount = 0;
let dataCount = 0;
$('*').each(function() {
elementCount++;
if ($.hasData(this)) {
dataCount++;
}
});
console.log(`Elements: ${elementCount}, With data: ${dataCount}`);
}
// Enhanced remove method cleans up data
$.fn.remove = function() {
return this.each(function() {
// Clean up data before removing
$(this).removeData();
$(this).find('*').removeData();
// Remove from DOM
if (this.parentNode) {
this.parentNode.removeChild(this);
}
});
};Combining data storage with event handling.
// Store event handlers with data
$('.interactive').each(function(index) {
const $this = $(this);
// Store element-specific data
$this.data('index', index);
$this.data('clickCount', 0);
// Event handler using stored data
$this.on('click', function() {
const index = $this.data('index');
let clickCount = $this.data('clickCount');
clickCount++;
$this.data('clickCount', clickCount);
console.log(`Element ${index} clicked ${clickCount} times`);
});
});
// Pass data to event handlers
$('.button').on('click', {action: 'save', id: 123}, function(e) {
console.log('Action:', e.data.action);
console.log('ID:', e.data.id);
});Using data storage for caching and performance optimization.
// Cache expensive computations
function getExpensiveData($element) {
let cached = $element.data('expensive-cache');
if (!cached) {
// Perform expensive computation
cached = performExpensiveComputation();
$element.data('expensive-cache', cached);
}
return cached;
}
// Cache with expiration
function getCachedData($element, key, computeFn, ttl = 60000) {
const now = Date.now();
const cached = $element.data(key);
if (cached && cached.timestamp && (now - cached.timestamp) < ttl) {
return cached.data;
}
const fresh = computeFn();
$element.data(key, {
data: fresh,
timestamp: now
});
return fresh;
}
// Usage
const data = getCachedData($('.expensive'), 'api-data', () => {
return $.getJSON('/api/data');
}, 300000); // 5 minute cacheRecommendations for effective data management.
// Use consistent naming conventions
$('.item').data('item-id', 123); // kebab-case for HTML attributes
$('.item').data('itemId', 123); // camelCase for JavaScript
// Namespace data to avoid conflicts
$('.widget').data('myPlugin.config', config);
$('.widget').data('myPlugin.state', state);
// Store references, not copies
const largeObject = {/* large data */};
$('.item').data('reference', largeObject); // Store reference
// Not: $('.item').data('copy', $.extend({}, largeObject));
// Clean up data when destroying components
function destroyWidget($element) {
const widget = $element.data('widget-instance');
if (widget) {
widget.cleanup();
$element.removeData('widget-instance');
}
}
// Use data for configuration, not large datasets
// Good: $('.chart').data('config', {type: 'line', color: 'blue'});
// Bad: $('.chart').data('dataset', hugeArrayOfData);