• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Immediate change to Text Field's character limit?

Engaged ,
Mar 23, 2016 Mar 23, 2016

Copy link to clipboard

Copied

I have a PDF form that I am trying to make more foolproof. As a user enters their credit card number, I want it to check the first two digits to see which kind of card it is (Visa/MasterCard/American Express) and select the appropriate radio button for them, as well as limit the number of digits that can be entered in that credit card number field. I have it mostly figured out, but it seems that changing the character limit (charLimit) of the Card Number field doesn't actually take place until the focus leaves the field, then re-enters it. Here's the code I have so far, in the Custom Keystroke Script property on the Format tab of that field:

event.rc = /^\d*$/.test(event.change);

var thisField = event.target;

var amexTest = /^3[47]/;

var mcTest = /^5[1-5]/;

var visaTest = /^4/;

var firstTwo = event.value.slice(0,2);

var ccButtons = getField("Credit Card Buttons");

if (amexTest.test(firstTwo)) {

    thisField.charLimit = 15;

    ccButtons.value = "AMEX";

} else if (mcTest.test(firstTwo)) {

    thisField.charLimit = 16;

    ccButtons.value = "Master Card";

} else if (visaTest.test(firstTwo)) {

    thisField.charLimit = 19;

    ccButtons.value = "Visa";

}

It looks like my pasted code got a little cut off toward the end for some reason, but I think that's enough to show what I want to have happen. Because this script runs at every keystroke, then after the first two characters are typed, I want it to limit the number of characters to what is appropriate for that type of card. This should help a bit in having people mis-type their number. However, as I said, the change doesn't actually take place until the focus leaves and re-enters that field.

What can I do to make the change immediate?

TOPICS
Acrobat SDK and JavaScript

Views

1.3K

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

Community Expert , Mar 23, 2016 Mar 23, 2016

I don't think you can't do it like that, but you don't need to. Since you're already using a script for the Keystroke event you can check the length of the full text and then reject the keystroke if it's too long.

Votes

Translate

Translate
Community Expert ,
Mar 23, 2016 Mar 23, 2016

Copy link to clipboard

Copied

I don't think you can't do it like that, but you don't need to. Since you're already using a script for the Keystroke event you can check the length of the full text and then reject the keystroke if it's too long.

Votes

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
Engaged ,
Mar 23, 2016 Mar 23, 2016

Copy link to clipboard

Copied

Okay, I see where you are going with this, but I'm having trouble figuring out the exact line of code that would be necessary for it. I'm close with this:

event.rc = event.value.length < 15 || !/^[\w\s]*$/.test(event.change);

Placing that in the if (amexTest.test(firstTwo)) condition, after the ccButtons.value = "AMEX"; line doesn't quite seem to work. Neither the [DELETE] nor [BACKSPACE] keys work once the limit has been reached. Also, when the focus changes away from the field, the entire field is emptied. Definitely not what I want. I'm sure I have to find some way of using event.willCommit, but I do not know how. Thoughts?

Votes

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
Community Expert ,
Mar 23, 2016 Mar 23, 2016

Copy link to clipboard

Copied

You need to use AFMergeChange(event) to get access to the full new value of the field. event.value will only return the value before the current keystroke, which is not what you want. I'm also not sure about your regular expression. What are you trying to do there, exactly?

Votes

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
Engaged ,
Mar 23, 2016 Mar 23, 2016

Copy link to clipboard

Copied

I'll have to research AFMergeChange(event). In the mean time, I actually got it all working as I wanted it to, by simply adding together .value and .change, thusly:

var digitsOnly = /^\d*$/;

event.rc = digitsOnly.test(event.change);

var thisField = event.target;

var amexTest = /^3[47]/;

var mcTest = /^5[1-5]/;

var visaTest = /^4/;

var allText = event.value + event.change;

var firstTwo = allText.slice(0,2);

var ccButtons = getField("Credit Card Buttons");

