Expand my Community achievements bar.

Guidelines for the Responsible Use of Generative AI in the Experience Cloud Community.

Help with advanced programming

Avatar

Former Community Member
I'm trying to modify the Purchase order sample PDF form that comes with Adobe Designer 7.0. I've modified the part numbers to product names ("T-shirt", "Socks", "Pants"). I'd like to show two drop-downs in the description field when I select "T-shirt" in the part number drop-down (for size and color). If I select "Pants", I'd like it to function as is, putting a description in the description field.



Secondly, I'd like to allow for quantity discounts. If someone orders more than 10 T-shirts (which can be on multiple lines), the unit price needs to change.



Is any of this possible? I'm totally lost as to where to start modifying the JavaScript. Is there a website, or book that gets into the more advanced programming aspects of the PDF interactive form?



Thanks for any help.
7 Replies

Avatar

Former Community Member
The problem with displaying not one but two drop down lists in the row when the user selects "t-shirts" from the part number drop down list is that two drop down lists require two separate cells in the table as opposed to a single one with the description field. This gets a little complicated.



One way you could keep things relatively simple is by making a copy of the detail row and giving it another name (let's say we rename the detail row to "OtherDetail" and the new (copy) to "TShirtDetail"). In the new TShirtDetail row, you would replace the description field with a drop down list for the size. You would then select the description column and use the Table Tools to insert a column into the table. This will mess-up your table layout a little bit but it should be easy to clean-up. In the end, you want an extra cell only in the TShirtDetail row (this implies you'll need to merge some of the cells on the rows above and below the TShirtDetail row). Once you've got this layout, add the second drop down list to the TShirtDetail row for the color. Finally, select the txtPartNum drop down list in the TShirtDetail row and change its type to a text field set to read-only (using the Type property on the Object palette's Value tab) with a default value of "T-Shirt". You'll also need to remove "T-Shirt" from the part number arrays in the script which populates the txtPartNum drop down list in the OtherDetail row.



At this point, you'll have two rows: One specifically for t-shirts and the other for the remaining items (socks and pants). Now you'll need to add another button next to the existing "Add Item" button which adds an instance of the OtherDetail row. This new button will be the one which adds instances of the TShirtDetail row. Don't forget to modify the Click event scripts on these "add" buttons as well as each row's "X" button and all the total fields to use the new row names: "_detail" changes to "OtherDetail" and "TShirtDetail" depending on the row, the button and the total field. Finally, using the Object palette's Binding tab, I would the initial count of each row to 1 so that an instance of each one is initially visible.



Now you should have a functioning form in which you can add and remove "other" detail and "t-shirt" detail rows except for the fact that the instance of the TShirtDetail rows don't have unit prices anymore. Fixing this will also let us apply the "bulk discount" for quantities of t-shirts above 10.



By specifying script on the Calculate event of the numUnitPrice numeric field in the TShirtDetail row, you can specify what the price is depending on the quantity of t-shirts requested. The following script will set a reduced price is the quantity ordered in more than 10:



if (numQty.rawValue > 10) // if order more than 10, give discount

this.rawValue = 19.99;

else

this.rawValue = 24.99;


Because of the way form calculations work, all other total fields should properly reflect the change in price as the quantity and price change.



This will only work for a single row, though, so the script needs to be tweaked to count the total quantity of t-shirts across all instances of the TShirtDetail row. This can be done easily by retrieving a list of all TShirtDetail row instances using the "resolveNodes" function:



var nTotalShirtCount = 0;

var oTShirtDetailList = form1.purchaseOrder.details.
resolveNodes("TShirtDetail[*]");



for (var i = 0; i < oTShirtDetailList.length; i++)



{



var oTShirtDetailRow = oTShirtDetailList.item(i);



nTotalShirtCount += (oTShirtDetailRow.numQty.rawValue != null) ? oTShirtDetailRow.numQty.rawValue : 0;



}



if (nTotalShirtCount > 10) // if order more than 10, give discount

this.rawValue = 19.99;

else

this.rawValue = 24.99;


This script gets a list of all instances of the TShirtDetail row and, for each instance, accumulates the total number of t-shirts ordered and then applies the discount accordingly.



I've attached a modified version of the Purchase Order sample which implements these changes so you can see what I'm trying to explain here.



Stefan

Adobe Systems

Avatar

Former Community Member
Wow, great stuff. Thanks for your help!!! I dug out a JavaScript book and have playing with this myself. I started out maintaining the one detail row and using visible/invisible code to show/hide the color/size dropdowns depending on what the partnum was selected. It works pretty good, but your way makes it much easier to figure the quantity discounts. The only problem is there are more products that require the color/size dropdowns (and these different products have their own color choices). I'll see if I can tweak what you have with code to accommodate the 4 other 'shirt' products. I'm wondering how you would handle this type of form if more products were this different. I would assume there would be a limit to how many different detail rows you would want.



BTW, there's an additional variable I need to add accommodate for... for one of the shirt items, if someone orders an XXL, it's +$6.00/each, and an XXXL is +$8.00/each. This is turning out to be a great exercise in learning Adobe Design. I really appreciate your example... I've learned a lot from dissecting it.

Avatar

Former Community Member
That's great news! It's always nice to know our customers are learning useful things by using these forums.



For the problem of different shirts, I think you should be able to use code similar to the way the code in the OtherDetail row works (where the description field get populated according to what's picked in the part number drop down box). What you'll need to know are the following pieces of information:



MyList.clearItems();


This will clear all items in a list (list box or drop down list). Use this to start with when there's a new selection in the "shirt type" list in order to clear-out all the size and color information for the previous shirt selection.



Then you'll need to add items to the size and/or color drop down lists and you can do that with the following script:



MyList.addItem(
text [,
value]);


In this case,
text is a string which represents the text that'll show-up for the item in the size/color drop down list whereas [,
value] represents an optional parameter which specifies the value associated to the item. If you only specify text, the text you specify also becomes the value. If you specify a value different from the text, then the value is used when data is exported/submitted from the form.



