Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/marcog83/robojs

RoboJS is a library that aims to dynamically load JS modules depending on how the DOM is composed.
https://github.com/marcog83/robojs

dom loader mediator mutationobserver systemjs webcomponents

Last synced: about 2 months ago
JSON representation

RoboJS is a library that aims to dynamically load JS modules depending on how the DOM is composed.

Awesome Lists containing this project

README

        

RoboJS is a library that aims to dynamically load JS modules depending on how the DOM is composed.
Add a node to the DOM and a JS will be loaded!
Remove a node and the JS will be disposed!!
Not further framework frontend , but a tool that lets you manage the association DOM and JS in less than 4k gzipped;

[![NPM](https://nodei.co/npm/robojs.png)](https://nodei.co/npm/robojs/)
[![Greenkeeper badge](https://badges.greenkeeper.io/marcog83/RoboJS.svg)](https://greenkeeper.io/)
[![Build Status](https://travis-ci.org/marcog83/RoboJS.svg?branch=master)](https://travis-ci.org/marcog83/RoboJS)
[![codebeat badge](https://codebeat.co/badges/04be77bb-9247-4988-8499-3711bcbe1485)](https://codebeat.co/projects/github-com-marcog83-robojs-master)
[![Maintainability](https://api.codeclimate.com/v1/badges/73702f345d75cdc37cb7/maintainability)](https://codeclimate.com/github/marcog83/RoboJS/maintainability)
[![Test Coverage](https://api.codeclimate.com/v1/badges/73702f345d75cdc37cb7/test_coverage)](https://codeclimate.com/github/marcog83/RoboJS/test_coverage)
[![Coverage Status](https://coveralls.io/repos/github/marcog83/RoboJS/badge.svg?branch=master)](https://coveralls.io/github/marcog83/RoboJS?branch=master)
[![Inline docs](http://inch-ci.org/github/marcog83/RoboJS.svg?branch=master)](http://inch-ci.org/github/marcog83/RoboJS)
[![NSP Status](https://nodesecurity.io/orgs/marcog83/projects/c8621ee6-fb99-4e5f-ae62-265279409532/badge)](https://nodesecurity.io/orgs/marcog83/projects/c8621ee6-fb99-4e5f-ae62-265279409532)
[![devDependencies Status](https://david-dm.org/marcog83/RoboJS/dev-status.svg)](https://david-dm.org/marcog83/RoboJS?type=dev)
[![Known Vulnerabilities](https://snyk.io/test/github/marcog83/RoboJS/badge.svg?targetFile=package.json)](https://snyk.io/test/github/marcog83/RoboJS?targetFile=package.json)

# The idea behind the code

To understand how and why I decided to write this tool, please read this [post](https://github.com/marcog83/RoboJS/wiki/RoboJS-::-the-idea-behind-the-code)

# Quick Demo
A quick demo can be found [HERE](http://marcog83.github.io/RoboJS/). It simulate a bunch of modules loaded from server and a page where to place them (on the right).

# Installation
```javascript

npm install robojs
```

# How it works.

`robojs` will iterate the DOM trying to match components id with `data-mediator` attributes.
Each time it finds a match, a request is send to load the right script.
The first time the script is loaded from network, while the next one is retrived from cache.
`MutationObserver` is used to handle DOM changes, and when it happens `robojs` iterates over the new added nodes.

# Usage

You set a `data-mediator` attribute with an ID (whatever you want)
```html

a-2


```
in `definitions.js` you define a Map where the key is an ID , and the value is the file to request in order to register the element.

```json
{
"my-mediator": "component/mediator"
}
```

By default `robojs` supposes the presence of an AMD Loader like `RequireJS` in order to request the component and its dependencies.
For example "component/mediator" looks like the follow

```javascript
//mediator.js
define(function(){
return function Mediator(node){
//
}
})

```

When `robojs` finds a match between a `data-mediator` attribute and an ID from `definitions.js`,
it will load `component/mediator.js` file and it will execute the `Mediator` function.
The `node` parameter is a reference to the DOM element.

```javascript
import {bootstrap} from "robojs"
const definitions={
"my-mediator": "component/mediator"
}
//basic usage
bootstrap({definitions}) // return {dispose,promise}

```
you can store, and use later, the returned Object from bootstrap function.
```javascript
import {bootstrap} from "robojs"
const definitions={
"my-mediator": "component/mediator"
};
var application=bootstrap({definitions}) // return {dispose:Function,promise:Promise}

//you can handle when every Mediators in page are executed
application.promise.then(function(){
console.log("all mediators loaded")
}).catch(function(e){
console.log("something went wrong",e);
})

//later in your code you can dispose the RoboJS instance.
application.dispose();
```

# Mediator Function.
Mediator is the context where your logic runs for a specific Mediator. It is a simple function.
When a `data-mediator` attribute matches an ID from the component definitions the `Mediator` function is called and a function returns.

The returned function is called later when the module will be disposed.
`Mediator` function takes two parameters, `node` and `dispatcher`. `node` is a reference to DOM element,
`dispatcher` is a reference to `EventDispatcher` Object.

```javascript

function Mediator(node,dispacther) {
return function(){
// destroy everything, es. handlers
}
}
```

# Loader Object
Default loader is `AMD` based, it means that by default any module should be exported as amd.
You can customize script loading strategy passing a function to `Loader`.

For instance if you use `SystemJS` module loader, you can do something like the follow.

```javascript
import {bootstrap,Loader} from "robojs"
const definitions={
"my-mediator": "component/mediator"
};
//this is the strategy used to load external modules
function loaderFn(id, resolve, reject) {
System.import(id).then(resolve).catch(reject)
}
bootstrap({definitions,loader:Loader(loaderFn)})
```

If you use ES2015 `import` statement, you can create something different.
You don't need to load `Mediator` from external file, but just retrieve the `Mediator` function from `definitions` Map

```javascript
import {bootstrap,Loader} from "robojs"
import Mediator from "./component/mediator";
const definitions={
"my-mediator": Mediator
};

//this is the strategy used to get Mediator from definitions
function loaderFn(id, resolve, reject) {
resolve(definitions[id]);
}

bootstrap({definitions,loader:Loader(loaderFn)});
```

### EventDispatcher Object.
The `EventDispatcher` can be your messaging System. It dispatches and listens to `Events` from your Application.
It's meant to be a Singleton in your application. Every robojs instance has one.

You can get a new instance of EventDispatcher by calling `makeDispatcher` function

```javascript
import {makeDispatcher} from "robojs"
var myNewEventDispatcher=makeDispatcher();
```

## Configurations

Using `RequireJS`

```javascript

requirejs.config({
paths: {
robojs: "../../dist/robojs"
}
});
//
require(["robojs"],({bootstrap})=>{
const definitions={
"my-mediator": "component/mediator"
}
bootstrap({definitions});
});

```
Using `ES2015`

```javascript
import {bootstrap} from "robojs"
const definitions={
"my-mediator": "component/mediator"
};

bootstrap({definitions});

```

Using `SystemJS`


```javascript

System.config({
defaultJSExtensions: true,
paths:{
robojs:"../../dist/robojs"
}
});
//
System.import("robojs").then(({bootstrap})=>{
const definitions={
"my-mediator": "component/mediator"
};

bootstrap({definitions});
});
```

# Dependencies
no dependencies

### Build project
You can run npm script named `build`.

```
npm run build
```
### Test project
from test folder you can run script named `test`.
```
npm run test
```

### Polyfills
If you need to support old browsers, you need to something for

1. [MutationObserver](https://github.com/megawac/MutationObserver.js) by megawac.
2. [Webcomponents](https://github.com/webcomponents). If you use custom element extension.