VoiceXML

 

Handling Events Page 4 of 6

VoiceXML places events in two categories - pre-defined events and application-defined events. Pre-defined events are events thrown by the Platform and are divided into two subcategories - normal events and error events. Application-defined events are custom events that are both thrown and caught by the voice application. Application-defined events are discussed later in this document.

Pre-defined normal events

The following table describes the pre-defined normal events defined in the VoiceXML 2.0 specification.

help Thrown when the user requests help.
noinput Thrown within an interactive call state when the user has said nothing within the timeout period.
nomatch Thrown when the user utters something outside the active grammars.
telephone.disconnect.hangup Thrown when the user disconnects or is disconnected. Post Hang-up Processing is limited to 5 seconds. If you need to do extensive processing, your event handler should execute a submit to your Web server to perform any additional processing.
cancel Thrown when the user has requested the current prompt be canceled.
exit Thrown when the user has asked to exit.
maxspeechtimeout Thrown when the user input exceeded the 'maxspeechtimeout' property.
telephone.disconnect.transfer Thrown when the user has been transferred unconditionally to another line and will not return.

Pre-defined error events

The following table describes pre-defined error events defined in the VoiceXML 2.0 specification:

error.semantic Thrown when the VoiceXML interpreter detects a run-time error.
error.badfetch Thrown when an HTTP request for a VoiceXML document, external grammar, or external script fails. If the VoiceXML document that required the fetch contains semantic errors, the badfetch event is thrown to the container element that attempted to navigate to the document.
error.noauthorization Thrown when the user is not authorized to perform the requested operation.
error.unsupported.format Thrown when the requested resource is in an unsupported format.
error.unsupported.language Thrown when the Platform doesn't support the specified language.
error.unsupported.element Thrown when the Platform doesn't support the given VoiceXML element.

Handling events

To handle events, use the catch element and set the event attribute to the name of the desired event. For example, the following nomatch handler plays some audio and then listens for user input:

<catch event="nomatch">
  <audio>I'm sorry. I didn't get that. 
     Please say the name of a sport. 
     For example, say baseball.
  </audio>
</catch>

To handle the common pre-defined events - help, noinput, and nomatch - the VoiceXML specification defines corresponding elements with the same names to make it easier for the VoiceXML developer. For example, the following noinput handler plays some audio to the user and then replays the prompt:

<noinput>
   <audio>I'm sorry. I didn't hear you</audio>
   <reprompt/>
</noinput>

To handle different events with the same handler, delimit each event name with a space in the event attribute of the catch element. For example, the following code defines an event handler for a noinput and nomatch event.

<catch event="nomatch noinput">
  <audio>I'm sorry. I didn't get that. 
     Please say the name of a sport. 
     For example, say baseball.
  </audio>
</catch>

Understanding event handler selection

In the previous section you learned that the VoiceXML interpreter executes an event handler whose name matches that of the event that was thrown. This is an oversimplified explanation. The interpreter uses a number of additional criteria when selecting an event handler. These include:

When considering the event handler selection process, construct a list of potential handlers for the event, apply one criterion at a time, and cross the handlers off the list that do not meet the current criteria. After applying all criteria, select the first event handler still on the list. That's the event the VoiceXML intepreter would execute. If the list is empty, you should modify your code to include a handler for the unhandled event.

The following sections discuss each of the criteria in detail.

Understanding event scoping

In the introductory section on handling events, you learned to declare a handler within a field element to catch events such as a noinput or a nomatch. The field defines an anonymous scope, and the event handler has access to all the variables, scripts, and data declared within that scope in addition to those scopes defined by containing elements including the form also known as dialog scope, the vxml element also known as document scope, and the application root document also known as application scope. In addition to defining variables, scripts, and data at dialog, document, and application scope, you can also define event handlers at these scopes. When the VoiceXML interpreter begins the event handler selection process, it considers the handlers defined within the current anonymous scope as well as the outer containing scopes.

The following example defines a noinput event handler at application scope. If the user says nothing within the default timeout in response to the prompt, the VoiceXML interpreter gathers the event handlers at the anonymous scope defined by the fruit field, the dialog scope defined by the get_fruit dialog, the document scope defined by the vxml element in "fruit.vxml", and the application scope defined by the vxml element in "app_root.vxml." The interpreter executes the event handler at application scope for lack of discovering a qualified event handler from a more immediate scope. Observe that the event handler has access to both the variable ex defined at dialog scope as well as the function SayEx defined at document scope.

<!-- app_root.vxml -->
<vxml version="2.0">
<noinput>
  <audio>Sorry. I couldn't hear you.</audio>
  <audio>Say the name of a fruit.</audio>
  <script>SayEx(ex);</script>
</noinput>

</vxml>

