Skip to main content
AODA_Developer
Inspiring
April 9, 2016
Question

How to dynamically update a dropdownlist after it's been created?

  • April 9, 2016
  • 2 replies
  • 1788 views

I'm trying to create a small GUI that gives the user the ability to select a layer from the list of layers in a document. Initial population of the drop down is easy, it's done at creation. But if the user creates or deletes a layer, then I need to update the items in the dropdownlist. I've gone over the relevant documentation (including the latest rev of "Beginning ScriptUI"), but can't seem to find a way to do this.

Here's a standalone snippet of code that *should* work, except that the events are not being called (onClick, onActivate, onDraw). Anyone have any tips?

#target Illustrator

#targetengine main

var testW = new Window ("palette", "test");

var labelSpacing = 15;

var listOfLayers = [];

// Create group for layers label and dropdown list

var grpLayer = testW.add("group");

grpLayer.alignment = "left";

// label for Layers selection

var layerName = grpLayer.add ("statictext", undefined, "Layers:");

// populate the list of layers from the active Illustrator document

listOfLayers = buildCurrentLayerList();

var mydropdownList = grpLayer.add ("dropdownlist", undefined, listOfLayers);

mydropdownList.characters = labelSpacing;

mydropdownList.selection = listOfLayers.active;

// Add onClick event - builds list of current layers

mydropdownList.onClick = function() {

  alert("onClick event on dropdownlist, activeDoc = " + app.activeDocument);

  listOfLayers = buildCurrentLayerList();

  myropdownList.removeAll();

  listOfLayers.foreach(mydropdownList.add(listOfLayers[index]));

}

// TRY onActivate event listener to build list of current layers

mydropdownList.addEventListener ('onActivate', function() {

  alert("onActivate event on dropdownlist, activeDoc = " + app.activeDocument);

  mydropdownList.removeAll();

  listOfLayers = buildCurrentLayerList();

  listOfLayers.foreach(mydropdownList.add(listOfLayers[index]));

});

// TRY onDraw event listener to build list of current layers

mydropdownList.addEventListener ('onDraw', function() {

  alert("onDraw event on dropdownlist, activeDoc = " + app.activeDocument);

  mydropdownList.removeAll();

  listOfLayers = buildCurrentLayerList();

  listOfLayers.foreach(mydropdownList.add(listOfLayers[index]));

});

// Create Close button

var grpButtons = testW.add("group");

grpLayer.alignment = "center";

var closeButton = grpButtons.add ("button", undefined, "Close");

// close the window

closeButton.onClick = function() {

  testW.close();

  testW = null;

}

// Draw the window

testW.show();

// ============================================================

// Function: buildCurrentLayerList

// Returns:  array of layer names and index of active field

// ============================================================

function buildCurrentLayerList() {

  var layerCount;

  var layers = ["<use active layer>","-"];

  layers.active = 0;

       

  if ( app.activeDocument == null ) {

    alert("Active documents is null");

  } else if ( app.activeDocument == "" ) {

    alert("Active documents is empty");

  } else {

    layerCount = app.activeDocument.layers.length;

    for ( idx = 0; idx < layerCount; idx++ ) {

      layers[idx+2] = app.activeDocument.layers[idx].name;

      if ( layers[idx+2] == app.activeDocument.activeLayer.name ) {

        layers.active = idx+2;

      }

    }

  }

  return(layers);

}

This topic has been closed for replies.

2 replies

tt27079448
Inspiring
April 11, 2016

My approach is to increase a button

Button's function is to close the window, open again

AODA_Developer
Inspiring
April 11, 2016

Hi tt27079448,

Thanks for the alternative. However, asking the user to open/close the window all the time to update the contents would become irritating.

In my reading from Carlos I've come across a great discussion that summarizes BridgeTalk nicely:

How to access app.activeDocument from a palette button?

alanomaly gave a simple example of how to implement the comms between a palette and Illustrator. It's actually much simpler than I thought and should be relatively easy to integrate into my tool. I'll still have to destroy and recreate the dropdownlist, but at least now I can get the current information from Illustrator without requiring any extra user interaction.

Basic code from alanomaly is:

function someFunction() {

  // get data from the application

  return app.activeDocument.selection.length;

}

palette.button.onclick = function(){

  // make a BridgeTalk object to throw the script

  var bt = new BridgeTalk();

  bt.target = "illustrator";

 

  // a string containing javascript code to execute in Illustrator

  bt.body = someFunction.toString()+'someFunction();';

 

  // a function that recieves whatever the body JS above returns

  bt.onResult = function(result){

    palette.info.text = result.body;

  };

 

  bt.send();

}

tt27079448
Inspiring
April 12, 2016

it's cool, thank you

CarlosCanto
Community Expert
Community Expert
April 9, 2016

couple of concepts, in order for palettes to communicate with Illustrator, you must use BridgeTalk, check the Tools Guide for details. You can also search the forum, we have posted plenty of samples on this subject, here's one of them

Introducing: Select Layers Script

next, to repopulate the dropdown list dynamically, you need to remove your dropdown, then add a new one with the new set of items.

your script has a couple of errors,

- dropdown lists don't respond to onClick events, use onChange instead.

- typo here "myropdownList.removeAll();" missing a "d"

- this version of javascript does not support "foreach"

I didn't do extensive debugging, get the above sorted and we'll go from there.

AODA_Developer
Inspiring
April 9, 2016

Hi Carlos,

Thanks for the quick reply. I wasn't sure about the onClick so I added onActivate and onDraw to test further. And yes, I saw the missing 'd' after I posted, I should have learned by now not to code on the fly. Same thing goes for 'foreach', I'll switch it to a proper 'for' loop.

Removing and re-adding seems rather extreme, but I'll give it a try. I just need those events to trigger first. Out of curiosity, does the onChange trigger when the dropdown is clicked? Or will it trigger after the list has been displayed and the user has click on an entry? I couldn't find a reference about sequences or order of operations.

In the meantime I'll follow your link and get informed, thanks for the tip!

CarlosCanto
Community Expert
Community Expert
April 9, 2016

yeah, in reality there's no way (that I know of) to update dropdowns dynamically, removing and recreating is a workaround I found rather painfully.