1.0.1 • Published 2 years ago

wyser v1.0.1

Weekly downloads
-
License
ISC
Repository
github
Last release
2 years ago

Wyser.js

A JavaScript Single Page Application (SPA) Framework

Installation

Intall using npm package manager

npm i wyser

Usage


Src\app.js

import middleware from "./middleware";
import components from "./components";
import tags from "./tags";
import layouts from "./layouts";
import routes from "./routes";
import events from "./events";

export default () => {
    routes();

    components();

    events();

    tags();

    layouts();

    middleware();
};

Src\index.js

import Wyser from 'wyser';
import app from './app.js';

app();

Wyser.load();

Layouts

Define the layout of components to use on page load


Src\layouts.js

import { Layout } from 'wyser';
import { create, div, component, element } from 'wyser/Dom';

export default () => {
    Layout('page.one.layout', create(element(div('root', 'container'), [
        element(component('sidenav')),
        element(div('main', 'container__main'), [
            element(component('header')),
            element(component('page.title')),
            element(component('profile.navigation')),
            element(div('container-main-center', 'container__main__center profile'), [
                element(div('profile-main', 'profile__main'), [
                    element(component('profile.details'))
                ])
            ])
        ])
    ])));

    Layout('page.two.layout', create(element(div('root', 'container'), [
        element(component('sidenav')),
        element(div('main', 'container__main'), [
            element(component('header')),
            element(component('page.title')),
            element(div('container-main-center', 'container__main__center'), [
                element(component('page.stuff'))
            ])
        ])
    ])));
};

Tags

Used for changing content dynamically on page reload


Src\tags.js

import { Tag } from "wyser";

export default () => {
    /**
        tag 'profile.title' will be switched out for 
        component 'author.profile.title' or 'reader.profile.title'
        depending on the URI
    */
    Tag('profile.title', [
        { name: 'author.profile.title', uri: '/a/johndoe/profile' }, // uri (string) | uris (array)
        { name: 'reader.profile.title', uri: '/r/janedoe/profile' } // uri (string) | uris (array)
    ]);
};

Components

Building blocks of the application, they are loaded individually and cached and re-used where necessary


Src\components.js

Creating a standard component

import { Component } from "wyser";

export default () => {
    Component('sidenav', {
        html: '<div>I am sidenav.</div>',
        scope: 'all' // string | array
    });
}

Creating a components with navigation

Components.create('sidenav', {
    html: '<div>I am sidenav.</div>',
    nav: {
        parent: 'sidenav',

        /**
            classes or class that can be clicked | Array | String
        */
        targets: 'sidenav__item',

        /**
            Highlights the main page on a navigation element like a header or sidebar while the current page is within a sub directory
        */
        linkmultiple: {

            /**
                can be named anything really
            */
            mainPage: ['page.main.tab.one', 'page.main.tab.two']
        }
    },

    /**
        The navigation is limited to routes within the scope
    */
    scope: [
        'page.one',
        'page.two'
    ]
});

Properties to take note of

  • nav (Optional) Indicates that a component is of type navigation, makes things easier for the developer in such a way that the Framework detects an active page, adds event listeners, highlights active pages and sub-pages / sub-directories (linkmultiple is required for sub-pages / sub-directories)

  • linkmultiple (Optional) Each sub property like mainPage defined above correspondes to data-linkmultiple on the HTML side of things. The array elements represent sub-pages or sub-directories

  • scope (Optional but required for nav) Navigation is limited to pages defined in the scope

HTML example of a nav component

    <div class="sidenav">
        <div class="sidenav__item" data-linkmultiple="mainPage" data-linkaddress='/u/johndoe/page-one' data-linkactive='sidenav__item--active'>
            <p>Page one</p>
        </div>
        <div class="sidenav__item" data-linkaddress='/u/johndoe/page-two' data-linkactive='sidenav__item--active'>
            <p>Page two</p>
        </div>
    </div>

Routes

Routes are paths where a layout has to be rendered


Src\routes.js

import { Route } from 'wyser';

export default () => {
    Route('page.one', {
        title: 'Page one',
        uri: '/u/:user/page-one',
        tags: ['type.of.tag.one', 'page.name', 'another.tag'],
        layout: 'page.one.layout'
    });

    Route('page.two', {
        title: 'Page two',
        uri: '/u/:user/page-two',
        tags: ['type.of.tag.two', 'page.name', 'another.tag'],
        layout: 'page.two.layput'
    });
};

Route Params. Params can be defined in a route URI and resolved when that route is loaded by the brower

import { Router } from "wyser";

console.log(Router.currentParams); // returns params of the current route

console.log(Router.use('route.name').params) // returns params

Route Tags. Group routes into multiple categories and return their names when they are used

import { Router } from "wyser";
 
export default () => {
    const allRoutes = Router.getRoutesByTag('another.tag');

    console.log(allRoutes[0], allRoutes[1]) // [page.one], [page.two]

    // tags can used to limit components to certain routes effeciently
    Components.create('sidenav', {
        html: '<div>I am sidenav.</div>',

        // attaches on-click events to links
        nav: {
            // highlights relevent icon when on a sub-page
            linkmultiple: {
                links: Router.getRoutesByTag('links'),
                linksTwo: Router.getRoutesByTag('linksTwo')
            }
        },

        // limits 'sidenav' to specified routes
        scope: Router.getRoutesByTag('page.name')
    });
};

Middleware


Middleware functions are run every time before components and routes are loaded

Src\middleware.js

import { Middleware, Singleton } from "wyser";

module.exports = () => {
    // string | array
    Middleware('page.one', async (next) => {
        const response = await fetch('/some-data');

        if (response.data) {
            Singleton.save(
                'someData',
                response.data
            );
        }

        next();
    });
};

Events


Component events, will be fired when something happens to the component, like when it is loaded

Src\events.js

import { Components, Singleton } from 'wyser';

const getSideNav = (someData) => {
    return `<div>Name: ${someData.name}</div>`;
};

export default () => {
    // runs every time before the component has loaded
    Components.use('sidenav').onBeforeLoad((component) => {
        const sidenav =  Singleton.get('someData');

        component.html = sidenav;
    });

    // runs every time after the component has loaded
    Components.use('sidenav').onLoaded((component) => {
        // do stuff
    });
};