I have a cross platform app built using PhoneGap/Cordova.
I am trying to implement a function that runs an external JavaScript file when a controller loads. I am following a solution from HERE. And similarly HERE. But I want the JavaScript to execute without the window.open event, i.e. I want to run executeScript as soon as the device is ready.
How do I call the executeScript() without defining the var ref first though?
var navigation = angular.module("navigation", []);
navigation.controller("Navigation", function ($scope) {
var init = function () {
document.addEventListener("deviceready", onDeviceReady, false);
};
init();
function onDeviceReady() {
// LOAD EXTERNAL SCRIPT
var ref = window.open('http://www.haruair.com/', '_blank', 'location=yes, toolbar=yes, EnableViewPortScale=yes');
ref.addEventListener("loadstop", function () {
ref.executeScript(
{ file: 'http://haruair.com/externaljavascriptfile.js' },
function () {
ref.executeScript(
{ code: 'getSomething()' },
function (values) {
var data = values[0];
alert("Name: " + data.name + "\nAge: " + data.age);
});
}
);
});
});
You could try to add the script in the index.html file and do whatever you want from JS. Also, you must add to your whitelist this endpoint.
<!-- index.html -->
<script>
function onCustomLoad() {
//do stuff
}
</script>
<script src="your-custom-script" onload="onCustomLoad"></script>
you could use
var script = document.createElement("script");
script.type = "text/javascript";
script.id = "some_id";
script.src = 'http://haruair.com/externaljavascriptfile.js';
document.head.appendChild(script);
then call the function once finished
Related
I have some simple code like this:
JS:
function load (element, url) {
element.innerHTML = '';
fetch(url).then(function (resp) {
return resp.text();
}).then(function (content) {
element.insertAdjacentHTML('afterbegin', content);
});
}
Content of url parameter of load function:
<div>
<button id="some-button">Execute click!</button>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('some-button').addEventListener('click', function () {
alert('Click at button has been executed.');
});
});
</script>
My question is: Why click event (or any other JS code) does not work? HTML content is loaded, script tag also do, but JS code does not executing. I just want to replace jQuery function load with custom function load described above.
Thanks in advance!
I think JS code included like that does not get recognized as JS code. I mean, text containing <script> tag is not considered as JS code and not run. Tried the following and it seems to work. Not sure if this solves your requirement, but it might help you understand the issue. Note the usage of document.createElement('script')
<div id="content"></div>
<script>
var scr = `document.getElementById('some-button').addEventListener('click', function () {
alert('Click at button has been executed.');
});`;
var content = `<div><button id="some-button">Execute click!</button></div>`;
document.getElementById('content').insertAdjacentHTML('afterbegin', content);
var sel = document.createElement('script');
sel.text = scr;
document.getElementById('content').appendChild(sel);
</script>
Here is final working code:
fetch(url).then(function (resp) {
return resp.text();
}).then(function (body) {
element.insertAdjacentHTML('afterbegin', body);
let scripts = element.getElementsByTagName('script');
for (let scr of scripts) {
var scriptContent = scr.innerText;
var newScript = document.createElement('script');
newScript.text = scriptContent;
scr.remove();
element.appendChild(newScript);
}
});
I have two functions injectChat and firstTimeTrigger in my content script. Both of them attach a script to the body of the DOM.
I need injectChat to run first and after it's fully complete then load firstTimeTrigger. firstTimeTrigger doesn't work unless injectChat run and is fully loaded.
These are the two functions -
function injectChat(){
console.log("Injecting Chat");
const script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.setAttribute("src", `${host}/api/botpress-platform-webchat/inject.js/`);
script.setAttribute("id", 'botpress-script');
document.body.appendChild(script);
script.addEventListener('load', function(){
const botpress_settings = `window.botpressWebChat.init({host: '${host}'})`;
const settings = document.createElement('script');
settings.setAttribute("id", "botpress-settings");
settings.innerHTML = botpress_settings;
document.body.appendChild(settings);
});
};
function firstTimeTrigger(){
console.log("First Time Trigger");
chrome.runtime.sendMessage({type: "isFirstTime"}, function(response) {
if(response == true){
const botpress_trigger_1 = "window.botpressWebChat.sendEvent({ type: 'show' })";
const botpress_trigger_2 = `window.botpressWebChat.sendEvent({ type: 'proactive-trigger', platform: 'web', text: '${JSON.stringify(config)}' })`;
const trigger = document.createElement('script');
trigger.innerHTML = botpress_trigger_1 + '\n' + botpress_trigger_2;
document.body.appendChild(trigger);
}
});
};
Currently, I've been doing it like this
injectChat();
setTimeout(function(){
firstTimeTrigger();
}, 3000);
But it's very unreliable because of the various page load times due to this being inside a content script.
How do I make this happen? Promises don't work in here.
You can pass firstTimeTrigger inside of injectChat as a parameter and call it at the end of the function, like this:
function injectChat(firstTimeTrigger) {
// logic of the injectChat function...
firstTimeTrigger();
}
Welcome to Javascript's callback hell :)
In order to run a function after the previous script has finished, you have to call it at the end of the script's load event. Remember to set up the load listener before actually adding the script element to the page. For example:
function injectChat(){
console.log('Injecting Chat');
const script = document.createElement('script');
script.setAttribute('type','text/javascript');
script.setAttribute('src', `${host}/api/botpress-platform-webchat/inject.js/`);
script.setAttribute('id', 'botpress-script');
script.addEventListener('load', injectSettings); //set up the load listener ...
document.body.appendChild(script); //...before adding the script element to the page
}
function injectSettings(){
console.log('Injecting settings');
const settings = document.createElement('script');
settings.setAttribute('id', 'botpress-settings');
settings.innerHTML = `window.botpressWebChat.init({host: '${host}'})`;
settings.addEventListener('load', firstTimeTrigger); //set up listener...
document.body.appendChild(settings); //...before injecting code
}
function firstTimeTrigger(){
console.log('First Time Trigger');
chrome.runtime.sendMessage({type: 'isFirstTime'}, function(response) {
if(response == true){
const trigger = document.createElement('script');
trigger.innerHTML = `
window.botpressWebChat.sendEvent({ type: 'show' });
window.botpressWebChat.sendEvent({ type: 'proactive-trigger', platform: 'web', text: ${JSON.stringify(config)} });
`;
document.body.appendChild(trigger);
}
});
}
injectChat();
I am using Google API, based on their link I have to put the following script in the HTML file
<script src="https://apis.google.com/js/client.js?onload=callback"></script>
The custom callback function is being loaded after the client.js is loaded successfully.
function callback() {
var ROOT = 'https://your_app_id.appspot.com/_ah/api';
gapi.client.load('your_api_name', 'v1', function() {
doSomethingAfterLoading();
}, ROOT);
}
I would like to
Separate HTML with JS file
I downloaded the client.js file and put it in my local repo. But for reducing web request I would like to concat the client.js with other JS file. But I have no idea how to load the content with the concatenated JS file with the callback is being called
Thanks in advance
If you are looking for javascript only solution:
var sScriptSrc = "https://apis.google.com/js/client.js?onload=callback"
loadScript(sScriptSrc);
function loadScript(sScriptSrc) {
var oHead = document.getElementsByTagName("HEAD")[0];
var oScript = document.createElement('script');
oScript.type = 'text/javascript';
oScript.src = sScriptSrc;
oHead.appendChild(oScript);
oScript.onload = loadedCallback();
}
function loadedCallback() {
alert("WoHooo I am loaded");
}
See it running here: JSFiddle
EDIT
Let me do some refining, if I understand correctly what you want to achieve:
I made a simple main html page:
<html>
<head>
<script src="client.js"></script>
</head>
<body>
PAGE BODY
</body>
</html>
Which is loading client.js
client.js contains:
// you can call this function with
// param1: src of the script to load
// param2: function name to be executed once the load is finished
function loadScript(sScriptSrc, loadedCallback) {
var oHead = document.getElementsByTagName("HEAD")[0];
var oScript = document.createElement('script');
oScript.type = 'text/javascript';
oScript.src = sScriptSrc;
oHead.appendChild(oScript);
oScript.onload = loadedCallback;
}
// let's load the Google API js and run function GoggleApiLoaded once it is done.
loadScript("https://apis.google.com/js/client.js", GoggleApiLoaded);
function GoggleApiLoaded() {
alert("WoHooo Google API js loaded");
}
Of course, instead of GoggleApiLoaded example function you could run a method which start the loading of different js and the callback of that one could load a next one and so on...
Is this what you were looking for?
jQuery has a nice method for this. https://api.jquery.com/jquery.getscript/
jQuery.getScript("https://apis.google.com/js/client.js", function() {
console.log("hello");
})
If you want to be compatible with IE, including IE 9, you can use this async JS file loader & callback:
function loadAsync(src, callback){
var script = document.createElement('script');
script.src = src;
script.type = 'text/javascript';
script.async = true;
if(callback != null){
if (script.readyState) { // IE, incl. IE9
script.onreadystatechange = function() {
if (script.readyState == "loaded" || script.readyState == "complete") {
script.onreadystatechange = null;
callback();
}
};
} else {
script.onload = function() { // Other browsers
callback();
};
}
}
a=document.getElementsByTagName('script')[0];
a.parentNode.insertBefore(script,a);
}
loadAsync("https://www.example.com/script.js", callbackFunction);
function callbackFunction() {
console.log('Callback function run');
}
I have the following signal r client code on my razor partial view
It is working fine in partial view. I want to move it to an external javascript file.
<script type="text/javascript">
$(function () {
debugger;
$.connection.hub.logging = true;
var proxy = $.connection.broadcastMessage;
proxy.client.receiveNotification = function (message, count) {
debugger;
$("#not_count").html(count);
$("#not_count").show();
};
$.connection.hub.start();
});
</script>
How can i move this to an external JS file?
Add new javascript file(eg. signalrStuff.js) to solution with your code:
$(function () { debugger; $.connection.hub.logging = true; var proxy = $.connection.broadcastMessage;
proxy.client.receiveNotification = function (message, count) {
debugger;
$("#not_count").html(count);
$("#not_count").show();
};
$.connection.hub.start();
});
Then reference the new script replacing the javascript in the partial view:
<script src="signalrStuff.js" type="text/javascript"></script>
Make sure to load the jQuery script first.
From below code I am trying to load javascript file TestJScript.js dynamically and after loading want to call javascript function LoadData() exist in that file. But I am getting error please check image.
Note: Error get only on IE-8.0.6001 update 0.
Please suggest me correction such that It will work from 6 to all version of IE.
Or any another solution.
if it require any windows updates. Please let me know.
Please don't suggest with JQUERY code
Javascript file code :
function LoadData() {
alert('ok');
}
Code:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script>
function LoadJSFile() {
var js = document.createElement("script")
js.setAttribute("type", "text/javascript")
js.setAttribute("src", "C:\\TestJScript.js")
document.getElementsByTagName("head")[0].appendChild(js)
//call below function exist in TestJScript.js file
LoadData();
}
</script>
</head>
<body onload="LoadJSFile();">
</body>
</html>
Error Image:
Try this http://dustindiaz.com/scriptjs.
Like this:
$script('yui-base.js', function() {
// do stuff with base...
$script(['yui-anim.js', 'yui-connect.js'], function() {
// do stuff with anim and connect...
});
$script('yui-drag.js', function() {
// do stuff with drag...
});
});
The error reports a problem in the javascript file that you're loading. So the problem lies not in how you dynamically load the javascript file, but in the javascript file itself.
It looks like there is a problem with the file once it has loaded. Are you sure there is no syntax error in the file itself.
Also, I would recommend you use a relative path to the javascript file instead of the absolute path.
EDIT:
Try this:
function LoadJSFile() {
var script = document.createElement('script');
script.src = "C:\\TestJScript.js";
script.onload = function () {
LoadData();
};
document.getElementsByTagName("head")[0].appendChild(script)
}
You could try the following:
<script>
function LoadJSFile(src, callback) {
var js = document.createElement('script');
js.src = src;
js.async = true;
js.onreadystatechange = js.onload = function() {
var state = js.readyState;
if (!callback.done && (!state || /loaded|complete/.test(state))) {
callback.done = true;
callback();
}
};
document.getElementsByTagName('head')[0].appendChild(js);
}
LoadJSFile('C:\\TestJScript.js', function() {
LoadData();
});
</script>
If you are using c# code then another solution to solve this script error is, invoke script through c# code.
Code:
/
/Assiging html value to control
webBrowser.DocumentText = "HTML content";
//Calling document load completed event
webBrowser.DocumentCompleted += webBrowser_DocumentCompleted;
void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
HtmlDocument htmlDocument = webBrowser.Document;
HtmlElement htmlElementHead = htmlDocument.GetElementsByTagName("head")[0];
HtmlElement HtmlElementScript = htmlDocument.CreateElement("script");
HtmlElementScript.SetAttribute("text", "C:\\TestJScript.js");
htmlElementHead.AppendChild(HtmlElementScript);
htmlDocument.InvokeScript("LoadData");
webBrowser.DocumentCompleted -= webBrowser_DocumentCompleted;
}