Welcome to the Monster Saga

Once upon a digital time, in a cyberspace not too different from your own, a lightweight, robust, and amazingly easy-to-use library called Monster was born.

Picture this: You’re tirelessly coding away, tangled up in a web of JavaScript functions and CSS rules. Just when you think you’re stuck in an endless loop of complication, Monster comes to the rescue!

For those eager to dive right in, you can start your journey here.

The API Documentation is available here and the full source code is available here.

Meet Monster: Your new frontend sidekick

Monster is not your typical JavaScript library; it’s more like the Robin to your Batman, a seamless sidekick in your quest for a powerful frontend. It has the superpower of integrating seamlessly into any existing web project, without having to be the without having to be the sole hero.

Why you’ll want to know Monster better

Your journey with Monster starts now, and trust us, you won’t want to return to zero! In the next section, `Getting Started’, we’ll reveal the secret spells that will let Monster into your site and change your frontend development experience forever.

Freedom at its best

Licensed under a freedom-giving, no-cost license, Monster is customizable down to its very core. Whether you’re building an e-commerce site or a portfolio, this frontend library can morph into whatever you need.

Unparalleled Flexibility and Compatibility

The beauty of Monster? It’s a lone wolf that plays well with the pack. Even though it is it’s a standalone entity with zero dependencies, it works flawlessly with other libraries and frameworks, including jQuery and Bootstrap.

Core Design Goals: A legacy to uphold

Monster comes with a promise - a legacy, even. It promises to provide:

Reusability: web components are self-contained entities that can be easily reused in different parts of an application, reducing the amount of duplicate code and increasing maintainability.

Modularity: Web components can be assembled from other web components, allowing developers to create complex user interfaces from small, modular building blocks.

Interoperability: Web components are developed based on web standards and are therefore compatible with other web technologies and frameworks. This allows developers to easily integrate web components into their existing applications.

Performance: Web components are lightweight and powerful, they can be rendered and updated quickly, which can improve the overall performance of web applications.

Acceptability: web components are increasingly used by browsers and developers and are part of the web platform, making it easy to find support and guidance online.

Flexible: web components are not tied to a specific framework, so developers can choose the tools that best suit their needs.

Overall, MonsterJS and its web components offer a great way to improve the scalability, maintainability and performance of web applications.

So, are you ready to embark on an exciting journey with Monster and revolutionize the way you look at front-end development?

Stay tuned!

Getting Started

To use Monster, you must have a foundation in HTML, CSS, and JavaScript. If you are just starting out in frontend development, it is recommended that you have a beginner’s guide open while working through this guide.

You can also ask for help on Stack Overflow by tagging your questions with “javascript” and “monster”.

Using Monster in the browser

To get started with Monster, all you need is a text editor and a browser. The best way to begin is to copy the following example into a file and save it as index.html.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Unleash your inner monster!</title>
</head>
<body>

<div>Your version is:
    <span id="version"></span>
</div>

<script type="module">
    import { Version } from 'https://cdn.skypack.dev/@schukai/monster@latest/source/types/version.js';
    document.getElementById('version').innerText = new Version('1.0.0').toString();
</script>

</body>
</html>

Then, open this file in your browser. You have now used the ‘Version’ class from Monster to create a Version object, which is output in a span.

Congratulations!

As shown in the version example, each Monster class or function can be used independently. Alternatively, Monster can be used as a collection of many useful classes and functions via the Monster namespace as a single JavaScript file.

In addition to being available on CDN providers like jsDelivr and Skypack, Monster can also be obtained via NPM or the git repos.

Monster itself has no dependencies and does not impose any specific requirements, so you can use it with Bootstrap, jQuery, or other frameworks.

Using Monster with NPM

To install Monster using npm, you will need to have Node.js and npm (which comes with Node.js) installed on your system.

  • Open a terminal or command prompt on your computer.
  • Run the following command: npm install @schukai/monster

This will install the latest version of Monster from the npm registry. If you want to install a specific version of Monster, you can specify the version number after the package name, like this: npm install @schukai/[email protected].

Once the installation is complete, you can import the modules in your JavaScript file like this:

import {Version} from '@schukai/monster/source/types/version.js';
console.log(new Version('1.0.0').toString());

Instead of npm you can of course also use yarn or pnpm.

Style

The CSS Style guide for Monster is a set of guidelines and best practices for writing and organizing CSS code. It is designed to help developers maintain a consistent and organized codebase, making it easier to read, understand, and modify. The style guide covers a wide range of topics, including naming conventions, code organization, and performance optimization. Following the guidelines in this style guide will help ensure that your CSS code is clean, maintainable, and efficient.

The following example shows how to include the stylesheets independently of the rest of the document.

<!-- here we define the desired content -->
<template id="contenttemplate">
    <p>this is an example</p>
</template>

<script type="module">

    // here we import the stylesheets
    import {NormalizeStyleSheet} from
                '@schukai/monster@latest/source/components/stylesheet/normalize.mjs';
    import {PropertyStyleSheet} from 
                '@schukai/monster@latest/source/components/stylesheet/property.mjs';
    import {ColorStyleSheet} from 
                '@schukai/monster@latest/source/components/stylesheet/color.mjs';
    import {ThemeStyleSheet} from 
                '@schukai/monster@latest/source/components/stylesheet/theme.mjs';
    
    // we create a node
    const node = document.createElement('div');
    
    // we attach the shadow root to the node
    const shadow = node.attachShadow({ mode: 'open' });
    
    // we clone the template and attach it to the shadow root
    const template = document.getElementById('contenttemplate');
    shadow.appendChild(template.content.cloneNode(true));
     
    // we attach the stylesheets to the shadow root
    shadow.adoptedStyleSheets = [
        NormalizeStyleSheet, 
        PropertyStyleSheet,
        ColorStyleSheet,
        ThemeStyleSheet
    ];
    
    // we attach the node to the body
    document.body.appendChild(node);

</script>

Typography

This page is a demonstration of the elements that can be formatted using Monster. It is not intended to be a comprehensive guide to typography, but rather a reference of the styles that are available.

Level (z-index)

The z-index property specifies the stack order of an element. An element with greater stack order is always in front of an element with a lower stack order.

CSS-Properties

Property
--monster-z-index-default
--monster-z-index-outline
--monster-z-index-dropdown
--monster-z-index-dropdown-overlay
--monster-z-index-sticky
--monster-z-index-sticky-overlay
--monster-z-index-fixed
--monster-z-index-fixed-overlay
--monster-z-index-modal-backdrop
--monster-z-index-modal-backdrop-overlay
--monster-z-index-offcanvas
--monster-z-index-offcanvas-overlay
--monster-z-index-modal
--monster-z-index-modal-overlay
--monster-z-index-popover
--monster-z-index-popover-overlay
--monster-z-index-tooltip
--monster-z-index-tooltip-overlay

Media Queries (Breakpoints)

Media queries are used to apply different styles to a document depending on the size of the screen. Media queries are defined in the @media rule. The @media rule is used inside a style sheet to apply different styles for different media types/devices.

More information about media queries can be found on MDN.

In Monster we use the following media queries:

ClassFromTo
viewport00480px
viewport-40480px
viewport-70768px
viewport-90992px
viewport-1201200px
viewport4480px
viewport7768px
viewport9992px
viewport121200px
viewport4-7480px768px
viewport7-9768px992px
viewport9-12992px1200px

In the following graphic you can see the different media queries and the corresponding mixins.

Skeleton (loading animation)

Skeleton is a CSS class that provides a loading animation for elements. It can be used to indicate that an element is loading or that the user has to wait for the content to be loaded. The monster-skeleton-col-xxx classes define the look of the skeleton. The xx defines the width of the skeleton in percent. monster-skeleton-col-100 is the widest skeleton and monster-skeleton-col-10 is the narrowest skeleton.

The monster-skeleton-animated class defines the animation.

<div class="monster-skeleton-col-100 monster-skeleton-animated">.</div>
<div class="monster-skeleton-col-90 monster-skeleton-animated">.</div>
<div class="monster-skeleton-col-80 monster-skeleton-animated">.</div>
<div class="monster-skeleton-col-70 monster-skeleton-animated">.</div>
<div class="monster-skeleton-col-60 monster-skeleton-animated">.</div>
<div class="monster-skeleton-col-60 monster-skeleton-animated">.</div>
<div class="monster-skeleton-col-40 monster-skeleton-animated">.</div>
<div class="monster-skeleton-col-30 monster-skeleton-animated">.</div>
<div class="monster-skeleton-col-20 monster-skeleton-animated">.</div>
<div class="monster-skeleton-col-10 monster-skeleton-animated">.</div>

Icons

IconClassDescription
monster-icon-primary-1-infoInfo icon
monster-icon-primary-1-positivPositiv icon
monster-icon-primary-1-negativNegativ icon
monster-icon-primary-1-warningWarning icon
monster-icon-primary-1-neutralNeutral icon
monster-icon-primary-1-questionQuestion icon
monster-icon-primary-1-plusPlus icon
monster-icon-primary-1-dashDash icon
monster-icon-primary-1-gearGear icon
monster-icon-primary-1-homeHome icon
monster-icon-primary-1-counterclockwiseCounterclockwise icon
monster-icon-secondary-1-infoInfo icon
monster-icon-secondary-1-positivPositiv icon
monster-icon-secondary-1-negativNegativ icon
monster-icon-secondary-1-warningWarning icon
monster-icon-secondary-1-neutralNeutral icon
monster-icon-secondary-1-questionQuestion icon
monster-icon-secondary-1-plusPlus icon
monster-icon-secondary-1-dashDash icon
monster-icon-secondary-1-gearGear icon
monster-icon-secondary-1-homeHome icon
monster-icon-secondary-1-counterclockwiseCounterclockwise icon
monster-icon-tertiary-1-infoInfo icon
monster-icon-tertiary-1-positivPositiv icon
monster-icon-tertiary-1-negativNegativ icon
monster-icon-tertiary-1-warningWarning icon
monster-icon-tertiary-1-neutralNeutral icon
monster-icon-tertiary-1-questionQuestion icon
monster-icon-tertiary-1-plusPlus icon
monster-icon-tertiary-1-dashDash icon
monster-icon-tertiary-1-gearGear icon
monster-icon-tertiary-1-homeHome icon
monster-icon-tertiary-1-counterclockwiseCounterclockwise icon
monster-icon-success-1Success icon
monster-icon-success-2Success icon
monster-icon-success-3Success icon
monster-icon-success-4Success icon
monster-icon-warning-1Warning icon
monster-icon-warning-2Warning icon
monster-icon-warning-3Warning icon
monster-icon-warning-4Warning icon
monster-icon-error-1Error icon
monster-icon-error-2Error icon
monster-icon-error-3Error icon
monster-icon-error-4Error icon

Usage

This is an <span class="monster-icon-primary-1-info"></span>-Icon.

Create own icon with mixin

@import "@schukai/monster/source/components/style/mixin/icon.pcss";

@mixin icon my-icon {
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' " +
        "width='16' height='16' fill='currentColor' class='bi bi-dash-circle' " +
        "viewBox='0 0 16 16'%3E%3Cpath d='M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0" +
        "1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z'/%3E%3Cpath d='M4 8a.5.5 0 0 1 " +
        ".5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8z'/%3E%3C/svg%3E");
}

Spacing (margin, padding)

CSS-Properties

ClassValue
--monster-space-00
--monster-space-12px
--monster-space-24px
--monster-space-36px
--monster-space-410px
--monster-space-516px
--monster-space-626px
--monster-space-742px

Classes

  • monster-margin-<0, 1, 2, 3, 4, 5, 6, 7>
  • monster-padding-<0, 1, 2, 3, 4, 5, 6, 7>
  • monster-margin-<start, end, top, bottom>-<0, 1, 2, 3, 4, 5, 6, 7>
  • monster-padding-<start, end, top, bottom>-<0, 1, 2, 3, 4, 5, 6, 7>

Examples

<div class="monster-padding-5"></div>
<div class="monster-padding-start-5"></div>

Form

The form is the most important element for user interaction. It is used to collect data from the user and send it to the server.

In the following example, the form is styled with the monster components.

<main class="monster-color-primary-1">
    <form class="monster-form">
        <label for="msg">Your message:
            <textarea id="msg2" name="user_message"></textarea>
        </label>
        <fieldset>
            <legend>Personal Information</legend>
            <label for="name">from
                <input type="text" id="na3me" name="user_name"/></label>
            <label for="mail">reply:
                <input type="email" id="ma3il" name="user_email"/>
            </label>
            <label for="msg">Your message:
                <textarea id="ms1g" name="user_message"></textarea>
            </label>
        </fieldset>
        <fieldset>
            <legend>Detasil Information</legend>
            <div id="from">
                <label for="name">from:</label>
                <input type="text" id="name" name="user_name"/>
            </div>
            <div id="reply">
                <label for="mail">reply:</label>
                <input type="email" id="mail" name="user_email"/>
            </div>
            <div id="message">
                <label for="msg">Your message:</label>
                <textarea id="msg" name="user_message"></textarea>
            </div>
            <div class="button">
                <button type="submit">Send your message</button>
            </div>
        </fieldset>
    </form>
</main>

Here you can see the result in the browser:

Personal Information
Detasil Information

Spinner

The spinner is a CSS class that provides a loading animation. So that the spinner can be used in different situations, it is possible to set the size and the theme and the spinner is not a component.

Usage

<div class="monster-spinner"></div>

Size

You must set the width and height of the spinner.

<div class="monster-spinner" style="width: 100px; height: 100px;"></div>

Themes

Therefor the spinner can be used in different themes.

<div style="display: flex; justify-content: space-around; align-items: center;">
    <div class="monster-spinner monster-theme-primary-1" style="width: 100px; height: 100px;"></div>
    <div class="monster-spinner monster-theme-primary-2" style="width: 100px; height: 100px;"></div>
    <div class="monster-spinner monster-theme-primary-3" style="width: 100px; height: 100px;"></div>
    <div class="monster-spinner monster-theme-primary-4" style="width: 100px; height: 100px;"></div>
</div>

This will result in the following output:

The themes can be used in combination with the monster-theme class.

<div class="monster-theme-secondary-4" style="display: flex; justify-content: space-around; align-items: center;">
    <div class="monster-spinner monster-theme-secondary-1" style="width: 100px; height: 100px;"></div>
    <div class="monster-spinner monster-theme-secondary-2" style="width: 100px; height: 100px;"></div>
    <div class="monster-spinner monster-theme-secondary-3" style="width: 100px; height: 100px;"></div>
    <div class="monster-spinner monster-theme-secondary-4" style="width: 100px; height: 100px;"></div>
</div>

Info

To ensure that the spinner also works well in dark mode, the right combination must always be selected.

Table

A table is a good way to display data in a structured way.


<div class="monster-table-container">
    <table class="monster-table">
        <thead>
        <tr>
            <th>Name</th>
            <th>Number</th>
        </tr>
        </thead>
        <tbody>
        <tr>
            <td>Jackie</td>
            <td>012345</td>
        </tr>
        <tr>
            <td>Lucy</td>
            <td>112346</td>
        </tr>
        <tr>
            <td>David</td>
            <td>493029</td>
        </tr>
        <tr>
            <td>Kerry</td>
            <td>395499</td>
        </tr>
        <tr>
            <td>Steve</td>
            <td>002458</td>
        </tr>
        </tbody>
    </table>
</div>

Now you can see the result in the browser:

Name Number
Jackie 012345
Lucy 112346
David 493029
Kerry 395499
Steve 002458

Color

Color is part of the visual language of a design system. It is used to communicate meaning, organize elements, and create visual interest in designs. Color is also used to create contrast between elements, so that users can easily scan and interact with content.

Theme Colors

The theme colors are listed below. The values must be prefixed with monster-theme-. The colors contain a definition for the background and the text. The color scheme is optimized for display in light and dark mode.

primary-1
primary-2
primary-3
primary-4
primary-disabled-1
primary-disabled-2
primary-disabled-3
primary-disabled-4
secondary-1
secondary-2
secondary-3
secondary-4
tertiary-1
tertiary-2
tertiary-3
tertiary-4
destructive-1
destructive-2
destructive-3
destructive-4
success-1
success-2
success-3
success-4
warning-1
warning-2
warning-3
warning-4
error-1
error-2
error-3
error-4
selection-1
selection-2
selection-3
selection-4

Special colors

<div class="monster-color-neutral-1"></div>

The special colors are listed below. The values must be prefixed with monster-color-. The colors contain a definition for the background or the text.

neutral-1
neutral-2
neutral-3 + bg-color-primary-3
neutral-4 + bg-color-primary-4
neutral-1 + bg-color-secondary-1
neutral-1 + bg-color-secondary-2
neutral-1 + bg-color-secondary-3
neutral-4 + bg-color-secondary-4
neutral-1 + bg-color-secondary-1 + border-primary
neutral-1 + bg-color-secondary-2 + border-color-2
neutral-1 + bg-color-secondary-3 + border-color-3
neutral-4 + bg-color-secondary-4 + border-color-4

Border colors

<div class="monster-border-primary-1"></div>

The border colors are listed below. The values must be prefixed with monster-. The colors contain a definition for the border including the border width and the border style.

border-primary-1
border-primary-2
border-primary-3
border-primary-4
border-secondary-1
border-secondary-2
border-secondary-3
border-secondary-4
border-tertiary-1
border-tertiary-2
border-tertiary-3
border-tertiary-4

Color Properties

References

Cards

A card is a flexible and extensible content container.

<div class="cards">
    <div class="card">
        <img src="./bg.jpg" alt="">
        <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
            labore et dolore magna aliquyam erat, sed diam voluptua.</p>
        <button>button</button>
    </div>
    <div class="card">
        <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
            labore et dolore magna aliquyam erat, sed diam voluptua.</p>
        <button>button</button>
    </div>
    <div class="card">
        <button>button</button>
        <img src="./bg.jpg" alt="">
        <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
            labore et dolore magna aliquyam erat, sed diam voluptua.</p>
        <button>button</button>
    </div>
    <div class="card">
        <h1>Lorem ipsum </h1>
        <button>button</button>
        <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
            labore et dolore magna aliquyam erat, sed diam voluptua.</p>
        <button>button</button>
    </div>
</div>

Button


Button group

A button group is a vertical list of buttons. It is used to group buttons together.

<div class="monster-button-group">
    <button class="">button</button>
    <button class="monster-button-outline-primary">
        monster-button-outline-primary
    </button>
</div>

Button bar

A button bar is a horizontal list of buttons. It is used to group button groups together.

<div class="monster-button-bar">
    <div class="monster-button-group">
        <button class="">button</button>
        <button class="monster-button-outline-primary">
            monster-button-outline-primary
        </button>
    </div>
    <div class="monster-button-group monster-margin-start-4">
        <button class="monster-button-outline-secondary">
            monster-button-outline-secondary
        </button>
        <button class="monster-button-outline-tertiary">
            monster-button-outline-tertiary
        </button>
    </div>
</div>

Badge

Badges are used to highlight an item’s status for quick recognition. They can be used to indicate the status of an item or to draw attention to an item.

monster-badge-primary
monster-badge-primary-pill
monster-badge-secondary
monster-badge-secondary-pill
monster-badge-tertiary
monster-badge-tertiary-pill
monster-badge-destructive
monster-badge-destructive-pill
monster-badge-success
monster-badge-success-pill
monster-badge-warning
monster-badge-warning-pill
monster-badge-error
monster-badge-error-pill

Display & Visibility

The following classes can be used to set the display and visibility properties of an element.

ClassProperty
.blockdisplay: block;
.inlinedisplay: inline;
.inline-blockdisplay: inline-block;
.griddisplay: grid;
.inline-griddisplay: inline-grid;
.flexdisplay: flex;
.inline-flexdisplay: inline-flex;
.hidden, .none, .hidedisplay: none;
.visiblevisibility: visible;
.invisiblevisibility: hidden;

Build CSS styles

The styles are defined as PostCSS files. For this reason, you must parse these files with PostCSS to generate CSS or Javascript files from them.

The following tool is recommended for this purpose: PostCSS.

The following plugins are used in the build script:

#!/usr/bin/env node

import fs from 'fs';
import postcss from 'postcss'; // https://postcss.org/

// https://github.com/postcss/postcss-import
import importCss from 'postcss-import';

// https://github.com/postcss/postcss-mixins
import mixins from 'postcss-mixins';

// https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-nesting
import nesting from 'postcss-nesting';

// https://github.com/csstools/postcss-normalize
import normalize from 'postcss-normalize';

// https://github.com/notiv-nt/postcss-fluid
import fluid from 'postcss-fluid';

// https://github.com/antyakushev/postcss-for
import forStruct from 'postcss-for';

// https://github.com/madeleineostoja/postcss-responsive-type
import responsiveType from 'postcss-responsive-type';

// https://github.com/postcss/autoprefixer
import autoprefixer from 'autoprefixer';

// https://cssnano.co/
import cssnano from 'cssnano'; 

const sourceFile = 'source/main.pcss';

fs.readFile(sourceFile, (err, css) => {
    postcss([
        importCss(), // This plugin should probably 
                     // be used as the first plugin 
                     // of your list.
        mixins,
        nesting(),

        normalize,
        fluid,

        forStruct,
        responsiveType,
        autoprefixer,
        cssnano,
    ])
        .process(css, {from: sourceFile})
        .then(result => {
           console.log(result.css)
        }).catch(err => {
           console.log(err)
        })
})

The plugins do different things. For example, the postcss-normalize creates a CSS file that contains the CSS reset.

By using of the import plugin you can use the CSS instructions and mixin from monster.

@import "@schukai/monster/source/components/style/mixin/button.pcss";

button {
    @mixin button;
}

Read the documentation for each plugin for more details.

You can also use postcss-cli.

npm i -D postcss postcss-cli
postcss src/app.css -o dest/app.css -m

References

  • https://github.com/postcss/postcss-cli
  • https://postcss.org/
  • https://github.com/postcss/postcss-import
  • https://github.com/postcss/postcss-mixins
  • https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-nesting
  • https://github.com/csstools/postcss-normalize
  • https://github.com/notiv-nt/postcss-fluid
  • https://github.com/antyakushev/postcss-for
  • https://github.com/madeleineostoja/postcss-responsive-type
  • https://github.com/postcss/autoprefixer
  • https://cssnano.co/

DOM

The Document Object Model (DOM) is a programming interface for HTML and XML documents. It represents the structure of a document as a tree-like structure, where each node in the tree represents an element, attribute, or text content in the document.

JavaScript provides a set of functions and classes for working with the DOM, including methods for creating, modifying, and querying elements, as well as handling events.

JavaScript’s DOM functions and classes can be divided into several categories:

  • Document: this includes the Document object, which represents the entire HTML or XML document and provides methods for manipulating the structure and content of the document.
  • Element: This includes classes such as HTMLElement, which represent an HTML element and provide methods for manipulating the attributes, content, and style of the element.
  • Event: This includes classes such as Event and EventTarget, which provide methods for processing and responding to events such as clicks, mouse movements, and keystrokes.
  • Node: This includes classes such as Node, which represent a node in the DOM tree and provide methods for processing the node’s parent and child nodes.
  • Selector: These include functions such as document.getElementById(), document.querySelector(), and document.querySelectorAll(), which are used to select elements from the DOM by their ID, class, or tag name.

By using these functions and classes, developers can create dynamic and interactive web pages and develop a variety of web applications.

In this section, we will delve deeper into the functions and classes provided by Monster and provide examples of their usage for manipulating the DOM and handling events.

Form Handling

Forms can be bound to a structure just like other structures via the updater class.

Suppose we have an html form with some controls.

<div>
    <form id="form1">
        <input type="checkbox" name="checkbox">
        <input type="text" name="text">
        <input type="radio" name="radio">

        <select name="select">
            <option>value1</option>
            <option>value2</option>
        </select>

        <textarea name="textarea">
        </textarea>

        <input type="button" name="button">

    </form>
</div>

A new updater is created in this case via the following call.

const updater = new Updater(document.getElementById('form1'));

With the method Updater.getSubject() you can get the structure of the updater. If you want to use an already defined structure, you can pass it to the updater as a second parameter.

let subject =  updater.getSubject();
console.log(subject);

Now we want a click on the checkbox to be mapped in the data structure.

To do this we need to extend the html with the data-monster-bind attribute.

The values or states of controls are mapped to the data structure via this binding.

<div>
    <form id="form1">
        <!-- data-monster-bind added -->
        <input type="checkbox" name="checkbox" data-monster-bind="path:state">
    </form>
</div>

In this case the status of the checkbox is mapped to the key state. If the checkbox is selected the field state contains the value on , otherwise state is undefined.

If you want to use another value instead of on, you can set the attribute value.

<input type="checkbox" name="checkbox" value="checked" data-monster-bind="path:state">

To see the magic the handling must still be switched on.

updater.enableEventProcessing()

Templating

Monster’s updater uses a DOM-based approach. The configuration and the template system are valid and parsable HTML.

The configuration is done via some special attributes with a data-monster- prefix.

Code is always the most informative. So let’s take a look at a complete example right away.

// The first thing to do is to include the Updater class.
import {Updater} from 'https://cdn.skypack.dev/@schukai/monster@latest/source/dom/updater.js';

// Now we prepare the html document.
// This is done here via script, but can also be inserted into the document as pure html. 
// To do this, simply insert the tag <h1 data-monster-replace="path:headline"></h1>.
const body = document.querySelector('body');
const headline = document.createElement('h1');
headline.setAttribute('data-monster-replace','path:headline')
body.appendChild(headline);

// the data structure
let obj = {
    headline: "Go!",
};

// Now comes the real magic. we pass the updater the parent HTMLElement
// and the desired data structure.
const updater = new Updater(body, obj);

// now we get the used data structure. why can't we take the original structure? 
// the updater puts a proxy over the data structure and thus allows to monitor changes.
// We would not see changes to the original object.
const subject = updater.getSubject();

// now start the updater
updater.run();

// Now you can change the data structure and the HTML will follow these changes.
// to illustrate, let's put the change into a timer call.
setTimeout(function(){
    console.log(obj);
    subject['headline'] = "Hello!"

},1000);

We have seen how we can change the content of an htm element. now let’s look at what options are available.

Replace

The simplest manipulation is to replace the content of a HTMLElement.
To do this, simply use the data-monster-replace attribute (see example).

The syntax is quite simple. The result of the attribute pipe is inserted as content of the
HTMLElement. For the processing the Pipe and Transformer class
is used.

If, for example, you have an object x with the structure listed below and want to insert the value of the key b, you write: path:a.b.

The pipe can then be used to apply operators. For example, tolower can be used to convert everything to lowercase.

let x = {
   a: {
      b: "EXAMPLE"
   }
}

this is how it looks as an attribute:

<div data-monster-replace="static:HELLO | tolower"></div>

The result is then the following html:

<div data-monster-replace="static:hello">hello</div>

A full example looks like this:

import {Updater} from 'https://cdn.skypack.dev/@schukai/monster@latest/source/dom/updater.js';
const body = document.querySelector('body');
const headline = document.createElement('h1');
headline.setAttribute('data-monster-replace','static:hello')
body.appendChild(headline);
// result in ↦ <div data-monster-replace="static:hello"></div>

new Updater(body).run(); 

Attributes

Attributes can be added via the data-monster-attributes attribute. The syntax is attribute name followed by
a space and the desired pipe definition.

<div data-monster-attributes="id static:myid">hello</div>

The result is then the following html:

<div id="myid" data-monster-attributes="id static:myid">hello</div>

Multiple attributes can be separated by commas.

<div data-monster-attributes="id static:myid, class static:myclass">hello</div>

Remove

The data-monster-remove attribute can be used to remove html elements. it is important to
note that this cannot be undone. Once removed, nodes will not be reinserted.

This tag is removed via the updater

<div data-monster-remove></div>

Insert

The strongest feature is adding elements to a node.

For this feature you need a template and the data-monster-insert attribute.

The syntax of the attribute is first an id followed by a space. This is then followed by the pipe command.

<ol data-monster-insert="myid path:a"></ol>

Furthermore, you need a template. The template must have the same string as id.

<template id="myid">
   <li data-monster-replace="path:myid | index:id | tostring | prefix:x"></li>
</template>

In this template, we define the structure of the new elements. In this case, the id is taken
from the dataset index:id, converted to a string tostring, and an x is placed in front of it prefix:x.

The values for the corresponding data must be available as an array.

let obj = {
    a: [
        {"id": 1},
        {"id": 2},
        {"id": 3},
        {"id": 4}
    ]
};

Below we have a complete example. Instead of specifying the template <template /> in HTML, it is constructed via
javascript document.createElement('template'). But it is essentially the same.

const body = document.querySelector('body');
const li = document.createElement('li');
li.innerHTML="-/-";
li.setAttribute('data-monster-replace','path:myid | index:id | tostring | prefix:x');

const template = document.createElement('template');
template.setAttribute('id','myid');
template.content.appendChild(li);

body.appendChild(template);

const list = document.createElement('ul');
list.setAttribute('data-monster-insert', 'myid path:a')

body.appendChild(list);

let obj = {
    a: [
        {"id": 1},
        {"id": 2},
        {"id": 3},
        {"id": 4}
    ]
};

const updater = new Updater(body, obj)
updater.run();

The result will be

<ul data-monster-insert="myid path:a">
  <li data-monster-replace="path:a.0 | index:id | tostring | prefix:x" data-monster-insert-reference="myid-0">x1</li>
  <li data-monster-replace="path:a.1 | index:id | tostring | prefix:x" data-monster-insert-reference="myid-1">x2</li>
  <li data-monster-replace="path:a.2 | index:id | tostring | prefix:x" data-monster-insert-reference="myid-2">x3</li>
  <li data-monster-replace="path:a.3 | index:id | tostring | prefix:x" data-monster-insert-reference="myid-3">x4</li>
</ul>

You can easily add and delete values to the array. The DOM will be adjusted accordingly.
The attribute data-monster-insert-reference identifies if the entry already exists.

Components

Web components are a set of technologies that allow developers to create custom, reusable elements for use in Web pages and Web applications. in Web pages and Web applications. These elements, called custom elements, can be created using JavaScript, HTML, and CSS, and are fully functional and can be used just like any other standard HTML element.

Web components are a key aspect of web development because they allow developers to create reusable, modular code that can be easily shared and integrated. code that can be easily shared and integrated with other projects. In addition, because Web Components are part of the Web platform and not tied to a specific framework or library, they are highly portable and can be used in a variety of environments. Overall, Web Components provide a powerful and flexible way to way to build Web applications and create custom, reusable elements for Web pages.

Create your own web component

This section is about how to create your own
Web Component.

Using classes and functions from Monster.

First, we create a class derived from CustomControl. The parent class
CustomControl already implements some functions that will make life in the following
easier.

class Button extends CustomControl {
}

The next step determines which tag the control should get in the HTML.

class Button extends CustomControl {
    static getTag() {
        return "monster-button";
        
    }
}

To be able to configure the control later, we have to create the possibility,
to be able to create options. We can use the structures of the class
CustomControl and only need to create a separate property default.

class Button extends CustomControl {

    // ..... other implementations
    
    get defaults() {
        return Object.assign({}, super.defaults, {})
    }

}

The templates of the control are also defined via this structure. In this way one can the control with a standard and give the user of the control the possibility to adapt the templates. Customize the templates.

So, now let’s get to work on the appearance of the control and create a template for it. We want the button to use a simple HTML5 button.

<button>Hello!</button>

The main template of the button is maintained via the templates.main option.

So, we have to insert the HTML into the default structure introduced above. We can
specify the HTML directly here.

return Object.assign({}, super.defaults, {
    templates: {
        main: `<button>Hello!</button>`
    },
})

With templateMapping we can map key values to the HTML template.

return Object.assign({}, super.defaults, {
    templateMapping: {
        a: "b"
    },
})

To maintain an overview of larger templates, you can alternatively
template into a function and only call up the function here.

return Object.assign({}, super.defaults, {
    templates: {
        main: getTemplate()
    },
})

If we now insert the HTML tag <monster-button></monster-button> into an HTML file we get so far so unspectacular a button.

Screenshot

Now comes the magic. In the DOM there are two important methods that are called when a control is included and removed. When a control is removed.

If a control is hooked into the DOM, the method
connectedCallback is called.

When a control is removed from the DOM, on the other hand, the method disconnectedCallback is called

We implement both methods in our new class.

class Button extends CustomControl {

    // ..... other implementations

    connectedCallback() {
        super.connectedCallback();
    }

    disconnectedCallback() {
        super.disconnectedCallback();
    }
} 

Within these two methods, we can now initialize structures or add and remove event handlers. Adding and removing event handlers.

The CustomControl has two other important methods that can be overridden to initialize, they can be overridden to initialize the control. These two methods have no direct method name, but are hidden behind a symbol key. symbol key.

import {
    assembleMethodSymbol,
    initMethodSymbol,
} from "@schukai/monster/dist/modules/dom/customelement.js";

class Button extends CustomControl {

    // ..... other implementations

    [initMethodSymbol]() {
        super[initMethodSymbol]();
    }

    [assembleMethodSymbol]() {
        super[assembleMethodSymbol]();
    }
} 

The method initMethodSymbol is called directly from the constructor and is used for one-time initialization of internal structures. internal structures.

The method assembleMethodSymbol is called the first time the control is included in the
DOM. If the control is removed and re-included, the assembleMethodSymbol method is called. assembleMethodSymbol` is not called again.

Configure a Monster Control

Many of the components of the Monster Control can be configured. Components are created either by a tag in the HTML code or by the document.createElement method.

Example

The following example shows how to configure the Monster Control.

// Create a new Monster Control
var monster = document.createElement('monster-control');

Configuration

Mittels JavaScript können die Monster Controls über die Methode setOption konfiguriert werden. Dazu muss der Name der Option und der Wert übergeben werden.

monster.setOption('optionName', 'optionValue');

A list of available options can be found in the respective documentation of the component or can be read out using the default property.

const control = document.createElement('monster-control');
console.log(control.default);

There are three ways to configure a Monster Control via HTML.

JSON via an attribute

You can simply pass the JSON as a string to the data-monster-options attribute.

<monster-control data-monster-options='{"optionName": "optionValue"}'></monster-control>

If the JSON is too long or contains special characters, it can be converted to a data URL.

new Monster.Types.DataUrl(btoa(JSON.stringify({
    "optionName": "optionValue"
})),'application/json',true).toString()

JSON via a script tag

But the preferred way is to use a script tag.

<script id="id-for-this-config" type="application/json">
    {
        "optionName": "optionValue"
    }
</script>

<monster-control data-monster-options-selector="#id-for-this-config"></monster-control>

Options via attributes

Almost every option can also be set via an attribute. The name of the attribute begins with data-monster-option- and ends with the name of the option. The value of the attribute is the value of the option.

