Skip to content

Instantly share code, notes, and snippets.

@TechNinjaWeb
Created December 26, 2015 00:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TechNinjaWeb/e846e9a5059f5d638162 to your computer and use it in GitHub Desktop.
Save TechNinjaWeb/e846e9a5059f5d638162 to your computer and use it in GitHub Desktop.
Custom App - Module Installer - Test Using Require
define(function (require) {
// Function Executes with window[your-module.namespace]
// && selector of div to hold alerts eg: <div id='alert'></div>
// || <div class="alert"></div>
return (function(m, selector) {
// Define The Module To Be Instantiated
var that;
var AlertSystem = that = new m.constructor({
name: 'AlertSystem',
state: {
current: "Alerts Module Initialized",
last: m.getModuleProperty('state').prototype.memory
},
init: this.init
});
// Define App Boundaries
that.primaryNode = m.getModuleProperty('node');
// Return Any Element By Id
that.getNode = function(id) {
var type = id[0] === "." ? 'class' : id[0] === "#" ? 'id' : 'undefined';
// Return Node
return document.querySelectorAll(id)[0];
}
/**
* This tiny script just helps us demonstrate
* what the various example callbacks are doing
*/
that.Alerts = (function() {
"use strict";
// Apend Alerts Container to Body
var alerts = document.createElement('div');
alerts.id = "alert",
alerts.className = "alert-system",
alerts.style.display = "none";
var span = document.createElement('span');
span.innerHTML = "Loading Notification System";
// Create Text Span and append to alerts div
alerts.appendChild(span),
// Append alerts to body
document.body.appendChild(alerts);
// Initialize Private Variables
var elem,
hideHandler,
self = {};
// Run Custom Options
self.init = function(options) { // Set Element By options.selector
elem = !options ? alerts : document.querySelectorAll(options.selector)[0];
};
// Function to Show Alerts To Client
self.log = function(text, args, alertType) {
clearTimeout(hideHandler);
// Add Alert Type To Element
if (!!alertType) elem.classList.add(alertType);
// Set HTML Text
elem.firstChild.innerHTML = text + " " + args || text;
// Find Element To Fade
var el = document.querySelector(selector);
// Fade Node Function with auto init();
self.fadeNode = (function(el) {
// Fade In with Init()
(function fadeIn() {
return new Promise(function(resolve, reject) {
setTimeout(function() { el.classList.remove('fade-out'); resolve(el.classList.add('fade-in')); }, 100)
}).then(function(res) { setTimeout(function() { el.style.display = 'block'; fadeOut(); }, 100); })
}());
// Fade Out
function fadeOut() {
return new Promise(function(resolve, reject) {
setTimeout(function() { el.classList.remove('fade-in'); resolve(el.classList.add('fade-out')); }, 2500)
}).then(function(res) { setTimeout(function() { el.style.display = 'none'; !!alertType ? el.classList.remove( alertType ) : null }, 2500); })
}
// Return the log function;
return self.log;
}(elem));
};
return self;
}());
// Define the Selector To Search For
// And Initialize the Alert
that.init = function() {
// Initialize The Alerts Module
!!selector ? that.Alerts.init({"selector": selector}) : that.Alerts.init();
// Set Alert System As Active Messaging Service
m.getModuleProperty('messaging').active = that.Alerts
m.getModuleProperty('messaging').active.Class = 'alert-info';
}
// Install the module to App Modules list
m.prototype.installModule(that);
}( require('modules/main-module') ))
});
// For any third party dependencies, like jQuery, place them in the lib folder.
// Configure loading modules from the lib directory,
// except for 'app' ones, which are in a sibling
// directory.
requirejs.config({
baseUrl: '',
paths: {
app: 'modules'
}
});
// Load the primary constructor,
// Define the app and Instantiate
// Each Module with main as the object
requirejs(['modules/main-module'], function(main){
requirejs(['modules/alerts-module'])
requirejs(['modules/local-storage-module'])
requirejs(['modules/user-module'])
requirejs(['modules/http-module'])
requirejs(['modules/events-module']),
requirejs(['js/examples'])
});
console.log("Loaded App.js");
define(function (require) {
return (function(m){
var that;
// Define The Module To Be Instantiated
var EventManager = that = new m.constructor({ name: 'EventManager',
state: {current: "Event Manager Initialized",
last: m.getModuleProperty('state').prototype.memory
} });
// Event Node Creation Function
that.createEvent = function(name, eventObject) { return new CustomEvent(name, eventObject); }
// Default Node Creation
that.createNode = function(id, eventName, listener, options) {
if (!id || !listener || !eventName) return "Arguments Not Valid Got " + arguments.length + " arguments. Need 3 arguments";
var node = document.createElement('div');
node.id = id;
// Add Options to node
if (options) for (var property in options) { node[property] = options[property]; }
// Add Event Listenr
node.addEventListener(eventName, listener);
return node;
}
that.setEvent = function(id, eventData, listener, options) {
// Return if defaults not mset
if (!id || !listener || !eventData) return "Arguments Not Valid Got " + arguments.length + " arguments. Need 3 arguments";
// Create Event and Event Node
var event = this.createEvent(eventData.name || id, eventData.data);
console.warn("Here's the event", event, eventData);
var node = this.createNode(id, listener, options || {});
console.warn("Your node sir", node);
// Register Node to Event Module
this.registerEvent(event, node, listener);
return {event: event, node: node};
}
// Send Node Through System
that.sendEvent = function(node, event) {
if (document.createEvent) {
// console.log("Dispatching Event", event);
return node.dispatchEvent(event);
} else {
// console.log("Firing Event", event);
return node.fireEvent("on" + event.eventType, event);
}
}
// Create Internal Dom Node
// To Respond To Events
that.responderNode = (function(EM, m) {
EM.responder = document.createElement('div');
EM.responder.id = EM.name;
EM.responder.className = "default-node";
EM.responder.module = {};
EM.responder.data = {default: 'value is this'};
EM.responder.addEventListener(EM.name, function(e){
console.log("I Will Respond Shortly ...", e.detail);
return this;
});
EM.responder.listener = [].push(EM.responder);
return EM.responder;
}(EventManager, m));
// Add Event Listener to document
that.registerEvent = function(event, node, cb) {
var elem = !node ? window.document : node;
// Attach Event Listener
if (!cb) elem.addEventListener(event.type, node);
else elem.addEventListener(event.type, cb);
// Set The Listener's Copy On The Element
if (cb) elem.listener = [].push(cb);
// Test Event Fire
var event = new CustomEvent('EventManager', {detail: {message: 'Got It'}});;
// Return The Dom Nodes To This Function
// return that.responderNode.push(elem) && that.responderNode;
return that.responderNode.appendChild(node) && that.responderNode;
}
// Convert an element node into a JSON object
that.getNode = function(id) {
var type = id[0] === "."
? 'class'
: id[0] === "#"
? 'id' : 'undefined';
// Responder Nodes Definition
var def = that.responderNode;
// Definitions Children
var elems = def.children;
// Return the Node That is Equal To id
// console.log("Truth?", "#" + el.id, id, "#" + el.id == id)
var idx = Array.prototype.slice.call(elems).filter(function(el, i, a){
return ("#" + el.id) == id;
});
// Determine if IDX Is valid,
// Return def if idx returns nothing
if (idx.length <= 0) return def;
// Return IDX since it contains node ref
else if (idx) return idx[0];
// Handle Uncaught Error
else return "Don't Know What To Return";
}
// Install the module to App Modules list
m.prototype.installModule(that);
// Set Event Manager As Default
var events = m.getModuleProperty('events');
events.prototype.setEventSystem(that);
// Hide Enumeration
Object.defineProperty(events, 'prototype', {enumerable: false});
// Disable Enumeration For Functions
that.prototype.disableFunctionEnumeration(that);
}( require('modules/main-module') ))
});
define(function (require) {
// Define the app and Instantiate
// Each Module
var app = window.TechNinjaModule = require('../modules/main-module');
// require('../modules/alerts-module')(app);
// require('../modules/events-module')(app);
// require('../modules/http-module')(app);
// require('../modules/local-storage-module')(app);
// require('../modules/user-module')(app);
console.log("Examples", app);
/*
This allows an object to be created
using the "new" constructor and it takes on
properties of the main module using the
this.namespace property
eg: var bob = new TechNinjaModule.constructor({name: 'test', properties: [undefined]});
*/
/*
Events Module will allow you to create
A messaging service between modules and
Page elements
*/
/*
// create ref to Event Manager
var EventManager = app.getModuleProperty('modules').EventManager;
// Must Use Detail Property To Send Data
// Name Is Optional
var eventObject = {name: 'CustomEventMagic', detail: {message: "This is the sweetest thing ever!"}};
// Create A Listner Function
var listener = function(event){
console.log("This Node Has Heard Your Request");
// Advanced: Tap into Alert System Module
app.getModuleProperty('modules').AlertSystem.sendMessageToClient("Your Welcome", "");
// Turn Off Messaging Service
app.turnOffMessaging();
}
// Store Event Ref
var eventNode = EventManager.setEvent('myEventNode', eventObject, listener, {className: "my-class-name", data: eventObject, fakeProperty: "I am cool!"});
console.log("Here's the Event & Node", eventNode);
// Send Something to this node
setTimeout(function(){
// Turn Messaging System On
app.turnOnMessaging();
// Enjoy Messaging Service
EventManager.sendEvent(eventNode.node, eventNode.event);
}, 4000)
*/
/* Example Of Alert */
/*
// Ref to Module
var alerts = app.getModuleProperty('modules').Alerts;
// Create Your Custom Alert
var sendAlert = function(message) { alerts.log(message, "", 'alert-success') };
*/
/*
Example Below:
This module allows you to set and retrieve data
From the browsers local storage
*/
/*
setTimeout(function(){
// Set Storage System Refs
var storageSystem = app.getModuleProperty('modules').StorageSystem.storage;
// Local Cache Ref
var localStore = app.getModuleProperty('modules').StorageSystem.storage.cache;
// Store Data
storageSystem.save('some-data', 'Hello World');
// Retrieve Your Item By ID/Property Name
var getData = storageSystem.get('some-data');
console.log("Your Item Saved As", '"'+getData+'"');
console.log("Don't Believe Me, Check The Storage Adapters", app.getModuleProperty('modules').StorageSystem.storage);
}, 1);
*/
/*
Example below shows how to save
and retrieve a user from the local cache
*/
/*
// Create Module Ref
var UserModule = app.getModuleProperty('modules').UserModule;
// Save A User
var saveUser = UserModule.saveUser({name: 'ben johnson', age: 25});
// Get All Users In DB
var getAll = UserModule.getUser();
console.log("Here Are All Users", getAll);
// Retrieve The User You've Created
var getBen = UserModule.getUser('name', 'ben');
console.log("This is Ben", getBen[0]);
*/
/* Example 2:
Set Config Object
Request Headers is optional
*/
/*
// Create Ref to HTTP Module
var http = require('modules/main-module').getModuleProperty('modules').HTTP;
// Basic GET Example
// Create Callback Object
var callback = {
success: function(e){
console.log("response", [e]);
return e;
},
error: function(e){
console.log('got error', e);
return e;
}
};
// Create Your Request
var request1 = http.request('/index.html', callback).then(function(res){ console.log("got response"); return res; });
// Second Chain Method
request1.then(function(res){ console.log("Second Chain", [res]); });
// Example 2:
// Timeout Only for Example. Not required
setTimeout(function(){
var config = {url: '/index.html', method: 'GET', requestHeaders: []};
// Make Your Request on the Config
var request2 = http.request(config);
// Chain Your request object
// Make sure to return res to continue chain
request2.then(function(res){console.log("First Chain"); return res;});
// Continue chaining ...
request2.then(function(res){console.log("Second Chain", [res]); return res}).then(function(res){console.log("Last Chain", [res])});
}, 1000);
*/
});
define(function (require) {
return (function(m){
// Define The Module To Be Instantiated
var that;
var HTTP = that = new m.constructor({
name: 'HTTP',
state: {current: "HTTP Module Initialized", last: m.getModuleProperty('state').prototype.memory },
init: function(){ m.getModuleProperty('state').prototype.memory; }
});
// Create HTTP Object
var xhr = window['XMLHttpRequest'] ? new window['XMLHttpRequest']() : new ActiveXObject("Microsoft.xhr");
// Request Function
that.request = function(url, callback){
// If only 1 argument, set config to this
// Otherwise set default
var config = !callback ? url : {url: url, method: 'GET'};
// Set Request Headers if config provided
config.requestHeaders ? config.requestHeaders.forEach(function(header){
xhr.setRequestHeader(header[0], header[1]);
}) : null;
// Open Connection to URL
xhr.open(config.method, config.url, config.async || true);
// Return new Promise to chain function
return new Promise(function(resolve, reject){
// Resolve Response from Ready State Change
xhr.onreadystatechange = callback ? function() {
try {
if (xhr.status == 200 && xhr.readyState == 4) {
// Resolve The Response And Create
// Chain Method
return resolve(callback.success(xhr.response));
// console.log(xhr.response);
} else if (xhr.status != 200 && xhr.readyState == 4) {
// Reject Any Response That
// Is Not 200 OK
return reject(callback.error(xhr.response));
// console.log(xhr.response);
}
} catch(e) { console.error(e.message, e); }
}: function basicReadyState() {
// If no callback provided in config
// Use basicReadyState functionality
try {
if (xhr.status == 200 && xhr.readyState == 4) {
// Resolve The Response And Create
// Chain Method
return resolve(xhr.response);
// console.log(xhr.response);
} else if (xhr.status != 200 && xhr.readyState == 4) {
// Reject Any Response That
// Is Not 200 OK
return reject(xhr.response);
// console.log(xhr.response);
}
} catch(e) { console.error(e.message, e); }
};
// Stringify User Provided Parameters
// Use if config has a POST method
var params = JSON.stringify(config.params || {});
// Send Request
xhr.send(params);
});
}
// Install the module to App Modules list
m.prototype.installModule(that);
}( require('modules/main-module') ))
});
<!doctype html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<title>Tech Ninja | Web &amp; IT</title>
<meta name="description" content="Tech Ninja | Web &amp; IT Advanced Web Applications">
<meta name="author" content="4UmNinja">
<link rel="stylesheet" href="css/bootstrap.css">
<!-- Custom Module -->
<script type="application/javascript" async="true" data-main="app" src="js/require.js"></script>
<style>
/* Alert System Classes And Key Frames */
@-webkit-keyframes fade-in {
to {
opacity: 1;
}
}
@keyframes fade-in {
to {
opacity: 1;
}
}
@-webkit-keyframes fade-out {
0% { opacity: 1; }
85% { opacity: 1; }
100% { opacity: 0; }
}
@keyframes fade-out {
0% { opacity: 1; }
85% {opacity: 1; }
100% { opacity: 0;}
}
.fade-in {
-webkit-animation: fade-in .5s ease-in 1 forwards;
animation: fade-in .5s ease-in 1 forwards;
opacity: 0;
}
.fade-out {-webkit-animation-delay: 1.5s;}
.fade-out {
-webkit-animation: fade-out 1s ease-out;
-webkit-animation-fill-mode: forwards;
-webkit-animation-iteration-count: 1;
opacity: 1;
}
.is-paused {
animation-play-state: paused;
}
/* Alert System Main Class */
.bb-alert, .alert-system {
position: fixed;
bottom: 5%;
right: 0;
margin-bottom: 0;
font-size: 1.2em;
padding: 1em 1.3em;
z-index: 2000;
}
</style>
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head><body tn-app></body></html>
define(function (require) {
return (function(m) {
// Define The Module To Be Instantiated
var that;
var StorageSystem = that = new m.constructor({
name: 'StorageSystem',
state: {
current: "Local Storage Module Initialized",
last: m.getModuleProperty('state').prototype.memory
},
init: function() {
// Available Storage System
var storages = ['localStorage', 'sessionStorage', 'cache'];
// Define A Storage Objects
that.storage = {};
// Set Storage System
for(var system in storages) {
// Empty Reference Object
that.storage[storages[system]] = window[storages[system]] || {};
// Set Storage Name In Object
that.storage[storages[system]]['namespace'] = StorageSystem["namespace"];
that.storage[storages[system]]['DB'] = storages[system];
}
// Define A Save Function
that.storage.save = function(property, value){
// If No Second Arg Present,
// Assume It's an Object
var cache = that.storage.cache;
var message;
// console.warn(["Data is cached", dataIsCached(property || "", value)], "\n",
// ["Values are equal", valuesAreEqual(cache[property] || "", value)], "\n",
// []);
// console.warn("Attempting to save user", property, value);
if (!dataIsCached(property || "", value) && !valuesAreEqual(that.storage.localStorage[property] || "", value))
saveToAllStorageSystems(property, value)
, message = "Saved Data Successfully";
if (dataIsCached(property || "", value) && !valuesAreEqual(that.storage.localStorage[property] || "", value))
mergeAndReturnData(property, value)
, message = "Updated Data Successfully";
else message = "Data Already Cached";
// Update Cache Length
cache.length = Object.keys(that.storage.cache).length;
// Send Success Or Fail To Client
return m.sendMessageToClient(message, "");
}
function mergeAndReturnData(property, value) {
console.warn("Implement Merging Unequal Data Keys", property, value);
var data = that.storage.get(property),
type = typeof data !== 'string' || typeof data !== 'number'
? Array.isArray(data)
? 'array'
: typeof data === 'object' && !Array.isArray(data)
? 'object'
: 'basic'
: null;
console.log("Type of Data", type, data);
if (type === 'basic') return saveToAllStorageSystems( property, value );
if (type === 'array') return saveToAllStorageSystems(property, data);
// -------- TEMPORARY USER FORCED MERGE -------
// --------------------------------------------
// if (property === "Users") return saveToAllStorageSystems( property, value );
// if (!that.cache[property]) saveToAllStorageSystems( property, value );
}
// Determine Type and Save To Storage
function saveToAllStorageSystems(property, value) {
var s = storages.slice();
s.splice(s.indexOf('cache'), 1);
for(var system in s) {
// Save The Property And It's Value
if (typeof value === 'object') that.storage[s[system]][property] = returnStringData(value);
else that.storage[s[system]][property] = value;
}
that.storage.cache[property] = value;
}
function returnParsedData(data) {
console.warn("Return This As Parsed", data);
var response;
try {
response = JSON.parse(data);
} catch(e) {
response = data;
} finally {
console.info("Data Has Been Parsed", response);
return response;
}
}
function returnStringData(data) {
// console.warn("Return This As String", data);
var response;
try {
response = JSON.stringify(data);
} catch(e) {
response = data;
} finally {
// console.info("Data Has Been Stringified", response);
return response;
}
}
// Check If Data Already Exists
// In Local Cache
function dataIsCached(property, value) {
// console.log("Prop In Cache", that.storage.cache.hasOwnProperty(property), property, value);
// console.log("Stings Are Equal?", returnStringData( that.storage.cache[property] ) == returnStringData(value), [returnStringData( that.storage.cache[property] ), returnStringData(value)]);
// Check If Data Is Cached
// Return true if so, else false
if (!that.storage.cache.hasOwnProperty(property) && !valuesAreEqual(that.storage.cache[property] || "", value)) return false;
else return returnStringData( that.storage.cache[property] ) == returnStringData(value);
}
// Return Bool If Data Equal
function valuesAreEqual(val1, val2){
// console.info("Arguments", val1, val2);
// Determine Both Value Types
var isArray = [Array.isArray(val1), Array.isArray(val2)].every(function(el){ return el === true; });
var isObject = [Object.keys(val1)[0] != "0", Object.keys(val2)[0] != "0"].every(function(el){ return el === true; });
// console.warn("Is Array?", isArray, "Is Object?", isObject, ["data", [val1, val2]], ["Keys", Object.keys(val1), Object.keys(val2)]);
// Check If Array Lengths Are the same or return false
if (typeof val1 == 'string' && typeof val2 == 'string' || typeof val1 == 'number' && typeof val2 == 'number') return val1 == val2;
if (isArray && val1.length == val2.length) return Array.prototype.slice.call(val1).every(function(element, index, keys){
// console.log("This Array Is Same", val1[index] == val2[index]);
return JSON.stringify(val1[index]) == JSON.stringify(val2[index]);
});
// Check if Object[key].values are equal or return false
var aKeys = Object.keys(val1);
var bKeys = Object.keys(val2);
if (isObject && Object.keys(val1).length == Object.keys(val2).length) Array.prototype.slice.call(aKeys).every(function(property, index, keys){
console.log("This Object Is Same", JSON.stringify(val1[property]) == JSON.stringify(val2[property]));
return JSON.stringify(val1[property]) == JSON.stringify(val2[property]);
});
else return false;
}
// Get Item From Store
that.storage.get = function(id) {
for (var system in storages) {
// Get id from DB
// 2nd Argument is Bool that Forces Get Item To
// Return from the Local Storage
if (arguments[1]) return new Promise(function(res, rej){
var data = that.storage[storages[system]].getItem(id)
if (typeof data == 'string') data = JSON.parse(data);
return res( data );
})
// If Data Is Not Cached
// Get From Local Storage
if (!dataIsCached) return new Promise(function(res, rej){
// Return String Data As Object
return res(JSON.parse( that.storage[storages[system]].getItem(id) ));
});
// If Data Is Cached Return It From Local Data
else {
var data;
try {// Try To Parse Data
data = JSON.parse(that.storage.cache[id]); } catch(e)
{ // Data Cannot Be Parsed
data = that.storage.cache[id];
} finally { // Save Data To Local Store
// console.log("Data", data);
return data;
}
}
}
}
// Delete Feature
that.storage.delete = function(id) {
var s = storages.slice();
s.splice(s.indexOf('cache'), 1);
for(var system in s) {
// Delete Stored Ref
delete that.storage[s[system]][id];
}
// Delete From Cache
delete that.storage.cache[id];
}
// Remove Single Reference
that.storage.deleteOne = function(id, index) {
/* Implementation Needs More Work To
determine how to remove object nodes
*/
var data = that.storage.get(id),
type = typeof data !== 'string' || typeof data !== 'number'
? Array.isArray(data)
? 'array'
: typeof data === 'object' && !Array.isArray(data)
? 'object'
: 'basic'
: null;
console.log("Data", data);
if (type === 'array') return data.splice(index, 1), saveToAllStorageSystems(id, data);
if (type === 'object') return saveToAllStorageSystems(id ,deleteKey(data, index));
if (type === 'basic') return that.storage.delete(id);
function deleteKey(object, key) {
console.warn("Delete This Key", key, "From Object", object);
// Iterate over each key in the object
// If You reach the key, delete it
// And return the object
var parsedKey = key.split('.'),
ref;
for (var i=0;i<parsedKey.length;i++){
console.log("Working on Iteration - "+ i, "Ref", ref);
if (i < (parsedKey.length)) ref = object[parsedKey[i]];
else console.log("Deleting This Ref", ref[parsedKey[i]])// delete ref[parsedKey[i]];
return ref;
}
}
return data;
}
that.storage.manuallyUpdateLocalCache = function(property, value){
// Add Item To Local Store
var cache = that.storage.cache;
var data;
try {// Try To Parse Data
data = JSON.parse(value); } catch(e)
{ // Data Cannot Be Parsed
data = data;
} finally { // Save Data To Local Store
cache[property] = data;
console.log("Cache Data - " + property, data);
}
}
// Set Emtpy Function
that.storage.clear = function()
{ window['localStorage'].clear(); window['sessionStorage'].clear(); return "Local Storage Emptied"; };
// Get All Data Saved In Local Storage
(function populateLocalCache(s) {
for(system in s) {
// Define Store Refs
var store = that.storage[s[system]];
var cache = that.storage.cache;
// Loop over Prop Names and Save
// To Local Cache
for (var prop in store) {
// Add Item To Local Store
var data = that.storage[s[system]].getItem(prop);
try {// Try To Parse Data
data = JSON.parse(data); } catch(e)
{ // Data Cannot Be Parsed
data = data;
} finally { // Save Data To Local Store
cache[prop] = data;
}
}
// Set Local DB name to 'Cache'
cache.DB = "Cache";
// Set Length Of Storage
cache.length = Object.keys(cache).length;
// Hide Length From Enumeration
Object.defineProperty(cache, 'length', {enumerable: false})
// console.log("Data Has Been Populated");
return cache;
}
}(storages));
// Disable Function Enumeration
that.prototype.disableFunctionEnumeration(that.storage);
}
});
// console.log("Storage Object", StorageSystem);
// Listen For Changes From Other Clients
window.addEventListener('storage', function(e) { // Update Local Cache When DB Changes
that.storage.manuallyUpdateLocalCache(e.key, e.newValue);
});
// Install the module to App Modules list
m.prototype.installModule(that);
// Set App Storage to Cached Data
m.setStore(that.storage.cache);
// Enable Main Module's Default Storage
m.setStorageDevice( that.storage );
}( require('modules/main-module') ))
});
define(function (require) {
return (function(m){
m.constructor = (function constructor(s){
// This constructor's return acts as an index
// For all new modules instantiated by this function
return function() {
var args = Array.prototype.slice.call(arguments);
// Check for arguments definition
if (typeof args[0] != 'undefined'
|| typeof args[0] != null) for (var key in args[0]) { this[key] = args[0][key]; }
// Standard NameSpace For All Applications
this.namespace = "TechNinjaModule";
// Prototype Obeject (blank)
this.prototype = {};
// Return the Proterty to the client
this.getModuleProperty = function(property) { return s[property]; }
// Function List Factory
this.prototype.installModule = s.install;
this.prototype.uninstallModule = s.uninstall;
this.prototype.reboot = s.reinstall;
this.setState = s.state.set;
this.plugins = s.installedModules;
this.components = this.components || {};
this.toggleMessages = s.toggleMessages;
this.turnOnMessaging = function(){ return s.messagesEnabled = true; };
this.turnOffMessaging = function(){ return s.messagesEnabled = false; };
this.setMessagingTo = s.messaging.setActive;
this.sendMessageToClient = s.sendMessageToClient;
this.setStore = s.setStore;
this.setStorageDevice = s.setStorageDevice;
this.localStorageDevice = {};
this.localStorageDevice.save = this.getModuleProperty('storageDevice').save;
// Set State To Initialized
s.state.set({current: "App Initialized", last: s.state.prototype.memory});
// Disable all function enurations
this.prototype.disableFunctionEnumeration = function(o) {
for (var p in o) {
if (!isFunction(o[p])) "Skipping";
else Object.defineProperty(o, p, {
enumerable: false
});
}
// Return True if Object is a Function
function isFunction(functionToCheck) {
var getType = {};
return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
}
// Return self
return this;
}
// Init Disable Function Enumeration
this.prototype.disableFunctionEnumeration(this);
this.prototype.disableFunctionEnumeration(this.prototype);
// Define Properties for this module
Object.defineProperties(this, {
prototype: {
enumerable: false
},
namespace: {
value: this.namespace,
writable: false
},
localStorageDevice: {
enumerable: false
}
});
};
})(m);
// Define Private Function to This Module
// All m['some property'] are hidden from
// the client and window scope
m.id = "Installation Manager";
// Get The Node The App Is Defined On
m.node = document.querySelectorAll('[tn-app]')[0] || document.body;
// Define State of the Application
m.state = {
current: "Starting App ...",
last: ""
};
// State Manager
m.state.set = function(s){
// Get Keys from arguments object
var keys = Object.keys(s);
// Get Keys for the Modules state object
var stateKeys = Object.keys(m.state);
// Validate state keys argument
var valid = keys.length > 0 ? keys.every(function(key){ return stateKeys.indexOf(key) >= 0 }) : false;
// If Keys are valid,
// Set the state with keys
if (valid) { // Set Properties onto state object;
for (var prop in s) { m.state[prop] = s[prop]; } }
else return {message: 'Could Not Set State. State Object Is Invalid'};
return m.state;
}
// Reference to Last State
m.state.prototype = {};
m.state.prototype.memory = m.state.current;
Object.defineProperty(m.state, 'prototype', {
enumerable: false
})
// Define an Applications Node List
m.modules = {};
m.installedModules = [];
// Define a logging system,
// Must be an object with log property
// eg: {log: { some log functionality eg: console.log() }};
m.messaging = {
default: console,
active: {},
installed: ['console']
};
m.messaging.setActive = function(object) {
console.log("Setting To", object);
Object.defineProperty(m.messaging, 'setActive', {
enumerable: false
});
m.messaging['active'] = object;
m.sendMessageToClient("Loaded Messagin Service", object);
return object;
}
// Client Console Messaging System
m.messagesEnabled = false;
// Toggle Messaging On Or Off
m.toggleMessages = function(){ m.messagesEnabled = !m.messagesEnabled }
// Send Message To Client Function
m.sendMessageToClient = function(message, args, Class) {
if (!m.messagesEnabled) return "Messages Disabled";
// Class is an optional value to
// determine what css style
// is to be used eg: alert-danger or alert-success
if (!args) args = "";
else if (Object.keys(args)[0] != 0) args = JSON.stringify(args);
if (!m.messaging.active.hasOwnProperty('log')) m.messaging.default.log(message, args);
else m.messaging.active.log(message, args, Class || m.messaging.active.Class);
}
// Set Storage Object
m.store = {};
// Set Default Storage
m.storageDevice = {};
m.setStore = function(storage){ m.store.data = storage; }
// Define Default Save Behavior
m.setStorageDevice = function(device){ m.storageDevice = device; }
// Save Functionality
m.storageDevice.saveDataToStore = function(data){
console.log("Data To Save", data, m.storageDevice, this);
// Store Data Into Local Store
for ( var Class in data ) { m.store[Class] = data[Class]; }
}
m.events = {};
m.events.prototype = {};
m.events.prototype.setEventSystem = function(system) {
// If Object Is Available Set Event System
if (Object.keys(m.events).length <= 1 && m.events.hasOwnProperty('prototype'))
// For Each Property Add it to events Object
for (var property in system) { m.events[property] = system[property]; m.prototype.disableFunctionEnumeration(m.events)}
else return "Event System Already Set";
}
// Run App Functionality
m.run = function(app, cb) { // Apply the Callback on the new app module
cb(app); }
// Module Installer Functionality
m.install = function(app) {
m.run(app, function(a){
try {
/* Run This App (just return true);
Check if name has been loaded and
is not unidentified
*/
if (app.hasOwnProperty('name') && app.hasOwnProperty('prototype') && !m.modules.hasOwnProperty(app.name)) { m.modules[app.name] = app; }
// Halt the compiler
else throw new Error("App Not Valid. Check app.prototype = {} or app.name is correct");
// Run Module Initilizer
// If Apps List has this app's name
if (m.modules.hasOwnProperty(a.name) && a.hasOwnProperty("init")) a.init();
// No Init().. Do Not Init Module
else if (m.modules.hasOwnProperty(a.name) && !a.hasOwnProperty("init")) "No Module To Load";
// Halt the compiler
else throw new Error("Could Not Initialize " + a.name) + " Module";
// Update InstalledApps List
m.installedModules.push(app.name);
// Send Success To Client;
m.sendMessageToClient(a.name + " Has Been Initialized Successfully", "");
// Change State
m.state.set({current: "Initialized " + a.name, last: m.state.prototype.memory});
// Catch The Error
} catch (e) {
// Send Error to Client
console.error({message: e.message, stack: e, arguments: arguments});
} finally {
// To Be Implemented
}
});
}
// Uninstall App Functionality
m.uninstall = function(name) {
// Delete App Node
delete m.modules[name];
// Send Success To Client, but not uninitialized;
m.sendMessageToClient(name + " Has Been Uninstalled Successfully", "");
// Change State
m.state.set({current: "Uninstalled " + name, last: m.state.prototype.memory});
}
// Reinstall App Functionality
m.reinstall = function(name) {
var app = m.modules[name];
// Uninstall App
m.uninstall(name);
// Install App
m.install(app);
// Send Success To Client;
m.sendMessageToClient(name + " Has Been Reinstalled Successfully", "");
// Change State
m.state.set({current: "Reinstalled " + name, last: m.state.prototype.memory});
}
// Implement Better Error Handling
m.ErrorHandler = function(fn, args) {
// Empty Function
}
m.prototype = {};
m.prototype.disableFunctionEnumeration = function(o) {
for (var p in o) {
if (!isFunction(o[p])) "Skipping";
else Object.defineProperty(o, p, {
enumerable: false
});
}
// Return True if Object is a Function
function isFunction(functionToCheck) {
var getType = {};
return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
}
// Return self
return this;
}
// Hide Inner Properties of this module
Object.defineProperties(m, { constructor: { enumerable: false } });
// Return this object and it's constructor
return (function(m){ var self = new m.constructor(); return self; }(m));
}({}));
});
(function(m){
// Define The Module To Be Instantiated
var that;
var TestModule = that = new m.constructor({
name: 'TestModule',
components: {array: [1,2,3,4]},
state: {current: "Test Module Initialized", last: m.getModuleProperty('state').prototype.memory },
init: function(){ m.getModuleProperty('state').prototype.memory; }
});
// Define A Component either in the constructor,
// or as an object key
that.components.properties = [1,2,4];
// Install the module to App Modules list
m.prototype.installModule(that);
}(requirejs('modules/main-module')));
define(function (require) {
return (function(m){
// Define The Module To Be Instantiated
var that;
var UserModule = that = new m.constructor({
name: 'UserModule',
state: {current: "Test Module Initialized", last: m.getModuleProperty('state').prototype.memory },
init: function(){ m.getModuleProperty('state').prototype.memory; }
});
// Get Default Storage Device
var store = m.getModuleProperty('storageDevice');
// Save User As Object
that.saveUser = function(user) {
// Get User Object From Storage
var users = m.getModuleProperty('store').data['Users'] || [];
// Add User If Not Already In List
var userInList = users.some(function(u){ return u.name == user.name });
// Push and Save if User Not In List
// And Storage Device has Save Method
if (!userInList) users.push(user);
// Save The Users Object
if (store.hasOwnProperty('save') && !userInList) store.save("Users", users);
else if (store.hasOwnProperty('save') && userInList) m.sendMessageToClient('User Already In List', '');
// Handle If No Storage Method Present
else console.warn("No Storage Device Set", "Find Other Save Method Or None At All");
}
that.getUser = function(reference, value) {
// Provide a reference/ID and a Value
// To Retrieve a name.. Run function with
// No values to retrieve all users
var cache = m.getModuleProperty('store').data.Users;
return !!reference ? cache.filter(function(user){ if (user[reference]) return user[reference].search(value) >= 0; }) : cache;
}
// Install the module to App Modules list
m.prototype.installModule(that);
// Disable Enumeration for this Module
that.prototype.disableFunctionEnumeration(that);
}( require('modules/main-module') ))
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment