JavaScript Closure Problem

Post here questions and problems related to oXygen frameworks/document types.
jlpoole
Posts: 23
Joined: Sun Jan 15, 2017 3:15 pm
Location: Salem, Oregon

JavaScript Closure Problem

Post by jlpoole » Fri Nov 15, 2019 9:44 pm

Code: Select all

function print (msg) {
	if (typeof(msg) == "undefined"){
		// getting an undefined causes error as interpreter does not
		// know if string or object
		Packages.java.lang.System.out.println("undefined");
		return;
	}
	// next line for debugging
	//Packages.java.lang.System.out.println("[print 59] typeof msg = " + typeof(msg));
	if (typeof(msg) == "object"){
		Packages.java.lang.System.out.println("[toString] " + msg.toString);
	} else {
		Packages.java.lang.System.out.println(msg);
	}
}

function applicationStarted(pluginWorkspaceAccess){
	myWorkspaceAccess = pluginWorkspaceAccess;
	var edChangedListener = {
	    var editor = pluginWorkspaceAccess.getEditorAccess(editorLocation, Packages.ro.sync.exml.workspace.api.PluginWorkspace.MAIN_EDITING_AREA);
	    if(editor.getCurrentPageID() == "Author"){
			actionApple = {
				customizePopUpMenu: function (popUp, authorAccess) {				 
					try {
						documentController = authorAccess.getDocumentController();			
						mi = new Packages.javax.swing.JMenuItem("Print Apples");
						popUp.add(mi);
						actionPerfObj = {
							actionPerformed: function (e) {
								print("Apples @ 7th level");
								// want to call methods on authorAccess and documentController, e.g. process nodes with Apples in them
							}  // 7 levels of nesting! whew!
						}	
					}	
				}
			}
			
			actionBanana = {
				customizePopUpMenu: function (popUp, authorAccess) {				 
					try {
						documentController = authorAccess.getDocumentController();			
						mi = new Packages.javax.swing.JMenuItem("Print Bananas");
						popUp.add(mi);
						actionPerfObj = {
							actionPerformed: function (e) {
								print("Bananas @ 7th level");
								// want to call methods on authorAccess and documentController, e.g. process nodes with Bananas in them
							}  
						}	
					}	
				}
			}
			
			actionCherries = {
				customizePopUpMenu: function (popUp, authorAccess) {				 
					try {
						documentController = authorAccess.getDocumentController();			
						mi = new Packages.javax.swing.JMenuItem("Print Cherries");
						popUp.add(mi);
						actionPerfObj = {
							actionPerformed: function (e) {
								print("Cherries @ 7th level");
								// want to call methods on authorAccess and documentController, e.g. process nodes with Cherries in them
							}  
						}	
					}	
				}
			}
			actionDoAll = {
				customizePopUpMenu: function (popUp, authorAccess) {				 
					try {
						documentController = authorAccess.getDocumentController();			
						mi = new Packages.javax.swing.JMenuItem("Do All");
						popUp.add(mi);
						actionPerfObj = {
							actionPerformed: function (e) {
								// want to do each of the three calls of methods for Apples, Bananas & Cherries above
							}  
						}	
					}	
				}
			}
		}
	}
}
The above codes will create four separate submenus. For the last action, actionDoAll, I want to execute the 3 codes sections at level 7 above it. How can I have the code Apples, Bananas, and Cherries execute called by Do All?. Note: for simplicity,the above examples seem similar. In fact, my needs are that each of the first three do completely separate operations and are not so similar as to be distinguished by a variable.

I think this is a closure issue. I tried to isolate the code that would be at the 7th level into separate functions at the global level like my "print" function so they could be called from more than one place, but at load time, I get error messages about undefined values. This would coincide with my understanding of closure that the code is executed when called upon when various senior variables are defined, not at load time.

How can I structure code that would be executed say at the Apples 7th level and then executed at the DoAll 7th level without acutally having the code written out in each one? I'd like to have a single source of truth.

Radu
Posts: 6979
Joined: Fri Jul 09, 2004 5:18 pm

Re: JavaScript Closure Problem

Post by Radu » Mon Nov 18, 2019 10:29 am

Hi,

I do not quite understand, is your posted code incomplete? For example the "edChangedListener" does not seem to overwrite any function and is also not used anywhere.
Anyway, you can define top level functions in Javaascript which receive parameters and then call the functions with various parameters like:

Code: Select all

function printApples(authorAccess){
    ....
}
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

jlpoole
Posts: 23
Joined: Sun Jan 15, 2017 3:15 pm
Location: Salem, Oregon

Re: JavaScript Closure Problem

Post by jlpoole » Tue Nov 19, 2019 1:53 am

Hmmm. I had done just as you described: moved the repeated function to the top level with an entry parameter of authorAccess . I then started getting "not defined" error messages.

So I created a test case plugin and the task of passing an authorAccess works. I'll have to go back into my main code and try again.

Radu
Posts: 6979
Joined: Fri Jul 09, 2004 5:18 pm

Re: JavaScript Closure Problem

Post by Radu » Tue Nov 19, 2019 1:36 pm

Hi,

If you will need help I will need to look at the entire unchanged Javascript file that you are using.
Try to keep as much as possible local variables instead of global, and prefix each local variable declaration with the "var " keyword.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

Post Reply