Skip to content

JavaScript Plugins

Contents of this page:

The Guppy Theme extends the Shopware frontend through specialized JavaScript plugins that provide modern functionalities and improved user interactions.

Plugin Architecture

The Guppy Theme uses the Shopware plugin system and extends it with custom components:

Registration

javascript
// New plugins
PluginManager.register('SplideSliderPlugin', SplideSliderPlugin);
PluginManager.register('UspBannerPlugin', UspBannerPlugin);
PluginManager.register('ProductBoxClickPlugin', ProductBoxClickPlugin);

// Plugin overrides
PluginManager.override('QuantitySelector', () => import('./js/quantity-selector.plugin'));

Plugin Initialization

javascript
// Automatic initialization via data attributes
<div data-splide-slider-plugin="true" data-splide-slider-plugin-options='{...}'>

Splide Slider Plugin

Description

Modern slider based on the Splide.js library that replaces the standard Tiny Slider.

Features

  • Better Performance: Optimized for modern browsers
  • Accessibility: Full keyboard navigation and screen reader support
  • Responsive Design: Automatic adaptation to different screen sizes
  • Touch Support: Native touch gestures for mobile devices

Implementation

javascript
export default class SplideSliderPlugin extends Plugin {
    static options = {
        splideSnippets: ""
    }

    init() {
        this._mountSlider(this.el, this.options.splideSnippets);
    }

    _mountSlider(element, options) {
        var splideSlider = new Splide(element, {
            i18n: options
        }).mount();

        // Autoplay handling
        const splideOptions = Object.getPrototypeOf(splideSlider.options);
        if (splideOptions.autoplay === "pause") {
            splideSlider.Components.Autoplay.play();
        }
    }
}

Usage

html
<div class="splide" data-splide-slider-plugin="true">
    <div class="splide__track">
        <ul class="splide__list">
            <li class="splide__slide">Slide 1</li>
            <li class="splide__slide">Slide 2</li>
            <li class="splide__slide">Slide 3</li>
        </ul>
    </div>
</div>

USP Banner Plugin

Description

Interactive banner system for Unique Selling Points with tooltip functionality and responsive behavior.

Features

  • Tooltip System: Automatic tooltips for longer content
  • Responsive Display: Different number of USPs depending on screen size
  • Slider Integration: Automatic slider behavior on mobile devices
  • Configurable Layouts: Standard and benefit layout available

Configuration

javascript
// Theme configuration
{
    "guppy-usp-active": true,
    "guppy-usp-layout": "benefits",
    "guppy-usp-layout-benefit1": "Free Shipping",
    "guppy-usp-layout-benefit2": "30 Day Returns",
    "guppy-usp-layout-benefit3": "Fast Delivery"
}

Responsive Behavior

  • Desktop: 1-4 USPs (static)
  • Tablet: 1-2 USPs (slider with infinite loop)
  • Mobile: 1 USP (slider with infinite loop)

Product Box Click Plugin

Description

Extends product box functionality with improved click interactions and accessibility.

Features

  • Entire Box Clickable: Not just the product name
  • Keyboard Navigation: Full keyboard support
  • Focus Management: Correct focus handling
  • Event Delegation: Efficient event handling

Implementation

javascript
// Enhanced product box interaction
document.addEventListener('click', (event) => {
    const productBox = event.target.closest('.product-box');
    if (productBox && !event.target.closest('.btn, .product-action')) {
        const link = productBox.querySelector('.product-name a');
        if (link) {
            link.click();
        }
    }
});

Custom Checkout Plugin

Description

Optimizes the checkout experience through improved user guidance and form handling.

Features

  • Form Validation: Extended client-side validation
  • Progress Tracking: Visual progress through checkout steps
  • Auto-Save: Automatic saving of form data
  • Error Handling: Improved error handling

Usage

javascript
// Automatic activation on checkout pages
<div class="checkout-main" data-custom-checkout-plugin="true">

Quantity Selector Plugin (Override)

Description

Extends the standard Quantity Selector with improved user interaction and validation.

Features

  • Input Validation: Prevents invalid inputs
  • Keyboard Support: Arrow key navigation
  • Accessibility: ARIA labels and screen reader support
  • Animation: Smooth transitions on changes

Extended Functionality

javascript
// Enhanced quantity selection
PluginManager.override('QuantitySelector', QuantitySelectorPlugin, '[data-quantity-selector]');

Additional Plugins

Remove Extra H1 Plugin

  • Purpose: SEO optimization by removing redundant H1 tags
  • Automatic: Runs after DOM load
  • SEO Compliant: Prevents multiple H1 tags per page

Delivery Information Margin Plugin

  • Purpose: Dynamic margin adjustment for delivery information
  • Responsive: Adapts to different screen sizes
  • Layout Optimization: Improved visual hierarchy
  • Purpose: Extended gallery functionality
  • Thumbnail Navigation: Synchronized thumbnail view
  • Zoom Integration: Seamless zoom functionality
  • Touch Gestures: Extended touch interactions
  • Purpose: Responsive footer behavior
  • Mobile First: Accordion behavior on mobile devices
  • Accessibility: Correct ARIA attributes
  • Animation: Smooth collapse animations

Detailed Plugin Configuration

