Added mobile example app
This commit is contained in:
parent
4fbf705ae5
commit
cf364fc418
9
.gitignore
vendored
9
.gitignore
vendored
|
@ -15,7 +15,14 @@ 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
|
||||
|
|
20
README.md
20
README.md
|
@ -161,7 +161,23 @@ 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 <repro-url>
|
||||
* 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
|
||||
|
||||
|
@ -203,6 +219,8 @@ 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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
38
example/app_mobile/config.xml
Normal file
38
example/app_mobile/config.xml
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<widget id="net.forwardfire.spa.loader" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
|
||||
<name>FFSpaLoaderExample</name>
|
||||
<description>
|
||||
A sample FFSpaLoader example application.
|
||||
</description>
|
||||
<author email="ffspaloader.example.2016@forwardfire.net" href="http://forwardfire.net">
|
||||
FFSpaLoaderExample
|
||||
</author>
|
||||
<content src="index.html" />
|
||||
<plugin name="cordova-plugin-whitelist" spec="1" />
|
||||
<plugin name="cordova-sqlite-storage" spec="1" />
|
||||
<access origin="*" />
|
||||
<icon src="www/img/ic_launcher_mdpi.png" />
|
||||
<icon src="www/img/ic_launcher_mdpi.png" platform="android" density="ldpi" />
|
||||
<icon src="www/img/ic_launcher_mdpi.png" platform="android" density="mdpi" />
|
||||
<icon src="www/img/ic_launcher_hdpi.png" platform="android" density="hdpi" />
|
||||
<icon src="www/img/ic_launcher_xhdpi.png" platform="android" density="xhdpi" />
|
||||
<allow-intent href="http://*/*" />
|
||||
<allow-intent href="https://*/*" />
|
||||
<allow-intent href="tel:*" />
|
||||
<allow-intent href="sms:*" />
|
||||
<allow-intent href="mailto:*" />
|
||||
<allow-intent href="geo:*" />
|
||||
<platform name="android">
|
||||
<allow-intent href="market:*" />
|
||||
<!-- Build for lowest version of cordova 5.x -->
|
||||
<preference name="android-minSdkVersion" value="14" />
|
||||
</platform>
|
||||
<platform name="ios">
|
||||
<allow-intent href="itms:*" />
|
||||
<allow-intent href="itms-apps:*" />
|
||||
<!-- disable backup to ICloud of db file -->
|
||||
<preference name="BackupWebStorage" value="none"/>
|
||||
</platform>
|
||||
<hook type="before_build" src="scripts/copy-ff-spa-loader.js" />
|
||||
<hook type="after_build" src="scripts/rename-android-apk.js" />
|
||||
</widget>
|
3
example/app_mobile/platforms/platforms.json
Normal file
3
example/app_mobile/platforms/platforms.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"android": "4.1.1"
|
||||
}
|
18
example/app_mobile/plugins/android.json
Normal file
18
example/app_mobile/plugins/android.json
Normal file
|
@ -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": {}
|
||||
}
|
18
example/app_mobile/plugins/fetch.json
Normal file
18
example/app_mobile/plugins/fetch.json
Normal file
|
@ -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": {}
|
||||
}
|
||||
}
|
16
example/app_mobile/scripts/copy-ff-spa-loader.js
Normal file
16
example/app_mobile/scripts/copy-ff-spa-loader.js
Normal file
|
@ -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;
|
||||
}
|
15
example/app_mobile/scripts/rename-android-apk.js
Normal file
15
example/app_mobile/scripts/rename-android-apk.js
Normal file
|
@ -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;
|
||||
}
|
BIN
example/app_mobile/www/img/ic_launcher_hdpi.png
Normal file
BIN
example/app_mobile/www/img/ic_launcher_hdpi.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
BIN
example/app_mobile/www/img/ic_launcher_mdpi.png
Normal file
BIN
example/app_mobile/www/img/ic_launcher_mdpi.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
BIN
example/app_mobile/www/img/ic_launcher_xhdpi.png
Normal file
BIN
example/app_mobile/www/img/ic_launcher_xhdpi.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
20
example/app_mobile/www/index.html
Normal file
20
example/app_mobile/www/index.html
Normal file
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src * 'self' 'unsafe-inline' 'unsafe-eval' data: gap:">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="msapplication-tap-highlight" content="no">
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript" src="cordova.js"></script>
|
||||
<script type="text/javascript" src="es5-ff-spa-loader.js"></script>
|
||||
<script>
|
||||
FFSpaLoader.options.debug.enable = true;
|
||||
FFSpaLoader.options.boot.angular.modules.push('exampleUI');
|
||||
FFSpaLoader.options.server.assets = '/static/spa-client-resources';
|
||||
FFSpaLoader.start();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -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<script>'+inlineData+'</script>';
|
||||
var inlineNot = '\n\t\t<script src=\"/static/es5-ff-spa-loader.js\"></script>';
|
||||
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.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.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());
|
||||
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) {
|
|
@ -2,9 +2,10 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<title>Loading</title><%- inlineNot %>
|
||||
<title>Loading</title>
|
||||
</head>
|
||||
<body><%- inline %>
|
||||
<body>
|
||||
<script><%- inlineScript %></script>
|
||||
<script>
|
||||
FFSpaLoader.options.debug.enable = true;
|
||||
FFSpaLoader.options.boot.angular.modules.push('exampleUI');
|
|
@ -4,7 +4,7 @@
|
|||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node example.js"
|
||||
"start": "node app_server/example.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"angular": "^1.4.8",
|
||||
|
@ -15,6 +15,8 @@
|
|||
"express": "4.11.x",
|
||||
"fetch": "0.3.x",
|
||||
"jquery": "^2.1.4",
|
||||
"morgan": "^1.6.1"
|
||||
"jshashes": "^1.0.5",
|
||||
"morgan": "^1.6.1",
|
||||
"uglify-js": "^2.6.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,10 +48,6 @@
|
|||
"dependencies": {},
|
||||
"files": [
|
||||
"README.md",
|
||||
"example/www_static/",
|
||||
"example/www_views/",
|
||||
"example/example.js",
|
||||
"example/package.json",
|
||||
"dist/"
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue