2
0
Fork 0

Linted code and added basic tests.

This commit is contained in:
Willem 2016-01-17 21:57:59 +01:00
parent e5e2dfc56f
commit 0fd0f026ec
9 changed files with 219 additions and 107 deletions

5
.jshintignore Normal file
View file

@ -0,0 +1,5 @@
node_modules
example/node_modules
example/www_static
example/www_views
example/mobile_app

38
.jshintrc Normal file
View file

@ -0,0 +1,38 @@
{
"predef": [
"before",
"after",
"it",
"describe",
"beforeEach",
"afterEach"
],
"asi" : false,
"bitwise" : true,
"boss" : false,
"curly" : true,
"debug": false,
"devel": false,
"eqeqeq": true,
"evil": false,
"expr": true,
"forin": false,
"immed": true,
"latedef" : false,
"laxbreak": false,
"multistr": true,
"newcap": true,
"noarg": true,
"node" : true,
"noempty": false,
"nonew": true,
"onevar": false,
"plusplus": false,
"proto": true,
"regexp": false,
"strict": false,
"sub": false,
"trailing" : true,
"undef": true,
"unused": true
}

View file

@ -52,6 +52,17 @@ A javascript library providing server defined loading of resources for a single
* Iceweasel 43 * Iceweasel 43
* Opera 12 Presto * Opera 12 Presto
* Android 5 in Cordova * Android 5 in Cordova
## Todo
* Auto cache cleanup code.
* test in production
* Server header set+check support
* Redo css(?divs) of server question
* Add more tests
* css: set tag.media = 'only you';
* css: add media in resouces
* Add in browser tests
## Contributing ## Contributing

View file

