Linted code and added basic tests.
This commit is contained in:
parent
e5e2dfc56f
commit
0fd0f026ec
5
.jshintignore
Normal file
5
.jshintignore
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
node_modules
|
||||||
|
example/node_modules
|
||||||
|
example/www_static
|
||||||
|
example/www_views
|
||||||
|
example/mobile_app
|
38
.jshintrc
Normal file
38
.jshintrc
Normal 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
|
||||||
|
}
|
11
README.md
11
README.md
|
@ -53,6 +53,17 @@ A javascript library providing server defined loading of resources for a single
|
||||||
* 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
|
||||||
|
|
||||||
In lieu of a formal styleguide, take care to maintain the existing coding style.
|
In lieu of a formal styleguide, take care to maintain the existing coding style.
|
||||||
|
|
|
@ -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,7 +40,16 @@
|
||||||
*
|
*
|
||||||
* @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: {
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
})();
|
});
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
14
package.json
14
package.json
|
@ -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
3
test/jshint.spec.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('mocha-jshint')(['es5-ff-spa-loader.js','example']);
|
26
test/test-exports.js
Normal file
26
test/test-exports.js
Normal 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
26
test/test-factory.js
Normal 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());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in a new issue