2
0
Fork 0

Fixed offline injection and added Error support

This commit is contained in:
Willem 2016-01-20 21:57:05 +01:00
parent 1679782085
commit 2010e420d8
3 changed files with 70 additions and 56 deletions

View file

@ -77,7 +77,7 @@ A javascript library providing server defined loading of assets for a single pag
* debug.handler = Prints/log debug message. (default: console.log)
* debug.prefix = Debug message prefix. (default: 'FFSpaLoader.')
* error.handler = The error handler. (default: internal error handler ui)
* error.title = The error title. (default: 'Loader Error');
* error.title = The error title. (default: 'Loader ');
* error.style = The error ui css style. (default: red border box)
* 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)
@ -143,6 +143,7 @@ A javascript library providing server defined loading of assets for a single pag
* Chromium 46
* Iceweasel 43
* Opera 12 Presto
* IE 11 Edge
* Android 5 in Cordova
## Todo
@ -167,6 +168,7 @@ Add unit tests for any new or changed functionality. Lint and test your code.
### 0.0.4
* Disable cordova timeout per default.
* Remove unused mobileAgent detect.
* Fixed cached resources loading.
### 0.0.3

View file

@ -49,7 +49,7 @@
},
error: {
handler: null, // auto filled
title: 'Loader Error',
title: 'Loader ',
style: '.ffError { margin: auto;width: 90%;border: 3px solid red;padding-left: 1em;padding-bottom: 1em;}'
},
boot: {
@ -158,20 +158,20 @@
cb(null);
};
};
var sqlErrorHandler = function(cb) {
return function (tx, err) {
cb(err.message+' code: '+err.code);
};
var executeSql = function(tx, query, values, resultHandler, errorHandler) {
tx.executeSql(query, values, resultHandler, function(tx,err) {
errorHandler(new Error('Code: '+err.code+' '+err.message+' by query: '+query));
});
};
var cacheDBInit = function(cb) {
cacheDB.transaction(function(tx) {
var query = 'CREATE TABLE cache_store(id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT NOT NULL, value TEXT NOT NULL)';
utilDebug('websql.init query '+query);
tx.executeSql(query, [], function(tx) {
executeSql(tx, query, [], function(tx) {
var query = 'CREATE UNIQUE INDEX cache_store__key__udx ON cache_store (key)';
utilDebug('websql.init query '+query);
tx.executeSql(query, [], function() {cb(null);}, sqlErrorHandler(cb));
}, sqlErrorHandler(cb));
executeSql(tx, query, [], nullDataHandler(cb), cb);
}, cb);
});
};
return {
@ -187,7 +187,7 @@
cacheDB.transaction(function(tx) {
var query = 'SELECT value FROM cache_store WHERE key = \"test-for-table\"';
utilDebug('websql.cacheOpen query '+query);
tx.executeSql(query, [], function() {
executeSql(tx, query, [], function() {
cb(null);
}, function() {
cacheDBInit(cb);
@ -198,40 +198,40 @@
cacheDB.transaction(function(tx) {
var query = 'SELECT value FROM cache_store WHERE key = ?';
utilDebug('websql.cacheGetValue query '+query);
tx.executeSql(query,[key], function(tx, res) {
executeSql(tx, query,[key], function(tx, res) {
if (res.rows.length === 0) {
cb(null, null);
} else {
var value = res.rows.item(0).value;
cb(null, JSON.parse(value));
}
}, sqlErrorHandler(cb));
}, cb);
});
},
cacheSetValue: function(key, value, cb) {
cacheDB.transaction(function(tx) {
var query = 'SELECT value FROM cache_store WHERE key = ?';
utilDebug('websql.cacheSetValue query '+query);
tx.executeSql(query,[key], function(tx, res) {
executeSql(tx, query,[key], function(tx, res) {
if (res.rows.length === 0) {
var queryInsert = 'INSERT INTO cache_store (key,value) VALUES (?,?)';
utilDebug('websql.cacheSetValue query '+queryInsert);
tx.executeSql(queryInsert, [key,JSON.stringify(value)], nullDataHandler(cb), sqlErrorHandler(cb));
executeSql(tx, queryInsert, [key,JSON.stringify(value)], nullDataHandler(cb), cb);
} else {
var queryUpdate = 'UPDATE cache_store SET value = ? WHERE key = ?';
utilDebug('websql.cacheSetValue query '+queryUpdate);
tx.executeSql(queryUpdate, [JSON.stringify(value),key], nullDataHandler(cb), sqlErrorHandler(cb));
executeSql(tx, queryUpdate, [JSON.stringify(value),key], nullDataHandler(cb), cb);
}
}, sqlErrorHandler(cb));
}, cb);
});
},
cacheDeleteValue: function(key, cb) {
cacheDB.transaction(function(tx) {
var query = 'DELETE FROM cache_store WHERE key = ?';
utilDebug('websql.cacheDeleteValue query '+query);
tx.executeSql(query, [key], function () {
setTimeout(function() {cb(null);}); // return next tick so transaction is flushed before location.reload
}, sqlErrorHandler(cb));
executeSql(tx, query, [key], function () {
setTimeout(nullDataHandler(cb)); // return next tick so transaction is flushed before location.reload
}, cb);
});
}
};
@ -257,10 +257,14 @@
* @private
*/
var utilErrorHandler = function(err) {
utilDebug('utilErrorHandler error '+err); // TODO: Add Error object support
if (!(err instanceof Error)) {
err = new Error(err);
}
utilDebug('utilErrorHandler error '+err.name+' '+err.message);
var rootTag = document.createElement('div');
rootTag.setAttribute('class','ffError');
document.getElementsByTagName('body')[0].appendChild(rootTag);
var cssTag = document.createElement('style');
cssTag.type = 'text/css';
@ -268,14 +272,24 @@
rootTag.appendChild(cssTag);
var titleTag = document.createElement('h1');
titleTag.appendChild(document.createTextNode(options.error.title));
titleTag.appendChild(document.createTextNode(options.error.title+err.name));
rootTag.appendChild(titleTag);
var questionTag = document.createElement('p');
questionTag.appendChild(document.createTextNode(err));
questionTag.appendChild(document.createTextNode(err.message));
rootTag.appendChild(questionTag);
document.getElementsByTagName('body')[0].appendChild(rootTag);
try {
var stack = err.stack || '';
stack = stack.split('\n').map(function (line) { return line.trim(); });
var stackText = stack.splice(stack[0] == 'Error' ? 2 : 1);
var traceTag = document.createElement('div');
traceTag.appendChild(document.createTextNode(stackText));
rootTag.appendChild(traceTag);
} catch (stackError) {
utilDebug('No stack: '+stackError);
}
};
/**
@ -315,7 +329,7 @@
};
var cacheCheckType = function (type, cb, action) {
cacheHasService(type)?action():cb('No caching for '+type);
cacheHasService(type)?action():cb(new Error('No caching for '+type));
};
var cacheGetValue = function(type, key , cb) {
@ -450,33 +464,27 @@
loadResource(resourceStack[0],resourceLoader);
};
var injectResource = function(resource, cb) {
cacheGetValue(resource.type,resource.hash,function(err,item) {
injectResourceData(resource,item.data,cb);
});
}
var injectResources = function(resources, cb) {
var startTime = new Date().getTime();
utilDebug('injectResources');
resources.forEach(function (resource) {
cacheGetValue(resource.type,resource.hash,function(err,item) {
// TODO reuse injectResourceData
var tag = null;
if (resource.type === 'css' || resource.type === 'cssData') {
tag = document.createElement('style');
tag.type = 'text/css';
}
if (resource.type === 'js') {
tag = document.createElement('script');
tag.type = 'text/javascript';
}
utilDebug('injectResources from '+JSON.stringify(resource));
tag.appendChild(document.createTextNode(item.data));
//document.getElementsByTagName('head')[0].appendChild(tag);
var ref = document.getElementsByTagName('script')[0];
ref.parentNode.insertBefore(tag, ref); // note in reverse order
});
});
var resourceStack = resources;
var resourceLoader = function(err) {
if (err !== null) { return cb(err); }
resourceStack = resourceStack.slice(1);
if (resourceStack.length === 0) {
utilDebug('injectResources done in '+(new Date().getTime()-startTime)+' ms.');
cb(null); // FIXME async
cb(null);
} else {
injectResource(resourceStack[0],resourceLoader);
}
};
injectResource(resourceStack[0],resourceLoader);
};
/**
@ -488,11 +496,11 @@
*/
var startLoader = function (cb) {
if (options.server.url === null) {
cb('Missing options.server.url');
cb(new Error('No url'));
return;
}
if (options.server.assets === null) {
cb('Missing options.server.assets');
cb(new Error('No assets'));
return;
}
rootWindow[options.server.flag] = options.server.url;
@ -507,13 +515,13 @@
if (err !== null) {
cb(err);
} else if (value === null) {
cb('Have no cache of server resouces from '+options.server.url);
cb(new Error('Have no cache of server resouces from '+options.server.url));
} else {
injectResources(value, cb);
}
});
} else {
cb('Could not fetch server resouces from '+options.server.url);
cb(new Error('Could not fetch server resouces from '+options.server.url));
}
return;
}

View file

@ -9,7 +9,7 @@ var morgan = require('morgan');
// example options;
var serverUrl = 'http://localhost:8080';
var useInline = true; // or false
var useInline = false; // or false
var clientResourcesWeb = [];
var clientResources = {
@ -123,7 +123,11 @@ server.use('/static/module/angular', express.static(path.join(__dirname,'n
server.use('/static/module/angular-route', express.static(path.join(__dirname,'node_modules/angular-route')));
server.get('/static/es5-ff-spa-loader.js', function (req,res) {
if (fs.existsSync(__dirname+'/../es5-ff-spa-loader.js')) {
res.write(fs.readFileSync(__dirname+'/../es5-ff-spa-loader.js', 'utf8'));
} else {
res.write(fs.readFileSync(__dirname+'/../dist/es5-ff-spa-loader.js', 'utf8'));
}
res.end();
});
server.get('/static/spa-client-resources', function (req,res) {