Quantcast

Newbie JavaScript question

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Newbie JavaScript question

Bob Loushin
I’m teaching myself JavaScript (for use with ImageJ) using information for the developers page of the ImageJ website, Rhino’s homepage and links from there, Codecademy, etc.  One basic question I have been unable to find an answer for is, “How do I call a function defined in one file from another one?”  For a simple example, I have two files, both in the plugins folder of ImageJ:

In test1.js, just two lines:

//test1();
function test1() {IJ.log("Function test1() was called.");}

If I uncomment the first line and run the plugin, the message appears in the log file.

The other file is in test2.js, just one line:

test1();

When I run test2, it doesn’t  know what test1 is.  In C++ the two files get joined at compile time.  In Java, they can be jarred together, or found if the path is set right.  If they were macros, they’d also be found if the path was set up right.  This doesn’t appear to happen in JavaScript, however, they’re both in the same folder, and that folder should be in the default path.  importClass and importPackage don’t seem to help, either, I think because they only allow importing of Java packages.

Can anybody tell me how to do this?

Thank you,

Bob
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Newbie JavaScript question

Sullivan, Michael J (College of Med.)
I've never used js w/ imageJ, plugin or otherwise, but it's my understanding that external javascript (i.e. js not imbedded in HTML) code becomes part of the Document.
In a HTML file I could imbed js from two files by putting these two lines in the head section:

<script language="javascript" src="file1.js"></script>
<script language="javascript" src="file2.js"></script>

All js code is essentially now "linked" together.

HTH

--- Mike


-----Original Message-----
From: ImageJ Interest Group [mailto:[hidden email]] On Behalf Of Bob
Sent: Friday, March 16, 2012 4:57 PM
To: [hidden email]
Subject: Newbie JavaScript question

I’m teaching myself JavaScript (for use with ImageJ) using information for the developers page of the ImageJ website, Rhino’s homepage and links from there, Codecademy, etc.  One basic question I have been unable to find an answer for is, “How do I call a function defined in one file from another one?”  For a simple example, I have two files, both in the plugins folder of ImageJ:

In test1.js, just two lines:

//test1();
function test1() {IJ.log("Function test1() was called.");}

If I uncomment the first line and run the plugin, the message appears in the log file.

The other file is in test2.js, just one line:

test1();

When I run test2, it doesn’t  know what test1 is.  In C++ the two files get joined at compile time.  In Java, they can be jarred together, or found if the path is set right.  If they were macros, they’d also be found if the path was set up right.  This doesn’t appear to happen in JavaScript, however, they’re both in the same folder, and that folder should be in the default path.  importClass and importPackage don’t seem to help, either, I think because they only allow importing of Java packages.

Can anybody tell me how to do this?

Thank you,

Bob

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Newbie JavaScript question

dscho
Hi Mike and Bob (who hopefully gets this mail, too),

On Mon, 19 Mar 2012, Sullivan, Michael J wrote:

> > -----Original Message-----
> > From: ImageJ Interest Group [mailto:[hidden email]] On Behalf Of Bob
> > Sent: Friday, March 16, 2012 4:57 PM
> > To: [hidden email]
> > Subject: Newbie JavaScript question
> >
> > I’m teaching myself JavaScript (for use with ImageJ) using information
> > for the developers page of the ImageJ website, Rhino’s homepage and
> > links from there, Codecademy, etc.  One basic question I have been
> > unable to find an answer for is, “How do I call a function defined in
> > one file from another one?”  For a simple example, I have two files,
> > both in the plugins folder of ImageJ:
> >
> > In test1.js, just two lines:
> >
> > //test1();
> > function test1() {IJ.log("Function test1() was called.");}
> >
> > If I uncomment the first line and run the plugin, the message appears
> > in the log file.
> >
> > The other file is in test2.js, just one line:
> >
> > test1();
> >
> > When I run test2, it doesn’t  know what test1 is.  In C++ the two
> > files get joined at compile time.  In Java, they can be jarred
> > together, or found if the path is set right.  If they were macros,
> > they’d also be found if the path was set up right.  This doesn’t
> > appear to happen in JavaScript, however, they’re both in the same
> > folder, and that folder should be in the default path.  importClass
> > and importPackage don’t seem to help, either, I think because they
> > only allow importing of Java packages.
> >
> > Can anybody tell me how to do this?
> >
> > Thank you,
> >
> > Bob
>
> > I've never used js w/ imageJ, plugin or otherwise, but it's my
> understanding that external javascript (i.e. js not imbedded in HTML)
> code becomes part of the Document.  In a HTML file I could imbed js from
> two files by putting these two lines in the head section:
>
> <script language="javascript" src="file1.js"></script>
> <script language="javascript" src="file2.js"></script>
This is Javascript embedded in HTML. In ImageJ, the scripts are not
embedded in HTML.

