winbox
    DefinitelyTyped icon, indicating that this package has TypeScript declarations provided by the separate @types/winbox package

    0.2.0 • Public • Published

    WinBox.js: HTML5 Window Manager for the Web.

    Modern window manager for the web: lightweight, outstanding performance, no dependencies, fully customizable, open source!

    Demo  •  Getting Started  •  Options  •  API  •  Themes  •  Customize  •  Changelog

    Live Demo / Code Examples:
    https://nextapps-de.github.io/winbox/

    Getting Started

    Get Latest Stable Build (Recommended):

    Bundle: (all assets bundled into one single file: js + css + html + icons)
    winbox.bundle.js Download https://rawcdn.githack.com/nextapps-de/winbox/0.1.8/dist/winbox.bundle.js

    Non-Bundled: (js and css are separated, css includes icons as base64)
    winbox.min.js Download https://rawcdn.githack.com/nextapps-de/winbox/0.1.8/dist/js/winbox.min.js
    winbox.min.css Download https://rawcdn.githack.com/nextapps-de/winbox/0.1.8/dist/css/winbox.min.css

    Sources: (not bundled at all, images as url to original resources)
    ES6 Modules Download The /src/js folder of this Github repository
    LESS Files (source) Download The /src/css folder of this Github repository
    winbox.css (compiled) Download https://rawcdn.githack.com/nextapps-de/winbox/0.1.8/src/css/winbox.css
    src.zip Download Download all source files including image original resources.

    Get Latest (NPM):

    npm install winbox

    Get Latest Nightly (Do not use for production!):

    Just exchange the version number from the URLs above with "master", e.g.: "/winbox/0.1.8/dist/" into "/winbox/master/dist".

    Use Bundled Version

    The bundled version includes all assets like js, css, html and icon images as base64.

    <html>
    <head>
        <script src="winbox.bundle.js"></script>
    </head>
    <body></body>
    </html>

    Use Non-Bundled Version

    The non-bundled version needs to load js and css separately (css also includes icons as base64).

    <html>
    <head>
        <link rel="stylesheet" href="winbox.min.css">
        <script src="winbox.min.js"></script>
    </head>
    <body></body>
    </html>

    Preload Library / Async Load (Recommended)

    Just add a link tag to the header sections which indicated to preload the script. Right before the body is closing add your site scripts. Depending on your code you may need to load them in the right order.

    <html>
    <head>
        <title></title>
        <link rel="preload" href="winbox.bundle.js" as="script">
    </head>
    <body>
        <!--
        
        HTML CONTENT
        
        -->
        <!-- BOTTOM OF BODY -->
        <script src="winbox.bundle.js" defer></script>
        <!-- YOUR SCRIPT -->
        <script src="my-script.js" defer></script>
    </body>
    </html>

    You can also load the non-bundled version in the same way.

    In rare situations it might produce a short flashing/reflow after page load, depending on your stack. Moving the script tag into the head section will solve this issue. Also try to use the non-bundled version.

    ES6 Modules

    The ES6 modules are located in src/js/. You need to load the stylesheet file explicitly (includes icons as base64).

    <head>
        <link rel="stylesheet" href="dist/css/winbox.min.css">
    </head>
    <script type="module">
      import WinBox from "./src/js/winbox.js";
    </script>

    You can also load modules via CDN, e.g.:

    <script type="module">
      import WinBox from "https://unpkg.com/winbox@0.1.8/src/js/winbox.js";
    </script>

    The ES6 modules are not minified. Please use your favored bundler or build tool for this purpose.

    Overview

    Constructor:

    Global methods:

    Instance methods:

    Instance properties:

    Options

    Option Values Description
    id number | string Set a unique id to the window. Used to define custom styles in css, query elements by context or just to identify the corresponding window instance. If no ID was set it will automatically create one for you.
    index number Set the initial z-index of the window to this value (could be increased automatically when unfocused/focused).
    title string The window title.
    mount HTMLElement Mount an element (widget, template, etc.) to the window body.
    html string Set the innerHTML of the window body.
    url string Open URL inside the window (loaded via iframe).
    width
    height
    number | string Set the initial width/height of the window (supports units "px" and "%").
    minwidth
    minheight
    number | string Set the minimal width/height of the window (supports units "px" and "%").
    x
    y
    number | string Set the initial position of the window (supports: "right" for x-axis, "bottom" for y-axis, "center" for both, units "px" and "%" for both).
    max boolean Automatically toggles the window into maximized state when created.
    top
    right
    bottom
    left
    number | string Set or limit the viewport of the window's available area (supports units "px" and "%").
    background string Set the background of the window (supports all CSS styles which are also supported by the style-attribute "background", e.g. colors, transparent colors, hsl, gradients, background images)
    border number Set the border width of the window (supports all css units, like px, %, em, rem, vh, vmax).
    class string Add one or more classnames to the window (multiple classnames as array or separated with whitespaces e.g. "class-a class-b"). Used to define custom styles in css, query elements by context (also within CSS) or just to tag the corresponding window instance.

    WinBox provides you some useful Built-in Control Classes to easily setup a custom configuration.
    modal boolean Shows the window as modal.
    onmove function(x, y) Callback triggered when the window moves. The keyword this inside the callback function refers to the corresponding WinBox instance.
    onresize function(width, height) Callback triggered when the window resizes. The keyword this inside the callback function refers to the corresponding WinBox instance.
    onclose function(force) Callbacks triggered when the window is closing. The keyword this inside the callback function refers to the corresponding WinBox instance. Note: the event 'onclose' will be triggered right before closing and stops closing when a callback was applied and returns a truthy value.
    onfocus
    onblur
    function() Callbacks to several events. The keyword this inside the callback function refers to the corresponding WinBox instance.
    splitscreen boolean Enable split screen to see two windows side by side by drag at the side the window

    Create and Setup Window

    Basic Window

    When no root was specified the window will append to the document.body.

    new WinBox("Window Title");

    Alternatively:

    WinBox.new("Window Title");

    Alternatively:

    new WinBox({ 
        title: "Window Title" 
    });

    Alternatively:

    var winbox = WinBox();
    winbox.setTitle("Window Title");

    Custom Root

    The root is the unique element in a document where the window will append to. In most cases that is usually the document.body which is the default root. Multiple roots at the same time are just partially supported (they share the same viewport actually).

    new WinBox("Window Title", {
        root: document.body
    });

    Custom Color

    Supports all CSS styles which are also supported by the style-attribute "background", e.g. colors, transparent colors, hsl, gradients, background images.

    new WinBox("Custom Color", {
        background: "#ff005d"
    });

    Alternatively:

    var winbox = new WinBox("Custom Color");
    winbox.setBackground("#ff005d");

    Custom Border

    Supports all units.

    new WinBox({
        title: "Custom Border",
        border: "1em"
    });

    You can also define multiple border values (the order is: top, right, bottom, left):

    new WinBox({
        title: "Custom Border",
        border: "0 1em 15px 1em"
    });

    Custom Viewport

    Define the available area (relative to the document) in which the window can move or could be resized (supports units "px" and "%").

    new WinBox("Custom Viewport", {
        top: "50px",
        right: "5%",
        bottom: 50,
        left: "5%"
    });

    Alternatively (just support numbers!):

    var winbox = new WinBox("Custom Viewport");
    
    winbox.top = 50;
    winbox.right = 200;
    winbox.bottom = 0;
    winbox.left = 200

    Custom Position / Size

    Supports "right" for x-axis, "bottom" for y-axis, "center" for both, units "px" and "%" also for both.

    new WinBox("Custom Viewport", {
        x: "center",
        y: "center",
        width: "50%",
        height: "50%"
    });
    new WinBox("Custom Viewport", {
        x: "right",
        y: "bottom",
        width: "50%",
        height: "50%"
    });

    Alternatively (also supports same units as above):

    var winbox = new WinBox("Custom Viewport");
    
    winbox.resize("50%", "50%")
          .move("center", "center");

    Alternatively (just support numbers!):

    var winbox = new WinBox("Custom Viewport");
    
    winbox.width = 200;
    winbox.height = 200;
    winbox.resize();
    
    winbox.x = 100;
    winbox.y = 100;
    winbox.move();

    Modal Window

    new WinBox({
        title: "Modal Window",
        modal: true
    });

    Themes

    Feel free to create your own themes and share them with us.

    You will find all themes here.

    Load the corresponding css files (or use a bundler), e.g.:

    <head>
        <link rel="stylesheet" href="dist/css/winbox.min.css">
        <link rel="stylesheet" href="dist/css/themes/modern.min.css">
        <script src="dist/js/winbox.min.js"></script>
    </head>

    Just add the name of the theme as a class:

    var winbox = new WinBox({
        title: "Theme: Modern",
        class: "modern"
    });

    Alternatively:

    var winbox = new WinBox("Theme: Modern");
    winbox.addClass("modern");

    You can change themes during the lifetime of the window.

    Manage Window Content

    Set innerHTML

    Do not forget to sanitize any user inputs which is part of the html as this can lead to unintended XSS!

    new WinBox("Set innerHTML", {
        html: "<h1>Lorem Ipsum</h1>"
    });

    Alternatively:

    var winbox = new WinBox("Set innerHTML");
    winbox.body.innerHTML = "<h1>Lorem Ipsum</h1>";

    Mount DOM (Cloned)

    By cloning you can easily create multiple window instances of the same content in parallel.

    <div id="content">
        <h1>Lorem Ipsum</h1>
        <p>Lorem ipsum [...]</p>
    </div>
    var node = document.getElementById("content");
    
    new WinBox("Mount DOM", {
        mount: node.cloneNode(true)
    });

    Alternatively:

    var node = document.getElementById("content");
    var winbox = new WinBox("Mount DOM");
    
    winbox.mount(node.cloneNode(true));

    Mount DOM (Singleton) + Auto-Unmount

    A singleton is a unique fragment which can move inside the document. When creating multiple windows and mounting the same fragment to it, the fragment will leave the old window (see the method above for cloning).

    This workaround is also compatible if you are using server-side rendering.

    You can simply use a hidden backstore to hold contents, as well you can use any other strategy like a templating engine etc.

    <div id="backstore" style="display: none">
        <div id="content">
            <h1>Lorem Ipsum</h1>
            <p>Lorem ipsum [...]</p>
        </div>
    </div>
    var node = document.getElementById("content");
    
    new WinBox("Mount DOM", {
        mount: node
    });

    Auto-Unmount is a great feature which automatically moves back the fragment to the backstore source when closing the window.

    Alternatively:

    var node = document.getElementById("content");
    var winbox = new WinBox("Mount DOM");
    
    winbox.mount(node);

    Explicit Unmount

    <div id="backstore" style="display: none">
        <div id="content">
            <h1>Lorem Ipsum</h1>
            <p>Lorem ipsum [...]</p>
        </div>
    </div>
    <div id="backstore-2" style="display: none"></div>
    var node = document.getElementById("content");
    var winbox = new WinBox("Mount DOM");

    Move fragment from hidden backstore to the window body:

    winbox.mount(node);

    Move fragment back to the hidden backstore source:

    winbox.unmount();

    Or move fragment to another destination:

    winbox.unmount(document.getElementById("backstore-2"));

    Or just auto-unmount as default when closing:

    winbox.close();

    Override default auto-unmount behavior when closing the window:

    new WinBox("Mount DOM", {
        mount: node,
        onclose: function(){
            this.unmount(document.getElementById("backstore-2"));
        }
    });

    Manual Mount

    Feel free to use the winbox.body directly:

    var node = document.getElementById("content");
    var winbox = new WinBox("Mount DOM");
    
    winbox.body.appendChild(node);

    Or delegate it as a root to your templating engine, e.g.:

    Mikado(template).mount(winbox.body).render(data);

    Open URI / URL

    Do not forget to sanitize any user inputs which is part of the url as this can lead to unintended XSS!

    new WinBox("Open URL", {
        url: "https://wikipedia.com"
    });

    You can use every URI scheme which is supported by src attribute, e.g. URL, image or video, base64 encoded data.

    Alternatively:

    var winbox = new WinBox("Open URL");
    winbox.setUrl("https://wikipedia.com");

    The Window Instance

    Window States / Information:

    var winbox = new WinBox();
    
    console.log("Window ID:", winbox.id);
    console.log("Current Maximize State:", winbox.max);
    console.log("Current Minimize State:", winbox.min);

    Window Size:

    var winbox = new WinBox();
    
    winbox.width = 200;
    winbox.height = 200;
    winbox.resize();
    
    console.log("Current Width:", winbox.width);
    console.log("Current Height:", winbox.height);

    Window Position:

    var winbox = new WinBox();
    
    winbox.x = 100;
    winbox.y = 100;
    winbox.move();
    
    console.log("Current Position X:", winbox.x);
    console.log("Current Position Y:", winbox.y);

    Window Viewport:

    var winbox = new WinBox();
    
    winbox.top = 50;
    winbox.right = 50;
    winbox.bottom = 50;
    winbox.left = 50;
    
    
    console.log("Current Viewport Top:", winbox.top);
    console.log("Current Viewport Right:", winbox.right);
    console.log("Current Viewport Bottom:", winbox.bottom);
    console.log("Current Viewport Left:", winbox.left);

    The window body acts like the document.body and has a scroll pane:

    var winbox = new WinBox();
    winbox.body.innerHTML = "<h1>Lorem Ipsum</h1>";

    The parent element of the window body winbox.body.parentNode points to the window most outer root element which also holds the window control and state classes:

    const root = winbox.body.parentNode;
    const hidden = root.classList.contains("hide");
    const focused = root.classList.contains("focus");
    const root = winbox.body.parentNode;
    root.classList.remove("modal");
    root.classList.add("my-theme");

    When changing classes you can use the WinBox built-in methods:

    winbox.removeClass("modal");
    winbox.addClass("my-theme");

    Controls

    var winbox = new WinBox();

    Focus a window (bring up to front):

    winbox.focus();

    Toggle the minimized state of a window:

    winbox.minimize();

    Explicitly set the minimized state of a window:

    winbox.minimize(true);
    winbox.minimize(false);

    Toggle the maximized state of a window:

    winbox.maximize();

    Explicitly set the maximized state of a window:

    winbox.maximize(true);
    winbox.maximize(false);

    Toggle the fullscreen state of a window:

    winbox.fullscreen();

    Explicitly set the fullscreen state of a window:

    winbox.fullscreen(true);
    winbox.fullscreen(false);

    Hide a specific window:

    winbox.hide();

    Show a specific hidden window:

    winbox.show();

    Close and destroy a window:

    winbox.close();

    Chaining Methods

    var winbox = WinBox();
    
    winbox.setTitle("Title")
          .setBackground("#fff")
          .resize("50%", "50%")
          .move("center", "center")
          .mount(document.getElementById("content"));

    When using "center" as position you need to call resize() before move().

    Callbacks

    You can assign callbacks via the option payload when creating a window.

    The keyword this in your callback function refers to the corresponding WinBox Instance.

    var winbox = WinBox({
        onfocus: function(){
            this.setBackground("#fff");
        },
        onblur: function(){
            this.setBackground("#999");
        },
        onresize: function(width, height){
            console.log("width", width);
            console.log("height", height);
        },
        onmove: function(x, y){
            console.log("x", x);
            console.log("y", y);
        },
        onclose: function(force){
            // return "true" to skip the closing
            // return "false" to allow closing
            // use delegated force parameter optionally
            return !confirm("Close window?");
        }
    });

    The "onclose" callback

    The event onclose will be triggered right before closing and stops closing when a callback was applied and returns a truthy value.

    Within your callback function just return true to stops the closing or return false to perform closing as default.

    new WinBox({ 
        onclose: function(){
            // return "true" to skip the closing
            // return "false" to allow closing
            if(do_some_checks()){
                return true;
            }
        } 
    });

    The force parameter from the winbox.close(boolean) will be delegated to your callback function as the first parameter. You need to handle the "force" state in your callback function.

    var winbox = WinBox({ 
        onclose: function onclose(force){
            // use delegated force parameter optionally
            return !force && !confirm("Close window?");
        } 
    });

    Close the window and execute callback as default (will show the prompt from example above):

    winbox.close();

    Force closing the window (does not show the prompt from example above):

    winbox.close(true);

    Custom Splitscreen

    Use the viewport limit to define your own splitscreen areas, e.g. for a simple vertical split:

    new WinBox("Split Left", {
        right: "50%"
    });
    
    new WinBox("Split Right", {
        x: "50%",
        left: "100%" // 100% of its own size
    });

    Same way you can also define custom sizes for each split as well as different grids, e.g.:

    new WinBox("Split Top-Left", { right: "66%", bottom: "50%", max: true });
    new WinBox("Split Bottom-Left", { right: "66%", top: "50%", max: true });
    
    new WinBox("Split Middle", { left: "34%", right: "34%", max: true });
    
    new WinBox("Split Top-Right", { left: "66%", bottom: "50%", max: true });
    new WinBox("Split Bottom-Right", { left: "66%", top: "50%", max: true });

    This looks like this grid:

    ---------------------------------------------
    |             |              |              |
    |             |              |              |
    |  Top Left   |              |  Top right   |
    |             |              |              |
    |             |              |              |
    ---------------    Middle    ----------------
    |             |              |              |
    |             |              |              |
    | Bottom Left |              | Bottom right |
    |             |              |              |
    |             |              |              |
    ---------------------------------------------
    

    Use Control Classes

    WinBox provides you some built-in control classes you can pass when creating a window instance.

    All control classes from this list could be added or removed during lifetime of the window (after creation). State classes like "max", "min" and "focus" could not be changed manually.

    Classname     Description
    no-animation Disables the windows transition animation
    no-shadow Disables the windows drop shadow
    no-header Hide the window header incl. title and toolbar
    no-min Hide the minimize icon
    no-max Hide the maximize icon
    no-full Hide the fullscreen icon
    no-close Hide the close icon
    no-resize Disables the window resizing capability
    no-move Disables the window moving capability

    Also, only this two css-only state classes could be toggled programmatically:

    Classname     Description
    modal Show the window in modal mode
    hide Hide the window

    Without the header the user isn't able to move the window frame. It may be useful for creating fixed popups.

    Pass in classnames when creating the window to apply behaviour:

    const winbox = WinBox({
        class: [
            "no-min",
            "no-max",
            "no-full",
            "no-resize",
            "no-move"
        ]
    });

    The example above is a good start to create classical popups.

    Alternatively you can use a whitespace separated string:

    const winbox = WinBox({
        class: "no-min no-max no-full no-resize no-move"
    });

    You can add or remove all control classes from above along the window's lifetime:

    const winbox = WinBox();
    
    winbox.addClass("no-resize")
          .addClass("no-move");
    winbox.removeClass("no-resize")
          .removeClass("no-move");

    Customize Window

    Additionally, take a look into the themes folder to get some ideas how to customize the window.

    The window boilerplate:

    WinBox Boilerplate

    Hide or disable specific icons:

    .wb-min   { display: none }
    .wb-full  { display: none }
    .wb-max   { display: none }
    .wb-close { display: none }

    Modify a specific icon:

    .wb-max {
        background-image: url(src/img/max.png);
        background-position: center;
        background-size: 15px auto;
    }

    Use black standard icons (useful for bright backgrounds):

    .wb-icon { filter: invert(1) }

    Modify or disable resizing areas on the window borders:

    /* north */
    .wb-n  { display: none }
    
    /* east */
    .wb-e  { display: none }
    
    /* south */
    .wb-s  { display: none }
    
    /* west */
    .wb-w  { display: none }
    
    /* north-west */
    .wb-nw { display: none }
    
    /* north-east */
    .wb-ne { display: none }
    
    /* south-west */
    .wb-sw { display: none }
    
    /* south-east */
    .wb-se { display: none }

    Modify or disable the window drop shadow:

    .winbox { box-shadow: none }

    Style the header title:

    .wb-title { font-size: 12px }

    Style the window background (frame):

    .winbox {
        background: linear-gradient(90deg, #ff00f0, #0050ff);
        border-radius: 12px 12px 0 0;
    }

    Style the body of a window element and set the frame border:

    .wb-body {
        /* the width of window frame border: */
        margin: 4px;
        color: #fff;
        background: #131820;
    }

    The margin of .wb-body corresponds to the width of the window border.

    Apply styles when window is in "minimized" state:

    .winbox {
        border-radius: 10px;
    }
    .winbox.min {
        border-radius: 0;
    }
    .winbox.min .windbox-title {
        font-size: 12px;
    }

    Apply styles when window is NOT in "minimized" state:

    .winbox:not(.min) {
        /* apply styles */
    }

    Apply styles when window is in "maximized" state:

    .winbox {
        border-radius: 10px;
    }
    .winbox.max {
        border-radius: 0;
    }
    .winbox.max .wb-max {
        opacity: 0.5;
    }

    Apply styles when window is NOT in "maximized" state:

    .winbox:not(.max) {
        /* apply styles */
    }

    Apply styles when window is in "fullscreen" state:

    .wb-body:fullscreen {
        /* apply styles */
    }

    Apply styles when window is in "focus" state:

    .winbox {
        background: #999;
    }
    .winbox.focus {
        background: #0050ff; 
    }
    .winbox .wb-icon {
        display: none;
    }
    .winbox.focus .wb-icon {
        display: block;
    }

    Apply styles when window is NOT in "focus" state (the same logic from example above, but shorter):

    .winbox:not(.focus) {
        background: #999;
    }
    .winbox:not(.focus) .wb-icon {
        display: none;
    }

    Apply styles when window is in "modal" state:

    .winbox.modal .wb-close { display: none }

    Customize the modal background overlay:

    .winbox.modal:after {
        background: #0d1117;
        opacity: 0.5;
        animation: none;
    }

    Style Scrollbars

    .wb-body::-webkit-scrollbar {
        width: 12px;
    }
    .wb-body::-webkit-scrollbar-track {
        background: transparent;
    }
    .wb-body::-webkit-scrollbar-thumb {
        border-radius: 10px;
        background: #263040;
    }
    .wb-body::-webkit-scrollbar-thumb:window-inactive {
        background: #181f2a;
    }
    .wb-body::-webkit-scrollbar-corner {
        background: transparent;
    }

    Useful Hints

    Often you need to hide specific content parts when it was mounted to a window. You can solve this easily by using some css:

    .winbox .wb-hide { display: none }

    The same for hiding when NOT inside a window:

    .wb-show { display: none }
    .winbox .wb-show { display: block }

    Now you can add this two classes to any element to control visibility between the two states "inside" and "outside" a window:

    <body>
        <main id="content">
            <header class="wb-hide">Hide this header when in windowed mode</header>
            <section>
                <!-- page contents -->
            </section>
            <footer class="wb-show">Hide this footer when NOT in windowed mode</footer>
        </main>
    </body>

    The property display: block might not fit your needs. That's why this workaround was not added as one of the built-in classes yet. Please change to your desired display-state accordingly.

    new WinBox({
        mount: document.getElementById("content")
    });

    Best Practices

    • Use a non-scrolling body element to get the best user experience on mobile devices.
    • Or provide an alternative view strategy for mobile devices, e.g. when the device is a touch device then open a classical app view. If a mouse pointer is available, then mount this view to the WinBox window. Also, you can place a switch button in your application where the user can also toggle between these two modes.

    WinBox on Angular application

    Step 1: Install WinBox library

    npm i winbox
    

    Step 2: Install WinBox types

    npm i @types/winbox --save-dev
    

    Step 3: Import WinBox in a component

    import { Component } from '@angular/core';
    import 'winbox';
    declare const WinBox: WinBox.WinBoxConstructor;
    
    @Component({
      selector: 'my-app',
      template: '<button (click)="openWindow()">Open Window</button>'
    })
    export class AppComponent {
      openWindow() {
        WinBox.new();
      }
    }

    Custom Builds

    Go to the root directory of WinBox and run:

    npm install

    Perform a build:

    npm run build

    The final build is located in the dist/ folder.


    Copyright 2021 Nextapps GmbH
    Released under the Apache 2.0 License

    Install

    npm i winbox

    DownloadsWeekly Downloads

    704

    Version

    0.2.0

    License

    Apache-2.0

    Unpacked Size

    143 kB

    Total Files

    62

    Last publish

    Collaborators

    • nextapps