Skip to content

Instantly share code, notes, and snippets.

@mrosata
Created September 11, 2015 16:25
Show Gist options
  • Save mrosata/5d09524bbb975b399310 to your computer and use it in GitHub Desktop.
Save mrosata/5d09524bbb975b399310 to your computer and use it in GitHub Desktop.
Template adapter for phonegap version of our web app (Fill the hole that .htaccess left behind).
/******
* @author: Steven Spielburg, j/k, it's me!
* @since: Long time away
* @galaxy: Far far away
*
* Usually our .htaccess would build a proper query string so that index.php can handle any request for us.
* Now we have no .htaccess except on the api server. So we must map our own templates. This pattern below
* will serve as almost middleware to AjaxHustleBunny. Normally AHB would make HTTP request and index.php
* would return the correct page, then AHB would fire enpoint event (`controller/action`, id) to all JS
* modules, but now instead AHB will call aroma.loadAssets() with params and aroma.loadAssets shall return
* a promise that will resolve to AHB after page is loaded, then AHB can fire ajax enpoint pub/sub event to
* all JS modules like normal day at office.
*
*/
var aroma = (function ($, window, undefined) {
var API_URL = API_URL || 'http://api.example.net';
var BASE_URL = null;
/**
* aroma.loadAssets [Function: Public]
*
* Loads the html Assets for the requested controller, action, id combination. Sort of middleware
* because in webapp AjaxHustleBunny handles all this. In PhoneGap app AjaxHustleBunny.getPage
* calls this function with {controller,action,id} built from the passed url that is passed in from
* AjaxHustleBunny.hopHere function or an '.ahb-click' element click event.
*
* This function will return a promise that resolves after template has been loaded. This will be the
* signal to AjaxHustleBunny to fire endpoint event as it normally does after it loads a new page
* itself in the webapp version of `Chainplace`.
*
* @params params [object][Function: Object] -
* {}.controller [string]
* {}.action [string]
* {}.id [string|int] [optional]
*
* @return promise [object][Function: Promise] - resolves after templated page is loaded
*/
function loadAssets(parameters) {
if (!parameters.hasOwnProperty('controller') || !parameters.hasOwnProperty('action')) {
return false;
}
parameters.controller = parameters.controller || 'login';
parameters.action = parameters.action || 'index';
parameters.id = parameters.id || '';
//....... STUFF HAPPENS HERE, WE NEED TO LOAD THE TEMPATE FOR MOBILE APP!!!
//....... FIRST WE NEED TO KNOW WHAT HTML TO USE!!!
//....... THEN WE NEED TO LET AjaxHustleBunny KNOW WE ARE DONE!!!
mapUserTemplate(parameters)
.then(
function(mapToHTML) {
// Here We have the resolved path to template in resolved promise returned to us from
// the mapUserTemplate function (SCROLL DOWN PAGE TO SEE HOW THAT WORKS).
$('[data-template-view]')
.load('views/' + mapToHTML + '.html'
,function () {
promise.resolve(true);
});
});
return promise;
}
/*************
Object Name: __pageMap
Properties are controller names and are themselves Objects which map views on that specific controller.
So `__pageMap.charts` would be set to an object mapping all views in the `charts` controller.
Below is an example of a view named `pie` in the `charts` controller.
__pageMap.charts.pie = {network: 'charts/page1', franchise: 'home/index', requiresID: true}
When the app navigates to the 'charts/pie' page it while the current user is a `network` user then the
app would template in something like:
$('[data-chainplace-view]').load(`views/charts/page1.html`)
if the user was `franchise` user:
$('[data-chainplace-view]').load(`views/home/index.html`)
- May I caution against sending the user to views outside of the current folder however. If a franchise user
doesn't belong inside a controller view, then just don't map anything to that user type. We can then let
the application handle what it wants to do in that senerio. But, we do have that power, it becomes useful
in situations like controller `home` where `home/index` actually maps by default to either the `network` or
`franchise` view folders.
**************/
var __pageMap = new Object();
/** HOME **/
__pageMap.home = {
index: {
network: 'network/index',
franchise: 'franchise/index',
requiresID: false
}
};
/** FRANCHISE **/
__pageMap.franchise = {
index: {
franchise: 'franchise/index'
}
};
/** NETWORK **/
__pageMap.network = {
index: {
network: 'network/index'
}
};
/** BRANCHES **/
__pageMap.branches = {
index: {
network: 'branches/net-branch-list'
},
create: {
requiresID: true,
network: 'branches/create-form',
withoutID: {
network: 'branches/inprogress'
}
},
francreate: {
network: 'branches/francreate'
},
newbranch: {
network: 'branches/net-create-branch'
},
products: {
network: 'branches/products' // I THINK THIS REQUIRED AN ID...
},
update: {
network: 'branches/net-branch-update'
}
};
/** CERTIFICATES **/
__pageMap.certificates = {
branches: {
network: 'certificates/net-specific-branch'
},
details: {
requiresID: true,
network: 'certificates/net-details',
franchise: 'certificates/fran-details'
},
expired: {
network: 'certificates/net-specific-branch-expired'
},
index: {
franchise: 'certificates/fran-main',
network: 'certificates/net-main'
},
overview: {
network: 'certificates/overview'
},
rent: {
network: 'certificates/rent'
},
updates: {
franchise: 'certificates/fran-updates',
network: 'certificates/net-updates'
}
};
/** CHARTS **/
__pageMap.charts = {
complaints: {
network: 'charts/net-charts',
franchise: 'charts/fran-charts'
},
effective: {
network: 'charts/net-charts',
franchise: 'charts/fran-charts'
},
exam: {
network: 'charts/net-charts',
franchise: 'charts/fran-charts'
},
index: {
network: 'charts/net-charts',
franchise: 'charts/fran-charts'
},
secret: {
network: 'charts/net-charts',
franchise: 'charts/fran-charts'
},
};
/** COMPLAINTS **/
__pageMap.complaints = {
controls: {
network: 'fran-index',
franchise: 'net-index'
},
details: {
requiresID: true,
network: 'net-details',
franchise: 'fran-details'
},
filenew: { // note: started to edit this php view -> html while building this list (delete this note after 9-12).
network: 'filenew'
},
formal: {
requiresID: true,
network: 'net-formal-message',
franchise: 'fran-formal-message'
},
index: {
franchise: 'fran-index',
network: 'net-index'
}
};
/**
* aroma.mapUserTemplate
* [Private Function]
*
* Takes controller, action, id and then after making an API call for logged in user type this function can map the
* html file to use as a template for that controller, action, id combination.
*
* @param pageOptions [object][Function: Object]
* {}.controller [string], most cases this will be the views` folder ex: 'charts'
* {}.action [string], [optional] 'index' by default. Name of action that maps us to correct template
* {}.id [int], [optional] null by default. Only if view requiresID is this needed
* @return promise [object][Function: Promise] - Will resolve with the views folder 'folder/file' template location.
*/
function mapUserTemplate(pageOptions) {
if (typeof pageOptions !== "object" || pageOptions === null || !pageOptions.hasOwnProperty('controller')) {
console.error("TQSOFT:: aroma.getUsersPage() requires type \"object\", and at least prop 'controller'.");
return false;
}
// Parse out the options to make up the page.
var controller = pageOptions.controller,
action = pageOptions.action || 'index',
hasID = pageOptions.hasOwnProperty('id'),
id = pageOptions.id || null;
// This will be the return promise that resolves as 'folder/file' of view template html.
var promise = $.Deferred(),
viewMap;
// We will only make the call to check if user is logged in and then to load the page if this really is a page in our object map.
if ( __pageMap.hasOwnProperty(controller) && typeof __pageMap[controller] === "object"
&& __pageMap[controller].hasOwnProperty(action) && typeof __pageMap[controller][action] === "object"
&& __pageMap[controller][action] !== null) {
// This is the object mapping the controller/action --- we still need to check user type before knowing end uri
viewMap = __pageMap[controller][action];
// Let's see if the user is logged in, what user type they are, and then we'll be able to find correct template.
api.call('getUsernameInformation', function(resp) {
if (resp && resp.success == 1 && resp.type === 'network' || resp.type === 'franchise') {
// The user is logged in, so let's figure out how to setup their page.
var userType = resp.type;
if ( viewMap.hasOwnProperty(userType) && typeof viewMap[userType] === "string") {
console.log('PAGE TO GET WILL BE => ', 'views/' + viewMap[userType]);
return promise.resolve(viewMap[userType]);
}
}
// One way or the other it didn't work.
return promise.reject("Can't map user to page or user not looged in yet. [aroma::private::mapUserPage()]");
});
// Return the created promise while we make the call
return promise;
}
else {
if ('DEBUG_AROMA' in window && !!DEBUG_AROMA) {
// If debug is on then thow message
console.error("TQSOFT:: aroma.mapUserPage [Function: private] can't find the user page that you've requested"
+ " with params = {controller: " + controller + ", action: " + action+", id: " + id + "}");
}
// No point to return the promise, We will reject it though in the case that it was passed to us as an argument.
return promise.reject('Bad params passed into aroma.mapUserTemplate [Function: private]');
}
}
/**
* AROMA Public API
*/
return {
/*
api: api,
fetch: fetch,
*/
bindings: {},
loadAssets: loadAssets
};
}(jQuery, window));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment