es5-ff-spa-loader
=========

A javascript library providing server defined loading of assets for a single page application.

## Installation

  npm --save install es5-ff-spa-loader

  Then use the dist/es5-ff-spa-loader.min.js script inline in the index.

## Features

 * Assets caching for offline use.
 * Assets hashing for fast syncing.
 * Assets types: js,css,dss
 * Caching backends: localStorage,webSqlDB,sqllite,none
 * Multi server/version support by url question ui.
 * Progress indicator ui.
 * Loader error ui.
 * No external dependencies.
 * Technology agnostic booting.
 * Build-in Cordova booting.
 * Build-in AngularJS-1 booting.

## Usage

### Usage Multi Server (Minimal)

	FFSpaLoader.options.server.assets = '/api/path/to/spa/client/resources';
	FFSpaLoader.start();

### Usage Single Server

	FFSpaLoader.options.server.url = 'http://myserver'; // or window.location.href;
	FFSpaLoader.options.server.assets = '/api/path/to/spa/client/resources';
	FFSpaLoader.start();

### Usage Angular

	FFSpaLoader.options.boot.debug.enable = true;
	FFSpaLoader.options.boot.angular.modules.push('exampleUI');
	FFSpaLoader.options.server.url = 'http://myserver';
	FFSpaLoader.options.server.assets = '/api/path/to/spa/client/resources';
	FFSpaLoader.start(function(err) {
		console.log('FFExample.boot done');
	}); 