Splide Slider Options

The Splide Slider supports all Splide.js options:

javascript
// Via data attributes
<div class="splide"
     data-splide-slider-plugin="true"
     data-splide-slider-plugin-options='{
       "type": "loop",
       "perPage": 4,
       "perMove": 1,
       "gap": "1rem",
       "pagination": false,
       "arrows": true,
       "autoplay": true,
       "interval": 5000,
       "pauseOnHover": true,
       "breakpoints": {
         "1024": { "perPage": 3 },
         "768": { "perPage": 2 },
         "576": { "perPage": 1 }
       }
     }'>
OptionTypeDefaultDescription
typestringslideSlider type: slide, loop, fade
perPagenumber1Visible slides
perMovenumber1Slides per movement
gapstring0Gap between slides
arrowsbooleantrueShow navigation arrows
paginationbooleantrueShow pagination dots
autoplaybooleanfalseAutomatic playback
intervalnumber5000Autoplay interval (ms)
pauseOnHoverbooleantruePause on hover
rewindbooleanfalseRewind to beginning
speednumber400Animation speed (ms)
easingstringcubic-bezier(0.25, 1, 0.5, 1)Easing function

Splide Events

javascript
// Add event listeners
document.addEventListener('DOMContentLoaded', () => {
    const splideEl = document.querySelector('.splide');
    const splide = splideEl._splide; // Access Splide instance

    if (splide) {
        // Slide changed
        splide.on('move', (newIndex, prevIndex) => {
            console.log(`Moved from ${prevIndex} to ${newIndex}`);
        });

        // Slider initialized
        splide.on('mounted', () => {
            console.log('Slider mounted');
        });

        // Autoplay started/stopped
        splide.on('autoplay:play', () => console.log('Autoplay started'));
        splide.on('autoplay:pause', () => console.log('Autoplay paused'));
    }
});

USP Banner Plugin Options

javascript
// Theme configuration (theme.json)
{
    "guppy-usp-active": true,
    "guppy-usp-layout": "benefits",  // "benefits" or "standard"

    // Benefits Layout (up to 4 USPs)
    "guppy-usp-layout-benefit1": "Free shipping over $50",
    "guppy-usp-layout-benefit2": "30-day return policy",
    "guppy-usp-layout-benefit3": "Fast delivery",
    "guppy-usp-layout-benefit4": "Secure payment",

    // Standard Layout
    "guppy-usp-layout-text": "Get 10% off now!",
    "guppy-usp-layout-link": "/promotions",
    "guppy-usp-layout-newTab": false,

    // Colors
    "guppy-usp-text-color": "#2b3136",
    "guppy-usp-hover-color": "#0042a0",
    "guppy-usp-background-color": "#EEEEEE"
}

Product Box Click Plugin

javascript
// Customize plugin behavior
export default class ProductBoxClickPlugin extends Plugin {
    static options = {
        // Elements excluded from click
        excludeSelectors: '.btn, .product-action, .wishlist-button, input, select',
        // Link selector for product page
        linkSelector: '.product-name a, .product-image-link'
    }

    init() {
        this.el.addEventListener('click', this._onClick.bind(this));
        this.el.addEventListener('keydown', this._onKeydown.bind(this));
    }

    _onClick(event) {
        if (event.target.closest(this.options.excludeSelectors)) {
            return;
        }

        const link = this.el.querySelector(this.options.linkSelector);
        if (link) {
            link.click();
        }
    }

    _onKeydown(event) {
        if (event.key === 'Enter' || event.key === ' ') {
            this._onClick(event);
        }
    }
}

Plugin Debugging

DevTools Integration

javascript
// Get plugin instance
const element = document.querySelector('[data-splide-slider-plugin]');
const pluginInstance = window.PluginManager.getPluginInstanceFromElement(element, 'SplideSliderPlugin');

// Show plugin options
console.log(pluginInstance.options);

// List all registered plugins
console.log(window.PluginManager.getPluginList());

Common Issues

IssueCauseSolution
Plugin not loadingJavaScript errorCheck browser console
Slider shows no slidesWrong HTML structureCheck Splide classes
Events not firingPlugin not initializedWait for DOMContentLoaded
Autoplay not workingautoplay: "pause" setChange to true

Creating Custom Plugins

Plugin Template

javascript
import Plugin from 'src/plugin-system/plugin.class';

export default class MyCustomPlugin extends Plugin {
    static options = {
        // Default options
        myOption: 'default-value',
        anotherOption: true
    };

    init() {
        // Plugin initialization
        this._registerEvents();
    }

    _registerEvents() {
        this.el.addEventListener('click', this._onClick.bind(this));
    }

    _onClick(event) {
        // Event handler
        console.log('Clicked!', this.options.myOption);
    }

    // Lifecycle: Plugin is removed
    destroy() {
        // Cleanup
    }
}

Register Plugin

javascript
// main.js
import MyCustomPlugin from './plugins/my-custom-plugin';

window.PluginManager.register('MyCustomPlugin', MyCustomPlugin, '[data-my-custom-plugin]');

Use Plugin

html
<div data-my-custom-plugin="true"
     data-my-custom-plugin-options='{"myOption": "custom-value"}'>
    <!-- Content -->
</div>