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&q...
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