On 2012.07.16. 17:20, Robert Hanson wrote:
Leap-frogging here....


On Mon, Jul 16, 2012 at 6:31 AM, Gusts Kaksis <gusts.kaksis@gmail.com> wrote:
>
> We need this class to overcome stupid "functionName"-as-a-string passed to Java Applet
>
> Note that JmolApi does access the function directly, but I don't know
> that there is an alternative to sending  a String to the Java applet.
> This function name is (or can be) set by Jmol scripting, so it starts
> as a String and is saved as a String. Within Java we just access the
> method with that name. Are you thinking there's a way around that?
There isn't. Saddly this is the way web and plugins work together, even
in ActionScript you have to call ExternalInterface.call("functionName",
someParam); Which is kinda stupid, that you cannot send a
pointer/reference to a real function. But I think it's because of the
way JavaScript is - it's an interpreted scripting language, so there are
no real function hanging somewhere in RAM, that's why you have to use
string name from Java side, and the browser looks it up in some kind of
hash table of functions.


Java can save the JSObject for the function. We could do that; we just don't. I don't think once the function is parsed it is in string form anymore. Evidence of this is that at least with MSIE the function string version is different from what the user typed. Like the way tags are not string anymore after HTML is parsed. They are part of the DOM at that point.
Then a static callback wrapper class will be necessary, or maybe there is a possibility to introduce a new method in applets public interface where I could add private methods, not just a string name. Just like a script() method. Something like addCallback(callbackName, callbackFunctionPtr). Because private methods (functions within functions in JavaScript) are not accessible globally. thus they can not be set with "set callbackName functionName".
What is the possible output from these callbacks (measure, hover, pick),
like what arguments can I expect and what do they mean?

see http://jmol.sourceforge.net/jslibrary/#jmolSetCallback
I'm more intereseted weather the syntax of hover's 1st parameter will allways be "atom atmo_num x y z"?
And what about those parameters of measurement?
"Angle H #2 - C #1 - H #3 : 109.477165", 3, "measurePicked", 109.47716522216797
1st - a string representation of a mesurement
2nd - ?
3rd - action name?
4th - the angle as a float, right?

I think it would be easier for a developer if thease values would be presented in a nice and documented structure, so that they can create whatever output they wish from it.

 
I just thought
that preparing a consequent data object for these callbacks are more
useful for a developer then a raw string. For example, hover and pick
methods send really simple data, that can be prepared as I've already
done.

But the format of those strings is totally programmable by the page developer. You are just using the default settings, so that amounts to a hack. Fine for a demo; not appropriate for a general solution.
Aah, so you can script the output of these callbacks through Jmol's scripting?
 
The measurement is a little bit tougher, and there is really no
documentation on your site about all the parameters, so I was doing a
wild guess there. :)


yes, that's a bit hard to find: http://jmol.sourceforge.net/jslibrary/#jmolSetCallback
Well the question is about all the parameters, this documentation just covers the string output, but as I mentioned before, there are more arguments coming out from Jmol.
 
I know that you can call "set callbackName functionName", but if we're
doing it jQuery way, then events are more versatile than callbacks, as
you can bind multiple functions to the same event, which is not possible
with callbacks. At least I think it isn't, what's happening on Java side
there - does set callbackName overwrite previous callback function name?

Yes, it sets the callback function name to a new function.
So for jQuery user's it would be more convenient to use events, I just need to think of a hack to catch a moment when someone binds a listener to some of my custom events (like, hover or pick)
 
> It's important to have a random number indicated as the sync id. Don't
> just assign 0. See JmolApi for several more defaults. Be sure to make
> it clear how one overrides these.
Random or unique? Because, if it's 0, a real number will be assigned in
_appletBuild method which is an applet counter (it increments every time
a new applet instance is created in page), that should be unique enough.
Or have I forgotten about some inter-window (or even inter-browser)
communication?

These need to be unique across an entire session, not just a page. Someone could easily have multiple pages with Jmol applets, and for rapid inter-applet communication we need to register the applets. Thus they need unique names. 10 digits of randomness is sufficient, though not perfect.
Ok, noted, I'll implement Jmol's solution then.

> Well, if we can avoid creating multiple objects it would be better.
> How many primary objects are you creating here -- only
> JmolCallbackWrapper? Can that all be within "Jmol." ? Also, you don't
> necessarily do yourself a favor to generate unnecessary callbacks in
> Jmol. You are loading it up with callbacks when you don't know that
> the user is interested. That's just wasted communication.

It's more like a private class intended to intercept callbacks and
translate into events. It should never be used as a real class. And it's
static, so there is only one instance. As the Jmol itself sends an
ID/name of applets <object> tag, this class forwards all the calls to
the appropriate jQuery wrapper.


Take a look at what is done in JmolApplet.js. There is no issue of ID there. The applet is sent the correct function name up front for the callback, and that always goes to the proper _Applet straight away. No need for checking later. See if you can do this with out the _applets associative array.
Well I had problems there. Even after I received a message from readyCallback, the applets object still does not have a script() methods exported to JavaScript. That's why I'm storing the internal object received by readyCallback into _applets array.

 
As for communication, I agree, I should strip it down even more and use
"set callbackName functioName", only for now I can not intercept when
user calls jQuery's bind() method. I'll probably have to work on some
cheat here, like wrapping jQuery itself.

ouch.
Yep :)
 
>
>                                               // Funny thing about Jmol Java applet :)
>                                               // Hacking is the way to the victory
>                                               _applets[id] = args[3];
>
> Agreed. I think that one got missed in the  documentation.
Thank god, we cleared up this one, so it's safe to use that 4th argument
as the real applet's interface.

It's just very new. Came  with JmolApplet.js and Jmol 12.3.
Well then maybe I'll still stick with this, because, as I mentioned previously - I had a lot of problems, event after receiving a message to readyCallback - "HTMLObject does not have a method named script()", but not every time, it was like 2 times it worked, and then some 4 times it didn't (just simply refreshing a page).
 
>
> On the ready signal, you need to send all cached scripts.
>
>               _appletScript = function(id, command){
>                       var applet = _appletFind(id);
>
> _appletFind is obsolete. The  idea is to always pass the object to the
> function so that there is no finding anything. This was a legacy
> default that has caused all sorts of grief and it is good to be done
> with it.
Umm, I'm not using any of Jmol.js methods, it's only my jQuery Jmol
plugin (as I said, it's completely standalone for now), without any
dependencies to Jmol.js or JmolApi.js at all. And _appletFind is my
private method to get an applet's interface from internal cache (array)
named _applets;

RIght. That's what I'm trying to avoid if possible. Can you set up a simple page with two applets and show us how we can query them in different ways and get different callbacks? For example, get the state from one and pass it to the other?
OK, I'll try it out tomorrow.
 
That's it, but we can turn it into cached script if you say, that it's
the new way of Jmol.
> Most importantly, you need to make sure you never access the applet
> except after its ready callback. no scripts sent; no queries made.
OK. I still need to work on callback setters when needed, and the only
callback that will be left at initialization time is ready callback.

It's the ready callback that probably should initialize all the other callbacks. Otherwise your buttons will be active prior to the applet being ready, and a press of a button could crash the browser. (really)
OK. Even better solution would be, if I could somehow catch this event binding in jQuery, but for now it seems won't be able to do that in a legal manner. :)
 
> Overall, I think it has great potential.
Thanks :)
>
> Q: Will changes to jQuery have to be made to ensure the applet never
> experiences CSS style.display = "none"?
I think this is close to impossible, as it can happen any way from a
different script, written by user.

It must not happen, and it must not be possible to do this inadvertently -- specifically because jQuery might happen to do this in some context the user is not aware of. This is absolutely necessary. I would say this is a major concern. Unfortunately, for many browsers it does not matter, so someone not testing on MSIE will think their page works great, and if they have, say, used jQuery extensively and built their page around some cool jQuery functionality such as tabbed divs, they could be in for a huge surprise way late in the game. So, if nothing else, we need to identify exactly when jQuery would do that and have very visible information for users to NOT use that particular functionality.

Just a quick look at an old jQuery code I have on hand:

                // Go through and make them visible, but in reverse
                // (It would be better if we knew the exact display type that they had)
                for ( var i = 0; i < stack.length; i++ )
                    if ( color( stack[ i ] ) ) {
                        swap[ i ] = stack[ i ].style.display;
                        stack[ i ].style.display = "block";
                    }

                // Since we flip the display style, we have to handle that
                // one special, otherwise get the value
                ret = name == "display" && swap[ stack.length - 1 ] != null ?
                    "none" :
                    ( getComputedStyle && getComputedStyle.getPropertyValue( name ) ) || "";

                // Finally, revert the display styles back
                for ( var i = 0; i < swap.length; i++ )
                    if ( swap[ i ] != null )
                        stack[ i ].style.display = swap[ i ];


Death to the applet in MSIE.

Animation, for example, would probably be in this category.
Ouch. I think I already saw what happens next ... I was testing a fast reset of Jmol - like remove it from DOM and put it back in - IE went dead. Yep, now I get it. One more thing on a todo list. I should start to write it down somewhere in github probably.
-- 
Gusts Kaksis