The name of the option is converted to a property path. It replaces the dashes with dots to form the property path. For example, the attribute ‘data-monster-option-url’ maps to the ‘url’ property in the options object.

With the mapping parameter, the attribute value can be mapped to a different value. For example, the attribute ‘data-monster-option-foo’ maps to the ‘bar’ property in the options object.

The mapping object would look like this:

{
'foo': (value) => value + 'bar'
// the value of the attribute 'data-monster-option-foo' is appended with 'bar'
// and assigned to the 'bar' property in the options object.
// e.g. <div data-monster-option-foo="foo"></div>
'bar.baz': (value) => value + 'bar'
// the value of the attribute 'data-monster-option-bar-baz' is appended with 'bar'
// and assigned to the 'bar.baz' property in the options object.
// e.g. <div data-monster-option-bar-baz="foo"></div>
}

Here is an example of how to configure a Monster Control via attributes.

<monster-my-control data-monster-option-bar-baz="foo"></monster-my-control>

Datatable Components

The datatable component is a component that allows you to display data in a table.

Dataset

The dataset component is a component that allows you to display a data row from a datasource.

Usage

The dataset component needs a datasource to get the data that should be displayed in the table. The datasource can be configured via the data-monster-datasource-selector attribute. The value of the attribute is a selector that points to the datasource component.

<monster-dataset data-monster-datasource-selector="#data1"></monster-dataset>

Overview

ArgumentTypeDefaultDescription
data-monster-indexstring0The index of the row in the datasource.
data-monster-datasource-selectorstringThe selector of the datasource component.

Datatable

The datatable component is a component that allows you to display data in a table. The datatable is build with the css grid system and is therefore very flexible.

Installation

To install the Monster-Datatable custom control, run the following command:

Usage

pnpm i @schukai/monster

Registering the Control

To register the control, import the datatable.mjs file:

import "@schukai/monster/source/components/datatable/datatable.mjs";

This will create an empty datatable without any columns or data.

Adding Columns

To add columns, insert a template with an ID:

<monster-datatable>
    <template id="this-is-a-row-id">
        <div data-monster-mode="fixed" data-monster-sortable="oid" data-monster-head="OID">
            <a data-monster-attributes="href path:this-is-a-row-id.oid | tostring | prefix:#"
               data-monster-replace="path:this-is-a-row-id.oid | tostring">Link</a>
        </div>
        <div>
            <button data-monster-replace="static:doit">Click</button>
        </div>
    </template>
</monster-datatable>
  • The top-level div elements in the template define the columns.
  • The template’s ID must be used in the path: attribute.

Header Attributes

  • data-monster-mode="fixed": Specifies that the column cannot be removed or hidden.
  • data-monster-attributes="href path:this-is-a-row-id.oid | tostring | prefix:#": Adds an href attribute to the element with the value from this-is-a-row-id.oid. The value is passed through the pipe | to tostring and converted to a string. Then, the prefix # is added.
  • data-monster-replace: Replaces the child nodes of an element with the value from the specified path.
  • data-monster-sortable="number": Indicates that the column is sortable by the number property.
  • data-monster-head="Number": Sets the header for the column to the specified name (e.g., “Number”).

Control Options

The Monster-Datatable control accepts various options in the form of a JSON object:

{
  "templates": {
    "main": getTemplate(),
            "emptyState": getEmptyTemplate()
  },
  "datasource": {
    "selector": null
  },
  "mapping": {
    "data": "dataset"
  },
  "data": [],
          "headers": [],
          "responsive": {
    "breakpoint": 800
  },
  "labels": {
    "theListContainsNoEntries": "The list contains no entries"
  },
  "features": {
    "settings": true,
            "footer": true
  },
  "templateMapping": {
    "row-key": null,
            "filter-id": null
  }
}

Here is a description of each option:

  • templates: An object that specifies the main template and the empty state template.

    • main: The main template for the datatable, usually provided by a function such as getTemplate().
    • emptyState: The template to display when the datatable has no data, usually provided by a function such as getEmptyTemplate().
  • datasource: An object that defines the datasource for the datatable.

    • selector: The selector for the datasource, set to null by default.
  • mapping: An object that maps the datatable properties.

    • data: Maps the property name for the dataset, default is “dataset”.
  • data: An array of data objects for the datatable.

  • headers: An array of header objects for the datatable.

  • responsive: An object that defines responsive behavior for the datatable.

    • breakpoint: The pixel width at which the datatable switches to responsive mode, default is 800.
  • labels: An object that defines labels for the datatable.

    • theListContainsNoEntries: The label to display when the datatable has no data, default is “The list contains no entries”.
  • features: An object that enables or disables certain datatable features.

    • settings: Enables or disables the settings feature, default is true.
    • footer: Enables or disables the footer feature, default is true.
  • templateMapping: An object that defines template mapping properties.

    • row-key: The row key mapping, set to null by default.
    • filter-id: The filter ID mapping, set to null by default.

