This question already has an answer here:
How to call external javascript function from jslib plugin Unity webgl
(1 answer)
Closed 1 year ago.
I'm working on a program that will be used by different users and they will individually change the content of the js file to match with their expectation.
On the web I found many tutorials on how to call JS function in unity WEBGL but the Js file was built with the unity project.
I wanted a way to call a JS function which is hosted by the website (incluing it in the index.html of unity WEBGL but without building it).
What you are trying to do is possible. But it is a bit of a hack.
a quick google search turned up this article, from the unity documentation
But it might not be clear how to do it. so here is an example:
example:
Let us say you want to call a js function called foo().
.jslib
The first thing to do is create a file with a .jslib file extension in a folder named "Plugins".
this file tells unity that the function exists and is a just js
mergeInto(LibraryManager.library, {
foo_js: function () {
foo()
},
});
Here I declare a function called foo_js and tell unity that it exists.
This function consists of js, and in this case, all it does is call the js function foo().
Note: the name foo_js is arbitrary, and it can be called anything, Including just foo. but it is the same name as you will be using in c#. so I would recommend making it clear that it is not a native c# function
c#
now in a c# script, you start by declaring the function, which is done by adding
[DllImport("__Internal")]
private static extern void foo_js();
to a class and add
using System.Runtime.InteropServices;
to the top of the file
you can now call the function as foo_js() in your c# script
after built
after you have built the unity project, you need to add a js script. To "index.html" that has a function called foo() for unity to call.
And it should work, for more detail read the article from the beginning.
Edit:
Something I forgot to mention is that it is not going to work in the editor, as the js function is not defined, so you need to export the project and define the function on the website
it should be possible to detect that the game is running in the editor and use a default behaviour instead of the js function, but I am not sure how right now
Related
I am trying to use some functions from a code that has been obfuscated. So i have an html file that is calling a JS file thru the tag:
<script src="gwt_svg_viewer/gwt_svg_viewer.nocache.js"></script>
that file is defining a function called "onScriptdownloaded" which receives a string like this:
gwt_svg_viewer.onScriptDownloaded(["var $wnd = window.parent;function RE(){}"]);
So my question is how can i access to RE? in another JS file?
It seems that there was a kind of GWT code implemented, but i am not really familiar with that.
Variable names and functions in gwt will be obfuscated every time you compile your project, and variables and functions will be renamed in the process, in order to call a gwt code from javascript in a consistence manner you will need to use jsinterop to export java types. more information can be found in the gwt jsinterop documentation
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.
I am learning package:js and the dart file, which is a dart wrapper for chart.js.
I think this file is a bridge which connects dart and javascript. So, in this file, it must tell what javascript library this dart file is trying to connect. Am I right? But I did not find it.
What do the following statements mean? Do the following two statements tell what javascript library this dart file is trying to connect?
#JS('Chart')
library chart.js;
I have no idea how to map functions https://github.com/google/chartjs.dart/blob/master/lib/chartjs.dart to functions in https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.js. Anyone can give more tutorials?
You don't need to map to a JavaScript file, you just need to map to JS objects and functions.
You need to add a script tag to index.html that loads the JavaScript file you want to map to, this will make it available globally.
You then need to map
Dart functions to JavaScript functions, so when you call such a Dart function the call will actually be forwarded to the JavaScript function.
Dart classes so that you can use strongly typed Dart classes which will then be converted to and from JavaScript objects when you for example pass them as parameters to mapped functions or get them as return values from such function calls.
#JS('Chart')
library chart.js;
The name chart.js after library is arbitrary. The library directive just needs an unique name.
#JS('Chart') means that the loaded chart.js library is available in JavaScript land under window.Chart (window means global in JS land and is implicit).
#JS()
class Chart {
declares a Dart class Chart and #JS() maps it to a JS class with the same name in the library scope declared above. So the Dart class Chart will map to the JavaScript class window.Chart.Chart.
external factory Chart(
The external ... declarations inside the Dart Chart class map to the JS methods with the same name.
More details can be found in the README.md https://pub.dartlang.org/packages/js.
If you're still stuck you can ask more concrete questions. It's difficult to answer generic questions about how to use a package.
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)
Hy,
I'm working at a project that must call from C++ a custom function made in JavaScript. I'm able to run the function
The project should work only on Windows (actually it's a Windows service), so it's ok to use interfaces IWebBrowser2 and IHtmlDocument2
The function's signature is string function(string). I'm able to run the function in C++, based on this tutorial (I'm using IWebBrowser2 and IHtmlDocument2 interface), but I'm not able to get the output from that JS function back in C++.
Is there any method to retrieve the output from that JS function back in C++, using those interfaces? ( or maybe other)
Thank you,
I'll answer to my own question, if someone will have the same question:
Short answer is you can't obtain the output of javascript script using these interfaces. The IWebBrowser2 and IHtmlDocument are running in a context based on IE, so you can't obtain the output of running scripts.
The solutions for this problem are:
V8 or SpiderMonkey
Active Script Interfaces
If you plan to use V8 in your application, the basic example for calling a function is provided at Calling a v8 javascript function from c++ with an argument (But, be aware of the Dispose() function, which is wrongly placed)
If you plan to use Active Script Interfaces, the basic example is provided at Run JavaScript function from C++ without MFC . It's a useful example that shows how to run a JavaScript function.