Создание плагинов

Библиотека Cash, как облегчённый аналог jQuery, поддерживает расширение функционала через плагины. Плагин в Cash — это функция или набор функций, которые добавляют методы к объекту Cash. Основной принцип работы плагинов заключается в расширении прототипа Cash.prototype, что позволяет использовать новые методы на любом объекте Cash так же, как встроенные методы библиотеки (.css(), .addClass(), .on() и т.д.).

// Простейший пример плагина
Cash.prototype.highlight = function(color = 'yellow') {
    this.css('background-color', color);
    return this; // возврат для цепочек
};

В этом примере метод highlight добавляет подсветку выбранных элементов. Возврат this важен для поддержки цепочек вызовов.


Структура и организация плагина

Плагин может включать следующие элементы:

  1. Инициализация — функция, выполняющаяся при вызове метода на объекте Cash.
  2. Обработка аргументов — поддержка опций конфигурации и параметров.
  3. Возврат значения — чаще всего возвращается this для цепочек, но иногда могут возвращаться данные (например, .val()).

Пример плагина с настройками:

Cash.prototype.fadeText = function(options = {}) {
    const settings = {
        duration: 400,
        color: 'black',
        ...options
    };

    this.each(el => {
        el.style.transition = `color ${settings.duration}ms`;
        el.style.color = settings.color;
    });

    return this;
};

Ключевой момент: использование метода each, встроенного в Cash, для итерации по выбранным элементам.


Принципы написания безопасных плагинов

  1. Избегание конфликтов имён Названия методов должны быть уникальными, чтобы не перезаписать существующие функции. Рекомендуется использовать префиксы, например: myFade вместо fade.

  2. Поддержка цепочек вызовов Методы, которые изменяют DOM, должны возвращать this. Методы, возвращающие значения, должны быть отделены, чтобы не ломать цепочки.

  3. Обработка ошибок и типов данных Проверка аргументов и наличие элементов в выборке повышает стабильность плагина.

Cash.prototype.toggleClassSafe = function(className) {
    if (typeof className !== 'string') throw new TypeError('className должен быть строкой');
    this.each(el => el.classList.toggle(className));
    return this;
};

Взаимодействие с событиями и асинхронными операциями

Плагины часто используют события (.on, .off) или анимации. Важно учитывать контекст (this) и сохранять цепочку вызовов:

Cash.prototype.flash = function(color = 'red', duration = 300) {
    this.each(el => {
        const originalColor = el.style.backgroundColor;
        el.style.backgroundColor = color;
        setTimeout(() => {
            el.style.backgroundColor = originalColor;
        }, duration);
    });
    return this;
};

При работе с асинхронными функциями, такими как fetch или setTimeout, сохранение ссылки на this через const self = this; или стрелочные функции предотвращает потерю контекста.


Плагины с возвратом данных

Некоторые плагины могут возвращать информацию о элементах, а не this. В таких случаях важно отделять методы для получения данных от методов для изменения DOM:

Cash.prototype.getTextLengths = function() {
    return this.map(el => el.textContent.length);
};

Метод возвращает массив длин текстов всех выбранных элементов и не поддерживает цепочки.


Рекомендации по организации больших плагинов

  1. Разделение на модули Если плагин сложный, логично разделить его на внутренние функции. Основной метод обращается к ним, что упрощает поддержку и тестирование.
function applyFade(el, duration, color) {
    el.style.transition = `color ${duration}ms`;
    el.style.color = color;
}

Cash.prototype.complexFade = function(options = {}) {
    const settings = { duration: 500, color: 'blue', ...options };
    this.each(el => applyFade(el, settings.duration, settings.color));
    return this;
};
  1. Использование параметров по умолчанию Предотвращает ошибки, если вызов метода происходит без аргументов.

  2. Документирование методов Четкие комментарии и описание параметров помогают другим разработчикам использовать плагин без необходимости читать исходный код.


Расширение функционала Cash без изменения ядра

Для сохранения совместимости и облегчения обновлений библиотеки рекомендуется не менять встроенные методы Cash, а добавлять новые через Cash.prototype. Альтернатива — создание собственного объекта-обёртки, который расширяет функционал, но оставляет ядро библиотеки нетронутым.


Примеры комплексных плагинов

Слайдер изображений:

Cash.prototype.simpleSlider = function(options = {}) {
    const settings = { interval: 3000, ...options };
    this.each(container => {
        const slides = container.children;
        let index = 0;

        function showSlide(i) {
            Array.from(slides).forEach((slide, idx) => {
                slide.style.display = idx === i ? 'block' : 'none';
            });
        }

        showSlide(index);
        setInterval(() => {
            index = (index + 1) % slides.length;
            showSlide(index);
        }, settings.interval);
    });
    return this;
};

Фильтр элементов по атрибуту:

Cash.prototype.filterByAttr = function(attr, value) {
    return this.filter(el => el.getAttribute(attr) === value);
};

Этот метод возвращает новый объект Cash, содержащий только элементы, соответствующие условию, что позволяет применять к ним последующие методы цепочки.


Создание плагинов в Cash требует понимания работы с прототипами, управления контекстом и поддержки цепочек вызовов. Правильная организация кода, проверка аргументов и использование встроенных методов библиотеки делают плагины устойчивыми, гибкими и удобными для интеграции в проекты любой сложности.