You can also add a footer to the Monster-Datatable by including a div element with a slot=“footer” attribute. Here’s the updated section of the guide:

To add a footer to the Monster-Datatable, insert a div element with the slot=“footer” attribute and the desired content:

<div slot="footer" class="monster-button-group">
    <monster-button>Aktion 1</monster-button>
    <monster-button>Aktion 2</monster-button>
    <monster-button>Aktion 3</monster-button>
</div>

This example creates a footer with a button group containing three buttons labeled “Aktion 1”, “Aktion 2”, and “Aktion 3”. Customize the footer content as needed for your specific use case.

Adding a Pagination Control

To add a pagination control to the Monster-Datatable, insert a div element with the slot=“bar” attribute and a monster-embedded-pagination element:

<div slot="bar" class="monster-button-group">
  <monster-embedded-pagination
          data-monster-datasource-selector="#data1"></monster-embedded-pagination>
</div>

This example adds a pagination control that uses a datasource selector with the ID data1. Customize the datasource selector and other attributes as needed for your specific use case.

Adding a Filter Button and Filter Area

To add a filter button and a filter area to the Monster-Datatable, insert a monster-datatable-filter-button element within the div element with the slot="bar" attribute:

<div slot="bar" class="monster-button-group">
    <monster-embedded-pagination
        data-monster-datasource-selector="#data1"></monster-embedded-pagination>

    <monster-datatable-filter-button data-monster-reference="#my-collapse" data-monster-role="filter-button">Filter</monster-datatable-filter-button>
</div>

This filter button opens a section that contains a filter when clicked. Define the filter area using a monster-collapse element with the appropriate ID and a data-monster-role=“filter-collapse” attribute:

<monster-collapse id="my-collapse" data-monster-role="filter-collapse">
  <div class="flex">
    <monster-datatable-filter id="listfilter1" slot="filter">
      <label data-monster-label="OID" data-monster-template="${value | call:range:oid}" style="display:none">OID <input name="value" type="text"></label>
    </monster-datatable-filter>
  </div>
</monster-collapse>

This example creates a filter area with an input field for filtering by “OID”. Customize the filter area and other attributes as needed for your specific use case.

Adding Data

The datatable component needs a datasource to get the data that should be displayed in the table. The datasource can be configured via the data-monster-datasource-selector attribute. The value of the attribute is a css selector that points to the datasource component.

<monster-datatable data-monster-datasource-selector="#data1"></monster-datatable>

Overview

ArgumentTypeDefaultDescription
idstringThe id of the datatable (necessary for saving the configuration).
data-monster-datasource-selectorstringThe selector of the datasource component.
data-monster-responsive-breakpointstringThe breakpoint at which the table should be responsive.

Columns

The columns of the datatable are defined via a template element. The template element must have the id attribute with the value row.

Every column is defined via a div element. The div element can configure the following attributes:

The headlines of the table are defined via the data-monster-head attribute. The value of the attribute is a json


<div data-monster-head="ID"></div>

The columns of the data table can be localized. For this purpose, the prefix i18n: must be specified in the title attributes data-monster-head.


<div data-monster-head="i18n:myKey"></div>

The alignment of the column is defined via the data-monster-align attribute. The value of the attribute is a css.


<div data-monster-align="center"></div>

When a column is sortable, the data-monster-sortable attribute must be set. The value of the attribute is the name of the column in the datasource.


<div data-monster-sortable="id"></div>

The mode of the datatable can be set via the data-monster-mode attribute. The value of the attribute is a string that can be fixed, visible or hidden. The default value is visible.


<div data-monster-mode="fixed"></div>

Fixed means that the column is always visible. Visible means that the column is visible as long as nothing else has been configured. Hidden means that the column is hidden as long as nothing else has been configured.

The visibility of the columns can be specified when defining the table. The user can show and hide all non-fixed columns.

The settings can be stored in the client if a monster-host component is available on the page.

The data is stored in the indexedDB. Additionally, the datatable needs an ID. This is set via the attribute ‘id’.

<monster-datatable id="my-table"></monster-datatable>

The localization is done via the i18n functions of the monster library.

Overview

ArgumentTypeDefaultDescription
data-monster-headstringindex of columnThe headline of the column.
data-monster-grid-templatestring1frThe css grid template for the column. it is important that the column has a fraction unit.
data-monster-alignstringstartThe css grid align for the column. Valid values are start, center and end.
data-monster-sortablestringThe name of the column in the datasource.
data-monster-modestringvisibleThe mode of the column. Valid values are fixed, visible and hidden.

Layout

The select control can be customized to your own needs. For this purpose, the control can be designed via css.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

#select1::part(popper) {
    background-color: white;
}

The individual parts are shown in the following picture.

Datatable Filter

The <monster-datatable-filter> HTML control is used to define filters for a data table. Within the control, you can create one or more labels, each representing a filter. These labels must be placed inside the control and can include any HTML controls.

Here is an example of a <monster-datatable-filter> control:

<monster-datatable-filter  id="my-filter" slot="filter">
    <label data-monster-label="OID" 
           data-monster-template="${value | call:range:oid}" style="display:none">
      OID <input name="value" type="search"></label>
</monster-datatable-filter>

This defines a filter that can be used to filter data by OID. The filter is hidden by default, but can be selected from the dropdown menu in the data table. The following image shows the filter.

Defining Filter Names

The data-monster-label attribute is used to specify the name of the filter as it will appear in the dropdown menu where users can select filters. In the example above, the data-monster-label attribute is set to “OID”.

Creating Query Parts with Data-Monster-Template

The data-monster-template attribute is used to define how the key and input value are combined to create a query part. For example, using data-monster-template="oid=${value}" and entering the value 1425 would result in the query oid=1425.

In the example provided, the data-monster-template attribute is set to "${value | call:range:oid}", which calculates a range. If a user enters “1425-1430”, the resulting query would be oid>=1425 AND oid<=1430.

This expression takes the input range and converts it into a query that includes both the lower and upper bounds of the range.

Hiding the Filter by Default

The style="display:none" attribute is used to hide the filter initially. This ensures that the filter is not visible until the user selects it from the dropdown menu.

Positioning the Filter in the Data Table

To position the filter within the filter area of the data table, you can include the slot="filter" attribute. This attribute ensures that the filter is displayed in the correct location within the data table.

Layout

The select control can be customized to your own needs. For this purpose, the control can be designed via css.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

Datatable Filter

The <monster-datatable-status> HTML control is used to display the status of a datasource. The status can display the loading state and the error state. The loading state is displayed when the datasource is request data. The error state is displayed when the datasource has an error.

Usage

The <monster-datatable-status> HTML control is used to display the status of a datasource. It should be placed inside the <monster-datatable> HTML control.

<div slot="bar" class="monster-button-group">
   <monster-datasource-status 
           data-monster-option-datasource-selector="#data1"></monster-datasource-status>
   <monster-embedded-pagination
            data-monster-datasource-selector="#data1"></monster-embedded-pagination>
                <monster-datatable-filter-button data-monster-reference="#my-collapse"
                                                 data-monster-role="filter-button">Filter
                </monster-datatable-filter-button>
            </div>
        </div>
    </div>

The data-monster-option-datasource-selector attribute is used to set the datasource. The value of the attribute is a CSS selector. The selector must point to a Monster Datasource HTML control.

Internationalization

The error status can be translated into different languages. Therefore, the monster-datatable-status' component component implements the i18n transformer. For example, if you have the following status: Failed to fetch`, which is usually thrown by the in the datasource, you can add a translation by adding the following code to your HTML file.

<script type="application/json" data-monster-role="translations">
{
  "Failed to fetch": "This is an error message"
}
</script>

Pagination

The dataset pagination component is a component that can be used to paginate the data that is displayed in a datatable component.

Usage

The pagination component needs a datasource to get the data that should be used to calculate the pagination. The datasource can be configured via the data-monster-datasource-selector attribute. The value of the attribute is a selector that points to the datasource component.

<monster-pagination data-monster-datasource-selector="#datasource">
</monster-pagination>

Embedded Pagination

The embedded dataset pagination component is a component that can be used to paginate the data that is displayed in a datatable component. It is derived from the pagination component and can be used in the same way. The only difference is that it has an embedded style.

Usage

The pagination component needs a datasource to get the data that should be used to calculate the pagination. The datasource can be configured via the data-monster-datasource-selector attribute. The value of the attribute is a selector that points to the datasource component.

<monster-embedded-pagination data-monster-datasource-selector="#datasource">
</monster-embedded-pagination>

Datatable Example

The following example shows how to use the datatable component to display data from a REST API.

The rest api is a Monster component that allows you to make REST calls to a REST API.

<script id="id-for-this-config" type="application/json">
    {
        "read": {
            "url": "https://example.com/api/commerce/orders/search?page=${page}",
            "init": {
                "method": "GET",
                "headers": {
                    "Authorization": "Basic secret",
                    "Accept": "application/json"
                }
            },
            "credentials": "include"
        }
    }

</script>
<monster-datasource-rest id="data1" 
                         data-monster-options-selector="#id-for-this-config">
    
</monster-datasource-rest>

After the datasource is configured, the datatable can be configured. The reference to the datasource is made via the data-monster-datasource-selector attribute.

The headlines of the table are defined via the data-monster-head attribute. If no value is defined, the number of the column is used as the headline.

The grid template width is defined via the data-monster-grid-template attribute. The default value is 1fr.

With the data-monster-align attribute, the alignment of the content can be defined. Values are start, center and end. Additionally, the alignment should be defined in the CSS class for the column.

<monster-datatable data-monster-datasource-selector="#data1">
    <template id="row">
        <div data-monster-head="OID" 
             data-monster-grid-template="1fr"
             data-monster-replace="path:row.oid | tostring | 
             prefix:<a href=/> | suffix:</a>"></div>
        <div data-monster-head="ERP" 
             data-monster-replace="path:row.erpCreation"></div>
        <div class="center" data-monster-align="center" 
             data-monster-replace="path:row.orderState"></div>
        <div class="end" data-monster-align="end"
             data-monster-replace="path:row.orderState | tostring 
                       | prefix:<span class=monster-badge-secondary-pill>|
                       suffix:</span>"></div>
        <div data-monster-replace="path:row.orderState"></div>
        <div data-monster-replace="static:this is a static value"></div>
    </template>
</monster-datatable>

If you want to use the i18n component, you can define the translations in a script tag with the data-monster-role attribute.

<script type="application/json" data-monster-role="translations">
    {
        "head1": "Headline 1",
        "head2": "Headline 2",
    }

</script>

In the html template, the data-monster-head attribute is used to define the location of the headline.

<template id="row">
    <div data-monster-head="i18n:head1"></div>
    <div data-monster-head="i18n:head2"></div>
</template>

And now the datatable is ready to use. The pagination can be used to load more data. The reference to the datasource is made via the data-monster-datasource-selector attribute.

<monster-pagination data-monster-datasource-selector="#data1"></monster-pagination>

You also need to include the javascript and css files for the datatable component.

import "@schukai/monster/source/components/datatable/datasource/rest.mjs";
import "@schukai/monster/source/components/datatable/pagination.mjs";
import "@schukai/monster/source/components/datatable/datatable.mjs";

The datatable component uses the following css classes.

import "@schukai/monster/source/components/style/style/color.pcss";
import "@schukai/monster/source/components/style/style/theme.pcss";
import "@schukai/monster/source/components/style/style/table.pcss";
import "@schukai/monster/source/components/style/style/property.pcss";
import "@schukai/monster/source/components/style/style/badge.pcss";
import "@schukai/monster/source/components/style/style/link.pcss";
import "@schukai/monster/source/components/style/style/data-grid.pcss";
import "@schukai/monster/source/components/style/style/property.pcss";

Form component

Web forms are a way for users to enter and submit data on a web page. They are created using HTML and can include a variety of input elements such as text fields, checkboxes, radio buttons, and more.

Web forms are a critical aspect of many websites because they allow users to interact with the site and provide information such as login credentials, contact information, and more.

Create form

Usage

The Form component allows the user to create a form and in interaction with a datasource to change data.

// create element
const form = document.createElement('monster-form');

Input controls

A form needs input fields. These can be easily defined within the tag. Either via Javascript directly or via the markup.

const input = document.createElement('input')
input.setAttribute('name','field');
form.appendChild(input);

via markup

<monster-form>
    <input name="field">
</monster-form>

The formula field ➊ are included as slotted elements in the shadow root ➋.

Datasource

One of the more interesting features of the form is the ability to connect the form to a data source. A datasource has a simple API to read and write an object (see Monster Framework under Datasources).

In this example we use a RestAPI datasource, but other datasources work as well. The example url httpbin.org is a service that provides a simple api with data. This is for this example only. You can of course specify your own api here.

const datasource =  new RestAPI({
  url: 'https://httpbin.org/get'
},{
  url: 'https://httpbin.org/post'
});
form.setOption('datasource', datasource)

In order to see the data as a value in the input field, we must specify the attribute data-monster-attributes.

const input = document.createElement('input')
input.setAttribute('name','field');
input.setAttribute('data-monster-attributes','value path:headers.Host');
form.appendChild(input);

