Table of Contents
Server-Side
Download Node.js release LTS Version from http://www.nodejs.org/
and follow the installation instructions for it.
Tested with Node.js version 12.18.0!
Create a project directory and install IOport Blip (Blip for short) into it.
$ npm install ioportblip
Let the above install complete and then follow it with the command below.
$ node node_modules/ioportblip/setup.js
Example
A new Framework directory will be present in the project directory after this step is complete.
Change to the Framework/Server directory.
You may remove the original installation files and directories, leaving only the Framework directory.
Note: Use the backslash "\" throughout this document if using the Windows OS.
Note: Use the backslash "\" throughout this document if using the Windows OS.
$ cd Framework/Server
Example
You can start the Blip server which is configured to run from
host localhost. Ensure your system is configured for this hostname.
Entering the node File-Server.js command will start the server.
$ node File-Server.js
Example
From within a browser enter the URL localhost to view the Blip client-side interface.
This application framework is designed to accomplish the following:
- Structured Management
- Code Integrity
- High Performance
- Expandability
- Flexibility
- Small Footprint
- Decrease Development Turnaround Time
Blip has two main directories at the root level which are Server and Assets. All the files are split respectfully according to how they are processed. The server activity data is located in the Logs directory.
- Blip
- Server
- Assets
- Logs
Directory
Templates are theme based and Blip is where you'll find all of the template filename.html.tpl files.
- Blip
- Server
- Templates
- Themes
- Blip
- Common
- Pages
- Sandbox
- Blip
- Themes
- Templates
- Server
Directory
Modules is where any server code additions should be kept that are outside of the main codebase.
- Blip
- Server
- Modules
- Server
Directory
Server configuration is done by altering and/or adding entries to the Configuration-Extension.js file located in the root Server directory.
Example entries and comments can be found in the File-Server.js file and no changes should be made to it when possible.
Rename Configuration-Extension.js.master to use.
- Blip
- Server
Configuration-Extension.js
Directory
Module configuration is done inside each individual module, in a file called Modules.js located in the server Modules directory.
Example entries and comments can be found in the Module-Skeleton-Basic.zip archive which can be used as a springboard for fresh module creation.
- Blip
- Server
- Modules
- Module Name
- Modules
- Server
Modules.js
Directory
const localhost = '127.0.0.1';
const domainName = 'localhost';
const svar = {
siteDomain: domainName,
serverIp: localhost,
serverPort: 80
}
JavaScript
A simple template initialization and implementation example.
var template = new blip.templateAssembler.TemplateEngine(blip.branch[
blip.svar.branchId.coreServicesUser].appUrl, true);
template.addFragFilePath( blip.path.templatesPagesDir + 'Page_Home-Body.html.tpl', false );
blip.server.httpApp.get(template.url, function (req, res) {
template.sendPage( req, res );
});
JavaScript
const localhost = '127.0.0.1';
const domainName = 'localhost';
const svar = {
siteDomain: domainName,
serverIp: localhost,
serverPort: 80
}
JavaScript
sslPassphrase is the password for the SSL certificate which is located in the designated SSL directory.
const svar = {
sslPassphrase: 'Local$1private'
}
JavaScript
The TemplateEngine class is the nuts and bolts that not only holds the framework together, but also allows control over its contents programmatically;
ofwhich, you'll discover as you become more familiar with the members inside.
The class constructor contains the parameters needed to control the data being served. The order of operation is a class object is initialized, then loaded with content fragments and other parameteres before serving a response by using one of its send methods.
class TemplateEngine {
constructor(url = null, flagCache = false) {
this.id = te_tEOCntr++; // Object ID
this.url = url; // URL of page
this.cache = { enabled: flagCache, data: null, time: null }; // Cache control object
this.cacheMemSize = 0; // Size of cache object
this.frag = []; // Holds all of the fragment objects
this.type = 'page'; // Page or fragment
templateEngineObjects.push(this); // Holds all of the initialized TemplateEngine objects
}
.
.
.
}
JavaScript
This class is part of the blip object and uses the syntax new blip.templateAssembler.TemplateEngine(...) to initialize.
Typically it will include the URL argument, but this is not required.
var template = new blip.templateAssembler.TemplateEngine(blip.branch[
blip.svar.branchId.coreServicesUser].appUrl + 'Documentation', true);
JavaScript
Adds data to a TemplateEngine object and returns its stored fragment id. To cache the data in memory set enabled to true.
var text = "AJAX return text.";
template.addFragData(text);
// or
template.addFragData(text, true);
JavaScript
Adds the filePath to a TemplateEngine object and returns its stored fragment id. To cache the file's contents in memory set enabled to true.
var filePath = "./filename.html.tpl";
template.addFragFilePath(filePath);
// or
template.addFragFilePath(filePath, true);
JavaScript
Adds the header includes code to a TemplateEngine object by passing the TemplateEngine
store id and an includes object. This method can be called multiple times, adding to the existing includes each time.
var htmlIncludes = { css: [{sipTag: '{sip var="commonCss" /}', externalFile: '<link rel="stylesheet" href="Buttons_Generic.css" />'}],
js: [{sipTag: '{sip var="commonJs" /}', externalFile: '<script src="Buttons_Generic.js"></script>'}] };
var templateFragPageHeaderId = template.addFragFilePath("Header-Filename.html.tpl", true );
template.addIncludesHeader(templateFragPageHeaderId, htmlIncludes);
JavaScript
Adds the footer includes code to a TemplateEngine object by passing the TemplateEngine
store id and an includes object. This method can be called multiple times, adding to the existing includes each time.
var htmlIncludes = { js: [{sipTag: '{sip var="commonJs" /}', externalFile: '<script src="Buttons_Special.js"></script>'}] };
var templateFragPageFooterId = template.addFragFilePath("Footer-Filename.html.tpl", true );
template.addIncludesHeader(templateFragPageFooterId, htmlIncludes);
JavaScript
Adds a string search and replace pair inside an object literal to a TemplateEngine object by passing the TemplateEngine
store id and an object (obj) containing the two string pairs. This method can be called multiple times,
adding to the existing entries each time.
A RegExp object can be used for the srcStr property.
var sourceString = "foo"
var replaceString = "bar";
template.addStrReplace(id, {srcStr: sourceString, rplStr: replaceString});
JavaScript
Returns the fragment associated with the id.
var frag = template.getFrag(id);
JavaScript
Send a server response text msg.
The status code 200 and "'Content-Type', 'text/html'" will precede the msg by default.
template.sendError(res, "Error: This is an error message!");
// or
template.sendError(res, "Error: This is an error message!", false); // No header information is sent.
JavaScript
Sends the entire page including all of the added fragments to the template object and any header and/or footer includes. The fragments are sent in the order they were added unless changed.
The status code 200 and "'Content-Type', 'text/html'" will precede the page by default.
template.sendPage(req, res);
// or
template.sendPage(req, res, false); // No header information is sent.
JavaScript
Sends response text without needing to initializate a TemplateEngine object.
No status or header information is sent with this server response.
var msg = "Arbitrary text."
blip.templateAssembler.TemplateEngine.sendText(res, msg);
JavaScript
Sends response text without needing to initialize a TemplateEngine object.
The status code 200 and "'Content-Type', 'text/html'" will precede the page by default.
var msg = "Arbitrary text."
blip.templateAssembler.TemplateEngine.sendTextHtmlPage(res, msg);
JavaScript
If true this method will check if the page cache memory is enabled and sends the entire page including all of the added fragments to the template object and any header and/or footer includes.
No page is sent if the return value is false.
var sentCachedPage = template.sendPageCacheHandler(req, res, id);
JavaScript
Sets a template object's fragment memory cache enabled state to true or false.
template.setFragCacheState(templateFragId, true);
JavaScript
Updates a template object's fragment memory cache data store associated with its id.
var cachedData = "New cached data.";
template.updateFragCache(templateFragId, cachedData);
// or
template.updateFragCache(templateFragId, cachedData, false);
JavaScript
Updates a template object's fragment data store associated with its id.
var newData = "New data.";
template.updateFrag(templateFragId, newData);
// or
template.updateFrag(templateFragId, newData, true);
JavaScript
Updates a template object's fragment SIP (Server Induced Population) data associated with its id.
var sipData = {dbItem1: 'Foo', dbItem2: 'Bar'};
template.setFragSipKeyedData(templateFragId, sipData);
JavaScript
Contains the amount of memory the template object is using.
var templateMemoryUsed = template.cacheMem;
JavaScript
Contains all of the TemplateEngine initialized objects.
var templateObjects = blip.templateAssembler.TemplateEngine.objects;
JavaScript
The blip.templateAssembler object contains class methods and functions used to assemble content into usable server responses.
The blip.templateAssembler object's functions exist outside of the TemplateEngine class and no template initialization is required to use them.
The TemplateEngine class is mentioned here since it is part of the blip.templateAssembler object and its documentation can be found here.
Returns the contents of a template file.
var fileContents = blip.templateAssembler.getContentsFromTplFile("./filename.html.tpl");
JavaScript
Returns a text string with a SIP operation performed.
var text = "The quick red {sip var="animal" /} jumped."
var sippedText = blip.templateAssembler.performStringSip(text, "animal", "fox");
console.log(sippedText);
//Output: The quick red fox jumped.
JavaScript
Returns the string indices from a string containing SIP loop tags.
SIP loop tag Example: {sipLoop id="TemplateEngine"}...{sipLoopSplit var="id" /}...{/sipLoop}
var fragIndices = blip.templateAssembler.getLoopFragIndices(str);
JavaScript
Returns a sorted loop fragment object.
var sortedFrags = blip.templateAssembler.getSortFragLoops(str);
JavaScript
Returns a string of assembled frag loops containing template sipLoopSplit variable data.
var fragWithLoop = '{sipLoop id="TemplateEngine"}
<div>{sipLoopSplit var="id" /}</div><div>{sipLoopSplit var="url" /}<div>
{/sipLoop}';
var loopData = {TemplateEngine: [
{id: 0,
url: "http://localhost"},
{id: 1,
url: "http://localhost/Core"},
{id: 2,
url: "http://localhost/Cp"}
]};
var sortedFragLoop = blip.templateAssembler.getSortFragLoops(fragWithLoop);
var assembledLoopFrag = blip.templateAssembler.assembleLoopFragData(sortedFragLoops, loopData);
console.log(assembleLoopFrag);
/* Output
<div>0</div><div">http://localhost<div>
<div>1</div><div>http://localhost/Core<div>
<div>2</div><div>http://localhost/Cp<div>
*/
JavaScript
Returns a small .png filler image URL from the Assets/Common/Images directory.
var imageUrl = blip.utilities.fillerImage();
JavaScript
Returns a JSON object from the JSON source object with all of its members decoded using node.js's decodeURIComponent().
var decodedJsonObj = blip.utilities.JSONDecodeURIComponent(json);
JavaScript
Returns a database results set with all of the field values = ''.
To be used with the mysql node module which can be installed using $ npm install mysql.
var emptyResults = blip.utilities.returnEmptyResults(fields);
JavaScript
Returns all SIP elements within text with No results.
To be used with the mysql node module which can be installed using $ npm install mysql.
var emptyResults = blip.utilities.splitFillNoResults(text);
JavaScript
Stores selected server request members to the blip.server.appConnQueReqLogging object.
blip.utilities.storeReqLogParams(req);
// Example from source.
function storeReqLogParams(req){
blip.server.appConnQueReqLogging = {
url: req.url || 'NA',
method: req.method || 'NA',
ip: req.ip || 'NA',
host: ((req.headers != undefined) ? req.headers.host || 'NA' : 'NA'),
referer: ((req.headers != undefined) ? req.headers.referer || 'NA' : 'NA'),
lang: ((req.headers != undefined) ? req.headers['accept-language'] || 'NA' : 'NA'),
userAgent: ((req.headers != undefined) ? req.headers['user-agent'] || 'NA' : 'NA'),
cookieId: ((req.headers != undefined) ? req.headers.cookie || 'NA' : 'NA')
};
}
JavaScript
Sends server request information with a message to the logs.
var msg = "Log this message.";
blip.utilities.logRequest(null, msg);
JavaScript
Sends server request information and/or a message to the logs.
var msg = "Log this message.";
blip.utilities.requestFailedHandler(null, msg);
JavaScript
Adds a layer of error checking by performing an argument type validation defined in the ops object.
function assembleLoopFragData(dataObj, loopData = {}){
if(!blip.utilities.argIntegrityCheck([
{op: dataObj, type: 'object', subType: 'array'},
{op: loopData, type: 'object', subType: 'object literal'}
])) return -1;
.
.
.
}
JavaScript
Blip uses winston and winston-daily-state-file Node.js modules for its logging code foundation. Additional documentation
that is not included in this document can be found in its corresponding npm repository.
Add any of the below svar members to the Configuration-Extension.js file to override the members in the File-Server.js file.
var svar = {
logToConsole: false,
flagVerbose: true,
logDir: '/../../../Logs',
logInfoFileNamePrefix: 'Log_Server-Info',
logErrorFileNamePrefix: 'Log_Server-Error',
logFileNameExt: '_%DATE%.log',
logTimestamp: 'YYYY-MM-DD hh:mm:ss.SS',
logDatePattern: null,
logFrequency: null,
logMaxSize: '10m',
logMaxFiles: '90d',
}
JavaScript
Customizing the Blip logger can be done by accessing the blip.server.logger, blip.server.loggerInfoErr, blip.server.loggerInfo, and blip.server.loggerErr objects.
The source code can be found in the Server/Core/Common/Common_Utilities.js file.
blip.server.logger;
blip.server.loggerInfoErr;
blip.server.loggerInfo;
blip.server.loggerErr;
JavaScript
There are two different types of plug-and-play modules within Blip which are Core and user supplied. The Core modules are supplied by IOport and should not be used by the end user; whereas, the user supplied modules are
supplied by the end user or a 3rd party.
Core is reserved for IOport supplied modules.
- Blip
- Server
- Modules (user supplied location)
- Core (reserved for IOport supplied modules)
- Modules (user supplied location)
- Server
Directory
Supplied is a Module-Skeleton-Basic archive that can be used as a module creation springboard. The installed version has a
Module-Configuration.js file that functions in the same way as the Configuration-Extension.js file.
- Blip
- Server
- Modules
- Skeletons
- Modules
- Server
Directory
To install a module, all that is required is to put the module archive into the Modules directory and restart the server. In this case we will use the Module-Skeleton-Basic
skeleton. After restarting the server you will see new log entries and a new module directory in Modules. Any archives are moved to the ./TmpPackages directory after installation.
{"message":"Loading module: Module-Skeleton-Basic","level":"info","timestamp":"2019-10-19 11:35:39.57"}
Log Entry
- Blip
- Server
- Modules
- Module-Skeleton-Basic
- Modules
- Server
Directory
Client-Side
Blip organizes its client-side assets into common and themes based directory trees. As good practice, any Blip included assets and their locations should never
be moved or altered in any way to help ensure code integrity if updates are applied. End user or 3rd party assets should be added to a newly created
common and/or themed directory tree.
All javascript code is isolated using (function (){...})(); wrappers and any global activity is done with the GLOBAL object found in Main.js.
Assets used for styling and special purposes.
- Assets
- Themes
- Blip
- Common
- Images
- Buttons
- ...
- Blip
- Themes
Directory
Server-side configuration settings are found in the File-Server.js file and changes should follow the Core Server documentation.
const svar = {
cssExt: 'css',
jsExt: 'js',
styleTheme: 'Blip'
.
.
.
}
const path = {
serverAssetsDir: __dirname + '/../Assets/',
AssetsCommonImagesDir: '/Assets/Common/Images/',
AssetsCommonJsDir: '/Assets/Common/Js/',
AssetsCommonCssDir: '/Assets/Common/Css/',
AssetsThemeCommonJsDir: '/Assets/Themes/' + svar.styleTheme + '/Common/Js/',
.
.
.
}
JavaScript
Client-side configuration settings are found in the Main.js file with the settings located in the
GLOBAL object.
- Assets
- Common
- Js
- Main.js
- Js
- Common
Directory
var GLOBAL = {
displayErrors: {type: "popup"}, // type: <"none" | "popup" | "console">
themeNames: {blip: 'Blip'},
domain: 'localhost',
httpURLHostname: 'http://',
httpsURLHostname: 'https://',
httpPort: '', // Ex: ':8000', optional, default will be used if empty.
httpsPort: '', // Ex: ':4443', optional, default will be used if empty.
appURL: '/', // Application URL example: '/' or '/app/'
popups: {shadow: undefined},
onWindowLoadFunc: undefined,
flagIsTouch: false,
flagIsSilkBrowser: false,
touchBottomAdjValue: 40,
emailCheck: /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
utility: {}, // Used for utility functions. To initialize use GLOBAL.utility.[<name>] = <functionName>;
onWindowLoadRun: [] // Used to run extension functions on the window.onload event. To initialize use GLOBAL.onWindowLoadRun.push(<functionName>);
};
JavaScript
Blip uses the CSS @media style modifier to compensate for screen size variations which allows for a rich interactive experience whether viewing from the desktop or mobile devices.
Blip detects touch devices and dynamically loads files with dedicated CSS @media style modifiers that enhance the interface for touch use.
Below is an example used by Blip for Buttons Generic.
GLOBAL.utility.addCssFileTouch("/Assets/Themes/Blip/Buttons/Css/Buttons_Generic_Touch.css");
Javascript
By default Blip uses the BlipDynamoTabs menu theme and it resides inside the Blip style theme directory tree.
This menu is intended to be used as main site navigation and the active tab states will not be functional in the below example.
Example
- Assets
- Themes
- Blip
- Menus
- BlipDynamoTabs
- Menus
- Blip
- Themes
Directory
To use add the ./Css/Menus.css and the ./Js/Base/Menu-Base.js to your HTML page using
TemplateEngine.addIncludesHeader(id, includes) and then add the below syntax to the javascript file dedicated to your page layout.
linkAlternative is optional and can be used with a single URL or an array of URLs. Used to set active state of tab along with link.
urlParamParsers is optional and can be used to split URLs so tabs can become active.
linkAlternative and urlParamParsers are only used as topMenu object members.
(function (){
init();
function init(){
GLOBAL.run.push(initTopMenuButtons);
}
let urlParamParsers = ['#','?']; // Used to split URLs so tabs can become active.
function initTopMenuButtons(){
menuGroup = [
{idName: 'flyoutPanel', link: '*'},
{topMenu: {id: 'buttonTopMenuBarTabHome',
name: 'Home',
urlParamParsers: urlParamParsers,
link: GLOBAL.httpURL + GLOBAL.appURL,
linkAlternative: 'http://' + GLOBAL.domain + GLOBAL.appURL, // Optional
style: 'top-menu-bar-tab-left',
styleActive: 'top-menu-bar-tab-active',
styleTabEffect: 'top-menu-bar-tab-wrapper',
styleTabEffectActive: 'top-menu-bar-tab-wrapper-active',
styleText: 'text-padding-8px',
styleTextActive: null,
styleTextEffect: null,
styleTextEffectActive: null,
styleFiller: 'top-menu-bar-tab-filler',
styleFillerActive: 'top-menu-bar-tab-filler-active',
width: null,
textAlign: 'left'},
flyoutMenu: {id: 'buttonFlyoutMenuHome',
name: 'Home',
link: GLOBAL.httpURL + GLOBAL.appURL,
style: 'flyout-menu-button',
styleActive: 'flyout-menu-button-active'}},
.
.
.
];
var BDT = GLOBAL.utility.BlipDynamoTabs();
BDT.topMenuBarCondensedElement = 'topMenuBarCondensedTab';
BDT.topMenuBarContainerElement = 'topMenuBarContainer';
BDT.initParentMenu(menuGroup);
}
})();
JavaScript
Use ./Js/Menus.js along with the Header.html.tpl template file found in the Common directory as an example.
Blip button assets are located in the Blip/Buttons themes directory and the style rules found in ./Css/Buttons_Generic.css.
- Assets
- Themes
- Blip
- Buttons
- Blip
- Themes
Directory
Example
HTML
let button = document.getElementById("button");
button.onclick = function(){
// action
}
JavaScript
Example
HTML
This is a sample Text link.
Example
This is a sample Text link.
HTML
Load data asynchronously to a webpage using the CommXmlHttp class.
- Assets
- Common
- Js
- Comm.js
- Js
- Common
Directory
Initialize the URL to send a request to.
comm.setUrl("http://locahost.com/ajax");
JavaScript
Delays the execution of the setOnTimeoutFunc(func) assigned function if it is set.
let count = 250; //Milliseconds
comm.setTimeout(count);
JavaScript
Assigns a function to be executed after a successful request reply using a delay which is set with setTimeout(count).
let func = function(){
.
.
.
}
comm.setOnTimeoutFunc(func);
JavaScript
Assigns a function to be executed before a successful request reply.
let func = function(){
.
.
.
}
comm.setPreReqFunc(func);
JavaScript
Assigns a function to be executed after a successful request replies with results.
this.responseData comes directly from the comm object and should use this exact syntax.
let func = function(){
let data = this.responseData;
.
.
.
}
comm.setPostResFunc(func);
JavaScript
Assigns the target element to update its inner HTML contents and a loader animation element if present. The loaderId is optional.
let targetId = "innerHTMLParent";
let loaderId = "targetLoader"; // Optional
comm.setResTarget(targetId, <loaderId or null>);
JavaScript
Assigns a new target loader function and its arguments which replaces the default in the comm object.
Example
HTML
let args = {xmlHttpOpenAsync: false}; //Optional, sets xmlHttp.open(...) async state. Default is true.
function func(){
.
.
.
};
comm.setTargetLoaderFunc(func, <args or null>);
JavaScript