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);
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);
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.
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/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With