Now we have to report the data back to the datasource. For this we use the attribute data-monster-bind. In this example we write the value in the same field, but we can also choose another field if for example the POST api has a different structure.

input.setAttribute('data-monster-bind','path:headers.Host');

Actions

What is a form without action? To be able to send the changed data we can add a button.

const button = document.createElement('monster-state-button');
// let's give the button a text
button.setOption('labels.button','click!')
// this attribute ensures that the form sets an action handler in the button.
button.setAttribute('data-monster-datasource-handler','write')

button.setOption('actions.click', undefined);

form.appendChild(button);

If we now click on the button, the modified dataset will be sent to the url previously specified in the RestAPI datasource.

Layout

The select control can be customized to your own needs. For this purpose, the control can be designed via css.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

#select1::part(popper) {
    background-color: white;
}

The individual parts are shown in the following picture.

Custom button

Usage

The button control encapsulates a button and serves as a basis for derived controls.

// create element
const button = document.createElement('monster-button');

// insert element into the DOM
document.getElementById('body').appendChild(button);
<monster-button></monster-button>

Slotted Button

The text of the button can be defined either by the option labels.button.

// create element
const button = document.createElement('monster-button');

// insert element into the DOM
document.getElementById('body').appendChild(button);

// Label
button.setOption('labels.button','My Button');

Or by a slot.

<monster-button>My Button</monster-button>

Action

Standard HTML buttons can listen to different events. Since the standard button sits in a shadowRoot the click event is accessible via an option. The component button uses a callback to listen for click events.

To do this, you must pass a callback to the actions.click option.

const button = document.querySelector('monster-button');
button.setOption('actions.click',(event)=>{
  console.log('clicked!');
});

State-Button

The status button is a special form of the button and has an icon to display the status.

You can also define your own statuses. these must be specified in the options.

// create element
const button = document.createElement('monster-state-button');

// insert element into the DOM
document.getElementById('body').appendChild(button);

// Label
button.setOption('labels.button','My Button');

// set state: successful, activity or failed
button.setState('successful');

Or by a slot.

<monster-state-button>My Button</monster-state-button>

Layout

The button control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

monster-button::part(button) {
    background-color: white;
}

The color scheme of the button can be set using CSS class via the options. You should always use a light color scheme for the status button, so that the icon is the icon is clearly visible. When using the standard design, you should always use the Outline variant should always be used.

const button = document.querySelector('monster-button');
button.setOption('classes.button','monster-button-outline-secondary');

if you want to use the standard classes, you have to include the properties, this can be done for example with postcss.

import  "@schukai/monster/source/components/style/style/color.pcss";
import  "@schukai/monster/source/components/style/style/theme.pcss";
import  "@schukai/monster/source/components/style/style/property.pcss";

The individual parts and slots are shown in the following picture.

Confirm button

Usage

The ConfirmButton component enables the display of a confirmation prompt before the final execution of an action.

// create element
const button = document.createElement('monster-confirm-button');
// set label
button.setOption('labels.button', 'click me!');

// insert element into the DOM
document.getElementById('body').appendChild(button);

Add confirm action

The confirm button can be given a function via the actions.confirm option.

button.setOption('actions.confirm', function (event) {
    console.log('confirm');
    button.hideDialog();
});

Add confirm action with state

The state is realized via a process queue.

button.setOption('actions.confirm', function (event) {

    const self = this;
    new Processing(() => {
        self.setState('activity'); // set state
        button.setOption('disabled', true);
    }, 2000, () => { // delay 2000 milliseconds 
        button.hideDialog();
    }).run().then(() => {
        button.setOption('disabled', undefined); // remove state
    });

});

Layout

The confirm-button control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

monster-confirm-button::part(popper) {
    background-color: white;
}

The nested parts can each be addressed via the part name and the subpart name. So the part button is addressable from the confirm button via confirm-button.

monster-confirm-button::part(confirm-button) {
    background-color: white;
}

The individual parts and slots are shown in the following picture.

Popper button

Usage

The PopperButton component enables the display of a form or other content in a pop-up window.

// create element
const button = document.createElement('monster-popper-button');
// set label
button.setOption('labels.button', 'click me!');

// insert element into the DOM
document.getElementById('body').appendChild(button);

Layout

The popper-button control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

monster-confirm-button::part(popper) {
    background-color: white;
}

Message State button

Usage

The MessageStateButton button can be used to display a button with a message. The message is displayed when the method showMessage() is called. The message is hidden when the method hideMessage() is called.

// create element
const button = document.createElement('monster-message-state-button');
// set label
button.setOption('labels.button', 'click me!');

Set Message

The message can be set via the method setMessage(). The message can be a string or an HTML element.

// create element
const button = document.createElement('monster-message-state-button');
// set label
button.setOption('labels.button', 'click me!');
// set message
button.setMessage('This is a message');
// show message
button.showMessage();

Layout

The message-state-button control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

monster-message-state-button::part(popper) {
    background-color: white;
}

The nested parts can each be addressed via the part name and the subpart name. So the part button is addressable from the confirm button via message-state-button.

monster-message-state-button::part(message-state-button) {
    background-color: white;
}

The individual parts and slots are shown in the following picture.

Reload

Usage

The Reload component allows the user to reload a content via URL. The content is reloaded only when the element is in the viewport. The IntersectionObserver API is used.

Im Standard wird der Inhalt nur einmal geladen. Möchte man den Inhalt immer wieder neu Laden, so muss die Option data-monster-reload auf “always” gesetzt werden.

It is important to follow the CORS guidelines.

// reload element
const reload = document.createElement('monster-reload');

// loader content
const defaultContent = document.createElement('div');
defaultContent.setAttribute('data-monster-role','container');
defaultContent.innerHTML='load'
reload.appendChild(defaultContent);

// fetch follow url
reload.setAttribute('data-monster-url',
    'https://monsterjs.org/assets/16-forms-reload-content.html')

// append element 
document.getElementById('example').appendChild(reload);


<monster-reload>
  <div data-monster-role="container">
    LOADER ...
  </div>
</monster-reload>

If the child element has the attribute data-monster-role="container", then the content is replaced with the fetched content.

Events

The following events are fired by the component.

Layout

The tabs control can be customized to your own needs. For this purpose, the control can be designed via css.

The different parts of the control can be designed using CSS.

By default, the Shadow DOM is disabled for this component. You can enable it by setting the option shadowMode: false, to open or closed.

Since the internals of the component are optionally encapsulated in a shadow tree, access is via css pseudo-element parts.

#reload::part(container) {
    background-color: white;
}

The individual parts and slots are shown in the following picture.

Searchable select

Usage

Select component allows user to pick any amount of option from the given data:

// create element
const select = document.createElement('monster-select');

// set multiselect
select.setOption('type', 'checkbox');