But a simple DuckDuckGo search reveals that there is a load() function:

http://stackoverflow.com/questions/650377/javascript-rhino-use-library-or-include-other-scripts#651620

Use it thusly:

        load("file1.js");

Hth,
Johannes
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Newbie JavaScript question

Bob Loushin
Johannes' suggestion of load() looked like exactly what I needed, so I tried
adding the line
load("test1.js");
to the beginning of test2.
It failed with the error message "ReferenceError: 'load' is not defined."  I
did a lot of digging on Mozilla's web site and learned two things:

1)  They could learn a lot about documentation from the ImageJ people.
Seriously (and this isn't said often enough), the documentation of the API
on the ImageJ site is very well done which makes it quite helpful.
Congratulations and thank you to the ImageJ team for that!

2)  It appears that load isn't part of JavaScript itself, but is instead a
feature of the interactive shell.  On the page describing the Rhino shell,
the section in which "load()" is described starts with the comment "Scripts
executing in the shell have access to some additional properties of the
top-level object."

I also got a private e-mail from Wayne Rasband saying, in summary,
JavaScript in ImageJ isn't set up for multi-file source code, and if the
project is complex enough to require it, use Java.

So it looks like this isn't going to be practical.  Thank you to everyone
who responded to my question.

Bob

-----Original Message-----
From: Johannes Schindelin
Sent: Monday, March 19, 2012 9:09 AM
To: [hidden email]
Subject: Re: Newbie JavaScript question

Hi Mike and Bob (who hopefully gets this mail, too),

On Mon, 19 Mar 2012, Sullivan, Michael J wrote:

> > -----Original Message-----
> > From: ImageJ Interest Group [mailto:[hidden email]] On Behalf Of
> > Bob
> > Sent: Friday, March 16, 2012 4:57 PM
> > To: [hidden email]
> > Subject: Newbie JavaScript question
> >
> > I’m teaching myself JavaScript (for use with ImageJ) using information
> > for the developers page of the ImageJ website, Rhino’s homepage and
> > links from there, Codecademy, etc.  One basic question I have been
> > unable to find an answer for is, “How do I call a function defined in
> > one file from another one?”  For a simple example, I have two files,
> > both in the plugins folder of ImageJ:
> >
> > In test1.js, just two lines:
> >
> > //test1();
> > function test1() {IJ.log("Function test1() was called.");}
> >
> > If I uncomment the first line and run the plugin, the message appears
> > in the log file.
> >
> > The other file is in test2.js, just one line:
> >
> > test1();
> >
> > When I run test2, it doesn’t  know what test1 is.  In C++ the two
> > files get joined at compile time.  In Java, they can be jarred
> > together, or found if the path is set right.  If they were macros,
> > they’d also be found if the path was set up right.  This doesn’t
> > appear to happen in JavaScript, however, they’re both in the same
> > folder, and that folder should be in the default path.  importClass
> > and importPackage don’t seem to help, either, I think because they
> > only allow importing of Java packages.
> >
> > Can anybody tell me how to do this?
> >
> > Thank you,
> >
> > Bob
>
> > I've never used js w/ imageJ, plugin or otherwise, but it's my
> understanding that external javascript (i.e. js not imbedded in HTML)
> code becomes part of the Document.  In a HTML file I could imbed js from
> two files by putting these two lines in the head section:
>
> <script language="javascript" src="file1.js"></script>
> <script language="javascript" src="file2.js"></script>

This is Javascript embedded in HTML. In ImageJ, the scripts are not
embedded in HTML.

But a simple DuckDuckGo search reveals that there is a load() function:

http://stackoverflow.com/questions/650377/javascript-rhino-use-library-or-include-other-scripts#651620

Use it thusly:

load("file1.js");

Hth,
Johannes
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Newbie JavaScript question

dscho
Hi Bob,

On Mon, 19 Mar 2012, Bob wrote:

> Johannes' suggestion of load() looked like exactly what I needed, so I tried
> adding the line
> load("test1.js");
> to the beginning of test2.
> It failed with the error message "ReferenceError: 'load' is not defined."

My bad. I tried with "ImageJ-linux32 --js" from the command-line because
it was quicker, but that mode is exactly what you describe: Rhino's shell,
which defines the load() function.

Since Rhino's shell can do it, and we basically use Rhino ourselves to
interpret Javascript, there is no good reason why we should not be able to
recreate that functionality, right?

So that's what I just did. Once you update your Fiji, the load() function
is available.

In plain ImageJ, you can recreate that functionality by putting this code
at the start of your file that wants to call another file:

        function load(path) {
                importClass(Packages.org.mozilla.javascript.Context);
                importClass(Packages.java.io.FileReader);
                var cx = Context.getCurrentContext();
                cx.evaluateReader(this, new FileReader(path), path, 1, null);
        }

Ciao,
Dscho

