diff --git a/.gitignore b/.gitignore index 0ad2ac8..9a8014e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,12 +10,19 @@ node_modules npm-debug.log # Ignore mocha test data -test/data +test/data # Ignore example data example/node_modules example/npm-debug.log -example/mobile_app + +# Ignore example cordova data +example/app_mobile/platforms/* +!example/app_mobile/platforms/platforms.json +example/app_mobile/plugins/* +!example/app_mobile/plugins/android.json +!example/app_mobile/plugins/fetch.json +example/app_mobile/www/es5-ff-spa-loader.js # Ignore binary files *.o diff --git a/README.md b/README.md index 0e3dab7..38c4388 100644 --- a/README.md +++ b/README.md @@ -161,8 +161,24 @@ A javascript library providing server defined loading of assets for a single pag ## Example Application - There is a fully working nodejs example application in the example folder. + There is a fully working nodejs example application in the example folder; + * git clone + * cd es5-ff-spa-loader + * cd example + * 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 @@ -203,7 +219,9 @@ Add unit tests for any new or changed functionality. Lint and test your code. * Fixed sqlitePlugin open function was 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. + ### 0.1.0 * Moved options.server.question to options.question. * Added question.validate.[min|max|regex].value|message options. diff --git a/es5-ff-spa-loader.js b/es5-ff-spa-loader.js index 8046f98..dd47b7d 100644 --- a/es5-ff-spa-loader.js +++ b/es5-ff-spa-loader.js @@ -698,9 +698,8 @@ deleteTag.setAttribute('class','ffQuestion ffQuestionLoad'); var clearUi = function(err) { - if (err !== null) { return cb(err); } - document.getElementsByTagName('body')[0].removeChild(deleteTag); - cb(null); + document.getElementsByTagName('body')[0].removeChild(deleteTag); // also delete on error + cb(err); }; if (cacheHasService('meta')) { cacheSetValue('meta','server_url',options.server.url, function(err) { diff --git a/example/app_mobile/config.xml b/example/app_mobile/config.xml new file mode 100644 index 0000000..5854a27 --- /dev/null +++ b/example/app_mobile/config.xml @@ -0,0 +1,38 @@ + + + FFSpaLoaderExample + + A sample FFSpaLoader example application. + + + FFSpaLoaderExample + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/app_mobile/platforms/platforms.json b/example/app_mobile/platforms/platforms.json new file mode 100644 index 0000000..54f14bd --- /dev/null +++ b/example/app_mobile/platforms/platforms.json @@ -0,0 +1,3 @@ +{ + "android": "4.1.1" +} \ No newline at end of file diff --git a/example/app_mobile/plugins/android.json b/example/app_mobile/plugins/android.json new file mode 100644 index 0000000..3ff847a --- /dev/null +++ b/example/app_mobile/plugins/android.json @@ -0,0 +1,18 @@ +{ + "prepare_queue": { + "installed": [], + "uninstalled": [] + }, + "config_munge": { + "files": {} + }, + "installed_plugins": { + "cordova-plugin-whitelist": { + "PACKAGE_NAME": "net.forwardfire.spa.loader" + }, + "cordova-sqlite-storage": { + "PACKAGE_NAME": "net.forwardfire.spa.loader" + } + }, + "dependent_plugins": {} +} \ No newline at end of file diff --git a/example/app_mobile/plugins/fetch.json b/example/app_mobile/plugins/fetch.json new file mode 100644 index 0000000..a28e7a5 --- /dev/null +++ b/example/app_mobile/plugins/fetch.json @@ -0,0 +1,18 @@ +{ + "cordova-sqlite-storage": { + "source": { + "type": "registry", + "id": "cordova-sqlite-storage" + }, + "is_top_level": true, + "variables": {} + }, + "cordova-plugin-whitelist": { + "source": { + "type": "registry", + "id": "cordova-plugin-whitelist@1" + }, + "is_top_level": true, + "variables": {} + } +} \ No newline at end of file diff --git a/example/app_mobile/scripts/copy-ff-spa-loader.js b/example/app_mobile/scripts/copy-ff-spa-loader.js new file mode 100644 index 0000000..83906f3 --- /dev/null +++ b/example/app_mobile/scripts/copy-ff-spa-loader.js @@ -0,0 +1,16 @@ +var fs = require('fs'); + +module.exports = function(context) { + var Q = context.requireCordovaModule('q'); + var deferral = new Q.defer(); + console.log('copy-ff-spa-loader start'); + fs.readFile('../../es5-ff-spa-loader.js',function(err,data) { + if (err) return deferral.reject(err); + fs.writeFile('www/es5-ff-spa-loader.js',data,function(err) { + if (err) return deferral.reject(err); + console.log('copy-ff-spa-loader done'); + deferral.resolve(); + }) + }); + return deferral.promise; +} diff --git a/example/app_mobile/scripts/rename-android-apk.js b/example/app_mobile/scripts/rename-android-apk.js new file mode 100644 index 0000000..b96c03c --- /dev/null +++ b/example/app_mobile/scripts/rename-android-apk.js @@ -0,0 +1,15 @@ +var fs = require('fs'); + +module.exports = function(context) { + var Q = context.requireCordovaModule('q'); + var deferral = new Q.defer(); + var nameOld = 'platforms/android/build/outputs/apk/android-debug.apk'; + var nameNew = 'platforms/android/build/outputs/apk/FFSpaLoaderExample.apk'; + console.log('rename-android-apk start old: '+nameOld); + fs.rename(nameOld,nameNew,function(err) { + if (err) return deferral.reject(err); + console.log('rename-android-apk done new: '+nameNew); + deferral.resolve(); + }); + return deferral.promise; +} diff --git a/example/app_mobile/www/img/ic_launcher_hdpi.png b/example/app_mobile/www/img/ic_launcher_hdpi.png new file mode 100644 index 0000000..271a0ad Binary files /dev/null and b/example/app_mobile/www/img/ic_launcher_hdpi.png differ diff --git a/example/app_mobile/www/img/ic_launcher_mdpi.png b/example/app_mobile/www/img/ic_launcher_mdpi.png new file mode 100644 index 0000000..c6702c5 Binary files /dev/null and b/example/app_mobile/www/img/ic_launcher_mdpi.png differ diff --git a/example/app_mobile/www/img/ic_launcher_xhdpi.png b/example/app_mobile/www/img/ic_launcher_xhdpi.png new file mode 100644 index 0000000..7ab0cfa Binary files /dev/null and b/example/app_mobile/www/img/ic_launcher_xhdpi.png differ diff --git a/example/app_mobile/www/index.html b/example/app_mobile/www/index.html new file mode 100644 index 0000000..9cd21f2 --- /dev/null +++ b/example/app_mobile/www/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + diff --git a/example/example.js b/example/app_server/example.js similarity index 65% rename from example/example.js rename to example/app_server/example.js index fbac69c..4e28f99 100644 --- a/example/example.js +++ b/example/app_server/example.js @@ -1,15 +1,14 @@ 'use strict'; +var httpPort = 9090; var express = require('express'); var path = require('path'); var fs = require('fs'); var fetch = require('fetch'); var cors = require('cors'); var morgan = require('morgan'); - -// example options; -var serverUrl = 'http://localhost:8080'; -var useInline = true; // or false +var UglifyJS = require("uglify-js"); +var Hashes = require('jshashes'); var clientResourcesWeb = []; var clientResources = { @@ -22,21 +21,12 @@ var addClientResource = function(clientResource, resourceType) { clientResources[resourceType].push(clientResource); }; -var stringHash = function (str) { - /* jslint bitwise: true */ - var hash = 31; // prime - for (var i = 0; i < str.length; i++) { - hash = ((hash<<5)-hash)+str.charCodeAt(i); - hash = hash & hash; // keep 32b - } - return hash; - /* jslint bitwise: false */ -}; - var fetchHashResource = function(fetchEntry,cb) { + var serverUrl = 'http://localhost:'+httpPort; + var hashDigest = new Hashes.SHA1; fetch.fetchUrl(serverUrl + fetchEntry.url,function(err, meta, data) { if (err !== null) { return cb(err); } - var assetHash = stringHash(''+data); + var assetHash = hashDigest.hex(''+data); clientResourcesWeb.push({ url: fetchEntry.url, type: fetchEntry.type, @@ -88,17 +78,15 @@ function renderTemplatePath(viewPath) { } function renderIndex() { - var inlineData = fs.readFileSync(__dirname+'/../dist/es5-ff-spa-loader.min.js'); - var inline = '\n\t\t'; - var inlineNot = '\n\t\t'; return function (req, res) { + var inlineScript = UglifyJS.minify(__dirname+'/../../es5-ff-spa-loader.js'); res.render('index', { - inlineNot: useInline?'':inlineNot, - inline: useInline?inline:'' + inlineScript: inlineScript.code }); }; } +// Add resources ORDERED per type addClientResource('/static/module/jquery/jquery.js','js'); addClientResource('/static/module/angular/angular.js','js'); addClientResource('/static/module/angular-route/angular-route.js','js'); @@ -106,8 +94,8 @@ addClientResource('/static/module/bootstrap/css/bootstrap.css','css'); addClientResource('/static/module/bootstrap/js/bootstrap.js','js'); addClientResource('/static/css/boot.css','css'); addClientResource('/static/css/style.css','css'); -addClientResource('/static/js/example-app.js','js'); -addClientResource('/static/js/controller/page-bar.js','js'); +addClientResource('/static/js/example-app.js','js'); // deps: jquery,angular +addClientResource('/static/js/controller/page-bar.js','js'); // deps: example-app.js addClientResource('/static/js/controller/page-foo.js','js'); addClientResource('/static/js/controller/page-index.js','js'); @@ -117,30 +105,17 @@ server.use(cors({credentials: true, origin: '*'})); server.set('view engine', 'ejs'); server.set('views', path.join(__dirname,'www_views')); server.use('/static', express.static(path.join(__dirname,'www_static'))); -server.use('/static/module/bootstrap', express.static(path.join(__dirname,'node_modules/bootstrap/dist'))); -server.use('/static/module/jquery', express.static(path.join(__dirname,'node_modules/jquery/dist'))); -server.use('/static/module/angular', express.static(path.join(__dirname,'node_modules/angular'))); -server.use('/static/module/angular-route', express.static(path.join(__dirname,'node_modules/angular-route'))); +server.use('/static/module/bootstrap', express.static(path.join(__dirname,'../node_modules/bootstrap/dist'))); +server.use('/static/module/jquery', express.static(path.join(__dirname,'../node_modules/jquery/dist'))); +server.use('/static/module/angular', express.static(path.join(__dirname,'../node_modules/angular'))); +server.use('/static/module/angular-route', express.static(path.join(__dirname,'../node_modules/angular-route'))); +server.get('/static/spa-client-resources', function (req,res) {res.json({data: {resources: clientResourcesWeb}});}); +server.get('/', function (req, res) {res.redirect('/example-ui');}); +server.get('/example-ui/thtml/*', renderTemplatePath('thtml/')); +server.get('/example-ui', renderIndex()); -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) { - res.json({data: {resources: clientResourcesWeb}}); -}); - -server.get('/', function (req, res) {res.redirect('/example-ui');}); -server.get('/example-ui/thtml/*', renderTemplatePath('thtml/')); -server.get('/example-ui', renderIndex()); -console.info('Server config done.'); - -server.listen(8080); -console.info('Server started on port 8080'); +server.listen(httpPort); +console.info('Server started on port '+httpPort); var res = createClientResourceFetchList(); fetchHashResources(res, function(err) { diff --git a/example/www_static/css/boot.css b/example/app_server/www_static/css/boot.css similarity index 100% rename from example/www_static/css/boot.css rename to example/app_server/www_static/css/boot.css diff --git a/example/www_static/css/style.css b/example/app_server/www_static/css/style.css similarity index 100% rename from example/www_static/css/style.css rename to example/app_server/www_static/css/style.css diff --git a/example/www_static/js/controller/page-bar.js b/example/app_server/www_static/js/controller/page-bar.js similarity index 100% rename from example/www_static/js/controller/page-bar.js rename to example/app_server/www_static/js/controller/page-bar.js diff --git a/example/www_static/js/controller/page-foo.js b/example/app_server/www_static/js/controller/page-foo.js similarity index 100% rename from example/www_static/js/controller/page-foo.js rename to example/app_server/www_static/js/controller/page-foo.js diff --git a/example/www_static/js/controller/page-index.js b/example/app_server/www_static/js/controller/page-index.js similarity index 100% rename from example/www_static/js/controller/page-index.js rename to example/app_server/www_static/js/controller/page-index.js diff --git a/example/www_static/js/example-app.js b/example/app_server/www_static/js/example-app.js similarity index 100% rename from example/www_static/js/example-app.js rename to example/app_server/www_static/js/example-app.js diff --git a/example/www_views/index.ejs b/example/app_server/www_views/index.ejs similarity index 81% rename from example/www_views/index.ejs rename to example/app_server/www_views/index.ejs index eedc08b..f69d5b0 100644 --- a/example/www_views/index.ejs +++ b/example/app_server/www_views/index.ejs @@ -2,9 +2,10 @@ - Loading<%- inlineNot %> + Loading - <%- inline %> + +