Now for the additional per-item price for XXL and XXXL shirts. You would simply add an IF statement to the Calculate script on the "item cost" field in the TShirtDetail row which checks the value of the size drop down list (following is in FormCalc, assuming a base cost of $10.00):



if (SizeList == "XXL") then

16.00

else if (SizeList == "XXXL") then

18.00

else

10.00

endif


Stefan

Adobe Systems

Avatar

Former Community Member
Hi Stefan,



Thanks for your recent reply.



I've presented your form to my client and they feel it is a bit confusing. I was wondering if there is a way to show 10 "OtherDetail" rows (eliminate the "Add T-Shirt" and "Add Other Item" buttons), then switch an "OtherDetail" row to a "TShirtDetail" if a "tshirt" PartNum is selected?

Avatar

Former Community Member
If I understand correctly, you want to remove the ability to add/remove rows and show a form with a static set of rows?



If that's the case, then the problem gets easier. The only catch is that changing from one row type to another isn't going to be trivial because in one row type, the description cell is actually split into two cells which means you'd have to modify the colSpan attribute on all the description fields on all other rows as well as replace the instance of OtherDetail with an instance of TShirtDetail.



If I've understood your new requirement correctly, then I would suggest you stop using a table. Extract the detailHeader2, OtherDetail, TShirtDetail and total rows (which are subforms) out of the table and delete the table.



Then I would wrap all subforms into a subform and make this subform's Content property (on the Object palette's Subform tab)
Flowed. This will then let you specify that a subform within this flowed container is repeatable.



Next, I would combine the OtherDetail and TShirtDetail subforms into one Detail subform where the size and color lists would initially be "invisible" and the description field visible such that when "t-shirt" is picked from the part number list, the size and color lists are made visible and the description field is made invisible.



The next step would be to modify the Calculate script on the numUnitPrice field to take into account the value selected in the part number list:



if (txtPartNum.rawValue == "t-shirt") then

// do what was on the numUnitPrice field in the TShirtDetail row

endif


Remember that when something is picked from the part number list, its unit price is assigned to the numUnitPrice field and since there aren't any exceptions for socks and pants, you don't need to do anything special for those items. Another way to do this (which would be a little "cleaner" in terms of coding) would be to not have the script on the part number list's Change event set the unit price but rather have the Calculate script on the numUnitPrice field set it accordingly for all parts (instead of just t-shirts).



Finally, I would select the combined Detail subform and make it repeatable inside its flowed container subform by using the Object palette's Binding tab to set its
Repeat Row for Each Data Item property, uncheck the Min Count restriction and set the Initial Count to 10, giving you 10 rows.



Note that you may also need to modify the Calculate scripts on the total subform in light of the changes in object hierarchy and object names.



Stefan

Adobe Systems

Avatar

Former Community Member
Confusion with Adobe Products (Adobe Reader, Acrobat, LiveCycle, Reader Extensions). What does the end user need to fill-in form and save a copy of the filled-in form to his computer? What app does my client need who is receiving the completed PDF form from the end user via the Email button?



I have built a dynamic form in LiveCycle 7.0 including some of the features discussed in this thread. Now I'm confused who needs what application to fill-in the form, and to retrieve the data on the form. I have LiveCycle and created the form for a client who does not have LiveCycle. When my client tests the form on their computer, they get part of the information filled in on the form. When I test it, everything works fine. The problem might be in the way I'm making fields visible/invisible.



If my client or end users need any addition software (extensions) to make this work, can you please provide a link to send me in the right direction. Also, is there is a better way to handle this for the end user? I don't want the end user to have to download an extension just to be able to fill-in the form. If sending it via XML, does my client need LiveCycle to read the data?



I'd like to attach the form, but how??

Avatar

Former Community Member
Yes, this can get a little confusing. Hopefully I can make sense of it all.



The key thing to remember is that the Adobe Reader doesn't let you save the form's data to the local PC -- unless you Reader-Extend the form that it's displaying, in which case "local save" can be enabled in the Reader. Another feature that's disabled in the Reader is the ability to import data into the form (so xfa.host.importData won't work in Reader 7.0.7) and again, the form can be Reader-Extended to give this ability to the user when using that specific form in Reader.



Ideally, you would design your form such that it doesn't require data to be imported when it's filled and its data is submitted via email or http. All this can be done with the free Reader without Reader Extensions. Then, upon receiving the data, your client would use Acrobat Pro to open the form and then import the submitted data into it (using the import options under the "File | Form Data" menu in Acrobat Pro).



If your client doesn't have access to Acrobat Pro, then they would need a version of the form which has been Reader-Extended so that they could use the free Reader to import data into the form -- at which point you could just distribute the Reader-Extended form to end-users and let your form require data to be imported in order to be filled.



In the end, the person filling the form only needs Acrobat. If the form requires data to be imported in order to be filled (prior to data submission), then they either need Acrobat Pro or they need a Reader-Extended form. On the receiving end of things, the client only needs either Acrobat Pro or a Reader-Extended version of the form, depending on how you go about doing things.



Hopefully this clarifies things a little.



Forum users don't have permission to attach documents to their posts. If you'd like me to have a look at your form, please send it to dev_info@adobe.com and include the subject of this thread in the email's subject. I'll make sure it's then passed-on to me.



Finally, here's the link for
Adobe LiveCycle Reader Extensions, in case you want to read-up on it.



Stefan

Adobe Systems