Call javascript functions of preloaded library from application - javascript

I have a WebView where a some page was already loaded webview.loadUrl(URL);
Also there is an amount of javascript functions like a:
function myFunction1() {// some code}
function myFunction2() {// some code}
function myFunction3() {// some code}
I need to preload all functions onto WebView (when page is already loaded) and then execute them one by one from application as webview.loadUrl("javascript: myFunction1()"); or webview.loadUrl("javascript: myFunction3()");
Is this possible to preload library instead of attaching js in the html code <script src="js/myLibrary.js"></script>?

It's not difficult. Look, at first you should use console.log. It might help you to understand what happening during the script execution:
console.log('This message should appear as a debug message in Logcat.');
put this into javascript and you will get this message in the LogCat:
11-15 12:31:10.652: I/Web Console(16214): This message should appear as a debug message in Logcat.:1
Then, your question: you must load your javascript functions in the row:
wv.loadUrl("javascript: var globalVar; function init() {globalVar=1;}; function global() {init(); var gl = '2'; console.log(globalVar);}");
, here we have init() function that initializes globalVar and global, that init all vars and print result in logcat!
After preloading you could execute any functions:
wv.loadUrl("javascript: global();");
and you will see in logcat "1"! And that all!

Related

Call a function from js file in Robot Framework

There is a possibility to execute javascript from file.
Execute JavaScript ${CURDIR}/js_to_execute.js
But how can I call a function by name from this file?
There is no way to call a function using Execute Javascript out of the box. But it's possible to pass a function name as an argument.
Execute Javascript ${CURDIR}/js/utils.js ARGUMENTS clickElement ${locator}
The content of utils.js file:
var utils = utils || {};
(function (arguments) {
utils.clickElement = function (locator) {
// implementation of the function
}
// this piece of code does the trick
// get function name from arguments and remove it from the list of arguments
var functionName = [].shift.call(arguments);
// call the function and pass the arguments
utils[functionName].apply(this, arguments);
})(arguments);
This will be little ugly but it works. You need to inject your whole Javascript code using Execute Javascript first and than you will be able to call the function you injected.
You can inject Javascript using below javascript code on google home page,
var s = document.createElement('script');
s.text = "document.getElementById('hplogo').addEventListener('click',function(){alert('Google');});";
document.getElementsByTagName('head')[0].appendChild(s);
In robotframework you can do the same using Execute Javascript
Open Browser https://www.google.com
Wait Until Page Contains Element id=hplogo
Execute Javascript var s = document.createElement('script');s.text = "document.body.addEventListener('click',function(){alert('Google')})";document.getElementsByTagName('head')[0].appendChild(s);
Sleep 2s #wait so that injected javascript gets evaluated
Execute Javascript document.getElementById('hplogo').click();
Sleep 10s #wait and click anywhere on body of the page to see the alert
Your s.text variable will have whole javascript code from js file in one line. Of course if your javascript is long than it will be dirty work but in one of the site I had to do this for pdf export and it is working fine.

Different output in 3 anonymous function in GAS

I have a question.
In the formal web page of google.script run, they saids that you can call "any server-side function" from client side using google.script.run.
In the below gs file, I defined function "hoge" using normal function expression.(the "this!" row)
If I execute this situation, output is randomly 1-4 numbers displayed on browser
By the way, I tried to change the define style of function "hoge". I created 3 pattern using anonymous function. (all are called from client side using "hoge(vv)")
var hoge = function hoge(x){return x;}; (both side using "hoge" keyword) → then this worked same as normal function definition style.
var hoge = function (x){return x;}; (only left using "hoge" keyword) → error
var hogeNot = function hoge(x){return x;}; (only right using "hoge" keyword) → error
Q. Why, "1" work well, but "2" is error.
Thank you.
// gs file
var x;
function doGet() {
return HtmlService.createTemplateFromFile("hello").evaluate(); // テンプレートオブジェクトの取得
}
function hoge(x){ // this!
return x;
}
// html file
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<p id="wi">hello</p>
<script>
function success(get){
document.getElementById("wi").insertAdjacentHTML("afterend","<p>" + get + "</p>");
}
for (var v=1; v <= 4; ++v){ // aaを4回呼ぶ
aa(v);
}
async function aa(vv){
await google.script.run.withSuccessHandler(success).hoge(vv);
}
</script>
</body>
</html>
Q. Why, "1" work well, but "2" is error.
For this question, how about this answer? Please think of this as just one of several possible answers.
Experiment:
At Google Apps Script, it seems that when the function can be recognized with the script editor and the function can be seen at this, the function can be directly run. For checking whether the function is included in this, the following script can be used.
Sample script:
function myFunction() {
for (var i in this) {
if (i == "hoge") {
Logger.log("%s, %s", i, typeof this[i])
}
}
}
About var hoge = function hoge(x){return x;};
In this case, the function of hoge can be seen at the script editor and this function can be directly run by the script editor. And also, above script returns hoge, function.
About var hoge = function (x){return x;};
In this case, the function of hoge cannot be seen at the script editor while above script returns hoge, function. And hoge cannot be directly run because this cannot be seen at the script editor.
When this function of hoge is run from other function, the script works.
About var hogeNot = function hoge(x){return x;};
In this case, the function of hogeNot cannot be seen at the script editor. But the function of hoge can be seen at the script editor. When the function of hoge is run by the script editor, an error like the function is not found occurs. At the above script, i == "hoge" is always false. But when i == "hogeNot" is used for the if statement, hogeNot, function is returned.
When this function of hogeNot is run from other function, the script works. But when this function of hoge is run from other function, an error occurs.
Result:
From above situations, it is considered that in order to run with google.script.run, it is required to be able to directly run the function at the script editor. I think that this might be the specification of Google side.
If I misunderstood your question and this was not the direction you want, I apologize.

How to invoke a function in javascript which has been declared in a html file

I have a html file with function displayJsonWithAjax and function displayOtherJsonWithAjax declared in a script-tag.
In another script-tag, I invoke those functions with this code when a select box change:
<script>
import fetchJson from 'some.module'
function displayJsonWithAjax() {
...
}
function displayOtherJsonWithAjax() {
...
}
</script>
<script>
$(document).ready(function () {
$('#selectBox').change(function () {
displayJsonWithAjax();
displayOtherJsonWithAjax();
}).change();
});
</script>
When debugging with a browser, I get the following error:
ReferenceError: displayJsonWithAjax is not defined
If I try to put all the functions in the same script tag, no code is automatically executed when the browser load the page... How do I accomplish to call these two functions?
import fetchJson from 'some.module'
Does that really work? Check you console.
If a script line fails, everything after that line won't be executed, so the script functions won't be declared and won't be usable elsewhere (and that will explain why "If I try to put all the functions in the same script tag, no code is automatically executed when the browser load the page": the script fails at line 1, and nothing else is executed).
test();
<script>function test(){
alert('hello');
}</script>

Invoking a p:remoteCommand via a JavaScript function passing a message local to that function to another function through the "oncomplete" handler

This question is purely based on this previously asked question (courtesy) but the question is messed up completely with the Java EE 7 WebSockets API attempting to show the actual practical approach/scenario which is now very unlikely to receive any answer based on <p:remoteCommand>.
Given below a snippet of JavaScript (this is only a test scenario).
<script type="text/javascript">
function test() {
var message = "myMessage";
window["myFunction"]();
// This is literally interpreted as a JavaScript function "myFunction()".
// "myFunction()" in turn is associated with a <p:remoteCommand>.
}
$(document).ready(test);
function notifyAll() {
alert("notifyAll() invoked.");
}
</script>
The test() function is invoked as soon as the page is loaded which causes the following <p:remoteCommand> to trigger which in turn invokes another JavaScript function, namely notifyAll(), using an oncomplete handler that simply alerts the said message.
<h:form>
<p:remoteCommand process="#this"
name="myFunction"
actionListener="#{bean.listener}"
oncomplete="notifyAll()"
ignoreAutoUpdate="true"/>
</h:form>
Assume that the local JavaScript variable message inside the test() function is assigned a JSON message which is asynchronously received through a WebSockets channel.
The notifyAll() function in turn has to send a notification message (myMessage local to the test() function - actually a JSON message which is received previously in the test() function) to another WebSockets channel which is completely ignored in this question for brevity.
Is it possible to pass the value of var message = "myMessage" local to the test() function to another function notifyAll() through the oncomplete handler of the given <p:remoteCommand>?
Declaring message as a global JavaScript variable may overwhelm the functionality of WebSockets as the message is received asynchronously i.e. a new message may be received while the processing of <p:remoteCommand> is still going on/awaiting to complete. Thus, declaring message as a global JavaScript variable is not an option.
.
I'm not seeing a better way than passing it as a parameter into the <p:remoteCommand> function and having the oncomplete function extract from it.
function test() {
var message = "myMessage";
myFunction([{name: "message", value: message}]);
}
function notifyAll(data) {
var message = decodeURIComponent(data.match(/&message=([^&]*)/)[1]);
// ...
}
<p:remoteCommand name="myFunction" ... oncomplete="notifyAll(this.data)" />
The data argument is already injected in the JS function scope by oncomplete and it represents the XHR query string. The regex extracts the parameter from it. Note that the regex assumes that the parameter is never in the beginning of the query string, which is true as it always starts with JSF/PF specific parameters, so it can be kept simple (JS regex is tricky with negative lookbehind).

What's the correct way to call JavaScript Function?

In the following code, the function writeMessage is called without parenthesis. However it works fine but Is it a correct way of function calling in javaScript or its better to use parenthesis along with writeMessage().
window.onload = writeMessage;
function writeMessage()
{
document.write("Hello World");
}
window.onload = writeMessage; is not a call - it's an assignment. You assign the writeMessage function as the onload field of the window object. The actual call is performed (internally) as window.onload() which is equivalent to writeMessage() in your case.
In the following code, the function writeMessage is called without parenthesis.
Actually, it isn't. The code
window.onload = writeMessage;
does not call the function. It assigns the function to the onload property of window. Part of the process of loading the page in browsers is to fire the function assigned to that property (if any) once the loading process is complete.
If you wrote
window.onload = writeMessage();
what you'd be doing is calling writeMessage and assigning the result of the call to window.onload, just like x = foo();.
Note that the code you've actually quoted, which executes a document.write when the page loads, will wipe out the page that just loaded and replace it with the text "Hello world", because when you call document.write after the page load is complete, it implies document.open, which clears the page. (Try it here; source code here.) In modern web pages and apps, you almost never use document.write, but in the rare cases where you do, it must be in code that runs as the page is being loaded (e.g., not later).
the () is used to EXECUTE the function
when you write
window.onload = writeMessage;
you actually set a delegate ( pointer to a function to be executed) for which - when the onload event will occour.
That's correct already.
You don't need parenthesis because you're just storing the function in window.onload, not calling it yourself.

Categories