Copy link to clipboard
Copied
Hello everyone,
Thanks to those have helped me so far.
New question, I have a script which has some parameters which can be changed but they are parameters which ought hardly ever to be changed. This is for InDesign
So I would prefer for the user not to have to face a dialogue box everytime they run it.
Can you prevent a dialogue box appear if they run it from shortcut? and only appear if run from the script menu?
Many thanks all,
Best,
Smyth
Copy link to clipboard
Copied
Hmm, don't think so. But you can write the prefs to a txt file in the same folder as the script, and have the values autopopulate in the panel. Then they could just hit OK, or adjust the parameters if needed (and you can write the new prefs back to the pref file).
Copy link to clipboard
Copied
It seems they can.
Ive managed to get the script when clicked to prompt a box in which the user can change parameters
and when they run the shortcut no parameter box comes up
it is reading to a json files which seems insane, as when the user inputs data it holds it in the json file and then that data is used if they use the shortcut
surely indesign can hold user data itself without having to use external json files etc
Copy link to clipboard
Copied
This code
used to work - this is later version which is even more destroyed
however it does correcrly record user parameters to the json file
there as a time the script would allow for users to input data
and then on the shortcut running the script it would just do defult
// JSON polyfill
#targetengine "jsonPolyfill" // This avoids polluting the global namespace
// Include the JSON polyfill library
$.evalFile("C:\\Users\\user\\Desktop\\json2.js"); // Replace with the actual path to the json2.js file
// Initialize settingsFile as a File object
var settingsFile = new File("C:\\Users\\user\\Desktop\\rule_settings.json");
// Check if the script was invoked via a shortcut key
var invokedViaShortcut = false;
if (ScriptUI.environment.keyboardState.ctrlKey || ScriptUI.environment.keyboardState.altKey) {
invokedViaShortcut = true;
}
// Declare user-defined variables
var userDefinedAmountTop = 0;
var userDefinedAmountBottom = 0;
// Function to save user-defined settings
function saveUserSettings() {
var settings = {
top: userDefinedAmountTop,
bottom: userDefinedAmountBottom
};
// Save settings to the settingsFile
settingsFile.open("w");
settingsFile.write(JSON.stringify(settings));
settingsFile.close();
}
// Function to load user-defined settings
function loadUserSettings() {
if (settingsFile.exists) {
settingsFile.open("r");
var settingsData = settingsFile.read();
settingsFile.close();
var settings = JSON.parse(settingsData);
userDefinedAmountTop = settings.top;
userDefinedAmountBottom = settings.bottom;
}
}
// Load user-defined settings when not invoked via shortcut
if (!invokedViaShortcut) {
// Create a dialog box to input user-defined values
var dialog = app.dialogs.add({ name: "Enter Values" });
with (dialog) {
// Add a dialog column
with (dialogColumns.add()) {
// Add fields to input user-defined values
staticTexts.add({ staticLabel: "User-defined Amount Top:" });
var topInput = measurementEditboxes.add({ editValue: userDefinedAmountTop });
staticTexts.add({ staticLabel: "User-defined Amount Bottom:" });
var bottomInput = measurementEditboxes.add({ editValue: userDefinedAmountBottom });
// Remove unit values from user input fields
topInput.editUnits = MeasurementUnits.POINTS;
bottomInput.editUnits = MeasurementUnits.POINTS;
}
}
// Display the dialog box
if (dialog.show() == true) {
userDefinedAmountTop = topInput.editValue;
userDefinedAmountBottom = bottomInput.editValue;
// Save user-defined settings
saveUserSettings();
} else {
alert("Please select at least two text frames.");
}
dialog.destroy(); // Close the dialog after processing
} else {
// Load user-defined settings
loadUserSettings();
// Sort selected text frames by their horizontal position
selectedFrames.sort(function(a, b) {
return a.geometricBounds[1] - b.geometricBounds[1];
});
// Wrap the script in an undoable action
app.doScript(function() {
// Iterate through the sorted selected text frames
for (var i = 0; i < selectedFrames.length - 1; i++) {
var currentFrame = selectedFrames[i];
var nextFrame = selectedFrames[i + 1];
// Check if the frames are on the same page
if (currentFrame.parentPage === nextFrame.parentPage) {
// Calculate the center position for the vertical rule
var centerX = (currentFrame.geometricBounds[3] + nextFrame.geometricBounds[1]) / 2;
// Calculate the height of the rule (same as the height of the taller object)
var ruleHeight = Math.max(
currentFrame.geometricBounds[2] - currentFrame.geometricBounds[0],
nextFrame.geometricBounds[2] - nextFrame.geometricBounds[0]
);
// Determine the starting and ending heights for the rule
var startHeight = Math.max(
currentFrame.geometricBounds[2],
nextFrame.geometricBounds[2]
);
var endHeight = Math.min(
currentFrame.geometricBounds[0],
nextFrame.geometricBounds[0]
);
// Adjust the start height for the line based on the user-defined amount
var adjustedStartHeight = startHeight + userDefinedAmountBottom;
var adjustedEndHeight = endHeight - userDefinedAmountTop;
// Create a new line
var newLine = currentFrame.parentPage.graphicLines.add();
newLine.paths[0].entirePath = [
[centerX, adjustedStartHeight],
[centerX, adjustedEndHeight]
];
// Send the line to the back
newLine.sendToBack();
}
}
}, ScriptLanguage.JAVASCRIPT, [], UndoModes.ENTIRE_SCRIPT, "Add Vertical Lines Between Text Boxes");
}
Copy link to clipboard
Copied
You can write the data to app.label and read that label using app.extractLabel, but what's wrong with writing to file?
Copy link to clipboard
Copied
Like @brian_p_dts, I'm a big fan of writing to script settings to file(s). That keeps them accessible/inspectable but you can still keep them right out of sight (eg. if stored in the userData folder).
- Mark
Copy link to clipboard
Copied
Can you prevent a dialogue box appear if they run it from shortcut? and only appear if run from the script menu?
You could have two different scripts saved in the panel, one with a dialog and another with the default values and no dialog, then assign 2 different keyboard shortcuts—e.g. Command-A no dialog, or Command-Option-A show dialog.
Copy link to clipboard
Copied
Rob's suggestion is a very good one. You put all your logic in "script file A". If you run "script file A" then the script runs using existing settings (json?). Then you make a UI/editor script—"script file B". If you run "script file B" it shows a UI, then runs "script file A" with those settings, and (optionally) saves the new settings to the json file that is read by "script file A".
- Mark
Copy link to clipboard
Copied
Hello Rob and Mark,
I do like this idea, two files - one with the script which provides funtionality - another which is an interface to paramerters. Both scripts access JSON one writes the other reads.
I would like to give this a shot also - I feel like this should work quite easliy without tearing up much the origional script.
The amusing part is that the script works perfectly fine, just would be easlier for users not to have to adjust via opening the file and editing - although once set users ought not to need to change but users will be users
Thanking you kindly.
Smyth
Copy link to clipboard
Copied
You can also use Extendscript’s XML object to get and set dialog values. Here the last used values are saved in the script’s parent folder—if the XML file doesn’t exist one is wrtten with the values set as 0:
//this script’s folder
var f = File($.fileName).parent + "/defaults.xml";
//if there’s no XML set a default
var xml = readXML(f)
if (xml == "") {
xml = XML( "<dialog><values><top>0</top><bottom>0</bottom></values></dialog>")
}
//get the top and bottom values from XML
//will be 0 if an xml file does not exist
var tv = Number(xml.values.top);
var bv = Number(xml.values.bottom);
var t, b;
makeDialog();
function makeDialog(){
var d = app.dialogs.add({name:"Enter Values", canCancel:true});
with(d.dialogColumns.add()){
staticTexts.add({staticLabel:"User-defined Amount Top:"});
staticTexts.add({staticLabel:"User-defined Amount Bottom:"});
}
with(d.dialogColumns.add()){
t = measurementEditboxes.add({editUnits:MeasurementUnits.POINTS, editValue:tv, minWidth:50});
b = measurementEditboxes.add({editUnits:MeasurementUnits.POINTS, editValue:bv, minWidth:50});
}
if(d.show() == true){
//get the edit values
t = t.editValue;
b = b.editValue;
//update defaults.xml with the entered dialog values
xml.values.top = t;
xml.values.bottom = b;
writeXML(f, xml.toXMLString());
//run main script
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Set Dimensions');
d.destroy();
}
}
/**
* The main script
*/
function main(){
alert("Dialog values:\r" + t + "\r" +b)
$.writeln(xml)
//returns the updated xml text
//do something...
}
/**
* Write an XML file
* @ param the file path
* @ param the xml text
* @ return void
*/
function writeXML(p,s){
var file = new File(p);
file.encoding = 'UTF-8';
file.open('w');
file.write(s);
file.close();
}
/**
* Read an XML file
* @ param the file path
* @ returns an XML object
*/
function readXML(p) {
var f = new File(p);
f.open("r");
var t = f.read();
f.close();
return XML(t);
}
First run result:
Next run dialog:
Copy link to clipboard
Copied
Wow, thank you.
I will give this a shot to see how it works,
Thank you,
Smyth
Copy link to clipboard
Copied
Hi @SmythWharf, maybe holding alt key would be a viable solution? - Mark
var value = 34;
var altKey = ScriptUI.environment.keyboardState.altKey;
if (altKey) {
// call your UI here
value = prompt('Enter the number: ', value);
}
if (value !== null)
alert('The number is ' + value + '.');
Copy link to clipboard
Copied
Hello,
Many thanks for the replys.
Mark very nice concept - I wille explore this seems like it could cutdown a lot of code plus extra files.
Best,
Smyth