David,
I'm going to review the code. Do you advise me to review Rico ? Do you
plan to integrate it into Jetspeed ?
Thanks,
Christophe
On 11/24/05, David Sean Taylor <[EMAIL PROTECTED]> wrote:
> Christophe Lombart wrote:
> > Hi all,
> >
> > What is the current status of the Ajax support in J2 ? I didn't
> > follow all messages about this topic and I'm wondering what we can do
> > with Ajax within J2.
> >
> > Are there some tools to use Ajax in my own portlet ? or is it better
> > to use other frameworks like Taconite, dwr, ... For example, I
> > would like to build a dynamic tree view which can retrieve subitems
> > only when it is needed.
> >
> Funny that you ask, thats what Roger and I plan to work on next week.
> And yes, there is an AJAX pipeline in Jetspeed-2 to handle AJAX request
> through the Jetspeed pipeline.
> We're currently working on a Layout API for Javascript customization.Its
> in subversion trunk under the portal component:
>
> org.apache.jetspeed.ajax.AjaxRequestServiceImpl and AjaxServiceImpl
> org.apache.jetspeed.layout.impl.*
>
> This is still a work in progress..
>
> In a custom project, we wrote an AJAX treeview widget with Rico. The
> code is mixed in another project but was more of a first time prototype,
> so its not integrated with the ongoing work in subversion head. It uses
> a concept of builders and actions to supply XML responses over HTTP.
> Here is an example builder that builds a tree view, the javascript to
> expand and contract, and finally the service that handles the request.
> Since doing this work, Ive been working on porting it back into
> Jetspeed, although I haven't considering porting back the treeview yet.
> The builder and action classes are not included here, since they are
> being refactored in the SVN trunk. It would be best if we ported the
> treeview code back to the new AJAX services and builders in SVN trunk.
> I'd be glad to work with you on that.
>
> <?xml version="1.0"?>
> #macro (ajaxChildren $children)
> #foreach( $child in $children)
> #set($isLeaf = "false")
> #set($isDocument = "false")
> #if($child.isLeaf() == true)
> #set($isLeaf = "true")
> #end
> #if($child.isDocument() == true)
> #set($isDocument = "true")
> #end
> <child label="$child.label" name="$child.name" isLeaf="$isLeaf"
> isDocument="$isDocument" #if($child.anchor.length() > 0)
> anchor="$child.anchor" #end >
> #if($child.getChildren().size() > 0)
> #set($grandchildren = $child.getChildren())
> #ajaxChildren($grandchildren)
> #end
> </child>
> #end
> #end
> <ajax-response>
> <response type="object" id="treeUpdater"><node name="${ajaxnode.name}"
> contextPath="$contextPath">
> #set($t = $ajaxnode.getChildren())
> #ajaxChildren( $t )
> </node>
> </response>
> </ajax-response>
>
> Javascript to expand / contract tree nodes:
>
> var treeBuilder = "";
> var documentBuilder = "";
> var loaded = { };
> var currentDocument = "";
> var expandTree = "";
>
> var TreeUpdater = Class.create();
> /*
> TreeUpdater.attributes = [ "fullName", "title", "firstName", "lastName",
> "streetAddress",
> "city", "state", "zipcode", "occupation", "phoneNumber", "mobileNumber",
> "personNotes" ];*/
>
> TreeUpdater.prototype = {
>
> initialize: function() {
> this.useHighlighting = true;
> this.lastNodeSelected = null;
> },
>
> ajaxUpdate: function(ajaxResponse) {
> log("Received response from server");
> this.updateTree(ajaxResponse.childNodes[0]);
> },
> updateTree: function(node) {
> this.lastNodeSelected = node;
>
> log("Found node with nodeName=" + node.nodeName);
> var treeNodeName = node.getAttribute("name");
> log("TreeNodeName=" + treeNodeName);
> var div = document.getElementById(treeNodeName);
> div.style.display = "inline";
> log("DIV Object Id =" + div);
>
> this.updateExpandInfo(treeNodeName);
>
> var html = this.outputChildren(node, treeNodeName);
>
> div.innerHTML = html;
> html = null;
> },
> updateExpandInfo: function(treeNodeName) {
> //var a = document.getElementById("PLUS_" + treeNodeName);
> //a.innerHTML = "-";
> },
> outputChildren: function(node, treeNodeName) {
> var children = node.childNodes;
> var html = "";//"<ul>"
> log("Number of Children = " + children.length);
>
> for(var i=0; i< children.length; ++i) {
> var child = children[i];
> log("Found child " + child.nodeName);
> if(child.nodeName == "#text") continue;
>
> var childName = child.getAttribute("name");
> var label = child.getAttribute("label");
> var title = child.getAttribute("title");
>
> var hasChildren =
> child.getElementsByTagName("child").length > 0;
>
> //loaded[childName] = "false";
>
> log("ChildNodeName=" + child.nodeName);
> log("childName=" + childName);
> var isLeaf = child.getAttribute("isLeaf");
> html = html + "<li>";
>
> /*
> if(isLeaf == "true") {
> //do nothing
> } else {
> html = html + "<a id=\"PLUS_" + childName + "\" ";
> if(title != null) { html = html + "title=\"" + title +
> "\" "; }
> html = html + "href=\"javascript:getNodeInfo('" +
> childName + "');\"> "
> if(hasChildren) {
> html = html + "-";
> } else {
> html = html + "+";
> }
> html = html + " </a>";
> }
> */
>
> var spanStyle = "<span>";
> var isDoc = child.getAttribute("isDocument");
> var anchor = child.getAttribute("anchor");
> if(isDoc == "true") {
> html = html + "<a href=\"javascript:getDocInfo('" +
> childName +"');\">" + spanStyle + label + "</span></a>";
> } else if(anchor != null && currentDocument == treeNodeName) {
> html = html + "<a href=\"" + anchor + "\">" + label +
> "</a>";
> } else if(anchor != null) {
> log("Anchor=" + anchor);
> html = html + "<a href=\"javascript: currentAnchor='" +
> anchor + "'; getDocInfo('" + childName +"');\">" + spanStyle + label +
> "</span></a>";
> } else {
> html = html + spanStyle + " <a
> href=\"javascript:getNodeInfo('" + childName + "');\"> " + label +
> "</a></span>";
> }
> html = html + "<div id=\"" + childName + "\" ";
>
> if(hasChildren) {
> html = html + "style=\"display:inline;\"";
> } else {
> html = html + "style=\"display:none;\"";
> }
> html = html + ">";
>
> if(child.childNodes.length > 0) {
> html = html + this.outputChildren(child, treeNodeName);
> }
> html = html + "</div>";
> html = html + "</li>";
> }
>
> if(html.length > 0) {
> html = "<ul>" + html + "</ul>";
> } else {
> //html = " ";
> }
> log(html);
> return html;
> }
>
> /*
> substitute: function( tagName, tagClass, value ) {
> var elements = document.getElementsByTagAndClassName(
> tagName, tagClass);
> for ( var i = 0 ; i < elements.length ; i++ )
> elements[i].innerHTML = value;
> },*/
> };
>
> function getDocInfo(nodeName) {
> log("Sending doc info request");
>
> var now = new Date();
> log("Started at " + formatTime(now));
>
> log("NodeName=" + nodeName);
> log("CurDoc=" + currentDocument);
>
> if(nodeName && nodeName.length > 0) {
> var hash = nodeName.indexOf("#");
> var anchor = "";
> if(hash != -1) {
> anchor = nodeName.substring(hash);
> nodeName = nodeName.substring(0, hash);
> }
> }
>
> if(currentDocument && currentDocument.length > 0 &&
> currentDocument.indexOf(nodeName) >= 0) {
> log(anchor);
> if(anchor.length > 0) {
> location.hash = anchor;
> }
> log("Returning..."); return;
> }
> currentDocument = nodeName;
>
> if(nodeName == null) {
> nodeName = "";
> }
>
> var ranNum= Math.random()*4;
> ajaxEngine.sendRequest( 'getDocInfo', "node=" + nodeName,
> "builder=" + documentBuilder, "random="+ranNum);
> }
>
> function expand(nodeName) {
> log("Sending expand info");
> var ranNum= Math.random()*4;
> ajaxEngine.sendRequest( 'expandState', "node=" + nodeName,
> "action=expandState", "expandTree="+expandTree, "random="+ranNum);
> }
>
> function getNodeInfo(nodeName) {
> var div = document.getElementById(nodeName);
> //var a = document.getElementById("PLUS_" + nodeName);
> log(nodeName);
>
> if(loaded[nodeName] == "true") {
> log("Request div info for already loaded div. Will hide or
> display as appropriate.");
> if(div.style.display == "none") {
> log("Displaying node " + nodeName);
> div.style.display = "inline";
> //a.innerHTML = "-";
> expand(nodeName);
> } else {
> log("Hiding node " + nodeName);
> div.style.display = "none";
> //a.innerHTML = "+";
> expand(nodeName);
> }
> } else {
> if(div.style.display == "none") {
> log("Sending AJAX request to server");
> ajaxEngine.sendRequest( 'getNodeInfo', "node=" + nodeName,
> "builder=" + treeBuilder);
> expand(nodeName);
> }
> loaded[nodeName] = "true";
> //expand(nodeName); //TODO: add action param to getNodeInfo
> request, combine http request this way
> }
> }
>
> function expandRoot() {
> log("expandRoot");
> var ranNum= Math.random()*4;
> ajaxEngine.sendRequest( 'getNodeInfo', "node=ROOT-NODE",
> "builder="+treeBuilder, "random="+ranNum);
> }
>
> THe Java service:
>
> package com.xxxxx.xxxx.services.ajax;
>
> import java.io.*;
> import java.util.Map;
>
> import javax.servlet.ServletConfig;
> import javax.servlet.ServletContext;
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpServletResponse;
>
> import org.apache.velocity.VelocityContext;
> import org.apache.velocity.app.VelocityEngine;
> import org.apache.velocity.context.Context;
>
> import xxx.xxxxx.xxx.cms.request.XXXXRequestContext;
> import xxx.xxxxx.xxx.cms.request.XXXXRequestContextImpl;
> import xxx.xxxxx.xxx.services.context.builder.ContextBuilder;
> import xxx.xxxxx.xxx.services.context.velocity.VelocityContextImpl;
>
> /**
> * @author Jeremy Ford
> *
> */
> public class AjaxService
> {
> private boolean debug = false;
>
> private static final String WAIT_FOR_RESPONSE = "WAIT_FOR_RESPONSE";
> private static final String CONTENT_TYPE = "text/xml";
> private static final String AJAX_PROCESSOR = "AJAX processor";
>
> private static final String BUILDER = "builder";
> private static final String ACTION = "action";
>
> private VelocityEngine engine = null;
> private Map builders;
> private Map actions;
>
> private String velocityProperties =
> "/WEB-INF/velocity/velocity.properties";
>
> public AjaxService(Map builders)
> {
> this.builders = builders;
> }
>
> public AjaxService(Map builders, Map actions, VelocityEngine engine)
> {
> this.builders = builders;
> this.actions = actions;
> this.engine = engine;
> }
>
> public ContextBuilder getBuilder(String key)
> {
> return (ContextBuilder) builders.get(key);
> }
>
> public void init(ServletConfig config) throws Exception
> {
> /*
> if (engine == null)
> {
> engine = new VelocityEngine();
> Properties props = new Properties();
>
> props.load(config.getServletContext().getResourceAsStream(
> velocityProperties));
> engine.init();
> }
> */
> }
>
> public void process(HttpServletRequest request,
> HttpServletResponse response, ServletConfig servletConfig)
> {
> processAction(request, response, servletConfig);
> processRequest(request, response, servletConfig);
> }
>
> public void processAction(HttpServletRequest request,
> HttpServletResponse response, ServletConfig servletConfig)
> {
> XXXXRequestContext requestContext = new
> XXXXRequestContextImpl(request,
> response, servletConfig);
>
> String actionKey = request.getParameter(ACTION);
> if(actionKey != null) {
> AJAXRunnable action = (AJAXRunnable) actions.get(actionKey);
>
> String waitForResponse =
> request.getParameter(WAIT_FOR_RESPONSE);
>
> boolean wait = true; //by default, wait for response
>
> if(waitForResponse != null) {
> Boolean.getBoolean(waitForResponse);
> }
> if(wait) {
> action.run(requestContext);
> } else {
> //TODO: handle pooling
> Thread t = new Thread(action);
> t.start();
> }
> }
> }
>
> public void processRequest(HttpServletRequest request,
> HttpServletResponse response, ServletConfig servletConfig)
> {
> response.setContentType(CONTENT_TYPE);
>
> XXXXRequestContext requestContext = new
> XXXXRequestContextImpl(request,
> response, servletConfig);
>
> Context context = new VelocityContext();
> VelocityContextImpl responseContext = new
> VelocityContextImpl(context);
>
> String builderKey = request.getParameter(BUILDER);
> ServletContext servletContext = request.getSession()
> .getServletContext();
>
> ContextBuilder builder = getBuilder(builderKey);
> if (builder == null)
> {
> buildError();
> }
> else
> {
> try
> {
> StringWriter writer = new StringWriter();
> boolean result = builder.buildContext(requestContext,
> responseContext);
> if (result)
> {
> final InputStream templateResource = servletContext
> .getResourceAsStream(builder.getTemplate());
> Reader template = new
> InputStreamReader(templateResource);
> engine.evaluate(context, writer, AJAX_PROCESSOR,
> template);
>
> String buffer = writer.getBuffer().toString();
> if (debug)
> {
> System.out.println(buffer);
> }
> response.getWriter().write(buffer);
> }
> else
> {
> buildError();
> }
> }
> catch (Exception e)
> {
> //TODO: log
> buildError();
> e.printStackTrace();
> }
> }
> }
>
> private void buildError()
> {
>
> }
> /**
> * @param velocityProperties The velocityProperties to set.
> */
> public void setVelocityProperties(String velocityProperties)
> {
> this.velocityProperties = velocityProperties;
> }
> }
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]