Oddity in Javascript map object

New Here ,
Jan 07, 2019

Copy link to clipboard

Copied

I'm using the javascript map object and its not working as expected. I searched the forum for any issues with the map object, but found nothing. The relevant javascript documentation is here. I created a form with javascript at the Page Level. The javascript uses an iterable literal for initialization:

this.myMapIterable = [ [ "002", { "code": "002", "rate": 0.0165 } ], ];

this.myMap = new Map(this.myMapIterable);

I shortened myMapIterable to one entry, but in the original there are over 50 entries. The length of the iterable does not present itself as an issue. Given the above code one would expect that getting an entry, using the following code, would produce the associated object:

this.myMap.get("002");

The above, should according to the Javascript documentation, produce the object:

{ "code": "002", "rate": 0.0165 }

Unfortunately, it doesn't. What I get is undefined!? I been battling this issue for the past day. Playing around in the Javascript debugger, I have found that the Acrobat implementation of Javascript makes a distinction between how a string is quoted. I'm not sure why since the Javascript documents points out in the note just above here​, that there is no difference between a single quoted string or a double quoted string. If I change the code to the following:

this.myMapIterable = [ [ '002', { 'code': '002', 'rate': 0.0165 } ], ];

this.myMap = new Map(this.myMapIterable);

and then also do:

this.myMap.get('002');

then, finally I get:

{ 'code': '002', 'rate': 0.0165 }

However, if I change the above myMap.get() to:

this.myMap.get("002");

then, I get undefined!?

This makes no sense to me given the Javascript documentation. Further, I tried both versions in NodeJS and both work as expected, regardless of which quotes were used for either myMapIterable and those used in the myMap.get(). Mixing and matching in NodeJS just works and it seems to be in line with the Javascript documentation, IMHO.

Does anyone have a reason for this behavior in Acrobat DC and do you concur on my reading of the Javascript documentation and how things work in NodeJS?

TOPICS
Acrobat SDK and JavaScript, Windows

Views

112

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

Oddity in Javascript map object

New Here ,
Jan 07, 2019

Copy link to clipboard

Copied

I'm using the javascript map object and its not working as expected. I searched the forum for any issues with the map object, but found nothing. The relevant javascript documentation is here. I created a form with javascript at the Page Level. The javascript uses an iterable literal for initialization:

this.myMapIterable = [ [ "002", { "code": "002", "rate": 0.0165 } ], ];

this.myMap = new Map(this.myMapIterable);

I shortened myMapIterable to one entry, but in the original there are over 50 entries. The length of the iterable does not present itself as an issue. Given the above code one would expect that getting an entry, using the following code, would produce the associated object:

this.myMap.get("002");

The above, should according to the Javascript documentation, produce the object:

{ "code": "002", "rate": 0.0165 }

Unfortunately, it doesn't. What I get is undefined!? I been battling this issue for the past day. Playing around in the Javascript debugger, I have found that the Acrobat implementation of Javascript makes a distinction between how a string is quoted. I'm not sure why since the Javascript documents points out in the note just above here​, that there is no difference between a single quoted string or a double quoted string. If I change the code to the following:

this.myMapIterable = [ [ '002', { 'code': '002', 'rate': 0.0165 } ], ];

this.myMap = new Map(this.myMapIterable);

and then also do:

this.myMap.get('002');

then, finally I get:

{ 'code': '002', 'rate': 0.0165 }

However, if I change the above myMap.get() to:

this.myMap.get("002");

then, I get undefined!?

This makes no sense to me given the Javascript documentation. Further, I tried both versions in NodeJS and both work as expected, regardless of which quotes were used for either myMapIterable and those used in the myMap.get(). Mixing and matching in NodeJS just works and it seems to be in line with the Javascript documentation, IMHO.

Does anyone have a reason for this behavior in Acrobat DC and do you concur on my reading of the Javascript documentation and how things work in NodeJS?

TOPICS
Acrobat SDK and JavaScript, Windows

Views

113

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
Jan 07, 2019 0
Adobe Community Professional ,
Jan 07, 2019

Copy link to clipboard

Copied

If you're using Acrobat, which version are you using, exactly? If you're using something other than Acrobat, what is 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
Reply
Loading...
Jan 07, 2019 0
New Here ,
Jan 07, 2019

Copy link to clipboard

Copied

I'm using Acrobat Pro DC.

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
Reply
Loading...
Jan 07, 2019 0
Adobe Community Professional ,
Jan 07, 2019

Copy link to clipboard

Copied

The following works for me as the Mouse Up script for a button:

var myMapIterable = [

    ["002", {"code" : "002", "rate" : 0.0165} ]

];

var myMap = new Map(myMapIterable);

