Line breaks not working on secondary script running from UI

Explorer ,
Apr 15, 2021 Apr 15, 2021

Copy link to clipboard

Copied

I have an issue I have encoutered a couple of times recently whereby a '\n' line break works fine in a script if it is run directly from the script menu, but if run from a palette UI I have created it returns as literal text i.e. 'Line \nBreak' rather than 'Line

Break' (see screenshots and simple code example of the script being run from the UI palette):

alert("Line \nBreak");

Does anyone know the reason for this and how I would overcome the issue?

Run_From_UI.png

Run_Direct.png

  

TOPICS
Scripting

Views

505

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct Answer

Adobe Community Professional , May 28, 2021 May 28, 2021
Hi glibshaft, try this: var alertMessage = ''' Line Break '''; alert( alertMessage ); From my German Windows 10 machine with AI 25.2.3: Regards, Uwe Laubender ( ACP )

Likes

Translate

Translate
Adobe Community Professional ,
Apr 15, 2021 Apr 15, 2021

Copy link to clipboard

Copied

I don't have a complete answer for you, but i can say that when you run code from a UI Panel, things get wonky. I think you need to pass the information through BridgeTalk in order to get the expected output. I've never sat down and tried to figure out bridgetalk, so i don't have any specific advice. But hopefully that'll at least give you a good jumping off point for finding the answer you need. 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Apr 15, 2021 Apr 15, 2021

Copy link to clipboard

Copied

