/**
Using Sentiment:
JSON
"default false"
speechToText.sentiment {
"isActive": true,
"minConfidence": 0.5
}
*/
/**
* @module modes/iha
* @description This module manages IHA (iHealth Assist) Mode functionality.
* @requires common/view
* @requires modes/iha-services
* @requires managers/mappedin-manager
* @requires managers/timer-manager
* @requires managers/prsonas-manager
* @requires managers/connection-manager
*/
define([
"common/view",
"modes/iha_services",
"ihaManagers/mappedin-manager",
"managers/timer-manager",
"managers/prsonas-manager",
"managers/connection-manager"
],
function (View, IhaServices, MappedInManager, Timer, Prsonas)
{
// ---------------------------------------------------------------
//
// CUSTOM IHA HANDLING
//
// ---------------------------------------------------------------
var Iha = function ()
{
console.log(" * <iha>");
this.oView = View;
this.oMappedIn = window.oMappedIn = new MappedInManager();
this.oTimer = Timer;
this.oPrsonas = Prsonas;
this.oIhaServices = IhaServices;
window.tEvent.eventStr.EVENT_GO_TO_LOCATION = "EVENT_GO_TO_LOCATION";
window.tEvent.eventStr.EVENT_IHA_SEARCH_CLEAR = "EVENT_IHA_SEARCH_CLEAR";
window.tEvent.eventStr.EVENT_IHA_LOCATION_CLICK = "EVENT_IHA_LOCATION_CLICK";
window.tEvent.eventStr.EVENT_PAGE_IHA_SEARCH_LOCATION_NAME = "EVENT_PAGE_IHA_SEARCH_LOCATION_NAME";
window.tEvent.eventStr.EVENT_IHA_RESET_INTERFACE = "EVENT_IHA_RESET_INTERFACE";
window.tEvent.eventStr.EVENT_IN_WALKAWAY = "EVENT_IN_WALKAWAY";
window.tEvent.eventStr.EVENT_IN_WALKUP = "EVENT_IN_WALKUP";
window.tEvent.eventStr.EVENT_LANGUAGE_CONFIG_LOADED = "EVENT_LANGUAGE_CONFIG_LOADED";
window.tEvent.eventStr.EVENT_IHA_UPDATE_QR_CODE = "EVENT_IHA_UPDATE_QR_CODE";
window.tEvent.eventStr.EVENT_IHA_RELOAD_BROWSER = "EVENT_IHA_RELOAD_BROWSER";
window.tEvent.eventStr.EVENT_IHA_PRESENTATION_HOME = "EVENT_IHA_PRESENTATION_HOME";
window.tEvent.eventStr.EVENT_IHA_PRESENTATION_NEXT = "EVENT_IHA_PRESENTATION_NEXT";
window.tEvent.eventStr.EVENT_IHA_PRESENTATION_BACK = "EVENT_IHA_PRESENTATION_BACK";
window.tEvent.eventStr.EVENT_IHA_PRESENTATION_SHOW = "EVENT_IHA_PRESENTATION_SHOW";
this.ui = {
micToggle : ".js-complex-mic",
title : ".js-complex-title",
map : ".js-complex-map",
resetMap : ".js-complex-camera-reset",
queryBtn : ".js-complex-query-btn",
searchLocTitle : ".js-search-location-title",
insearchTitle : ".js-search-location-insearch-title",
searchLocResults : ".js-complex-search-btn-container",
searchInput : ".js-search-location-input",
qrCodeContainer : ".js-iha-map-qr-container",
qrCode : ".js-iha-map-qr",
scroller : ".js-nice-scroller",
qrBtn : ".js-iha-qr-btn",
pres : ".js-complex-pres",
presImg : ".js-complex-pres-img",
presAdditionalContent : ".js-complex-pres-add-content",
presBtn : ".js-complex-pres-btn",
presCounterCurrent : ".js-complex-pres-counter-current",
presCounterLast : ".js-complex-pres-counter-last"
};
// defines / constants
this.def = -1;
// state of IHA mode
this.isIha = false;
this.manifest = -1;
// project.json
this.jConfig = -1;
// enable first load events
this.firstLoad = true;
// presentation data
this.presentation = -1;
this.presentationTimer = -1;
this.tweenSlideTransition = -1;
this.init();
};
Iha.prototype =
{
// ______________________________________________________________
// init
/**
* init
* @description Initializes class
* @memberOf module:modes/iha
* @instance
*/
init: function() {
var self = this;
// is model ready?
if (typeof window.oModel === "undefined" || window.oModel.modelReady === false){
window.tEvent.addListener("EVENT_MODEL_READY", function(evt, data) {
self.onModelReady();
});
} else {
self.onModelReady();
}
},
// ______________________________________________________________
// onModelReady
/**
* onModelReady
* @description Called when project.json is loaded
* @fires initIha()
* @fires assignListeners()
* @fires initMappedIn()
* @memberOf module:modes/iha
* @instance
*/
onModelReady: function() {
// set defines
this.def = window.helpers.clone(window.oModel.def);
this.def.CLASS_HIDE_ME = "hide-me";
this.def.CLASS_NO_QR_CODE = "no-qr-code";
// set jConfig data
this.jConfig = window.oModel.jConfig;
if (typeof $("#configuration").attr("data-mode") !== "undefined" && $("#configuration").attr("data-mode") === "iha"){
this.isIha = true;
$("body").attr("data-mode", "iha");
console.log(" * <iha.onModelReady> IHA is active");
}
// assign listeners
if (this.isIha){
this.initIha();
this.assignListeners();
this.initMappedIn();
}
},
// ______________________________________________________________
// initIha
/**
* initIha
* @description Sets up persistent page elements
* @memberOf module:modes/iha
* @instance
*/
initIha: function() {
var ihaConfig = this.jConfig.iha;
},
// ______________________________________________________________
// assignListeners
/**
* assignListeners
* @description Assigns listeners to events used in this class.
* @listens EVENT_ADMIN_GOT_MANIFEST
* @listens EVENT_TEMPLATE_LOADED
* @listens EVENT_IHA_UPDATE_QR_CODE
* @listens EVENT_PAGE_IHA_SEARCH_LOCATION
* @listens EVENT_PAGE_IHA_SEARCH_LOCATION_STOP_ANIM
* @listens EVENT_IHA_LOCATION_CLICK
* @listens EVENT_PAGE_IHA_MAP
* @listens EVENT_PAGE_IHA_MAP_STOP_ANIM
* @listens EVENT_IHA_SEARCH_CLEAR
* @listens EVENT_IHA_PRESENTATION_HOME
* @listens EVENT_IHA_PRESENTATION_NEXT
* @listens EVENT_IHA_PRESENTATION_BACK
* @listens EVENT_PAGE_IHA_SEARCH_LOCATION_NAME
* @listens EVENT_IHA_RELOAD_BROWSER
* @listens avatar.eventTypes["CC"]
* @listens avatar.eventTypes["END_CC"]
* @listens UX qrBtn
* @listens UX searchInput
* @memberOf module:modes/iha
* @instance
*/
assignListeners: function() {
var self = this;
// page load
window.tEvent.addListener("EVENT_ADMIN_GOT_MANIFEST", function(evt, data){
self.manifest = data;
});
window.tEvent.addListener(window.tEvent.eventStr.EVENT_TEMPLATE_LOADED, function(evt, eventId){
self.onPageLoad(eventId);
});
window.tEvent.addListener(window.tEvent.eventStr.EVENT_IHA_UPDATE_QR_CODE, function(evt, data){
self.updateQrCode(data);
});
window.tEvent.addListener(["EVENT_PAGE_IHA_SEARCH_LOCATION", "EVENT_PAGE_IHA_SEARCH_LOCATION_STOP_ANIM"], function(evt, data){
self.onFindLocation(data);
});
window.tEvent.addListener("EVENT_IHA_LOCATION_CLICK", function(evt, data){
if (typeof window.oMappedIn.oMapVenue._categoriesById[data] !== "undefined"){
$(self.ui.searchInput).val(window.oMappedIn.oMapVenue._categoriesById[data].name);
}
self.onFindLocation(data);
});
window.tEvent.addListener(["EVENT_PAGE_IHA_MAP", "EVENT_PAGE_IHA_MAP_STOP_ANIM"], function(evt, data){
self.onMap(data);
});
window.tEvent.addListener("EVENT_IHA_SEARCH_CLEAR", function(evt, data){
self.onFindLocation("findloc");
$(self.ui.searchInput).val("");
});
window.tEvent.addListener("EVENT_IHA_PRESENTATION_HOME", function(evt, data){
self.onPresHome();
});
window.tEvent.addListener("EVENT_IHA_PRESENTATION_NEXT", function(evt, data){
self.onPresNext();
});
window.tEvent.addListener("EVENT_IHA_PRESENTATION_BACK", function(evt, data){
self.onPresBack();
});
window.tEvent.addListener("EVENT_PAGE_IHA_SEARCH_LOCATION_NAME", function(evt, data){
self.onFindLocation(data);
});
window.tEvent.addListener("EVENT_IHA_RELOAD_BROWSER", function(evt, data){
window.location.reload();
});
// cc event
this.oPrsonas.sdk.subscribe(this.oPrsonas.avatar.eventTypes["CC"], function(evt) {
self.onCcEvent(evt);
});
// endcc event
this.oPrsonas.sdk.subscribe(this.oPrsonas.avatar.eventTypes["END_CC"], function(evt) {
self.onEndCcEvent(evt);
});
// qr code btn
$("body").hammer().on("click", this.ui.qrBtn, function(e){
self.onToggleQrCode();
});
// search input
$("body").hammer().on("keyup", this.ui.searchInput, function(e){
var str = $(this).val().trim();
self.oMappedIn.onFindLocation(str, function(ret){
self.showSearchResults(ret.data, str);
});
});
},
// --------------------------------------------------------------
// HELPERS
// --------------------------------------------------------------
// ______________________________________________________________
// initMappedIn
/**
* initMappedIn
* @description Initializes MappedIn
* @memberOf module:modes/iha
* @instance
*/
initMappedIn: function() {
var self = this;
if (this.jConfig.map.mappedin.config.venue !== -1){
window.oMappedIn.onInitMappedIn(function(ret){
console.log(" * <iha.initMappedIn>", ret);
});
} else {
console.log(" ! <iha.initMappedIn> Disabled.");
}
},
// ______________________________________________________________
// showSearchResults
/**
* showSearchResults
* @description Shows the search results based on a list of buttons and title to UX
* @param {Array} locList - List of buttons
* @param {String} titleName - Title of search
* @memberOf module:modes/iha
* @instance
*/
showSearchResults: function(locList, titleName) {
if (typeof locList === "undefined") {
locList = [];
}
$(this.ui.searchLocResults).scrollTop(0);
// show search results
var lang = $("body").attr("data-lang");
var emptyModule = this.jConfig.modules["iha-interactive-search-empty"];
var languageCopy = window.oLang.jLangConfig.languageCopy[emptyModule.data["lang-copy-id"]][lang];
var template = window.oDxpTemplates["iha-template-search-location-btns"]({
emptyModule: emptyModule,
languageCopy: languageCopy,
btnList: locList,
data: emptyModule.data
});
$(this.ui.searchLocResults).html(template);
// set title
if (typeof titleName !== "undefined"){
$(this.ui.searchLocTitle).addClass(this.def.CLASS_IN_SEARCH);
$(this.ui.insearchTitle).html(titleName);
} else {
$(this.ui.searchLocTitle).removeClass(this.def.CLASS_IN_SEARCH);
$(this.ui.insearchTitle).html("");
}
},
// ______________________________________________________________
// findCategoriesAndLocations
/**
* findCategoriesAndLocations
* @description Gets MappedIn category(s) and location(s) based on an ID
* @param {String} [findId=findloc] - If an ID is provided then a target category or location will be defined. If not, then a list of all categories and locations will be provided.
* @fires showSearchResults(results)
* @memberOf module:modes/iha
* @instance
*/
findCategoriesAndLocations: function(findId) {
console.log(" * <iha.findCategoriesAndLocations>", findId);
var categories = [];
var locations = [];
var catAndLoc = [];
if (typeof findId === "undefined" || typeof findId === "object" || findId === ""){
findId = "findloc";
}
if (findId !== "findloc") {
// show locations under categories
var category = window.oMappedIn.oMapVenue._categoriesById[findId];
if (typeof category !== "undefined"){
var locations = category.locations
locations = _.sortBy(locations, 'name');
this.showSearchResults(locations, category.name);
} else {
var location = window.oMappedIn.oMapVenue._locationsById[findId];
window.tEvent.fire(window.tEvent.eventStr.EVENT_PAGE_IHA_MAP, location);
}
} else {
$(this.ui.searchLocTitle).removeClass(this.def.CLASS_IN_SEARCH);
// show all categories
categories = _.sortBy(window.oMappedIn.oMapVenue.categories, 'name');
locations = _.sortBy(window.oMappedIn.oMapVenue.locations, 'name');
catAndLoc = categories.concat(locations);
this.showSearchResults(catAndLoc);
}
},
// ______________________________________________________________
// updateQrCode
/**
* updateQrCode
* @description Updates the QR Code graphic
* @param {String} url - Url of the MappedIn WebApp
* @memberOf module:modes/iha
* @instance
*/
updateQrCode: function(url) {
//console.log(" * <iha.updateQrCode> url", url);
if (typeof window.nc_gfx === "undefined"){
console.warn(" ! <iha.updateQrCode> nuBrowser window.nc_gfx is not available");
return;
}
var qrCodeBase64 = window.nc_gfx.getQrCodeBase64(url, 4, "L");
$(this.ui.qrCode).html("<img src='data:image/png;base64, " + qrCodeBase64 + "'/>");
$(this.ui.qrCodeContainer).removeClass(this.def.CLASS_NO_QR_CODE);
},
// ______________________________________________________________
// initPresentation
/**
* initPresentation
* @description Initializes a presentation
* @param {Object} presData - Configuration data of the presentation
* @fires showPresPage()
* @example
* {
* "pageCount": 10,
* "folder": "content/images/Pres1/",
* "filePrefix": "slide_",
* "pageConfig": {
* "slide_5": {
* "id": "m-string",
* "class": "slide5",
* "copy": "Just a reminder that this is slide 5"
* }
* }
* }
* @memberOf module:modes/iha
* @instance
*/
initPresentation: function(presData) {
console.log(" * <iha.initPresentation> ", presData);
var self = this;
this.presentation = window.helpers.clone(presData);
this.presentation._currentPage = 1;
$(this.ui.pres).attr("data-current-page", this.presentation._currentPage);
$(this.ui.presCounterLast).html(this.presentation.pageCount);
// auto nav
if (this.presentationautoNav) {
window.clearTimeout(this.presentationTimer);
this.presentationTimer = window.setTimeout(function(){
self.presAutoNav();
}, this.presentation.autoNavTransitionDelay);
}
this.showPresPage();
},
// ______________________________________________________________
// showPresPage
/**
* showPresPage
* @description Shows the current page of the presentation
* @fires EVENT_IHA_PRESENTATION_SHOW
* @memberOf module:modes/iha
* @instance
*/
showPresPage: function() {
var self = this;
var lang = $("body").attr("data-lang");
var filename = this.presentation.filePrefix + this.presentation._currentPage;
var filepath = this.presentation.folder + lang + "/" + filename + ".png";
if (filename === $(this.ui.pres).attr("data-id")) {
return;
}
// pres data
$(this.ui.pres).attr("data-id", filename);
// pres image
$(this.ui.presImg).attr("src", filepath);
$(this.ui.presImg).css("opacity", 0);
if (typeof this.tweenSlideTransition === "object"){
this.tweenSlideTransition.kill();
}
this.tweenSlideTransition = TweenLite.to($(this.ui.presImg), 1, {opacity: 1});
// show additional content
if (this.presentation !== -1 && typeof this.presentation.pageConfig[filename] !=="undefined"){
var addContent = this.presentation.pageConfig[filename];
$(this.ui.presAdditionalContent).html(window.oDxpTemplates[addContent.id](addContent));
} else {
$(this.ui.presAdditionalContent).html("");
}
// update button states
if (this.presentation._currentPage <= 1){
$(this.ui.presBtn + "[data-id='back']").addClass(this.def.CLASS_IS_DISABLED);
} else {
$(this.ui.presBtn + "[data-id='back']").removeClass(this.def.CLASS_IS_DISABLED);
}
if (this.presentation._currentPage >= this.presentation.pageCount) {
$(this.ui.presBtn + "[data-id='next']").addClass(this.def.CLASS_IS_DISABLED);
} else {
$(this.ui.presBtn + "[data-id='next']").removeClass(this.def.CLASS_IS_DISABLED);
}
// set counter
$(this.ui.presCounterCurrent).html(this.presentation._currentPage);
// send event
window.tEvent.fire(window.tEvent.eventStr.EVENT_IHA_PRESENTATION_SHOW, this.presentation);
},
// ______________________________________________________________
// presAutoNav
/**
* presAutoNav
* @description Auto navigates presentation
* @fires EVENT_IHA_PRESENTATION_NEXT
* @memberOf module:modes/iha
* @instance
*/
presAutoNav: function() {
if ($(this.ui.presBtn + "[data-id='next']").hasClass("is-disabled")){
//window.tEvent.fire("EVENT_IHA_PRESENTATION_HOME");
} else {
window.tEvent.fire("EVENT_IHA_PRESENTATION_NEXT");
window.oTimer.resetTimeout();
}
},
// ______________________________________________________________
// getProjectId
/**
* getProjectId
* @description Returns the project ID. First trying the commandline then falling back to project JSON prsonas.projectId
* @return {String} Returns the project ID
* @memberOf module:modes/iha
* @instance
*/
getProjectId: function() {
var projectId = this.jConfig.prsonas.projectId;
if (typeof this.oPrsonas !== "undefined" &&
typeof this.oPrsonas.app !== "undefined" &&
this.oPrsonas.app.getCommandLineParameters() !== null){
if (typeof this.oPrsonas.app.getCommandLineParameters().experience !== "undefined"){
projectId = this.oPrsonas.app.getCommandLineParameters().experience;
}
}
return (projectId);
},
// --------------------------------------------------------------
// EVENTS
// --------------------------------------------------------------
// ______________________________________________________________
// onCcEvent
/**
* onCcEvent
* @description Receives closed caption event
* @param {Object} data - Message object
* @memberOf module:modes/iha
* @fires showCC()
* @instance
*/
onCcEvent: function(data){
// presentation handling
if (this.presentation !== -1 && this.presentation.autoNav){
window.clearTimeout(this.presentationTimer);
}
},
// ______________________________________________________________
// on`Event
/**
* onEndCcEvent
* @description Receives end closed caption event
* @param {Object} data - Message object
* @memberOf module:modes/iha
* @instance
*/
onEndCcEvent: function(data){
// presentation handling
if (this.presentation !== -1 && this.presentation.autoNav){
window.clearTimeout(this.presentationTimer);
this.presentationTimer = window.setTimeout(function(){
self.presAutoNav();
}, this.presentation.autoNavTransitionDelay);
}
},
// ______________________________________________________________
// onPresHome
/**
* onPresHome
* @description Presentation home btn clicked
* @fires showPresPage()
* @fires EVENT_IHA_PRESENTATION_HOME
* @memberOf module:modes/iha
* @instance
*/
onPresHome: function() {
this.presentation._currentPage = 1;
$(this.ui.pres).attr("data-current-page", this.presentation._currentPage);
this.showPresPage();
},
// ______________________________________________________________
// onPresNext
/**
* onPresNext
* @description Presentation next btn clicked
* @fires showPresPage()
* @fires EVENT_IHA_PRESENTATION_NEXT
* @memberOf module:modes/iha
* @instance
*/
onPresNext: function() {
if (this.presentation._currentPage < this.presentation.pageCount){
this.presentation._currentPage++;
$(this.ui.pres).attr("data-current-page", this.presentation._currentPage);
this.showPresPage();
}
},
// ______________________________________________________________
// onPresBack
/**
* onPresBack
* @description Presentation back btn clicked
* @fires showPresPage()
* @fires EVENT_IHA_PRESENTATION_BACK
* @memberOf module:modes/iha
* @instance
*/
onPresBack: function() {
if (this.presentation._currentPage > 1){
this.presentation._currentPage--;
$(this.ui.pres).attr("data-current-page", this.presentation._currentPage);
this.showPresPage();
}
},
// ______________________________________________________________
// onToggleQrCode
/**
* onToggleQrCode
* @description Toggles the QR Code graphic on/off
* @memberOf module:modes/iha
* @instance
*/
onToggleQrCode: function() {
var $qr = $(this.ui.qrCodeContainer);
if ($qr.hasClass(this.def.CLASS_IS_ACTIVE)){
$qr.removeClass(this.def.CLASS_IS_ACTIVE);
} else {
$qr.addClass(this.def.CLASS_IS_ACTIVE);
}
},
// ______________________________________________________________
// onMap
/**
* onMap
* @description Update MappedIn iframe web app with chosen location
* @param {String} locationName Location name or ID of the location to show
* @memberOf module:modes/iha
* @instance
*/
onMap: function(locationName) {
var self = this;
var startLoc = this.jConfig.map.mappedin.startLocation.id;
var locationData;
var dirStr = "";
if (typeof locationName === "undefined"){
// // reset map
window.oMappedIn.setIframeUrl({
context: "home"
});
return;
}
if (typeof locationName === 'object'){
locationData = locationName;
} else {
locationData = window.oMappedIn.getLocation(locationName);
}
if (locationData === -1){
window.oMappedIn.setIframeUrl({
context: "home"
});
return;
}
console.log(" * <iha.onMap> locationData", locationData);
// show map
window.oMappedIn.setIframeUrl({
context: "directions",
to: locationData.id
});
},
// ______________________________________________________________
// onFindLocation
/**
* onFindLocation
* @description Find result for location by name or ID
* @param {String} locationName Location name or ID of the location to show
* @fire EVENT_PAGE_IHA_SEARCH_LOCATION
* @memberOf module:modes/iha
* @instance
*/
onFindLocation: function(locationName) {
var categories = window.oMappedIn.oMapVenue.categories;
var locationId = "findloc";
var temp;
for (var i = 0; i < categories.length; i++){
temp = window.oMappedIn.parseExternalId(categories[i].externalId);
if (locationName = categories[i].id){ // check by id
locationId = categories[i].id;
break;
} else if (categories[i].name.toLowerCase() === locationName.toLowerCase()){ //check by name
locationId = categories[i].id;
break;
} else if (locationName === temp.name){ // check by externalid
locationId = categories[i].id;
break;
}
}
window.tEvent.fire("EVENT_PAGE_IHA_SEARCH_LOCATION", locationId);
},
// ______________________________________________________________
// onShowMap
/**
* onShowMap
* @description Toggle the map display on and off
* @param {Boolean} state - True is on. False is off.
* @memberOf module:modes/iha
* @instance
*/
onShowMap: function(state) {
if (state){
this.oMappedIn.onFocus(true);
if ( $(this.ui.qrCode + " img").length === 0 ){
$(this.ui.qrCodeContainer).addClass(this.def.CLASS_NO_QR_CODE);
}
} else {
this.oMappedIn.onFocus(false);
}
},
// ______________________________________________________________
// onPageLoad
/**
* onPageLoad
* @description Called when a page is loaded
* @param {String} eventId - Event ID
* @param {Object} data - Event data
* @memberOf module:modes/iha
* @instance
*/
onPageLoad: function(eventId, data) {
var self = this;
var speechState;
if (this.firstLoad){
this.firstLoad = false;
}
switch(eventId){
case "EVENT_PAGE_IHA_MAP":
this.onShowMap(true);
// show interactive
$(this.ui.micToggle).css("display", "block");
break;
default:
this.onShowMap(false);
}
// check for presentation
var modules = this.jConfig.modules;
var isPresentation = false;
for (var mod in modules){
if (typeof modules[mod].event !== "undefined"){
if (modules[mod].event === eventId){
if (typeof modules[mod].presentation !== "undefined"){
// this is a presentation
isPresentation = true;
this.initPresentation(modules[mod].presentation);
break;
}
}
}
}
if (!isPresentation){
window.clearTimeout(this.presentationTimer);
this.presentation = -1;
this.presentationTimer = -1;
}
// init scroller
if ($(this.ui.scroller).length > 0){
$(this.ui.scroller).niceScroll({touchbehavior:true, autohidemode:false});
} else {
$(".nicescroll-rails").remove();
}
}
};
/**
* @global
*/
var oIha = window.oIha = new Iha();
return (oIha);
});