Calling javascript from objective-c code - javascript

I found a lots of ways to call objective-c code from javascript, but I want to call the javascript code from objective-c. Last time I submitted a HTML FORM from objective-c, and now I wan't to call a javascript method. What do you think, is there any way to call it and get the response? I am interested in any solution, but I started to think and I think I need to send a html call or something like this, but I am not sure about this because the javascript is client side code, so maybe I need to process it from my objective-c code.
What do you think about this?

Are you looking for UIWebView's stringByEvaluatingJavaScriptFromString: method?
This lets you run JS code inside of the sandbox of a web view, from Objective-C.

Sounds like you are using a WebKit embedded in your app to link JavaScript to your "native" Obj-C code right?
If so you simply do this:
NSString* script = #"function __wrapper() { return (typeof webNodeEvent == \"function\") } __wrapper();";
id resultObj = [nodeScriptObject evaluateWebScript:script];
if ([resultObj boolValue]) { // its there, call it
[nodeScriptObject callWebScriptMethod:#"webNodeEvent" withArguments:[NSArray arrayWithObject:eventType]];
}
The nodeScriptObject is from the WebView and is just the JavaScript object.

Related

Call local function in Node.js <%%> tag in a document

I'm using Node.js and trying to use a local function of a document that needs to use a JSON I send it in res.render. Is there a way to do it?
Example of the way I was trying to use it:
<%local_variable = localFunction(sent_JSON)%>
Edit: sorry if this is a simple question, I'm a newbie when it comes to web development.
You can do:
res.render('yourpage', {
sent_JSON: yourJson,
});

write to Java console when my Javascript callback (made in Selenium) returns

I have learned how to create Javascript callback functions and I have a basic understanding of 'functional programming' since it seems easy enough. I am however, new to javascript and it's syntax and I can't find a good way to test said syntax while in my IntelliJ IDE.
What is it you're doing?
I'm creating a Selenium based tool to click on a webelement, wait for it to reload the page, become stale or wait for a timeout. The reason I'm doing this is to classify webelements into three categories: causes a page reload, becomes stale, doesn't change. To do this I've made a simple javascript script with the JavascriptExecutor that comes with Java. Most of my code is in java and that is the language I am proficient in. I want to learn how to use javascript with java to do the things I want with web pages.
Ok but what specifically is the problem?
I have a javascript callback function:
function test(callback) {callback();}
function Return() {SeleniumTest.isPageReloaded.JavascriptWorking}
window.addEventListener('onload', test(Return));
which is executed inside a Javascript Executor like so:
System.setProperty("webdriver.chrome.driver",
"C:\\chromedriver_win32\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
String script = "function test(callback) {callback();}" +
"function Return()" +
"{SeleniumTest.isPageReloaded.JavascriptWorking}" +
"window.addEventListener('onload', test(Return));";
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript(script);
Which is basically the Javascript script from before, executing as a String. As you can see I am attempting to call a java class. SeleniumTest is my package, isPageReloaded is the current class and JavascriptWorking is a static method within that class. That static method looks like this:
public static void JavascriptWorking(){
System.out.println("Javascript ran here");
}
Its meant to be a simple way to get something from the javascript to my java code. The reason I tried it this way is because I read this:
https://documentation.progress.com/output/ua/OpenEdge_latest/index.html#page/bpm-appdev/invoking-java-methods-in-javascript.html
But then I realized that it wouldn't work and I dug deeper. I read that Javascript and Java are seperated by server and client and I gained some insight from this question:
calling java methods in javascript code
However I'm not 100% sure this is accurate to my case since the Javascript I'm executing isn't coming from the webpage I'm testing, Rather I made it myself inside the java code as a String. Additionally I'm still highly confused on if the answer to that question actually applies to me. There is only one and it basically just says, 'install some stuff because java is clientside and javascript is serverside'. I (kindof) understand what those terms mean but I'm not sure that the javascript I made in my class would be considered 'server-side' in fact it would seem to not be that way. What I need is clarification on A: is the javascript I'm running/creating in my java code actually serverside?
B: if yes then can someone give me a basic rundown on how I would go about calling java code from the server? does this require permissions? I assume I have to communicate with said server so does that mean I use GET and POSt requests?
C: If the Javascript Isn't server side then it must be clientside and I should be able to call it pretty easily right? How do I do this?
Show us what exactly you want
I want to be able to run:
System.setProperty("webdriver.chrome.driver",
"C:\\chromedriver_win32\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
String script = "function test(callback) {callback();}" +
"function Return()" +
"{//insert callback code here}" +
"window.addEventListener('onload', test(Return));";
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript(script);
and get either a static java method ran, something printed to console, or some other means that links the javascript code to the javacode. So for example if I inserted the correct code to call my static method:
SeleniumTest.IsPageReloaded.JavascriptWorking
(which again looks like):
public static void JavascriptWorking(){
System.out.println("Javascript ran here");
}
Then I'd want to see "Javascript ran here" on my java console. The driver being used is interchangebale, I just used chrome first because its fast. All that this needs is an enclosing main class and It ((should)) be runnable but no promises.
The purpose is to get something in java that I can then use as a flag to know that my asynchronous javascript is done in java and I can continue on with program execution. I can get the async javascript part and I understand it, I just need a link back to my java code.
Possible Solutions
I've been told that the common way to provide a flag for your java code is to create a certain webelement on the page with javascript and test for it in java (hence the link). I don't feel like adding to the webpages I test because I want to test them without actually editing/changing them. I'm generally open to other simple solutions but the biggest thing I need is clarification on the whole clientside serverside issue because its specific to my setup (Selenium java -> javascript -> java) where most questions only cover (javascript -> java) or vice versa.
The link you mentioned about JS invoking Java is for a specific application, that is meant to do that. Not saying it is impossible (I wrote FF plugins based on similar principle), but it is not applicable in this case. It also requires special application support (by default Javascript executed in browser is heavily sandboxed - it can't access anything out of its own scope. Invoking other apps on its own is a big no.).
The scripts you are injecting are always client side, they are executed only in the browser, that is isolated from the java code itself. With that said nothing is impossible.
Would like to mention two interesting features of the Selenium library that can come handy for you.
You mention a magic term many times "async Javascript execution" - and as I can see you are implementing your own version of executeAsyncScript. Webdriver does provide this method out of the box, pretty much for the purpose you want to use it with.
When you use executeScript, it will return pretty much immediately once it finished - in your case it will just inject your listener with your code, and then it returns. Using executeAsyncScript you can get a callback - just what you are doing. When calling executeAsyncScript, a default callback method is added to your code as the last argument, that needs to be called by your JS code for the method to return.
A simple example:
String script = "var callback = arguments[arguments.length - 1];" + //the last argument is the callback function
"var classToCall = 'SeleniumTest.IsPageReloaded';" + //the classname you want to return to call from Java in case of success)
"window.addEventListener('onload', callback(classToCall));";
//you can give any supported return value to the callback function. Here I assume that you want to call a static method. This is the class name that can be used later.
try {
JavascriptExecutor js = (JavascriptExecutor)driver;
//classToCall has the value we passed to the callback function
String classToCall = js.executeAsyncScript(script);
} catch (ScriptTimeoutException e) {
System.err.println("Uhhh... this failed I guess");
e.printStackTrace();
}
The executeAsyncScript does not return until the callback is called - to avoid infinite hangs, you can set the WebDriver.Timeouts.setScriptTimeout property to control this. If the script takes longer, JavascriptExecutor will throw an exception. Once returned, you can instantiate the returned class, and print like
Class clazz = Class.forName(classToCall); //it is only necessary if the classname is dynamic. If it is the same always, you can just go ahead with that.
((IsPageReloaded)clazz.newInstance()).JavascriptWorking();
Of course you can return a more complex datastructure also from the JS where you specify the method name also, but using reflection is really offtopic here.
Take a look at EventFiringWebdriver. This is a useful class that makes use of WebDriverEventListener to create custom Webdriver wrappers, with hooks on many events, allowing you to execute custom code before/after clicking, before/after pageload... and beside some others more importantly before/after executing javascript in the webdriver. You could leverage this to always call the same code around javascript execution - just create your own WebDriverEventListener.
You can find more info on the js executor here, and on WebDriverEventListener here.

JSTL. How to call a function from <script> in c:set jstl tag?

I just need something like this:
<c:set var="cls" value="${myFunc(param)}"/>
.....
<script>
function myFunc(param) {
if(param == true) {
return "aaa";
} else {
return "bbb";
}
}
</script>
When I try it then get this error:
org.apache.jasper.el.JspELException: /script.jsp(22,12) '${myFunc()}'
Function [:myFunc] not found
Is what you are trying to do, possible??
Answer to this in one word would be NO...
Let's dive into the reason, hint is here.. JSTL (JavaServer Pages Standard Tag Library).. see the word 'Server'. Yes.
The JSP pages gets compiled as like your Java files. Once the compilation is successful, it can be then sent as a response and then browser renders this response and displays the page.
JavaScript : is a client side programming language which means codes in JavaScript are run by the browser not by the server.
When compiler compiles Jsp file, it only plays around the Scriptlet and JSTL part, and rest of the code (I mean the rest of HTML, CSS and JS code) is just a piece of string.
Now, imagine a situation in your code, while Java compiler is trying to compile it finds that myFunc must be a method but where to look for?
It cannot see it as a javascript function, because javascript runs only in browser not in server side. And hence, you are not able to set the value of cls variable, because myFunc is unknown for Java.
Hope this helps you understand JSP and Server Side working.
Keeping above things in mind, try some better approach to solve your problem.
Happy Coding :)

Calling javascript functions from android activity

Is it possible to call a javascript function from java code in Android. Consider the javascript function in a .js file.
function calcSum(firstNumber, secondNumber){
return (firstNumber+secondNumber);
}
I want to call this function from my java code and show the result in TextView. I don't want to use WebView.
If you dont want to use web view you will need a nother kind of javascript interpreter. For example Rhino:
http://www.mozilla.org/rhino
http://en.wikipedia.org/wiki/Rhino_(JavaScript_engine)

Calling a function in a JavaScript file with Selenium IDE

So, I'm running these Selenium IDE tests against a site I'm working on. Everything about the tests themselves is running fine, except I would like to do a bit of clean-up once I'm done. In my MVC3 Razor based site, I have a JavaScript file with a function that gets a JsonResult from a Controller of mine. That Controller handles the database clean-up that Selenium IDE otherwise couldn't handle.
However, I'm having a hard time finding any sort of documentation on how to do this. I know I can do JavaScript{ myJavascriptGoesHere } as one of the Values for a line in the test, but I can't seem to find a way to tell it to go find my clean-up function.
Is it even possible for Selenium IDE to do this sort of thing?
If it comes down to it, I can just make a separate View to handle the clean-up, but I'd really like to avoid that if possible.
Thanks!
If you want to execute your own JavaScript function that exists in your test page from Selenium IDE, you need to make sure you access it via the window object. If you look at the reference for storeEval for instance, it says:
Note that, by default, the snippet will run in the context of the
"selenium" object itself, so this will refer to the Selenium object.
Use window to refer to the window of your application, e.g.
window.document.getElementById('foo')
So if you have your own function e.g. myFunc(). You need to refer to it as window.myFunc().
This can be very handy for exercising client-side validation without actually submitting the form, e.g. if you want to test a variety of invalid and valid form field values.
If you use runScript, that should already run in the window's context.
This works for me.
IJavaScriptExecutor js = driver as IJavaScriptExecutor;
string title = (string)js.ExecuteScript("myJavascriptGoesHere");
Make sure your javascript works first before using it here!
Actually to access your page javascript space, you need to get the real window of your page : this.browserbot.getUserWindow()
See this statement to get the jQuery entry point in your page (if it has jQuery of course ^^ )
https://stackoverflow.com/a/54887281/2143734

Categories

Resources