Our teams is currently under consideration of which JavaScript Engine Bridge to use. We are choosing between LiquidCore and J2V8.
My question is concerning j2v8. Supposedly, I have to create several instances of some java class in JavaScript, how can one achieve this in j2v8 using standard instantiation annotation (new ClassName())? In liquidcore you can bind some class, that extends JSFuction, with super constructor:
JSFunction(JSContext ctx, final String methodName, final Class<?extends JSObject> instanceClass)
and register property with desired class name like this:
jsBaseContext.getJsContext().property("WebSocket", this);
and then on calling:
var x = new WebSocket();
java method methodName will fire, where we'll get new instanceClass as JSValue object as parameter, already binded and ready to use in javascript.
Since no one is going to discuss this topic, i'll answer myself.
This feature is not currently considered to be added in official J2V8 release, however there is a branch on Mizumi's pull request. So, have a look, if you've faced similar issues.
Related
The Problem
I am trying to feed a Java object into a script that would normally operate on the Document Object Model (DOM) of a web page. For the most part this functions as intended. However I have encountered a problem when dealing with attributes/properties of the DOM elements.
A particular property chain of interest is somediv.firstChild.href. What I can't figure out is how to get the firstChild property value dynamically. The simplest way I can think of at the moment is to use source.replaceAll("firstChild", "firstChild()"); to force the firstChild property to invoke the function firstChild() instead. However this will eventually open up a new can of worms.
The Question
How do I define an object that can be passed to a javascript function that can be operated on via the DOM?
Background
Learnings from C#
Before diving into Java I had learnt C#. In C# the concept of setters and getters is quite prevalent. If this interface method were available in Java my problem would be solved.
public string firstChild {
get { return this.getFirstChild(); }
set { this.setFirstChild(value); }
}
Current Implementation
The script is currently invoked by wrapping it in a function where I can pass in the window and document Java objects into the function's workspace.
document is a special top-level version of SpoofedDomElement (that extends it) but is functionally identical to the sample shown below. window is another object with minimal functions that handle event listeners.
Javascript (snippet) to operate on DOM
var somediv = document.createElement('div');
somediv.style.display = "block"
somediv.innerHTML="<a href='/mywork/server/test.html'>The Test Server Homepage</a>";
var linkvalue = somediv.firstChild.href;
This snippet is stored as the string theOriginalSource and used in the next section.
Java code to evaluate Javascript
String wrappedSource = "var scriptToInvoke = function(window, document){"
+ "\n" + theOriginalSource // from above
+ "\n};"
Object result = invocable.invokeFunction("scriptToInvoke", window, document);
This snippet wraps the javascript snippet so that I can pass in objects to use as window and document.
Java classes that spoof DOM elements
public class SpoofedDomElement {
public SpoofedDomElement firstChild;
public String id;
public String innerHtml;
public String href;
public SpoofedStyleProperties style = new SpoofedStyleProperties();
public String tagname;
...
}
public class SpoofedStyleProperties {
public String background = "transparent none repeat scroll 0% 0% auto padding-box border-box";
public String color = null;
public String display = "inline";
}
The above classes handle irrelevant parts of the code just fine (such as the assignment somediv.style.display = "block"). But it starts to fall apart when handling the values of firstChild or innerHtml when either value is changed.
Past Work
N.B. I include this section in all my questions to document what I have tried for future SO users who get here by Google. This might help someone reach a solution by aiding brainstorming.
Attempted Solutions
I have attempted to use a framework (HtmlUnit) to evaluate the Javascript. But I couldn't control which Javascript snippets were executed.
Potential Solutions
The following are questions that I am currently researching to find a solution. If I find anything I will report back.
Is there a way to emulate C# getter/setter behaviour in Java?
Can Javascript evaluate firstChild as a function?
Is there a way to create a wrapper within Javascript with getter/setters that can invoke my Java class's functions?
Is there an Apache Commons library for Nashorn (or similar) that isn't as heavy as the complete simulation frameworks (such as Selenium)?
It appears that you're trying to implement friendly access of script objects from Java code as well as trying to provide script-friendly API on top of java library/libraries.
For the first part [ script object access from Java ]
Apart from javax.script.Invocable interface, you can use JSObject. Nashorn exposes script objects as instances of jdk.nashorn.api.scripting.JSObject/.ScriptObjectMirror
https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/ScriptObjectMirror.html
For the second part [ friendlier access of Java objects from scripts ]
You can write script friendly wrappers in script itself using "JSAdapter".
Doc and Example:
https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-JSAdapterconstructor
If you'd prefer to do in Java, you can implement your own jdk.nashorn.api.scripting.JSObject/.AbstractJSObject.
Doc and Example:
https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-jsobject
Other nashorn specific script extensions may also be used to trap unknown property/method access in per object basis:
noSuchProperty hook in any script object:
https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-noSuchProperty
noSuchMethod hook in any script object:
https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-noSuchMethod
Object.bindProperties:
There script API extension can be used to bind properties of one object to another - the source object could be a Java object as well.
https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-Object.bindProperties
With jdk9, there is more flexible inter-language linking possible with Dynalink API [ http://openjdk.java.net/jeps/276 ]
See also:
https://blogs.oracle.com/sundararajan/entry/dynamic_linker_api_for_the
https://blogs.oracle.com/sundararajan/entry/writing_pluggable_dynalink_linker_and
https://blogs.oracle.com/sundararajan/entry/nashorn_javascript_access_to_python
There are dynalink samples "samples/dynalink" directory of Nashorn OpenJDK repository:
http://hg.openjdk.java.net/jdk9/dev/nashorn/file/4a6ee1185fc8/samples/dynalink
I am wondering (perhaps more so from a UML point of view) how others have managed to document JavaScript objects successfully.
JavaScript can be expressed as OOP but in addition to these objects, files may also contain 'lose standing' scripts, which belongs to the file itself - not the object you defined.
Would you document the file itself as a class, and the classes it contain as nested classes?
Someone adapted UML for web artifact, its called the "WAE" extension of UML.
If you work with node.js, i created a module that generate class diagram for javascript/node/html/css. Its called wavi. For javascript, function,variable are automatically recognized. You can use it for documenting your application.
https://www.npmjs.org/package/wavi
No, it wouldn't make sense to document a JavaScript file as a class (with inner classes), but the "classes" it contains may be documented with a UML class diagram. However, since there is no explicit class concept in JavaScript, people use different code patterns for defining a "class". The most commonly used code pattern is the constructor-based definition of classes as proposed on the Mozilla website. In this approach, the constructor function (say, C) represents the class. It defines a number of properties (using this) and a number of methods/functions (using C.prototype). Then, in a UML class diagram, these properties and methods can be described in the form of a class rectangle.
If you want to document your javascript objects, you can even use a MVC pattern for javascript projects. I would personally try to avoid using innerclasses and use proper relationships between classes. If you mean with innerclasses; putting multiple classes sepperated in the same js file, then; yes that's a valid option. Javascript doesn't care in which file a class is, it only thinks about the classes (unlike Java if I'm correct).
Example I wrote 8 years ago for school showing the Control class:
function Control()
{
var myView = new View(respondOnChoice);
var myMathTest = new MathTest();
var myExercise = new Exercise();
function respondOnMathTestChoice()
{
myView.emptyMainDiv();
myView.showNameAndClassChoice();
}
}
Start.js (to initiate the control):
if (window.attachEvent) //IE
{
window.attachEvent("onload", initApp);
}
if (window.addEventListener)//Firefox
{
window.addEventListener("load", initApp,false);
}
function initGame()
{
var myControl = new Control();
}
In my opinion, this is the best way to use OOP in javascript. If you program properly, you won't have to mind about anything to do with innerclasses, just relationships between classes.
I've recently been working on a nice little JavaScript game engine that works a lot like Game Maker, but lets people create basic JavaScript games within a browser. Every instance of every object will have it's own preset methods, which the runner will iterate through and execute. I'm trying to find a way to let the user / creator dynamically edit any of the methods source code. When I say 'preset methods', I mean blank methods stored under specific preset names within the objects / object instances. Here's a basic example:
var newObject = object_add("object_name"); // Adds a new object 'blueprint' and returns the reference.
The function object_add(); creates a JavaScript object, and adds a number of preset methods to it, such as:
create
destroy
step
draw
.. and many more
Each of these methods will have no code in them to start with. I need to let the creator dynamically change any of the methods source code. I could simply overwrite the variable that points towards the method, with a new method, but how can you set method's source code using a string?
I know that something like:
newObject.create = function(){textbox.innerHTML};
definitely wouldn't work. Any ideas?
Many thanks,
Dan.
Looks like you want to use eval function, but it's generally a bad idea.
The answer was found at: Creating functions dynamically in JS
Here's the answer (copied from the other page).
Well, you could use Function, like in this example:
var f = new Function('name', 'return alert("hello, " + name + "!");');
f('erick');
//This way you're defining a new function with arguments and body and assigning it to a variable f. You could use a hashset and store many functions:
var fs = [];
var fs['f1'] = new Function('name', 'return alert("hello, " + name + "!");');
fs['f1']('erick');
//Loading xml depends if it is running on browser or server.
Thanks, #CBroe https://stackoverflow.com/users/1427878/cbroe
I've got this page I'm doing some tests in Javascript and jQuery: JS Tests
I've got a few questions on how to create, not sure if this is right term, but compound controls via Javascript. In something like Flash, you'd create the Object class, have the getters and setters, draw your images, etc. In JS, it seems to be a very different thought process. My main question is How do you create multiple elements with getters and setters to be rendered, filtered, and interacted with in Javascript?
The main code regarding this example sits with:
var html = (function(){
// var FRAG = $(document.createDocumentFragment());
htmlBox = $(document.createElement("div"));
var eTitle = $(document.createElement("h4"));
var ePrice = $(document.createElement("p"));
// set class first
htmlBox.addClass("box")
htmlBox.css({
backgroundColor : color
})
// set text values
eTitle.text(title);
ePrice.text("$" + price);
htmlBox.append(eTitle)
htmlBox.append(ePrice)
return htmlBox;
})();
... inside the Box() class. If someone could take a look at the source and let me know what isn't quite right, that'd be great.
EDIT
Here's the final result for this example. Some logistics to work out, but what I'm after.
http://geerswitch.in/tests/obj/
As for the jQuery creating nodes, the built in JS version works fine for this, and some research on Google shows that the non-jquery way is faster in most cases anyway (and looks worse, imo)
You're doing it almost right. You've created a Box class to represent your higher-order UI element, you're instantiating it for each element, and your main program is manipulating the elements through its interface. The only thing you're missing is the split between the public interface and the private implementation. There's nothing to prevent me from doing myBox.price += 10 right now, even though the Box interface clearly implies that price should be set at construction and never modified.
JavaScript doesn't have visibility modifiers like "private" and "public", but you can create the same effect yourself. Check out Douglas Crockford's explanation for the details. Crockford is an opinionated genius when it comes to JavaScript, and he's the brains behind JSLint and JSON.
So I asked an earlier question (Original Question). I got a great answer that did exactly what I wanted. However, since I am new to Javascript/Dojo, I wasn't able to fully understand it, and neither was the answerer of the question.
My question is: How does the following code work?
dndController: function(arg, params){
return new dijit.tree.dndSource(
arg, // don't mess up with the first parameter
dojo.mixin({}, params, {copyOnly:true}))
//create a copy of the params object, but set copyOnly to true
}
So the part bugging me the most is the "args" and "params" parameters. I don't understand where they come from and what they mean or represent. (If there needs to be more context to the code, I can edit the question later, so just post it in the comments). Also, why couldn't I just use the new dijit.tree.dndSource directly and why did I need to use the function to return it?
Thanks
Take a look at dijit/Tree.js in the dojo source.
in Tree.js, inside the postCreate function (which is used by any widget as a part of the dijit lifecycle):
if(this.dndController){
if(dojo.isString(this.dndController)){
this.dndController = dojo.getObject(this.dndController);
}
var params={};
for(var i=0; i<this.dndParams.length;i++){
if(this[this.dndParams[i]]){
params[this.dndParams[i]] = this[this.dndParams[i]];
}
}
this.dndController = new this.dndController(this, params);
}
You'll see a section which checks what the dndController property is. If it is a string it sets the dndController attribute to the function that creates the class that the string describes (this is what dojo.getObject(string) is doing).
For example if this.dndController was the string "my.special.dnd.controlller", it would return the function that, when called instantiates a new instance of my.special.dnd.controller.
It then copies some parameters into an object, followed by executing the function that was either:
(1) looked up via dojo.getObject
(2) uses the custom function you passed in.
I would assume the maintainer of this widget does it this way as some people only need to specify a specific class to use as the dnd controller, whereas others need to do some something more custom based on what parameters the Tree was passed.