Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Callback not being invoked

I am building a custom Power BI visualization, so I have access to a javascript file which is consumed by the platform. I don't have access to any markup, only an element that is injected where I am to mount my visualization.

I am trying to mount a Bing Map, the docs look like this:

    <div id='myMap' style='width: 100vw; height: 100vh;'></div>

    <script type='text/javascript'>
            var map;
            function loadMapScenario() {
                map = new Microsoft.Maps.Map(document.getElementById('myMap'), {});
            }


    </script>

    <script type='text/javascript' src='https://www.bing.com/api/maps/mapcontrol?key=YourBingMapsKey&callback=loadMapScenario' async defer></script>

The URL to the script has a callback querystring param that includes the name of the function to invoke.

Given I don't have access to the markup, I'm trying to do everything dynamically in my visualization's constructor. I create a function, move it to global scope, and then I add the querystring var to reference it, but it never gets invoked. Can you see anything I might be missing?

constructor(options: VisualConstructorOptions) {
        this.host = options.host;
        this.elem = options.element;
        const self = this;

        function moveMethodsIntoGlobalScope(functionName){
            var parts = functionName.toString().split('\n');
            eval.call(window, parts.splice(1, parts.length - 2).join(''));  
        }

        function methodsToPutInGlobalScope(){
            function loadMapScenario(){
                console.log("finally called loadMapScenario");
            }
        }

        const script = document.createElement('script');
        script.type = 'text/javascript';
        script.async = true;

        console.log(loadMapScenario === undefined); // false, definitely in global scope
        script.src = 'https://www.bing.com/api/maps/mapcontrol?key=xxxxxxxxxx&callback=loadMapScenario';
        document.getElementsByTagName('head')[0].appendChild(script);
like image 953
Mister Epic Avatar asked Nov 17 '17 18:11

Mister Epic


3 Answers

You've defined the functions required to accomplish what you want. However, in the snippet you've given, you're not actually calling upon moveMethodsIntoGlobalScope(), which is why loadMapScenario is undefined. Just add this line before injecting the script.

moveMethodsIntoGlobalScope(methodsToPutInGlobalScope);
like image 200
jaswrks Avatar answered Nov 08 '22 23:11

jaswrks


To put a method into the global scope in the browser, you can probably make do with something simpler, like:

window.loadMapScenario = () => {
  console.log("finally called loadMapScenario")
}

I don't think you need moveMethodsIntoGlobalScope or methodsToPutInGlobalScope - you aren't calling either of them from this code, in any case.

like image 3
qntm Avatar answered Nov 08 '22 22:11

qntm


I think this code is enough:

window.loadMapScenario = function() {
  console.log("finally called loadMapScenario");
}

const script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = `https://www.bing.com/api/maps/mapcontrol?key=${API_KEY}&callback=loadMapScenario`;
document.getElementsByTagName('head')[0].appendChild(script);

Here is a JSFiddle you can try with your API_KEY: https://jsfiddle.net/9mfzrcfd/2/

like image 2
vl4d1m1r4 Avatar answered Nov 08 '22 22:11

vl4d1m1r4