Gridstack.js предоставляет возможность работы с гибкой
сеточной системой, где элементы (widgets) можно
перемещать, изменять их размер и динамически добавлять. Одной из мощных
возможностей является расширение прототипов классов,
что позволяет добавлять новые методы и свойства к существующим объектам
Gridstack без модификации исходного кода библиотеки.
В Gridstack ключевым объектом является экземпляр класса
GridStack, к которому можно обращаться через
grid или напрямую через селектор DOM. Все элементы сетки
представлены как DOM-элементы с метаданными,
хранящимися в data-gs-* атрибутах.
const grid = GridStack.init({
float: true,
cellHeight: 80,
resizable: { handles: 'all' }
});
Расширение прототипа позволяет добавить кастомные
методы ко всем экземплярам GridStack:
GridStack.prototype.logAllWidgets = function() {
this.engine.nodes.forEach(node => {
console.log(`Widget id=${node.el.id} x=${node.x} y=${node.y} w=${node.w} h=${node.h}`);
});
};
После этого метод становится доступен у всех объектов:
grid.logAllWidgets();
Каждый элемент сетки (widget) представлен
DOM-узлом, который оборачивается в объект GridStack.
Для удобства часто добавляют методы прямо к прототипу
HTMLElement, но безопаснее расширять через Gridstack
API.
GridStack.prototype.highlightWidget = function(widgetEl, color = 'yellow') {
const node = this.engine.nodes.find(n => n.el === widgetEl);
if(node) node.el.style.backgroundColor = color;
};
Использование:
const widget = document.querySelector('#widget1');
grid.highlightWidget(widget, 'lightblue');
Это позволяет централизованно управлять поведением всех виджетов.
Gridstack.js не запрещает использование миксины для прототипов. Можно создавать модульные расширения:
const WidgetMixin = {
enableBlink() {
this.style.transition = 'background-color 0.5s';
setInterval(() => {
this.style.backgroundColor = this.style.backgroundColor === 'red' ? 'transparent' : 'red';
}, 500);
}
};
// Расширение прототипа HTMLElement для всех виджетов
Object.assign(HTMLElement.prototype, WidgetMixin);
// Использование
document.querySelector('#widget2').enableBlink();
Преимущество такого подхода — можно добавлять наборы функционала к любым элементам без дублирования кода.
В Gridstack иногда требуется изменить поведение стандартных методов. Для этого можно сохранить оригинал и вызвать его внутри новой реализации:
const originalAddWidget = GridStack.prototype.addWidget;
GridStack.prototype.addWidget = function(el, options) {
console.log('Добавление виджета с кастомной логикой');
// Вызов оригинального метода
return originalAddWidget.call(this, el, options);
};
Таким образом, сохраняется базовая функциональность, но добавляется дополнительная логика (например, логирование или проверка данных).
Gridstack поддерживает события (added,
removed, change). Можно расширять прототип,
чтобы автоматически подписываться на события при инициализации:
GridStack.prototype.initCustomEvents = function() {
this.on('added', (event, items) => {
items.forEach(i => console.log(`Добавлен виджет ${i.el.id}`));
});
this.on('removed', (event, items) => {
items.forEach(i => console.log(`Удален виджет ${i.el.id}`));
});
};
После инициализации:
grid.initCustomEvents();
Все новые виджеты будут отслеживаться автоматически.
Для хранения дополнительной информации о виджетах удобно использовать
data-* атрибуты или добавлять свойства через прототип:
GridStack.prototype.setWidgetMeta = function(widgetEl, key, value) {
const node = this.engine.nodes.find(n => n.el === widgetEl);
if(node) node.el.dataset[key] = value;
};
GridStack.prototype.getWidgetMeta = function(widgetEl, key) {
const node = this.engine.nodes.find(n => n.el === widgetEl);
return node ? node.el.dataset[key] : undefined;
};
Пример использования:
grid.setWidgetMeta(widget, 'priority', 'high');
console.log(grid.getWidgetMeta(widget, 'priority')); // "high"
Это особенно полезно для построения интерактивных интерфейсов с динамическими данными.
data-* атрибуты для хранения метаданных.Эти подходы позволяют создавать гибкую архитектуру расширений, упрощают повторное использование кода и обеспечивают контроль над всеми виджетами и их поведением в динамических интерфейсах.