@ -1,4 +1,3 @@
'use strict';
/* /*
* Copyright (c) 2015-2016, Willem Cazander * Copyright (c) 2015-2016, Willem Cazander
* All rights reserved. * All rights reserved.
@ -21,11 +20,8 @@
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* jslint browser: true */
/* global angular,define */
// TODO:
// set tag.media = 'only you';
// add media in resouces
/** /**
* FFSpaLoader is an assets loader for single page applications. * FFSpaLoader is an assets loader for single page applications.
@ -44,8 +40,17 @@
* *
* @module FFSpaLoader * @module FFSpaLoader
*/ */
var FFSpaLoader = (/** @lends module:FFSpaLoader */function () { (function (root, factory) {
if ( typeof define === 'function' && define.amd ) {
define('FFSpaLoader', factory(root));
} else if ( typeof exports === 'object' ) {
module.exports = factory(root);
} else {
root.FFSpaLoader = factory(root);
}
})(this || window, /** @lends module:FFSpaLoader */ function (rootWindow) {
'use strict';
var options = { var options = {
debug: { debug: {
enable: false, enable: false,
@ -102,27 +107,27 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
localStorage: function() { localStorage: function() {
try { try {
var testData = 'localStorageDetect'; var testData = 'localStorageDetect';
localStorage.setItem(testData, testData); rootWindow.localStorage.setItem(testData, testData);
localStorage.removeItem(testData); rootWindow.localStorage.removeItem(testData);
return true; return true;
} catch(e) { } catch(e) {
return false; return false;
} }
}, },
openDatabase: function() { openDatabase: function() {
return 'openDatabase' in window; return 'openDatabase' in rootWindow;
}, },
sqlitePlugin: function() { sqlitePlugin: function() {
return 'sqlitePlugin' in window; return 'sqlitePlugin' in rootWindow;
}, },
cordova: function() { cordova: function() {
return 'cordova' in window; return 'cordova' in rootWindow;
}, },
cordovaDevice: function() { cordovaDevice: function() {
return options.boot.cordova.flag in window; return options.boot.cordova.flag in rootWindow;
}, },
mobileAgent: function() { mobileAgent: function() {
return navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|IEMobile)/); return rootWindow.navigator !== undefined && rootWindow.navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|IEMobile)/);
} }
}, },
cache: { cache: {
@ -130,7 +135,7 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
return { return {
cacheGetValue: function(key, cb) { cacheGetValue: function(key, cb) {
try { try {
var dataRaw = localStorage.getItem(key); var dataRaw = rootWindow.localStorage.getItem(key);
var data = JSON.parse(dataRaw); var data = JSON.parse(dataRaw);
cb(null, data); cb(null, data);
} catch(e) { } catch(e) {
@ -139,7 +144,7 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
}, },
cacheSetValue: function(key, value, cb) { cacheSetValue: function(key, value, cb) {
try { try {
localStorage.setItem(key,JSON.stringify(value)); rootWindow.localStorage.setItem(key,JSON.stringify(value));
cb(null); cb(null);
} catch(e) { } catch(e) {
cb(e); cb(e);
@ -147,22 +152,22 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
}, },
cacheDeleteValue: function(key, cb) { cacheDeleteValue: function(key, cb) {
try { try {
localStorage.removeItem(key); rootWindow.localStorage.removeItem(key);
cb(null); cb(null);
} catch(e) { } catch(e) {
cb(e); cb(e);
} }
} }
} };
}, },
websql: function(opt) { websql: function(opt) {
if (opt === undefined) { opt = {}; } if (opt === undefined) { opt = {}; }
if (opt.name === undefined) { opt.name = 'ffSpaLoader.db'; } if (opt.name === undefined) { opt.name = 'ffSpaLoader.db'; }
if (opt.size === undefined) { opt.size = -1; } if (opt.size === undefined) { opt.size = -1; }
if (opt.version === undefined) { opt.version = '1.0'; } if (opt.version === undefined) { opt.version = '1.0'; }
if (opt.openDatabase === undefined) { opt.openDatabase = window.openDatabase; } if (opt.openDatabase === undefined) { opt.openDatabase = rootWindow.openDatabase; }
var nullDataHandler = function(cb) { var nullDataHandler = function(cb) {
return function (tx, results) { return function () {
cb(null); cb(null);
}; };
}; };
@ -175,26 +180,26 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
cacheDB.transaction(function(tx) { cacheDB.transaction(function(tx) {
var query = 'CREATE TABLE cache_store(id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT NOT NULL, value TEXT NOT NULL)'; var query = 'CREATE TABLE cache_store(id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT NOT NULL, value TEXT NOT NULL)';
utilDebug('websql.init query '+query); utilDebug('websql.init query '+query);
tx.executeSql(query, [], function(tx,res) { tx.executeSql(query, [], function(tx) {
var query = 'CREATE UNIQUE INDEX cache_store__key__udx ON cache_store (key)'; var query = 'CREATE UNIQUE INDEX cache_store__key__udx ON cache_store (key)';
utilDebug('websql.init query '+query); utilDebug('websql.init query '+query);
tx.executeSql(query, [], function(tx,res) {cb(null)}, sqlErrorHandler(cb)); tx.executeSql(query, [], function() {cb(null);}, sqlErrorHandler(cb));
}, sqlErrorHandler(cb)); }, sqlErrorHandler(cb));
}); });
} };
return { return {
cacheOpen: function(cb) { cacheOpen: function(cb) {
if (cacheDB !== null) { if (cacheDB !== null) {
cb(null); // open once. cb(null); // open once.
return; return;
} }
cacheDB = window.openDatabase(opt.name, opt.version, opt.name, opt.size); cacheDB = rootWindow.openDatabase(opt.name, opt.version, opt.name, opt.size);
cacheDB.transaction(function(tx) { cacheDB.transaction(function(tx) {
var query = 'SELECT value FROM cache_store WHERE key = \"test-for-table\"'; var query = 'SELECT value FROM cache_store WHERE key = \"test-for-table\"';
utilDebug('websql.cacheOpen query '+query); utilDebug('websql.cacheOpen query '+query);
tx.executeSql(query, [], function(tx,res) { tx.executeSql(query, [], function() {
cb(null); cb(null);
}, function(tx,errorNoTable) { }, function() {
cacheDBInit(cb); cacheDBInit(cb);
}); });
}); });
@ -219,13 +224,13 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
utilDebug('websql.cacheSetValue query '+query); utilDebug('websql.cacheSetValue query '+query);
tx.executeSql(query,[key], function(tx, res) { tx.executeSql(query,[key], function(tx, res) {
if (res.rows.length === 0) { if (res.rows.length === 0) {
var query = 'INSERT INTO cache_store (key,value) VALUES (?,?)'; var queryInsert = 'INSERT INTO cache_store (key,value) VALUES (?,?)';
utilDebug('websql.cacheSetValue query '+query); utilDebug('websql.cacheSetValue query '+queryInsert);
tx.executeSql(query, [key,JSON.stringify(value)], nullDataHandler(cb), sqlErrorHandler(cb)); tx.executeSql(queryInsert, [key,JSON.stringify(value)], nullDataHandler(cb), sqlErrorHandler(cb));
} else { } else {
var query = 'UPDATE cache_store SET value = ? WHERE key = ?'; var queryUpdate = 'UPDATE cache_store SET value = ? WHERE key = ?';
utilDebug('websql.cacheSetValue query '+query); utilDebug('websql.cacheSetValue query '+queryUpdate);
tx.executeSql(query, [JSON.stringify(value),key], nullDataHandler(cb), sqlErrorHandler(cb)); tx.executeSql(queryUpdate, [JSON.stringify(value),key], nullDataHandler(cb), sqlErrorHandler(cb));
} }
}, sqlErrorHandler(cb)); }, sqlErrorHandler(cb));
}); });
@ -234,12 +239,12 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
cacheDB.transaction(function(tx) { cacheDB.transaction(function(tx) {
var query = 'DELETE FROM cache_store WHERE key = ?'; var query = 'DELETE FROM cache_store WHERE key = ?';
utilDebug('websql.cacheDeleteValue query '+query); utilDebug('websql.cacheDeleteValue query '+query);
tx.executeSql(query, [key], function (tx, res) { tx.executeSql(query, [key], function () {
setTimeout(function() {cb(null);}); // return next tick so transaction is flushed before location.reload setTimeout(function() {cb(null);}); // return next tick so transaction is flushed before location.reload
}, sqlErrorHandler(cb)); }, sqlErrorHandler(cb));
}); });
} }
} };
}, },
} }
}; };
@ -293,13 +298,13 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
var startTime = new Date().getTime(); var startTime = new Date().getTime();
var httpRequest = new XMLHttpRequest(); var httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function() { httpRequest.onreadystatechange = function() {
if (httpRequest.readyState == 4 && httpRequest.status === 200) { if (httpRequest.readyState === 4 && httpRequest.status === 200) {
utilDebug('utilHttpFetch url \"'+url+'\" done in '+(new Date().getTime()-startTime)+' ms.'); utilDebug('utilHttpFetch url \"'+url+'\" done in '+(new Date().getTime()-startTime)+' ms.');
cb(null, httpRequest); cb(null, httpRequest);
} else if (httpRequest.readyState == 4) { } else if (httpRequest.readyState === 4) {
cb('Wrong status '+httpRequest.status); cb('Wrong status '+httpRequest.status);
} }
} };
httpRequest.open('GET', url, true); httpRequest.open('GET', url, true);
httpRequest.timeout = options.server.timeout; // ieX: after open() httpRequest.timeout = options.server.timeout; // ieX: after open()
httpRequest.ontimeout = function() { httpRequest.ontimeout = function() {
@ -347,12 +352,11 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
}); });
}; };
var cleanupCache = function (resources, cb) { // var cleanupCache = function (resources, cb) {
utilDebug('cleanupCache TODO cacheList '+0+' resources '+resources.length); // utilDebug('cleanupCache TODO cacheList '+0+' resources '+resources.length);
// // TODO: impl for removes in resource lists
// TODO: impl for removes in resource lists // cb(null);
cb(null); // };
};
var injectResourceData = function(resource, data, cb) { var injectResourceData = function(resource, data, cb) {
utilDebug('injectResourceData resource '+JSON.stringify(resource)+' data '+data.length); utilDebug('injectResourceData resource '+JSON.stringify(resource)+' data '+data.length);
@ -387,14 +391,14 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
value.push(resource.hash); value.push(resource.hash);
cacheSetValue('meta',cacheKey,value, cb); cacheSetValue('meta',cacheKey,value, cb);
}); });
} };
var storeResource = function (resource, httpRequest, cb) { var storeResource = function (resource, httpRequest, cb) {
utilDebug('storeResource url '+resource.url+' hash '+resource.hash); utilDebug('storeResource url '+resource.url+' hash '+resource.hash);
var item = { var item = {
resource: resource, resource: resource,
data: httpRequest.responseText data: httpRequest.responseText
} };
cacheSetValue(resource.type, resource.hash, item , function(err) { cacheSetValue(resource.type, resource.hash, item , function(err) {
if (err !== null) { if (err !== null) {
cb(err); cb(err);
@ -412,10 +416,7 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
utilDebug('loadResource '+JSON.stringify(resource)); utilDebug('loadResource '+JSON.stringify(resource));
if (cacheHasService(resource.type)) { if (cacheHasService(resource.type)) {
cacheGetValue(resource.type,resource.hash,function(err, value) { cacheGetValue(resource.type,resource.hash,function(err, value) {
if (err !== null) { if (err !== null) { return cb(err); }
cb(err);
return;
}
if (value === null) { if (value === null) {
utilDebug('loadResource cache miss'); // + hash mismatch as its the key utilDebug('loadResource cache miss'); // + hash mismatch as its the key
} else if (value.resource === undefined) { } else if (value.resource === undefined) {
@ -426,23 +427,18 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
return; return;
} }
utilHttpFetch(resourceUrl, function(err, httpRequest) { utilHttpFetch(resourceUrl, function(err, httpRequest) {
if (err !== null) { if (err !== null) { return cb(err); }
cb(err); storeResource(resource, httpRequest, function (err) {
} else { if (err !== null) { return cb(err); }
storeResource(resource, httpRequest, function (err) { injectResourceData(resource,httpRequest.responseText,cb);
injectResourceData(resource,httpRequest.responseText,cb); });
});
}
}); });
}); });
} else { } else {
// note: was links but now download + inject so order stays sequenced // note: was links but now download + inject so order stays sequenced
utilHttpFetch(resourceUrl, function(err, httpRequest) { utilHttpFetch(resourceUrl, function(err, httpRequest) {
if (err !== null) { if (err !== null) { return cb(err); }
cb(err); injectResourceData(resource,httpRequest.responseText,cb);
} else {
injectResourceData(resource,httpRequest.responseText,cb);
}
}); });
} }
}; };
@ -452,10 +448,7 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
utilDebug('loadResources'); utilDebug('loadResources');
var resourceStack = resources; var resourceStack = resources;
var resourceLoader = function(err) { var resourceLoader = function(err) {
if (err !== null) { if (err !== null) { return cb(err); }
cb(err);
return;
}
resourceStack = resourceStack.slice(1); resourceStack = resourceStack.slice(1);
if (resourceStack.length === 0) { if (resourceStack.length === 0) {
utilDebug('loadResources done in '+(new Date().getTime()-startTime)+' ms.'); utilDebug('loadResources done in '+(new Date().getTime()-startTime)+' ms.');
@ -512,7 +505,7 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
cb('Missing options.server.assets'); cb('Missing options.server.assets');
return; return;
} }
window[options.server.flag] = options.server.url; rootWindow[options.server.flag] = options.server.url;
var resourcesUrl = options.server.url + options.server.assets; var resourcesUrl = options.server.url + options.server.assets;
utilDebug('startLoader assets \"'+resourcesUrl+'\"'); utilDebug('startLoader assets \"'+resourcesUrl+'\"');
@ -541,11 +534,8 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
utilDebug('startLoader resources '+resources.length); utilDebug('startLoader resources '+resources.length);
if (cacheHasService('meta')) { if (cacheHasService('meta')) {
cacheSetValue('meta','server_resources',resources, function (err) { cacheSetValue('meta','server_resources',resources, function (err) {
if (err !== null) { if (err !== null) { return cb(err); }
cb(err); loadResources(resources, cb);
} else {
loadResources(resources, cb);
}
}); });
} else { } else {
loadResources(resources, cb); loadResources(resources, cb);
@ -578,25 +568,27 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
utilDebug('askUrlStart check assets '+resourcesUrl); utilDebug('askUrlStart check assets '+resourcesUrl);
// TODO: add+check headers // TODO: add+check headers
utilHttpFetch(resourcesUrl,function(err, req) { utilHttpFetch(resourcesUrl,function(err, httpRequest) {
if (err !== null) { if (err !== null) {
inputErrorTag.appendChild(document.createTextNode('Error could not get data.')); inputErrorTag.appendChild(document.createTextNode('Error could not get data.'));
return; return;
} }
if (httpRequest.responseText.length === 0) {
inputErrorTag.appendChild(document.createTextNode('Error Got empty data.'));
return;
}
document.getElementsByTagName('body')[0].removeChild(deleteTag); document.getElementsByTagName('body')[0].removeChild(deleteTag);
if (cacheHasService('meta')) { if (cacheHasService('meta')) {
cacheSetValue('meta','server_url',options.server.url, function(err) { cacheSetValue('meta','server_url',options.server.url, function(err) {
if (err !== null) { if (err !== null) { return cb(err); }
cb(err); startLoader(cb);
} else {
startLoader(cb);
}
}); });
} else { } else {
startLoader(cb); startLoader(cb);
} }
}) });
} };
/** /**
* Creates the ask url ui. * Creates the ask url ui.
@ -666,7 +658,7 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
if (options.cache[type] === null) { if (options.cache[type] === null) {
if (factory.detect.cordovaDevice() && factory.detect.sqlitePlugin()) { if (factory.detect.cordovaDevice() && factory.detect.sqlitePlugin()) {
utilDebug('startCacheType auto sqlitePlugin for '+type); utilDebug('startCacheType auto sqlitePlugin for '+type);
options.cache[type] = factory.cache.websql({openDatabase: window.sqlitePlugin}); options.cache[type] = factory.cache.websql({openDatabase: rootWindow.sqlitePlugin});
} else if (factory.detect.openDatabase()) { } else if (factory.detect.openDatabase()) {
utilDebug('startCacheType auto openDatabase for '+type); utilDebug('startCacheType auto openDatabase for '+type);
options.cache[type] = factory.cache.websql(); options.cache[type] = factory.cache.websql();
@ -677,7 +669,7 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
utilDebug('startCacheType '+type+' none'); utilDebug('startCacheType '+type+' none');
} }
} }
if (options.cache[type] !== null && typeof options.cache[type]['cacheOpen'] === "function") { if (options.cache[type] !== null && typeof options.cache[type].cacheOpen === 'function') {
options.cache[type].cacheOpen(cb); options.cache[type].cacheOpen(cb);
} else { } else {
cb(null); cb(null);
@ -711,12 +703,12 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
utilDebug('start done in '+(new Date().getTime()-startTime)+' ms.'); utilDebug('start done in '+(new Date().getTime()-startTime)+' ms.');
bootAngular(function(err) { bootAngular(function(err) {
if (err !== null) { return options.error.handler(err); } if (err !== null) { return options.error.handler(err); }
if (typeof cbArgu === "function") { if (typeof cbArgu === 'function') {
cbArgu(); cbArgu();
} }
}); });
} }
} };
if (options.debug.enable === true) { if (options.debug.enable === true) {
var optionsKeys = Object.keys(options); var optionsKeys = Object.keys(options);
for (var keyId in optionsKeys) { for (var keyId in optionsKeys) {
@ -759,7 +751,7 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
} else { } else {
cb(null); cb(null);
} }
} };
var bootAngular = function(cb) { var bootAngular = function(cb) {
if (options.boot.angular.enable !== true) { if (options.boot.angular.enable !== true) {
@ -773,7 +765,7 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
utilDebug('bootAngular start '+options.boot.angular.modules); utilDebug('bootAngular start '+options.boot.angular.modules);
angular.bootstrap(document, options.boot.angular.modules); angular.bootstrap(document, options.boot.angular.modules);
cb(null); cb(null);
} };
/** /**
* Helper for cordova applications which want to use the sqllite plugin as cache. * Helper for cordova applications which want to use the sqllite plugin as cache.
@ -805,7 +797,7 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
bootOnce(); bootOnce();
}, options.boot.cordova.timeout); }, options.boot.cordova.timeout);
document.addEventListener("deviceready", function () { document.addEventListener("deviceready", function () {
window[options.boot.cordova.flag] = true; rootWindow[options.boot.cordova.flag] = true;
utilDebug('bootCordova '+options.boot.cordova.flag); utilDebug('bootCordova '+options.boot.cordova.flag);
bootOnce(); bootOnce();
}, false); }, false);
@ -820,4 +812,4 @@ var FFSpaLoader = (/** @lends module:FFSpaLoader */function () {
start: start, start: start,
clearServerUrl: clearServerUrl clearServerUrl: clearServerUrl
}; };
})(); });

View file

@ -6,7 +6,7 @@ var fs = require('fs');
var minify = require('minify'); var minify = require('minify');
var fetch = require('fetch'); var fetch = require('fetch');
var cors = require('cors'); var cors = require('cors');
var morgan = require('morgan') var morgan = require('morgan');
// example options; // example options;
var serverUrl = 'http://localhost:8080'; var serverUrl = 'http://localhost:8080';
@ -17,19 +17,21 @@ var clientResources = {
js: [], js: [],
css: [], css: [],
cssData: [] cssData: []
} };
var addClientResource = function(clientResource, resourceType) { var addClientResource = function(clientResource, resourceType) {
clientResources[resourceType].push(clientResource); clientResources[resourceType].push(clientResource);
} };
var stringHash = function (str) { var stringHash = function (str) {
/* jslint bitwise: true */
var hash = 31; // prime var hash = 31; // prime
for (var i = 0; i < str.length; i++) { for (var i = 0; i < str.length; i++) {
hash = ((hash<<5)-hash)+str.charCodeAt(i); hash = ((hash<<5)-hash)+str.charCodeAt(i);
hash = hash & hash; // keep 32b hash = hash & hash; // keep 32b
} }
return hash; return hash;
/* jslint bitwise: false */
}; };
var fetchHashResource = function(fetchEntry,cb) { var fetchHashResource = function(fetchEntry,cb) {
@ -60,17 +62,17 @@ var fetchHashResources = function(fetchList, cb) {
var createClientResourceFetchList = function() { var createClientResourceFetchList = function() {
var fetchList = []; var fetchList = [];
for (var clientResourceIdx in clientResources.js) { for (var clientResourceIdxJs in clientResources.js) {
var url = clientResources.js[clientResourceIdx]; var urlJs = clientResources.js[clientResourceIdxJs];
fetchList.push({url:url,type:'js'}); fetchList.push({url:urlJs,type:'js'});
} }
for (var clientResourceIdx in clientResources.css) { for (var clientResourceIdxCss in clientResources.css) {
var url = clientResources.css[clientResourceIdx]; var urlCss = clientResources.css[clientResourceIdxCss];
fetchList.push({url:url,type:'css'}); fetchList.push({url:urlCss,type:'css'});
} }
for (var clientResourceIdx in clientResources.cssData) { for (var clientResourceIdxCssData in clientResources.cssData) {
var url = clientResources.cssData[clientResourceIdx]; var urlCssData = clientResources.cssData[clientResourceIdxCssData];
fetchList.push({url:url,type:'cssData'}); fetchList.push({url:urlCssData,type:'cssData'});
} }
return fetchList; return fetchList;
}; };
@ -86,7 +88,7 @@ function renderTemplatePath(viewPath) {
}; };
} }
function renderIndex(server) { function renderIndex() {
var inline = ''; var inline = '';
minify(__dirname+'/../es5-ff-spa-loader.js', {}, function(err, data) { minify(__dirname+'/../es5-ff-spa-loader.js', {}, function(err, data) {
inline = '\n\t\t<script>'+data+'</script>'; inline = '\n\t\t<script>'+data+'</script>';
@ -113,7 +115,7 @@ addClientResource('/static/js/controller/page-foo.js','js');
addClientResource('/static/js/controller/page-index.js','js'); addClientResource('/static/js/controller/page-index.js','js');
var server = express(); var server = express();
server.use(morgan('dev')) server.use(morgan('dev'));
server.use(cors({credentials: true, origin: '*'})); server.use(cors({credentials: true, origin: '*'}));
server.set('view engine', 'ejs'); server.set('view engine', 'ejs');
server.set('views', path.join(__dirname,'www_views')); server.set('views', path.join(__dirname,'www_views'));
@ -133,8 +135,7 @@ server.get('/static/spa-client-resources', function (req,res) {
server.get('/', function (req, res) {res.redirect('/example-ui');}); server.get('/', function (req, res) {res.redirect('/example-ui');});
server.get('/example-ui/thtml/*', renderTemplatePath('thtml/')); server.get('/example-ui/thtml/*', renderTemplatePath('thtml/'));
server.get('/example-ui', renderIndex(server)); server.get('/example-ui', renderIndex());
server.get('/example-ui/*', renderIndex(server)); // must be last; for HTML5 history
console.info('Server config done.'); console.info('Server config done.');
server.listen(8080); server.listen(8080);
@ -142,7 +143,7 @@ console.info('Server started on port 8080');
var res = createClientResourceFetchList(); var res = createClientResourceFetchList();
fetchHashResources(res, function(err) { fetchHashResources(res, function(err) {
if (err !== null) {console.log(err);}; if (err !== null) {console.log(err);}
console.log('Total assets build: '+clientResourcesWeb.length); console.log('Total assets build: '+clientResourcesWeb.length);
}); });

View file

@ -3,6 +3,9 @@
"version": "0.0.1", "version": "0.0.1",
"description": "Javascript Single Page Application Loader", "description": "Javascript Single Page Application Loader",
"main": "es5-ff-spa-loader.js", "main": "es5-ff-spa-loader.js",
"scripts": {
"test": "export JUNIT_REPORT_PATH=test/data/report.xml;export JUNIT_REPORT_STACK=1;node_modules/mocha/bin/mocha --reporter mocha-jenkins-reporter"
},
"author": "Willem <willem.git.2016@forwardfire.net> (http://forwardfire.net/)", "author": "Willem <willem.git.2016@forwardfire.net> (http://forwardfire.net/)",
"keywords": [ "keywords": [
"website", "website",
@ -14,15 +17,22 @@
"mobile", "mobile",
"resources", "resources",
"sync", "sync",
"cache" "cache",
"localStorage",
"openDatabase"
], ],
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://bitbucket.org/im_ik/es5-ff-spa-loader.git" "url": "https://bitbucket.org/im_ik/es5-ff-spa-loader.git"
}, },
"devDependencies": {
"jsdoc": "^3.4.0",
"mocha": "2.2.x",
"mocha-jenkins-reporter": "0.1.x",
"mocha-jshint": "2.2.x"
},
"dependencies": { "dependencies": {
"jsdoc": "^3.4.0"
}, },
"files": [ "files": [
"README.md", "README.md",

3
test/jshint.spec.js Normal file
View file

@ -0,0 +1,3 @@
'use strict';
require('mocha-jshint')(['es5-ff-spa-loader.js','example']);

26
test/test-exports.js Normal file
View file

@ -0,0 +1,26 @@
'use strict';
var assert = require('assert');
var FFSpaLoader = require('../es5-ff-spa-loader');
describe('Check module exports', function() {
it('FFSpaLoader.options should be defined', function() {
assert.equal(false, FFSpaLoader.options === undefined);
});
it('FFSpaLoader.factory should be defined', function() {
assert.equal(false, FFSpaLoader.factory === undefined);
});
it('FFSpaLoader.start should be defined', function() {
assert.equal(false, FFSpaLoader.start === undefined);
});
it('FFSpaLoader.start should be function', function() {
assert.equal(true, typeof FFSpaLoader.start === 'function');
});
it('FFSpaLoader.clearServerUrl should be defined', function() {
assert.equal(false, FFSpaLoader.clearServerUrl === undefined);
});
it('FFSpaLoader.clearServerUrl should be function', function() {
assert.equal(true, typeof FFSpaLoader.clearServerUrl === 'function');
});
});

26
test/test-factory.js Normal file
View file

@ -0,0 +1,26 @@
'use strict';
var assert = require('assert');
var FFSpaLoader = require('../es5-ff-spa-loader');
describe('Check factory detect', function() {
it('FFSpaLoader.factory.detect.localStorage', function() {
assert.equal(false, FFSpaLoader.factory.detect.localStorage());
});
it('FFSpaLoader.factory.detect.openDatabase', function() {
assert.equal(false, FFSpaLoader.factory.detect.openDatabase());
});
it('FFSpaLoader.factory.detect.sqlitePlugin', function() {
assert.equal(false, FFSpaLoader.factory.detect.sqlitePlugin());
});
it('FFSpaLoader.factory.detect.cordova', function() {
assert.equal(false, FFSpaLoader.factory.detect.cordova());
});
it('FFSpaLoader.factory.detect.cordovaDevice', function() {
assert.equal(false, FFSpaLoader.factory.detect.cordovaDevice());
});
it('FFSpaLoader.factory.detect.mobileAgent', function() {
assert.equal(false, FFSpaLoader.factory.detect.mobileAgent());
});
});