Skip to main content
Jake7732
Inspiring
September 13, 2018
Question

New workaround? Palette ScriptUI communicating with AI without BridgeTalk.

  • September 13, 2018
  • 1 reply
  • 1724 views

Not sure if this is new or not but, (sorry if its old!)

After looking around at why i cant get my script to pull width/height data from a document after using a palette UI window, I found that its only possible with BridgeTalk.

However, i have a script i am currently using that I think tricks it into working by calling up illustrator to run an action.

Not sure what is causing it to function correctly but it works without BridgeTalk.

Figured some more talented people could deconstruct this monster of a mess i've thrown together and figure out how or why it works so it can help others out.

Setup:

Create a desktop folder called "test"

Create a random PNG file and save in "test"

Download this tab-delimited TXT file and save to desktop.

Change var folder to your desktop test folder location.

Create an action folder in illustrator called "test"

Create an action in that test folder called "test" that does just a select all.

Run:

Drag and drop the JSX file into illustrator

Click Run

Open the downloaded TXT file when prompted.

It should add in "Hello World" to the bottom left of your artboard and alert you of the png width size.

#target illustrator 

#targetengine main 

var originalInteractionLevel = userInteractionLevel;

function theRip(){ // enclosing function wraps the body of the script 

var w = new Window("palette");

var stkrow = w.add("group");

var stktit = stkrow.add("statictext",undefined,"Stk");

var stkrow2 = w.add("group");

var stk3x4 = stkrow2.add("button", undefined, "Run");

w.show();

stk3x4.onClick=function(){

app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;

//silly-v txt to variable

  var f = File.openDialog("Choose a CSV file.", "*.txt"); // choose a file with a .txt extension in Windows 

  if(!f){ 

    return; // exit script if the Cancel button was pressed 

  } 

  var gridStr; 

  f.open('r'); 

  gridStr = f.read(); // read the contents of the .txt file into a string variable 

  f.close(); 

 

  var grid = gridStr.split(/[\n\r]/); // turn the text into groups of rows by splitting the text by nextlines or carriage returns 

  for(var i=0; i<grid.length; i++){ // go through each of the row groups and turn them into groups of cells by splitting with tab characters 

   grid = grid.split(/\t/g); 

  }; 

 

 

  // set the active document to a variable 

  var ptArr = [], thisRow, x, y; // process the spreadsheet array to eliminate blank or incomplete rows 

  for(var i=1; i<grid.length; i++){ 

    if(typeof(grid[1]) == "undefined" || typeof(grid[2]) == "undefined" || grid[1] == "" || grid[2] == ""){ 

      continue; // if there are blank or missing cells where the x or y points should be, ignore this row 

    } 

    thisRow = grid

    x = thisRow [1].toString().replace(/"/g, '').replace(",", ".") * 1; // convert any nordic cells to numbers by removing any excel-generated quotes and replacing commas with periods, then cast to number by multiplying times one 

    y = thisRow [2].toString().replace(/"/g, '').replace(",", ".") * 1; 

    ptArr.push([x, y]); // add the processed coordinate point to array 

  }; 

for(var i=0; i<grid.length; i++){

var order = grid[0];

var wo = grid[1];

var design = grid[2];

var qty = grid[3];

if(order>1){

var folder = "/C/Users/Jake/Desktop/test/" // select folder 

    var files = find_files (folder, ['.png']); 

          var fileCount = files.length; // count them

          if (fileCount>0) { 

                    for (p=0; p<fileCount; p++) { 

var idoc = app.open(files[0]);

                    }  

          } 

          else { 

                    alert("There are no PNG files in this folder."); 

          }   

// recurse subfolders - Peter Kharel 

function find_files (dir, mask_array){ 

    var arr = []; 

    for (var i = 0; i < mask_array.length; i++){ 

        arr = arr.concat (find_files_sub (dir, [], mask_array.toUpperCase())); 

    } 

    return arr; 

 

function find_files_sub (dir, array, mask){ 

    var f = Folder (dir).getFiles ( '*.*' ); 

    for (var i = 0; i < f.length; i++){ 

        if (f instanceof Folder){ 

            find_files_sub (f, array, mask); 

        } else if (f.name.substr (-mask.length).toUpperCase() == mask){ 

            array.push (f); 

        } 

    } 

    return array; 

}

}//end if workorder > 1

if(order>1){ //run ai action

app.doScript('test','test');

var imgw = app.activeDocument.selection[0].width;

alert(imgw);

//reset ruler origin

app.activeDocument.rulerOrigin = [0,0];

//add text for barcode

var pointTextRef = app.activeDocument.textFrames.add();

pointTextRef.contents = "HELLO WORLD";

pointTextRef.textRange.characterAttributes.textFont = app.textFonts.getByName("Arial");

pointTextRef.textRange.characterAttributes.size = 20;

pointTextRef.position = [15, 19];

pointTextRef.selected = true;

redraw();

}

}//for loop

}//stk on click

app.userInteractionLevel = originalInteractionLevel;

}; 

theRip(); 

This topic has been closed for replies.

1 reply

Silly-V
Legend
September 13, 2018

What an interesting discovery, and I am baffled by why it works - but it has a good potential to bring the power of BridgeTalk to scripts by circumventing it so.

What I found is that the script works once an action is played in it at least one time. I commented out the doScript and was able to run the script successfully in that document and new ones I created.

Here's a condensed version I edited to experiment with.

So it would be no doubt easy to create palette code than using the BT object, but I wonder if there's any issues that could arise from this method.

Another question is if there's another action that could be done that didn't have to edit the current selection, as this would allow us super-easy control to make own tools using only jsx and no BT.

To use the below example, have a document open and a path shape in there.

#target illustrator

#targetengine main

var originalInteractionLevel = userInteractionLevel;

function theRip() { // enclosing function wraps the body of the script

  function deFocusPanel(){

    var w = new Window("palette");

    w.show();

    w.close();

  };

  var w = new Window("palette", "My Title");

  var stkrow = w.add("group");

  var stktit = stkrow.add("statictext", undefined, "Stk");

  var stkrow2 = w.add("group");

  stkrow2.orientation = "column";

  var disp_imgw = stkrow2.add("edittext", undefined, "", {readonly:true});

  disp_imgw.characters = 10;

  var stk3x4 = stkrow2.add("button", undefined, "Run");

  w.show();

  stk3x4.onClick = function() {

    app.doScript("Action 1", "Test"); // only needs to run one time from an event-handling function

    var imgw = app.activeDocument.pathItems[0].width;

    disp_imgw.text = imgw;

    // alert(imgw);

    app.activeDocument.rulerOrigin = [0, 0];

    var pointTextRef = app.activeDocument.textFrames.add();

    pointTextRef.contents = "HELLO WORLD.\nImgw: " + imgw;

    pointTextRef.textRange.characterAttributes.textFont = app.textFonts.getByName("ArialMT"); // careful to change font name to your system's

    pointTextRef.textRange.characterAttributes.size = 20;

    pointTextRef.position = [15, 19];

    pointTextRef.translate(20, 20);

    pointTextRef.selected = true;

    app.redraw();

    deFocusPanel();

  }

};

theRip();

Jake7732
Jake7732Author
Inspiring
September 13, 2018

This was actually just a snipet of code that I am currently using.

My entire script has multiple palette buttons that each individually reference a whole bunch of code to process art files (create outlines, set strokes, change colors, opacity, etc) that uses app.activeDocument without referencing BT.

The workaround I am doing is just app.doScript('nan','nan'); where nan isnt even a folder or action in illustrator. Everything after seems to be able to reference app.activeDocument just fine.

Simplifying your code even further without the extra UI rows seems to work as well, seems as though all we have to do is a simple app.doScript('x','x');

#target illustrator 

#targetengine main 

var originalInteractionLevel = userInteractionLevel; 

 

 

function theRip() { // enclosing function wraps the body of the script 

 

 

  function deFocusPanel(){ 

    var w = new Window("palette"); 

    w.show(); 

    w.close(); 

  }; 

 

 

  var w = new Window("palette", "My Title"); 

  var stk3x4 = w.add("button", undefined, "Run"); 

  w.show(); 

 

 

  stk3x4.onClick = function() { 

    app.doScript("nan", "nan"); // only needs to run one time from an event-handling function 

    var imgw = app.activeDocument.pathItems[0].width; 

    alert(imgw); 

 

 

    app.activeDocument.rulerOrigin = [0, 0]; 

    var pointTextRef = app.activeDocument.textFrames.add(); 

    pointTextRef.contents = "HELLO WORLD.\nImgw: " + imgw; 

    app.redraw(); 

    deFocusPanel(); 

  } 

}; 

theRip(); 

EDIT** One thing to note is that it can really mess with illustrator, for some reason, when you try to manually interact with it afterwards (continuing to run scripts works fine). For instance, if you run the above script then try to close the document it may sometimes ask you to save it even if you don't want to save it. Only way to get out of it is to save it somewhere and delete it or force quit AI.

Silly-V
Legend
September 14, 2018

I too noticed the UI issues, one time my Ai crashed - but I was testing the script all sorts of ways so I don't blame it.

Main issue I notice is that the selection doesn't show the outlines, and you sometimes have to zoom or pan a little to get a shape to gain its appearance stroke when you first draw it. To be safe after doing these tests I restarted Ai and selections behave normally.