/**
* @module managers/nav-manager
* @description This module manages common global navigation
* @requires modules/hash
* @requires common/view
* @requires managers/template-manager
* @requires managers/prsonas-manager
* @requires jHammer
*/
define([
"modules/hash",
"common/view",
"managers/template-manager",
"managers/prsonas-manager",
"jHammer"
],
function (hash, view, templateManager, prsonasManager)
{
// ---------------------------------------------------------------
//
// NAV MANAGER
//
// ---------------------------------------------------------------
var Nav = function ()
{
console.log(" * <nav>");
this.oView = view;
this.oHash = hash;
this.oTemplateManager = templateManager;
this.oPrsonas = prsonasManager;
window.tEvent.eventStr.EVENT_PAGE_BACK_BTN = "EVENT_PAGE_BACK_BTN";
window.tEvent.eventStr.EVENT_PAGE_HOME_BTN = "EVENT_PAGE_HOME_BTN";
this.ui = {
eventBtn : ".js-btn-event",
microphone : ".js-microphone",
licenseStatus : ".js-license-status"
};
this.micActiveTimer = false;
this.micTimer = -1;
this.historyObj = {
current: {
event: "",
data: -1
},
past: {
event: "",
data: -1
},
eventStack: []
};
this.pageHistory = [];
this.init();
};
Nav.prototype =
{
// ______________________________________________________________
// init
/**
* init
* @description Initializes class
* @fires assignListeners()
* @memberOf module:managers/nav-manager
* @instance
*/
init: function()
{
this.assignListeners();
},
// ______________________________________________________________
// assignListeners
/**
* assignListeners
* @description Assigns listeners to events used in this class.
* @listens EVENT_ADMIN_GOT_MANIFEST
* @listens EVENT_NEW_PAGE
* @listens EVENT_BACK_BUTTON
* @listens EVENT_BACK_BUTTON_NO_ANIM
* @listens EVENT_TIMER_EXPIRED
* @listens EVENT_TOGGLE_MIC
* @listens EVENT_HISTORY
* @memberOf module:managers/template-manager
* @instance
*/
assignListeners: function()
{
var self = this;
// new page action
window.tEvent.addListener("EVENT_ADMIN_GOT_MANIFEST", function(evt, manifest)
{
self.onProcessManifest(manifest);
});
// new page action
window.tEvent.addListener("EVENT_NEW_PAGE", function(evt, newPageData)
{
self.onNewPage(newPageData);
});
// back button
window.tEvent.addListener("EVENT_BACK_BUTTON", function(evt, data)
{
self.onBackButtonClick(data);
});
// back button for _NO_ANIM event append
window.tEvent.addListener("EVENT_BACK_BUTTON_NO_ANIM", function(evt, data)
{
self.onBackButtonNoAnimClick(data);
});
// timer expired
window.tEvent.addListener("EVENT_TIMER_EXPIRED", function(evt, data)
{
window.oModal.close();
});
window.tEvent.addListener("EVENT_TOGGLE_MIC", function(evt, data){
var state;
switch(data.property){
case "SPEECH_ENABLED":
state = "on";
break;
case "SPEECH_DISABLED":
state = "off";
break;
}
self.onToggleMicrophone(state);
});
// page is loaded, check for anchor and scroll to anchor
if (typeof window.oModel === "undefined" || window.oModel.jConfig === -1){
window.tEvent.addListener("EVENT_MODEL_READY", function(evt, data)
{
self.initHotkeys();
});
} else {
self.initHotkeys();
}
$("body").hammer().on("click", this.ui.eventBtn, function(e){
var eventId = $(this).attr("data-event");
var data = $(this).attr("data-id");
self.onEventBtnClick(e, eventId, data);
});
$("body").hammer().on("click", this.ui.microphone, function(e){
self.onToggleMicrophone();
});
window.tEvent.addListener("EVENT_HISTORY", function(evt, data){
// save navigation for going back
self.updateHistory(data.eventId, data.data);
});
window.tEvent.addListener("EVENT_PAGE_BACK_BTN", function(evt, data){
self.onGoBack();
});
},
// --------------------------------------------------------------
// HELPERS
// --------------------------------------------------------------
// ______________________________________________________________
// initHotkeys
/**
* initHotkeys
* @description Initializes hot key handling from project JSON document.hotkeys. Also, enables/disables nuBrowser key capture based on SDK config EnableGlobalKeyHandling
* @memberOf module:managers/nav-manager
* @instance
*/
initHotkeys: function() {
var self = this;
var target,
key;
var enableBrowserKeyCapture = false;
if (typeof window.oPrsonas.app.getSetting !== "undefined") {
enableBrowserKeyCapture = window.oPrsonas.app.getSetting("EnableGlobalKeyHandling");
}
$(document).keydown(function(e){
if ($(e.target).attr("class").indexOf("input") < 0){
key = e.key.toLowerCase();
console.log(" * <nav.initHotkeys>", e);
for (var item in window.oModel.jConfig.document.hotkeys){
target = window.oModel.jConfig.document.hotkeys[item];
if (key === target.key && e.ctrlKey){
console.log(" * <nav.initHotkeys> firing event", target.event);
window.tEvent.fire(target.event);
break;
}
}
}
});
},
// ______________________________________________________________
// updateHistory
/**
* updateHistory
* @description Keeps history of the events called (used for back button)
* @param {String} eventId - Event ID
* @param {Object} data - Any data passed with the event call
* @memberOf managers/nav-manager
* @instance
*/
updateHistory: function(eventId, data) {
eventId = eventId.split("_STOP_ANIM")[0];
var modelData = window.oModel.jConfig;
if (typeof data === "undefined") {
data = "";
};
if (eventId === modelData.document.startEvent.split("_STOP_ANIM")[0] ||
eventId === modelData.prsonas.timers.expiredEvent ||
eventId === "EVENT_PAGE_HOME_BTN" ||
(typeof modelData.proxySendkeyEvents["EVENT_PAGE_HOME_BTN"] !== "undefined" && eventId === modelData.proxySendkeyEvents["EVENT_PAGE_HOME_BTN"]) ) {
this.historyObj.eventStack = [
{
event: eventId,
data: data
}
]
} else {
if (this.historyObj.eventStack[this.historyObj.eventStack.length - 1].event !== eventId) {
this.historyObj.eventStack.push({
event: eventId,
data: data
});
}
}
},
// ______________________________________________________________
// onGoBack
/**
* onGoBack
* @description Goes back in history to the previous event recorded
* @memberOf managers/nav-manager
* @instance
*/
onGoBack: function() {
if (this.historyObj.eventStack.length === 0) {
var evt = this.jConfig.document.startEvent;
window.tEvent.fire(evt);
} else {
var evt = this.historyObj.eventStack[this.historyObj.eventStack.length - 2];
if (evt.event !== "EVENT_PAGE_HOME_BTN" && evt.event.indexOf("_STOP_ANIM") === -1){
evt.event += "_STOP_ANIM";
}
// remove last 2 items in stack
this.historyObj.eventStack.splice(-1);
this.historyObj.eventStack.splice(-1);
window.tEvent.fire(evt.event, evt.data);
}
},
// --------------------------------------------------------------
// EVENTS
// --------------------------------------------------------------
// ______________________________________________________________
// onProcessManifest
/**
* onProcessManifest
* @description Gathers data from manifest
* @param {Object} manifest Manifest from Prsonas application
* @fire onToggleMicrophone()
* @memberOf module:managers/nav-manager
* @instance
*/
onProcessManifest: function(manifest) {
// set microphone state
this.onToggleMicrophone("off", true);
},
/*
Markup eg:
<div class="microphone-toggle js-microphone" data-status="on"></div>
*/
// ______________________________________________________________
// onToggleMicrophone
/**
* onToggleMicrophone
* @description Toggles the microphone state
* @param {Boolean} forceState Forces the microphone state
* @param {Boolean} affectIconOnly Just affect the icon state
* @memberOf module:managers/nav-manager
* @instance
*/
onToggleMicrophone: function(forceState, affectIconOnly) {
var self = this;
var $mic = $(this.ui.microphone);
var micStatus = $mic.attr("data-status");
if (typeof forceState !== "undefined"){
$mic.attr("data-status", forceState);
micStatus = forceState;
} else {
if (!this.micActiveTimer && $(this.ui.licenseStatus).css("display") === "none"){
switch(micStatus){
case "on":
$mic.attr("data-status", "off");
break;
case "off":
$mic.attr("data-status", "on");
break;
}
}
}
// do send key and timer if not just for visual status
if (typeof affectIconOnly === "undefined" || affectIconOnly === false){
// discourage quick consecutive clicks - prevents error
this.micActiveTimer = true;
this.micTimer = setTimeout(function(){
self.micActiveTimer = false;
}, 3000);
}
},
// ______________________________________________________________
// onEventBtnClick
/**
* onEventBtnClick
* @description Module configured button click
* @param {Event} btnEvt Button event
* @param {String} eventId Event ID to be triggered
* @param {Object} data Data to be passed with the event
* @memberOf module:managers/nav-manager
* @instance
*/
onEventBtnClick: function(btnEvt, eventId, data)
{
console.log(" * <nav.onEventBtnClick> ", eventId, data);
var interactionBlockedState = window.oModel.getInteractionBlockState();
if (!interactionBlockedState){
window.tEvent.fire("EVENT_SET_INTERACTION_BLOCK_TIMER");
if (eventId !== ""){
window.tEvent.fire(eventId, data);
}
} else {
btnEvt.stopPropagation();
}
},
// ______________________________________________________________
// onNewPage
/**
* onNewPage
* @description Maintains page history
* @param {Object} newPageData
* @memberOf module:managers/nav-manager
* @instance
*/
onNewPage: function(newPageData)
{
// maintain page history for back button
if (newPageData === "EVENT_PAGE_IDLE"){
this.pageHistory = [];
} else if (newPageData === "EVENT_PAGE_MAIN_MENU") {
this.pageHistory = ["EVENT_PAGE_MAIN_MENU_STOP_TALK"];
} else {
this.pageHistory.push(newPageData);
}
},
// ______________________________________________________________
// onBackButtonNoAnimClick
/**
* onBackButtonNoAnimClick
* @description Trigger back button with no intent/animation action by triggering history event adding _NO_ANIM to prevent redundant animation
* @param {Object} data Data associated with event history
* @fire EVENT_SET_INTERACTION_BLOCK_TIMER
* @fire Page history event += "_NO_ANIM"
* @memberOf module:managers/nav-manager
* @instance
*/
onBackButtonNoAnimClick: function(data)
{
window.tEvent.fire("EVENT_SET_INTERACTION_BLOCK_TIMER");
// remove last page
this.pageHistory.splice(-1, 1);
// go to previous page
window.tEvent.fire(this.pageHistory[this.pageHistory.length-1] + "_NO_ANIM", data);
},
// ______________________________________________________________
// onBackButtonClick
/**
* onBackButtonClick
* @description Trigger back button
* @param {Object} data Data associated with event history
* @fire EVENT_SET_INTERACTION_BLOCK_TIMER
* @fire Page history event
* @memberOf module:managers/nav-manager
* @instance
*/
onBackButtonClick: function(data)
{
window.tEvent.fire("EVENT_SET_INTERACTION_BLOCK_TIMER");
// remove last page
this.pageHistory.splice(-1, 1);
// go to previous page
window.tEvent.fire(this.pageHistory[this.pageHistory.length-1], data);
}
};
var oNav = window.oNav = new Nav();
return (oNav);
});