2
0
Fork 0

Added mobile example app

This commit is contained in:
Willem 2016-01-24 21:38:21 +01:00
parent 4fbf705ae5
commit cf364fc418
26 changed files with 187 additions and 61 deletions

View file

@ -0,0 +1,125 @@
'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');
var UglifyJS = require("uglify-js");
var Hashes = require('jshashes');
var clientResourcesWeb = [];
var clientResources = {
js: [],
css: [],
cssData: []
};
var addClientResource = function(clientResource, resourceType) {
clientResources[resourceType].push(clientResource);
};
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 = hashDigest.hex(''+data);
clientResourcesWeb.push({
url: fetchEntry.url,
type: fetchEntry.type,
hash: assetHash
});
cb(null);
});
};
var fetchHashResources = function(fetchList, cb) {
var resourceStack = fetchList;
var resourceLoader = function() {
resourceStack = resourceStack.slice(1);
if (resourceStack.length === 0) {
cb(null);
} else {
fetchHashResource(resourceStack[0],resourceLoader);
}
};
fetchHashResource(resourceStack[0],resourceLoader);
};
var createClientResourceFetchList = function() {
var fetchList = [];
for (var clientResourceIdxJs in clientResources.js) {
var urlJs = clientResources.js[clientResourceIdxJs];
fetchList.push({url:urlJs,type:'js'});
}
for (var clientResourceIdxCss in clientResources.css) {
var urlCss = clientResources.css[clientResourceIdxCss];
fetchList.push({url:urlCss,type:'css'});
}
for (var clientResourceIdxCssData in clientResources.cssData) {
var urlCssData = clientResources.cssData[clientResourceIdxCssData];
fetchList.push({url:urlCssData,type:'cssData'});
}
return fetchList;
};
function renderTemplatePath(viewPath) {
return function (req, res) {
res.locals.query = req.query;
var qi = req.url.indexOf('?');
if (qi === -1) {
qi = req.url.length;
}
res.render(viewPath + req.url.substring(req.route.path.length-1, qi));
};
}
function renderIndex() {
return function (req, res) {
var inlineScript = UglifyJS.minify(__dirname+'/../../es5-ff-spa-loader.js');
res.render('index', {
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');
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'); // 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');
var server = express();
server.use(morgan('dev'));
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/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.listen(httpPort);
console.info('Server started on port '+httpPort);
var res = createClientResourceFetchList();
fetchHashResources(res, function(err) {
if (err !== null) {console.log(err);}
console.log('Total assets build: '+clientResourcesWeb.length);
});

View file

@ -0,0 +1,119 @@
body {
margin-top: 50px;
background-color: #222;
}
#wrapper {
padding-left: 0;
}
#page-wrapper {
width: 100%;
padding: 10px;
background-color: #fff;
}
.huge {
font-size: 50px;
}
.top-nav {
padding: 0 15px;
}
.top-nav>li {
display: inline-block;
float: left;
}
.top-nav>li>a {
padding-top: 15px;
padding-bottom: 15px;
line-height: 20px;
color: #999;
}
.top-nav>li>a:hover, .top-nav>li>a:focus, .top-nav>.open>a, .top-nav>.open>a:hover,
.top-nav>.open>a:focus {
color: #fff;
background-color: #000;
}
.top-nav>.open>.dropdown-menu {
float: left;
position: absolute;
margin-top: 0;
border: 1px solid rgba(0, 0, 0, .15);
border-top-left-radius: 0;
border-top-right-radius: 0;
background-color: #fff;
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
}
.top-nav>.open>.dropdown-menu>li>a {
white-space: normal;
}
ul.message-dropdown {
padding: 0;
max-height: 250px;
overflow-x: hidden;
overflow-y: auto;
}
li.message-preview {
width: 275px;
border-bottom: 1px solid rgba(0, 0, 0, .15);
}
li.message-preview>a {
padding-top: 15px;
padding-bottom: 15px;
}
li.message-footer {
margin: 5px 0;
}
ul.alert-dropdown {
width: 200px;
}
/* Side Navigation */
@media ( min-width :768px) {
.side-nav {
position: fixed;
top: 51px;
left: 225px;
width: 225px;
margin-left: -225px;
border: none;
border-radius: 0;
overflow-y: auto;
background-color: #222;
}
.side-nav>li>a {
width: 225px;
}
.side-nav li a:hover, .side-nav li a:focus {
outline: none;
background-color: #000 !important;
}
}
.side-nav>li>ul {
padding: 0;
}
.side-nav>li>ul>li>a {
display: block;
padding: 10px 15px 10px 38px;
text-decoration: none;
color: #999;
}
.side-nav>li>ul>li>a:hover {
color: #fff;
}

View file

@ -0,0 +1,59 @@
#wrapper {
padding-right: 0px;
padding-left: 0px;
}
.side-nav {
right: 0px;
left: 0px;
}
.btn {
margin-right: 10px;
}
.navbar-footer {
margin-left: 45%;
}
.navbar-toggle {
display: none;
}
.navbar-brand {
background-color: #C110D8;
}
.navbar-inverse .navbar-brand {
color: #FFFFFF;
}
.navbar-inverse .navbar-brand:focus {
outline: none;
}
.navbar-inverse .navbar-brand:hover {
background-color: #0F9A28;
outline: none;
}
.navbar-inverse {
background-color: #C110D8;
}
@media only screen and (-webkit-min-device-pixel-ratio: 1.3),
only screen and (-o-min-device-pixel-ratio: 13/10),
only screen and (min-resolution: 120dpi) {
body {
font-size:1.8em !important;
}
@media screen and (min-width: 1440px) {
body {
font-size:2em !important;
}
}
}

View file

@ -0,0 +1,10 @@
pageRouteInit.push(function ($routeProvider, $locationProvider) {
$routeProvider.when('/example-ui/bar', {
templateUrl: window.serverUrl+'/example-ui/thtml/bar',
controller: PageFoo
});
});
function PageFoo($scope, $http) {
}

View file

@ -0,0 +1,42 @@
var tpl = '<div><h2>Foo</h2><p>Welcome to the foo.</p></div>';
tpl += '<input type=\"button\" class=\"btn btn-default\" ng-click=\"doReload()\" value=\"Reload\"></input>';
tpl += '<input type=\"button\" class=\"btn btn-default\" ng-click=\"doClearServerUrl()\" value=\"Clear Server Url\"></input>';
tpl += '<input type=\"button\" class=\"btn btn-default\" ng-click=\"doClearCache()\" value=\"Clear Cache\"></input>';
tpl += '<p>{{message}}</p>';
pageRouteInit.push(function ($routeProvider, $locationProvider) {
$routeProvider.when('/example-ui/foo', {
template: tpl,
controller: PageFoo
});
});
function PageFoo($scope) {
$scope.message = '';
$scope.doReload = function () {
window.location.reload(true);
};
$scope.doClearServerUrl = function () {
FFSpaLoader.clearServerUrl(function(err) {
if (err) {
$scope.message = 'Error: '+err;
} else {
$scope.message = 'Cleared server url';
}
$scope.$apply();
});
};
$scope.doClearCache = function () {
FFSpaLoader.clearCache(function(err) {
if (err) {
$scope.message = 'Error: '+err;
} else {
$scope.message = 'Cleared cache';
}
$scope.$apply();
});
};
}

View file

@ -0,0 +1,10 @@
pageRouteInit.push(function ($routeProvider, $locationProvider) {
$routeProvider.when('/example-ui', {
template: '<div><h2>Example UI Index</h2><p>Welcome make yourself at home.</p></div>',
controller: PageIndex
});
});
function PageIndex($scope, $http) {
}

View file

@ -0,0 +1,27 @@
'use strict';
document.title = 'FFSpaLoader Example';
var serverUrl = window.FFServerUrl;
console.log('FFExample provided serverUrl \"'+serverUrl+'\"');
$(document.createElement('div')).attr('id', 'wrapper').appendTo($('body'));
$(document.createElement('div')).attr('ng-controller', 'ApplicationController').attr('ng-include', '\''+serverUrl+'/example-ui/thtml/header\'').appendTo($('#wrapper'));
$(document.createElement('div')).attr('id', 'page-wrapper').appendTo($('#wrapper'));
$(document.createElement('div')).attr('id', 'container-fluid').attr('ng-view', '').appendTo($('#page-wrapper'));
$(document.createElement('div')).attr('ng-include', '\''+serverUrl+'/example-ui/thtml/footer\'').appendTo($('body'));
var pageRouteInit = [];
var exampleUI = angular.module('exampleUI', ['ngRoute']).config(
['$routeProvider','$locationProvider','$sceDelegateProvider', function
($routeProvider , $locationProvider , $sceDelegateProvider) {
pageRouteInit.forEach(function(init) { init($routeProvider, $locationProvider); });
$sceDelegateProvider.resourceUrlWhitelist(['self',serverUrl+'/**']);
$routeProvider.otherwise({ redirectTo: '/example-ui' });
$locationProvider.html5Mode({requireBase: false});
}]);
exampleUI.controller('ApplicationController',function($scope,$http,$location) {
$scope.goLink = function ( path ) {
$location.path( path );
};
});

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Loading</title>
</head>
<body>
<script><%- inlineScript %></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>

View file

@ -0,0 +1,7 @@
<div><h2>Bar</h2><p>Welcome to the bar.</p><div class="table-responsive">
<table class="table table-bordered table-hover table-striped"><tbody>
<tr><th>Chair</th><th>Person</th><th>Drinking</th></tr></tbody><tbody>
<tr><td>seat 1</td><td>empty</td><td>none</td></tr>
<tr><td>seat 2</td><td>you</td><td>coffee</td></tr>
<tr><td>seat 3</td><td>cat</td><td>water</td></tr>
</tbody></table></div></div>

View file

@ -0,0 +1,5 @@
<nav class="navbar">
<div class="navbar-footer">
Example footer
</div>
</nav>

View file

@ -0,0 +1,13 @@
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" ng-click="goLink('/example-ui/')">Home</a>
<a class="navbar-brand" ng-click="goLink('/example-ui/foo')">Foo</a>
<a class="navbar-brand" ng-click="goLink('/example-ui/bar')">Bar</a>
</div>
</nav>