Hi, yes this and related changes in myFaces.js was my first idea, but this did not work right. I added a additional field to the options.
Seems you have the sources? please try the attached files, it works on my tomcat, but i can't test on a portlet. If this works i can commit this into svn. Regards, Volker PS: please rename myFaces.js-xxx as myFaces.js, js files are blocked from my firewall. Luo. Haihua wrote: > Hi Volker, > > thanks for ur always warm-hearted reply!:) > > Do you mean sth. like this in InputSuggestAjaxRenderer.java? > > out.writeText("', {\n" + > " method: 'post',\n" + > ... > " parameters: 'affectedAjaxComponent=" + clientId + > "',\n" + > ... > > It seems that it still not work... > > Cheers, > > Haihua > > > > -----Ursprüngliche Nachricht----- > Von: Volker Weber [mailto:[EMAIL PROTECTED] > Gesendet: Donnerstag, 9. Februar 2006 11:50 > An: MyFaces Discussion > Betreff: Re: integration problem with <s:inputSuggestAjax> and portlet > > Hi, > > i think this can be solved by adding the parameters as post parameter to > the options, instead of empty. > > I will give it a try this afternoon (german time). > > Regards, > Volker > > Luo. Haihua wrote: > >>Hi dear all, >> >> >> >>I am using portlet and want to insert a tag <s:inputSuggestAjax> into >>one of my .jsp page. However, it doesn't work due to a javascript error >>"element.getClassName has no properties" in firefox. >> >> >> >>I have read the generated html file, even jumped deeply into the source >>codes of myfaces and found following problem: >> >> >> >>Within the generated html page, myfaces generates following javascript >>codes for inputSuggestAjax: >> >> >> >> <SCRIPT type=text/javascript><!-- >> >>new >>Ajax.MyFacesAutocompleter('Pluto_ProcessOverviewPortlet_r1_c1_p1__id0:Pluto_ProcessOverviewPortlet_r1_c1_p1__id2','Pluto_ProcessOverviewPortlet_r1_c1_p1__id0:Pluto_ProcessOverviewPortlet_r1_c1_p1__id2_auto_complete','*/pluto/portal/ProcessOverviewPortlet/_ac_ProcessOverviewPortlet_r1_c1_p1/AC/_pid/ProcessOverviewPortlet_r1_c1_p1**?**org.apache.myfaces.portlet.MyFacesGenericPortlet.VIEW_ID=%2Fview.jsp**?**affectedAjaxComponent=Pluto_ProcessOverviewPortlet_r1_c1_p1__id0:Pluto_ProcessOverviewPortlet_r1_c1_p1__id2*', >>{ >> >> method: 'post', >> >> asynchronous: true, >> >> parameters: '', >> >> callback: function(element,entry) {return >>entry+'&jsf_tree_64='+encodeURIComponent(document.getElementById('jsf_tree_64').value)+'&jsf_state_64='+encodeURIComponent(document.getElementById('jsf_state_64').value)+'&jsf_viewid='+encodeURIComponent(document.getElementById('jsf_viewid').value)} >> >>}) >> >>//--></SCRIPT> >> >> >> >>Note that the third parameter of the js function, which should be an >>encodeURL, contains TWO "?", the first is generated by the portlet, the >>second by the myfaces! Therefore it is no more a valid encodeURL to >>parse by myfaces! >> >> >> >>So it seems that inputSuggestAjax does not support any call by a page >>whose URL already contains parameters. Any tips or suggestions how to >>resolve this problem? >> >> >> >>Mit freundlichen Grüßen / Kindest regards >> >> >> >>Haihua Luo >> >> > > -- Don't answer to From: address! Mail to this account are droped if not recieved via mailinglist. To contact me direct create the mail address by concatenating my forename to my senders domain.
/* * Copyright 2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.myfaces.custom.inputsuggestajax; import org.apache.commons.lang.StringUtils; import org.apache.myfaces.renderkit.html.util.AddResource; import org.apache.myfaces.renderkit.html.util.AddResourceFactory; import org.apache.myfaces.custom.ajax.api.AjaxPhaseListener; import org.apache.myfaces.custom.ajax.api.AjaxRenderer; import org.apache.myfaces.custom.prototype.PrototypeResourceLoader; import org.apache.myfaces.renderkit.JSFAttr; import org.apache.myfaces.renderkit.RendererUtils; import org.apache.myfaces.renderkit.html.HTML; import org.apache.myfaces.renderkit.html.HtmlRendererUtils; import org.apache.myfaces.renderkit.html.util.UnicodeEncoder; import org.apache.myfaces.renderkit.html.ext.HtmlTextRenderer; import javax.faces.application.ViewHandler; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.el.MethodBinding; import javax.faces.el.MethodNotFoundException; import java.io.IOException; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * @author Gerald Muellan * @author Martin Marinschek * @version $Revision: 177984 $ $Date: 2005-05-23 19:39:37 +0200 (Mon, 23 May 2005) $ */ public class InputSuggestAjaxRenderer extends HtmlTextRenderer implements AjaxRenderer { private static final int DEFAULT_MAX_SUGGESTED_ITEMS = 200; /** * Encodes any stand-alone javascript functions that are needed. * Uses either the extension filter, or a * user-supplied location for the javascript files. * * @param context FacesContext * @param component UIComponent * @throws java.io.IOException */ private void encodeJavascript(FacesContext context, UIComponent component) throws IOException { // AddResource takes care to add only one reference to the same script String javascriptLocation = (String)component.getAttributes().get(JSFAttr.JAVASCRIPT_LOCATION); String styleLocation = (String)component.getAttributes().get(JSFAttr.STYLE_LOCATION); AddResource addResource = AddResourceFactory.getInstance(context); if(javascriptLocation != null) { addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, javascriptLocation + "/prototype.js"); addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, javascriptLocation + "/effects.js"); addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, javascriptLocation + "/dragdrop.js"); addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, javascriptLocation + "/controls.js"); addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, javascriptLocation + "/myFaces.js"); } else { addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, PrototypeResourceLoader.class, "prototype.js"); addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, PrototypeResourceLoader.class, "effects.js"); addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, PrototypeResourceLoader.class, "dragdrop.js"); addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, PrototypeResourceLoader.class, "controls.js"); addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, InputSuggestAjaxRenderer.class, "myFaces.js"); } if( StringUtils.isNotBlank( styleLocation ) ) { addResource.addStyleSheet(context, AddResource.HEADER_BEGIN, styleLocation + "/theme.css"); } else { String theme = ((InputSuggestAjax)component).getLayout(); if(theme == null) { theme = "default"; } addResource.addStyleSheet(context, AddResource.HEADER_BEGIN, InputSuggestAjaxRenderer.class, theme + "/theme.css"); } } public void encodeEnd(FacesContext context, UIComponent component) throws IOException { RendererUtils.checkParamValidity(context, component, InputSuggestAjax.class); if( HtmlRendererUtils.isDisplayValueOnly(component) || isDisabled(context, component)){ super.encodeEnd(context, component); return; } InputSuggestAjax inputSuggestAjax = (InputSuggestAjax) component; this.encodeJavascript(context,component); inputSuggestAjax.getAttributes().put("autocomplete","off"); String oldStyleClass = inputSuggestAjax.getStyleClass(); inputSuggestAjax.setStyleClass( (oldStyleClass!=null && oldStyleClass.length()>=0 ? oldStyleClass : "")+" myFacesInputSuggestAjax"); super.encodeEnd(context, component); inputSuggestAjax.setStyleClass(oldStyleClass); ResponseWriter out = context.getResponseWriter(); out.startElement(HTML.DIV_ELEM, null); if(inputSuggestAjax.getLayout().equals("default")) { out.writeAttribute(HTML.CLASS_ATTR, "ajaxPopup", null); } if(inputSuggestAjax.getPopupStyleClass()!= null) { out.writeAttribute(HTML.CLASS_ATTR, inputSuggestAjax.getPopupStyleClass(), null); } if (inputSuggestAjax.getPopupId() != null) { out.writeAttribute(HTML.ID_ATTR,inputSuggestAjax.getPopupId(), null); } else { out.writeAttribute(HTML.ID_ATTR, component.getClientId(context)+"_auto_complete", null); } if (inputSuggestAjax.getPopupStyle() != null) { out.writeAttribute(HTML.STYLE_ATTR, inputSuggestAjax.getPopupStyle(),null); } out.endElement(HTML.DIV_ELEM); String clientId = component.getClientId(context); String viewId = context.getViewRoot().getViewId(); ViewHandler viewHandler = context.getApplication().getViewHandler(); String actionURL = viewHandler.getActionURL(context, viewId); out.startElement(HTML.SCRIPT_ELEM, null); out.writeAttribute(HTML.TYPE_ATTR, "text/javascript", null); out.writeText("new Ajax.MyFacesAutocompleter('",null); out.writeText(clientId,null); out.writeText("','",null); if (inputSuggestAjax.getPopupId() != null) { out.writeText(inputSuggestAjax.getPopupId(), null); } else { out.writeText(clientId+"_auto_complete",null); } out.writeText("','",null); out.writeText(context.getExternalContext().encodeActionURL(actionURL),null); if (context.getApplication().getStateManager().isSavingStateInClient(context)) { out.writeText("', {\n" + " method: 'post',\n" + " asynchronous: true,\n" + " parameters: '',\n"+ " ajaxComponentId: '" + clientId + "',\n"+ " callback: function(element,entry) {return entry+'&jsf_tree_64='+encodeURIComponent(document.getElementById('jsf_tree_64').value)+'&jsf_state_64='+encodeURIComponent(document.getElementById('jsf_state_64').value)+'&jsf_viewid='+encodeURIComponent(document.getElementById('jsf_viewid').value)}" + " })",null); } else { out.writeText("', {\n" + " method: 'post',\n" + " asynchronous: true,\n" + " parameters: '',\n" + " ajaxComponentId: '" + clientId + "',\n"+ " callback: function(element,entry) {return entry}" + " })", null); } out.endElement(HTML.SCRIPT_ELEM); } public void decode(FacesContext facesContext, UIComponent component) { super.decode(facesContext, component); } public void encodeAjax(FacesContext context, UIComponent uiComponent) throws IOException { RendererUtils.checkParamValidity(context, uiComponent, InputSuggestAjax.class); InputSuggestAjax inputSuggestAjax = (InputSuggestAjax) uiComponent; MethodBinding mb = inputSuggestAjax.getSuggestedItemsMethod(); Collection suggesteds = null; int maxSuggestedCount = inputSuggestAjax.getMaxSuggestedItems()!=null ? inputSuggestAjax.getMaxSuggestedItems().intValue() : DEFAULT_MAX_SUGGESTED_ITEMS; if (inputSuggestAjax.getMaxSuggestedItems()!=null) { try{ suggesteds = (Collection) mb.invoke(context,new Object[]{ AjaxPhaseListener.getValueForComponent(context, uiComponent), new Integer(maxSuggestedCount)}); }catch(MethodNotFoundException dummy){ suggesteds = (List) mb.invoke(context,new Object[]{ AjaxPhaseListener.getValueForComponent(context, uiComponent)}); } } else { try{ suggesteds = (List) mb.invoke(context,new Object[]{ AjaxPhaseListener.getValueForComponent(context, uiComponent)}); }catch(MethodNotFoundException dummy){ suggesteds = (Collection) mb.invoke(context,new Object[]{ AjaxPhaseListener.getValueForComponent(context, uiComponent), new Integer( DEFAULT_MAX_SUGGESTED_ITEMS )}); } } StringBuffer buf = new StringBuffer(); buf.append("<ul"); if (inputSuggestAjax.getListStyleClass() != null) { buf.append(" class='"+inputSuggestAjax.getListStyleClass()+"'"); } if (inputSuggestAjax.getListStyle() != null) { buf.append(" style='"+inputSuggestAjax.getListStyle()+"'"); } if (inputSuggestAjax.getListId() != null) { buf.append(" id='"+inputSuggestAjax.getListId()+"'"); } buf.append(">"); int suggestedCount=0; for (Iterator i = suggesteds.iterator() ; i.hasNext() ; suggestedCount++) { if( suggestedCount > maxSuggestedCount ) break; buf.append("<li"); if (inputSuggestAjax.getListItemStyleClass() != null) { buf.append(" class='"+inputSuggestAjax.getListItemStyleClass()+"'"); } if (inputSuggestAjax.getListItemStyle() != null) { buf.append(" style='"+inputSuggestAjax.getListItemStyle()+"'"); } buf.append(">"); buf.append(UnicodeEncoder.encode(i.next().toString())); buf.append("</li>"); } buf.append("</ul>"); context.getResponseWriter().write(buf.toString()); } }
Ajax.MyFacesAutocompleter = Class.create(); Ajax.MyFacesAutocompleter.prototype = Object.extend(new Autocompleter.Base(), Object.extend(new Ajax.Base(), { initialize: function(element, update, url, options) { this.baseInitialize(element, update, options); this.options.asynchronous = true; this.options.onComplete = this.onComplete.bind(this) this.options.method = 'post'; this.url = url; this.options.onShow = function(element, update){ if(!update.style.position || update.style.position=='absolute') { update.style.position = 'absolute'; var offsets = Position.cumulativeOffset(element); update.style.top = (offsets[1] + element.offsetHeight) + 'px'; update.style.left = offsets[0] + 'px'; // Position.clone(element, update, {setHeight: false, offsetTop: element.offsetHeight}); } Effect.Appear(update,{duration:0.15}); }; }, getUpdatedChoices: function() { Element.addClassName(this.element, "myFacesInputSuggestAjaxThrobbing"); var entry = encodeURIComponent(this.element.name) + '=' + encodeURIComponent(this.getToken()); this.options.parameters = "affectedAjaxComponent=" + encodeURIComponent(this.options.ajaxComponentId) + "&" + (this.options.callback ? this.options.callback(this.element, entry) : entry); new Ajax.Request(this.url, this.options); }, onComplete: function(request) { Element.removeClassName(this.element, "myFacesInputSuggestAjaxThrobbing"); this.updateChoices(request.responseText); this.resetWidth(); }, resetWidth: function() { this.update.style.width = this.element.offsetWidth + 'px'; var offset = this.iefix ? 2 : -8; if ((this.update.scrollWidth + offset) > this.element.offsetWidth) { this.update.style.width = (this.update.scrollWidth + offset) + 'px'; } } }));