[ajax4jsf-svn-commits] JBoss Ajax4JSF SVN: r263 - in trunk: a4j-portlet/src/main/java/org/ajax4jsf/portlet and 5 other directories.

ajax4jsf-svn-commits at lists.jboss.org ajax4jsf-svn-commits at lists.jboss.org
Tue Jun 12 21:28:07 EDT 2007


Author: alexsmirnov
Date: 2007-06-12 21:28:07 -0400 (Tue, 12 Jun 2007)
New Revision: 263

Added:
   trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/ComponentsLoader.java
   trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/ComponentsLoaderImpl.java
   trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/AbstractAjax4jsfPortletTestCase.java
   trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/application/
   trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/application/ComponensLoaderTestCase.java
   trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/application/PortletViewStateTestCase.java
   trunk/framework/src/main/javascript/ajaxjsf/jsshell.js
   trunk/framework/src/main/resources/org/ajax4jsf/framework/ajax/jsshell.html
Modified:
   trunk/a4j-portlet/pom.xml
   trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/AjaxFacesPortlet.java
   trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/PortalStateManager.java
   trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/PortletStateHolder.java
   trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/PortletViewState.java
   trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockActionRequest.java
   trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockActionResponse.java
   trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockPortletRequest.java
   trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockPortletResponse.java
   trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockRenderResponse.java
   trunk/framework/src/main/javascript/ajaxjsf/JSFAJAX.js
   trunk/framework/src/main/javascript/ajaxjsf/log4ajax.js
Log:
Create unit tests for a portal StateManager implementation.
Append debug JavaScript shell to a project.

Modified: trunk/a4j-portlet/pom.xml
===================================================================
--- trunk/a4j-portlet/pom.xml	2007-06-12 18:10:00 UTC (rev 262)
+++ trunk/a4j-portlet/pom.xml	2007-06-13 01:28:07 UTC (rev 263)
@@ -49,7 +49,7 @@
 		<dependency>
 			<groupId>com.sun.facelets</groupId>
 			<artifactId>jsf-facelets</artifactId>
-			<version>1.1.11</version>
+			<version>1.1.12</version>
 			<optional>true</optional>
 		</dependency>
 		<dependency>

Modified: trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/AjaxFacesPortlet.java
===================================================================
--- trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/AjaxFacesPortlet.java	2007-06-12 18:10:00 UTC (rev 262)
+++ trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/AjaxFacesPortlet.java	2007-06-13 01:28:07 UTC (rev 263)
@@ -29,6 +29,8 @@
 import javax.portlet.RenderRequest;
 import javax.portlet.RenderResponse;
 import org.ajax4jsf.framework.ajax.AjaxContext;
+import org.ajax4jsf.portlet.application.ComponentsLoader;
+import org.ajax4jsf.portlet.application.ComponentsLoaderImpl;
 import org.ajax4jsf.portlet.application.PortletStateHolder;
 import org.ajax4jsf.portlet.application.PortletViewState;
 import org.ajax4jsf.portlet.application.PortletWindowStates;
@@ -51,7 +53,10 @@
     private Lifecycle lifecycle;
 
     private FacesContextFactory facesContextFactory;
+    
+    private ComponentsLoader componentLoader;
 
+
     /*
          * (non-Javadoc)
          * 
@@ -87,7 +92,10 @@
 	    log.debug("Done portlet initialisation for "
 		    + config.getPortletName());
 	}
-	getPortletContext().setAttribute(PORTLET_CONFIG, config);
+//	getPortletContext().setAttribute(PORTLET_CONFIG, config);
+	// TODO - use only one loader instance.
+	componentLoader = new ComponentsLoaderImpl();
+
     }
 
     /*
@@ -202,7 +210,7 @@
 	UIViewRoot viewRoot = null;
 	if(null != viewId){
 	    PortletViewState viewState = states.getState(viewId);
-	    viewRoot = viewState.restore(facesContext);
+	    viewRoot = viewState.restore(facesContext,getComponentLoader());
 	} else {
 	    viewId = portletStateHolder.getViewId(facesContext);	    
 	}
@@ -319,4 +327,12 @@
 	}
 	return mode;
     }
+
+    /**
+     * @return the componentLoader
+     */
+    public ComponentsLoader getComponentLoader() {
+	// TODO - share loader instance with a StateManager
+        return componentLoader;
+    }
 }

Added: trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/ComponentsLoader.java
===================================================================
--- trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/ComponentsLoader.java	                        (rev 0)
+++ trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/ComponentsLoader.java	2007-06-13 01:28:07 UTC (rev 263)
@@ -0,0 +1,9 @@
+package org.ajax4jsf.portlet.application;
+
+import javax.faces.component.UIComponent;
+
+public interface ComponentsLoader {
+
+    public abstract UIComponent createComponent(String type);
+
+}
\ No newline at end of file

Added: trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/ComponentsLoaderImpl.java
===================================================================
--- trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/ComponentsLoaderImpl.java	                        (rev 0)
+++ trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/ComponentsLoaderImpl.java	2007-06-13 01:28:07 UTC (rev 263)
@@ -0,0 +1,81 @@
+/**
+ * 
+ */
+package org.ajax4jsf.portlet.application;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.faces.FacesException;
+import javax.faces.component.UIComponent;
+
+import org.apache.commons.collections.Transformer;
+import org.apache.commons.collections.map.LazyMap;
+
+/**
+ * @author asmirnov
+ * 
+ */
+public class ComponentsLoaderImpl implements Transformer, ComponentsLoader {
+
+    private Map classes;
+
+    private ClassLoader loader;
+
+    public ComponentsLoaderImpl() {
+	classes = Collections.synchronizedMap(LazyMap.decorate(new HashMap(),
+		this));
+    }
+
+    /*
+         * (non-Javadoc)
+         * 
+         * @see org.ajax4jsf.portlet.application.ComponentsLoader#createComponent(java.lang.String)
+         */
+    public UIComponent createComponent(String type) {
+	// Classes is a lazy Map, new object will be create on the fly.
+	Class componentClass = (Class) classes.get(type);
+	try {
+	    return (UIComponent) componentClass.newInstance();
+	} catch (InstantiationException e) {
+	    throw new FacesException(
+		    "Error on create new instance of the component with class "
+			    + type, e);
+	} catch (IllegalAccessException e) {
+	    throw new FacesException(
+		    "IllegalAccess on attempt to create new instance of the component with class "
+			    + type, e);
+	}
+    }
+
+    public Object transform(Object input) {
+	if (null == input) {
+	    throw new NullPointerException(
+		    "Name for a UIComponent class to restore is null");
+	}
+	ClassLoader loader = getClassLoader();
+	Class componentClass = null;
+	try {
+	    componentClass = loader.loadClass(input.toString());
+	} catch (ClassNotFoundException e) {
+	    throw new FacesException("Can't load class " + input.toString(), e);
+	}
+	return componentClass;
+    }
+
+    /**
+     * lazy create ClassLoader instance.
+         * @return
+         */
+    private ClassLoader getClassLoader() {
+	if (loader == null) {
+	    loader = Thread.currentThread().getContextClassLoader();
+	    if (loader == null) {
+		loader = this.getClass().getClassLoader();
+	    }
+
+	}
+	return loader;
+    }
+}

Modified: trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/PortalStateManager.java
===================================================================
--- trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/PortalStateManager.java	2007-06-12 18:10:00 UTC (rev 262)
+++ trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/PortalStateManager.java	2007-06-13 01:28:07 UTC (rev 263)
@@ -24,11 +24,14 @@
 public class PortalStateManager extends AjaxStateManager {
     
     private static final String VIEW_STATES_MAP = PortalStateManager.class.getName();
+    
+    private ComponentsLoader componentLoader;
     /**
      * 
      */
     public PortalStateManager(StateManager parentStateManager) {
 	super(parentStateManager);
+	componentLoader = new ComponentsLoaderImpl();
     }
 
     /* (non-Javadoc)
@@ -43,7 +46,7 @@
 	    PortletStateHolder portletStateHolder = PortletStateHolder.getInstance(context);
 	    PortletWindowStates windowStates = portletStateHolder.getWindowStates(context);
 	    PortletViewState viewState = windowStates.getState(viewId);
-	    viewRoot = viewState.restore(context);
+	    viewRoot = viewState.restore(context,componentLoader);
 	}
 	// TODO - implement portal-specific view state.
 	    return viewRoot;
@@ -66,20 +69,4 @@
 	return serializedView;
     }
     
-    
-    private Map getStatesMap(FacesContext context){
-	Map stateMap;
-	ExternalContext externalContext = context.getExternalContext();
-	Map sessionMap = externalContext.getSessionMap();
-	Object session = externalContext.getSession(false);
-	synchronized (session) {
-	    stateMap = (Map) sessionMap.get(VIEW_STATES_MAP);
-	    if(null == stateMap){
-		stateMap = new LRUMap();
-		sessionMap.put(VIEW_STATES_MAP, stateMap);
-	    }
-	}
-	return stateMap;
-    }
-    
 }

Modified: trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/PortletStateHolder.java
===================================================================
--- trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/PortletStateHolder.java	2007-06-12 18:10:00 UTC (rev 262)
+++ trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/PortletStateHolder.java	2007-06-13 01:28:07 UTC (rev 263)
@@ -103,7 +103,7 @@
 	    viewId = (String) context.getExternalContext().getRequestParameterMap().get(AbstractExternalContext.VIEW_ID_PARAMETER);
 	}
 	// If none of above happen, try to get default viewId for a current mode.
-	PortletConfig config = (PortletConfig) context.getExternalContext().getApplicationMap().get(AjaxFacesPortlet.PORTLET_CONFIG);
+	PortletConfig config = (PortletConfig) context.getExternalContext().getRequestMap().get(AjaxFacesPortlet.PORTLET_CONFIG);
 	if (null == viewId && null != config) {
 		PortletMode portletMode = AjaxFacesPortlet.getPortletMode(context);
 		if(null == portletMode){

Modified: trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/PortletViewState.java
===================================================================
--- trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/PortletViewState.java	2007-06-12 18:10:00 UTC (rev 262)
+++ trunk/a4j-portlet/src/main/java/org/ajax4jsf/portlet/application/PortletViewState.java	2007-06-13 01:28:07 UTC (rev 263)
@@ -69,12 +69,12 @@
 	}
     }
 
-    public UIViewRoot restore(FacesContext facesContext) {
+    public UIViewRoot restore(FacesContext facesContext,ComponentsLoader loader) {
 	// facesContext.setViewRoot(getViewRoot());
 	TreeStrutureNode structure = (TreeStrutureNode) getTreeStructure();
 	UIViewRoot root = null;
 	if (null != structure) {
-	    root = (UIViewRoot) structure.restore();
+	    root = (UIViewRoot) structure.restore(loader);
 	    root.processRestoreState(facesContext, getComponentsState());
 	    // facesContext.setViewRoot(root);
 	    if (facesContext.getExternalContext().getRequest() instanceof RenderRequest) {
@@ -183,7 +183,7 @@
 	this.treeStructure = treeStructure;
     }
 
-    private static class TreeStrutureNode implements Serializable {
+    protected static class TreeStrutureNode implements Serializable {
 	/**
          * 
          */
@@ -223,29 +223,19 @@
 	    }
 	}
 
