Problem with UI and functions

Find out why the . goes before the /

Moderator: Paul Tuersley

Post Reply
Simma
Posts: 98
Joined: June 8th, 2010, 2:57 pm

Hi all,

I have a strange problem that's driving me crazy. It might very well be that I'm misunderstanding the syntax, but I can't seem to find a solution. Anyway, the problem is the following:

I have a script with a button and a dropdown list. When I press the button the script will alert the active composition and it will alert the current selection of the dropdown list. The script can be run both as a panel and as a palette.

I then have another script that has only one button. If I press it it will alert a string. This also works. However, if I run the first script, then run the second script, and then run the first script again, I can no longer call the value of the dropdown list (myPalette.grp.one.dropdown.selection.toString()). It seems like running another script (I've tested with others and same result) breaks the first script and it has to be re-launched.

This is causing problems and I would very much appreciate if anyone could help me with this. I will attach the code for the two test scripts below.

Script 1:

Code: Select all

var dropDown = new Array ("1", "2", "3", "4")

// Build UI
var myPalette = buildUI(this);

    if(myPalette != null && myPalette instanceof Window) {
       myPalette.show();
    }

function buildUI (thisObject) {
    
    if(thisObject instanceof Panel) {
        var myPalette = thisObject;
        }else{
            var myPalette = new Window ("palette", "test", undefined, {resizeable:true});
            }

    if (myPalette != null) {
    
    var res =
    "Group { \
    orientation: 'column', \
    alignment: ['fill', 'fill'], \
    alignChildren: ['left', 'top'], \
    minimumSize: [125, 26],\
        one: Group { \
            orientation: 'row', \
            dropdown: DropDownList {size: ['100', '25']}, \
            button01: Button {text:'test', size: ['85', '25']}, \
            } \
    }";

myPalette.grp = myPalette.add(res);
myPalette.layout.layout(true);
myPalette.layout.resize()
myPalette.resizing = myPalette.onResize = function () {this.layout.resize()};

// Populate view lut dropdown list.
for(i=0; i<dropDown.length; i++) {
    myPalette.grp.one.dropdown.add('item',dropDown[i]);
    }

// Set default dropdown selection.
myPalette.grp.one.dropdown.selection = myPalette.grp.one.dropdown.items[0];

myPalette.grp.one.button01.onClick = function () {
    button01 (myPalette);
    }

}//if(myPalette != null) {

return myPalette;
    
} //buildUI

function button01 (palObject) {
    
// Check that a single comp is selected or active
    if (app.project.activeItem == null){
        alert("Select a composition.");
        return;
        }

var myComp = app.project.activeItem.name;
alert("The active composition is: " + myComp);

var mySelection = myPalette.grp.one.dropdown.selection.toString();
alert("The current selection is: " + mySelection);

}
Script 2:

Code: Select all

// Build UI
var myPalette = buildUI(this);

    if(myPalette != null && myPalette instanceof Window) {
       myPalette.show();
    }

function buildUI (thisObject) {
    
    if(thisObject instanceof Panel) {
        var myPalette = thisObject;
        }else{
            var myPalette = new Window ("palette", "test", undefined, {resizeable:true});
            }

    if (myPalette != null) {
    
    var res =
    "Group { \
    orientation: 'column', \
    alignment: ['fill', 'fill'], \
    alignChildren: ['left', 'top'], \
    minimumSize: [125, 26],\
        one: Group { \
            orientation: 'row', \
            temp: Button {text: 'temp', size: ['85', '25']}, \
            } \
    }";

myPalette.grp = myPalette.add(res);
myPalette.layout.layout(true);
myPalette.layout.resize()
myPalette.resizing = myPalette.onResize = function () {this.layout.resize()};

myPalette.grp.one.temp.onClick = function () {
    temp (myPalette);
    }

}//if(myPalette != null) {

return myPalette;
    
} //buildUI

function temp (palObject) {
    
alert("tester");

}
Paul Tuersley
Posts: 704
Joined: June 5th, 2004, 7:59 am
Location: London, UK

I think this is because variables defined outside a function have global scope across all scripts, and your myPalette variable is getting redefined by the second script. You should use unique names for variables defined in the main scope, but even these would conflict if you were to run multiple instances of the same script.

Here's a post with an example of a script framework that puts the whole script in a function so you shouldn't have to worry about global scope. Jeff Almasol did it this way in his scripts and a lot of us have adopted it. (I still always use unique names for my palette and main object variables though)
http://forums.adobe.com/message/4035846#4035846
Simma
Posts: 98
Joined: June 8th, 2010, 2:57 pm

Paul, once again, thank you for your help. I truly appriciate it.

I tried the code you linked to and it does seem to work. However, I'm a bit unsure where to put my functions and user variables. Would you mind having a look at it? I will try to read up more on this as I realize I'm not fully following this.

Here's some code:

Code: Select all

{

///////////////////// Is this where I put my user variables? ////////////////////////////////

var user_variable = new Array ("sony film (ocio)", "gamma 2.2", "sRGB", "rec709")
    
function myScript(thisObj) {
 
var myScript_Data = new Object();
myScript_Data.scriptName = "myScript";
// myScript_Data.luts = new Array ("sony film (ocio)", "gamma 2.2", "sRGB", "rec709")
 
function myScript_buildUI(thisObj) {
var pal = (thisObj instanceof Panel) ? thisObj : new Window("palette", myScript_Data.scriptName, undefined);
 
    if (pal != null) {
    var res=
    "Group { \
    orientation: 'column', \
    alignment: ['fill', 'fill'], \
    alignChildren: ['left', 'top'], \
    minimumSize: [125, 26],\
    one: Group { \
        orientation: 'row', \
        dropdown: DropDownList {size: ['100', '25']}, \
        button: Button {text: 'alert selection', size: ['100', '25']}, \
        } \
        }";
 
pal.grp = pal.add(res);
pal.layout.layout(true);
pal.layout.resize()
pal.resizing = pal.onResize = function () {this.layout.resize()};

// Populate view lut dropdown list.
for(i=0; i<user_variable.length; i++) {
    pal.grp.one.dropdown.add('item',user_variable[i]);
    }

// Set default bit depth in dropdown & project.
pal.grp.one.dropdown.selection = pal.grp.one.dropdown.items[0];

pal.grp.one.button.onClick = function () {
    viewLUT (pal);
    }
 
return pal;

} // if (pal != null) {

} // function myScript_buildUI(thisObj) { 

var myPal = myScript_buildUI(thisObj);
    if (myPal != null) {
        if (myPal instanceof Window) {
        myPal.center();
        myPal.show();
        } // if (myPal instanceof Window) {
    } // if (myPal != null) {




/////////////// Is this where I put my functions? Or at the bottom? //////////////

function viewLUT (pal) {
    
var selection = pal.grp.one.dropdown.selection.toString();
alert(selection);
}

//////////////////////////////////////////////////////////////////////////////////




} // function myScript(thisObj) {


myScript(this);


} // {




Paul Tuersley
Posts: 704
Joined: June 5th, 2004, 7:59 am
Location: London, UK

I've added some comments which will hopefully help explain things.

Code: Select all

{	// THESE MATCHING BRACKETS AT START/END MAY NOT BE NECESSARY
	// I THINK WE USED TO DO THIS THINKING IT PREVENTED VARIABLES HAVING GLOBAL (APP WIDE) SCOPE
	// BUT THAT ISN'T THE CASE. I DON'T THINK THEY REALLY DO ANYTHING.

	///////////////////// Is this where I put my user variables? ////////////////////////////////
	// NO, THIS IS IN GLOBAL SCOPE, DEFINED OUTSIDE OF ANY FUNCTIONS
	//var user_variable = new Array ("sony film (ocio)", "gamma 2.2", "sRGB", "rec709")
		
	// THIS IS THE FUNCTION THAT CONTAINS THE WHOLE SCRIPT
	function myScript(thisObj) {

		var myScript_Data = new Object();
		myScript_Data.scriptName = "myScript";
		
		// THIS IS A GOOD PLACE TO DEFINE YOUR VARIABLES THAT NEED TO BE ACCESSIBLE THROUGHOUT THE SCRIPT
		// CAN EITHER CREATE SEPARATE VARIABLES, OR ADD THEM TO THE myScript_Data object.	
		// EITHER OF THESE WILL WORK
		// myScript_Data.luts = new Array ("sony film (ocio)", "gamma 2.2", "sRGB", "rec709");
		var user_variable = new Array ("sony film (ocio)", "gamma 2.2", "sRGB", "rec709");

		function myScript_buildUI(thisObj) {
			var pal = (thisObj instanceof Panel) ? thisObj : new Window("palette", myScript_Data.scriptName, undefined);

			if (pal != null) {
				var res=
				"Group { \
				orientation: 'column', \
				alignment: ['fill', 'fill'], \
				alignChildren: ['left', 'top'], \
				minimumSize: [125, 26],\
				one: Group { \
					orientation: 'row', \
					dropdown: DropDownList {size: ['100', '25']}, \
					button: Button {text: 'alert selection', size: ['100', '25']}, \
					} \
				}";

				pal.grp = pal.add(res);
				pal.layout.layout(true);
				pal.layout.resize()
				pal.resizing = pal.onResize = function () {this.layout.resize()};

				// Populate view lut dropdown list.
				for(i=0; i<user_variable.length; i++) {
					pal.grp.one.dropdown.add('item',user_variable[i]);
				}

				// Set default bit depth in dropdown & project.
				pal.grp.one.dropdown.selection = pal.grp.one.dropdown.items[0];

				pal.grp.one.button.onClick = function () {
					viewLUT (pal);
				}

				return pal;

			} // if (pal != null) {

		} // function myScript_buildUI(thisObj) { 
	

		/////////////// Is this where I put my functions? Or at the bottom? //////////////
		// I WOULD GENERALLY PUT MY MAIN FUNCTIONS HERE

		function viewLUT (pal) {
			
			// IF A VARIABLE IS ONLY NEEDED INSIDE A FUNCTION YOU CAN DEFINE IT (var) INSIDE THAT FUNCTION
			// YOU CAN HAVE MULTIPLE VARIABLES WITH SAME NAME IN DIFFERENT FUNCTIONS WITHOUT THEM CONFLICTING
			// THESE VARIABLES WILL CEASE TO EXIST WHEN RETURNING FROM THE FUNCTION.
			
			var selection = pal.grp.one.dropdown.selection.toString();
			alert(selection);
		}


		// THIS IS THE MAIN BIT OF CODE THAT RUNS WHEN YOU LAUNCH THE SCRIPT
		
		// IT STARTS BY CALLING THE MYSCRIPT FUNCTION  i.e. myScript(this)
		// DEFINES YOUR SCRIPT-WIDE VARIABLES
		// DEFINES YOUR FUNCTIONS
		// THEN FINALLY GETS TO THIS CODE
		
		// THIS IS WHERE I USUALLY CHECK FOR AE VERSION AND READ ANY PREFERENCES ASSOCIATED WITH THIS SCRIPT	
		
		// THEN FINALLY YOU CALL THE BUILDUI FUNCTION

		var myPal = myScript_buildUI(thisObj);
		if (myPal != null) {
			if (myPal instanceof Window) {
				myPal.center();
				myPal.show();
			} // if (myPal instanceof Window) {
		} // if (myPal != null) {
	
	

	} // function myScript(thisObj) {


	// THIS IS THE ONLY CODE IN THE MAIN SCOPE OF THE SCRIPT
	// EVERYTHING ELSE IS IN THE MYSCRIPT FUNCTION
	// THIS FUNCTION NAME PROBABLY HAS TO BE UNIQUE FOR THAT REASON
	myScript(this);


} // {
Simma
Posts: 98
Joined: June 8th, 2010, 2:57 pm

Thanks a lot Paul, that explains a lot. I also believe your explanation helped me track down an old bug in another script of mine. Thanks for taking the time!
Post Reply