I need to have variables that are defined in my VXML application root document, which other documents modify, available to the JSP/EL pages. The idea here is that based on the value of these variable I can add logic to the JSP to render different blocks of VXML back to the IVR browser.
What I have tried so far does not generate any errors. It simply does not render the expected block of VXML code within the EL. My guess is that I am not de-referencing them correctly in EL.
Below is some of what I have tried.
root.vxml doc has
..
<var name="promptRetries" expr="''" />
...
start.jsp:
<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml" application="/root.vxml" >
....
<assign name="application.promptRetries" expr="'3'" />
.....
<block>
<submit next="${pageContext.request.contextPath}/nextdoc.jsp" />
</block>
nextdoc.jsp
<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml" application="/root.xml" >
....
<!-- at this point I can print and see the value of 3 for promptRetries -->
<!-- How can I expose this to JSP to accomplish something like the code below
I have used .equals() and other forms in the EL expression with no luck.
-->
<c:if test="${(application.promptRetries eq 1)} ">
<!-- Setting prompts for 1 retry -->
<catch event="noinput undefined" count="1" >
<audio expr="curPrompt2"/>
<log expr="buildLogStr(ibmCallId, documentName,frmName ,blkName,
'event=noinput count=1 reprompt', '')" />
</catch>
</c:if>
...
....
When developing VoiceXML applications in JSP, you need to be aware that there are two execution spaces. First, the Java server that generates the VoiceXML. Second, the VoiceXML Browser that executes it.
You already have an example of passing data from JSP to VoiceXML with the ${variable_name} syntax. To pass data from VoiceXML to JSP, you need to explicitly list the variables to send in the submit element:
<submit next="${pageContext.request.contextPath}/nextdoc.jsp" namelist="promptRetries"/>
And then in your second JSP page, use
request.getParameter("promptRetries")
to access the variable sent from the browser.
Related
Can an HTML form be bound to an XML document?
To give some context, Adobe XFA forms are XML documents created for purpose of rendering as a PDF form. They support XML bindings very similar to what I am looking for, but I'm not aware of anything similar in HTML forms and seeking suggestions.
An XFA form can also define bindings to an XML document that are bound to its form fields. It is not necessary for a schema to be defined -
the form can be merged with XML data or it can generate XML data based on the bindings specified in the form.
Example form definition:
<subform layout="tb">
<bind match="dataRef" ref="$.doc" />
<field w="0.5in">
<bind match="none" />
<ui>
<button />
</ui>
<caption>
<value>Add</value>
</caption>
<event activity="click" name="event__click">
<script contentType="application/x-javascript">
this.resolveNode("itemList").instanceManager.addInstance();
</script>
<event>
</field>
<subform layout="tb" name="itemList">
<bind match="dataRef" ref="$.item[*]">
<occur min="1" max="-1" />
<field w="2in">
<bind match="dataRef" ref="$.name" />
<ui>
<textEdit />
</ui>
<caption>
<value>Name</value>
</caption>
</field>
</subform>
</subform>
If the form was rendered with no data, it would appear similar to:
If the form was merged with the following input data:
<doc>
<item>
<name>item1</name>
</item>
<item>
<name>item2</name>
</item>
<item>
<name>item3</name>
</item>
</doc>
It would render similar to:
As you may notice in the form defintion code, Adobe XFA form is using its own XML language and expression syntax called SOM expressions. The first binding $.doc is binding to the top-level root node name doc.
The next binding $.item[*] is nested with the subform element and is relative to the $.doc binding.
The subform element is a container, similar to an HTML div element.
The subform is bound to item elements under the root doc element. the [*] syntax means that the subform will repeat itself for each item element in the xml document.
The occur element within the the subform element further qualifies how many instances can occur. The min=1 means that even if there are no item elements in the data merged into the form, it will automatically generate one. The max=-1 means there is no limit on the number of item instances.
The field element is bound to $.name. This means its value will update (or create) a name element under the current item.
The 'Add' button in the form creates new instances, Adobe Reader has a built-in Javascript engine and its own API to manage instances of the form that are persisted back to the XML data bound to the form.
Of course, the XML data can also be extracted from a saved PDF form.
There are many more capabilities in XFA forms such as conditional bindings, but I'm curious if something along these lines exists in HTML forms, perhaps some library that can link a form to an XML document and target them in a similar way.
XPATH would be ideal instead of the Adobe SOM expression syntax. Also, it would be ideal to have the XML posted from the form rather than name / value pairs that HTML forms would do by default.
There are many ways to convert XML into an HTML form. This question sounds an awful lot like a tool recommendation, so the only thing to do is list options:
Method 1:
This site walks the user through pasting an XML document, and then turns it into a form. It's pretty outdated, since the last change log was in 2006.
http://www.datamech.com/XMLForm/
Method 2:
You can write the script yourself, by converting XML > JSON then JSON > HTMLForm.
Converting the XML into JSON tools:
xml-js (NPM module)
xml2json (more popular, but has issues installing in Windows)
Blog tutorial (hand-made code)
Converting JSON into form tools:
json-forms (This might need you to follow a specific schema.)
Write the code yourself!
I'm guessing that what you're looking for is XSLT. This lets you transform a well-formed document of one kind into another. If this is what you want, there's a good answer here already.
In case other people stumble across this same question, you can get to exactly what you are looking for (creating html from xml documents) using xslt.
Think of this lonely post as your jumping off point to xslt. If you've never dealt with it before, it can be a little hard to digest. Fear not. Every journey begins with the first step. (etc. etc.)
Start with xml, and some idea of the html you want to create
So - for your example XML:
<doc>
<item name="Item1" />
<item name="Item2" />
<item name="Item3" />
</doc>
Let's assume you want to create a fairly simple HTML snippit:
<form class="tb">
<div><a class="btn btn-primary">Add</a></div>
<ul>
<li><label>Name</label><input type="text" class="form-control" value="Item1" /></li>
<li><label>Name</label><input type="text" class="form-control" value="Item2" /></li>
<li><label>Name</label><input type="text" class="form-control" value="Item3" /></li>
</ul>
</form>
Next, build your Xslt
There's some work at the beginning, and some syntax to learn. But, if we cut to the chase, this is the xslt that you'll end up with. It's just text. Just another file that you can hard code, embed, store in a file, grab from a url, etc.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="html" />
<xsl:template match="doc">
<form class="tb">
<div><a class="btn btn-primary">Add</a></div>
<ul>
<xsl:for-each select="item">
<li><label>Name</label><input type="text" class="form-control" value="<xsl:value-of select="#name"/>" /></li>
</xsl:for-each>
<xsl:if test="count(item)=0">
<li><label>Name</label><input type="text" class="form-control" value="" /></li>
</xsl:if>
</ul>
</form>
</xsl:template>
A few Xslt Notes
As you can see from the above, you setup a BASE document node to loop through with the <xsl:template match="doc"> tag. If your xml document has a doc node, then the html within the template is included. If there isn't a doc node, then it's skipped.
You can break out your xslt into different templates - and include them in the main template as well. It's pretty cool.
In the example above, we loop through your item nodes with an <xsl:for-each> tag, and we even have an "alternate" html which gets displayed if there are ZERO item tags (that's the empty input tag surrounded by
<xsl:if test="count(item)=0">).
There are some really great xslt references out there, but I like the one from Microsoft because I can use the c# code below to get html from a specific xslt tempate and my xml doc.
Finally, put it all together
Once you have your xml (above) and your xslt (also above), you can use them both to generate a string of html that is as long and complicated as you'd like. This is an almost verbatim copy of the method we use to generate massive mortgage contracts from xslt and really complex xml documents. I swear - it's lightning quick, and produces thousands of pages of html every day for us.
private string GetHtmlFromXslt(string xml, string xslt) {
XslCompiledTransform transform = new XslCompiledTransform();
using (XmlReader reader = XmlReader.Create(new StringReader(xslt))) {
transform.Load(reader);
}
StringWriter results = new StringWriter();
using (XmlReader reader = XmlReader.Create(new StringReader(xml))) {
transform.Transform(reader, null, results);
}
return results.ToString();
}
This is a .net core project file, referencing just System.Xml and System.Xml.Xsl - both of which are standard in System.Xml.
C-sharp!? Blech! Ach! The OP said JAVASCRIPT. Jeez...
I know you are a javascript guy. There are tools to do exactly the same thing (exactly) here and here.
I just haven't used those libraries because all of our xml is (a) private and (b) located on servers. But - I took a look at the code and they both follow the same approach -- one xml file and one xslt file, married with about 8-10 lines of actual code and producing a lovely html baby.
So. That's it. No tools. No third party plugins. No crazy json stuff.
Good luck! Can't wait to see what you crazy-kids create!
I'm using javascript in my html page.
I've defined a variable 'language' in html:
<c:set var="language" value="${not empty param.language ? param.language : not empty language ? language : pageContext.request.locale}" scope="session" />
and I would like to use/modify this variable from javascript.
function changeLanguage(name) {
language = "fr";
}
how can I do it ?
What I have tried
I have a picture in html page and after clicking on it I call this js function. when it's called, variable 'language' should be changed to 'fr' . Maybe it can be done easier. I dont know.
Here JSTL code is executed at server side and the server sees the JavaScript/Html codes as simple texts. The generated contents from JSTL code (if any) will be rendered in the resulting HTML along with your other JavaScript/HTML codes. Now the browser renders HTML along with executing the Javascript codes. Now remember there is no JSTL code available for the browser.
So you cant use javascript to change value.
Change attributes(var) value(language) using JavaScript
Place this in your HTML Page
HTML
<c:set id="lang" var="language" scope="session" value="...." scope="...." />
<img src="abc.png" onclick="changelang()" />
<script>
$(document).ready(function(){
function changelang(){
$("#lang").attr("var", "fr");
}
});
</script>
Credit:
http://www.w3schools.com/jquery/tryit.asp?filename=tryjquery_dom_attr_set
I have an interesting task that I am trying to accomplish. While using VoiceXML, I'd like to have a caller call into a number, and then be transferred to number #1. If the caller is not connected (no answer) then the destination number is changed and the caller is then attempted to be connected to the second number.
I was given a little information by the support tech that stated:
The best option would be define a list of numbers in JavaScript, if the transfer is unsuccessful, pop the next of the list, and repeat the transfer (which means the 'dest' for the transfer would be a variable).
But I am not sure how to go about this, and so far, I'm unable to find any reference points to use for this. Could this be achieved by using PHP, maybe?
How can I add JavaScript to VoiceXML that would allow me to set a timeout variable on the transfer tag, and then cycle through the numbers if the caller isn't connected?
Assuming that you use a VoiceXML 2.1 compliant platform, you must use something like <transfer type="consultation" destexpr="myDestinationVariable" connecttimeout="20s" />.
However, the connecttimeout attribute cannot be a JavaScript expression, it must be a time literal. So you need to generate VoiceXML on the fly (with PHP or something else) if the time-out is not a constant.
If you can have a constant timeout, you could do something like (not tested):
<?xml version="1.0" encoding="utf-8"?>
<vxml version="2.1" xml:lang="en-US" xmlns="http://www.w3.org/2001/vxml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<var name="destinations" expr="['5555551111', '5555551112', '5555551113']" />
<var name="currentDestination" expr="destinations.shift()" />
<form id="myForm">
<transfer name="transferResult" type="consultation" cond="currentDestination!=undefined" destexpr="currentDestination"
connecttimeout="20s">
<filled>
<if cond="transferResult=='noanswer'">
<assign name="currentDestination" expr="destinations.shift()" />
<clear />
</if>
</filled>
<catch event="connection.disconnect.transfer">
<!-- transfer OK -->
</catch>
</transfer>
<block>
<!-- No more numbers to try -->
</block>
</form>
</vxml>
I am using Plone 3 and currently trying to override one of the default javascript files i.e. table_sorter.js.
Under the browser directory of my product, I created a directory "javascripts" (just to keep things organized), then registered the directory as a ressource, in configure.zcml:
<browser:resourceDirectory
name="myproduct.javascripts"
directory="javascripts"
layer=".interfaces.IThemeSpecific" />
Where "myproduct" is self explanatory.
Then in jssregistry.xml, I registered and ordered the javascript files:
<javascript id="++resource++myproduct.javascripts/table_sorter.js"
enabled="True"
cookable="False"
inline="False"
insert-after="jquery.js" />
Where table_sorter.js is the name of the javascript file that I need to override.
The reason I need to override the file is because the default has no way of telling the user whether a table is sortable or not until it is clicked on. I need to include icons on the table header by default.
I have followed the above steps but it does not seem to work. I have no idea where I'm going wrong. Any help will be highly appreciated.
You are missing the generic setup import step. Add a file skins.xml to your gs profile with this code:
<?xml version="1.0"?>
<object name="portal_skins" allow_any="False" cookie_persistence="False">
<object name="plonetheme_mytheme_js"
meta_type="Filesystem Directory View"
directory="your.product:skins/plonetheme_mytheme_js"/>
<skin-path name="*">
<layer name="plonetheme_mytheme_js"
insert-after="custom"/>
</skin-path>
</object>
After that, rembember to reinstall your product in order to apply your new gs step
Note: I'm giving another answer simply because code in comments isn't readable. Look at the #Martijn Pierters 's answer (and comments) for the initial part.
You are not overriding the original JavaScript file, only adding a new one.
You can do two different things here:
Remove the original table_sorter.js from portal_javascript:
<javascript id="table_sorter.js" remove="true" />
Because the original table_sorter.js file is server through a skin layer, you can put a new file with the same name in your own skin layer to override the original.
Considering that you have already placed your customised javascript file into your static directory, do as follows.
In file "your/app/profiles/default/jsregistry.xml"
<?xml version="1.0"?>
<object name="portal_javascripts">
<javascript id="table_sorter.js" remove="True" enabled="False" />
<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression=""
id="++resource++your.app/path/to/customised/script/table_sorter.js" inline="False"/>
</object>
Modify the attributes as you wish. :)
Problem description
Is it possible to register (include) javascript within RenderingTemplate? (RenderingTemplates are used to render list forms or fields)
By using
<SharePoint:RenderingTemplate ID="NewRelatedListItem" runat="server">
<Template>
<span id="part1">
<SharePoint:ScriptLink Name="SPFormFieldAssistant.js" Localizable="false" />
...
</span>
...
</Template>
</SharePoint:RenderingTemplate>
it couldn't be done - it didn't include script at HEAD area, but...:
Source http://img62.imageshack.us/img62/9826/ss20100324092808.png
Is something wrong with my code? Althought script IS at Layouts folder and I checked with Reflector that it uses Layouts folder if Localizable='False'.
I don't want this script to be loaded with every page, but only for forms.
Any ideas on how this could be achieved?
My idea that is not working...
My first idea was to add script programmatically with <% this.Page.ClientScript.RegisterClientScriptInclude("spffa", "/_layouts/SPFormFieldAssistant.js") %>, but it is not working, as that code evaluation is happening in Render method and i read somwhere that you cannot register client scripts within Render method, but usually is done within PreRender method. Pity
My second idea that is still not working
I thought i would create custom UserControl named RegisterClientScript and there within overriden PreRender method i would add scripts i need with client script manager (this.Page.ClientScript...) but, as with SharePoint:ScriptLink, my control also is rendered as text!
my control as text http://img693.imageshack.us/img693/3738/ss20100324115826.png
How do i overcome this and where's the catch?
Looks like you are missing the runat. Try this:
<SharePoint:ScriptLink Name="SPFormFieldAssistant.js" Localizable="false" runat="server" />
It turns out that you can directly add <script> tags to template!
<script src="/_layouts/SPFormFieldAssistant.js" type="text/javascript"></script>
Thank you for the notes however.
Sometime back I had a Similar requirement. For which I have included the script Register in the CreateChildControls method of the Field Control class.