0.1.3 • Published 7 years ago

spa-lib v0.1.3

Weekly downloads
6
License
MIT
Repository
github
Last release
7 years ago

SpaLib

Build Status

npm i spa-lib -S
  • Storage (local, session, cookies and indexedDB services)
  • Cache
  • Messenger
  • Observable and ObservableArray
  • Form binding and validation
  • Http (with interceptors)
  • OAuth (Google, Facebook, ...easy to extend)
  • TypeScript Promise polyfill

es6 / TypeScript

Example

import { Observable, TSPromise  } from 'spa-lib';
// or
import * as SpaLib from 'spa-lib';

es5

 <script src="node_modules/spa-lib/dist/spa.lib.js"></script>

Example

var messenger = new SpaLib.Messenger();

Observables

  • Observe value changes
const vm = {
    title: 'My title'
};

// observe an object's property
let observable = new Observable(vm, 'title');
observable.subscribe((value) => {

});

vm.title = 'My new title'; // => valuechanged
  • Observe array changes
let items = ['a', 'b'];
let observableArray = new ObservableArray(items);
observableArray.subscribe((event, value, index) => {
    switch (event) {
        case 'added':

            break;
        case 'removed':

            break;
        case 'filtered':

            break;
        case 'sorted':

            break;
    }
});
// example with push
items.push('c', 'd', 'e');

Support :

  • push
  • unshift
  • splice
  • shift
  • pop
  • sort
  • filter
  • resetFilter

Shorthands

const vm = {
    title: 'My title'
};

observe(vm, 'title', (value) => {

});
let items = ['a', 'b'];

observeArray(items, (event, value, index) => {

});

Form binding and validation

// model
let user = {
    firstname: 'marie',
    lastname: 'bellin',
    email: '',
    age: 20,
    list: '2',
    preference: 'b', 
    likes: ['Milk', 'Cakes'] // binding on array
};

// form config (validation on 'submit' by default or 'valuechanged')
const formConfig = new FormConfig()
    // form element name, validators array, updateType? ('valuechanged' by default or 'lostfocus')
    .addFormElementConfig('firstname', [Validator.required(), Validator.minLength(3)])
    .addFormElementConfig('lastname', [Validator.maxLength(10)])
    .addFormElementConfig('email', [Validator.pattern(/^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/, 'Please enter a valid email.')])
    .addFormElementConfig('age', [Validator.custom((value) => {
        return value > 0 && value < 120;
    }, 'Oops ??')])
    .addFormElementConfig('agree', [Validator.required()]) // validation with an element not in the model (checkbox for example)
    .addFormElementConfig('likes', [Validator.custom(() => {
        return user.likes.length > 0;
    }, 'Please select one or more items.')]);

// form binding
const formBinding = new FormBinding('#myform', user, formConfig);

Note: validation messages are appended to html element on error with css class 'has-error' or 'has-success' (could be desabled with form config).

on validation state changed

formBinding.onStateChanged((element, errors) => {
    console.log('State changed', element, errors);
});

on submit (create a sumary for example)

const sumary: any = document.querySelector('.sumary');
formBinding.onSubmit((response: FormSubmittedResponse) => {
    sumary.innerHTML = '';
    sumary.style.display = 'block';
    if (response.hasError) {
        response.errors.forEach((error: FormElementError) => {
            let p = document.createElement('p');
            p.innerHTML = error.message;
            sumary.appendChild(p);
        });
    }
    else {
        let json = JSON.stringify(response.source);
        sumary.innerHTML = `
            <h2>Ok (refresh on validation state changed)</h2>
            <pre>${json}</pre>
        `;
    }
});

Allow to bind and validate with a simple form (cons: actually interact with the DOM)

<form id="myform" class="form-horizontal">
    <div class="form-group">
        <label class="control-label" for="firstname">Firstname:</label>
        <input class="form-control" type="text" id="firstname" name="firstname" />
    </div>

    <div class="form-group">
        <label class="control-label" for="lastname">Lastname:</label>
        <input class="form-control" type="text" id="lastname" name="lastname" />
    </div>

    <div class="form-group">
        <label class="control-label" for="email">Email:</label>
        <input class="form-control" type="text" id="email" name="email" />
    </div>

    <div class="form-group">
        <label class="control-label" for="age">Age:</label>
        <input class="form-control" type="number" id="age" name="age" />
    </div>

    <div class="form-group">
        <label class="control-label" for="list">List (no validation):</label>
        <select class="form-control" name="list">
                    <option value="1">1</option>
                    <option value="2">2</option>
                    <option value="3">3</option>
                </select>
    </div>

    <div class="form-group">
        <h3>Preference</h3>
        <input type="radio" name="preference" value="a">A<br>
        <input type="radio" name="preference" value="b">B<br>
        <input type="radio" name="preference" value="c">C
    </div>

    <div class="form-group">
        <h3>Like (multiple choice)</h3>
        <input type="checkbox" name="likes" value="Cakes">Cakes<br>
        <input type="checkbox" name="likes" value="Milk">Milk<br>
        <input type="checkbox" name="likes" value="Nutella">Nutella
    </div>
    <br/>
    <div class="checkbox"> <label><input type="checkbox" name="agree">Agree to conditions</label></div>
    <input class="btn btn-default" type="submit" value="Submit" />
</form>

Messenger

let messenger = new Messenger();
// subscribe (one or more arguments)
messenger.subscribe('MyEvent', (result1, result2, result3) => {

});

// publish 
messenger.publish('MyEvent', 'my string', 10, { name: 'my object result' });

Http

Send a request (GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH)

const baseUrl = 'http://jsonplaceholder.typicode.com';
const http = new Http();
const request = new HttpRequest({ url: `${baseUrl}/posts` });
http.send(request).then((response: HttpResponse) => {
    let posts = JSON.parse(response.body);
});
  • Post JSON
const data = {
    title: 'My post',
    body: 'My content'
};
http.post(`${baseUrl}/posts`, JSON.stringify(data)).then((response: HttpResponse) => {
    let post = JSON.parse(response.body);
});
  • Post form
let body = 'title=' + encodeURIComponent('My post') + '&content=' + encodeURIComponent('My content');
const request = new HttpRequest({
    method: 'POST',
    headers: { 'content-type': 'application/x-www-form-urlencoded' },
    url: `${baseUrl}/posts`,
    body
});
http.send(request).then((response: HttpResponse) => {
    let post = JSON.parse(response.body);
});
  • FormData
let data = new FormData();
data.append('id', '101');
data.append('title', 'My post');
data.append('content', 'My content');

const request = new HttpRequest({
    method: 'POST',
    url: `${baseUrl}/posts`,
    body: data
});
http.send(request).then((response: HttpResponse) => {
    let post = JSON.parse(response.body);
});
  • Set a timeout (milliseconds)
const request = new HttpRequest({
    url: `${baseUrl}/posts`,
    timeout: 1000
});
http.send(request).then(() => {

}, (response: HttpResponse) => {
    // handle : 
    // - response with error status code 
    // - xhr error | timeout | abort
});
  • Abort a request
const request = new HttpRequest({ url: `${baseUrl}/posts`});
http.send(request).then(() => { }, (response) => {});
request.abort();
  • Handle progress
const request = new HttpRequest({
    url: `${baseUrl}/posts`,
    progress: (event) => {
        // ...
    }
});
http.send(request).then(() => {});
  • Response type => blob
const request = new HttpRequest({ url: 'http://res.cloudinary.com/romagny13/image/upload/v1464052663/dotnet_oh0ryu.png', responseType: 'blob' });
http.send(request).then((response: HttpResponse) => {

});

REST Shorthands (get,post,put,delete)