## Assets format

	{
		"data": {
			"resources": [
			{
				"url": "/static/js/some-asset.js",
				"type": "js",
				"hash": ​-164319899
			},
			{
				"url": "/static/css/some-asset.css",
				"type": "css",
				"hash": ​1391550981
			},
			{
				"url": "/static/css/more-asset-data.css",
				"type": "dss",
				"hash": ​1371811412
			},
        ]
    }

  The hash key is required as only on hash change the resource will be downloaded again, so multiple small files makes updates faster.


## Options

  The available FFSpaLoader.options.* values;

 * boot.debug.enable = Enable debug output. (default: false)
 * boot.debug.handler = Prints/log debug message. (default: console.log)
 * boot.debug.prefix = Debug message prefix. (default: 'FFSpaLoader.')
 * boot.error.enable = Enables the ui error handler. (default: true)
 * boot.error.title = The error title. (default: 'Loader ');
 * boot.cordova.enable = Use deviceready event to boot when cordova is detected. (default: true)
 * boot.cordova.timeout = Boot after (if<0=no-)timeout when deviceready event is not received. (default: -1)
 * boot.cordova.flag = The window flag which is set when cordova is booted. (default: 'FFCordovaDevice')
 * boot.angular.enable = Auto bootstrap angular modules. (default: true)
 * boot.angular.modules = The angular modules to boot. (default: empty)
 * boot.cleanup.enable = Auto cleanup the loader html tags. (default: true)
 * boot.cleanup.timeout = Cleanup after timeout(in ms) so css effects are done. (default: 1000)
 * boot.cleanup.tags = The array of tag ids to remove. (default: empty)
 * server.url = The server url like 'https://myhost', when null the user will get promted to input it. (default: null)
 * server.depath = Strip this path from the server.url needed when the ui has prefix from application root.
 * server.assets = The server path to the assets resources definition file, is required (default: null)
 * server.timeout = The timeout to download the server resources. (default: 4096)
 * server.flag = The window flag which is set when the server.url is know. (default: 'FFServerUrl')
 * server.header.request = An key value object with the request headers. (default: {'X-FFSpaLoader': 'sync'})
 * server.header.response = An key value object with the required response headers. (default: {})
 * question.transport = The transport to prefix the server.url with. (default: 'http://')
 * question.title = The question ui title. (default: 'Server')
 * question.submit = The start button text. (default: 'Start')
 * question.text = The question ui text. (default: 'Please provide the server name;')
 * question.size = The question ui input size. (default: 32)
 * question.validate.min.value = The minimal hostname length, false is disabled (default: 3)
 * question.validate.min.message = The error message (default: 'Server name is to short.')
 * question.validate.max.value = The maximal hostname length, false is disabled (default: 255)
 * question.validate.max.message =The error message (default: 'Server name is to long.')
 * question.validate.regex.value = The regex to validate the hostname, false is disabled. (default: '^([a-zA-Z0-9\.\:])*$')
 * question.validate.regex.message = The error message (default: 'Server name is invalid.')
 * loader.title = The loader title (default: 'Loading Application')
 * loader.footer = The loader footer (default: '© FFSpaLoader')
 * loader.await = The timeout in ms before the loader displays. (default: 250)
 * loader.progres.items.enable = Enables the per item progres. (default: true)
 * loader.progres.items.size = Shorten longer urls to this size. (default: 50)
 * loader.progres.bar.enable = Enables the progres bar. (default: true)
 * loader.progres.bar.percentage = Print percentage's in bar. (default: true) 
 * cache.meta = The cache backend for the meta information(server.url+content), null is auto select,false is disable. (default: null)
 * cache.js = The cache backend for for js, null is auto select,false is disable. (default: null)
 * cache.css = The cache backend for for css, null is auto select,false is disable. (default: null)
 * cache.dss = The cache backend for for dss, null is auto select,false is disable. (default: null)

## Functions

  The functions in FFSpaLoader.*;

 * start(cb) = Starts loading your application, optional function argument can be used for done and/or error callback.
 * clearServerUrl(cb) = Clears the cached server url so after reload user get promted again.
 * clearCache(cb) = Clears the cached values so after reload all assets get refetched.

## Factory

  The available FFSpaLoader.factory.* functions;

 * detect.localStorage() = Checks is localStorage is working.
 * detect.openDatabase() = Checks if openDatabase is defined.
 * detect.sqlitePlugin() = Checks if sqlitePlugin is defined.
 * detect.cordova() = Checks if cordova is defined.
 * detect.cordovaDevice() = Checks if the options.boot.cordova.flag is defined in the window.(NOTE: is always false before calling start();)  
 * cache.localStorage() = Creates an localStorage service.
 * cache.websql(opt) = Creates an websql service.

## Cache Types

  The cache types in FFSpaLoader.options.cache.* store different types data;

 * meta = Stores the server url and server assets.
 * js = Store application javascript data.
 * css = Stores application css data.
 * dss = Stores application css large data like base64 fonts/svg/etc.

## Cache Config

  Per default all cache types are auto selected in the following order;
  
 * detect.sqlitePlugin() and detect.cordovaDevice()
 * detect.openDatabase()
 * detect.localStorage()
 * none
  
  More custom schemas are possible like; (todo: needs testing)
  
	FFSpaLoader.options.cache.meta = false;
	FFSpaLoader.options.cache.js = false;
	FFSpaLoader.options.cache.css = false;
	FFSpaLoader.options.cache.dss = false; 
	
	if (FFSpaLoader.factory.detect.localStorage()) {
		FFSpaLoader.options.cache.css = FFSpaLoader.factory.cache.localStorage();
		FFSpaLoader.options.cache.dss = FFSpaLoader.factory.cache.localStorage();
	}
	FFSpaLoader.options.server.url = 'http://myserver';
	FFSpaLoader.options.server.assets = '/api/path/to/spa/client/resources';
	FFSpaLoader.start();
  

## Example Application

  There is a nodejs example application in the example folder;

 * git clone https://bitbucket.org/im_ik/es5-ff-spa-loader.git
 * cd es5-ff-spa-loader
 * npm install
 * npm start
 
  For the mobile example install+build steps are;
 
 * export ANDROID_HOME=/my/android-sdk/path
 * npm install cordova -g
 * cd es5-ff-spa-loader
 * cd example
 * cd app_mobile
 * cordova platform add android
 * cordova build
 
## Tested Browsers

 * Chromium	46
 * Iceweasel 43
 * Firefox Aurora 45
 * Opera 12 Presto
 * IE 11 Edge
 * Android 5.1.1 in Cordova + Site
 * Android 4.4.4 in Cordova + Site
 * Android 4.2.2 in Cordova + Site

## Todo

 * test in production
 * Add instance websql options so it can also be used in application code.
 * Split assets per type so do js first then boot then css + dss.
 * Add more tests
 * css: set tag.media = 'only you';
 * css: add media in resouces
 * Add in browser tests
 * cache limits for soft fallback to injecting ?
  
## Contributing

In lieu of a formal styleguide, take care to maintain the existing coding style.
Add unit tests for any new or changed functionality. Lint and test your code.

## Release History 

### 0.3.0
* Fixed clearServerUrl() to also clean the cached server resources json.
* Auto clean option.server.url from # and ? endings for: FFSpaLoader.options.server.url = window.location.href;
* Added server.depath option to strip the ui-prefix from the server.url.
* Added auto resetting server.url when is file:// for "Page save as" feature.
* Fixed askUrl to accept host and context path with auto clean/depathing.
* Fixed duplicate starts on askUrl submit multiple clicks.
* Switch to karma + jasmine unit tests.
* Fixed define.amd module constructor.
* Integrated example package.json to main file.
* Removed options.error.[handler|title].
* Added options.boot.error.[enable|title].
* start(cb) function callback now includes error. 
* Moved options.debug.* to options.boot.debug.*.
* Fixed example page/app offline use. (safe page as(html only))

### 0.2.1
* Fixed clearCache method to added json header.
* Added url to non 200 http status error message.
* Added boot.cleanup.tags options.

### 0.2.0
* Moved error.style and question.style to css file.
* Changed dist with extra css/js folder.
* Added loader progress bar.
* refined css so question/loader/error are equal.
* Added response header check support.
* Added json accept header on assets resources list.
* Added cb errors on assets resources json parse + result obj.
* Renamed cssData type to dss for enum easiness.
* Added unknown resource type error.

### 0.1.1
* Moved websql delete timeout to cleanServerlUrl for faster boot.
* Fixed websql db-size and db-name for older androids.
* Added more jsdoc.
* Added question.size option.
* Changed websql option openDatabase to returning open function.
* Fixed sqlitePlugin open function was 2x typo on openDatabase.
* Added websql table option. (defaults to 'cache_store')
* Added clearCache function.
* Fixed removed question div on loader error.
* Updated example and removed it from npm.
* Added cordova app with example.

### 0.1.0
* Moved options.server.question to options.question.
* Added question.validate.[min|max|regex].value|message options.
* Strip question value to hostname+port before use and validating.
* Allow user upgrade to https in question input from default of transport option.
* Added server request headers option.
* Updated css of question and error ui.
* Fixed cordova booting.

### 0.0.4
* Added auto cache clean code.
* Disable cordova timeout per default.
* Remove unused mobileAgent detect.
* Fixed cached resources injection order.

### 0.0.3
* Fixed example script path.
* Fixed example size.
* Initial release.