<!-- fruit.vxml -->
<vxml version="2.0" application="app_root.vxml"> <!-- doc scope -->

<script>
function SayEx(s) {return "For example, say " + s;}
</script>

<form id="get_fruit"> <!-- dialog scope -->
   <var name="ex" expr="apple"/>
   <field name="fruit"> <!-- anonymous scope -->
      <prompt>Pick a fruit</prompt>
      <grammar src="fruits.gsl"/>
      <filled>
         <audio>You picked <value expr="fruit"/></audio>
      </filled>
   </field>
</form>
</vxml>

Later when you learn about an event handler's count attribute, the definition of event handlers at different scopes will take on more relevance.

Understanding default platform behavior

The Tellme VoiceXML interpreter defines the following default event-handling behavior:

"Help" When the user utters, "Help," the Platform responds with the recorded audio "I'm sorry, no help is available" and executes a reprompt. You can override this behavior by providing your own helpevent handler. Because the Platform provides a default link for the utterance "help", you no longer need to explicitly include "help" in your grammars or a help link.
nomatch When a nomatch event occurs, the Platform responds with the recorded audio "I'm sorry, I didn't get that." and executes a reprompt.
noinput When a noinput event occurs, the Platform responds with the recorded audio "I'm sorry, I didn't hear you." and executes a reprompt..

Because the VoiceXML interpreter defines this behavior at session scope, your application can override this behavior at anonymous, dialog, document, or application scope. While these default event handlers will get you up and running, Tellme recommends that you override the default Platform behavior in your application in order to provide your users with the best possible user experience.

Understanding document source order

You can define more than one handler for an event at the same or at different scopes. As described above, when selecting the most qualified handler for an event, the VoiceXML interpreter not only considers the scope of the handler but also considers the order in which the event handler occurs compared to other event handlers within the same scope. This ordering is referred to as document source order. The count and cond attributes notwithstanding, if two handlers at the same scope catch the same event, the VoiceXML interpreter will select the first handler it encounters in document source order.

The following example implements two noinput handlers at the anonymous scope defined by the field element. When a noinput event occurs, the VoiceXML interpreter selects the first of these. The second handler will never get executed.

<vxml version="2.0"> <!-- doc scope -->
<form id="get_fruit"> <!-- dialog scope -->
   <var name="ex" expr="apple"/>
   <field name="fruit"> <!-- anonymous scope -->
   <prompt>Pick a fruit</prompt>
   <grammar src="fruits.gsl"/>

   <noinput>
     <audio>Sorry. I couldn't hear you.</audio>
     <reprompt/>
   </noinput>

   <noinput>
     <audio>Sorry. I still couldn't hear you.</audio>
     <reprompt/>
   </noinput>

   <filled>
      <audio>You picked <value expr="fruit"/></audio>
   </filled>
   </field>
</form>
</vxml>

In the next sections when you learn about the count and cond attributes, you'll see the usefulness of defining multiple event handlers.

Understanding the count attribute

An effective voice application takes notice if the user is experiencing trouble in a particular dialog. Trouble can be detected by the application if the Platform throws multiple nomatch, noinput, or help events in a single dialog. Rather than repeating the same information, the application can assist the user by varying the prompts played by these respective handlers.

The VoiceXML interpreter keeps track of the number of times an event is thrown within any form item or menu and allows you to implement distinct handlers for each occurrence of the event. You do so by setting the count attribute on your event handler. Each time an event executes, the VoiceXML interpreter selects the event handler that has the highest count less than or equal to the current count for that event.

Event counts are reset under the following circumstances:

If you do not specify an explicit count attribute for a handler, the default is one. If you implement multiple handlers for an event, you should specify the count attribute on each handler explicitly with a unique value. If the VoiceXML interpreter encounters multiple qualifying handlers with the same count value, it will only execute the first one it encounters in document source order within the same scope with further precedence dictated by increasing scope.

The following example implements multiple nomatch and noinput handlers for a dialog. Because the handlers exist at the same scope, the event handler selection process is simple as demonstrated by the following sample transcript.

A sample transcript for this example follows:

Tellme: Okay, now pick a fruit. (aka prompt count=1)
Caller: (noinput)
Tellme: I'm sorry. I didn't hear you. (aka noinput count=1)
Tellme: Please say the name of a fruit. For example, say banana. (aka prompt count=2)
Caller: softball
Tellme: I'm sorry. I didn't get that. (aka nomatch count=1)
Tellme: Please say the name of a fruit. For example, say banana. (aka prompt count=2)
Caller: cat
Tellme: I'm sorry. I still didn't get that. (aka nomatch count=2)
Tellme: Please say the name of a fruit. For example, say banana. (aka prompt count=2)
Caller: apple
Tellme: You chose apple.

