Copy link to clipboard
Copied
I was referred to @Peter Kahrel excellent tutorial on ScriptUI located here https://creativepro.com/files/kahrel/indesign/scriptui.html, but I am having a few issues with my scripts:
w.input = w.group.add ('edittext {characters: 10, active: true, justify: "right"}');​
I don't see where "characters: 10" is explained. I thought it would limit the input to 10 characters, but it does not seem to, either in his example or in my testing. Is there a way to do this? One of my input fields needs to be 7 characters and one of them needs to be 8 character date in format YYYYMMDD.
win.Panel2.txt2.onChanging = function () {
var valid = /^[\d]+$/.test (win.Panel2.txt2.text);
this.graphics.backgroundColor = this.graphics.newBrush (this.graphics.BrushType.
SOLID_COLOR, valid ? [1, 1, 1, 1] : [1, 0.5, 0.5, 1]);
win.Panel2.ApplyBtn.enabled = valid && win.Panel2.txt2.text.length=7;
}​
win.Panel2.txt3.onChanging = function () {
var valid = /^[\d]+$/.test (win.Panel2.txt3.text);
this.graphics.backgroundColor = this.graphics.newBrush (this.graphics.BrushType.
SOLID_COLOR, valid ? [1, 1, 1, 1] : [1, 0.5, 0.5, 1]);
var valid2 = Date.parse(win.Panel2.txt3.text);
win.Panel2.ApplyBtn.enabled = !valid2==NaN;
}​
I'll probably have more questions as I get further into my script, and I'll add them to this thread, if that is okay.
(The forum gave me an error about invalid HTML that it removed, but I'm not seeing what it changed).
Thanks in advance!
= is used to assign a value to a variable.
== and === test equality. === is used for strict equality, which means that the two items you compare must be the same type. == is for looser comparisons. == is slower because it tries to coerce the two items into type-equality.
Example:
var a = 5;
var b = '5';
a == b; // => true
a === b // => false
a is a number, b is a string. Strict comparison returns false because the variables are not the same type. Loose comparison returns true, it successfu
...Playing with text then textselection, in that order, may solve the cursor issue in EditText widgets. That's a bit of black magic so I do not guarantee the universality of the following code:
// . . .
// Your UI components (w, w.input, etc)
// . . .
// Predeclare brushes
var gx = w.input.graphics;
var BH =
[
gx.newBrush(gx.BrushType.SOLID_COLOR, [1.0, 0.5, 0.5, 1]), // KO
gx.newBrush(gx.BrushType.SOLID_COLOR, [1.0, 1.0, 1.0, 1]) // OK
];
// Text changing handle
...
@Marc Autret (or others)
Funny how things work - or maybe not if you are religious!!! Anyway, I was getting really frustrated and typed up a long post. I hit preview and walked away from my computer and never posted it. I couldn't see the forest for the trees, but I solved the problem!!!
This will be a long post, but it should help some people.
The main problem I was having had to do with "partially valid" regex. I have enough trouble coming up with "fully valid" regex - although I think I have t
...
Sorry I don't understand your code 😕 I'm afraid I've already detailed everything I can say about my own approach, so the code below basically just repeats the same logic.
Some advice to prevent infinite loops and other errors: Keep your objects encapsulated, only play with text/textselection once (and only if needed!), do not take the risk of reintroducing a changing event while you modify the text, do not resolve again the EditText instance (it is and remains this within t
...Copy link to clipboard
Copied
Figured out the first issue:
win.Panel2.ApplyBtn.enabled = valid && win.Panel2.txt2.text.length=7;
needs to be:
win.Panel2.ApplyBtn.enabled = valid && win.Panel2.txt2.text.length==7;
Double == before the 7
Copy link to clipboard
Copied
Ran into a hiccup with the date. Date.parse() will not work for me. 20230523 is valid and what I want, but 05232023 is also valid, but NOT compatible for my purposes. There is code further up the page that should work, but it doesn't seem to work with ScriptUI/ESTK.
Copy link to clipboard
Copied
I figured out the date validation code and posted it in the other thread related to this:
Copy link to clipboard
Copied
> I don't see where "characters: 10" is explained.
Well, the PDF has an index, which has an entry for 'characters' and guides you to p. 11, where it says:
> The characters property is used to set the control’s width
The control's width is not the same as the number of characters that you can enter in the control, but I'll agree with you that there's room for confusion here.
You can monitor what's entered into a control ('field'), there are some examples of that in the PDF.
> But I don't want the apply button enabled unless the field has seven characters
Take a look at this script: https://creativepro.com/files/kahrel/indesign/grep_query_manager.html
There's an option to save a configuration as a preset. The interface has two buttons: Save and Cancel. While you're typing a preset name, if what you type matches an existing preset, the Save button's text changes to Replace. It's in the function getValidName
> I'll probably have more questions as I get further into my script, and I'll add them to this thread, if that is okay.
Absolutely!
Copy link to clipboard
Copied
Here's a sample of how to enable a button only when a text field's content has a certain length:
w = new Window ('dialog');
w.field = w.add ('edittext {characters: 10, active: true}');
w.button = w.add ('button {text: "Apply"}');
w.field.onChanging = function () {
w.button.enabled = w.field.text.length === 7;
}
w.show();
You'd probably need to set the burron's state when the script is started, but I didn't add that here because the field might be populated from a history file.
(But I now see that you already fixed it. Mustard after the meal. Sorry.)
P.
Copy link to clipboard
Copied
Actually, stupid question time ...
I've done much more in Visual Basic, thus =7 seemed logical to me. I changed it to ==7 and that worked. You said ===7.
What are the differences and when would I use either one?
Copy link to clipboard
Copied
= is used to assign a value to a variable.
== and === test equality. === is used for strict equality, which means that the two items you compare must be the same type. == is for looser comparisons. == is slower because it tries to coerce the two items into type-equality.
Example:
var a = 5;
var b = '5';
a == b; // => true
a === b // => false
a is a number, b is a string. Strict comparison returns false because the variables are not the same type. Loose comparison returns true, it successfully coerces the variables into the same type (string or number, I don't know which).
Because strict comparison evaluates considerably quicker you should use it where you can. Especially in InDesign's DOM, when you test some enumeration repeatedly. For example
if (myPage.side === PageSideOptions.LEFT_HAND) {
is considerably quicker than
if (myPage.side == PageSideOptions.LEFT_HAND) {
If you don't know whether the two items to be compared are type-compatible, use ==
Copy link to clipboard
Copied
Excellent explanation - like I said, my main background is Visual Basic, which is only one "=" sign and the equivalent of "==" would be a type mismatch error.
Copy link to clipboard
Copied
Okay - this is what I have so far:
var w = new Window ('dialog');
// First attempt - allows more than 7 Characters.
w.group = w.add ('group');
w.group.add ('statictext {text: "Enter a 7-Digit number:"}');
w.input = w.group.add ('edittext {characters: 10, active: true, justify: "right"}');
w.buttons = w.add ('group {alignment: "right"}');
w.ok = w.buttons.add ('button {text: "OK", enabled: false}');
w.buttons.add ('button {text: "Cancel"}');
w.input.onChanging = function () {
var valid = /^[\d]+$/.test (w.input.text);
this.graphics.backgroundColor = this.graphics.newBrush (this.graphics.BrushType.
SOLID_COLOR, valid ? [1, 1, 1, 1] : [1, 0.5, 0.5, 1]);
w.ok.enabled = valid && w.input===7;
}
w.show();
It works fairly well - if you put anything other than a digit, it turns red, if you have more or less than 7 characters, OK is not enabled.
What I ideally want:
Field starts with "XXXXXXX". I will add a clear button that empties the field. I want cut and paste to work, but I only want to allow digits in the field (and probably delete or backspace). If the user types "A", I don't want an "A" and red background, I just want the input ignored, and I don't want more than 7 characters, if the field text is already 7 characters, I want the input ignored.
There were some helpful answers here, but https://stackoverflow.com/questions/2808184/restricting-input-to-textbox-allowing-only-numbers-and-d... but the most elegant seemed to be:
var validNumber = new RegExp(/^\d*\.?\d*$/);
var lastValid = document.getElementById("test1").value;
function validateNumber(elem) {
if (validNumber.test(elem.value)) {
lastValid = elem.value;
} else {
elem.value = lastValid;
}
}
But I wasn't sure how to implement it - or if I had to be using the keyboard input value or the onchanging value.
Thanks in advance!!!
Copy link to clipboard
Copied
Something I thought would be easy...
I started with a previous script that I had written which had panel 1 above panel 2. For this script, I would like to have panel1 on the left side of the window and Panel 2 next to it on the right. I would prefer the window to auto-size.
I thought this would work:
var win = new Window("palette", "My Window:"); // bounds = [left, top, right, bottom]
win.radioPanel = win.add("panel", [5, 10, 230, 90], "Panel 1");
win.Panel2 = win.add("panel", [235, 10, 505, 230], "Panel 2");
win.show();
But it still shows Panel 1 above Panel 2.
This works:
var win = new Window("palette",'MyWindow:', [15, 45, 525, 300]); // bounds = [left, top, right, bottom]
win.radioPanel = win.add("panel", [5, 10, 230, 90], "Panel 1");
win.Panel2 = win.add("panel", [235, 10, 505, 230], "Panel 2");
win.show();
But if I use this, I think ideally, I need to figure out which screen is running FM, what the resolution of that screen is, set left to 1/2 screen width - 1/2 window width, set top to 1/2 screen heigth - 1/2 window height, etc.
Is there a simpler way?
Copy link to clipboard
Copied
Somewhat clunky, but:
//var win = new Window("palette",'MyWindow:', [15, 45, 525, 300]); // bounds = [left, top, right, bottom]
var win = new Window("palette",'MyWindow:', [$.screens[0].right/2 - 253,$.screens[0].bottom/2 - 127, $.screens[0].right/2 + 253, $.screens[0].bottom/2 + 127]); // bounds = [left, top, right, bottom]
//var win = new Window("palette", "My Window:"); // bounds = [left, top, right, bottom]
win.radioPanel = win.add("panel", [5, 10, 230, 90], "Panel 1");
win.Panel2 = win.add("panel", [235, 10, 505, 230], "Panel 2");
win.show();
Works for single-screen or dual-monitor if FrameMaker is on screen 1. (Otherwise, it will show the dialog on Screen 1.) If I could figure out how to tell which screen has the active document, I could use that in the code and it would work.
Copy link to clipboard
Copied
See https://community.adobe.com/t5/framemaker-discussions/determine-screen-number-of-active-document/m-p... - for the sizing - at least the clunky method ...
Copy link to clipboard
Copied
See https://community.adobe.com/t5/framemaker-discussions/determine-screen-number-of-active-document/m-p... - for the sizing - at least the clunky method ...
Does not work. I need to know how to display the window on Screen 2 but only if FM is on Screen 2.
Copy link to clipboard
Copied
If you want to design and visual see the dialog. I recommend the website made by joonas. He has made a scriptui website in which you can drag and drop components and instantly see the design
Its a huge time saver and also returns very clean code.
Ive been using it now for couple years and it has taken out that slow peocess of testing and checking dialog design
Copy link to clipboard
Copied
Thank you! - really cool site!!!
Copy link to clipboard
Copied
Its si easy and fast now ti make the dialogs. Its godsend tool. Really big props to joonas
Copy link to clipboard
Copied
I tried to implement the StackOverflow solution. Logically, it makes sense to me. If you type a valid character, it stores the field text in the lastValid variable. If you add a valid character, it increases that variable. If you type an invalid character, it replaces the field with the last valid content - basically it deletes the character you just input.
The issue I am having is lastValid becomes undefined, and I'm not sure why. Here is what I have so far:
// Attempt to limit input.
w.group = w.add ('group');
w.group.add ('statictext {text: "Enter a 7-Digit number Anything other than a numeral will be ignored:"}');
w.input = w.group.add ('edittext {characters: 10, active: true, justify: "right"}');
w.clear = w.group.add ('button {text: "Clear"}');
w.buttons = w.add ('group {alignment: "right"}');
w.ok = w.buttons.add ('button {text: "OK", enabled: false}');
w.buttons.add ('button {text: "Cancel"}');
w.input.text="XXXXXXX"
var lastValid = w.input.text;
alert(lastValid); // returns XXXXXX
w.input.onChanging = function (lastValid) {
alert(lastValid); // returns undefined
w.ok.enabled = false;
var valid = /^[\d]+$/.test (w.input.text)&& w.input.text.length===7;
this.graphics.backgroundColor = this.graphics.newBrush (this.graphics.BrushType.
SOLID_COLOR, valid ? [1, 1, 1, 1] : [1, 0.5, 0.5, 1]);
w.ok.enabled = valid;
alert(lastValid); // returns undefined
var valid2 = /^[\d]+$/.test (w.input.text)&& w.input.text.length<7;
if (valid2){
alert("valid2");
lastValid = w.input.text;
alert(lastValid); // Returns field contents
}
else{
alert("Not valid2");
w.input.text = lastValid; // changes field contents to undefined
}
}
w.clear.onClick = function(){
var valid = /^[\d]+$/.test (w.input.text) && w.input.text.length===7;
if (valid){
if (confirm("Do you want clear the input field") ===false) {
return;
}
}
w.input.text = "";
}
w.show();
Initially, I have lastValid defined in the onChanging event function, but then it was updating whether the input was valid or not, so it didn't work.
Hopefully, someone sees a typo above, but otherwise, I'm going to look into keypress events, and then give up on this.
Copy link to clipboard
Copied
Took a brute force approach. Again, what I am looking for is anything other than a number is ignored, and once 7 characters are reached, any input is ignored.
New Code:
var w = new Window ('palette');
// Secong Attempt to limit input.
w.group = w.add ('group');
w.group.add ('statictext {text: "Enter a 7-Digit number Anything other than a numeral will be ignored:"}');
w.input = w.group.add ('edittext {characters: 10, active: true, justify: "right"}');
w.clear = w.group.add ('button {text: "Clear"}');
w.buttons = w.add ('group {alignment: "right"}');
w.ok = w.buttons.add ('button {text: "OK", enabled: false}');
w.buttons.add ('button {text: "Cancel"}');
w.input.onChanging = function (lastValid) {
w.ok.enabled = false;
var valid = /^[\d]+$/.test (w.input.text)&& w.input.text.length===7;
this.graphics.backgroundColor = this.graphics.newBrush (this.graphics.BrushType.
SOLID_COLOR, valid ? [1, 1, 1, 1] : [1, 0.5, 0.5, 1]);
w.ok.enabled = valid;
var valid2 = /^[\d]+$/.test (w.input.text)
if (!valid2){
// https://stackoverflow.com/questions/27772805/need-a-regex-to-remove-everything-except-numbers
w.input.text = w.input.text.replace(/\D+/g, "");
// https://stackoverflow.com/questions/596481/is-it-possible-to-simulate-key-press-events-programmatically
w.input.dispatchEvent(new KeyboardEvent('keydown', {'key': 'End'})); // Keyboard Event does not have a constructor.
}
var valid3 = w.input.text.length<7;
if (!valid3){
w.input.text =w.input.text.substring(0,7);
}
}
w.clear.onClick = function(){
var valid = /^[\d]+$/.test (w.input.text) && w.input.text.length===7;
if (valid){
if (confirm("Do you want clear the input field") ===false) {
return;
}
}
w.input.text = "";
}
w.show();
What this does:
If you type anything other than a number, the code deletes the non-numeric items. If you add numbers after the length is 7, the code returns the first 7 characters. If I could simulate pressing the "End" key, it would work fine.
Unfortunately, it moves the cursor back to the beginning after it does the replacement - for example:
If I could simulate sending the end key or moving the cursor to the end of the field, it should work.
Copy link to clipboard
Copied
I'm not JS expert and definitely not on InDesign's ScriptUI implementation - prefer VB6 - but from quick googling - javascript textfield cursor position - there is a selectionStart and selectionEnd for text fields in JS:
http://help.dottoro.com/ljtfkhio.php
Supported by objects:
HTML elements:
input:password, input:search, input:text, isindex, textarea
Or even more:
TextRange.moveEnd(): It helps to move the end of the range by a specified number of units.
TextRange.moveStart(): It moves the start of the range by a specified number of units.
Copy link to clipboard
Copied
Thanks, Robert, but those properties aren't available in ScriptUI.
Copy link to clipboard
Copied
Could i ask what OS you are using?
I remember i believe seeing this work on OSX. Ive now tried your examples on Windows and the input editText simply does not change color. I bumped into this after research the ScriptUI for Dummies PDF by Kahrel
Copy link to clipboard
Copied
I'm using Windows 10 Enterprise Version 22H2 and it works for me in FrameMaker 2019 and FrameMaker 2022. Note that I don't have access to InDesign, so I can't verify whether or not it works in that application.
Copy link to clipboard
Copied
Ah i see, in photoshop 21 and 23 it doesnt work for the text highlight. Like @Marc Autret states, i was wondering perhaps its an OSX thing where it still works.
Also tried Illustrator, there the input show white, but does not turn red on errors
Copy link to clipboard
Copied
Thanks for testing and clarifying. I remember previous comments that is was no longer supported and was pleased to see it still works in FrameMaker.
Hopefully, Adobe will re-enable it in the other programs, but I'm not holding my breath. (Hopefully that's re-conditionalize paragraph tags in FrameMaker like it used to have in FM 11, but that hasn't happened so far either - OT).