So I wrote this plugin for Jmol, that replaces default JavaScript library and makes it work jQuery way. You can see more here.
Now I’m struggling with some new ideas, so I’ll use my blog to lay out some problems and possible solutions.
Problems with chaining and return values
Jmol, has some methods like getPropertyAsJSON, that must return a value. jQuery on the other hand was not quite built with this in mind. So if I do not want to break method chaining – I should probably use callbacks that receive resulting values, like this:
$('#jmol').jmol('getprop', 'appletInfo', function(result){ // something happens here });
This, on the other hand, creates some problems with readability of the code. Other approach might be to restrict jmol() to receive max. 2 arguments, like this:
$('#jmol').jmol('getprop', { type : 'appletInfo', result : function(result){ // something } });
This would look more like the usual .ajax() call. Also, to keep in mind, getPropertyAsJSON can take two arguments: type and some sub-parameter. So this second approach would be more readable (easier to write) with changing number of arguments.
Options vs. Internal commands
Next problem (or more of a thought about) is about updating options and some internal commands, like ‘destroy’ (jQuery UI way), that would get passed as a string to .jmol().
There are only three internal commands (for now):
- hide – hide Jmol applet, because we can not use jQuery’s hide() as Java on Internet Explorer would crash with display:none, so instead we set it to 2×2 px
- show – restore Jmol applet into the view
- destroy – completely destroy Jmol plugin (same as you do with any jQuery UI widget or TinyMCE)
I’m already thinking to introduce a couple of new commands:
- getprop – getPropertyAsJSON + JSONDecode
- script – with script source as a second argument and get rid of jQuery method .jmolscript()
So what about options. I might go jQuery UI way with new command “option” which is followed by 2 arguments: key, value or by one argument (an object of key:value pairs)
Sounds fair enough, but what about those other methods, that are exposed through external interface of Jmol applet (scriptWait, syncScript, etc.)? Should I create a sepparate internal command for each of them?
What options?
As the list of Jmol commands is just HUGE, I cannot come up with some logical division, what should be brought out to jQuery plugin, and what should be left with script() method? Width, height, useSigned – they’re really only for initialization, but what about onEcho callback? onReady callback – yes, we really need it (and onDestroy too) to catch the first event of readiness.
Events or callbacks?
I’m still having second thoughts about event approach. As Robert Hanson pointed out in mailing lists, it’s not wise to add callbacks on something that’s not listened for. Also jQuery has no way to intercept .bind() call, so that I could set up a callback right on time and remove it on .unbind() call. So my approach was to point out which events “might” get listened for on run time.
On the other hand, there are at least two pros, while going with events:
- You can assign multiple event listeners
- You can unbind them (I think it was not quite possible to do with callbacks)
Completely different approach
Second idea was to create a wrapper object for Jmol applet, that exposes some external interface methods as JavaScript methods – so that we could make them available for every one. Also using prototyping extend (with a separate source file) Jmol wrapper with some functions, like the ones in Jmol.Controlls.js (addButton, addCheckbox, etc.). We could add some fake jQuery functions, like bind(), that would first set up a callback in Jmol and then call jQuery’s bind within. The same thing could be done with unbind().
This approach would deliver a wrapper object through onReady callback to developer, from where it could be used instead of .jmol() plugin.
Also there would be a need for JmolFactory – a standard factory class, that would act like a callback receiver and wrapper object storage (ID based).