<vxml version="2.0">
  <form id="get_fruit">
    <field name="fruit">

    <prompt count="1">
      <audio>Okay, now pick a fruit.</audio>
    </prompt>

    <prompt count="2">
      <audio>Please say the name of a fruit. For example, say
      banana.</audio>
    </prompt>

    <grammar src="fruits.gsl" />

    <nomatch count="1">
      <audio>I'm sorry. I didn't get that.</audio>
      <reprompt />
    </nomatch>

    <nomatch count="2">
      <audio>I'm sorry. I still didn't get that.</audio>
      <reprompt />
    </nomatch>

    <nomatch count="3">
      <audio>I'm sorry. I'm having trouble understanding. Type the
      first few letters of the fruit. Press pound when you're
      done.</audio>
    </nomatch>

    <nomatch count="4">
      <exit />
    </nomatch>

    <noinput count="1">
      <audio>I'm sorry. I didn't hear you.</audio>
      <reprompt />
    </noinput>

    <noinput count="2">
      <audio>I'm sorry. I still didn't hear you.</audio>
      <reprompt />
    </noinput>

    <noinput count="3">
      <goto next="_home" />
    </noinput>

    <filled>
       <audio>You chose <value expr="fruit"/></audio>
    </filled>
    </field>
  </form>
</vxml>

The next example adds some complexity to the previous example by moving the noinput handler with a count of three and the nomatch handler with a count of four to application scope. When the third noinput or fourth nomatch occurs, the user is returned to the Platform's main menu. Rather than repeating this standard behavior in every dialog throughout the application, it makes sense to define them once in the application root document. As described in the previous section, the VoiceXML interpreter considers these as part of the standard event handler selection process.

<!-- app_root.vxml -->
<vxml version="2.0">
    <nomatch count="4">
      <goto next="_home" />
    </nomatch>

    <noinput count="3">
      <goto next="_home" />
    </noinput>
</vxml>

<vxml version="2.0" application="app_root.vxml">
  <form id="get_fruit">
    <field name="fruit">

    <prompt count="1">
      <audio>Okay, now pick a fruit.</audio>
    </prompt>

    <prompt count="2">
      <audio>Please say the name of a fruit. For example, say
      banana.</audio>
    </prompt>

    <grammar src="fruits.gsl" />

    <nomatch count="1">
      <audio>I'm sorry. I didn't get that.</audio>
      <reprompt />
    </nomatch>

    <nomatch count="2">
      <audio>I'm sorry. I still didn't get that.</audio>
      <reprompt />
    </nomatch>

    <nomatch count="3">
      <audio>I'm sorry. I'm having trouble understanding. Type the
      first few letters of the fruit. Press pound when you're
      done.</audio>
    </nomatch>

    <noinput count="1">
      <audio>I'm sorry. I didn't hear you.</audio>
      <reprompt />
    </noinput>

    <noinput count="2">
      <audio>I'm sorry. I still didn't hear you.</audio>
      <reprompt />
    </noinput>

    <filled>
       <audio>You chose <value expr="fruit"/></audio>
    </filled>
    </field>
  </form>
</vxml>

Understanding the cond attribute

As part of the event handler selection process, the VoiceXML interpreter evaluates the cond attribute of an event handler at the time the event is fired to determine if it should be used to handle the event.

The value of the cond attribute must be a JavaScript expression that evaluates to a boolean (true or false). If the expression evaluates to true, the handler remains a valid candidate for handling the current instance of the event. If the expression evaluates to false, the handler is disqualified.

The following example initializes a boolean variable bIncludeEx to true. When the first nomatch event occurs, the VoiceXML interpreter evaluates the cond attribute of the first nomatch handler, determines that it is true, and because it is the first nomatch in document source order in the anonymous scope of the field element with a qualifying count, chooses it over the second nomatch handler. Upon execution of the handler, the bIncludeEx variable is set to false. When the second nomatch event occurs, the VoiceXML interpreter reevaluates the cond attribute of the first nomatch handler, determines that it is false, and selects the second handler for execution instead.

<vxml version="2.0">
<form id="get_fruit">
   <var name="bIncludeEx" expr="true"/>

   <field name="fruit">
   <prompt>Pick a fruit</prompt>

   <grammar src="fruits.gsl"/>

   <nomatch cond="bIncludeEx">
      <audio>I'm sorry. I didn't hear you.</audio>
      <audio>Pick a fruit. For example, say banana.</audio>
      <assign name="bIncludeEx" expr="false">
   </nomatch>
   
   <nomatch>
      <audio>I'm sorry. I still didn't hear you.</audio>
      <reprompt/>
   </nomatch>

   <filled>
      <audio>You picked <value expr="fruit"/></audio>
   </filled>
   </field>

   </form>
</vxml>