For doing more powerful Palette functions (or as you may think of it, doing them as a normal person would expect- you pass the script in and it should just work as usual, no added funny-business, right?) - you have to go ahead and hide the string's stuff that BridgeTalk messes with or doesn't work well with, by encoding them.
Thanks to Bob Stucky.

  function bridgeTalkEncode(txt) {

    /* thanks to Bob Stucky */

    txt = encodeURIComponent(txt);

    txt = txt.replace(/\r/, "%0d");

    txt = txt.replace(/\n/, "%0a");

    txt = txt.replace(/\\/, "%5c");

    txt = txt.replace(/'/g, "%27");

    return txt.replace(/"/g, "%22");

  };

 

 

  function bridgeTalkDecode(txt) {

    return txt.replace(/%0d/g, "\r").replace(/%0a/g, "\n").replace(/%5c/g, "\\").replace(/%27/g, "'").replace(/%22/g, '"');

  };

 

 

https://community.adobe.com/t5/illustrator/how-can-i-read-the-color-of-a-given-pixel-in-an-image/m-p/9353278

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 15, 2021 Apr 15, 2021

Copy link to clipboard

Copied

Thanks for this, I will take a look.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Apr 15, 2021 Apr 15, 2021

Copy link to clipboard

Copied

I have spent countless hours effing around with why my BridgeTalk was doing these types of things in 2014, so once I found an old post featuring this code from Bob Stucky, I remain forever grateful to the great Bob Stucky.
Other people may have found this sooner and it would have been no-big-deal. But me, I pulled my hair out and was close to barking at people - so regarding this issue you'll always find me heaping praises on none other than.. Bob Stucky!

 

I tried the link but it's not working even though it works: https://community.adobe.com/t5/illustrator/how-can-i-read-the-color-of-a-given-pixel-in-an-image/m-p...

Maybe I need to edit the post if my paste did that.
But here's the code which uses the function, notice for some reason I never used the decode function except the simple decodeURI.

    meat = bridgeTalkEncode(meat);

    btMsg = "var scp ='" + meat + "'";

    btMsg += ";\nvar scpDecoded = decodeURI( scp );\n";

    if (typeof resultFunc == "function") {

      btMsg += "btResult = eval( scpDecoded );";

    } else {

      btMsg += "eval( scpDecoded );";

    }

    bt.body = btMsg;

    if (typeof resultFunc == "function") {

      bt.onResult = function(info) {

        info = JSON.parse(info.body);

        resultFunc(info);

      };

    }

    bt.onError = function(res) {

      alert(res.body);

    };

    bt.send();

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 15, 2021 Apr 15, 2021

Copy link to clipboard

Copied

So, excuse my ignorance, but how would I go about applying this to the onclick function in my UI and my secondary script? (see below for my current onclick function):

  var scriptLoc = File($.fileName).path;
var scriptToLoad = new File (scriptLoc + "/Sub_Code/Create_Line_Break_Text.jsx/")

    scriptToLoad.open ("r");
    var message = scriptToLoad.read();
    scriptToLoad.close()

var scriptPath = File($.fileName).path;
var bt = new BridgeTalk();
bt.target = "Illustrator";
bt.body = message;
bt.send();

And my current secondary script to run from the UI:

alert("Line \nBreak");

 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Apr 15, 2021 Apr 15, 2021

Copy link to clipboard

Copied

I say, use it by wrapping your scriptToLoad.read() call in it.

 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 16, 2021 Apr 16, 2021

Copy link to clipboard

Copied

Thanks for the suggestion, to be honest, I got a little lost with how to do this and have tried all sorts to get it to work but can't seem to get it to work as I need.

 

I did however add an interim script that then launches the line break script from the UI that seems to works (the only down side is that as I am using the 'execute()' command I have had to set my final script to open into Illustrator by default). See codes below:

 

UI onClick function:

var scriptLoc = File($.fileName).path;
var scriptToLoad = new File (scriptLoc + "/Sub_Code/LaunchLineBreak.jsx/")


    scriptToLoad.open ("r");
    var message = scriptToLoad.read();
    scriptToLoad.close()

var scriptPath = File($.fileName).path;
var bt = new BridgeTalk();
bt.target = "Illustrator";
bt.body = "var SCRIPT_LOCATION = \"" + scriptPath + "\"" + message;
bt.send();

 

Interim script:

var fileLocation = (typeof(SCRIPT_LOCATION) == "string")? SCRIPT_LOCATION : $.fileName;
var f = fileLocation + "/Sub_Code/CreateLineBreakText.jsx";
var file1 = File(f);
file1.execute();

 

Final script:

alert("Line \nBreak");

I am still interested as to how I would actually wrap my scriptToLoad.read() call in my onClick function to eliminate the interim script. Sorry to be a pain but could you elaborate on how I would go about that?

Many thanks in advance for your hugely helpful advise.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Apr 21, 2021 Apr 21, 2021

Copy link to clipboard

Copied

Yea, I'll try to make a snippet soon.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Apr 26, 2021 Apr 26, 2021

Copy link to clipboard

Copied

As promised, check this out:

 

#target illustrator
#targetengine main // <--- IMPORTANT: turns out, BridgeTalk.onResult is USELESS without the #targetengine

function test () {

	function bridgeTalkEncode (txt) {
		txt = encodeURIComponent (txt);
		txt = txt.replace( /\r/, "%0d" );
		txt = txt.replace( /\n/, "%0a" );
		txt = txt.replace( /\\/, "%5c" );
		txt = txt.replace(/'/g, "%27");
		return txt.replace(/"/g, "%22"); 
	};

	function sendBasicBT (targetApp, scriptCode, resultFunc) {
		var bt = new BridgeTalk();
		bt.target = targetApp;

		var btMsg = "var scp ='" + bridgeTalkEncode( scriptCode ) + "';\n";
		btMsg += "var scpDecoded = decodeURI( scp );\n"; 
		btMsg += "res = eval( scpDecoded );";
	
		bt.body = btMsg;
		bt.onError = function (e) {
			alert("BT Error:\n" + e.body);
			if (typeof resultFunc != "undefined") {
				resultFunc(e.body);
			}
		}
		if (typeof resultFunc != "undefined") {
			bt.onResult = function (msg) {
				alert(msg.body);
				var myResult = msg.body;
				resultFunc(myResult);
			}
		}
// alert(btMsg);
		bt.send();
	};

	// NORMAL STRING: note the double-escape backslashes.
	// var myStringScript = "alert('Line \\n break'); 'ABCDEF!';";

	var myScriptCode = function btTest () { alert('Line \n break'); return 'ABCDEF!'; };
	var myScriptToSend = myScriptCode.toString() + "\nbtTest()"; // <--- create the result return variable here.

	var doc = app.activeDocument;

	var completionFunc = function (btResult) {
		alert("Hello back in Illustrator, the result was:\n" + btResult);
		postCompletionFunc();
	}

	function postCompletionFunc () {
		alert("But the fun doesn't stop here, we go on and on doing stuff back in Illustrator");
	}

	// When sending a simple string.
	// sendBasicBT("photoshop", myStringScript, completionFunc);

	// When sending a function:
	sendBasicBT("photoshop", myScriptToSend, completionFunc);

};
test();

 

 

Turns out, BT is a gift that just keeps on giving. For instance, I discovered that I nearly accidentally (may have forgotten) had it working the whole time. But when I tried to make this, it wasn't working until I inserted the #targetengine directive.

 

So, in the snippet here we have two ways of sending the message and it takes special consideration for how you treat those nextlines. For a simple script string you must double-escape all the stuff you don't want to have the "\" show up. You may be able to maybe do new String() to auto-do this I am not sure.
But for things which are a function in your code-file, you can forego this (use .toString() which automatically does string-escaping) and simply make sure you add the function's call at the end of the message.
For items ran from a separate file which can be activated as a stand-alone piece of code even when not used via BT, I think just reading the entire text and using the encoding/decoding URI methods will work just like the function-call message, but you won't have to add the function call at the bottom as it is likely to already be there.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
May 17, 2021 May 17, 2021

Copy link to clipboard

Copied

Hi, me again. I have been playing around with this sode you sent but I fear I may have not been clear in what I was asking.

I was using the alert function as an example of the line break. In reality, I actually need the final script to create me a text frame with prepopulated text (rather than just an alert).

 

The following is actually what I need, the first script is the onclick function of my UI (just launches a script to create the text frame wich is shown in the second snippet). How would I go about sending the 'bridgeTalkEncode' function to the second script that creates the text frame (and how would I go about having the second script understand to decode the hard return? 

UI onclick:

var scriptLoc = File($.fileName).path;
var scriptToLoad = new File (scriptLoc + "/Sub_Code/Test.jsx/")


    scriptToLoad.open ("r");
    var message = scriptToLoad.read();
    scriptToLoad.close()

var scriptPath = File($.fileName).path;
var bt = new BridgeTalk();
bt.target = "Illustrator";
bt.body = "var SCRIPT_LOCATION = \"" + scriptPath + "\"" + message;
bt.send();

 

2nd script to create text frame:

 

      var doc = app.activeDocument;
      var object1 = doc.textFrames.add();
      object1.contents = 'Line \n break';


I appreciate I have asked a lot of questions on this but just can't seem to get my head around it. Many thanks in advance.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
May 17, 2021 May 17, 2021

Copy link to clipboard

Copied

Do this:

		var btMsg = "var scp ='" + bridgeTalkEncode( message ) + "';\n";
		btMsg += "var scpDecoded = decodeURI( scp );\n"; 
		btMsg += "res = eval( scpDecoded );";
		bt.body = btMsg;
		

The "message" is going to be the script content you obtained with a File.read().

Alternatively you can engineer the strings to contain the string "eval('#include path/to/script.jsx')" and then you won't have to do a file-read, probably avoiding all encoding issues of the code content.
The utility of the bridgeTalkEncode function is using encodeURIComponent/encodeURI which converts the nextlines among other things to masked character groups which represent a nextline. Thus the string is being sent as plaintext to places where a multi-line text would not work, and then the decodeURI() function in the string sent via above snippet re-births the string content from URI-encoded entities to their regular representation.
Another really important note is that while my snippet in the thread above says:

	function postCompletionFunc () {
		alert("But the fun doesn't stop here, we go on and on doing stuff back in Illustrator");
	}

This function produces an alert in Illustrator, but it actually has no access to the Illustrator DOM. This means that any code that runs inside here can't do anything to an open document without having an error, but it can be used to interact with your palette and change text in it for such purposes and showing a log of what just happened.
If for some reason you also wanted to run another Illustrator script after such a message script is ran, you have to put another BridgeTalk call, this time to Illustrator itself (as in my example I was using Photoshop), essentially repeating the same technique as your first call. So basically the onResult functions which can be called from a message call you sent from a palette can only work for that palette or other ScriptUI palettes which may be placed by other scripts.. 
 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
May 26, 2021 May 26, 2021

Copy link to clipboard

Copied

Hi, sorry, I got no notification of your message and have only just checked back now. I will take a look tomorrow. Thanks for all your help on this so far. I will post back to let you know how I get on. Thanks.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
May 27, 2021 May 27, 2021

Copy link to clipboard

Copied

Got it to work, brilliant, thank you so much, but I have one further question.

 

How would I add in the BT message to look for a file loction that you helped me out with in this thread 'https://community.adobe.com/t5/illustrator/script-losing-path-when-run-from-another-script/m-p/11852... ("var SCRIPT_LOCATION = \"" + scriptPath + "\"" + message)?

In short, I need the BT message to incorporate both the file path and the line breaks together. I have tried the following (and many other variants) but with no luck;

 

UI script:

CreateLineBreakText.onClick = function(){
aiscriptE2 ();
}

function aiscriptE2() {
function bridgeTalkEncode (txt) {
  txt = encodeURIComponent (txt);
  txt = txt.replace( /\r/, "%0d" );
  txt = txt.replace( /\n/, "%0a" );
  txt = txt.replace( /\\/, "%5c" );
  txt = txt.replace(/'/g, "%27");
  return txt.replace(/"/g, "%22");
};

var scriptLoc = File($.fileName).path;
var scriptToLoad = new File (scriptLoc + "/Sub_Code/Test.jsx/")


    scriptToLoad.open ("r");
    var message = scriptToLoad.read();
    scriptToLoad.close()

var scriptPath = File($.fileName).path;
var bt = new BridgeTalk();
bt.target = "Illustrator";
var btMsg = "var scp ='" + bridgeTalkEncode( message ) + "';\n";
btMsg += "var scpDecoded = decodeURI( scp );\n";
btMsg += "res = eval( scpDecoded );\n";
btMsg += "var SCRIPT_LOCATION = \"" + scriptPath + "\"";// + message;
bt.body = btMsg;
bt.send();
//alert(btMsg)
}

 

second script:

function1A()

function function1A() {
var fileLocation = (typeof(SCRIPT_LOCATION) == "string")? SCRIPT_LOCATION : $.fileName;
var address1 = fileLocation + "/Sub_Code/Lockup_Elements/Portrait_Lockup.ai";
var file1 = File(address1);
file1 = open(file1);
}

      var doc = app.activeDocument;
      var object1 = doc.textFrames.add();
      object1.contents = 'Line\nbreak';

 

 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
May 27, 2021 May 27, 2021

Copy link to clipboard

Copied

You can add it as a parameter to the 'message' if your BT message is a function-declaration only or if it comes with a function call at the end: use string replacing to add in the text-form of the function call with a baked-in parameter.

There's an issue with backslashes in the BT message string concerning the parsing of JSON for which you will need to replace all \\ with \\\\ so that windows file paths do not cause JSON parsing issues. It may work OK as is if you're not using JSON at this time though or aren't using backslashes in the file paths (using the file.toString() vs file.fsName on Windows).

Suppose you have this as your stand-alone script:

 

/*
function MyScript (parentScriptFilePath) {
  ...
  IF parentScriptFilePath is good THEN
  Do the action that is controlled by the parent calling script, featuring this file path.
  ELSE...
  Do the stand-alone action,
  ...
}
MyScript();
*/

 

Then in your function that creates the BT message, you replace the last line using string replacing:

  1. txt = txt.replace("MyScript();", "");
  2. txt = txt + "\nMyScript('" + File($.fileName).path + "')";

 

And if your child script is simply a function declaration, 
Do almost the same thing, you just don't have to do the replacing.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
May 28, 2021 May 28, 2021

Copy link to clipboard

Copied

Hi glibshaft,

try this:

var alertMessage = 
'''
Line
Break
''';

alert( alertMessage );

 

From my German Windows 10 machine with AI 25.2.3:

AlertWithTrippleFencingString.PNG

 

Regards,
Uwe Laubender

( ACP )

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 01, 2021 Jun 01, 2021

Copy link to clipboard

Copied

Hi, this solution seems to work for me. I still want to investigate Silly-V's way of doing it, but for now this is a perfectly workable solution for my issue.

Thanks to eveyone for there help on this.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 01, 2021 Jun 01, 2021

Copy link to clipboard

Copied

LATEST

*their

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines