Search This Blog

Sunday, 5 May 2013

Adding Ghost Text to LiveCycle Designer form

Problem

Ghost Text is a common way of adding instruction text to a web form, especially if space is tight, but Designer has no built in support.

Solution

Using a null category picture clause and some JavaScript we can achieve a similar effect.

Detailed explanation

Below is an example of ghost text in a form, if the field is empty and has not been selected then we want some information text displayed (in a lighter color and in italics). If the field is selected then we want the information text cleared so the user can enter their response.



In the ready:form event for this field there is the following statements which just set the initial state of the field; (Note: I originally had this code in the initialize event, but as Joe McGloin pointed out in his comments below this does not fire when a Reset button is clicked).

this.execEvent("exit");
this.format.picture.value = "null{'" + this.assist.toolTip.value + "'}";


The trick to this whole approach is setting the format.picture.value to "null{ some text }" which causes Reader to display the some text whenever the field is null/empty. In this example I am displaying the text from the toolTip for the field but this could be any text.

In the enter event I change the font to black and normal posture so it looks like a regular text field once the user starts typing into it.

this.fontColor = "0,0,0";
this.font.posture = "normal";
   
In the enter event I change the font to black and normal posture so it looks like a regular text field once the user starts typing into it. 

In the exit event I change font back to grey, italic if the field is null so it looks like help text. This is also called from the initialize event to set the fields state initially.

if (this.isNull)
{
      this.fontColor = "153,153,153";
      this.font.posture = "italic";
}


There is some more code in the prePrint and postPrint events so the instruction text doesn't get printed out.

this.format.picture.value = "";

And then after printing setting it back;

this.format.picture.value = "null{'" + this.assist.toolTip.value + "'}";

Note: this method will only work on dynamic forms.

I have also added an example to the sample form of using proto elements to define the scripts required for this once and have the fields just reference the script. This requires editing the form in the XML Source view but does save duplicating the script. A proto field can be created by dragging a field from the Hierarchy view to the "Referenced Object" node, make a copy of the field first as this drag is a move not a copy. Once under the "Referenced Object" node it can be renamed and references to it (or parts of it) can be made from the "use" attribute which is common to all elements in the template. So now we can go into the XML Source view and add the following lines to refer to the required scripts.

<event use="protoGhostText.event__enter"/>
<
event use="protoGhostText.event__exit"
/>
<
event use="protoGhostText.event__prePrint"
/>
<
event use="protoGhostText.event__postPrint"
/>
<
event use="protoGhostText.event__form_ready"/>


Download sample, GhostText.pdf.


7 comments:

  1. Hi,

    this is a great idea, but I've noticed that the method above makes problems when it's applied on other forms.
    You'll propably will see an exception like: "Bad value: 'protoGhostText.event__form_ready' of the 'use' attribute of 'event' element ''. Default will be used instead.".
    It's because of the used reference syntax for the use attribute, which is not supported by XFA.
    At runtime it won't be a problem so far (ecept an exception when the form is opened), because the XFA processor will propably find the prototype somewhere within the template, but if you check the report tab in Designer it will be full of errors.

    There is a recommended way to reference prototypes by using XML IDs.

    Therefore you need to add a unique XML ID to each event in the XML source.

    < event activity="enter" name="event__enter" id="ghostEnter">
    ...

    To reference that script element in the prototype you only need to add a # followed by the XML ID in the ref attribute.

    < event use="#ghostEnter"/>

    ;-)

    ReplyDelete
  2. Hi Radzmar,

    I'm guessing you are using Designer ES3 (or later) and have added some Styles to your form. Designer ES3 broke a lot of my forms (at least at design time). Maybe because we end up with two proto elements, however I have not been able to reproduce the particular problem you describe. I got the idea of using proto elements from this blog, http://blogs.adobe.com/lcdesigner/2008/07/hyphenation_under_the_hood_huh.html which has a little more about using proto's.

    Still you fix is probably better, that does seem to be the approach they have taken with the samples in the XFA spec.

    I'll update the sample here.

    ReplyDelete
  3. I have tried the above on my form and while the font changes from grey to black, everything is displayed in the caption of the text field and not in the "value" where I would like the help text to appear. Any ideas on what might the problem be?

    ReplyDelete
  4. Hi,

    I can't think what could cause that, maybe if I could see the form. Can you post a comment with a link to your form?

    ReplyDelete
  5. That was very useful. Thank you so much.

    ReplyDelete
  6. The proto object is working fine with me. I am trying to use Javascript to set the use attribute during the initialization event, this will allow me to programmatically apply proto object which will save a lot of time. I applied "use" attribute for the tooltip part using XML, and it worked. But, when I tried to modify the "use" attribute on initialize event, I got this error: "Bad value: 'protoGhostText.assist.toolTip' of the 'use' attribute of 'toolTip' element ". Default will be used instead."
    Any idea on this?

    ReplyDelete
  7. what would be really handy for us dummies is the exact script I need to type in the script editor once I have the text.field selected in my form, eg

    }

    inthis.field.display <<"Enter the Data">>
    make.its.font <>
    and.its.font <>
    cleartheText.whenField=Selected

    }

    the font format for whatever is typed in the field would be whatever was set in the Font platelette.

    ReplyDelete