Thanks for all the help by the way. I finally got my zipcode completion with state/city drop working. I used the afterUpdateElement as follow. Cavear emptor I'm no _javascript_ guru I did whatever work the fastest (I wish I had _javascript_ code completion in Eclipse). Below is my zip code component
<!-- Zip Code -->
<component id="zipCode" type="tacos:Autocompleter" >
<binding name="displayName" value="literal:Zip Code" />
<binding name="value" value="ognl:user.address.zipCode" />
<binding name="listSource" value="ognl:zipCodeList" />
<binding name="listener" value="listener:searchZipCodes" />
<binding name="listItemRenderer" value="ognl:listRenderer" />
<binding name="direct" value="ognl:true" />
<binding name="frequency" value="literal:0.4" />
<binding name="afterUpdateElement">
literal:<![CDATA[
function handleAutoComplete(field, htmlElement) {
var span = dojo.dom.collectionToArray(htmlElement.getElementsByTagName("SPAN"))[0];
var spanBody = dojo.dom.textContent(span);
var values = spanBody.split(",");
var city = dojo.string.trim(values[0]);
var state = dojo.string.trim(values[1]);
document.getElementById("city").value=city;
document.getElementById("state").value=state;
}
]]>
</binding>
</component>
The JS updates the two field city and state which are just part of the form
<!-- City -->
<component id="city" type="TextField">
<binding name="value" value="ognl:user.address.city"/>
<binding name="validators" value="validators:required"/>
<binding name="displayName" value="literal:City"/>
</component>
The HTML template looks like:
<style>
div.auto_complete {
width: 350px;
background: #fff;
}
div.auto_complete ul {
border:1px solid #888;
margin:0;
padding:0;
width:100%;
list-style-type:none;
}
div.auto_complete ul li {
margin:0;
padding:3px;
}
div.auto_complete ul li.selected {
background-color: #ffb;
}
div.auto_complete ul strong.highlight {
color: #800;
margin:0;
padding:0;
}
ul.locations {
list-style-type: none;
margin:0px;
padding:0px;
}
ul.locations li.selected { background-color: #ffb; }
li.location {
list-style-type: none;
display:block;
margin:0;
padding:2px;
height:32px;
}
li.location div.zip {
font-weight:bold;
font-size:12px;
line-height:1.2em;
}
li.location div.description {
font-size:10px;
color:#888;
}
</style>
<form jwcid="@tacos:AjaxForm"
delegate="bean:delegate"
listener="ognl:listeners.add">
<table width="100%" border="0" summary="register">
...
<tr>
<td><span jwcid="cityLabel"><label>City</label></span></td>
<td><span jwcid="city"><input type="text" alt="City" /></span></td>
</tr>
<tr>
<td><span jwcid="stateLabel"><label>State</label></span></td>
<td><span jwcid="state"><input type="text" alt="State" /></span></td>
</tr>
<tr>
<td><span jwcid="zipCodeLabel"><label>ZipCode</label></span></td>
<td><span class="auto_complete" jwcid="zipCode"/></td>
</tr>
<tr>
<td><img jwcid="@ImageSubmit" image="asset:btn_submit" alt="Submit"/></td>
</tr>
</table>
</form>
The custom renderer looks like:
public class LocationRenderer implements ListItemRenderer {
/* (non-Javadoc)
* @see net.sf.tacos.ajax.components.ListItemRenderer#renderList(org.apache.tapestry.IMarkupWriter, org.apache.tapestry.IRequestCycle, java.util.Iterator)
*/
public void renderList(IMarkupWriter writer, IRequestCycle cycle, Iterator values) {
if (cycle.isRewinding())
return;
writer.begin("ul");
writer.attribute("class", "locations");
while (values.hasNext()) {
Location value = (Location)values.next();
if (value == null)
continue;
writer.begin("li");
writer.attribute("class", "location");
writer.begin("div");
writer.attribute("class", "zip");
writer.print(value.getZip());
writer.end("div");
writer.begin("div");
writer.attribute("class", "description");
writer.begin("span");
writer.attribute("class", "informal");
writer.print(value.getCity() + ", " + value.getState());
writer.end("span");
writer.end("div");
writer.end("li");
}
writer.end();
}
}
On the Java page file I have a method to use a EJB3 service, backed by DAO using Hibernate that does the zip searching.
public abstract class Register extends ActiveConferencePage {
/** List html renderer */
private static final ListItemRenderer LOCATION_RENDERER = new LocationRenderer();
/**
* The renderer
* @return
*/
public ListItemRenderer getListRenderer() {
return LOCATION_RENDERER;
}
public void pageBeginRender(PageEvent event) {
super.pageBeginRender(event);
if (getUser() == null) {
Builder builder = getBuilderFactory().getBuilder(AttendeeInfo.class);
setUser((AttendeeInfo)builder.build());
AddressInfo address = (AddressInfo)getBuilderFactory().getBuilder(AddressInfo.class).build();
getUser().setAddress(address);
}
}
public String add(IRequestCycle cycle ) {
IValidationDelegate delegate = (IValidationDelegate)getBeans().getBean("delegate");
if (delegate.getHasErrors()) {
return null;
}
// if it passes validation then register them
setUser( getUserService().registerAttendee(getUser()) );
// auto login the user??
// back to the page
return "attendee/Register";
}
public void searchZipCodes(String searchString) {
System.out.println("Searching for Zip Codes...");
List<Location> locations = getLocationLookupService().searchLocations(searchString);
setZipCodeList(locations);
}
public abstract Collection getZipCodeList();
public abstract void setZipCodeList(Collection values);
public abstract void setUser(AttendeeInfo i);
public abstract AttendeeInfo getUser();
public abstract UserService getUserService();
public abstract LocationLookupService getLocationLookupService();
public abstract BuilderFactory getBuilderFactory();
}
Next, I would like to have some effects when I drop the city and state but I need to learn more about Dojo to do that (and _javascript_ in general).
Overall the combination Tapesty+Tacos+EJB3+JBoss+Hibernate is working very well for us.
Regards,
Brian
On 12/30/05, Jesse Kuhnert <[EMAIL PROTECTED]> wrote:
Could you log a bug report for this issue? In the interest of getting your problem solved without having time to debug this parameter, you could probably easily use the AjaxSubmitEvent component ( http://tacos.sourceforge.net/components/AjaxEventSubmit.html) to listen for field changes to your Autocompleter and then populate your form fields.On 12/30/05, Brian Sam-Bodden <[EMAIL PROTECTED]> wrote:Jesse,
Unfortunately the inline _javascript_ didn't work. I tried this just to test that the event was being fired:
<!-- Zip Code -->
<component id="zipCode" type="tacos:Autocompleter" >
<binding name="displayName" value="literal:Zip Code" />
<binding name="value" value="ognl:user.address.zipCode" />
<binding name="listSource" value="ognl:zipCodeList" />
<binding name="listener" value="listener:searchZipCodes" />
<binding name="listItemRenderer" value="ognl:listRenderer" />
<binding name="direct" value="ognl:true" />
<binding name="frequency" value="literal:0.4" />
<binding name="afterUpdateElement">
literal:<![CDATA[
function handleAutoComplete(field, htmlElement) {
alert("zip has been selected!!")
}
]]>
</binding>
</component>
The HTML looks like this:
<tr>But nothing happens when the ZIP is selected from the dropdown.
<td><label for=
"zipCode">Zip Code</label></td>
< td><input
type="text" autocomplete="off" name=
"zipCode" value= "" id="zipCode"
frequency="0.4" class="auto_complete" afterUpdateElement
= "
function handleAutoComplete(field, htmlElement) {
alert("zip has been selected!!")
}"
/></td>
</tr>
<tr>
Thanks for the help,
BrianOn 12/29/05, Jesse Kuhnert <[EMAIL PROTECTED]> wrote:I would definitely use the afterUpdateElement. From the docs, http://wiki.script.aculo.us/scriptaculous/show/Ajax.Autocompleter , I think this method is expecting a function object passed in directly, so I would try adding something like this to your binding:
<binding name="afterUpdateElement">
<[[CDATA //this might be wrong, don't remember xml cdata syntax right now
function handleAutoComplete(field , htmlElement) {
htmlElement are the contents of the selected item in your response, field is your field
you can parse the individual contents of your html element out and populate your form fields..I reccomend learning some of the dojo dom/html api's to help you with that part
}
]]>
</binding>
On 12/29/05, Brian Sam-Bodden <[EMAIL PROTECTED] > wrote:Hi,
First of all thanks to all in the dev team for a wonderful set of components. I have a couple of questions about the autocompleter component. I'm doing a Zip code autocompleter. The dropdown should show Zipcode + City and State. When selected I want to drop the selected values into the fields of the enclosing form for zip, city and state.
1) I created a ListItemRenderer that takes care of showing the dropdown as I described above. Here's the relevant code:
public void renderList(IMarkupWriter writer, IRequestCycle cycle, Iterator values) {
if (cycle.isRewinding())
return;
writer.begin("ul");
writer.attribute("class", "locations");
while (values.hasNext()) {
Location value = (Location)values.next();
if (value == null)
continue;
writer.begin("li");
writer.attribute("class", "location");
writer.begin("div");
writer.attribute("class", "zip");
writer.print(value.getZip());
writer.end("div");
writer.begin("div");
writer.attribute("class", "description");
writer.print(value.getCity() + ", " + value.getState());
writer.end("div");
writer.end("li");
}
writer.end();
}
The problem is that when I select the item it drops the value of the Zip and also the value of the city + ", " + state. Here's the .page definitions:
<!-- Zip Code -->
<component id="zipCode" type="tacos:Autocompleter" >
<binding name="displayName" value="literal:Zip Code" />
<binding name="value" value="ognl:user.address.zipCode" />
<binding name="listSource" value="ognl:zipCodeList" />
<binding name="listener" value="listener:searchZipCodes" />
<binding name="listItemRenderer" value="ognl:listRenderer" />
<binding name="direct" value="ognl:true" />
<binding name="frequency" value="literal:0.4" />
</component>
So, what am I missing here? I saw the example on script.aculo.us and they do have an autocompleter that has a complex HTML dropdown with multiple lines of text but when selected only the text for the locale is added to the field.
2) How do I use the afterUpdateElement property? I want to drop the value of the City and State in their respective fields? Any ideas?
Thanks,
Brian