const data = {
    title: 'My post',
    body: 'lorem ipsum ...'
};
http.post(`${baseUrl}/posts`, JSON.stringify(data)).then((response: HttpResponse) => {

});
  • put
const data = {
    id: 1,
    title: 'My updated post',
    content: 'My updated content'
};
http.put(`${baseUrl}/posts/1`, JSON.stringify(data)).then((response: HttpResponse) => {
    let post = JSON.parse(response.body);
});
  • delete
http.delete(`${baseUrl}/posts/1`).then((response: HttpResponse) => {

});
  • With an access_token
let access_token = 'ya29.CjCmA3KKBZH7ElidD3j_peoQaPdy2G099Ek6DYuYRfwFqSMXpR3i2_2xSjjHBo6FNNo';
http.get(`${baseUrl}/posts`, access_token).then((response: HttpResponse) => {});

Interceptors

Create an interceptor

http.interceptors.push({
    before(request: HttpRequest, next: Function) {

        next(true); // cancel if false
    },
    after(response: HttpResponse, next: Function) {
        
        next(true);
    }
});

Load

http.load('http://localhost/blog/mytemplate.html', (template) => {

});

OAuth

Look at the OAuth example

TSPromise

Documentation

Cache

// create a cache
const cache = new Cache();
let k = 'mykey';
let item = { name: 'my value' };
// store
cache.store(k, item);
// check
let hasItem = cache.has(k);
// get
let result = cache.retrieve(k);
// save to local storage
let storageKey = '__cache';
cache.save(storageKey);
// restore cache from local storage
cache.restore(storageKey);
// remove an item by key
cache.remove(k);
// clear
cache.clear();

Storage

Cookies

const cookieService = new CookieService();
let name = 'mycookie';
// create a cookie (arguments: name, value, expirationDays, path, domain, secure)
cookieService.set(name, value, 10);
// check
let hasCookie = cookieService.has(name)
// get
let result = cookieService.get(name);
// delete
let result = cookieService.delete(name);
// clear all cookies
cookieService.clear();

Local and session storage

let localService = new StorageService();

let key = 'mykey';
// set
localService.set(key, 'my value'); // value could be an object
// check
let hasItem = localService.has(key)
// get
let item = localService.get(key);
// remove
localService.remove(key);
// clear
localService.clear();
let sessionService = new StorageService('session');

let key = 'mykey';
// set
sessionService.set(key, 'my value'); // value could be an object
// check
let hasItem = sessionService.has(key)
// get
let item = sessionService.get(key);
// remove
sessionService.remove(key);
// clear
sessionService.clear();

indexedDB

MDN

const dbConfigs = [{
    name: 'testdb', // db name
    created: true, // add created and modified fields
    // object stores
    objectStores: [{
        name: 'users',
        key: { keyPath: 'id', autoIncrement: true }, // key
        indexes: [{ name: 'username', definition: { unique: false } }] // indexes
    }]
}];
const indexeddbService = new IndexedDBService(dbConfigs);
// open /create / update the db (if db version is updated)
indexeddbService.openCreateDb('testdb', 1).then((result) => {
 
 // then could get, insert, update,... data

}, (error) => {

});
  • Insert
indexeddbService.insert('users', { userName: 'marie' }).then((result) => {

});
  • get all
indexeddbService.getAll('users').then((result: any[]) => {

});
  • get one
// object store and key
indexeddbService.getOne('users', 1).then((result) => {

};
  • update
let user = {
    userName: 'updated'
};
indexeddbService.update('users', 1, user).then((result) => {

});
  • delete
indexeddbService.delete('users', 1).then((result) => {

});
0.1.3

7 years ago

0.1.2

7 years ago

0.1.1

7 years ago

0.1.0

7 years ago

0.0.8

7 years ago

0.0.7

7 years ago

0.0.6

7 years ago

0.0.5

7 years ago

0.0.4

7 years ago

0.0.3

7 years ago

0.0.2

7 years ago

0.0.1

7 years ago