Source: managers/mappedin-manager.js

/*
    Loading mappedin.js note:
    The mappedin.js needs to be loaded in the HTML headers as it is not compatible with RequireJS

    Docs:
    https://docs.mappedin.com/web/v6/latest/

    Mobile site:
    https://developer.mappedin.com/pre-built-applications/responsive-web-app-guide

    Languages:
    https://developer.mappedin.com/pre-built-applications/responsive-web-app-guide#2-language
*/

/**
 * @module managers/mappedin-manager
 * @description This module manages MappedIn integration
 * {@link https://www.mappedin.com/}
 */

define([    
], 

function () {

    // ---------------------------------------------------------------
    //
    // MappedIn
    //
    // ---------------------------------------------------------------

    var MappedInManager = function () {
        console.log(" * <mappedin>");        

        window.tEvent.eventStr.EVENT_MAPPEDIN_SDK_READY = "EVENT_MAPPEDIN_SDK_READY";
        window.tEvent.eventStr.EVENT_MAPPEDIN_SEARCH = "EVENT_MAPPEDIN_SEARCH";

        // services
        this.oServices = -1;

        // model loaded
        this.isReady = false;

        // config
        this.jConfig = -1;
        this.jLangConfig = -1;
        this.mapConfig = -1;

        this.def = {
            CLASS_IS_ACTIVE: "is-active"
        };

        this.ui = {
            map             : ".js-complex-map",
            iframe          : ".js-map-iframe",
            title           : ".js-complex-title",
            subtitle        : ".js-complex-subtitle",
            qrBtn           : ".js-iha-qr-btn",
            qrCodeContainer : ".js-iha-map-qr-container",
            configScript    : "#configuration"
        };

        this.activeLanguage = -1;
        this.startLocation = -1;

        // mappedin data
        this.oMapVenue = -1;
        this.oMapView = -1;
        this.offlineSearch = -1;

        this.speechObj = -1;

        this.historyCache = {
            url: -1
        };

        this.init();
    };

    MappedInManager.prototype = {    
       
        // ______________________________________________________________
        //                                                           init
        /**
            * init
            * @description Initializes class
            * @fires assignListeners()
            * @memberOf module:managers/mappedin-manager
            * @instance
        */
        init: function() { 
            this.assignListeners();            
        },


        // ______________________________________________________________
        //                                                assignListeners
        // ______________________________________________________________
        //                                                assignListeners
        /** 
        * assignListeners
        * @description Assigns listeners to events used in this class.
        * @listens  EVENT_MODEL_READY
        * @listens  EVENT_LANGUAGE_CONFIG_LOADED
        * @listens  EVENT_SET_LANGUAGE
        * @listens  iframe MappedIn web app 'message'
        * @memberOf module:managers/mappedin-manager
        * @instance
        */
        assignListeners: function() {           
            var self = this;


            if (typeof window.oModel === "undefined" || window.oModel.jConfig === -1){
                window.tEvent.addListener("EVENT_MODEL_READY", function(evt, data)
                {
                    // clean up for new page
                    self.onJsonLoaded(); 
                });                
            } else {
                self.onJsonLoaded(); 
            }


            // get language config
            window.tEvent.addListener("EVENT_LANGUAGE_CONFIG_LOADED", function(evt, data){
                self.jLangConfig = data;
            });


            // set language 
            window.tEvent.addListener(window.tEvent.eventStr.EVENT_SET_LANGUAGE, function(evt, data){

                if (self.mapConfig.venue !== -1) {
                    var language = $("body").attr("data-lang");
                    if (self.activeLanguage !== language){
                        self.onInitMappedIn(function(){});
                    }                    
                }

            });


            //got message from iframe
            window.addEventListener('message', function(e){
                if (typeof e.data.isIha !== "undefined"){
                    self.onIframeMsg(e.data);
                }
            });

        },
      

        // --------------------------------------------------------------
        // HELPERS
        // --------------------------------------------------------------

        

        // ______________________________________________________________
        //                                                sendIframeEvent
        /**
            * sendIframeEvent
            * @description Send event with data to iframe web app
            * @param {Object} sendData - Data to send to iframe
            * @fires postMessage
            * @memberOf module:managers/mappedin-manager
            * @instance
        */
        sendIframeEvent: function(sendData) { 

            sendData.isIha = true;

            console.log(" * <mappedin.sendIframeEvent>", sendData);

            $(this.ui.iframe)[0].contentWindow.postMessage(sendData, "*");

        },

        // ______________________________________________________________
        //                                               getBaseWebAppUrl
        /**
            * getBaseWebAppUrl
            * @description Returns the webapp URL
            * @returns {String} URL
            * @memberOf module:managers/mappedin-manager
            * @instance
        */
        getBaseWebAppUrl: function() { 

            var mappedinConfig = this.jConfig.map.mappedin;
            var langMapping = mappedinConfig.languageMapping;
            var url = this.mapConfig.url + this.mapConfig.venue;

            // keey language up to date
            var language = $("body").attr("data-lang");
            if (typeof language === "undefined") {
                language = "_English";
            }
            self.activeLanguage = language;
            
            // set language            
            var langId = langMapping[language];
            this.mapConfig.language = langId;


            url += "&clientId=" + this.mapConfig.clientId;
            url += "&clientSecret=" + this.mapConfig.clientSecret;
            url += "&language=" + this.mapConfig.language;

            return(url);

        },

        // ______________________________________________________________
        //                                                     initWebApp
        /**
            * initWebApp
            * @description Initialize iframe web app
            * @memberOf module:managers/mappedin-manager
            * @instance
        */
        initWebApp: function() { 
            var url = this.getBaseWebAppUrl();

            console.log(" * <mappedin.initWebApp>", url);

            this.speechObj = -1;

            // create iframe webapp
            var iFrame = window.oDxpTemplates["m-iframe"]({
                "id": "m-iframe",
                "class": "iha-mappedin-container__iframe js-map-iframe",
                "source": url
            });
            $(this.ui.map).html(iFrame);
        },

        // ______________________________________________________________
        //                                                     initWebApp
        /**
            * setIframeUrl
            * @description Sets the iframe web app url
            * @param {Object} config - to, location IDs
            * @example
            * config = {
            *   context: "directions",
            *   to: location_id
            * }
            * 
            * config = {
            *   context: "location",
            *   location: location_id
            * }
            * @memberOf module:managers/mappedin-manager
            * @instance
        */
        setIframeUrl: function(config) { 

            if (!this.isSdk){
                console.log(" * <mappedin.initSDK> Using SDK.");
                return;
            }

            var url = this.getBaseWebAppUrl();

            

            switch(config.context){
                case "directions":
                    url += "#/directions?to=" + config.to;
                    url += "&from=" + this.startLocation.id;
                    break;

                case "location":
                    url += "#/profile?location=" + config.location; 
                    break;     

                case "home":
                    $(this.ui.iframe).attr("src", url);
                    return;
                    break;   
            }

            if (config.context !== "home") {
                if (typeof config.isFromSpeech !== "undefined" && config.isFromSpeech !== false) {
                    url += "&fromspeech=" + new Date().getMilliseconds();
                }
            }

            

            // send url change
            this.sendIframeEvent({
                url: url
            });

        },

        // ______________________________________________________________
        //                                               parseIncomingUrl

        /**
            * parseIncomingUrl
            * @description Parses incoming url from iframe web app and returns it as useful data
            * @param {String} url
            * @returns {Object}
            * @example
            * {
            *    "_hash": "directions",
            *    "_url": "https://app-webmaps-prod-uksouth-001.azurewebsites.net/iframe/index.html?venue=numedia-princess-alexandra#/directions?to=653c557290a8958587cdae90&from=653c5e5790a8958587cdae94",
            *    "to": "653c557290a8958587cdae90",
            *    "from": "653c5e5790a8958587cdae94"
            * }
            * @memberOf module:managers/mappedin-manager
            * @instance
        */
        parseIncomingUrl: function(url) {

            var foo = url.split("#/")[1].split("?");
            var dict = {};
            var elem = [];  
            
            dict._hash = foo[0];
            dict._url = url;

            if (foo.length > 1){
                foo = foo[1].split("&");
                for (var i = 0; i < foo.length; i++){
                    elem = foo[i].split('=');
                    dict[elem[0]] = elem[1];
                }
            }

            return dict;    
        },


        // ______________________________________________________________
        //                                               processIframeUrl
        
        /**
            * processIframeUrl
            * @description Process the results of the iframe web app URL parsing
            * @param {Object} urlObj - Object returned from parseIncomingUrl()
            * @param {Object} iframeData - Data returned from iframe
            * @returns {Object}
            * @fires EVENT_IHA_UPDATE_QR_CODE
            * @memberOf module:managers/mappedin-manager
            * @instance
        */
        processIframeUrl: function(urlObj, iframeData) {   
            var lang = $("body").attr("data-lang");
            var langExceptions = this.jConfig.services.genaiFallbackToIntents;
            var doFallback = false;

            var urlEdited = urlObj._url.replace("&isEditing=true", "");
            urlEdited = urlEdited.replace("&isEditing=false", "");
            urlEdited = urlEdited.replace("&textDirectionsVisible=true", "");
            urlEdited = urlEdited.replace("&textDirectionsVisible=false", "");

            var def = window.helpers.showStringDifferences(this.historyCache.url, urlEdited);


            // check for genai to intent fallback
            for (var i = 0; i < langExceptions.length; i++) {
                if (langExceptions[i] === lang) {
                    doFallback = true;
                    break;
                }
            }



            if (iframeData.fromSpeech === "true" || iframeData.fromSpeech === true){
                this.historyCache.url = urlObj._url;
            } else {
                if (this.historyCache.url === urlEdited){
                    // this is a redundant url return
                    return;
                } else {
                    this.historyCache.url = urlObj._url;
                }
            }

            // console.warn(" * <mappedin.processIframeUrl> String differences between received and history", def);

            if (urlObj._hash === "") {
                return;
            }    


            console.log(" * <mappedin.processIframeUrl>", urlObj);

            // remove qr (if using button)
            $(this.ui.qrCodeContainer).removeClass("is-active");

            switch(urlObj._hash){

                case "categories":
                    $(this.ui.subtitle).html("");
                    if (typeof urlObj.category !== "undefined"){                    
                        console.log(" * <mappedin.processIframeUrl> Got category", urlObj.category);
                        $(this.ui.title).html(urlObj.category);
                    } else {                        
                        console.log(" * <mappedin.processIframeUrl> In category select section");
                        $(this.ui.title).html("Categories");
                    }
                    break;



                case "search":
                    $(this.ui.title).html("Search");
                    $(this.ui.subtitle).html("");
                    break;



                case "directions":
                    $(this.ui.title).html(this.jConfig.map.mappedin.avatarSpeech.responses[lang].directionTitleCopy);
                    $(this.ui.subtitle).html("");
                    if (typeof urlObj.from === "undefined" && typeof urlObj.to === "undefined"){                        
                        //console.log(" * <mappedin.processIframeUrl> Ignored. Missing a location.");
                    } else if (typeof urlObj.from === "undefined"){

                        var toLocationData = this.getLocation(urlObj.to);
                        var fromLocationData = this.getLocation(this.startLocation.id);
                        var copy = this.jConfig.map.mappedin.avatarSpeech.responses[lang].directionFromToTitleCopy;
                        copy = window.helpers.replaceAll(copy, "[FROM_LOCATION_NAME]", fromLocationData.name);
                        copy = window.helpers.replaceAll(copy, "[TO_LOCATION_NAME]", toLocationData.name);
                        $(this.ui.subtitle).html(copy);

                        this.setIframeUrl({
                            "context": "directions",
                            "to": urlObj.to
                        });

                    } else  if (typeof urlObj.to === "undefined"){
                        //console.log(" * <mappedin.processIframeUrl> Ignored. Missing a location.");
                        var fromLocationData = this.getLocation(this.startLocation.id);

                        var copy = this.jConfig.map.mappedin.avatarSpeech.responses[lang].directionFromTitleCopy;
                        copy = window.helpers.replaceAll(copy, "[LOCATION_NAME]", fromLocationData.name);
                        $(this.ui.subtitle).html(copy);
                        
                    } else {
                        //console.log(" * <mappedin.processIframeUrl> got directions!");
                        var toLocationData = this.getLocation(urlObj.to);
                        var fromLocationData = this.getLocation(urlObj.from);
                        var copy = this.jConfig.map.mappedin.avatarSpeech.responses[lang].directionFromToTitleCopy;
                        copy = window.helpers.replaceAll(copy, "[FROM_LOCATION_NAME]", fromLocationData.name);
                        copy = window.helpers.replaceAll(copy, "[TO_LOCATION_NAME]", toLocationData.name);
                        $(this.ui.subtitle).html(copy);


                        if (this.speechObj !== -1) {
                            intent = window.oSpeech.formatIntentName(toLocationData.id);
                            window.oPrsonas.sendKey(intent, this.speechObj.answer);
                            this.speechObj = -1;
                        } else {
                            if (doFallback) {
                                window.oPrsonas.sendKey(this.jConfig.map.mappedin.avatarSpeech.signLanguageIntents.directions);
                            } else if (typeof this.jConfig.map.mappedin.avatarSpeech.responses[lang].directions !== ""){
                                var speechCopy = this.jConfig.map.mappedin.avatarSpeech.responses[lang].directions;
                                speechCopy = window.helpers.replaceAll(speechCopy, "[LOCATION_NAME]", toLocationData.name);

                                var intent = fromLocationData.name + "_to_" + toLocationData.name;
                                intent = window.oSpeech.formatIntentName(intent);
                                window.oPrsonas.sendKey(intent, speechCopy);
                            } else {
                                intent = window.oSpeech.formatIntentName(toLocationData.id);
                                window.oPrsonas.sendKey(intent, toLocationData.id);
                            }                            
                        }


                        
                    }
                    break;




                case "location":
                    var locationData = this.getLocation(urlObj.location);
                        $(this.ui.title).html(this.jConfig.map.mappedin.avatarSpeech.responses[lang].locationTitleCopy);
                        $(this.ui.subtitle).html(locationData.name);

                        if (this.jConfig.map.mappedin.routeLocationSelections) {
                            config = {
                                context: "directions",
                                "to": locationData.id
                            };
                            this.setIframeUrl(config);

                            if (doFallback) {
                                window.oPrsonas.sendKey(this.jConfig.map.mappedin.avatarSpeech.signLanguageIntents.location);
                            } else if (typeof this.jConfig.map.mappedin.avatarSpeech.responses[lang].location !== ""){
                                var speechCopy = this.jConfig.map.mappedin.avatarSpeech.responses[lang].location;
                                speechCopy = window.helpers.replaceAll(speechCopy, "[LOCATION_NAME]", locationData.name);
                                var intent = window.oSpeech.formatIntentName(locationData.name);
                                window.oPrsonas.sendKey(intent, speechCopy);
                            } else {
                                window.oPrsonas.sendKey(objData.intent);
                            }

                        } else {
                            if (locationData !== -1){

                                if (doFallback) {
                                    window.oPrsonas.sendKey(this.jConfig.map.mappedin.avatarSpeech.signLanguageIntents.location);                                    
                                } else if (typeof this.jConfig.map.mappedin.avatarSpeech.responses[lang].location !== ""){
                                    var speechCopy = this.jConfig.map.mappedin.avatarSpeech.responses[lang].location;
                                    speechCopy = window.helpers.replaceAll(speechCopy, "[LOCATION_NAME]", locationData.name);
                                    var intent = window.oSpeech.formatIntentName(locationData.name);
                                    window.oPrsonas.sendKey(intent, speechCopy);
                                } else {
                                    window.oPrsonas.sendKey(locationData.id);
                                }

                            }
                        }
                    break;




                default:
                    // profile
                    if (typeof urlObj.location !== "undefined"){
                        var locationData = this.getLocation(urlObj.location);
                        $(this.ui.title).html(this.jConfig.map.mappedin.avatarSpeech.responses[lang].locationTitleCopy);
                        $(this.ui.subtitle).html(locationData.name);
               
                        if (locationData !== -1){

                            if (doFallback) {
                                    window.oPrsonas.sendKey(this.jConfig.map.mappedin.avatarSpeech.signLanguageIntents.location);                                    
                            } else if (typeof this.jConfig.map.mappedin.avatarSpeech.responses[lang].location !== ""){
                                var speechCopy = this.jConfig.map.mappedin.avatarSpeech.responses[lang].location;
                                speechCopy = window.helpers.replaceAll(speechCopy, "[LOCATION_NAME]", locationData.name);
                                var intent = window.oSpeech.formatIntentName(locationData.name);
                                window.oPrsonas.sendKey(intent, speechCopy);
                            } else {
                                window.oPrsonas.sendKey(locationData.id);
                            }

                        }
                       
                    }
                    break;
            }

            
            window.tEvent.fire("EVENT_IHA_UPDATE_QR_CODE", urlObj._url);
        },


        // ______________________________________________________________
        //                                                          isSdk
        /**
            * isSdk
            * @description Getter if using the MappedIn SDK from project JSON map.mappedin.isUsingSDK 
            * @returns {Boolean} project JSON map.mappedin.isUsingSDK
            * @memberOf module:managers/mappedin-manager
            * @instance
        */
        isSdk: function() {
            return this.jConfig.map.mappedin.isUsingSDK;
        },


        // ______________________________________________________________
        //                                                        initSDK
        /**
            * initSDK
            * @description Initializes MappedIn SDK 
            * @memberOf module:managers/mappedin-manager
            * @fires EVENT_MAPPEDIN_SDK_READY
            * @instance
        */
        initSDK: function() {  

            console.log(" * <mappedin.initSDK> Using SDK.");

            var self = this;
            var mappedinConfig = this.jConfig.map.mappedin;
            var langMapping = mappedinConfig.languageMapping;
            var language = $("body").attr("data-lang");
            var returnObj = window.oModel.getReturnObj();
            var langId;
            var stackedMapConfig = {};

            this.speechObj = -1;

            if (typeof language === "undefined") {
                language = "_English";
            }
            self.activeLanguage = language;
            
            // set language            
            langId = langMapping[language];
            this.mapConfig.language = langId;

            if (mappedinConfig.enableStackMaps){
                stackedMapConfig = mappedinConfig.stackedMapConfig;
            }

            // show loading modal
            if (this.jLangConfig !== -1){
                window.oModal.load({
                    id       : "m_language_load",
                    content  :  window.oDxpTemplates.m_language_load(this.jLangConfig.languageCopy.iha_loading_modal[language]),
                    backdrop : 'static',
                    close    : false
                });
            }


            window.Mappedin.getVenue(this.mapConfig).then(function(mapVenueRet){

                console.log(" * <mappedin.initSDK@getVenue> success: " + langId);
                self.oMapVenue = mapVenueRet;


                window.Mappedin.showVenue(document.getElementById(mappedinConfig.containerId), self.oMapVenue, stackedMapConfig).then(function(mapViewRet){

                    console.log(" * <mappedin.initSDK@showVenue> success: " + langId);

                    self.oMapView = mapViewRet; 
                    
                    // init search
                    self.offlineSearch = new window.Mappedin.OfflineSearch(self.oMapVenue);

                    // get starting location
                    self.initStartingLocation();

                    if (typeof window.oModal.modals["m_language_load"] !== "undefined"){
                        window.oModal.modals["m_language_load"].close();
                    }

                    // announce map ready
                    window.tEvent.fire(window.tEvent.eventStr.EVENT_MAPPEDIN_SDK_READY);

                }, function(e){
                    console.log(" * <mappedin.initSDK@showVenue> failed: " + langId);
                });


            }, function(e){
                console.log(" * <mappedin.initSDK@getVenue> failed: " + langId);    
            });
        },


        // ______________________________________________________________
        //                                           initStartingLocation
        /**
            * initStartingLocation
            * @description Initializes starting location based on project JSON map.mappedin.startLocation. Override through index.html data-mappedin-start-loc-id config. Override through map_prsonas_loc_id Prsonas viewer commandline param.
            * @memberOf module:managers/mappedin-manager
            * @instance
        */
        initStartingLocation: function() { 
            var self = this;        
            var mappedinConfig = this.jConfig.map.mappedin;
            var locations = this.oMapVenue.locations;
            var qs = window.helpers.parseQuerystring();



            // from json
            this.startLocation = window.helpers.clone(mappedinConfig.startLocation);

            // from index.html config data-mappedin-start-loc-id
            if ($(this.ui.configScript).length !== 0 && $(this.ui.configScript).attr("data-mappedin-start-loc-id") !== "undefined"){
                this.startLocation = { id: $(this.ui.configScript).attr("data-mappedin-start-loc-id") };
            }

            if (typeof qs.map_prsonas_loc_id !== "undefined"){
                this.startLocation = { id: qs.map_prsonas_loc_id };
            }

            // from Prsonas viewer commandline map_prsonas_loc_id
            if (typeof window.oPrsonas !== "undefined" &&
                typeof window.oPrsonas.app !== "undefined" &&
                window.oPrsonas.app.getCommandLineParameters() !== null){

                if (typeof window.oPrsonas.app.getCommandLineParameters().map_prsonas_loc_id !== "undefined"){
                    this.startLocation = { id: window.oPrsonas.app.getCommandLineParameters().map_prsonas_loc_id };
                }                
            }



            // get lat/long of start location
            if (mappedinConfig.startLocation.id !== "" && this.startLocation.id !== -1){
                for (var i = 0; i < locations.length; i++){
                    if (locations[i].id === mappedinConfig.startLocation.id){
                        this.startLocation.latitude = locations[i].nodes[0].lat;
                        this.startLocation.longitude = locations[i].nodes[0].lon;
                        this.startLocation.node = locations[i].nodes[0];
                        this.startLocation.name = locations[i].name;
                        this.startLocation.id = locations[i].id;
                        break;
                    }
                }
            } else if (mappedinConfig.startLocation.name !== "" && this.startLocation.name !== -1){
                for (var i = 0; i < locations.length; i++){
                    if (locations[i].name === mappedinConfig.startLocation.name){
                        this.startLocation.latitude = locations[i].nodes[0].lat;
                        this.startLocation.longitude = locations[i].nodes[0].lon;
                        this.startLocation.node = locations[i].nodes[0];
                        this.startLocation.name = locations[i].name;
                        this.startLocation.id = locations[i].id;
                        break;
                    }
                }
            }
          
        },
       

        // ______________________________________________________________
        //                                                    getLocation
        /**
            * getLocation
            * @description Gets MappedIn location object from location ID or name
            * @param {String} location - Location ID or name
            * @returns {Object} MappedIn location object           
            * @memberOf module:managers/mappedin-manager
            * @instance
        */
        getLocation: function(location) { 

            if (!this.isSdk()){
                console.warn(" * <mappedin.getLocation> Not using SDK.");
                return;
            }

            location = location.toLowerCase();

            if (location.indexOf("_") !== -1){
                location = location.split("_")[1];
            }

            var locations = this.oMapVenue.locations;
            var retObj = -1;
            var externalId;
            var parsedLocation;

            for (var i = 0; i < locations.length; i++){
                
                externalId = locations[i].externalId.toLowerCase();
                externalId = this.parseExternalId(externalId);

                if (externalId !== -1 && externalId.name !== "undefined" && location === externalId.name) {// check by externalId    
                    retObj = locations[i];
                    break;
                } else if (location === locations[i].id){ // check by id
                    retObj = locations[i];
                    break;
                } else if (location === locations[i].name.toLowerCase()){ // check by name
                    retObj = locations[i];
                    break;
                }
            } 

            if (retObj === -1){
                for (var i = 0; i < locations.length; i++){
                    if (typeof locations[i].polygons !== "undefined"){
                        for (var x = 0; x < locations[i].polygons.length; x++) {
                            if (location === locations[i].polygons[x].id){
                                retObj = locations[i];
                                break;
                            }
                        }
                    }
                }
            }

            return(retObj);
        },

        // ______________________________________________________________
        //                                                 showDirections
        /**
            * showDirections
            * @description Show directions to a given location
            * @param {String} location - Location ID or name   
            * @param {Object} phraseObj - Identifies if this is from speech  
            * @memberOf module:managers/mappedin-manager
            * @instance
        */
        showDirections: function(locationId, phraseObj) { 

            if (typeof phraseObj === "undefined") {
                isFromSpeech = false;
            } else {

                isFromSpeech = true;

                if (phraseObj.answer !== ""){
                    this.speechObj = phraseObj;
                } 
            }

            this.setIframeUrl({
                "context"      : "directions",
                "to"           : locationId,
                "isFromSpeech" : isFromSpeech
            });
        },



        // --------------------------------------------------------------
        // EVENTS
        // --------------------------------------------------------------
        
        // ______________________________________________________________
        //                                                    onIframeMsg
        /**
            * onIframeMsg
            * @description Handles message object that comes from iframe web app
            * @param {Object} iframeData
            * @fires processIframeUrl()         
            * @memberOf module:managers/mappedin-manager
            * @instance
        */
        onIframeMsg: function(iframeData) {   

            switch(iframeData.context){
                case "urlChange":
                    var urlObj = this.parseIncomingUrl(iframeData.value);
                    this.processIframeUrl(urlObj, iframeData);                      
                    break;
            }
        },

         // ______________________________________________________________
        //                                                parseExternalId
        /*
            * @description Parses external id from String to Object. Parses externalId: "name=adsu|intent=ADSU"
            into an object
            * @param {String} externalId       
            * @memberOf module:managers/mappedin-manager
            * @instance
            
        */
        parseExternalId: function(externalId) {

            if (typeof externalId === "undefined"){
                return (-1);
            }

            var extId = externalId.split("|");
            var objData = {};
            for (var i = 0; i < extId.length; i++) {
                objData[extId[i].split("=")[0]] = extId[i].split("=")[1];
            }

            return(objData);
        },


        // ______________________________________________________________
        //                                                        onFocus
        /**
            * onFocus
            * @description Handles activity when iframe MappedIn web app is in focus
            * @param {Boolean} isFocus       
            * @memberOf module:managers/mappedin-manager
            * @instance
        */
        onFocus: function(isFocus) {   
            console.log(" * <mappedin.onFocus>", isFocus);

            if (isFocus){
                $(this.ui.map).addClass(this.def.CLASS_IS_ACTIVE);

            } else {
                $(this.ui.map).removeClass(this.def.CLASS_IS_ACTIVE);
                
                this.speechObj = -1;

                this.setIframeUrl({
                    context: "home"
                }); 

                // fixes no intent if navigating to the same page.
                this.historyCache.url = -1;               
            }
        },


        // ______________________________________________________________
        //                                                 onInitMappedIn
        /**
            * onInitMappedIn
            * @description Initializes MappedIn iframe web app and SDK
            * @fires initWebApp()
            * @fires initSDK()        
            * @memberOf module:managers/mappedin-manager
            * @instance
        */
        onInitMappedIn: function() {   
            
            if (typeof this.jConfig.map === "undefined"){
                return;
            }

            this.initWebApp();

            // are we using the SDK?
            if (!this.isSdk()){
                console.warn(" * <mappedin.onInitMappedIn> Not using SDK.");
            } else {
                this.initSDK();
            }

        },

        // ______________________________________________________________
        //                                                   onJsonLoaded
        /**
            * onJsonLoaded
            * @description Handles private vaiables when project JSON is loaded
            * @memberOf module:managers/mappedin-manager
            * @instance
        */
        onJsonLoaded: function() {              

            this.jConfig      = window.oModel.jConfig;

            if (typeof this.jConfig.map === "undefined"){
                return;
            }

            this.mapConfig    = window.helpers.clone(this.jConfig.map.mappedin.config);
            this.webAppConfig = window.helpers.clone(this.jConfig.map.mappedin.webApp);
            this.oServices    = window.oModel.oServices;

            if (this.mapConfig.venue !== -1){
                this.isReady = true;
            } else {
                this.jConfig.map.mappedin.isUsingSDK = false;
            }
            
        }


    };

    return (MappedInManager);        
   
});