P.S.: since I described this so neatly, the next daily build of ImageJ
will probably have a re-implementation of this, so you'll not need to
define the load() function yourself. Having said this, there should not be
any harm in defining it yourself, so you might want to do that e.g. if you
need to be able to run your Javascript on older ImageJ versions, too (for
whatever reason).
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Newbie JavaScript question

Bob Loushin
Awesome!  I tried this out, and it works as advertised.

Thank you!

Bob

-----Original Message-----
From: Johannes Schindelin
Sent: Tuesday, March 20, 2012 12:11 PM
To: Bob
Cc: [hidden email]
Subject: Re: Newbie JavaScript question

Hi Bob,

On Mon, 19 Mar 2012, Bob wrote:

> Johannes' suggestion of load() looked like exactly what I needed, so I
> tried
> adding the line
> load("test1.js");
> to the beginning of test2.
> It failed with the error message "ReferenceError: 'load' is not defined."

My bad. I tried with "ImageJ-linux32 --js" from the command-line because
it was quicker, but that mode is exactly what you describe: Rhino's shell,
which defines the load() function.

Since Rhino's shell can do it, and we basically use Rhino ourselves to
interpret Javascript, there is no good reason why we should not be able to
recreate that functionality, right?

So that's what I just did. Once you update your Fiji, the load() function
is available.

In plain ImageJ, you can recreate that functionality by putting this code
at the start of your file that wants to call another file:

function load(path) {
importClass(Packages.org.mozilla.javascript.Context);
importClass(Packages.java.io.FileReader);
var cx = Context.getCurrentContext();
cx.evaluateReader(this, new FileReader(path), path, 1, null);
}

Ciao,
Dscho

P.S.: since I described this so neatly, the next daily build of ImageJ
will probably have a re-implementation of this, so you'll not need to
define the load() function yourself. Having said this, there should not be
any harm in defining it yourself, so you might want to do that e.g. if you
need to be able to run your Javascript on older ImageJ versions, too (for
whatever reason).
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Newbie JavaScript question

Bob Loushin
As of Friday, 3/23, this update (the addition of load) had not yet been
propagated to ImageJ (as I said in my previous message, it does work in
Fiji) itself (our organization has standardized on ImageJ).  Also, I tried
Johannes' code for adding load to my own scripts, but it did not work in
ImageJ.  I suspect some of the needed infrastructure was left out of the
ImageJ code but included in Fiji.  Specifically, when I included Johannes'
code for load() in my file, and then run it, I get the error message "Error:
Function importClass must be called with a class; had "[JavaPackage
org.mozilla.javascript.Context]" instead. (<Unknown source>#2) in <Unknown
source> at line number 2".  Thinking perhaps it should be importPackage
instead of importClass in line 2, I made that change and tried again.  This
got me a little further, the error message was "ReferenceError: "Context" is
not defined. (<Unknown source>#4) in <Unknown source> at line number 4".

For now I am working around this by using Fiji when I need this trick, but
I'm hoping to be able to bring this back into ImageJ eventually.

Bob

-----Original Message-----
From: Bob
Sent: Tuesday, March 20, 2012 5:32 PM
To: [hidden email]
Subject: Re: Newbie JavaScript question

Awesome!  I tried this out, and it works as advertised.

Thank you!

Bob

-----Original Message-----
From: Johannes Schindelin
Sent: Tuesday, March 20, 2012 12:11 PM
To: Bob
Cc: [hidden email]
Subject: Re: Newbie JavaScript question

Hi Bob,

On Mon, 19 Mar 2012, Bob wrote:

> Johannes' suggestion of load() looked like exactly what I needed, so I
> tried
> adding the line
> load("test1.js");
> to the beginning of test2.
> It failed with the error message "ReferenceError: 'load' is not defined."

My bad. I tried with "ImageJ-linux32 --js" from the command-line because
it was quicker, but that mode is exactly what you describe: Rhino's shell,
which defines the load() function.

Since Rhino's shell can do it, and we basically use Rhino ourselves to
interpret Javascript, there is no good reason why we should not be able to
recreate that functionality, right?

So that's what I just did. Once you update your Fiji, the load() function
is available.

In plain ImageJ, you can recreate that functionality by putting this code
at the start of your file that wants to call another file:

function load(path) {
importClass(Packages.org.mozilla.javascript.Context);
importClass(Packages.java.io.FileReader);
var cx = Context.getCurrentContext();
cx.evaluateReader(this, new FileReader(path), path, 1, null);
}

Ciao,
Dscho

P.S.: since I described this so neatly, the next daily build of ImageJ
will probably have a re-implementation of this, so you'll not need to
define the load() function yourself. Having said this, there should not be
any harm in defining it yourself, so you might want to do that e.g. if you
need to be able to run your Javascript on older ImageJ versions, too (for
whatever reason).
Loading...