// set options
select.setOption('options', [
    {
        value: 'en', label: 'United Kingdom &lt;img width=20
        src = "https://raw.githubusercontent.com/lipis/flag-icon-css/master/flags/4x3/gb.svg" &gt; '},
    {
        value: 'se', label: 'Sverige &lt;img width=20
        src = "https://raw.githubusercontent.com/lipis/flag-icon-css/master/flags/4x3/se.svg" &gt; '},
    {
        value: 'de', label: 'Deutschland &lt;img width=20
        src = "https://raw.githubusercontent.com/lipis/flag-icon-css/master/flags/4x3/de.svg" &gt; '}
]);

// insert element into the DOM
document.getElementById('body').appendChild(select);

Single select

Radios are used for the single selection.

select.setOption('type', 'radio');

Multiselect

Checkboxes are used for multiple selection.

select.setOption('type', 'checkbox');

Import data

The options can be imported from an object. The object can be read in either directly via Select.importOptions() or indirectly via a URL. In the example, a json file is imported via https://monsterjs.org/assets/world.json`.

select.setOption('url', 'https://monsterjs.org/assets/world.json')

Alternatively, the data can also be imported from an object.

select.importOptions([
    {
        "name": "United Kingdom",
        "alpha-2": "GB",
        "country-code": "826",
    },
    {
        "name": "Sweden",
        "alpha-2": "SE",
        "country-code": "752",

    },
    {
        "name": "Germany",
        "alpha-2": "DE",
        "country-code": "276",
    }
]);

The mapping of the data to the options is done using the values defined in the mappings key.

select.setOption('mapping.labelTemplate', '${name} (${alpha-2})')
select.setOption('mapping.valueTemplate', '${country-code}')

If you want to specify a deeper structure, you can do so via selector`.

{
    a: {
        b: {
            c: [
                ....
        ]
        }
    }
}

select.setOption('mapping.selector', 'a.b.c')

It is also possible to filter values. This is done via the filter parameter. Further details on the structure of the map can be found in the Monster documentation.

There is also an example.

select.setOption('mapping.filter', function (value, key) {
    return (value['id'] >= 20) ? true : false
})

Options via DIV elements

The options can also be defined via HTML. The following example shows how to define the options. Important is the monster-value attribute. This is used to define the value of the option. The label is defined by the content of the div.


<monster-select>
    <div monster-value="value1">label-1</div>
    <div monster-value="value2">label-2</div>
    <div monster-value="value3">label-3</div>
</monster-select>

Display selected options

There are two predefined templates for displaying the selected options. The first is the default template.

import {getSelectionTemplate} 
    from '@schukai/monster/source/dom/select.mjs';

select.setOption('templateMapping.selected', 
    getSelectionTemplate())

Selection

The second is the summary template. This template is used to display the selected options in a summary. To configure the summary, the templateMapping.summary option can be used.

Summary

The template can be changed via the templateMapping.selected option should be filled with the template.

import {getSummaryTemplate} from '@schukai/monster/source/dom/select.mjs';

select.setOption('templateMapping.selected', 
    getSummaryTemplate())

You can also define your own template.

select.setOption('templateMapping.selected', 
    "<div>Selected: ...</div>")

With the attribute data-monster-selected-template you can also define the template directly in the HTML. Available templates are summary and selected.

<monster-select data-monster-selected-template="summary">
    
</monster-select>

Features

With the features option, the behavior of the component can be changed. The following features are available.

closeOnSelect

The closeOnSelect feature closes the select control after an option has been selected.

select.setOption('features.closeOnSelect', true)

clearAll

The clearAll feature shows a button to clear all selected options.

select.setOption('features.clearAll', true)

clear

The clear feature shows a button to clear

select.setOption('features.clear', true)

loadOnOpen

The loadOnOpen feature loads the data when the select control is opened.

select.setOption('features.loadOnOpen', true)

Events

The following events are fired by the component.

I18n

The component can be translated into different languages. For this you simply have to translate the corresponding labels. This can be done using the Select.setOption() method.

select.setOption('labels', {
    'cannot-be-loaded': 'The data cannot be loaded',
    'no-options-available': 'No options available'
});

You can also use the translation function. Therefore, the component can be translated via the Select.updateI18n() methods.

const selects = document.querySelector('monster-select')
select.updateI18n();

To see the keys of the translations, you can look at the default values under the labels key.

selects.getOption('labels')
// ↦ { .... }

Plural rules are available for the selection text. These can be set via the labels.summary-text option.

In the following example, the locales are set via an embed provider. First the keys are defined:

<script type="application/json" data-monster-role="translations">
    {
        "summary-text": {
            "zero": "Non sono state selezionate voci",
            "one": ",<span class='monster-badge-primary-pill'>1</span> voce è stata selezionata",
            "other": "Sono state selezionate <span class='monster-badge-primary-pill'>${count}</span> voci"
        }
    }
</script> 

The translations are then assigned to the component.

Embed.assignTranslationsToElement().then(() => {
  select.updateI18n();
});

Layout

The select control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

monster-select::part(popper) {
    background-color: white;
}

The individual parts are shown in the following picture.

State button

Usage

The StateButton button can be used to display a button with a state. The state is displayed when the method setState() is called. The state is hidden when the method removeState() is called.

// create element
const button = document.createElement('monster-state-button');
// set label
button.setOption('labels.button', 'click me!');

Set State

The state can be set via the method setState(). The sate is a string defined in the option. Currently, the following states are defined: activity, successful and failed. More states can be defined in the option.

// create element
const button = document.createElement('monster-state-button');
// set state
button.setState('activity');

The second parameter of the method setState() can be used to define a timeout after which the state is removed. If the timeout is not set, the state is not removed automatically.

// create element
const button = document.createElement('monster-state-button');
// set state
button.setState('activity', 1000);

In this example, the state is removed after 1000 milliseconds.

Remove State

The state can be removed via the method removeState().

// create element
const button = document.createElement('monster-state-button');
// set state
button.setState('activity');
// remove state
button.removeState();

Layout

The state-button control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

Context Error

Display an Icon with a tooltip for error messages.

Usage

The error message can be displayed in two modes: auto and manual. In auto mode, the error message is displayed when the user hovers the icon. In manual mode, the help message is displayed when the you call the showDialog method.

This is a text with a <monster-context-error id="error">
    <div>This is an error message</div>
</monster-context-error> error message.
Hover the icon to see the tooltip.

The result of the above example:

This is a text with a
error message. Hover the icon to see the tooltip.

The message can be set manually by calling the setErrorMessage(msg, show) method.

const error = document.getElementById('error');
error.setErrorMessage('This is an error message').showDialog();

// or

error.setErrorMessage('This is an error message', true);
// the message will be displayed immediately and will not be hidden

// or

error.setErrorMessage('This is an error message', 5000); 
// 5000 is the duration in ms, after which the message will be hidden

If you want to hide the message manually, you can call the resetErrorMessage method.

const error = document.getElementById('error');
error.resetErrorMessage();

To check if the message is currently displayed, you can call the hasErrorMessage method. This do not check if the message is visible, but if the message is set.

const error = document.getElementById('error');
error.hasErrorMessage(); // returns true or false

The control is derived from the popper component, so you can use all the attributes and methods of the popper component.

Internationalization

The error message can be translated into different languages. Therefore, the monster-context-error' component implements the implements the i18n transformer. For example, if you have the following error message: Failed to fetch`, you can add by adding the following code to your HTML file.

<script type="application/json" data-monster-role="translations">
{
  "Failed to fetch": "This is an error message"
}
</script>

Options

AttributeDescriptionTypeAccepted ValuesDefault
modeThe mode of the componentStringauto, manualauto
classes.buttonThe class of the buttonStringmonster-theme-error-2
templates.mainThe template of the componentStringmonster-context-error

Context Help

Display an Icon with a tooltip.

Usage

The help message can be displayed in two modes: auto and manual. In auto mode, the help message is displayed when the user hovers the icon. In manual mode, the help message is displayed when the you call the showDialog method.

This is a text with a <monster-context-help id="help">
    <div>This is a help message</div>
</monster-context-help> help message icon.
Hover the icon to see the tooltip.

The result of the above example:

This is a text with a
help message. Hover the icon to see the tooltip.

Options

AttributeDescriptionTypeAccepted ValuesDefault
modeThe mode of the componentStringauto, manualauto
classes.buttonThe class of the buttonStringmonster-theme-error-2
templates.mainThe template of the componentStringmonster-context-error

Tabs

Usage

The Tabs component allows the user to switch between multiple contents based on a navigation bar. The text for the buttons is formed from the content of the divs. No tab is active.

// tabs        
const tabs = document.createElement('monster-tabs');

// tab1
const tab1 = document.createElement('div');
tab1.innerHTML = 'this is tab 1';
tabs.appendChild(tab1)

// tab2
const tab2 = document.createElement('div');
tab2.innerHTML = 'this is tab 2';
tabs.appendChild(tab2)

// append to document
document.getElementById('example-tzxoiPwe').appendChild(tabs);
<monster-tabs>
    <div>this is tab 1</div>
    <div>this is tab 2</div>
</monster-tabs>

Active Tab

To set a tab active, you need to give the desired div the css class active`.

// tabs        
const tabs = document.createElement('monster-tabs');

// tab1
const tab1 = document.createElement('div');
tab1.innerHTML = 'this is tab 1';
// this tab should be active
tab1.classList.add('active')
tabs.appendChild(tab1)

// tab2
const tab2 = document.createElement('div');
tab2.innerHTML = 'this is tab 2';
tabs.appendChild(tab2)

// append to document
document.getElementById('example').appendChild(tabs);
<monster-tabs>
  <div class=&quot;active&quot;>this is tab 1</div>
  <div>this is tab 2</div>
</monster-tabs>

Tabs with label and icon

To use an explicit text for the button, you can use the data-monster-button-label attribute. If you also want to specify an icon, the attribute data-monster-button-icon` is available.

// tabs        
const tabs = document.createElement('monster-tabs');

// tab1
const tab1 = document.createElement('div');
tab1.innerHTML = 'this is tab 1';
tab1.classList.add('active')
tab1.setAttribute('data-monster-button-label','FIRST');
tabs.appendChild(tab1)

// tab2
const tab2 = document.createElement('div');
tab2.innerHTML = 'this is tab 2';
tab2.setAttribute('data-monster-button-label','SECOND');
tab2.setAttribute('data-monster-button-icon',
    'https://monsterjs.org/monster.png');
tabs.appendChild(tab2)

// append to document
document.getElementById('example').appendChild(tabs);
<monster-tabs>
    <div class=&quot;active&quot; data-monster-button-label=&quot;FIRST&quot;>this is tab 1</div>
    <div data-monster-button-label=&quot;SECOND&quot; 
            data-monster-button-icon=&quot;https://monsterjs.org/monster.png&quot;>
        this is tab 2</div>
</monster-tabs>

Prefix and suffix

If you want to add content before or after the navigation buttons, you can do so using the start and end slots.

// tabs        
const tabs = document.createElement('monster-tabs');

// prefix
const prefix = document.createElement('div');
prefix.innerHTML='this is a <b>prefix</b>';
prefix.setAttribute('slot','start')
tabs.appendChild(prefix);
            
// suffix
const suffix = document.createElement('div');
suffix.innerHTML='this is a <b>suffix</b>';
suffix.setAttribute('slot','end')
tabs.appendChild(suffix);

// tab1
const tab1 = document.createElement('div');
tab1.innerHTML = 'this is tab 1';
tab1.classList.add('active')
tab1.setAttribute('data-monster-button-label','FIRST');
tabs.appendChild(tab1)

// tab2
const tab2 = document.createElement('div');
tab2.innerHTML = 'this is tab 2';
tab2.setAttribute('data-monster-button-label','SECOND');
tabs.appendChild(tab2)

// append to document
document.getElementById('example').appendChild(tabs);
<monster-tabs>
    <div class=&quot;active&quot; data-monster-button-label=&quot;FIRST&quot;>this is tab 1</div>
    <div data-monster-button-label=&quot;SECOND&quot;>this is tab 2</div>
    <div slot=&quot;start&quot;>this is a <b>prefix</b></div>
    <div slot=&quot;end&quot;>this is a <b>suffix</b></div>
</monster-tabs>

Remove tabs

Tabs can be removed from the DOM. To do this, the desired content must have the attribute data-monster-removable. If you add multiple tabs and there is no space for newer tabs, they will be moved to a popup. You can see this by the sign.

// tabs        
const tabs = document.createElement('monster-tabs');

// tab1
const tab1 = document.createElement('div');
tab1.innerHTML = 'this is tab 1';
tab1.classList.add('active')
tab1.setAttribute('data-monster-button-label','FIRST');
tab1.setAttribute('data-monster-removable','true');
tabs.appendChild(tab1)

// tab2
const tab2 = document.createElement('div');
tab2.innerHTML = 'this is tab 2';
tab2.setAttribute('data-monster-button-label','SECOND');
tab2.setAttribute('data-monster-removable','true');
tabs.appendChild(tab2)

// append to document
document.getElementById('example').appendChild(tabs);
<monster-tabs>
    <div class=&quot;active&quot; 
         data-monster-button-label=&quot;FIRST&quot; 
         data-monster-removable=&quot;true&quot;>this is tab 1</div>
    <div data-monster-button-label=&quot;SECOND&quot; 
         data-monster-removable=&quot;true&quot;>this is tab 2</div>
</monster-tabs>

Fetch tab content

The content of a tab can also be fetched by specifying the attribute data-monster-url with the url of the desired content. The tab is loaded only once. If you want to load the tab fresh from the server for each show, you can specify the attribute data-monster-reload.

It is important to follow the CORS guidelines.

// tabs        
const tabs = document.createElement('monster-tabs');

// tab1
const tab1 = document.createElement('div');
tab1.innerHTML = 'this tab will be reloaded';
tab1.classList.add('active')
tab1.setAttribute('data-monster-button-label','FIRST');
tab1.setAttribute('data-monster-url','https://monsterjs.org/assets/15-forms-tabs-content1.html');
tabs.appendChild(tab1)

// tab2
const tab2 = document.createElement('div');
tab2.innerHTML = 'this is tab 2';
tab2.setAttribute('data-monster-button-label','SECOND');
tab2.setAttribute('data-monster-removable','true');
tabs.appendChild(tab2)

// append to document
document.getElementById('example').appendChild(tabs);
<monster-tabs>
    <div class=&quot;active&quot;
         data-monster-button-label=&quot;FIRST&quot;
         data-monster-url=&quot;https://monsterjs.org/assets/15-forms-tabs-content1.html&quot;>this tab will be reloaded</div>
    <div data-monster-button-label=&quot;SECOND&quot;
         data-monster-removable=&quot;true&quot;>this is tab 2</div>
</monster-tabs>

Events

The following events are fired by the component.

Layout

The tabs control can be customized to your own needs. For this purpose, the control can be designed via css.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

#select1::part(popper) {
    background-color: white;
}

The individual parts and slots are shown in the following picture.

parts

Searchable tree select

Usage

The TreeSelect control is derived from Select and therefore inherits all properties and functions. It extends the control by the display of hierarchical data.

const treeselect = document.createElement('monster-tree-select');

// URL
treeselect.setOption('url', 
     'https://monsterjs.org/assets/14-forms-treeselect-data.json');

// Multiselect
treeselect.setOption('type', 'checkbox');

// search for data in dataset
treeselect.setOption('mapping.selector', 'dataset.*');

// define label and key
treeselect.setOption('mapping.labelTemplate', '${localeLabel | index:en}');
treeselect.setOption('mapping.valueTemplate', '${cid | tostring }');

// wich field is the parent ID?
treeselect.setOption('mapping.parentTemplate', 'parentCID');
treeselect.setOption('mapping.idTemplate', 'cid');

// append
document.getElementById('container').appendChild(treeselect);            

Events

The following events are fired by the component.

Layout

The tree select control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

#tab::part(popper) {
    background-color: white;
}

The individual parts are shown in the following picture.

Popper

The popper component is a component that can be used to display a tooltip or a popover.

Usage

<monster-popper id="popper"></monster-popper>

Host Components

The host components are used to create a host for the application. The host is the main container for the web application. it offers several central functions, such as the loading configuration or the loading of the application translations.

Collapse

The collapse component allows you to display a a detailed description. The description is hidden by default and can be displayed by clicking on a button. The button is not part of the component. It must be created by the user.

Usage

Collapse component can be used to display a detailed description. The description is hidden by default.

// create element
const collapse = document.createElement('monster-collapse');

// insert element into the DOM
document.getElementById('body').appendChild(collapse);

Details-Content

The content of the details is defined by the user. The content can be defined as a child element of the collapse component.

<monster-collapse>
    <p>I am the content of the overlay.</p>
</monster-collapse>

It is also possible to load the content from an external file. For this purpose, the reload component is used.

<monster-collapse>
    <monster-reload data-monster-url="./nav.html"></monster-reload>
</monster-collapse>

Accordion

Combine multiple details into one Accordion.

<monster-collapse>
    <div>lorem ipsum dolor st amet, consteitur sadpselit, sed dam noum eiimocie naboeyminvit ut</div>
</monster-collapse>
<monster-collapse>
    <div>ineimad imnimevinam, qusi nostrud exerci tation ullacmorper susicpti lobrotis nsil uta lquiip</div>
</monster-collapse>

If you do not want to use the accordion, you can set the feature flag features.accordion to false.

Events

The following events are fired by the component.

Layout

The select control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

Call Button

The call button component can be used to call a function of a component. The function is called when the button is clicked.

Usage

The call button component search an element with the given reference and calls the function with the given name.

<div id="my-function-host"></div>
<script type="module">
    document.getElementById('my-function-host').myFunction = function () {
        console.log('myFunction called');
    }
</script>
<monster-call-button data-monster-reference="#my-function-host" data-monster-call="myFunction">
    call myFunction
</monster-call-button>

Layout

The call control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

Details

The details component allows you to display a summary and a detailed description.

Usage

Details component can be used to display a summary and a detailed description.

// create element
const details = document.createElement('monster-details');

// insert element into the DOM
document.getElementById('body').appendChild(details);

In order to display the summary, the attribute data-monster-button-label must be set.

Details-Content

The content of the overlay can be set via slotted content. The content is displayed in the body of the summary. In this example, the content is a simple text.

<monster-details>
    <p>I am the content of the overlay.</p>
</monster-details>

It is also possible to load the content from an external file. For this purpose, the reload component is used.

<monster-details>
    <monster-reload data-monster-url="./nav.html"></monster-reload>
</monster-details>

Accordion

Combine multiple details into one Accordion.

<monster-details>
    <div>lorem ipsum dolor st amet, consteitur sadpselit, sed dam noum eiimocie naboeyminvit ut </div>
</monster-details>
<monster-details>
    <div>ineimad  imnimevinam,  qusi nostrud exerci tation ullacmorper susicpti lobrotis nsil uta lquiip</div>
</monster-details>

If you do not want to use the accordion, you can set the feature flag features.accordion to false.

Events

The following events are fired by the component.

Layout

The select control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

To change the color of the open button, the following CSS can be used.

details::part(container) {
    border: 1px solid red;
}

The individual parts are shown in the following picture.

Toggle Button

The toggle button component is a special button that can be used to toggle between two states. The button is derived from the call button component and can be used in the same way.

Usage

The toggle button component search an element with the given reference and calls the function toggle. This is very helpful in combination with the collapse component.

<monster-collapse id="my-collapse">
  <monster-reload data-monster-url="./nav.html"></monster-reload>
</monster-collapse>

<monster-call-button data-monster-reference="#my-collapse">
    toggle
</monster-call-button>

Layout

The toggle control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

Overlay

The overlay component is used to display a modal dialog. It is used by the host component to display the login dialog. Im Standard wird oben links, absolute positioniert, ein Button angezeigt, der das Overlay öffnet. Das Overlay kann auch über den Aufruf der Methode open() geöffnet werden.

Usage

Overlay component allows user to display a modal dialog:

// create element
const select = document.createElement('monster-overlay');

// insert element into the DOM
document.getElementById('body').appendChild(select);

Overlay-Content

The content of the overlay can be set via slotted content. The content is displayed in the body of the overlay. In this example, the content is a simple text.

<monster-overlay>
    <p>I am the content of the overlay.</p>
</monster-overlay>

It is also possible to load the content from an external file. For this purpose, the reload component is used.

<monster-overlay>
    <monster-reload data-monster-url="./nav.html"></monster-reload>
</monster-overlay>

Multiple Overlay-Content

It is also possible to embed multiple overlays. The buttons are positioned absolute, therefore the containing div must be positioned relative.

<div style="position:relative">
    <monster-overlay>
        <monster-reload data-monster-url="./nav.html"></monster-reload>
    </monster-overlay>
</div>

<div style="position:relative">
    <monster-overlay>
        <p>I am the content of the overlay.</p>
    </monster-overlay>
</div>

Events

The following events are fired by the component.

Layout

The select control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

To change the color of the open button, the following CSS can be used.

monster-overlay::part(open) {
    border: 1px solid red;
}

The result is shown in the following picture.

The individual parts are shown in the following picture.

Host

The simple host component is used to create a host for the application. The host is the main container for the web application. This component has no visual representation. It offers several central functions, such as the loading configuration or the loading of the application translations.

Usage

You can embed the host component in your HTML document with the following code.

<monster-host></monster-host>

To add a navigation and a notification area, you can use the following code.

<monster-host>
    <monster-overlay>
        <monster-reload data-monster-url="./nav.html"></monster-reload>
    </monster-overlay>
    <monster-notify></monster-notify>
</monster-host>

onReady

The onReady method can be used to execute code after the host component has been initialized.

const host = document.querySelector('monster-host');
host.onReady(() => {
    console.log('Host is ready');
});

FocusManager

The host component offers a interface to the focus manager. The focus manager is used to manage the focus of the application.

const host = document.querySelector('monster-host');
host.focusManager.focusNext();

ResourceManager

The host component offers a interface to the resource manager. The resource manager is used to load resources such as translations or configuration files.

const host = document.querySelector('monster-host');
host.resourceManager.addStylesheet('https://example.com/style.css');

Translations

The has a interface to get the locale of the application. The locale is used to load the translations of the application.

const host = document.querySelector('monster-host');
host.locale 
// ↦ 'de'

The translations hold the translations of the application.

const host = document.querySelector('monster-host');
host.translations
// ↦ ...

Notifications

With the Host.pushNotification("example") method, you can add a notification to the notification area. The notification area is defined in the HTML document.

To use the notification area, you have to add the following code to your HTML document.

<monster-host>
    <monster-notify></monster-notify>
</monster-host>

Layout

The host control has no visual representation.

Notify Component

The notify component is a simple notification component.

Notify

The notify component encapsulates the notify message component.

Usage

The notify component is a simple graphical display that specifies a notification.

Layout

The notify control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

monster-notify::part(action) {
    background-color: white;
}

The individual parts and slots are shown in the following picture.

Messages

The notify message component is a simple notification message.

Usage

The notify component is a simple graphical display that specifies a notification.

Layout

The message control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

monster-notify-message::part(remove) {
    background-color: white;
}

The individual parts and slots are shown in the following picture.

State component

The components in this group are used to manage the state of an application.

State component

The state component is a simple state display component. It is used to display the current state of the application.

Usage

The status component is a simple graphical display that specifies a structure of elements. The aim of this component is to enable a uniform representation of such displays.

The component is composed of a visual, a heading and a text. Actions (buttons) can also be displayed.

import '@schukai/monster/source/components/form/button.mjs';
import '@schukai/monster/source/components/state/state.mjs';

// state element
const state = document.createElement('monster-state');
state.innerHTML = `  
<svg slot="visual" >...</svg>
<h1>This is a headline</h1>
<p>loreLorem ipsum dolor sit amet, consetetur sadipscing elitr, 
sed diam nonumy eirmod tempor invidunt 

ut labore et dolore magna aliquyam erat, sed diam voluptua. 

At vero eos et accusam et justo duo</p>
<monster-button slot="action" class="monster-button-primary">
  Button
</monster-button>
<monster-button slot="action">Button</monster-button>`;

<monster-state>
    <svg slot="visual" version="1.1" viewBox="0 0 612.41 583.39" xml:space="preserve"
         xmlns="http://www.w3.org/2000/svg">...</svg>
    <h1>This is a headline</h1>
    <p>loreLorem ipsum dolor sit amet, consetetur sadipscing elitr, 
        sed diam nonumy eirmod tempor invidunt ut labore et
        dolore magna aliquyam erat, sed diam voluptua. 
        At vero eos et accusam et justo duo</p>
    <monster-button slot="action" class="monster-button-primary">
        Button
    </monster-button>
    <monster-button slot="action">Button</monster-button>
    `;
</monster-state>

Layout

The state control can be customized to your own needs. For this purpose, the control can be designed via CSS.

The different parts of the control can be designed using CSS. Since the internals of the component are in a shadow tree, access is via css pseudo-element parts.

monster-state::part(action) {
    background-color: white;
}

The individual parts and slots are shown in the following picture.

Log component

The log component can be used to display log messages in the browser.

If no log messages are displayed, then a status dialog appears.

As log messages are added, they are displayed in the log component.

log.addEntry(new Entry({
    message: "add some entries",
    date: "2020-01-01",
    title: "the first title",
    user: "the user",
}))

If you have only one message, you can add it with the log.addMessage(message, date) method.

log.addMessage("this is a log message", "2020-01-01");
// if no date is specified, the current date is used
log.addMessage("this is a log message");

Example

<monster-log id="my-log"></monster-log>

<script>
    const log = document.getElementById("my-log");

    log2.addEntry(new Entry({
      message:"add some entries",
      date: "2020-01-01",
      title: "the first title",
      user: "the user",
    }))
    log2.addEntry(new Entry({
      message:"I have been doing it" ,
      date: "2021-12-12 16:15:14",
      title: "next title",
      user: "administrator",
    }))
    log2.addEntry(new Entry({
      message:"an entrie that is very long ...",
      date: "2023-01-01 12:12:12",
      title: "this is the title",
      user: "a customer",
    }))

    log2.addMessage("this is a log message");
</script>

Data

Functions and classes in this section are used to handle data.

Pathfinder

The Pathfinder class is used to access a specific path in a data object.

import {Pathfinder} from '@schukai/monster/source/data/pathfinder.mjs';
new Pathfinder({
    a: {
        b: {
            f: [
                {
                    g: false,
                }
            ],
        }
    }
}).getVia("a.b.f.0.g"); // ↦ false

The Pathfinder class is used to access a specific path in a data object. The path is defined as a string. The path is separated by a dot. The path can also be an array of strings. The path can also be a combination of both.

import {Pathfinder} from '@schukai/monster/source/data/pathfinder.mjs';
new Pathfinder({
    a: {
        b: {
            f: [
                {
                    g: false,
                }
            ],
        }
    }
}).getVia(["a", "b", "f", 0, "g"]); // ↦ false

Pipe

A Pipe is a class that is used to process data. The data is processed in a chain of functions. The functions are called in the order in which they were added to the pipe. The data is passed from one function to the next.

import {Pipe} from '@schukai/monster/source/data/pipe.mjs';
import {Pipe} from '@schukai/monster/source/data/pipe.mjs';

let obj = {
    a: {
        b: {
            c: {
                d: "world"
            }
        }
    }
}

console.log(new Pipe('path:a.b.c.d | toupper | prefix:Hello\\ ').run(obj));
// ↦ Hello WORLD

The Pipe class use the Pathfinder class to access the data and the Transformer class to transform the data.

Transformer

The Transformer class is used to transform data. The transformation is defined as a string.

import {Transformer} from '@schukai/monster/source/data/transformer.mjs';

const transformer = new Transformer("tolower")
console.log(transformer.run("HELLO"))
// ↦ hello

The following transformations are available:

commandparameteraliasdescription
callfunction:param1:param2:…Calling a callback function. The function can be defined in three places: either globally, in the context addCallback or in the passed object
concatpath or static:path or static:…This function concatenates the values of the passed paths. If no value in the path is found, the path is used as a static value.
containsChecks if an array or string contains a value (since 3.17)
currencymaximumFractionDigits:roundingIncrementmoneyConvert a currency and amount to a local string (since 3.17)
dateConvert a date string to a localized date string (since 3.16)
datetimeConvert a date string to a localized date-time string (since 3.17)
dayReturns the day of a date (since 3.16)
debugThe passed value is output (console) and returned
defaultvalue:type??If the value is undefined the first argument is returned, otherwise the value. The third optional parameter specifies the desired type. If no type is specified, string is used. Valid types are bool, string, int, float, undefined and object. An object default value must be specified as a base64 encoded json string. (since 1.12)
element-by-idplainAll HTML tags are removed (*)
emptyReturn empty String “”
equalsvalueCompare the comparison value with the specified value and return true if they match.
first-keydefaultCan be applied to objects and returns the value of the first key. All keys of the object are fetched and sorted. (since 1.23)
from-base64atobConverts the value from base64
fromjsonType conversion from a JSON string (since 1.12)
has-entrieshasentriesChecks whether an array or an object has elements. (since 3.17)
hourshourReturns the hours of a date (since 3.16)
ifstatement1:statement2?Is the ternary operator, the first parameter is the valid statement, the second is the false part. To use the current value in the queue, you can set the value keyword. On the other hand, if you want to have the static string “value”, you have to put one backslash \ in front of it and write value. the follow values are true: ‘on’, true, ‘true’. If you want to have a space, you also have to write \ in front of the space.
indexkey:defaultproperty, keyFetches a value from an object, an array, a map or a set
is-arrayisarrayChecks if the value is a array (since 3.17)
is-floatisfloatChecks if the value is a float (since 3.17)
is-nullisnullChecks if the value is null (since 3.17)
is-numberisnumberChecks if the value is a number (since 3.17)
is-objectisobjectChecks if the value is a object (since 3.17)
is-setissetChecks if the value is undefined and not null (since 3.17)
is-undefinedisundefinedChecks if the value is undefined (since 3.17)
last-keydefaultCan be applied to objects and returns the value of the last key. All keys of the object are fetched and sorted. (since 1.23)
lengthcountLength of the string or entries of an array or object
mapkey:value:key:value….Map a value with an existing mapping (since 3.16)
minutesminuteReturns the minutes of a date (since 3.16)
monthReturns the month of a date (since 3.16)
nopDo nothing
notConverts a bolian value into the opposite one (since 3.17)
nth-keyindex:defaultCan be applied to objects and returns the value of the nth key. All keys of the object are fetched and sorted. (since 1.23)
nth-last-keyindex:defaultCan be applied to objects and returns the value of the nth key from behind. All keys of the object are fetched and sorted. (since 1.23)
path-existspathCheck if the specified path is available in the value (since 1.24)
pathpathThe access to an object is done via a Pathfinder object
plaintextplainAll HTML tags are removed (*)
prefixtextAdds a prefix
rawurlencodeURL coding
secondssecondReturns the seconds of a date (since 3.16)
staticnoneThe Arguments value is used and passed to the value. Special characters \ and : can be quotet by a preceding .
substringstart:lengthReturns a substring
suffixtextAdds a suffix
timeConvert a date string to a localized time string (since 3.16)
timestampConvert a date string to a time stamp (since 3.16)
to-base64base64, btobConverts the value to base64
tointegerType conversion to an integer value
tojsonType conversion to a JSON string (since 1.8)
tolowerstrtolower, tolowercaseThe input value is converted to lowercase letters
tostringType conversion to a string.
toupperstrtoupper, touppercaseThe input value is converted to uppercase letters
translationkey:defaulti18nTranslations can be applied. The translations must be stored in the DOM. (*) To use the current value as key the first parameter must be set to undefined.
trimRemove spaces at the beginning and end
ucfirstFirst character large
ucwordsAny word beginning large
undefinedReturn undefined
uniqidCreates a string with a unique value (**)
weekdayReturns the day of the week of a date (since 3.16)
yearConvert a date string to a year (since 3.16)

(*) for this functionality the extension jsdom must be loaded in the nodejs context.

 // polyfill
if (typeof window !== "object") {
    const {window} = new JSDOM('', {
        url: 'http://example.com/',
        pretendToBeVisual: true
    });

    [
        'self',
        'document',
        'Node',
        'Element',
        'HTMLElement',
        'DocumentFragment',
        'DOMParser',
        'XMLSerializer',
        'NodeFilter',
        'InputEvent',
        'CustomEvent'
    ].forEach(key => (global[key] = window[key]));
}

(**) for this command the crypt library is necessary in the nodejs context.

import * as Crypto from "@peculiar/webcrypto";

global['crypto'] = new Crypto.Crypto();

With the method setCallback(name, callback, context) you can define your own transformation functions.

The context parameter is optional and can be used to define the context in which the callback function is called. If no context is specified, the global context is used. In the pipe the name of the callback function is used by prefixing it with a call:.

import {Transformer} from '@schukai/monster/source/data/transformer.mjs';

const transformer = new Transformer("call:myCallback");
transformer.setCallback("myCallback", function (value) {
    return value + " world";
});
console.log(transformer.run("hello")); // hello world

Internationalization

The localization classes and functions support you in dealing with
translations and country-specific settings.

Locale

The Locale class is used to determine the language and country settings.

The method parseLocale() parses a locale string and returns a Locale object.

import {parseLocale} from '@schukai/monster/source/i18n/locale.mjs';
var locale = parseLocale("en-US");
console.log(locale.language); // "en"
console.log(locale.country); // "US"

The Method getLocaleOfDocument() returns the Locale object of the current document.

import {getLocaleOfDocument} from '@schukai/monster/source/dom/locale.mjs';
var locale = getLocaleOfDocument();
console.log(locale.language); // "en"
console.log(locale.country); // "US"

In an HTML document you can set the language and country with the lang attribute.

<html lang="en-US">

The method getLocaleOfDocument() checks for the lang attribute first and takes the browser locale as fallback. If no locale is available, English is taken.

Formatter & Translations

We need the Formatter and Translations class and the parseLocale() function to handle translations.
In the context of the DOM we can also use the getLocaleOfDocument() method.

import {Translations} from '@schukai/monster/source/i18n/translations.mjs';
import {Formatter} from '@schukai/monster/source/text/formatter.mjs';
import {parseLocale} from '@schukai/monster/source/i18n/locale.mjs';
import {getLocaleOfDocument} from '@schukai/monster/source/dom/locale.mjs';

Let’s start with the function parseLocale(). This function can create a Locale object from a string.

So we can create the corresponding Locale object from the string en_GB.

const locale = parseLocale('en_GB')
// ↦ Locale {}

If we move in the browser, so we can also use the function getLocaleOfDocument().
This function returns a locale object as a result.

This function looks if the HTML tag <html lang="en"> has a lang attribute.
If no locale is defined, the default value is assumed to be en.

We now need an object with the translations. For this, we use the Translations class.

We can either define the translations ourselves or load them via an API.

// define translations
const translation = new Translations(parseLocale('en-GB'));
translation.assignTranslations({
           text1: 'hello world!',
           text2: {
             'one': 'click once',
             'other': 'click ${n | tostring} times' // this is where the pipe comes in
           }
        });

// fetch from API
const translation = new Fetch('https://example.com/${language}.json')
    .getTranslation('en-GB');
// ↦ https://example.com/en.json 

If we now have a translation, we can now read the desired strings. For this
we use the method Translation.getText() or the method Translation.getPluralRuleText()
for texts with more than one number.

const message = translation.getText('text1');
// -> hello world

To translate texts with number references, enter the desired number.

let n=1;
const message1 = translation.getPluralRuleText('text2', n);
// -> click once

n=2
const message2 = translation.getPluralRuleText('text2', n);
// -> click ${n} times

To replace the placeholder now, the formatter is used.

const text = new Formatter({n}).format(message2); 
console.log(text)
// ↦ click 2 times

Finally, let’s take a look at the formatter class from the i18n module.

import {Formatter} from 
    "@schukai/monster/source/text/formatter.mjs";

A translation object can be passed directly to this class.

There is also the possibility to pass values in the format string.

// define translation
const translations = new Translations('en')
    .assignTranslations({
        // text with placeholder
        message: "${animal} has eaten the ${food}!"
    });

// without marker and inline values
new Formatter({}, translations).format("message::animal=dog::food=cake")
// ↦ dog has eaten the cake!     

Translation

The Translation class encapsulates strings for a specific locale. It is used to translate strings into a specific language and country.

import {Translation} from '@schukai/monster/source/i18n/translation.mjs';

const translation = new Translation("en-US");
translation.set("hello", "Hello World!");

// plural rules
translation.setText("text6", {
    "zero": "There are no files on Disk.",
        "one": "There is one file on Disk.",
        "other": "There are files on Disk.",
    "default": "There are files on Disk."
});

If you want to assign a complete translation object, you can use the assignTranslations() method.

translation.assignTranslations({
    "hello": "Hello World!",
    "text6": {
        "zero": "There are no files on Disk.",
        "one": "There is one file on Disk.",
        "other": "There are files on Disk.",
        "default": "There are files on Disk."
    }
});

The getText() method returns the translated string for a given key.

translation.getText("hello"); // "Hello World!"

There are also methods for plural rules. The getPluralRuleText() method returns the translated string for a given key and a given number.

translation.getPluralRuleText("text6", 0); // "There are no files on Disk."
translation.getPluralRuleText("text6", 1); // "There is one file on Disk."
translation.getPluralRuleText("text6", 2); // "There are files on Disk."

Document Translation

First, you have to create a new script element with the data-monster-role="translations" and the type="application/json" attribute. The content of the element must be a JSON object.

<script type="application/json" data-monster-role="translations">
    {
        "key1": "translation1",
        "key2": {
            "other": "translation2"
        }
    }
</script> 

Then you have to assign the translations to the document. This can be done with the assignTranslationsToDocument() method. This static method returns a promise. Than you can use the getDocumentTranslations() method to get the translations. Finally, you can use the getText() method to get the translated string.

import { Embed } from "@schukai/monster/source/i18n/providers/embed.mjs";
import { getDocumentTranslations } from "@schukai/monster/source/i18n/translations.mjs";

Embed.assignTranslationsToElement().then(() => {

    const translations = getDocumentTranslations();

    translations.getText('no-key','with-default')
    // ↦ with-default

    translations.getText('key1')
    // ↦ translation1

}).catch((e) => {
// ...
})

Provider

The abstract Provider class is used to provide translations to the application.

import {Provider} from '@schukai/monster/source/i18n/provider.mjs';

Fetch Provider

The FetchProvider class is used to provide translations from a remote server.

import {Fetch} from '@schukai/monster/source/i18n/providers/fetch.mjs';
const provider = new Fetch(
    'https://example.com/translations${language}.json',
    {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json'
        }
    }
);
provider.getTranslations('en-US').then(translations => {
    console.log(translations);
});

The URL can contain the placeholder ${language}, ${script}, ${region}, ${variants}, ${extlang} and ${privateUse}. The placeholders will be replaced with the language, country and locale of the current document.

import {Fetch} from '@schukai/monster/source/i18n/providers/fetch.mjs';

const provider = new Fetch(
    'https://example.com/translations/${language}/${region}.json',
    {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json'
        }
    }
);
provider.getTranslations('en-US').then(translations => {
    console.log(translations);
});

Embed Provider

The EmbedProvider class is used to provide translations from a local tag.

You must add a script tag with the type application/json. This Tag must contain a JSON object with the translations.

<script id="mmylocale" type="application/json">
{
        "key": "translation"
}
</script>

Now you can use the EmbedProvider to get the translations.

import {Embed} from '@schukai/monster/source/i18n/providers/embed.mjs';

const provider = new Embed('mmylocale');
provider.getTranslations('en-US').then(translations => {
    console.log(translations);
});

Text

Functions and classes in this section are used to handle text.

Formatter

The Formatter class allows you to format messages by replacing placeholders with values from an object. It supports nested placeholders, callbacks, and custom markers. The class is part of the Monster.Text module.

Installation

npm install @schukai/monster

Usage

import {Formatter} from '@schukai/monster/source/text/formatter.mjs';

Basic Usage

Create an instance of the Formatter class by passing an object containing the values to be used for formatting. Then, call the format method with a string containing placeholders.

const formatter = new Formatter({
    key: 'value',
    nested: {
        key: 'nested value',
    },
});

const formattedText = formatter.format('This is a ${key} and this is a ${nested.key}');
console.log(formattedText); // Output: "This is a value and this is a nested value"

Nested Placeholders

Placeholders can be nested, allowing you to use the value of an inner placeholder as a key for an outer placeholder.

const text = '${mykey${subkey}}';
const obj = {
    mykey2: '1',
    subkey: '2',
};

const formatter = new Formatter(obj);
console.log(formatter.format(text)); // Output: "1"

Callbacks

You can adjust the values in a formatter using callbacks.

const formatter = new Formatter({x: '1'}, {
    callbacks: {
        quote: (value) => {
            return '"' + value + '"';
        },
    },
});

console.log(formatter.format('${x | call:quote}')); // Output: "\"1\""

Custom Markers

You can customize the markers for the placeholders by calling the setMarker method.


formatter.setMarker('#'); // both open and close markers are #
formatter.setMarker('[', ']');
formatter.setMarker('i18n{', '}');

generateRangeComparisonExpression

This documentation describes the generateRangeComparisonExpression function, its parameters, return value, and an example usage.

generateRangeComparisonExpression(expression, valueName, options = {}) generates a comparison expression for a comma-separated string of ranges and single values.

Parameters

  • expression (string): The string expression containing comma-separated ranges and single values to generate the comparison for.
  • valueName (string): The name of the value to compare against in the generated expression.
  • options (Object, optional): The optional parameters for the function. Defaults to an empty object.
  • urlEncode (boolean, optional): Whether to encode comparison operators for use in a URL. Defaults to false.
  • andOp (string, optional): The logical AND operator to use. Defaults to ‘&&’.
  • orOp (string, optional): The logical OR operator to use. Defaults to ‘||’.
  • eqOp (string, optional): The comparison operator for equality to use. Defaults to ‘==’.
  • geOp (string, optional): The comparison operator for greater than or equal to use. Defaults to ‘>=’.
  • leOp (string, optional): The comparison operator for less than or equal to use. Defaults to ‘<’.

Returns

(string): The generated comparison expression.

Throws

Error: If the input expression contains invalid ranges or values.

Example

const expression = "1,3,5-7";
const valueName = "x";
const comparisonExpression = generateRangeComparisonExpression(expression, valueName);
console.log(comparisonExpression); // "(x==1) || (x==3) || (x>=5 && x<=7)"

Extra Topics

Compatibility

In the monster library, we use current functions and objects for the implementation.
Some functions may not run on older runtimes.

There are several ways to increase compatibility.

One way is Babel and the @babel/preset-env preset.

More information about the browsers supported by Babel can be found in the browserslist project.

Polifyll

As a design decision, we decided against any kind of polyfill in our code. This not only benefits the codebase, but also makes testing easier.

A more effective way to compensate for incompatibilities is to add missing functionality via external polyfills.

To avoid having to search for and include every polyfill yourself, you can use services like polyfill.io. These can inject the missing functions and objects for each browser.

The URL builder can be used to compile the desired polyfills.

You can also automate the creation of the URL. For this you can install the tool create-polyfill-service-url.

With the following call the tool analyzes your script and throws out the desired URL.

npm i create-polyfill-service-url

With the following call the tool analyzes your script and throws out the desired URL.

npx create-polyfill-service-url analyse --file bundle.js

bundle.js is here the file that contains your code.

The result is a URL that you can easily paste into your HTML web page.

For Monster, the following code can currently be used in the header of an HTML page.

Firefox also needs the polyfill construct-style-sheets-polyfill for the monster components for the constructable stylesheets.

<script id="polyfill"
        src="https://polyfill.io/v3/polyfill.min.js?features=Array.prototype.entries,Array.prototype.filter,Array.prototype.forEach,Array.prototype.indexOf,Array.prototype.map,document,Event,fetch,IntersectionObserver,JSON,Map,MutationObserver,Object.assign,Object.entries,Promise,ResizeObserver,Set,String.prototype.trim,Symbol,Symbol.iterator,URL,WeakMap,WeakSet"
        crossorigin="anonymous"
        referrerpolicy="no-referrer"></script>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/es-module-shims.min.js"
        referrerpolicy="no-referrer"
        crossorigin="anonymous"></script>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/adoptedStyleSheets.min.js"
        referrerpolicy="no-referrer"
        crossorigin="anonymous"></script>

References

Contribution Guidelines

General Principles

  • Company-Wide Contributions: We encourage every member of the company to contribute to this main project. Your insights and code make us better.
  • Derived Projects: If you are working on a project derived from this main project and have developed features or fixes beneficial to the main project, please create an issue and submit a merge request.
  • Always Operational: The main project should always be in a fully functional state. This allows any team member to clone the repository and start working without extensive setup.
  • No Half-Baked Submissions: Please only submit completed and thoroughly tested work. If your changes are stable, tag a new version.
  • Documentation: Prior to contributing, please read through the available documentation to understand how the project functions.

Steps for Contributing

  • Create an Issue: Before starting any work, create an issue describing the feature, fix, or improvement. Link the issue to any corresponding projects or discussions as necessary.
  • Branching: Always create a new branch for each issue you are working on.
  • Code Review: Submit a merge request for code review. Make sure your code adheres to our style and quality standards.
  • Tagging: After merging and ensuring stability, tag a new version.

By following these guidelines, we maintain a high standard of quality, reduce the margin of error, and work more cohesively as a team.

Thank you for your contributions.

Troubleshooting

I can’t find the package.json file

The package.json file is located in the root directory of the project. If you can’t find it, you are probably in the wrong directory.

Changelog

This is the changelog for the documentation. The changelog for the code can be found in the repository itself.

2021-11-01

  • Update API documentation links

2023-09-27

  • Fix some script and layout issues

2023-09-24

  • Migrating documentation to mdbook

Imprint

Responsible for the content

schukai GmbH
Eichenstraße 26
82290 Landsberied
Germany

[email protected]
+49-8141-5098888
schukai.com