I want to load an external javascript (without jquery or others) into my Corodova/Phonegapp app (Visual Studio 2015, Cordova CLI 6.1.1) when the app is actually ready and online (I check that in the original code, but did not enter it in the example below). Ultimately this external javascript will be the google maps javascript api. However since I ran into some problems I first tryed with my own little javascript file (external_file.js
).
While debugging I can see that the <script src="https://myhost/external_file.js"></script>
tag is writen into the original code of my app, but I can not access the loaded code (function external_function()
is not available ). I tryed with the ripple emulator as well as with my android 5.1.1 device.
All my functions work on a "normal" html file without cordova. Also when I try to load the javascript file locally (from scripts/external_file.js
) I can access the functions located inside the file.
I search quite some time for a solution, but did not find anything usefull:
- Andreas Linnert had a similar problem in 2013, but no answer is given there.
- psycrow117 wanted to load the googel maps api with
<script></script>
tags (as given in the Google Maps Javascript API Example). However I would like to do that with a function - rolinger did not load the cordova-plugin-whitelist (which I do)
- FabianE and KRIZTE describe the same problem. I actually use the solution by Blauharley and e-satis with Jason Livesay to load the external script. However the problem does not seem to be solved in that post, too.
I know that there is the cordova-plugin-googlemaps to load the native environment. Let's just say I do not want to do that for now. If there is no other solution I will have to...
Since my functions work with a "normal" html file and I can also load a local script file corretly, I think I forgot to set something correctly to be able to execute the external code.
I set the Content-Security-Policy
to
<meta http-equiv="Content-Security-Policy" content="default-src: 'self' https://myhost https://maps.google.com 'unsafe-inline' 'unsafe-eval'">
<meta http-equiv="Content-Security-Policy" content="script-src: 'self' https://myhost https://maps.google.com 'unsafe-inline' 'unsafe-eval'">
I also entered the cordova-plugin-whitelist
parameters
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<access origin="https://*.googleapis.com" />
<access origin="https://myhost" />
<access origin="*" />
<allow-navigation href="https://*.googleapis.com" />
<allow-navigation href="https://myhost" />
<allow-navigation href="*" />
<allow-intent href="https://*.googleapis.com" />
<allow-intent href="https://myhost" />
<allow-intent href="*" />
But somehow that does not seem to work, too.
Does anyone have a solution to be able to execute the code after loading the external file?
Later the google maps javascript api needs to be asyncron, but that's a nother issue then.
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
<!-- Enable all requests, inline styles, and eval() -->
<meta http-equiv="Content-Security-Policy" content="default-src: 'self' https://myhost https://maps.google.com 'unsafe-inline' 'unsafe-eval'">
<meta http-equiv="Content-Security-Policy" content="script-src: 'self' https://myhost https://maps.google.com 'unsafe-inline' 'unsafe-eval'">
<link rel="stylesheet" type="text/css" href="css/index.css">
<title>Testapp</title>
</head>
<body>
<div class="app">
<h1>Testapp</h1>
<button id="loadexternal_button">load external file</button>
<button id="isloaded_button">is loaded?</button>
<div id="map"></div>
</div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="scripts/platformOverrides.js"></script>
<script type="text/javascript" src="scripts/index.js"></script>
</body>
</html>
index.css
.app {
background-color:white;
}
#map{
height: 400px;
width: 400px;
border:1px solid white;
}
index.js
(function () {
"use strict";
function onDeviceReady() {
// Event Listener for Buttons: https://stackoverflow.com/a/31892530/2381164
document.getElementById('isloaded_button').addEventListener('click', function () { checkLoadedFile(); }, false);
document.getElementById('loadexternal_button').addEventListener('click', function () { loadJS('https://myhost/external_file.js', hasloaded(), document.body);
}, false);
};
// https://stackoverflow.com/a/950146/2381164
function loadJS(url, implementationCode, location) {
var scriptTag = document.createElement('script');
scriptTag.src = url;
scriptTag.onload = implementationCode;
scriptTag.onreadystatechange = implementationCode;
location.appendChild(scriptTag);
};
// Change color of div when script is loaded
function hasloaded() {
var mapElement = document.getElementById('map');
mapElement.setAttribute('style', 'border:1px solid yellow');
}
// Change background-color of div when file is loaded propperly
function checkLoadedFile() {
var mapElement = document.getElementById('map');
if (typeof external_function === 'function') {
mapElement.setAttribute('style', 'background-color: green;');
} else {
mapElement.setAttribute('style', 'background-color: red;');
}
}
// Load when App is ready
document.addEventListener('deviceready', onDeviceReady.bind(this), false);
})();
external_file.js
function external_function() {
var mapElement = document.getElementById('map');
mapElement.setAttribute('style', 'background-color: orange;');
}