console.println(myMap.get("002"));

Where did you place the code you showed earlier?

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
Reply
Loading...
Jan 07, 2019 0
Most Valuable Participant ,
Jan 07, 2019

Copy link to clipboard

Copied

You should be aware this code won't work with earlier versions of Acrobat (or Reader), as the Map object is not supported there.

I recommend you don't use it if you want your file to work correctly in older versions, too. Or at the very least add a warning in case the file is opened in such an older version.

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
Reply
Loading...
Jan 07, 2019 0
Adobe Community Professional ,
Jan 07, 2019

Copy link to clipboard

Copied

Is there a reason for using the Map object over just a plain object?  The only reason I can see for this object is predictable ordering.  If you just want an iterable thing, then the Object.keys() function provides an easy way to iterate over the object using the array functions.

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
Reply
Loading...
Jan 07, 2019 0
New Here ,
Jan 07, 2019

Copy link to clipboard

Copied

It was placed at the Page Level, Page Open event.

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
Reply
Loading...
Jan 07, 2019 0
Adobe Community Professional ,
Jan 07, 2019

Copy link to clipboard

Copied

I'll have to do some more testing, but I have a few more general comments.

For code that you want to execute when the document is opened, it's better to place it in a document-level JavaScript. Using a page open event can cause problems in a multipage document if the code is executed again when the page is opened again.

Also, this:

this.myVariable = 1;

is supposed to be equivalent to:

var myVariable = 1;

in a page open or document-level script, outside of a function definition.

For code in a PDF, the "this" object will usually point to the document that it resides in, but not necessarily of course. It depends on the specific code/context. If you want to create a variable that's global to the document, I think it's better to use the var statement, but mostly for readability and ease of understanding. It's worth a try in your case to see if it makes any difference.

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
Reply
Loading...
Jan 07, 2019 1
New Here ,
Jan 07, 2019

Copy link to clipboard

Copied

BTW, using Acrobat Pro DC 2019.010.20069

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
Reply
Loading...
Jan 07, 2019 0
New Here ,
Jan 08, 2019

Copy link to clipboard

Copied

Thank you for your replies. A little history to understand "Why don't you do it this way..." Our IT department currently has a crisis and the persons whom normally modify the Acrobat forms are handling the crisis. I was asked to step in to get it done. I'm not an Acrobat developer, novice at best. I do use JSON and Javascript occasionally and would consider my skills as intermediate.

Why a Map Object vs. a plain Object? My understanding of the Map Object vs a plain Object is that a Map Object retains order of insertion and allows multiple keys with the same value. As far a I can see order of insertion isn't an issue, but I'm not sure about multiple keys with the same value. I'll investigate whether this is a requirement for the rest of the Javascript in the form to work correctly. IF not, then perhaps a rewrite could be done, although I'm not tasked with rewriting the code, only updating and correcting issues. #politics

Why this vs var and page vs document level? Original code used this as opposed to var. I did read in the SDK that these are equivalent in the situation George_Johnson​ mentions. If best practice is to use var instead of this, it seems like a reasonable change to make. The original code had the code in my original post at the document level. Since it wasn't working, I moved it to the page level to see whether that made a difference, it didn't. My further investigation found the issue I posted about. I think based on George_Johnson​ comments, I'll move it back to the document level now that I have an understand of why it's not working.

Backward compatibility: try67 noted that using the Map Object is not backward compatible, true, but if I were to use a plain Object as suggested neither is Object.keys(), Object.values() and the existing code also uses .filter(), so while backward compatibility was be nice, it seems like a significant effort would be needed, I could be wrong, suggestions welcome. I do like the suggestion about adding a warning in case the form is opened in an earlier version, but I'm struggling to see how that could be accomplished. I can use an app.alert() on the Page Open event, but I don't see an app.version or something that would give me the version. I'm researching this further, any pointers or suggestions would be helpful.

Thanks again for your suggestions and comments.

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
Reply
Loading...
Jan 08, 2019 0
try67 LATEST
Most Valuable Participant ,
Jan 08, 2019

Copy link to clipboard

Copied

You can use app.viewerVersion to return the current version number of the application.

Personally, I would not use JS features that don't work in earlier versions, unless the environment is highly controlled and you can guarantee that only the newer versions are used, or if those features are really necessary. Using a Map object is handy, but there are plenty of ways around using it that offer a similar functionality with simpler objects.

If this file is going to be used publicly you're just going to create for yourself extra problems down the road, I guarantee it. You'll end up having to do the same work twice, or constantly get complaints about your code not working in someone's (somewhat) older version.

But the decision is yours, of course...

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
Reply
Loading...
Jan 08, 2019 0