-	public UIComponent restore() {
+	public UIComponent restore(ComponentsLoader loader) {
 	    UIComponent component;
-	    ClassLoader loader = Thread.currentThread().getContextClassLoader();
-	    if (loader == null) {
-		loader = this.getClass().getClassLoader();
-	    }
-	    try {
-		Class componentClass = loader.loadClass(type);
-		component = (UIComponent) componentClass.newInstance();
+		component = loader.createComponent(type);
 		component.setId(id);
-	    } catch (Exception e) {
-		throw new FacesException("Error to restore component instance",
-			e);
-	    }
 	    for (Iterator i = facets.entrySet().iterator(); i.hasNext();) {
 		Entry element = (Entry) i.next();
 		UIComponent facet = ((TreeStrutureNode) element.getValue())
-			.restore();
+			.restore(loader);
 		component.getFacets().put(element.getKey(), facet);
 	    }
 	    for (Iterator i = children.iterator(); i.hasNext();) {
 		TreeStrutureNode node = (TreeStrutureNode) i.next();
-		UIComponent child = node.restore();
+		UIComponent child = node.restore(loader);
 		component.getChildren().add(child);
 	    }
 	    return component;

Added: trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/AbstractAjax4jsfPortletTestCase.java
===================================================================
--- trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/AbstractAjax4jsfPortletTestCase.java	                        (rev 0)
+++ trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/AbstractAjax4jsfPortletTestCase.java	2007-06-13 01:28:07 UTC (rev 263)
@@ -0,0 +1,59 @@
+/**
+ * 
+ */
+package org.ajax4jsf.portlet;
+
+import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
+
+/**
+ * @author asmirnov
+ *
+ */
+public class AbstractAjax4jsfPortletTestCase extends AbstractAjax4JsfTestCase {
+
+    protected MockActionRequest actionRequest;
+    protected MockActionResponse actionResponse;
+    protected MockPortletContext portletContext;
+    protected MockRenderRequest renderRequest;
+    protected MockRenderResponse renderResponse;
+
+    public AbstractAjax4jsfPortletTestCase(String name) {
+	super(name);
+    }
+    
+    public void setUp() throws Exception {
+        super.setUp();
+    }
+    
+    public void tearDown() throws Exception {
+        super.tearDown();
+        actionRequest = null;
+        actionResponse = null;
+        renderRequest = null;
+        renderResponse = null;
+        portletContext = null;
+    }
+
+    /**
+     * 
+     */
+    protected void setupActionRequest() {
+        actionRequest = new MockActionRequest();
+	actionResponse = new MockActionResponse();
+	portletContext = new MockPortletContext();
+	externalContext.setRequest(actionRequest);
+        externalContext.setResponse(actionResponse);
+    }
+
+    /**
+     * 
+     */
+    protected void setupRenderRequest() {
+        renderRequest = new MockRenderRequest();
+	renderResponse = new MockRenderResponse();
+	portletContext = new MockPortletContext();
+	externalContext.setRequest(renderRequest);
+        externalContext.setResponse(renderResponse);
+    }
+
+}

Modified: trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockActionRequest.java
===================================================================
--- trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockActionRequest.java	2007-06-12 18:10:00 UTC (rev 262)
+++ trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockActionRequest.java	2007-06-13 01:28:07 UTC (rev 263)
@@ -50,8 +50,7 @@
     /* (non-Javadoc)
      * @see javax.portlet.ActionRequest#getReader()
      */
-    public BufferedReader getReader() throws UnsupportedEncodingException,
-	    IOException {
+    public BufferedReader getReader() {
 	// TODO Auto-generated method stub
 	return null;
     }
@@ -59,8 +58,7 @@
     /* (non-Javadoc)
      * @see javax.portlet.ActionRequest#setCharacterEncoding(java.lang.String)
      */
-    public void setCharacterEncoding(String arg0)
-	    throws UnsupportedEncodingException {
+    public void setCharacterEncoding(String arg0) {
 	// TODO Auto-generated method stub
     }
 }

Modified: trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockActionResponse.java
===================================================================
--- trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockActionResponse.java	2007-06-12 18:10:00 UTC (rev 262)
+++ trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockActionResponse.java	2007-06-13 01:28:07 UTC (rev 263)
@@ -20,7 +20,7 @@
     /* (non-Javadoc)
      * @see javax.portlet.ActionResponse#sendRedirect(java.lang.String)
      */
-    public void sendRedirect(String arg0) throws IOException {
+    public void sendRedirect(String arg0) {
 	// TODO Auto-generated method stub
     }
 

Modified: trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockPortletRequest.java
===================================================================
--- trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockPortletRequest.java	2007-06-12 18:10:00 UTC (rev 262)
+++ trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockPortletRequest.java	2007-06-13 01:28:07 UTC (rev 263)
@@ -17,11 +17,13 @@
 import javax.portlet.PortletSession;
 import javax.portlet.WindowState;
 
+import org.apache.shale.test.mock.MockHttpServletRequest;
+
 /**
  * @author asmirnov
  *
  */
-public class MockPortletRequest implements PortletRequest {
+public class MockPortletRequest extends MockHttpServletRequest implements PortletRequest {
     
     public static final String PARAMETER_VALUE2 = "value2";
     public static final String PARAMETER_VALUE1 = "value1";

Modified: trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockPortletResponse.java
===================================================================
--- trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockPortletResponse.java	2007-06-12 18:10:00 UTC (rev 262)
+++ trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockPortletResponse.java	2007-06-13 01:28:07 UTC (rev 263)
@@ -5,11 +5,13 @@
 
 import javax.portlet.PortletResponse;
 
+import org.apache.shale.test.mock.MockHttpServletResponse;
+
 /**
  * @author asmirnov
  *
  */
-public class MockPortletResponse implements PortletResponse {
+public class MockPortletResponse extends MockHttpServletResponse implements PortletResponse {
     /* (non-Javadoc)
      * @see javax.portlet.PortletResponse#addProperty(java.lang.String, java.lang.String)
      */

Modified: trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockRenderResponse.java
===================================================================
--- trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockRenderResponse.java	2007-06-12 18:10:00 UTC (rev 262)
+++ trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/MockRenderResponse.java	2007-06-13 01:28:07 UTC (rev 263)
@@ -35,7 +35,7 @@
     /* (non-Javadoc)
      * @see javax.portlet.RenderResponse#flushBuffer()
      */
-    public void flushBuffer() throws IOException {
+    public void flushBuffer() {
 	// TODO Auto-generated method stub
     }
 

Added: trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/application/ComponensLoaderTestCase.java
===================================================================
--- trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/application/ComponensLoaderTestCase.java	                        (rev 0)
+++ trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/application/ComponensLoaderTestCase.java	2007-06-13 01:28:07 UTC (rev 263)
@@ -0,0 +1,39 @@
+package org.ajax4jsf.portlet.application;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.component.UIOutput;
+
+import org.ajax4jsf.tests.AbstractAjax4JsfTestCase;
+
+public class ComponensLoaderTestCase extends AbstractAjax4JsfTestCase {
+    
+    ComponentsLoaderImpl loader;
+
+    public ComponensLoaderTestCase(String name) {
+	super(name);
+    }
+
+    public void setUp() throws Exception {
+	super.setUp();
+	loader = new ComponentsLoaderImpl();
+    }
+
+    public void tearDown() throws Exception {
+	super.tearDown();
+	loader = null;
+    }
+
+    public final void testCreateComponent() {
+	UIComponent component = loader.createComponent(UIInput.class.getName());	
+	assertSame(UIInput.class, component.getClass());
+	UIComponent component1 = loader.createComponent(UIOutput.class.getName());	
+	assertSame(UIOutput.class, component1.getClass());
+    }
+
+    public final void testTransform() {
+	Object inputClass = loader.transform(UIInput.class.getName());
+	assertSame(UIInput.class, inputClass);
+    }
+
+}

Added: trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/application/PortletViewStateTestCase.java
===================================================================
--- trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/application/PortletViewStateTestCase.java	                        (rev 0)
+++ trunk/a4j-portlet/src/test/java/org/ajax4jsf/portlet/application/PortletViewStateTestCase.java	2007-06-13 01:28:07 UTC (rev 263)
@@ -0,0 +1,89 @@
+package org.ajax4jsf.portlet.application;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.application.FacesMessage.Severity;
+import javax.faces.component.UIInput;
+import javax.faces.component.UIOutput;
+import javax.faces.component.UIViewRoot;
+
+import org.ajax4jsf.portlet.AbstractAjax4jsfPortletTestCase;
+import org.ajax4jsf.portlet.application.PortletViewState.TreeStrutureNode;
+
+import junit.framework.TestCase;
+
+public class PortletViewStateTestCase extends AbstractAjax4jsfPortletTestCase {
+
+    ComponentsLoaderImpl loader;
+    private UIInput input;
+    private UIOutput output;
+    
+    public PortletViewStateTestCase(String name) {
+	super(name);
+    }
+
+    public void setUp() throws Exception {
+	super.setUp();
+    }
+
+    public void tearDown() throws Exception {
+	super.tearDown();
+    }
+
+    public final void testSave() {
+	setupActionRequest();
+	setupTree();
+	PortletViewState state = new PortletViewState();
+	state.save(facesContext);
+	assertNotNull(state.getComponentsState());
+	Object treeStructure = state.getTreeStructure();
+	assertTrue(treeStructure instanceof TreeStrutureNode);
+    }
+
+    /**
+     * 
+     */
+    private void setupTree() {
+	input = new UIInput();
+	input.setId("in");
+	UIViewRoot viewRoot = facesContext.getViewRoot();
+	viewRoot.getChildren().add(input);
+	output = new UIOutput();
+	output.setId("out");
+	viewRoot.getFacets().put("facet",output);
+    }
+
+    public final void testSaveMessages() {
+	setupActionRequest();
+	setupTree();
+	String clientId = input.getClientId(facesContext);
+	FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR,"msg","detail");
+	facesContext.addMessage(clientId, facesMessage);
+	PortletViewState state = new PortletViewState();
+	state.saveMessages(facesContext);
+	Map messages = state.getMessages();
+	assertEquals(1, messages.size());
+	List list = (List)messages.get(clientId);
+	assertEquals(1, list.size());
+	assertSame(facesMessage, list.get(0));
+    }
+
+    public final void testRestore() {
+	// TODO - implement test
+    }
+
+    public final void testRestoreMessages() {
+	// TODO - implement test
+    }
+
+    public final void testGetComponentsState() {
+	// TODO - implement test
+    }
+
+    public final void testGetTreeStructure() {
+	// TODO - implement test
+    }
+
+}

Modified: trunk/framework/src/main/javascript/ajaxjsf/JSFAJAX.js
===================================================================
--- trunk/framework/src/main/javascript/ajaxjsf/JSFAJAX.js	2007-06-12 18:10:00 UTC (rev 262)
+++ trunk/framework/src/main/javascript/ajaxjsf/JSFAJAX.js	2007-06-13 01:28:07 UTC (rev 263)
@@ -834,6 +834,20 @@
           		}
           	}
           };
+
+A4J.AJAX.getCursorPos =	function(inp){
+
+		   if(inp.selectionEnd != null)
+		     return inp.selectionEnd;
+		
+		   // IE specific code
+		   var range = document.selection.createRange();
+		   var isCollapsed = range.compareEndPoints("StartToEnd", range) == 0;
+		   if (!isCollapsed)
+		     range.collapse(false);
+		   var b = range.getBookmark();
+		   return b.charCodeAt(2) - 2;
+		}
           
 	// Locate enclosing form for object.
 A4J.AJAX.locateForm = function(obj){

Added: trunk/framework/src/main/javascript/ajaxjsf/jsshell.js
===================================================================
--- trunk/framework/src/main/javascript/ajaxjsf/jsshell.js	                        (rev 0)
+++ trunk/framework/src/main/javascript/ajaxjsf/jsshell.js	2007-06-13 01:28:07 UTC (rev 263)
@@ -0,0 +1,7 @@
+// short bookmarklet
+// javascript:function loadScript(scriptURL) { var scriptElem = document.createElement('SCRIPT'); scriptElem.setAttribute('language', 'JavaScript'); scriptElem.setAttribute('src', scriptURL); document.body.appendChild(scriptElem);} loadScript('http://blog.monstuff.com/archives/images/jsshell.js');
+
+
+with(window.open("","_blank","width="+screen.width*.6+",left="+screen.width*.35+",height="+screen.height*.9+",resizable,scrollbars=yes")){document.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n\n<html onclick=\"keepFocusInTextbox(event)\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n<title>JavaScript Shell 1.4 modified to support IE</title>\n\n<script type=\"text/javascript\">\nvar \nhistList = [\"\"], \nhistPos = 0, \n_scope = {}, \n_win, // a top-level context\nquestion,\n_in,\n_out,\ntooManyMatches = null,\nlastError = null;\n\nfunction refocus()\n{\n  _in.blur(); // Needed for Mozilla to scroll correctly.\n  _in.focus();\n}\n\nfunction init()\n{\n  _in = document.getElementById(\"input\");\n  _out = document.getElementById(\"output\");\n\n  _win = window;\n\n  if (opener && !opener.closed)\n  {\n    println(\"Using bookmarklet version of shell: commands will run in opener!
 's context.\", \"message\");\n    _win = opener;\n  }\n\n  initTarget();\n\n  recalculateInputHeight();\n  refocus();\n}\n\nfunction initTarget()\n{\n  _win.Shell = window;\n  _win.print = shellCommands.print;\n}\n\n\n// Unless the user is selected something, refocus the textbox.\n// (requested by caillon, brendan, asa)\nfunction keepFocusInTextbox(e) \n{\n  var g = e.srcElement ? e.srcElement : e.target; // IE vs. standard\n  \n  while (!g.tagName)\n    g = g.parentNode;\n  var t = g.tagName.toUpperCase();\n  if (t==\"A\" || t==\"INPUT\")\n    return;\n    \n  if (window.getSelection) {\n    // Mozilla\n    if (String(window.getSelection()))\n      return;\n  }\n  else if (document.getSelection) {\n    // Opera? Netscape 4?\n    if (document.getSelection())\n      return;\n  }\n  else {\n    // IE\n    if ( document.selection.createRange().text )\n      return;\n  }\n  \n  refocus();\n}\n\nfunction inputKeydown(e) {\n  // Use onkeydown because IE doesn't support onkeypress!
  for arrow keys\n\n  //alert(e.keyCode + \" ^ \" + e.keycode);\n\n  if
 (e.shiftKey && e.keyCode == 13) { // shift-enter\n    // don't do anything; allow the shift-enter to insert a line break as normal\n  } else if (e.keyCode == 13) { // enter\n    // execute the input on enter\n    try { go(); } catch(er) { alert(er); };\n    setTimeout(function() { _in.value = \"\"; }, 0); // can't preventDefault on input, so clear it later\n  } else if (e.keyCode == 38) { // up\n    // go up in history if at top or ctrl-up\n    if (e.ctrlKey || caretInFirstLine(_in))\n      hist(true);\n  } else if (e.keyCode == 40) { // down\n    // go down in history if at end or ctrl-down\n    if (e.ctrlKey || caretInLastLine(_in))\n      hist(false);\n  } "+
+"else if(e.ctrlKey && e.keyCode == 32) { // ctrl-space\n    tabcomplete();\n    e.cancelBubble = false;\n    e.returnValue = false;\n    return false; }" +
+"else if (e.keyCode == 9) { // tab\n    tabcomplete();\n    setTimeout(function() { refocus(); }, 0); // refocus because tab was hit\n  } else { }\n\n  setTimeout(recalculateInputHeight, 0);\n  \n  //return true;\n};\n\nfunction caretInFirstLine(textbox)\n{\n  // IE doesn't support selectionStart/selectionEnd\n  if (textbox.selectionStart == undefined)\n    return true;\n\n  var firstLineBreak = textbox.value.indexOf(\"\\n\");\n  \n  return ((firstLineBreak == -1) || (textbox.selectionStart <= firstLineBreak));\n}\n\nfunction caretInLastLine(textbox)\n{\n  // IE doesn't support selectionStart/selectionEnd\n  if (textbox.selectionEnd == undefined)\n    return true;\n\n  var lastLineBreak = textbox.value.lastIndexOf(\"\\n\");\n  \n  return (textbox.selectionEnd > lastLineBreak);\n}\n\nfunction recalculateInputHeight()\n{\n  var rows = _in.value.split(/\\n/).length\n    + 1 // prevent scrollbar flickering in Mozilla\n    + (window.opera ? 1 : 0); // leave room for scrollbar in!
  Opera\n  \n  if (_in.rows != rows) // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0.\n    _in.rows = rows;\n}\n\nfunction println(s, type)\n{\n  if((s=String(s)))\n  {\n    var newdiv = document.createElement(\"div\");\n    newdiv.appendChild(document.createTextNode(s));\n    newdiv.className = type;\n    _out.appendChild(newdiv);\n    return newdiv;\n  }\n}\n\nfunction printWithRunin(h, s, type)\n{\n  var div = println(s, type);\n  var head = document.createElement(\"strong\");\n  head.appendChild(document.createTextNode(h + \": \"));\n  div.insertBefore(head, div.firstChild);\n}\n\n\nvar shellCommands = \n{\nload : function load(url)\n{\n  var s = _win.document.createElement(\"script\");\n  s.type = \"text/javascript\";\n  s.src = url;\n  _win.document.getElementsByTagName(\"head\")[0].appendChild(s);\n  println(\"Loading \" + url + \"...\", \"message\");\n},\n\nclear : function clear()\n{\n  var CHILDREN_TO_PRESERVE = 3;\n  while (_out.c!
 hildNodes[CHILDREN_TO_PRESERVE]) \n    _out.removeChild(_out.childNode
s[CHILDREN_TO_PRESERVE]);\n},\n\nprint : function print(s) { println(s, \"print\"); },\n\n// the normal function, \"print\", shouldn't return a value\n// (suggested by brendan; later noticed it was a problem when showing others)\npr : function pr(s) \n{ \n  shellCommands.print(s); // need to specify shellCommands so it doesn't try window.print()!\n  return s;\n},\n\nprops : function props(e, onePerLine)\n{\n  if (e === null) {\n    println(\"props called with null argument\", \"error\");\n    return;\n  }\n\n  if (e === undefined) {\n    println(\"props called with undefined argument\", \"error\");\n    return;\n  }\n\n  var ns = [\"Methods\", \"Fields\", \"Unreachables\"];\n  var as = [[], [], []]; // array of (empty) arrays of arrays!\n  var p, j, i; // loop variables, several used multiple times\n\n  var protoLevels = 0;\n\n  for (p = e; p; p = p.__proto__)\n  {\n    for (i=0; i<ns.length; ++i)\n      as[i][protoLevels] = [];\n    ++protoLevels;\n  }\n\n  for(var a in e)\!
 n  {\n    // Shortcoming: doesn't check that VALUES are the same in object and prototype.\n\n    var protoLevel = -1;\n    try\n    {\n      for (p = e; p && (a in p); p = p.__proto__)\n        ++protoLevel;\n    }\n    catch(er) { protoLevel = 0; } // \"in\" operator throws when param to props() is a string\n\n    var type = 1;\n    try\n    {\n      if ((typeof e[a]) == \"function\")\n        type = 0;\n    }\n    catch (er) { type = 2; }\n\n    as[type][protoLevel].push(a);\n  }\n\n  function times(s, n) { return n ? s + times(s, n-1) : \"\"; }\n\n  for (j=0; j<protoLevels; ++j)\n    for (i=0;i<ns.length;++i)\n      if (as[i][j].length) \n        printWithRunin(\n          ns[i] + times(\" of prototype\", j), \n          (onePerLine ? \"\\n\\n\" : \"\") + as[i][j].sort().join(onePerLine ? \"\\n\" : \", \") + (onePerLine ? \"\\n\\n\" : \"\"), \n          \"propList\"\n        );\n},\n\nblink : function blink(node)\n{\n  if (!node)                     throw(\"blink: argume!
 nt is null or undefined.\");\n  if (node.nodeType == null)     throw(\
"blink: argument must be a node.\");\n  if (node.nodeType == 3)        throw(\"blink: argument must not be a text node\");\n  if (node.documentElement)      throw(\"blink: argument must not be the document object\");\n\n  function setOutline(o) { \n    return function() {\n      if (node.style.outline != node.style.bogusProperty) {\n        // browser supports outline (Firefox 1.1 and newer, CSS3, Opera 8).\n        node.style.outline = o;\n      }\n      else if (node.style.MozOutline != node.style.bogusProperty) {\n        // browser supports MozOutline (Firefox 1.0.x and older)\n        node.style.MozOutline = o;\n      }\n      else {\n        // browser only supports border (IE). border is a fallback because it moves things around.\n        node.style.border = o;\n      }\n    }\n  } \n  \n  function focusIt(a) {\n    return function() {\n      a.focus(); \n    }\n  }\n\n  if (node.ownerDocument) {\n    var windowToFocusNow = (node.ownerDocument.defaultView || node.owne!
 rDocument.parentWindow); // Moz vs. IE\n    if (windowToFocusNow)\n      setTimeout(focusIt(windowToFocusNow.top), 0);\n  }\n\n  for(var i=1;i<7;++i)\n    setTimeout(setOutline((i%252)?'3px solid red':'none'), i*100);\n\n  setTimeout(focusIt(window), 800);\n  setTimeout(focusIt(_in), 810);\n},\n\nscope : function scope(sc)\n{\n  if (!sc) sc = {};\n  _scope = sc;\n  println(\"Scope is now \" + sc + \".  If a variable is not found in this scope, window will also be searched.  New variables will still go on window.\", \"message\");\n},\n\nmathHelp : function mathHelp()\n{\n  printWithRunin(\"Math constants\", \"E, LN2, LN10, LOG2E, LOG10E, PI, SQRT1_2, SQRT2\", \"propList\");\n  printWithRunin(\"Math methods\", \"abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random, round, sin, sqrt, tan\", \"propList\");\n},\n\nans : undefined\n};\n\n\nfunction hist(up)\n{\n  // histList[0] = first command entered, [1] = second, etc.\n  // type something, press up -!
 -> thing typed is now in \"limbo\"\n  // (last item in histList) and s
hould be reachable by pressing \n  // down again.\n\n  var L = histList.length;\n\n  if (L == 1)\n    return;\n\n  if (up)\n  {\n    if (histPos == L-1)\n    {\n      // Save this entry in case the user hits the down key.\n      histList[histPos] = _in.value;\n    }\n\n    if (histPos > 0)\n    {\n      histPos--;\n      // Use a timeout to prevent up from moving cursor within new text\n      // Set to nothing first for the same reason\n      setTimeout(\n        function() {\n          _in.value = ''; \n          _in.value = histList[histPos];\n          var caretPos = _in.value.length;\n          if (_in.setSelectionRange) \n            _in.setSelectionRange(caretPos, caretPos);\n        },\n        0\n      );\n    }\n  } \n  else // down\n  {\n    if (histPos < L-1)\n    {\n      histPos++;\n      _in.value = histList[histPos];\n    }\n    else if (histPos == L-1)\n    {\n      // Already on the current entry: clear but save\n      if (_in.value)\n      {\n        histLi!
 st[histPos] = _in.value;\n        ++histPos;\n        _in.value = \"\";\n      }\n    }\n  }\n}\n\nfunction tabcomplete()\n{\n  /*\n   * Working backwards from s[from], find the spot\n   * where this expression starts.  It will scan\n   * until it hits a mismatched ( or a space,\n   * but it skips over quoted strings.\n   * If stopAtDot is true, stop at a '.'\n   */\n  function findbeginning(s, from, stopAtDot)\n  {\n    /*\n     *  Complicated function.\n     *\n     *  Return true if s[i] == q BUT ONLY IF\n     *  s[i-1] is not a backslash.\n     */\n    function equalButNotEscaped(s,i,q)\n    {\n      if(s.charAt(i) != q) // not equal go no further\n        return false;\n\n      if(i==0) // beginning of string\n        return true;\n\n      if(s.charAt(i-1) == '\\\\') // escaped?\n        return false;\n\n      return true;\n    }\n\n    var nparens = 0;\n    var i;\n    for(i=from; i>=0; i--)\n    {\n      if(s.charAt(i) == ' ')\n        break;\n\n      if(stopAtDot &&!
  s.charAt(i) == '.')\n        break;\n        \n      if(s.charAt(i) =
= ')')\n        nparens++;\n      else if(s.charAt(i) == '(')\n        nparens--;\n\n      if(nparens < 0)\n        break;\n\n      // skip quoted strings\n      if(s.charAt(i) == '\\'' || s.charAt(i) == '\\\"')\n      {\n        //dump(\"skipping quoted chars: \");\n        var quot = s.charAt(i);\n        i--;\n        while(i >= 0 && !equalButNotEscaped(s,i,quot)) {\n          //dump(s.charAt(i));\n          i--;\n        }\n        //dump(\"\\n\");\n      }\n    }\n    return i;\n  }\n\n  // XXX should be used more consistently (instead of using selectionStart/selectionEnd throughout code)\n  // XXX doesn't work in IE, even though it contains IE-specific code\n  function getcaretpos(inp)\n  {\n    if(inp.selectionEnd != null)\n      return inp.selectionEnd;\n      \n    var range = document.selection.createRange();\n    var isCollapsed = range.compareEndPoints(\"StartToEnd\", range) == 0;\n    if (!isCollapsed)\n        range.collapse(false);\n    var b = range.getBookma!
 rk();\n    return b.charCodeAt(2) - 2;  \n  }\n\n  function setselectionto(inp,pos)\n  {\n    if(inp.selectionStart) {\n      inp.selectionStart = inp.selectionEnd = pos;\n    }\n    else if(inp.createTextRange) {\n      var docrange = _win.Shell.document.selection.createRange();\n      var inprange = inp.createTextRange();\n      inprange.move('character',pos);\n      inprange.select();\n    }\n    else { // err...\n    /*\n      inp.select();\n      if(_win.Shell.document.getSelection())\n        _win.Shell.document.getSelection() = \"\";\n        */\n    }\n  }\n    // get position of cursor within the input box\n    var caret = getcaretpos(_in);\n\n    if(caret) {\n      //dump(\"----\\n\");\n      var dotpos, spacepos, complete, obj;\n      //dump(\"caret pos: \" + caret + \"\\n\");\n      // see if there's a dot before here\n      dotpos = findbeginning(_in.value, caret-1, true);\n      //dump(\"dot pos: \" + dotpos + \"\\n\");\n      if(dotpos == -1 || _in.value.char!
 At(dotpos) != '.') {\n        dotpos = caret;\n//dump(\"changed dot po
s: \" + dotpos + \"\\n\");\n      }\n\n      // look backwards for a non-variable-name character\n      spacepos = findbeginning(_in.value, dotpos-1, false);\n      //dump(\"space pos: \" + spacepos + \"\\n\");\n      // get the object we're trying to complete on\n      if(spacepos == dotpos || spacepos+1 == dotpos || dotpos == caret)\n      {\n        // try completing function args\n        if(_in.value.charAt(dotpos) == '(' ||\n (_in.value.charAt(spacepos) == '(' && (spacepos+1) == dotpos))\n        {\n          var fn,fname;\n  var from = (_in.value.charAt(dotpos) == '(') ? dotpos : spacepos;\n          spacepos = findbeginning(_in.value, from-1, false);\n\n          fname = _in.value.substr(spacepos+1,from-(spacepos+1));\n  //dump(\"fname: \" + fname + \"\\n\");\n          try {\n            with(_win.Shell._scope)\n              with(_win)\n                with(Shell.shellCommands)\n                  fn = eval(fname);\n          }\n          catch(er) {\n            //!
 dump('fn is not a valid object\\n');\n            return;\n          }\n          if(fn == undefined) {\n             //dump('fn is undefined');\n             return;\n          }\n          if(fn instanceof Function)\n          {\n            // Print function definition, including argument names, but not function body\n            if(!fn.toString().match(/function .+?\\(\\) +\\{\\n +\\[native code\\]\\n\\}/))\n              println(fn.toString().match(/function .+?\\(.*?\\)/), \"tabcomplete\");\n          }\n\n          return;\n        }\n        else\n          obj = _win;\n      }\n      else\n      {\n        var objname = _in.value.substr(spacepos+1,dotpos-(spacepos+1));\n        //dump(\"objname: |\" + objname + \"|\\n\");\n        try {\n          with(_win.Shell._scope)\n            with(_win)\n                obj = eval(objname);\n        }\n        catch(er) {\n          printError(er); \n          return;\n        }\n        if(obj == undefined) {\n          //!
  sometimes this is tabcomplete's fault, so don't print it :(\n        
  // e.g. completing from \"print(document.getElements\"\n          // println(\"Can't complete from null or undefined expression \" + objname, \"error\");\n          return;\n        }\n      }\n      //dump(\"obj: \" + obj + \"\\n\");\n      // get the thing we're trying to complete\n      if(dotpos == caret)\n      {\n        if(spacepos+1 == dotpos || spacepos == dotpos)\n        {\n          // nothing to complete\n          //dump(\"nothing to complete\\n\");\n          return;\n        }\n\n        complete = _in.value.substr(spacepos+1,dotpos-(spacepos+1));\n      }\n      else {\n        complete = _in.value.substr(dotpos+1,caret-(dotpos+1));\n      }\n      //dump(\"complete: \" + complete + \"\\n\");\n      // ok, now look at all the props/methods of this obj\n      // and find ones starting with 'complete'\n      var matches = [];\n      var bestmatch = null;\n      for(var a in obj)\n      {\n        //a = a.toString();\n        //XXX: making it lowercase could !
 help some cases,\n        // but screws up my general logic.\n        if(a.substr(0,complete.length) == complete) {\n          matches.push(a);\n          ////dump(\"match: \" + a + \"\\n\");\n          // if no best match, this is the best match\n          if(bestmatch == null)\n          {\n            bestmatch = a;\n          }\n          else {\n            // the best match is the longest common string\n            function min(a,b){ return ((a<b)?a:b); }\n            var i;\n            for(i=0; i< min(bestmatch.length, a.length); i++)\n            {\n              if(bestmatch.charAt(i) != a.charAt(i))\n                break;\n            }\n            bestmatch = bestmatch.substr(0,i);\n            ////dump(\"bestmatch len: \" + i + \"\\n\");\n          }\n          ////dump(\"bestmatch: \" + bestmatch + \"\\n\");\n        }\n      }\n      bestmatch = (bestmatch || \"\");\n      ////dump(\"matches: \" + matches + \"\\n\");\n      var objAndComplete = (objname || !
 obj) + \".\" + bestmatch;\n      //dump(\"matches.length: \" + matches
.length + \", tooManyMatches: \" + tooManyMatches + \", objAndComplete: \" + objAndComplete + \"\\n\");\n      if(matches.length > 1 && (tooManyMatches == objAndComplete || matches.length <= 10)) {\n\n        printWithRunin(\"Matches: \", matches.join(', '), \"tabcomplete\");\n        tooManyMatches = null;\n      }\n      else if(matches.length > 10)\n      {\n        println(matches.length + \" matches.  Press tab or ctrl-space again to see them all\", \"tabcomplete\");\n        tooManyMatches = objAndComplete;\n      }\n      else {\n        tooManyMatches = null;\n      }\n      if(bestmatch != \"\")\n      {\n        var sstart;\n        if(dotpos == caret) {\n          sstart = spacepos+1;\n        }\n        else {\n          sstart = dotpos+1;\n        }\n        _in.value = _in.value.substr(0, sstart)\n                  + bestmatch\n                  + _in.value.substr(caret);\n        setselectionto(_in,caret + (bestmatch.length - complete.length));\n      }\n    }!
 \n}\n\nfunction printQuestion(q)\n{\n  println(q, \"input\");\n}\n\nfunction printAnswer(a)\n{\n  if (a !== undefined) {\n    println(a, \"normalOutput\");\n    shellCommands.ans = a;\n  }\n}\n\nfunction printError(er)\n{ \n  var lineNumberString;\n\n  lastError = er; // for debugging the shell\n  if (er.name)\n  {\n    // lineNumberString should not be \"\", to avoid a very wacky bug in IE 6.\n    lineNumberString = (er.lineNumber != undefined) ? (\" on line \" + er.lineNumber + \": \") : \": \";\n    println(er.name + lineNumberString + er.message, \"error\"); // Because IE doesn't have error.toString.\n  }\n  else\n    println(er, \"error\"); // Because security errors in Moz /only/ have toString.\n}\n\nfunction go(s)\n{\n  _in.value = question = s ? s : _in.value;\n\n  if (question == \"\")\n    return;\n\n  histList[histList.length-1] = question;\n  histList[histList.length] = \"\";\n  histPos = histList.length - 1;\n  \n  // Unfortunately, this has to happen *before* !
 the JavaScript is run, so that \n  // print() output will go in the ri
ght place.\n  _in.value='';\n  recalculateInputHeight();\n  printQuestion(question);\n\n  if (_win.closed) {\n    printError(\"Target window has been closed.\");\n    return;\n  }\n  \n  try { (\"Shell\" in _win) }\n  catch(er) {\n    printError(\"The JavaScript Shell cannot access variables in the target window.  The most likely reason is that the target window now has a different page loaded and that page has a different hostname than the original page.\");\n    return;\n  }\n\n  if (!(\"Shell\" in _win))\n    initTarget(); // silent\n\n  // Evaluate Shell.question using _win's eval (this is why eval isn't in the |with|, IIRC).\n  _win.location.href = \"javascript:try{ Shell.printAnswer(eval('with(Shell._scope) with(Shell.shellCommands) {' + Shell.question + String.fromCharCode(10) + '}')); } catch(er) { Shell.printError(er); }; setTimeout(Shell.refocus, 0); void 0\";\n}\n\n</script>\n\n<!-- for http://ted.mielczarek.org/code/mozilla/extensiondev/ -->\n<script type=\"text/!
 javascript\" src=\"chrome://extensiondev/content/rdfhistory.js\"></script>\n<script type=\"text/javascript\" src=\"chrome://extensiondev/content/chromeShellExtras.js\"></script>\n\n<style type=\"text/css\">\nbody { background: white; color: black; }\n\n#output { white-space: pre; white-space: -moz-pre-wrap; } /* Preserve line breaks, but wrap too if browser supports it */\nh3 { margin-top: 0; margin-bottom: 0em; }\nh3 + div { margin: 0; }\n\nform { margin: 0; padding: 0; }\n#input { width: 100%; border: none; padding: 0; overflow: auto; }\n\n.input { color: blue; background: white; font: inherit; font-weight: bold; margin-top: .5em; /* background: #E6E6FF; */ }\n.normalOutput { color: black; background: white; }\n.print { color: brown; background: white; }\n.error { color: red; background: white; }\n.propList { color: green; background: white; }\n.message { color: green; background: white; }\n.tabcomplete { color: purple; background: white; }\n</style>\n</head>\n\n<body onl!
 oad=\"init()\">\n\n<div id=\"output\"><h3>JavaScript Shell 1.4</h3><h4
>Modified by <a href=\"http://blog.monstuff.com\">Julien Couvreur</a> to work in IE.</h4><div>Features: autocompletion of property names with Tab and Ctrl-Space, multiline input with Shift+Enter, input history with (Ctrl+) Up/Down, <a accesskey=\"M\" href=\"javascript:go('scope(Math); mathHelp();');\" title=\"Accesskey: M\">Math</a>, <a accesskey=\"H\" href=\"http://www.squarefree.com/shell/?ignoreReferrerFrom=shell1.4\"  title=\"Accesskey: H\">help</a></div><div>Values and functions: ans, print(string), <a accesskey=\"P\" href=\"javascript:go('props(ans)')\" title=\"Accesskey: P\">props(object)</a>, <a accesskey=\"B\" href=\"javascript:go('blink(ans)')\" title=\"Accesskey: B\">blink(node)</a>, <a accesskey=\"C\" href=\"javascript:go('clear()')\" title=\"Accesskey: C\">clear()</a>, load(scriptURL), scope(object)</div></div>\n\n<div><textarea id=\"input\" class=\"input\" wrap=\"off\" onkeydown=\"inputKeydown(event)\" rows=\"1\"></textarea></div>\n\n</body>\n\n</html>");docume!
 nt.close();}

Modified: trunk/framework/src/main/javascript/ajaxjsf/log4ajax.js
===================================================================
--- trunk/framework/src/main/javascript/ajaxjsf/log4ajax.js	2007-06-12 18:10:00 UTC (rev 262)
+++ trunk/framework/src/main/javascript/ajaxjsf/log4ajax.js	2007-06-13 01:28:07 UTC (rev 263)
@@ -30,7 +30,7 @@
 
 LOG.LEVEL = LOG.OFF;
 
-LOG.window = null;
+LOG._window = null;
 LOG.transmitToServer = true;
 LOG.consoleDivId = "logConsole";
 LOG.styles = {
@@ -73,29 +73,29 @@
 }
 
 LOG.registerPopup = function(hotkey,name,width,height,level){
-	if(!LOG._onKeyUp){
-		LOG._onKeyUp = document.onkeyup;
+	if(!LOG._onkeydown){
+		LOG._onkeydown = document.onkeydown;
 	}
 	var key = hotkey.toUpperCase();
-	document.onkeyup = function(e){
+	document.onkeydown = function(e){
 		if (window.event){ e = window.event;};
 		if (String.fromCharCode(e.keyCode) == key & e.shiftKey & e.ctrlKey){ 
 			LOG.LEVEL = level;
 			LOG.openWindow(name,'width='+width+',height='+height+',toolbar=no,scrollbars=yes,location=no,statusbar=no,menubar=no,resizable=yes,left = '+((screen.width - width) / 2)+',top ='+((screen.height - height) / 2));
 		} else {
-	      if(LOG._onKeyUp) LOG._onKeyUp(e);
+	      if(LOG._onkeydown) LOG._onkeydown(e);
 		}; 
 	}
 }
 
 LOG.openWindow = function(name,features){
-	if(LOG.window){
-		LOG.window.focus();
+	if(LOG._window){
+		LOG._window.focus();
 	} else {
-		LOG.window = window.open("",name,features);
+		LOG._window = window.open("",name,features);
 		var _LOG = LOG;
-		LOG.window.onunload = function(){
-			_LOG.window = null;
+		LOG._window.onunload = function(){
+			_LOG._window = null;
 			_LOG.LEVEL = _LOG.OFF;
 			_LOG=undefined;
 		}
@@ -139,9 +139,9 @@
 {
 	var consoleDiv ;
 	var doc;
-	if(LOG.window && LOG.window.document){
-		doc = LOG.window.document;
-		consoleDiv = LOG.window.document.body;
+	if(LOG._window && LOG._window.document){
+		doc = LOG._window.document;
+		consoleDiv = LOG._window.document.body;
 	} else {
 		doc = window.document;
 		consoleDiv = window.document.getElementById(LOG.consoleDivId);

Added: trunk/framework/src/main/resources/org/ajax4jsf/framework/ajax/jsshell.html
===================================================================
--- trunk/framework/src/main/resources/org/ajax4jsf/framework/ajax/jsshell.html	                        (rev 0)
+++ trunk/framework/src/main/resources/org/ajax4jsf/framework/ajax/jsshell.html	2007-06-13 01:28:07 UTC (rev 263)
@@ -0,0 +1,740 @@
+<!-- short bookmarklet
+// javascript:function loadScript(scriptURL) { var scriptElem = document.createElement('SCRIPT'); scriptElem.setAttribute('language', 'JavaScript'); scriptElem.setAttribute('src', scriptURL); document.body.appendChild(scriptElem);} loadScript('http://blog.monstuff.com/archives/images/jsshell.js');
+
+
+with(window.open("","_blank","width="+screen.width*.6+",left="+screen.width*.35+",height="+screen.height*.9+",resizable,scrollbars=yes")){document.write("" +
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+
+<html >
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>JavaScript Shell 1.4 modified to support IE</title>
+
+<script type="text/javascript">
+var 
+histList = [""], 
+histPos = 0, 
+_scope = {}, 
+_win, // a top-level context
+question,
+_in,
+_out,
+tooManyMatches = null,
+lastError = null;
+
+function refocus()
+{
+  _in.blur(); // Needed for Mozilla to scroll correctly.
+  _in.focus();
+}
+
+function init()
+{
+  _in = document.getElementById("input");
+  _out = document.getElementById("output");
+
+  _win = window;
+
+  if (opener && !opener.closed)
+  {
+    println("Using bookmarklet version of shell: commands will run in opener's context.", "message");
+    _win = opener;
+  }
+
+  initTarget();
+
+  recalculateInputHeight();
+  refocus();
+}
+
+function initTarget()
+{
+  _win.Shell = window;
+  _win.print = shellCommands.print;
+}
+
+
+// Unless the user is selected something, refocus the textbox.
+// (requested by caillon, brendan, asa)
+function keepFocusInTextbox(e) 
+{
+  var g = e.srcElement ? e.srcElement : e.target; // IE vs. standard
+  
+  while (!g.tagName)
+    g = g.parentNode;
+  var t = g.tagName.toUpperCase();
+  if (t=="A" || t=="INPUT")
+    return;
+    
+  if (window.getSelection) {
+    // Mozilla
+    if (String(window.getSelection()))
+      return;
+  }
+  else if (document.getSelection) {
+    // Opera? Netscape 4?
+    if (document.getSelection())
+      return;
+  }
+  else {
+    // IE
+    if ( document.selection.createRange().text )
+      return;
+  }
+  
+  refocus();
+}
+
+function inputKeydown(e) {
+  // Use onkeydown because IE doesn't support onkeypress for arrow keys
+
+  //alert(e.keyCode + " ^ " + e.keycode);
+
+  if (e.shiftKey && e.keyCode == 13) { // shift-enter
+    // don't do anything; allow the shift-enter to insert a line break as normal
+  } else if (e.keyCode == 13) { // enter
+    // execute the input on enter
+    try { go(); } catch(er) { alert(er); };
+    setTimeout(function() { _in.value = ""; }, 0); // can't preventDefault on input, so clear it later
+  } else if (e.keyCode == 38) { // up
+    // go up in history if at top or ctrl-up
+    if (e.ctrlKey || caretInFirstLine(_in))
+      hist(true);
+  } else if (e.keyCode == 40) { // down
+    // go down in history if at end or ctrl-down
+    if (e.ctrlKey || caretInLastLine(_in))
+      hist(false);
+  } else if(e.ctrlKey && e.keyCode == 32) { // ctrl-space
+    tabcomplete();
+    e.cancelBubble = false;
+    e.returnValue = false;
+    return false;
+  } else if (e.keyCode == 9) { // tab
+    tabcomplete();
+    setTimeout(function() { refocus(); }, 0); // refocus because tab was hit
+  } else { }
+
+  setTimeout(recalculateInputHeight, 0);
+  
+  //return true;
+};
+
+function caretInFirstLine(textbox)
+{
+  // IE doesn't support selectionStart/selectionEnd
+  if (textbox.selectionStart == undefined)
+    return true;
+
+  var firstLineBreak = textbox.value.indexOf("\n");
+  
+  return ((firstLineBreak == -1) || (textbox.selectionStart <= firstLineBreak));
+}
+
+function caretInLastLine(textbox)
+{
+  // IE doesn't support selectionStart/selectionEnd
+  if (textbox.selectionEnd == undefined)
+    return true;
+
+  var lastLineBreak = textbox.value.lastIndexOf("\n");
+  
+  return (textbox.selectionEnd > lastLineBreak);
+}
+
+function recalculateInputHeight()
+{
+  var rows = _in.value.split(/\n/).length
+    + 1 // prevent scrollbar flickering in Mozilla
+    + (window.opera ? 1 : 0); // leave room for scrollbar in Opera
+  
+  if (_in.rows != rows) // without this check, it is impossible to select text in Opera 7.60 or Opera 8.0.
+    _in.rows = rows;
+}
+
+function println(s, type)
+{
+  if((s=String(s)))
+  {
+    var newdiv = document.createElement("div");
+    newdiv.appendChild(document.createTextNode(s));
+    newdiv.className = type;
+    _out.appendChild(newdiv);
+    return newdiv;
+  }
+}
+
+function printWithRunin(h, s, type)
+{
+  var div = println(s, type);
+  var head = document.createElement("strong");
+  head.appendChild(document.createTextNode(h + ": "));
+  div.insertBefore(head, div.firstChild);
+}
+
+
+var shellCommands = 
+{
+load : function load(url)
+{
+  var s = _win.document.createElement("script");
+  s.type = "text/javascript";
+  s.src = url;
+  _win.document.getElementsByTagName("head")[0].appendChild(s);
+  println("Loading " + url + "...", "message");
+},
+
+clear : function clear()
+{
+  var CHILDREN_TO_PRESERVE = 3;
+  while (_out.childNodes[CHILDREN_TO_PRESERVE]) 
+    _out.removeChild(_out.childNodes[CHILDREN_TO_PRESERVE]);
+},
+
+print : function print(s) { println(s, "print"); },
+
+// the normal function, "print", shouldn't return a value
+// (suggested by brendan; later noticed it was a problem when showing others)
+pr : function pr(s) 
+{ 
+  shellCommands.print(s); // need to specify shellCommands so it doesn't try window.print()!
+  return s;
+},
+
+props : function props(e, onePerLine)
+{
+  if (e === null) {
+    println("props called with null argument", "error");
+    return;
+  }
+
+  if (e === undefined) {
+    println("props called with undefined argument", "error");
+    return;
+  }
+
+  var ns = ["Methods", "Fields", "Unreachables"];
+  var as = [[], [], []]; // array of (empty) arrays of arrays!
+  var p, j, i; // loop variables, several used multiple times
+
+  var protoLevels = 0;
+
+  for (p = e; p; p = p.__proto__)
+  {
+    for (i=0; i<ns.length; ++i)
+      as[i][protoLevels] = [];
+    ++protoLevels;
+  }
+
+  for(var a in e)
+  {
+    // Shortcoming: doesn't check that VALUES are the same in object and prototype.
+
+    var protoLevel = -1;
+    try
+    {
+      for (p = e; p && (a in p); p = p.__proto__)
+        ++protoLevel;
+    }
+    catch(er) { protoLevel = 0; } // "in" operator throws when param to props() is a string
+
+    var type = 1;
+    try
+    {
+      if ((typeof e[a]) == "function")
+        type = 0;
+    }
+    catch (er) { type = 2; }
+
+    as[type][protoLevel].push(a);
+  }
+
+  function times(s, n) { return n ? s + times(s, n-1) : ""; }
+
+  for (j=0; j<protoLevels; ++j)
+    for (i=0;i<ns.length;++i)
+      if (as[i][j].length) 
+        printWithRunin(
+          ns[i] + times(" of prototype", j), 
+          (onePerLine ? "\n\n" : "") + as[i][j].sort().join(onePerLine ? "\n" : ", ") + (onePerLine ? "\n\n" : ""), 
+          "propList"
+        );
+},
+
+blink : function blink(node)
+{
+  if (!node)                     throw("blink: argument is null or undefined.");
+  if (node.nodeType == null)     throw("blink: argument must be a node.");
+  if (node.nodeType == 3)        throw("blink: argument must not be a text node");
+  if (node.documentElement)      throw("blink: argument must not be the document object");
+
+  function setOutline(o) { 
+    return function() {
+      if (node.style.outline != node.style.bogusProperty) {
+        // browser supports outline (Firefox 1.1 and newer, CSS3, Opera 8).
+        node.style.outline = o;
+      }
+      else if (node.style.MozOutline != node.style.bogusProperty) {
+        // browser supports MozOutline (Firefox 1.0.x and older)
+        node.style.MozOutline = o;
+      }
+      else {
+        // browser only supports border (IE). border is a fallback because it moves things around.
+        node.style.border = o;
+      }
+    }
+  } 
+  
+  function focusIt(a) {
+    return function() {
+      a.focus(); 
+    }
+  }
+
+  if (node.ownerDocument) {
+    var windowToFocusNow = (node.ownerDocument.defaultView || node.ownerDocument.parentWindow); // Moz vs. IE
+    if (windowToFocusNow)
+      setTimeout(focusIt(windowToFocusNow.top), 0);
+  }
+
+  for(var i=1;i<7;++i)
+    setTimeout(setOutline((i%252)?'3px solid red':'none'), i*100);
+
+  setTimeout(focusIt(window), 800);
+  setTimeout(focusIt(_in), 810);
+},
+
+scope : function scope(sc)
+{
+  if (!sc) sc = {};
+  _scope = sc;
+  println("Scope is now " + sc + ".  If a variable is not found in this scope, window will also be searched.  New variables will still go on window.", "message");
+},
+
+mathHelp : function mathHelp()
+{
+  printWithRunin("Math constants", "E, LN2, LN10, LOG2E, LOG10E, PI, SQRT1_2, SQRT2", "propList");
+  printWithRunin("Math methods", "abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random, round, sin, sqrt, tan", "propList");
+},
+
+ans : undefined
+};
+
+
+function hist(up)
+{
+  // histList[0] = first command entered, [1] = second, etc.
+  // type something, press up --> thing typed is now in "limbo"
+  // (last item in histList) and should be reachable by pressing 
+  // down again.
+
+  var L = histList.length;
+
+  if (L == 1)
+    return;
+
+  if (up)
+  {
+    if (histPos == L-1)
+    {
+      // Save this entry in case the user hits the down key.
+      histList[histPos] = _in.value;
+    }
+
+    if (histPos > 0)
+    {
+      histPos--;
+      // Use a timeout to prevent up from moving cursor within new text
+      // Set to nothing first for the same reason
+      setTimeout(
+        function() {
+          _in.value = ''; 
+          _in.value = histList[histPos];
+          var caretPos = _in.value.length;
+          if (_in.setSelectionRange) 
+            _in.setSelectionRange(caretPos, caretPos);
+        },
+        0
+      );
+    }
+  } 
+  else // down
+  {
+    if (histPos < L-1)
+    {
+      histPos++;
+      _in.value = histList[histPos];
+    }
+    else if (histPos == L-1)
+    {
+      // Already on the current entry: clear but save
+      if (_in.value)
+      {
+        histList[histPos] = _in.value;
+        ++histPos;
+        _in.value = "";
+      }
+    }
+  }
+}
+
+function tabcomplete()
+{
+  /*
+   * Working backwards from s[from], find the spot
+   * where this expression starts.  It will scan
+   * until it hits a mismatched ( or a space,
+   * but it skips over quoted strings.
+   * If stopAtDot is true, stop at a '.'
+   */
+  function findbeginning(s, from, stopAtDot)
+  {
+    /*
+     *  Complicated function.
+     *
+     *  Return true if s[i] == q BUT ONLY IF
+     *  s[i-1] is not a backslash.
+     */
+    function equalButNotEscaped(s,i,q)
+    {
+      if(s.charAt(i) != q) // not equal go no further
+        return false;
+
+      if(i==0) // beginning of string
+        return true;
+
+      if(s.charAt(i-1) == '') // escaped?
+        return false;
+
+      return true;
+    }
+
+    var nparens = 0;
+    var i;
+    for(i=from; i>=0; i--)
+    {
+      if(s.charAt(i) == ' ')
+        break;
+
+      if(stopAtDot && s.charAt(i) == '.')
+        break;
+        
+      if(s.charAt(i) == ')')
+        nparens++;
+      else if(s.charAt(i) == '(')
+        nparens--;
+
+      if(nparens < 0)
+        break;
+
+      // skip quoted strings
+      if(s.charAt(i) == '\'' || s.charAt(i) == '"')
+      {
+        //dump("skipping quoted chars: ");
+        var quot = s.charAt(i);
+        i--;
+        while(i >= 0 && !equalButNotEscaped(s,i,quot)) {
+          //dump(s.charAt(i));
+          i--;
+        }
+        //dump("\n");
+      }
+    }
+    return i;
+  }
+
+  // XXX should be used more consistently (instead of using selectionStart/selectionEnd throughout code)
+  // XXX doesn't work in IE, even though it contains IE-specific code
+  function getcaretpos(inp)
+  {
+    if(inp.selectionEnd != null)
+      return inp.selectionEnd;
+      
+    var range = document.selection.createRange();
+    var isCollapsed = range.compareEndPoints("StartToEnd", range) == 0;
+    if (!isCollapsed)
+        range.collapse(false);
+    var b = range.getBookmark();
+    return b.charCodeAt(2) - 2;  
+  }
+
+  function setselectionto(inp,pos)
+  {
+    if(inp.selectionStart) {
+      inp.selectionStart = inp.selectionEnd = pos;
+    }
+    else if(inp.createTextRange) {
+      var docrange = _win.Shell.document.selection.createRange();
+      var inprange = inp.createTextRange();
+      inprange.move('character',pos);
+      inprange.select();
+    }
+    else { // err...
+    /*
+      inp.select();
+      if(_win.Shell.document.getSelection())
+        _win.Shell.document.getSelection() = "";
+        */
+    }
+  }
+    // get position of cursor within the input box
+    var caret = getcaretpos(_in);
+
+    if(caret) {
+      //dump("----\n");
+      var dotpos, spacepos, complete, obj;
+      //dump("caret pos: " + caret + "\n");
+      // see if there's a dot before here
+      dotpos = findbeginning(_in.value, caret-1, true);
+      //dump("dot pos: " + dotpos + "\n");
+      if(dotpos == -1 || _in.value.charAt(dotpos) != '.') {
+        dotpos = caret;
+	  //dump("changed dot pos: " + dotpos + "\n");
+      }
+
+      // look backwards for a non-variable-name character
+      spacepos = findbeginning(_in.value, dotpos-1, false);
+      //dump("space pos: " + spacepos + "\n");
+      // get the object we're trying to complete on
+      if(spacepos == dotpos || spacepos+1 == dotpos || dotpos == caret)
+      {
+        // try completing function args
+        if(_in.value.charAt(dotpos) == '(' ||
+ (_in.value.charAt(spacepos) == '(' && (spacepos+1) == dotpos))
+        {
+          var fn,fname;
+  var from = (_in.value.charAt(dotpos) == '(') ? dotpos : spacepos;
+          spacepos = findbeginning(_in.value, from-1, false);
+
+          fname = _in.value.substr(spacepos+1,from-(spacepos+1));
+  //dump("fname: " + fname + "\n");
+          try {
+            with(_win.Shell._scope)
+              with(_win)
+                with(Shell.shellCommands)
+                  fn = eval(fname);
+          }
+          catch(er) {
+            //dump('fn is not a valid object\n');
+            return;
+          }
+          if(fn == undefined) {
+             //dump('fn is undefined');
+             return;
+          }
+          if(fn instanceof Function)
+          {
+            // Print function definition, including argument names, but not function body
+            if(!fn.toString().match(/function .+?\(\) +\{\n +\[native code\]\n\}/))
+              println(fn.toString().match(/function .+?\(.*?\)/), "tabcomplete");
+          }
+
+          return;
+        }
+        else
+          obj = _win;
+      }
+      else
+      {
+        var objname = _in.value.substr(spacepos+1,dotpos-(spacepos+1));
+        //dump("objname: |" + objname + "|\n");
+        try {
+          with(_win.Shell._scope)
+            with(_win)
+                obj = eval(objname);
+        }
+        catch(er) {
+          printError(er); 
+          return;
+        }
+        if(obj == undefined) {
+          // sometimes this is tabcomplete's fault, so don't print it :(
+          // e.g. completing from "print(document.getElements"
+          // println("Can't complete from null or undefined expression " + objname, "error");
+          return;
+        }
+      }
+      //dump("obj: " + obj + "\n");
+      // get the thing we're trying to complete
+      if(dotpos == caret)
+      {
+        if(spacepos+1 == dotpos || spacepos == dotpos)
+        {
+          // nothing to complete
+          //dump("nothing to complete\n");
+          return;
+        }
+
+        complete = _in.value.substr(spacepos+1,dotpos-(spacepos+1));
+      }
+      else {
+        complete = _in.value.substr(dotpos+1,caret-(dotpos+1));
+      }
+      //dump("complete: " + complete + "\n");
+      // ok, now look at all the props/methods of this obj
+      // and find ones starting with 'complete'
+      var matches = [];
+      var bestmatch = null;
+      for(var a in obj)
+      {
+        //a = a.toString();
+        //XXX: making it lowercase could help some cases,
+        // but screws up my general logic.
+        if(a.substr(0,complete.length) == complete) {
+          matches.push(a);
+          ////dump("match: " + a + "\n");
+          // if no best match, this is the best match
+          if(bestmatch == null)
+          {
+            bestmatch = a;
+          }
+          else {
+            // the best match is the longest common string
+            function min(a,b){ return ((a<b)?a:b); }
+            var i;
+            for(i=0; i< min(bestmatch.length, a.length); i++)
+            {
+              if(bestmatch.charAt(i) != a.charAt(i))
+                break;
+            }
+            bestmatch = bestmatch.substr(0,i);
+            ////dump("bestmatch len: " + i + "\n");
+          }
+          ////dump("bestmatch: " + bestmatch + "\n");
+        }
+      }
+      bestmatch = (bestmatch || "");
+      ////dump("matches: " + matches + "\n");
+      var objAndComplete = (objname || obj) + "." + bestmatch;
+      //dump("matches.length: " + matches.length + ", tooManyMatches: " + tooManyMatches + ", objAndComplete: " + objAndComplete + "\n");
+      if(matches.length > 1 && (tooManyMatches == objAndComplete || matches.length <= 10)) {
+
+        printWithRunin("Matches: ", matches.join(', '), "tabcomplete");
+        tooManyMatches = null;
+      }
+      else if(matches.length > 10)
+      {
+        println(matches.length + " matches.  Press tab or ctrl-space again to see them all", "tabcomplete");
+        tooManyMatches = objAndComplete;
+      }
+      else {
+        tooManyMatches = null;
+      }
+      if(bestmatch != "")
+      {
+        var sstart;
+        if(dotpos == caret) {
+          sstart = spacepos+1;
+        }
+        else {
+          sstart = dotpos+1;
+        }
+        _in.value = _in.value.substr(0, sstart)
+                  + bestmatch
+                  + _in.value.substr(caret);
+        setselectionto(_in,caret + (bestmatch.length - complete.length));
+      }
+    }
+}
+
+function printQuestion(q)
+{
+  println(q, "input");
+}
+
+function printAnswer(a)
+{
+  if (a !== undefined) {
+    println(a, "normalOutput");
+    shellCommands.ans = a;
+  }
+}
+
+function printError(er)
+{ 
+  var lineNumberString;
+
+  lastError = er; // for debugging the shell
+  if (er.name)
+  {
+    // lineNumberString should not be "", to avoid a very wacky bug in IE 6.
+    lineNumberString = (er.lineNumber != undefined) ? (" on line " + er.lineNumber + ": ") : ": ";
+    println(er.name + lineNumberString + er.message, "error"); // Because IE doesn't have error.toString.
+  }
+  else
+    println(er, "error"); // Because security errors in Moz /only/ have toString.
+}
+
+function go(s)
+{
+  _in.value = question = s ? s : _in.value;
+
+  if (question == "")
+    return;
+
+  histList[histList.length-1] = question;
+  histList[histList.length] = "";
+  histPos = histList.length - 1;
+  
+  // Unfortunately, this has to happen *before* the JavaScript is run, so that 
+  // print() output will go in the right place.
+  _in.value='';
+  recalculateInputHeight();
+  printQuestion(question);
+
+  if (_win.closed) {
+    printError("Target window has been closed.");
+    return;
+  }
+  
+  try { ("Shell" in _win) }
+  catch(er) {
+    printError("The JavaScript Shell cannot access variables in the target window.  The most likely reason is that the target window now has a different page loaded and that page has a different hostname than the original page.");
+    return;
+  }
+
+  if (!("Shell" in _win))
+    initTarget(); // silent
+
+  // Evaluate Shell.question using _win's eval (this is why eval isn't in the |with|, IIRC).
+  _win.location.href = "javascript:try{ Shell.printAnswer(eval('with(Shell._scope) with(Shell.shellCommands) {' + Shell.question + String.fromCharCode(10) + '}')); } catch(er) { Shell.printError(er); }; setTimeout(Shell.refocus, 0); void 0";
+}
+
+</script>
+
+<!-- for http://ted.mielczarek.org/code/mozilla/extensiondev/ -->
+<script type="text/javascript" src="chrome://extensiondev/content/rdfhistory.js"></script>
+<script type="text/javascript" src="chrome://extensiondev/content/chromeShellExtras.js"></script>
+
+<style type="text/css">
+body { background: white; color: black; }
+
+#output { white-space: pre; white-space: -moz-pre-wrap; } /* Preserve line breaks, but wrap too if browser supports it */
+h3 { margin-top: 0; margin-bottom: 0em; }
+h3 + div { margin: 0; }
+
+form { margin: 0; padding: 0; }
+#input { width: 100%; border: none; padding: 0; overflow: auto; }
+
+.input { color: blue; background: white; font: inherit; font-weight: bold; margin-top: .5em; /* background: #E6E6FF; */ }
+.normalOutput { color: black; background: white; }
+.print { color: brown; background: white; }
+.error { color: red; background: white; }
+.propList { color: green; background: white; }
+.message { color: green; background: white; }
+.tabcomplete { color: purple; background: white; }
+</style>
+</head>
+
+<body onload="init()" onclick="keepFocusInTextbox(event)">
+
+<div id="output"><h3>JavaScript Shell 1.4</h3><h4>Modified by <a href="http://blog.monstuff.com">Julien Couvreur</a> to work in IE.</h4><div>Features: autocompletion of property names with Tab and Ctrl-Space, multiline input with Shift+Enter, input history with (Ctrl+) Up/Down, <a accesskey="M" href="javascript:go('scope(Math); mathHelp();');" title="Accesskey: M">Math</a>, <a accesskey="H" href="http://www.squarefree.com/shell/?ignoreReferrerFrom=shell1.4"  title="Accesskey: H">help</a></div><div>Values and functions: ans, print(string), <a accesskey="P" href="javascript:go('props(ans)')" title="Accesskey: P">props(object)</a>, <a accesskey="B" href="javascript:go('blink(ans)')" title="Accesskey: B">blink(node)</a>, <a accesskey="C" href="javascript:go('clear()')" title="Accesskey: C">clear()</a>, load(scriptURL), scope(object)</div></div>
+
+<div><textarea id="input" class="input" wrap="off" onkeydown="inputKeydown(event)" rows="1"></textarea></div>
+
+</body>
+
+</html>
+<!--
+");document.close();}
+-->
\ No newline at end of file




More information about the ajax4jsf-svn-commits mailing list