if (amexTest.test(firstTwo)) {

    ccButtons.value = "AMEX";

    event.rc = (allText.length <= 15 && digitsOnly.test(event.change)) || !/^[\w\s]*$/.test(event.change);

} else if (mcTest.test(firstTwo)) {

    ccButtons.value = "Master Card";

    event.rc = (allText.length <= 16 && digitsOnly.test(event.change)) || !/^[\w\s]*$/.test(event.change);

} else if (visaTest.test(firstTwo)) {

    ccButtons.value = "Visa";

    event.rc = (allText.length <= 19 && digitsOnly.test(event.change)) || !/^[\w\s]*$/.test(event.change);

}

if (!event.rc) {

    app.beep();

}

As for the regex in each case, the idea is to filter out all keystrokes once the character limit has been reached except for the delete or backspace keys. Thus allowing for the text to be replaced in case the user typed in the wrong number and needs to change it. It may not be necessary anymore now that I've added in the digitsOnly test, but I've run out of time today to find out. Perhaps tomorrow. Thanks for your help, try67‌!

Votes

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
Community Expert ,
Mar 23, 2016 Mar 23, 2016

Copy link to clipboard

Copied

This is a built-in, undocumented function that merges the old value with the new one correctly. You should use it instead of your makeshift version of it because it handles deletions, insertions in all locations, pasting text and other kinds of edits correctly.

Votes

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
Engaged ,
Mar 24, 2016 Mar 24, 2016

Copy link to clipboard

Copied

Sounds nice, but I'm afraid it breaks everything. When I replace the line

var allText = event.value + event.change;

with

var allText = AFMergeChange(event);

And click [OK], my Custom Formatting and Keyboard scripts disappear entirely: The Select format category dropdown changes from Custom to None, so my scripts are lost.

Even if I just put that phrase in a comment, such as

// AFMergeChange(event);

The dropdown changes to None when I hit [OK].

Votes

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
Community Expert ,
Mar 24, 2016 Mar 24, 2016

Copy link to clipboard

Copied

This is unfortunately how Acrobat works: if it recognizes certain internal names, it assumes (wrongly) that the JavaScript was generated by you using one of the predefined formats. The way around this is to create a document level function that calls the AF... function (this is not just limited to AFMergeChange), and then call that document level function from your format or keystroke event handler.

Votes

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
Engaged ,
Mar 24, 2016 Mar 24, 2016

Copy link to clipboard

Copied

LATEST

Sheesh, so many nuances to Acrobat that I never knew of. Undocumented functions that are better than hand-written ones, making assumptions and erasing days of work without so much as a warning. What a mess.

Nevertheless, your suggestion did work, khkremer‌, thank you. I now have a document script:

function getMergedText(event) {

    return AFMergeChange(event);

}

To go along with my form field's script:

var digitsOnly = /^\d*$/;

event.rc = digitsOnly.test(event.change);

var thisField = event.target;

var amexTest = /^3[47]/;

var mcTest = /^5[1-5]/;

var visaTest = /^4/;

var allText = getMergedText(event);

var firstTwo = allText.slice(0,2);

var ccButtons = getField("Credit Card Buttons");

if (amexTest.test(firstTwo)) {

    ccButtons.value = "AMEX";

    event.rc = allText.length <= 15 && digitsOnly.test(event.change);

} else if (mcTest.test(firstTwo)) {

    ccButtons.value = "Master Card";

    event.rc = allText.length <= 16 && digitsOnly.test(event.change);

} else if (visaTest.test(firstTwo)) {

    ccButtons.value = "Visa";

    event.rc = allText.length <= 19 && digitsOnly.test(event.change);

} else if (allText.length < 1) {

    ccButtons.value = null;

}

if (!event.rc) {

    app.beep();

}

I also have added in a format script so when the user changes focus to a different field, the credit card number is automatically formatted to look a tad nicer:

event.value = event.value.slice(0,4)

                + " " + event.value.slice(4,8)

                + " " + event.value.slice(8,12)

                + " " + event.value.slice(12);

And lastly, make sure the three radio buttons next to the credit card choices are emptied when the document is opened (unless a card number exists, of course):

if (getField("Card Number").value.length < 1) {

    getField("Credit Card Buttons").value = null;

}

And that's it! Yeah, it's probably a bit kludgy and could be coded more efficiently, but at least it works, thanks to your help! Now I just need to decide who gets the credit for the "Correct Answer." :~)

Votes

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