JBoss Portal SVN: r10719 - in modules/web/trunk/web/src/main/java/org/jboss/portal/web: impl and 1 other directory.
by portal-commits@lists.jboss.org
Author: julien(a)jboss.com
Date: 2008-04-26 16:51:08 -0400 (Sat, 26 Apr 2008)
New Revision: 10719
Modified:
modules/web/trunk/web/src/main/java/org/jboss/portal/web/WebRequest.java
modules/web/trunk/web/src/main/java/org/jboss/portal/web/impl/AbstractWebRequest.java
Log:
- added methods to retrieve query and body parameters without using the corresponding maps.
Modified: modules/web/trunk/web/src/main/java/org/jboss/portal/web/WebRequest.java
===================================================================
--- modules/web/trunk/web/src/main/java/org/jboss/portal/web/WebRequest.java 2008-04-25 22:56:30 UTC (rev 10718)
+++ modules/web/trunk/web/src/main/java/org/jboss/portal/web/WebRequest.java 2008-04-26 20:51:08 UTC (rev 10719)
@@ -69,6 +69,40 @@
Map<String, String[]> getQueryParameterMap();
/**
+ * Returns a parameter value from the query string or null if it cannot be found.
+ *
+ * @param parameterName the parameter name
+ * @return the parameter value
+ */
+ String getQueryParameter(String parameterName);
+
+ /**
+ * Returns a parameter values from the query string or null if it cannot be found.
+ *
+ * @param parameterName the parameter name
+ * @return the parameter value
+ */
+ String[] getQueryParameterValues(String parameterName);
+
+ /**
+ * Returns a parameter value from the body or null if it cannot be found. If the content type of the
+ * request is not <code>application/x-www-form-urlencoded</code> then this method will always return null.
+ *
+ * @param parameterName the parameter name
+ * @return the parameter value
+ */
+ String getBodyParameter(String parameterName);
+
+ /**
+ * Returns a parameter values from the body or null if it cannot be found. If the content type of the
+ * request is not <code>application/x-www-form-urlencoded</code> then this method will always return null.
+ *
+ * @param parameterName the parameter name
+ * @return the parameter value
+ */
+ String[] getBodyParameterValues(String parameterName);
+
+ /**
* Returns the body of the request when the request is of type POST otherwise return null.
*
* @return the body
Modified: modules/web/trunk/web/src/main/java/org/jboss/portal/web/impl/AbstractWebRequest.java
===================================================================
--- modules/web/trunk/web/src/main/java/org/jboss/portal/web/impl/AbstractWebRequest.java 2008-04-25 22:56:30 UTC (rev 10718)
+++ modules/web/trunk/web/src/main/java/org/jboss/portal/web/impl/AbstractWebRequest.java 2008-04-26 20:51:08 UTC (rev 10719)
@@ -113,4 +113,41 @@
{
return mediaType;
}
+
+ public String getQueryParameter(String parameterName)
+ {
+ String[] values = getQueryParameterValues(parameterName);
+
+ //
+ return values != null ? values[0] : null;
+ }
+
+ public String[] getQueryParameterValues(String parameterName)
+ {
+ if (parameterName == null)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ return queryParameterMap.get(parameterName);
+ }
+
+ public String getBodyParameter(String parameterName)
+ {
+ String[] values = getBodyParameterValues(parameterName);
+
+ //
+ return values != null ? values[0] : null;
+ }
+
+ public String[] getBodyParameterValues(String parameterName)
+ {
+ if (parameterName == null)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ //
+ return body instanceof Body.Form ? ((Body.Form)body).getParameters().get(parameterName) : null;
+ }
}
\ No newline at end of file
16 years
JBoss Portal SVN: r10718 - in modules/presentation/trunk: ajax and 15 other directories.
by portal-commits@lists.jboss.org
Author: julien(a)jboss.com
Date: 2008-04-25 18:56:30 -0400 (Fri, 25 Apr 2008)
New Revision: 10718
Added:
modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/context.xml
modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/jboss-beans.xml
modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/jboss-web.xml
modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/portlet.xml
modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralEventControllerContext.java
modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralPortletPageNavigationalState.java
modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralStateControllerContext.java
modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/spi/PresentationPortletInvocationContext.java
modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/spi/PresentationSecurityContext.java
Modified:
modules/presentation/trunk/ajax/pom.xml
modules/presentation/trunk/ajax/src/main/java/org/jboss/portal/presentation/ajax/model/AjaxNavigationalStateContext.java
modules/presentation/trunk/ajax/src/test/java/org/jboss/portal/presentation/test/portal/PresentationServerImpl.java
modules/presentation/trunk/build/pom.xml
modules/presentation/trunk/classic/pom.xml
modules/presentation/trunk/classic/src/assemble/presentation-war.xml
modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/page-structure.xml
modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/web.xml
modules/presentation/trunk/classic/src/main/java/org/jboss/portal/presentation/classic/ClassicPresentationClient.java
modules/presentation/trunk/classic/src/main/java/org/jboss/portal/presentation/classic/ClassicPresentationServlet.java
modules/presentation/trunk/pom.xml
modules/presentation/trunk/presentation/pom.xml
modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/PresentationServerImpl.java
modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/PresentationPortletInvoker.java
modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralPortletControllerContext.java
modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/spi/PresentationClientContext.java
modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/state/navigational/NavigationalStateContextImpl.java
modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/state/structural/NodeImporter.java
modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/protocol/LinkActivation.java
modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/state/navigational/NavigationalStateContext.java
Log:
start to integrate portlet container with presentation framework
Modified: modules/presentation/trunk/ajax/pom.xml
===================================================================
--- modules/presentation/trunk/ajax/pom.xml 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/ajax/pom.xml 2008-04-25 22:56:30 UTC (rev 10718)
@@ -60,16 +60,6 @@
</dependency>
<dependency>
- <groupId>org.jboss.portal.portlet</groupId>
- <artifactId>portlet-jsr168api</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.jboss.portal.portlet</groupId>
- <artifactId>portlet-portal</artifactId>
- </dependency>
-
- <dependency>
<groupId>org.jboss.portal.web</groupId>
<artifactId>web-web</artifactId>
</dependency>
Modified: modules/presentation/trunk/ajax/src/main/java/org/jboss/portal/presentation/ajax/model/AjaxNavigationalStateContext.java
===================================================================
--- modules/presentation/trunk/ajax/src/main/java/org/jboss/portal/presentation/ajax/model/AjaxNavigationalStateContext.java 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/ajax/src/main/java/org/jboss/portal/presentation/ajax/model/AjaxNavigationalStateContext.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -24,6 +24,7 @@
import java.util.List;
import java.util.ArrayList;
+import java.io.Serializable;
import org.jboss.portal.presentation.impl.state.navigational.NavigationalStateContextImpl;
import org.jboss.portal.presentation.state.StateChangeVetoException;
@@ -78,7 +79,7 @@
/**
*
*/
- public void setProperty(String objectId, String key, Object navigationalState)
+ public void setProperty(String objectId, String key, Serializable navigationalState)
throws StateChangeVetoException, StateException, IllegalArgumentException
{
this.markAsStale(objectId);
Modified: modules/presentation/trunk/ajax/src/test/java/org/jboss/portal/presentation/test/portal/PresentationServerImpl.java
===================================================================
--- modules/presentation/trunk/ajax/src/test/java/org/jboss/portal/presentation/test/portal/PresentationServerImpl.java 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/ajax/src/test/java/org/jboss/portal/presentation/test/portal/PresentationServerImpl.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -149,10 +149,16 @@
formParameters = ((Body.Form)body).getParameters();
}
}
+
+
- WindowState windowState = activation.getWindowState();
- Mode windowMode = activation.getWindowMode();
-
+ String windowStateParam = activation.getQueryParameter("windowstate");
+ WindowState windowState = windowStateParam != null ? WindowState.create(windowStateParam) : WindowState.NORMAL;
+
+
+ String windowModeParam = activation.getQueryParameter("mode");
+ Mode windowMode = windowModeParam != null ? Mode.create(windowModeParam) : Mode.VIEW;
+
//Perform processing of this request through to the PortletContainer
//Just Stub code...just mark all children on this page as stale for re-rendering
for(StructuralNode window: targetNode.getParent().getChildren())
Modified: modules/presentation/trunk/build/pom.xml
===================================================================
--- modules/presentation/trunk/build/pom.xml 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/build/pom.xml 2008-04-25 22:56:30 UTC (rev 10718)
@@ -31,13 +31,15 @@
<version.gwt>1.4.60</version.gwt>
<version.mygwt>0.3.0</version.mygwt>
+ <version.portlet-api>2.0</version.portlet-api>
+
<version.jboss.portal.common>1.2.0-SNAPSHOT</version.jboss.portal.common>
- <version.jboss.portal.portlet>2.0.0.CR2</version.jboss.portal.portlet>
+ <version.jboss.portal.portlet>2.0.0-SNAPSHOT</version.jboss.portal.portlet>
<version.jboss.portal.web>1.2.0-SNAPSHOT</version.jboss.portal.web>
<version.jboss.unit>1.2.0.Beta2</version.jboss.unit>
- <version.jboss.microcontainer>2.0.0.Beta9</version.jboss.microcontainer>
- <version.jboss.common.core>2.0.3.GA</version.jboss.common.core>
+ <version.jboss.microcontainer>2.0.0.Beta13</version.jboss.microcontainer>
+ <version.jboss.common.core>2.0.4.GA</version.jboss.common.core>
<version.jboss.remoting>2.2.1.GA</version.jboss.remoting>
<!-- your local appserver installation -->
@@ -120,6 +122,12 @@
</dependency>
<dependency>
+ <groupId>javax.portlet</groupId>
+ <artifactId>portlet-api</artifactId>
+ <version>${version.portlet-api}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.jboss.portal.common</groupId>
<artifactId>common-common</artifactId>
<version>${version.jboss.portal.common}</version>
@@ -138,24 +146,36 @@
</dependency>
<dependency>
+ <groupId>org.jboss.portal.web</groupId>
+ <artifactId>web-web</artifactId>
+ <version>${version.jboss.portal.web}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.jboss.portal.portlet</groupId>
- <artifactId>portlet-jsr168api</artifactId>
+ <artifactId>portlet-portlet</artifactId>
<version>${version.jboss.portal.portlet}</version>
</dependency>
<dependency>
<groupId>org.jboss.portal.portlet</groupId>
- <artifactId>portlet-portal</artifactId>
+ <artifactId>portlet-controller</artifactId>
<version>${version.jboss.portal.portlet}</version>
</dependency>
<dependency>
- <groupId>org.jboss.portal.web</groupId>
- <artifactId>web-web</artifactId>
- <version>${version.jboss.portal.web}</version>
+ <groupId>org.jboss.portal.portlet</groupId>
+ <artifactId>portlet-mc</artifactId>
+ <version>${version.jboss.portal.portlet}</version>
</dependency>
<dependency>
+ <groupId>org.jboss.portal.portlet</groupId>
+ <artifactId>portlet-samples</artifactId>
+ <version>${version.jboss.portal.portlet}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.jboss.unit</groupId>
<artifactId>jboss-unit</artifactId>
<version>${version.jboss.unit}</version>
@@ -187,12 +207,6 @@
<dependency>
<groupId>org.jboss.microcontainer</groupId>
- <artifactId>jboss-container</artifactId>
- <version>${version.jboss.microcontainer}</version>
- </dependency>
-
- <dependency>
- <groupId>org.jboss.microcontainer</groupId>
<artifactId>jboss-kernel</artifactId>
<version>${version.jboss.microcontainer}</version>
</dependency>
Modified: modules/presentation/trunk/classic/pom.xml
===================================================================
--- modules/presentation/trunk/classic/pom.xml 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/classic/pom.xml 2008-04-25 22:56:30 UTC (rev 10718)
@@ -14,62 +14,81 @@
<dependencies>
- <dependency>
- <groupId>org.jboss.portal.presentation</groupId>
- <artifactId>presentation-presentation</artifactId>
- <version>${project.version}</version>
- </dependency>
+ <dependency>
+ <groupId>org.jboss.portal.presentation</groupId>
+ <artifactId>presentation-presentation</artifactId>
+ <version>${project.version}</version>
+ </dependency>
- <dependency>
- <groupId>sun-servlet</groupId>
- <artifactId>servlet-api</artifactId>
- </dependency>
+ <dependency>
+ <groupId>sun-servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.jboss.portal.common</groupId>
- <artifactId>common-common</artifactId>
- </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
- <dependency>
- <groupId>org.jboss.portal.common</groupId>
- <artifactId>common-portal</artifactId>
- </dependency>
+ <dependency>
+ <groupId>org.jboss.portal.common</groupId>
+ <artifactId>common-common</artifactId>
+ </dependency>
- <dependency>
- <groupId>org.jboss.portal.web</groupId>
- <artifactId>web-web</artifactId>
- </dependency>
+ <dependency>
+ <groupId>org.jboss.portal.common</groupId>
+ <artifactId>common-portal</artifactId>
+ </dependency>
- <dependency>
- <groupId>org.jboss.microcontainer</groupId>
- <artifactId>jboss-container</artifactId>
- <version>${version.jboss.microcontainer}</version>
- </dependency>
+ <dependency>
+ <groupId>org.jboss.portal.common</groupId>
+ <artifactId>common-mc</artifactId>
+ </dependency>
- <dependency>
- <groupId>org.jboss.microcontainer</groupId>
- <artifactId>jboss-kernel</artifactId>
- </dependency>
+ <dependency>
+ <groupId>org.jboss.portal.web</groupId>
+ <artifactId>web-web</artifactId>
+ </dependency>
- <dependency>
- <groupId>org.jboss.microcontainer</groupId>
- <artifactId>jboss-dependency</artifactId>
- </dependency>
+ <dependency>
+ <groupId>org.jboss.portal.portlet</groupId>
+ <artifactId>portlet-portlet</artifactId>
+ </dependency>
- <dependency>
- <groupId>jboss</groupId>
- <artifactId>jboss-common-core</artifactId>
- </dependency>
+ <dependency>
+ <groupId>org.jboss.portal.portlet</groupId>
+ <artifactId>portlet-controller</artifactId>
+ </dependency>
- <dependency>
- <groupId>jboss</groupId>
- <artifactId>jboss-remoting</artifactId>
- </dependency>
+ <dependency>
+ <groupId>org.jboss.portal.portlet</groupId>
+ <artifactId>portlet-mc</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.portal.portlet</groupId>
+ <artifactId>portlet-samples</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.microcontainer</groupId>
+ <artifactId>jboss-kernel</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.microcontainer</groupId>
+ <artifactId>jboss-dependency</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jboss-common-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>jboss</groupId>
+ <artifactId>jboss-remoting</artifactId>
+ </dependency>
</dependencies>
<build>
Modified: modules/presentation/trunk/classic/src/assemble/presentation-war.xml
===================================================================
--- modules/presentation/trunk/classic/src/assemble/presentation-war.xml 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/classic/src/assemble/presentation-war.xml 2008-04-25 22:56:30 UTC (rev 10718)
@@ -23,10 +23,27 @@
<dependencySet>
<outputDirectory>WEB-INF/lib</outputDirectory>
<includes>
+
<include>org.jboss.portal.common:common-common</include>
<include>org.jboss.portal.common:common-portal</include>
+ <include>org.jboss.portal.common:common-mc</include>
<include>org.jboss.portal.web:web-web</include>
+ <include>org.jboss.portal.portlet:portlet-portlet</include>
+ <include>org.jboss.portal.portlet:portlet-controller</include>
+ <include>org.jboss.portal.portlet:portlet-mc</include>
+ <include>org.jboss.portal.portlet:portlet-samples</include>
<include>org.jboss.portal.presentation:presentation-presentation</include>
+
+ <include>javax.ccpp:ccpp</include>
+ <include>javax.portlet:portlet-api</include>
+
+ <include>org.jboss:jboss-common-core</include>
+ <include>org.jboss.microcontainer:jboss-kernel</include>
+ <include>org.jboss.microcontainer:jboss-dependency</include>
+ <include>org.jboss:jboss-reflect</include>
+ <include>org.jboss:jboss-mdr</include>
+ <include>org.jboss:jbossxb</include>
+
</includes>
</dependencySet>
</dependencySets>
Added: modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/context.xml
===================================================================
--- modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/context.xml (rev 0)
+++ modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/context.xml 2008-04-25 22:56:30 UTC (rev 10718)
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context privileged="true"/>
\ No newline at end of file
Added: modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/jboss-beans.xml
===================================================================
--- modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/jboss-beans.xml (rev 0)
+++ modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/jboss-beans.xml 2008-04-25 22:56:30 UTC (rev 10718)
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ JBoss, a division of Red Hat ~
+ ~ Copyright 2008, Red Hat Middleware, LLC, and individual ~
+ ~ contributors as indicated by the @authors tag. See the ~
+ ~ copyright.txt in the distribution for a full listing of ~
+ ~ individual contributors. ~
+ ~ ~
+ ~ This is free software; you can redistribute it and/or modify it ~
+ ~ under the terms of the GNU Lesser General Public License as ~
+ ~ published by the Free Software Foundation; either version 2.1 of ~
+ ~ the License, or (at your option) any later version. ~
+ ~ ~
+ ~ This software is distributed in the hope that it will be useful, ~
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of ~
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ~
+ ~ Lesser General Public License for more details. ~
+ ~ ~
+ ~ You should have received a copy of the GNU Lesser General Public ~
+ ~ License along with this software; if not, write to the Free ~
+ ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ~
+ ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org. ~
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+
+ <bean name="PortletApplicationDeployer" class="org.jboss.portal.portlet.mc.PortletApplicationDeployer">
+ <alias>PortletApplicationRegistry</alias>
+ <property name="servletContainer"><inject bean="ServletContainer"/></property>
+ <property name="containerPortletInvoker"><inject bean="ContainerPortletInvoker"/></property>
+ </bean>
+
+ <!-- The ServletContainerFactory -->
+ <bean name="ServletContainerFactory" class="org.jboss.portal.web.impl.DefaultServletContainerFactory">
+ <constructor factoryClass="org.jboss.portal.web.impl.DefaultServletContainerFactory" factoryMethod="getInstance"/>
+ </bean>
+
+ <!-- The servlet container obtained from the ServletContainerFactory -->
+ <bean name="ServletContainer" class="org.jboss.portal.web.ServletContainer">
+ <constructor factoryMethod="getServletContainer">
+ <factory bean="ServletContainerFactory"/>
+ </constructor>
+ </bean>
+
+ <!-- The producer persistence manager -->
+ <bean name="ProducerPersistenceManager" class="org.jboss.portal.portlet.impl.state.producer.PortletStatePersistenceManagerService"/>
+
+ <!-- The producer state management policy -->
+ <bean name="ProducerStateManagementPolicy" class="org.jboss.portal.portlet.impl.state.StateManagementPolicyService">
+ <property name="persistLocally"><value>true</value></property>
+ </bean>
+
+ <!-- The producer state converter -->
+ <bean name="ProducerStateConverter" class="org.jboss.portal.portlet.impl.state.StateConverterV0"/>
+
+ <!-- The consumer portlet invoker -->
+ <bean name="ConsumerPortletInvoker" class="org.jboss.portal.portlet.PortletInvokerInterceptor">
+ <property name="next"><inject bean="ConsumerCacheInterceptor"/></property>
+ </bean>
+ <bean name="ConsumerCacheInterceptor" class="org.jboss.portal.portlet.aspects.portlet.ConsumerCacheInterceptor">
+ <property name="next"><inject bean="PortletCustomizationInterceptor"/></property>
+ </bean>
+ <bean name="PortletCustomizationInterceptor" class="org.jboss.portal.portlet.aspects.portlet.PortletCustomizationInterceptor">
+ <property name="next"><inject bean="ProducerPortletInvoker"/></property>
+ </bean>
+
+ <!-- The producer portlet invoker -->
+ <bean name="ProducerPortletInvoker" class="org.jboss.portal.portlet.state.producer.ProducerPortletInvoker">
+ <property name="next"><inject bean="ContainerPortletInvoker"/></property>
+ <property name="persistenceManager"><inject bean="ProducerPersistenceManager"/></property>
+ <property name="stateManagementPolicy"><inject bean="ProducerStateManagementPolicy"/></property>
+ <property name="stateConverter"><inject bean="ProducerStateConverter"/></property>
+ </bean>
+
+ <!-- The portlet container invoker -->
+ <bean name="ContainerPortletInvoker" class="org.jboss.portal.portlet.container.ContainerPortletInvoker">
+ <property name="next"><inject bean="ValveInterceptor"/></property>
+ </bean>
+
+ <!-- Container stack -->
+ <bean name="ValveInterceptor" class="org.jboss.portal.portlet.aspects.portlet.ValveInterceptor">
+ <property name="portletApplicationRegistry"><inject bean="PortletApplicationRegistry" state="Instantiated"/></property>
+ <property name="next"><inject bean="SecureTransportInterceptor"/></property>
+ </bean>
+ <bean name="SecureTransportInterceptor" class="org.jboss.portal.portlet.aspects.portlet.SecureTransportInterceptor">
+ <property name="next"><inject bean="ContextDispatcherInterceptor"/></property>
+ </bean>
+ <bean name="ContextDispatcherInterceptor" class="org.jboss.portal.portlet.aspects.portlet.ContextDispatcherInterceptor">
+ <property name="servletContainerFactory"><inject bean="ServletContainerFactory"/></property>
+ <property name="next"><inject bean="ProducerCacheInterceptor"/></property>
+ </bean>
+ <bean name="ProducerCacheInterceptor" class="org.jboss.portal.portlet.aspects.portlet.ProducerCacheInterceptor">
+ <property name="next"><inject bean="CCPPInterceptor"/></property>
+ </bean>
+ <bean name="CCPPInterceptor" class="org.jboss.portal.portlet.aspects.portlet.CCPPInterceptor">
+ <property name="next"><inject bean="RequestAttributeConversationInterceptor"/></property>
+ </bean>
+ <bean name="RequestAttributeConversationInterceptor" class="org.jboss.portal.portlet.aspects.portlet.RequestAttributeConversationInterceptor">
+ <property name="next"><inject bean="EventPayloadInterceptor"/></property>
+ </bean>
+ <bean name="EventPayloadInterceptor" class="org.jboss.portal.portlet.aspects.portlet.EventPayloadInterceptor">
+ <property name="next"><inject bean="PortletContainerDispatcher"/></property>
+ </bean>
+ <bean name="PortletContainerDispatcher" class="org.jboss.portal.portlet.container.ContainerPortletDispatcher">
+ </bean>
+
+</deployment>
Added: modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/jboss-web.xml
===================================================================
--- modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/jboss-web.xml (rev 0)
+++ modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/jboss-web.xml 2008-04-25 22:56:30 UTC (rev 10718)
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ JBoss, a division of Red Hat ~
+ ~ Copyright 2006, Red Hat Middleware, LLC, and individual ~
+ ~ contributors as indicated by the @authors tag. See the ~
+ ~ copyright.txt in the distribution for a full listing of ~
+ ~ individual contributors. ~
+ ~ ~
+ ~ This is free software; you can redistribute it and/or modify it ~
+ ~ under the terms of the GNU Lesser General Public License as ~
+ ~ published by the Free Software Foundation; either version 2.1 of ~
+ ~ the License, or (at your option) any later version. ~
+ ~ ~
+ ~ This software is distributed in the hope that it will be useful, ~
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of ~
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ~
+ ~ Lesser General Public License for more details. ~
+ ~ ~
+ ~ You should have received a copy of the GNU Lesser General Public ~
+ ~ License along with this software; if not, write to the Free ~
+ ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ~
+ ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org. ~
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<!DOCTYPE jboss-web PUBLIC
+ "-//JBoss//DTD Web Application 4.2//EN"
+ "http://www.jboss.org/j2ee/dtd/jboss-web_4_2.dtd">
+<jboss-web>
+ <class-loading java2ClassLoadingCompliance="false">
+ <loader-repository>test:loader=portlet</loader-repository>
+ </class-loading>
+</jboss-web>
\ No newline at end of file
Modified: modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/page-structure.xml
===================================================================
--- modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/page-structure.xml 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/page-structure.xml 2008-04-25 22:56:30 UTC (rev 10718)
@@ -4,14 +4,23 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<page-def name="default">
<window-def name="windowA">
+ <properties>
+ <property>
+ <name>portlet-ref</name>
+ <value>/classic-presentation.Catalog</value>
+ </property>
+ </properties>
<content>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque odio nisl, faucibus id, placerat et, pulvinar at, nisi. Vivamus mollis pharetra risus. Mauris vitae massa vel augue congue eleifend. Morbi pede pede, adipiscing nec, scelerisque nec, ullamcorper sed, libero. Mauris iaculis lorem sit amet eros. Proin viverra eros. Morbi sit amet libero. Donec nec turpis et nunc consectetuer auctor. Fusce et metus. Sed commodo condimentum libero. Sed mollis tellus id justo. Nulla condimentum, libero ultricies accumsan pellentesque, nibh pede egestas quam, vitae varius nisi arcu ac urna. Phasellus interdum, odio vitae eleifend suscipit, nibh massa laoreet lorem, id mollis justo nisl non nunc. Sed enim enim, rutrum a, scelerisque eget, laoreet non, ante. Aenean molestie ipsum in nisi.</content>
</window-def>
<window-def name="windowB">
+ <properties>
+ <property>
+ <name>portlet-ref</name>
+ <value>/classic-presentation.Cart</value>
+ </property>
+ </properties>
<content>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque odio nisl, faucibus id, placerat et, pulvinar at, nisi. Vivamus mollis pharetra risus. Mauris vitae massa vel augue congue eleifend. Morbi pede pede, adipiscing nec, scelerisque nec, ullamcorper sed, libero. Mauris iaculis lorem sit amet eros. Proin viverra eros. Morbi sit amet libero. Donec nec turpis et nunc consectetuer auctor. Fusce et metus. Sed commodo condimentum libero. Sed mollis tellus id justo. Nulla condimentum, libero ultricies accumsan pellentesque, nibh pede egestas quam, vitae varius nisi arcu ac urna. Phasellus interdum, odio vitae eleifend suscipit, nibh massa laoreet lorem, id mollis justo nisl non nunc. Sed enim enim, rutrum a, scelerisque eget, laoreet non, ante. Aenean molestie ipsum in nisi.</content>
</window-def>
- <window-def name="windowC">
- <content>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque odio nisl, faucibus id, placerat et, pulvinar at, nisi. Vivamus mollis pharetra risus. Mauris vitae massa vel augue congue eleifend. Morbi pede pede, adipiscing nec, scelerisque nec, ullamcorper sed, libero. Mauris iaculis lorem sit amet eros. Proin viverra eros. Morbi sit amet libero. Donec nec turpis et nunc consectetuer auctor. Fusce et metus. Sed commodo condimentum libero. Sed mollis tellus id justo. Nulla condimentum, libero ultricies accumsan pellentesque, nibh pede egestas quam, vitae varius nisi arcu ac urna. Phasellus interdum, odio vitae eleifend suscipit, nibh massa laoreet lorem, id mollis justo nisl non nunc. Sed enim enim, rutrum a, scelerisque eget, laoreet non, ante. Aenean molestie ipsum in nisi.</content>
- </window-def>
<page-def name="child-page-default-1">
<window-def name="windowA">
<content>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque odio nisl, faucibus id, placerat et, pulvinar at, nisi. Vivamus mollis pharetra risus. Mauris vitae massa vel augue congue eleifend. Morbi pede pede, adipiscing nec, scelerisque nec, ullamcorper sed, libero. Mauris iaculis lorem sit amet eros. Proin viverra eros. Morbi sit amet libero. Donec nec turpis et nunc consectetuer auctor. Fusce et metus. Sed commodo condimentum libero. Sed mollis tellus id justo. Nulla condimentum, libero ultricies accumsan pellentesque, nibh pede egestas quam, vitae varius nisi arcu ac urna. Phasellus interdum, odio vitae eleifend suscipit, nibh massa laoreet lorem, id mollis justo nisl non nunc. Sed enim enim, rutrum a, scelerisque eget, laoreet non, ante. Aenean molestie ipsum in nisi.</content>
@@ -22,17 +31,32 @@
</page-def>
<page-def name="child-page-default-2">
<window-def name="windowA">
+ <properties>
+ <property>
+ <name>portlet-ref</name>
+ <value>/classic-presentation.PublicParameterPortlet1</value>
+ </property>
+ </properties>
<content>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque odio nisl, faucibus id, placerat et, pulvinar at, nisi. Vivamus mollis pharetra risus. Mauris vitae massa vel augue congue eleifend. Morbi pede pede, adipiscing nec, scelerisque nec, ullamcorper sed, libero. Mauris iaculis lorem sit amet eros. Proin viverra eros. Morbi sit amet libero. Donec nec turpis et nunc consectetuer auctor. Fusce et metus. Sed commodo condimentum libero. Sed mollis tellus id justo. Nulla condimentum, libero ultricies accumsan pellentesque, nibh pede egestas quam, vitae varius nisi arcu ac urna. Phasellus interdum, odio vitae eleifend suscipit, nibh massa laoreet lorem, id mollis justo nisl non nunc. Sed enim enim, rutrum a, scelerisque eget, laoreet non, ante. Aenean molestie ipsum in nisi.</content>
</window-def>
<window-def name="windowB">
+ <properties>
+ <property>
+ <name>portlet-ref</name>
+ <value>/classic-presentation.PublicParameterPortlet2</value>
+ </property>
+ </properties>
<content>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque odio nisl, faucibus id, placerat et, pulvinar at, nisi. Vivamus mollis pharetra risus. Mauris vitae massa vel augue congue eleifend. Morbi pede pede, adipiscing nec, scelerisque nec, ullamcorper sed, libero. Mauris iaculis lorem sit amet eros. Proin viverra eros. Morbi sit amet libero. Donec nec turpis et nunc consectetuer auctor. Fusce et metus. Sed commodo condimentum libero. Sed mollis tellus id justo. Nulla condimentum, libero ultricies accumsan pellentesque, nibh pede egestas quam, vitae varius nisi arcu ac urna. Phasellus interdum, odio vitae eleifend suscipit, nibh massa laoreet lorem, id mollis justo nisl non nunc. Sed enim enim, rutrum a, scelerisque eget, laoreet non, ante. Aenean molestie ipsum in nisi.</content>
</window-def>
<window-def name="windowC">
+ <properties>
+ <property>
+ <name>portlet-ref</name>
+ <value>/classic-presentation.PublicParameterPortlet3</value>
+ </property>
+ </properties>
<content>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque odio nisl, faucibus id, placerat et, pulvinar at, nisi. Vivamus mollis pharetra risus. Mauris vitae massa vel augue congue eleifend. Morbi pede pede, adipiscing nec, scelerisque nec, ullamcorper sed, libero. Mauris iaculis lorem sit amet eros. Proin viverra eros. Morbi sit amet libero. Donec nec turpis et nunc consectetuer auctor. Fusce et metus. Sed commodo condimentum libero. Sed mollis tellus id justo. Nulla condimentum, libero ultricies accumsan pellentesque, nibh pede egestas quam, vitae varius nisi arcu ac urna. Phasellus interdum, odio vitae eleifend suscipit, nibh massa laoreet lorem, id mollis justo nisl non nunc. Sed enim enim, rutrum a, scelerisque eget, laoreet non, ante. Aenean molestie ipsum in nisi.</content>
</window-def>
- <window-def name="windowD">
- <content>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque odio nisl, faucibus id, placerat et, pulvinar at, nisi. Vivamus mollis pharetra risus. Mauris vitae massa vel augue congue eleifend. Morbi pede pede, adipiscing nec, scelerisque nec, ullamcorper sed, libero. Mauris iaculis lorem sit amet eros. Proin viverra eros. Morbi sit amet libero. Donec nec turpis et nunc consectetuer auctor. Fusce et metus. Sed commodo condimentum libero. Sed mollis tellus id justo. Nulla condimentum, libero ultricies accumsan pellentesque, nibh pede egestas quam, vitae varius nisi arcu ac urna. Phasellus interdum, odio vitae eleifend suscipit, nibh massa laoreet lorem, id mollis justo nisl non nunc. Sed enim enim, rutrum a, scelerisque eget, laoreet non, ante. Aenean molestie ipsum in nisi.</content>
- </window-def>
</page-def>
</page-def>
<page-def name="default-sibling-1">
Added: modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/portlet.xml
===================================================================
--- modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/portlet.xml (rev 0)
+++ modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/portlet.xml 2008-04-25 22:56:30 UTC (rev 10718)
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ JBoss, a division of Red Hat ~
+ ~ Copyright 2008, Red Hat Middleware, LLC, and individual ~
+ ~ contributors as indicated by the @authors tag. See the ~
+ ~ copyright.txt in the distribution for a full listing of ~
+ ~ individual contributors. ~
+ ~ ~
+ ~ This is free software; you can redistribute it and/or modify it ~
+ ~ under the terms of the GNU Lesser General Public License as ~
+ ~ published by the Free Software Foundation; either version 2.1 of ~
+ ~ the License, or (at your option) any later version. ~
+ ~ ~
+ ~ This software is distributed in the hope that it will be useful, ~
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of ~
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ~
+ ~ Lesser General Public License for more details. ~
+ ~ ~
+ ~ You should have received a copy of the GNU Lesser General Public ~
+ ~ License along with this software; if not, write to the Free ~
+ ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ~
+ ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org. ~
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
+ version="2.0">
+
+ <portlet>
+ <description>Catalog Portlet</description>
+ <portlet-name>Catalog</portlet-name>
+ <display-name>Catalog Portlet</display-name>
+ <portlet-class>org.jboss.portal.portlet.samples.shoppingcart.CatalogPortlet</portlet-class>
+ <supports>
+ <mime-type>text/html</mime-type>
+ <portlet-mode>VIEW</portlet-mode>
+ </supports>
+ <portlet-info>
+ <title>Catalog Portlet</title>
+ <keywords>sample,event,catalog</keywords>
+ </portlet-info>
+ <supported-publishing-event>
+ <qname xmlns:jbp='urn:jboss:portal:samples:event'>jbp:CartEvent</qname>
+ </supported-publishing-event>
+ </portlet>
+
+ <portlet>
+ <description>Cart Portlet</description>
+ <portlet-name>Cart</portlet-name>
+ <display-name>Cart Portlet</display-name>
+ <portlet-class>org.jboss.portal.portlet.samples.shoppingcart.CartPortlet</portlet-class>
+ <supports>
+ <mime-type>text/html</mime-type>
+ <portlet-mode>VIEW</portlet-mode>
+ </supports>
+ <portlet-info>
+ <title>Cart Portlet</title>
+ <keywords>sample,event,cart</keywords>
+ </portlet-info>
+ <supported-processing-event>
+ <qname xmlns:jbp='urn:jboss:portal:samples:event'>jbp:CartEvent</qname>
+ </supported-processing-event>
+ </portlet>
+
+ <portlet>
+ <description>Portlet that manipulates its public render parameters</description>
+ <portlet-name>PublicParameterPortlet1</portlet-name>
+ <display-name>Public Parameter Portlet 1</display-name>
+ <portlet-class>org.jboss.portal.portlet.samples.basic.PublicParameterPortlet</portlet-class>
+ <supports>
+ <mime-type>text/html</mime-type>
+ </supports>
+ <portlet-info>
+ <title>Public Parameter Portlet</title>
+ <keywords>sample,test</keywords>
+ </portlet-info>
+ <supported-public-render-parameter>foo</supported-public-render-parameter>
+ <supported-public-render-parameter>bar</supported-public-render-parameter>
+ </portlet>
+ <portlet>
+ <description>Portlet that manipulates its public render parameters</description>
+ <portlet-name>PublicParameterPortlet2</portlet-name>
+ <display-name>Public Parameter Portlet 2</display-name>
+ <portlet-class>org.jboss.portal.portlet.samples.basic.PublicParameterPortlet</portlet-class>
+ <supports>
+ <mime-type>text/html</mime-type>
+ </supports>
+ <portlet-info>
+ <title>Public Parameter Portlet</title>
+ <keywords>sample,test</keywords>
+ </portlet-info>
+ <supported-public-render-parameter>foo</supported-public-render-parameter>
+ <supported-public-render-parameter>juu</supported-public-render-parameter>
+ </portlet>
+ <portlet>
+ <description>Portlet that manipulates its public render parameters</description>
+ <portlet-name>PublicParameterPortlet3</portlet-name>
+ <display-name>Public Parameter Portlet 3</display-name>
+ <portlet-class>org.jboss.portal.portlet.samples.basic.PublicParameterPortlet</portlet-class>
+ <supports>
+ <mime-type>text/html</mime-type>
+ </supports>
+ <portlet-info>
+ <title>Public Parameter Portlet</title>
+ <keywords>sample,test</keywords>
+ </portlet-info>
+ <supported-public-render-parameter>bar</supported-public-render-parameter>
+ <supported-public-render-parameter>juu</supported-public-render-parameter>
+ </portlet>
+
+ <public-render-parameter>
+ <name>foo</name>
+ <identifier>foo</identifier>
+ </public-render-parameter>
+
+ <public-render-parameter>
+ <name>bar</name>
+ <identifier>bar</identifier>
+ </public-render-parameter>
+
+ <public-render-parameter>
+ <name>juu</name>
+ <identifier>juu</identifier>
+ </public-render-parameter>
+
+ <event-definition>
+ <qname xmlns:jbp='urn:jboss:portal:samples:event'>jbp:CartEvent</qname>
+ <value-type>org.jboss.portal.portlet.samples.shoppingcart.CartEvent</value-type>
+ </event-definition>
+
+</portlet-app>
+
Modified: modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/web.xml
===================================================================
--- modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/web.xml 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/classic/src/main/artifacts/presentation-war/WEB-INF/web.xml 2008-04-25 22:56:30 UTC (rev 10718)
@@ -27,7 +27,17 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+ <listener>
+ <listener-class>org.jboss.portal.common.mc.bootstrap.WebBootstrap</listener-class>
+ </listener>
+
<servlet>
+ <servlet-name>ContainerServlet</servlet-name>
+ <servlet-class>org.jboss.portal.web.impl.tomcat.TC6ContainerServlet</servlet-class>
+ <load-on-startup>0</load-on-startup>
+ </servlet>
+
+ <servlet>
<servlet-name>ClassicPresentationServlet</servlet-name>
<servlet-class>org.jboss.portal.presentation.classic.ClassicPresentationServlet</servlet-class>
</servlet>
Modified: modules/presentation/trunk/classic/src/main/java/org/jboss/portal/presentation/classic/ClassicPresentationClient.java
===================================================================
--- modules/presentation/trunk/classic/src/main/java/org/jboss/portal/presentation/classic/ClassicPresentationClient.java 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/classic/src/main/java/org/jboss/portal/presentation/classic/ClassicPresentationClient.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -108,6 +108,9 @@
String link = encoder.encode(action, resp);
//
+
+
+ //
if (link == null)
{
throw new IllegalArgumentException("The action " + action + " cannot be rendered");
@@ -196,6 +199,9 @@
UIObject object = node.getObject();
//
+ writer.println("<div style=\"border: 1px solid black\">");
+
+ //
if (object instanceof UIContext)
{
renderChildren(node, writer);
@@ -240,6 +246,9 @@
e.printStackTrace();
}
}
+
+ //
+ writer.println("</div>");
}
private void renderChildren(ClassicUINode node, PrintWriter writer)
Modified: modules/presentation/trunk/classic/src/main/java/org/jboss/portal/presentation/classic/ClassicPresentationServlet.java
===================================================================
--- modules/presentation/trunk/classic/src/main/java/org/jboss/portal/presentation/classic/ClassicPresentationServlet.java 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/classic/src/main/java/org/jboss/portal/presentation/classic/ClassicPresentationServlet.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -32,6 +32,7 @@
import org.jboss.portal.web.WebRequest;
import org.jboss.portal.web.WebResponse;
import org.jboss.portal.web.endpoint.EndPointServlet;
+import org.jboss.portal.portlet.PortletInvoker;
import javax.servlet.ServletException;
import java.io.IOException;
@@ -70,7 +71,10 @@
}
//
- this.server = new PresentationServerImpl(structuralStateContext);
+ PortletInvoker portletInvoker = (PortletInvoker)getServletContext().getAttribute("ConsumerPortletInvoker");
+
+ //
+ this.server = new PresentationServerImpl(structuralStateContext, portletInvoker);
}
protected void service(WebRequest req, WebResponse resp) throws ServletException, IOException
Modified: modules/presentation/trunk/pom.xml
===================================================================
--- modules/presentation/trunk/pom.xml 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/pom.xml 2008-04-25 22:56:30 UTC (rev 10718)
@@ -29,6 +29,6 @@
<module>build</module>
<module>presentation</module>
<module>classic</module>
- <module>ajax</module>
+ <!--<module>ajax</module>-->
</modules>
</project>
Modified: modules/presentation/trunk/presentation/pom.xml
===================================================================
--- modules/presentation/trunk/presentation/pom.xml 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/presentation/pom.xml 2008-04-25 22:56:30 UTC (rev 10718)
@@ -19,8 +19,12 @@
</dependency>
<dependency>
<groupId>org.jboss.portal.portlet</groupId>
- <artifactId>portlet-portal</artifactId>
+ <artifactId>portlet-portlet</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.jboss.portal.portlet</groupId>
+ <artifactId>portlet-controller</artifactId>
+ </dependency>
</dependencies>
<build>
Modified: modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/PresentationServerImpl.java
===================================================================
--- modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/PresentationServerImpl.java 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/PresentationServerImpl.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -26,18 +26,36 @@
import org.jboss.portal.presentation.impl.state.structural.StructuralNode;
import org.jboss.portal.presentation.impl.state.structural.StructuralStateContextImpl;
import org.jboss.portal.presentation.impl.state.structural.WindowNode;
+import org.jboss.portal.presentation.impl.state.structural.PageNode;
+import org.jboss.portal.presentation.impl.server.portlet.StructuralPortletControllerContext;
import org.jboss.portal.presentation.model.content.WindowContent;
import org.jboss.portal.presentation.protocol.ErrorResponse;
import org.jboss.portal.presentation.protocol.ProtocolAction;
import org.jboss.portal.presentation.protocol.ShowUIObjectResponse;
import org.jboss.portal.presentation.protocol.UIObjectAction;
import org.jboss.portal.presentation.protocol.ViewUIObjectAction;
+import org.jboss.portal.presentation.protocol.LinkActivation;
+import org.jboss.portal.presentation.protocol.PostActivation;
import org.jboss.portal.presentation.server.PresentationRequest;
import org.jboss.portal.presentation.server.PresentationResponse;
import org.jboss.portal.presentation.server.PresentationServer;
import org.jboss.portal.presentation.server.PresentationServerException;
import org.jboss.portal.presentation.state.structural.StructuralStateContext;
+import org.jboss.portal.presentation.state.navigational.NavigationalStateContext;
+import org.jboss.portal.portlet.PortletInvoker;
+import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.controller.impl.ControllerRequestFactory;
+import org.jboss.portal.portlet.controller.request.ControllerRequest;
+import org.jboss.portal.portlet.controller.PortletController;
+import org.jboss.portal.portlet.controller.state.PortletPageNavigationalState;
+import org.jboss.portal.portlet.controller.response.ControllerResponse;
+import org.jboss.portal.portlet.controller.response.PageUpdateResponse;
+import org.jboss.portal.portlet.invocation.response.PortletInvocationResponse;
+import org.jboss.portal.portlet.invocation.response.FragmentResponse;
+import org.jboss.portal.web.Body;
+import java.util.Map;
+
/**
* @author <a href="mailto:julien@jboss-portal.org">Julien Viet</a>
* @version $Revision: 630 $
@@ -48,9 +66,13 @@
/** . */
private StructuralStateContextImpl structuralStateContext;
- public PresentationServerImpl(StructuralStateContextImpl structuralStateContext)
+ /** . */
+ private PortletInvoker portletInvoker;
+
+ public PresentationServerImpl(StructuralStateContextImpl structuralStateContext, PortletInvoker portletInvoker)
{
this.structuralStateContext = structuralStateContext;
+ this.portletInvoker = portletInvoker;
}
public StructuralStateContext getStructuralStateContext()
@@ -65,24 +87,38 @@
public WindowContent renderWindow(PresentationClient client, String windowId) throws PresentationServerException
{
- StructuralNode node = structuralStateContext.getNode(windowId);
-
- //
- if (node instanceof WindowNode)
+ try
{
- WindowNode window = (WindowNode)node;
+ WindowNode window = (WindowNode)structuralStateContext.getNode(windowId);
+ //
+ PageNode page = (PageNode)window.getParent();
+ //
+ PortletController controller = new PortletController();
-
+ //
+ StructuralPortletControllerContext portletControllerContext = new StructuralPortletControllerContext(
+ client,
+ page,
+ portletInvoker);
+ PortletInvocationResponse response = controller.render(portletControllerContext, null, null, windowId);
-
- return new WindowContent(0, "Window " + window.getName(), window.getContent());
+ //
+ if (response instanceof FragmentResponse)
+ {
+ FragmentResponse fragment = (FragmentResponse)response;
+ return new WindowContent(0, fragment.getTitle(), fragment.getContent());
+ }
+ else
+ {
+ return new WindowContent(0, "Unexpected response for window " + windowId, "");
+ }
}
- else
+ catch (PortletInvokerException e)
{
- throw new PresentationServerException("No such window " + windowId);
+ throw new PresentationServerException(e);
}
}
@@ -111,6 +147,64 @@
{
return new PresentationResponse(new ShowUIObjectResponse(targetId));
}
+ else if (objectAction instanceof LinkActivation)
+ {
+ LinkActivation linkActivation = (LinkActivation)objectAction;
+
+ //
+ if (targetNode instanceof WindowNode)
+ {
+ WindowNode targetWindow = (WindowNode)targetNode;
+
+ //
+ PageNode targetPage = (PageNode)targetWindow.getParent();
+
+ //
+ ControllerRequestFactory factory = new ControllerRequestFactory(null);
+
+ Body body = null;
+ if (linkActivation instanceof PostActivation)
+ {
+ body = ((PostActivation)linkActivation).getBody();
+ }
+
+ //
+ ControllerRequest controllerRequest = factory.decode(linkActivation.getQueryParameters(), body);
+
+ //
+ PortletController controller = new PortletController();
+
+ //
+ StructuralPortletControllerContext portletControllerContext = new StructuralPortletControllerContext(
+ client,
+ targetPage,
+ portletInvoker);
+
+ //
+ try
+ {
+ ControllerResponse response = controller.process(portletControllerContext, controllerRequest);
+
+ if (response instanceof PageUpdateResponse)
+ {
+ PageUpdateResponse pageUpdate = (PageUpdateResponse)response;
+
+ //
+ NavigationalStateContext nsc = client.getNavigationalStateContext();
+
+ //
+ PortletPageNavigationalState blah = pageUpdate.getPageNavigationalState();
+ }
+ }
+ catch (PortletInvokerException e)
+ {
+ e.printStackTrace();
+ }
+
+ //
+ return new PresentationResponse(new ShowUIObjectResponse(targetPage.getId()));
+ }
+ }
}
//
Modified: modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/PresentationPortletInvoker.java
===================================================================
--- modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/PresentationPortletInvoker.java 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/PresentationPortletInvoker.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -22,26 +22,10 @@
******************************************************************************/
package org.jboss.portal.presentation.impl.server.portlet;
-import org.jboss.portal.presentation.impl.state.structural.StructuralStateContextImpl;
-
/**
* @author <a href="mailto:julien@jboss-portal.org">Julien Viet</a>
* @version $Revision: 630 $
*/
public class PresentationPortletInvoker
{
-
- /** . */
- private StructuralStateContextImpl structuralContext;
-
- public PresentationPortletInvoker(StructuralStateContextImpl structuralContext)
- {
- this.structuralContext = structuralContext;
- }
-
- public void render(String windowId)
- {
-
- }
-
}
Added: modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralEventControllerContext.java
===================================================================
--- modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralEventControllerContext.java (rev 0)
+++ modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralEventControllerContext.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -0,0 +1,70 @@
+/******************************************************************************
+ * JBoss, a division of Red Hat *
+ * Copyright 2008, Red Hat Middleware, LLC, and individual *
+ * contributors as indicated by the @authors tag. See the *
+ * copyright.txt in the distribution for a full listing of *
+ * individual contributors. *
+ * *
+ * This is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU Lesser General Public License as *
+ * published by the Free Software Foundation; either version 2.1 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This software is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this software; if not, write to the Free *
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
+ ******************************************************************************/
+package org.jboss.portal.presentation.impl.server.portlet;
+
+import org.jboss.portal.portlet.controller.event.EventControllerContext;
+import org.jboss.portal.portlet.controller.event.EventPhaseContext;
+import org.jboss.portal.portlet.controller.event.PortletWindowEvent;
+import org.jboss.portal.portlet.invocation.response.PortletInvocationResponse;
+import org.jboss.portal.portlet.info.PortletInfo;
+
+/**
+ * @author <a href="mailto:julien@jboss-portal.org">Julien Viet</a>
+ * @version $Revision: 630 $
+ */
+public class StructuralEventControllerContext implements EventControllerContext
+{
+
+ /** . */
+ private final StructuralPortletControllerContext portletControllerContext;
+
+ public StructuralEventControllerContext(StructuralPortletControllerContext portletControllerContext)
+ {
+ this.portletControllerContext = portletControllerContext;
+ }
+
+ public void eventProduced(EventPhaseContext context, PortletWindowEvent producedEvent, PortletWindowEvent sourceEvent)
+ {
+ for (String windowId : portletControllerContext.getWindowIds())
+ {
+ PortletInfo portletInfo = portletControllerContext.getPortletInfo(windowId);
+ if (portletInfo.getEventing().getConsumedEvents().containsKey(producedEvent.getName()))
+ {
+ PortletWindowEvent distributedEvent = new PortletWindowEvent(producedEvent.getName(), producedEvent.getPayload(), windowId);
+ context.queueEvent(distributedEvent);
+ }
+ }
+ }
+
+ public void eventConsumed(EventPhaseContext context, PortletWindowEvent consumedEvent, PortletInvocationResponse consumerResponse)
+ {
+ }
+
+ public void eventFailed(EventPhaseContext context, PortletWindowEvent failedEvent, Throwable throwable)
+ {
+ }
+
+ public void eventDiscarded(EventPhaseContext context, PortletWindowEvent discardedEvent, int cause)
+ {
+ }
+}
Modified: modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralPortletControllerContext.java
===================================================================
--- modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralPortletControllerContext.java 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralPortletControllerContext.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -24,20 +24,38 @@
import org.jboss.portal.portlet.PortletInvoker;
import org.jboss.portal.portlet.PortletInvokerException;
+import org.jboss.portal.portlet.PortletContext;
+import org.jboss.portal.portlet.Portlet;
+import org.jboss.portal.portlet.impl.spi.AbstractUserContext;
import org.jboss.portal.portlet.controller.PortletControllerContext;
import org.jboss.portal.portlet.controller.event.EventControllerContext;
-import org.jboss.portal.portlet.controller.state.PageNavigationalState;
import org.jboss.portal.portlet.controller.state.StateControllerContext;
+import org.jboss.portal.portlet.controller.state.PortletPageNavigationalState;
import org.jboss.portal.portlet.info.PortletInfo;
import org.jboss.portal.portlet.invocation.ActionInvocation;
import org.jboss.portal.portlet.invocation.EventInvocation;
import org.jboss.portal.portlet.invocation.ResourceInvocation;
+import org.jboss.portal.portlet.invocation.RenderInvocation;
+import org.jboss.portal.portlet.invocation.PortletInvocation;
import org.jboss.portal.portlet.invocation.response.PortletInvocationResponse;
import org.jboss.portal.portlet.spi.PortletInvocationContext;
import org.jboss.portal.presentation.impl.state.structural.PageNode;
+import org.jboss.portal.presentation.impl.state.structural.StructuralNode;
+import org.jboss.portal.presentation.impl.state.structural.WindowNode;
+import org.jboss.portal.presentation.impl.server.portlet.spi.PresentationPortletInvocationContext;
+import org.jboss.portal.presentation.impl.server.portlet.spi.PresentationServerContext;
+import org.jboss.portal.presentation.impl.server.portlet.spi.PresentationWindowContext;
+import org.jboss.portal.presentation.impl.server.portlet.spi.PresentationInstanceContext;
+import org.jboss.portal.presentation.impl.server.portlet.spi.PresentationClientContext;
+import org.jboss.portal.presentation.impl.server.portlet.spi.PresentationPortalContext;
+import org.jboss.portal.presentation.impl.server.portlet.spi.PresentationSecurityContext;
+import org.jboss.portal.presentation.client.PresentationClient;
import javax.servlet.http.Cookie;
import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Set;
/**
* @author <a href="mailto:julien@jboss-portal.org">Julien Viet</a>
@@ -52,44 +70,136 @@
/** . */
private final PortletInvoker invoker;
- public StructuralPortletControllerContext(PageNode page, PortletInvoker invoker)
+ /** . */
+ private final StateControllerContext stateControllerContext;
+
+ /** A map of window ids to portlets. */
+ private final Map<String, Portlet> portlets;
+
+ /** A map of window ids to windows. */
+ private final Map<String, WindowNode> windows;
+
+ /** . */
+ private final PresentationClient client;
+
+ /** . */
+ private final EventControllerContext eventControllerContext;
+
+ public StructuralPortletControllerContext(
+ PresentationClient client,
+ PageNode page,
+ PortletInvoker invoker)
{
+ Map<String, Portlet> portlets = new HashMap<String, Portlet>();
+ Map<String, WindowNode> windows = new HashMap<String, WindowNode>();
+
+ //
+ for (StructuralNode child : page.getChildren())
+ {
+ if (child instanceof WindowNode)
+ {
+ String portletRef = child.getProperty("portlet-ref");
+
+ //
+ if (portletRef != null)
+ {
+ try
+ {
+ Portlet portlet = invoker.getPortlet(PortletContext.createPortletContext(portletRef));
+
+ //
+ portlets.put(child.getId(), portlet);
+ windows.put(child.getId(), (WindowNode)child);
+ }
+ catch (PortletInvokerException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ //
+ this.client = client;
this.page = page;
this.invoker = invoker;
+ this.stateControllerContext = new StructuralStateControllerContext(this, client.getNavigationalStateContext());
+ this.portlets = portlets;
+ this.windows = windows;
+ this.eventControllerContext = new StructuralEventControllerContext(this);
}
+ public String getPageId()
+ {
+ return page.getId();
+ }
+
+ public Set<String> getWindowIds()
+ {
+ return windows.keySet();
+ }
+
public PortletInfo getPortletInfo(String windowId)
{
- return null;
+ return portlets.get(windowId).getInfo();
}
- public PortletInvocationContext createPortletInvocationContext(String windowId, PageNavigationalState pageNavigationalState)
+ public PortletInvocationContext createPortletInvocationContext(String windowId, PortletPageNavigationalState pageNavigationalState)
{
- return null;
+ return new PresentationPortletInvocationContext(client, this, windowId);
}
public PortletInvocationResponse invoke(ActionInvocation actionInvocation) throws PortletInvokerException
{
- return null;
+ return invoke((PortletInvocation)actionInvocation);
}
public PortletInvocationResponse invoke(List<Cookie> requestCookies, EventInvocation eventInvocation) throws PortletInvokerException
{
- return null;
+ return invoke(eventInvocation);
}
+ public PortletInvocationResponse invoke(List<Cookie> requestCookies, RenderInvocation renderInvocation) throws PortletInvokerException
+ {
+ return invoke(renderInvocation);
+ }
+
public PortletInvocationResponse invoke(ResourceInvocation resourceInvocation) throws PortletInvokerException
{
- return null;
+ return invoke((PortletInvocation)resourceInvocation);
}
+ private PortletInvocationResponse invoke(PortletInvocation portletInvocation) throws PortletInvokerException
+ {
+ PresentationPortletInvocationContext ctx = (PresentationPortletInvocationContext)portletInvocation.getContext();
+
+ //
+ WindowNode window = windows.get(ctx.getWindowId());
+
+ //
+ portletInvocation.setServerContext(new PresentationServerContext(client));
+ portletInvocation.setSecurityContext(new PresentationSecurityContext());
+ portletInvocation.setClientContext(new PresentationClientContext());
+ portletInvocation.setInstanceContext(new PresentationInstanceContext(window));
+ portletInvocation.setPortalContext(new PresentationPortalContext());
+ portletInvocation.setUserContext(new AbstractUserContext());
+ portletInvocation.setWindowContext(new PresentationWindowContext(window));
+
+ //
+ Portlet portlet = portlets.get(ctx.getWindowId());
+ portletInvocation.setTarget(portlet.getContext());
+
+ //
+ return invoker.invoke(portletInvocation);
+ }
+
public EventControllerContext getEventControllerContext()
{
- return null;
+ return eventControllerContext;
}
public StateControllerContext getStateControllerContext()
{
- return null;
+ return stateControllerContext;
}
}
Added: modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralPortletPageNavigationalState.java
===================================================================
--- modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralPortletPageNavigationalState.java (rev 0)
+++ modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralPortletPageNavigationalState.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -0,0 +1,195 @@
+/******************************************************************************
+ * JBoss, a division of Red Hat *
+ * Copyright 2008, Red Hat Middleware, LLC, and individual *
+ * contributors as indicated by the @authors tag. See the *
+ * copyright.txt in the distribution for a full listing of *
+ * individual contributors. *
+ * *
+ * This is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU Lesser General Public License as *
+ * published by the Free Software Foundation; either version 2.1 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This software is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this software; if not, write to the Free *
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
+ ******************************************************************************/
+package org.jboss.portal.presentation.impl.server.portlet;
+
+import org.jboss.portal.portlet.controller.state.PortletPageNavigationalState;
+import org.jboss.portal.portlet.controller.state.PortletWindowNavigationalState;
+import org.jboss.portal.portlet.StateString;
+import org.jboss.portal.portlet.info.ParameterInfo;
+import org.jboss.portal.portlet.info.NavigationInfo;
+import org.jboss.portal.presentation.state.navigational.NavigationalStateContext;
+import org.jboss.portal.Mode;
+import org.jboss.portal.WindowState;
+
+import javax.xml.namespace.QName;
+import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:julien@jboss-portal.org">Julien Viet</a>
+ * @version $Revision: 630 $
+ */
+public class StructuralPortletPageNavigationalState implements PortletPageNavigationalState
+{
+
+ /** . */
+ private final StructuralPortletControllerContext portletControllerContext;
+
+ /** . */
+ private final NavigationalStateContext navigationalStateContext;
+
+ public StructuralPortletPageNavigationalState(StructuralPortletControllerContext portletControllerContext, NavigationalStateContext navigationalStateContext)
+ {
+ this.portletControllerContext = portletControllerContext;
+ this.navigationalStateContext = navigationalStateContext;
+ }
+
+ public Set<String> getPortletWindowIds()
+ {
+ return portletControllerContext.getWindowIds();
+ }
+
+ public PortletWindowNavigationalState getPortletWindowNavigationalState(String portletWindowId) throws IllegalArgumentException
+ {
+ Mode mode = (Mode)navigationalStateContext.getProperty(portletWindowId, "windowstate");
+ WindowState windowState = (WindowState)navigationalStateContext.getProperty(portletWindowId, "mode");
+ StateString portletNavigationalState = (StateString)navigationalStateContext.getProperty(portletWindowId, "portlet");
+ return new PortletWindowNavigationalState(portletNavigationalState, mode, windowState);
+ }
+
+ public void setPortletWindowNavigationalState(String portletWindowId, PortletWindowNavigationalState portletWindowState) throws IllegalArgumentException, IllegalStateException
+ {
+ navigationalStateContext.setProperty(portletWindowId, "windowstate", portletWindowState.getWindowState());
+ navigationalStateContext.setProperty(portletWindowId, "mode", portletWindowState.getMode());
+ navigationalStateContext.setProperty(portletWindowId, "portlet", portletWindowState.getPortletNavigationalState());
+ }
+
+ public Map<String, String[]> getPortletPublicNavigationalState(String portletWindowId) throws IllegalArgumentException
+ {
+ Map<QName, String[]> pageParameters = (Map<QName, String[]>)navigationalStateContext.getProperty(portletControllerContext.getPageId(), "portlet");
+
+ //
+ Map<String, String[]> portletParameters = null;
+
+ //
+ if (pageParameters != null)
+ {
+ NavigationInfo navigationInfo = portletControllerContext.getPortletInfo(portletWindowId).getNavigation();
+
+ //
+ for (ParameterInfo parameterInfo : navigationInfo.getPublicParameters())
+ {
+ QName parameterName = parameterInfo.getName();
+ String[] parameterValue = pageParameters.get(parameterName);
+
+ //
+ if (parameterValue != null)
+ {
+ if (portletParameters == null)
+ {
+ portletParameters = new HashMap<String, String[]>();
+ }
+
+ //
+ portletParameters.put(parameterInfo.getId(), parameterValue);
+ }
+ }
+ }
+
+ //
+ return portletParameters;
+ }
+
+ public void setPortletPublicNavigationalState(String portletWindowId, Map<String, String[]> update) throws IllegalArgumentException, IllegalStateException
+ {
+ HashMap<QName, String[]> pageParameters = (HashMap<QName, String[]>)navigationalStateContext.getProperty(portletControllerContext.getPageId(), "portlet");
+
+ //
+ if (pageParameters == null)
+ {
+ pageParameters = new HashMap<QName, String[]>();
+ }
+
+ //
+ NavigationInfo navigationInfo = portletControllerContext.getPortletInfo(portletWindowId).getNavigation();
+
+ //
+ for (Map.Entry<String, String[]> entry : update.entrySet())
+ {
+ ParameterInfo parameterInfo = navigationInfo.getPublicParameter(entry.getKey());
+
+ //
+ QName parameterName = parameterInfo.getName();
+
+ if (entry.getValue().length > 0)
+ {
+ pageParameters.remove(parameterName);
+ }
+ else
+ {
+ pageParameters.put(parameterName, entry.getValue());
+ }
+ }
+
+ //
+ navigationalStateContext.setProperty(portletControllerContext.getPageId(), "portlet", pageParameters);
+ }
+
+ public Set<QName> getPublicNames()
+ {
+ HashMap<QName, String[]> pageParameters = (HashMap<QName, String[]>)navigationalStateContext.getProperty(portletControllerContext.getPageId(), "portlet");
+
+ //
+ return pageParameters != null ? pageParameters.keySet() : null;
+ }
+
+ public String[] getPublicNavigationalState(QName name) throws IllegalArgumentException
+ {
+ Map<QName, String[]> pageParameters = (Map<QName, String[]>)navigationalStateContext.getProperty(portletControllerContext.getPageId(), "portlet");
+
+ //
+ return pageParameters != null ? pageParameters.get(name) : null;
+ }
+
+ public void setPublicNavigationalState(QName name, String[] value) throws IllegalArgumentException, IllegalStateException
+ {
+ HashMap<QName, String[]> pageParameters = (HashMap<QName, String[]>)navigationalStateContext.getProperty(portletControllerContext.getPageId(), "portlet");
+
+ //
+ if (pageParameters == null)
+ {
+ pageParameters = new HashMap<QName, String[]>();
+ }
+
+ //
+ pageParameters.put(name, value);
+
+ //
+ navigationalStateContext.setProperty(portletControllerContext.getPageId(), "portlet", pageParameters);
+ }
+
+ public void removePublicNavigationalState(QName name) throws IllegalArgumentException, IllegalStateException
+ {
+ HashMap<QName, String[]> pageParameters = (HashMap<QName, String[]>)navigationalStateContext.getProperty(portletControllerContext.getPageId(), "portlet");
+
+ //
+ if (pageParameters != null)
+ {
+ pageParameters.remove(name);
+
+ //
+ navigationalStateContext.setProperty(portletControllerContext.getPageId(), "portlet", pageParameters);
+ }
+ }
+}
Added: modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralStateControllerContext.java
===================================================================
--- modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralStateControllerContext.java (rev 0)
+++ modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/StructuralStateControllerContext.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -0,0 +1,57 @@
+/******************************************************************************
+ * JBoss, a division of Red Hat *
+ * Copyright 2008, Red Hat Middleware, LLC, and individual *
+ * contributors as indicated by the @authors tag. See the *
+ * copyright.txt in the distribution for a full listing of *
+ * individual contributors. *
+ * *
+ * This is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU Lesser General Public License as *
+ * published by the Free Software Foundation; either version 2.1 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This software is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this software; if not, write to the Free *
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
+ ******************************************************************************/
+package org.jboss.portal.presentation.impl.server.portlet;
+
+import org.jboss.portal.portlet.controller.state.StateControllerContext;
+import org.jboss.portal.portlet.controller.state.PortletPageNavigationalState;
+import org.jboss.portal.presentation.state.navigational.NavigationalStateContext;
+
+/**
+ * @author <a href="mailto:julien@jboss-portal.org">Julien Viet</a>
+ * @version $Revision: 630 $
+ */
+public class StructuralStateControllerContext implements StateControllerContext
+{
+
+ /** . */
+ private StructuralPortletControllerContext portletControllerContext;
+
+ /** . */
+ private NavigationalStateContext navigationalStateContext;
+
+ public StructuralStateControllerContext(StructuralPortletControllerContext portletControllerContext, NavigationalStateContext navigationalStateContext)
+ {
+ this.portletControllerContext = portletControllerContext;
+ this.navigationalStateContext = navigationalStateContext;
+ }
+
+ public PortletPageNavigationalState clonePortletPageNavigationalState(PortletPageNavigationalState portletPageNavigationalState, boolean modifiable)
+ {
+ return new StructuralPortletPageNavigationalState(portletControllerContext, navigationalStateContext);
+ }
+
+ public PortletPageNavigationalState createPortletPageNavigationalState(boolean modifiable)
+ {
+ return new StructuralPortletPageNavigationalState(portletControllerContext, navigationalStateContext);
+ }
+}
Modified: modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/spi/PresentationClientContext.java
===================================================================
--- modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/spi/PresentationClientContext.java 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/spi/PresentationClientContext.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -25,8 +25,6 @@
import org.jboss.portal.common.util.MultiValuedPropertyMap;
import org.jboss.portal.common.util.SimpleMultiValuedPropertyMap;
import org.jboss.portal.portlet.spi.ClientContext;
-import org.jboss.portal.presentation.protocol.GetActivation;
-import org.jboss.portal.presentation.protocol.LinkActivation;
import javax.servlet.http.Cookie;
import java.util.Collections;
@@ -39,17 +37,13 @@
public class PresentationClientContext implements ClientContext
{
- /** . */
- private final LinkActivation linkActivation;
-
- public PresentationClientContext(LinkActivation linkActivation)
+ public PresentationClientContext()
{
- this.linkActivation = linkActivation;
}
public String getMethod()
{
- return linkActivation instanceof GetActivation ? "GET" : "POST";
+ return "GET";
}
public MultiValuedPropertyMap<String> getProperties()
Added: modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/spi/PresentationPortletInvocationContext.java
===================================================================
--- modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/spi/PresentationPortletInvocationContext.java (rev 0)
+++ modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/spi/PresentationPortletInvocationContext.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -0,0 +1,112 @@
+/******************************************************************************
+ * JBoss, a division of Red Hat *
+ * Copyright 2008, Red Hat Middleware, LLC, and individual *
+ * contributors as indicated by the @authors tag. See the *
+ * copyright.txt in the distribution for a full listing of *
+ * individual contributors. *
+ * *
+ * This is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU Lesser General Public License as *
+ * published by the Free Software Foundation; either version 2.1 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This software is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this software; if not, write to the Free *
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
+ ******************************************************************************/
+package org.jboss.portal.presentation.impl.server.portlet.spi;
+
+import org.jboss.portal.portlet.spi.PortletInvocationContext;
+import org.jboss.portal.portlet.ContainerURL;
+import org.jboss.portal.portlet.URLFormat;
+import org.jboss.portal.portlet.controller.impl.PortletURLRenderer;
+import org.jboss.portal.portlet.controller.impl.ControllerRequestParameterMapFactory;
+import org.jboss.portal.portlet.controller.state.PortletPageNavigationalStateSerialization;
+import org.jboss.portal.portlet.controller.state.StateControllerContext;
+import org.jboss.portal.common.util.MarkupInfo;
+import org.jboss.portal.common.net.media.MediaType;
+import org.jboss.portal.presentation.impl.server.portlet.StructuralPortletControllerContext;
+import org.jboss.portal.presentation.protocol.GetActivation;
+import org.jboss.portal.presentation.client.PresentationClient;
+
+import java.io.Writer;
+import java.io.IOException;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:julien@jboss-portal.org">Julien Viet</a>
+ * @version $Revision: 630 $
+ */
+public class PresentationPortletInvocationContext implements PortletInvocationContext
+{
+
+ /** . */
+ private final MarkupInfo markup = new MarkupInfo(MediaType.TEXT_HTML, "UTF-8");
+
+ /** . */
+ private final StructuralPortletControllerContext portletControllerContext;
+
+ /** . */
+ private final String windowId;
+
+ /** . */
+ private final PresentationClient client;
+
+ public PresentationPortletInvocationContext(
+ PresentationClient client,
+ StructuralPortletControllerContext portletControllerContext,
+ String windowId)
+ {
+ this.client = client;
+ this.portletControllerContext = portletControllerContext;
+ this.windowId = windowId;
+ }
+
+ public String getWindowId()
+ {
+ return windowId;
+ }
+
+ public MarkupInfo getMarkupInfo()
+ {
+ return markup;
+ }
+
+ public String encodeResourceURL(String url) throws IllegalArgumentException
+ {
+ return url;
+ }
+
+ public String renderURL(ContainerURL containerURL, URLFormat format)
+ {
+ StateControllerContext stateControllerContext = portletControllerContext.getStateControllerContext();
+ PortletPageNavigationalStateSerialization serialiation = new PortletPageNavigationalStateSerialization(stateControllerContext);
+ ControllerRequestParameterMapFactory parameterMapFactory = new ControllerRequestParameterMapFactory(serialiation);
+
+ Map<String, String> parameters = parameterMapFactory.encode(null, windowId, containerURL);
+
+ Map<String, String[]> blah = new HashMap<String, String[]>();
+ for (Map.Entry<String, String> entry : parameters.entrySet())
+ {
+ blah.put(entry.getKey(), new String[]{entry.getValue()});
+ }
+
+ GetActivation getActivation = new GetActivation(windowId, "/", blah);
+
+ String url = client.renderURL(getActivation, null);
+
+ return url;
+ }
+
+ public void renderURL(Writer writer, ContainerURL containerURL, URLFormat format) throws IOException
+ {
+ writer.write(renderURL(containerURL, format));
+ }
+}
Added: modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/spi/PresentationSecurityContext.java
===================================================================
--- modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/spi/PresentationSecurityContext.java (rev 0)
+++ modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/server/portlet/spi/PresentationSecurityContext.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -0,0 +1,64 @@
+/******************************************************************************
+ * JBoss, a division of Red Hat *
+ * Copyright 2008, Red Hat Middleware, LLC, and individual *
+ * contributors as indicated by the @authors tag. See the *
+ * copyright.txt in the distribution for a full listing of *
+ * individual contributors. *
+ * *
+ * This is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU Lesser General Public License as *
+ * published by the Free Software Foundation; either version 2.1 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This software is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this software; if not, write to the Free *
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
+ ******************************************************************************/
+package org.jboss.portal.presentation.impl.server.portlet.spi;
+
+import org.jboss.portal.portlet.spi.SecurityContext;
+
+import java.security.Principal;
+
+/**
+ * @author <a href="mailto:julien@jboss-portal.org">Julien Viet</a>
+ * @version $Revision: 630 $
+ */
+public class PresentationSecurityContext implements SecurityContext
+{
+ public boolean isSecure()
+ {
+ return false;
+ }
+
+ public boolean isAuthenticated()
+ {
+ return false;
+ }
+
+ public String getAuthType()
+ {
+ return null;
+ }
+
+ public String getRemoteUser()
+ {
+ return null;
+ }
+
+ public Principal getUserPrincipal()
+ {
+ return null;
+ }
+
+ public boolean isUserInRole(String roleName)
+ {
+ return false;
+ }
+}
Modified: modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/state/navigational/NavigationalStateContextImpl.java
===================================================================
--- modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/state/navigational/NavigationalStateContextImpl.java 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/state/navigational/NavigationalStateContextImpl.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -29,6 +29,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
+import java.io.Serializable;
/**
* @author <a href="mailto:julien@jboss.org">Julien Viet</a>
@@ -38,16 +39,16 @@
{
/** . */
- private final Map<String, Map<String, Object>> map;
+ private final Map<String, Map<String, Serializable>> map;
- public NavigationalStateContextImpl(Map<String, Map<String, Object>> map)
+ public NavigationalStateContextImpl(Map<String, Map<String, Serializable>> map)
{
this.map = map;
}
public NavigationalStateContextImpl()
{
- this(new HashMap<String, Map<String, Object>>());
+ this(new HashMap<String, Map<String, Serializable>>());
}
public Set<String> getPropertyNames(String objectId)
@@ -61,7 +62,7 @@
return map.get(objectId).keySet();
}
- public void setProperty(String objectId, String key, Object navigationalState) throws StateChangeVetoException, StateException, IllegalArgumentException
+ public void setProperty(String objectId, String key, Serializable navigationalState) throws StateChangeVetoException, StateException, IllegalArgumentException
{
if (objectId == null)
{
@@ -73,14 +74,14 @@
}
//
- Map<String, Object> properties = map.get(objectId);
+ Map<String, Serializable> properties = map.get(objectId);
//
if (navigationalState != null)
{
if (properties == null)
{
- properties = new HashMap<String, Object>();
+ properties = new HashMap<String, Serializable>();
map.put(objectId, properties);
}
@@ -102,7 +103,7 @@
}
}
- public Object getProperty(String objectId, String key) throws IllegalArgumentException
+ public Serializable getProperty(String objectId, String key) throws IllegalArgumentException
{
if (objectId == null)
{
@@ -114,7 +115,7 @@
}
//
- Map<String, Object> properties = map.get(objectId);
+ Map<String, Serializable> properties = map.get(objectId);
//
if (properties != null)
Modified: modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/state/structural/NodeImporter.java
===================================================================
--- modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/state/structural/NodeImporter.java 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/impl/state/structural/NodeImporter.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -119,6 +119,11 @@
}
}
+ private void importProperties()
+ {
+
+ }
+
private void importContextDef(Element contextDefElt)
{
// Children pages
@@ -128,7 +133,7 @@
}
}
- private void importPageDef(StructuralNode parentNode, Element pageDefElt)
+ private PageNode importPageDef(StructuralNode parentNode, Element pageDefElt)
{
PageNode pageNode = createStructuralNode(parentNode, PageNode.class, pageDefElt);
@@ -143,9 +148,12 @@
{
importWindowDef(pageNode, childElt);
}
+
+ //
+ return pageNode;
}
- private void importWindowDef(StructuralNode parentNode, Element windowDefElt)
+ private WindowNode importWindowDef(StructuralNode parentNode, Element windowDefElt)
{
WindowNode windowNode = createStructuralNode(parentNode, WindowNode.class, windowDefElt);
@@ -155,6 +163,9 @@
//
String content = asString(contentElt);
windowNode.setContent(content);
+
+ //
+ return windowNode;
}
private <T extends StructuralNode> T createStructuralNode(StructuralNode parent, Class<T> type, Element nodeDefElt)
@@ -162,6 +173,29 @@
String nodeName = nodeDefElt.getAttribute("name");
//
- return parent.addChild(nodeName, type);
+ T node = parent.addChild(nodeName, type);
+
+ //
+ Element propertiesElt = XMLTools.getUniqueChild(nodeDefElt, "properties", false);
+
+ //
+ if (propertiesElt != null)
+ {
+ for (Element propertyElt : XMLTools.getChildren(propertiesElt, "property"))
+ {
+ Element nameElt = XMLTools.getUniqueChild(propertyElt, "name", true);
+ String propertyName = XMLTools.asString(nameElt);
+
+ //
+ Element valueElt = XMLTools.getUniqueChild(propertyElt, "value", true);
+ String propertyValue = XMLTools.asString(valueElt);
+
+ //
+ node.setProperty(propertyName, propertyValue);
+ }
+ }
+
+ //
+ return node;
}
}
Modified: modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/protocol/LinkActivation.java
===================================================================
--- modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/protocol/LinkActivation.java 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/protocol/LinkActivation.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -80,54 +80,34 @@
{
return queryParameters;
}
-
+
+
/**
- *
- * @return
+ * Returns the first value of the specified query parameter or null if no such value exists.
+ *
+ * @param parameterName the parameter name
+ * @return the query parameter value or null
+ * @throws IllegalArgumentException if the query parameter is null
*/
- public WindowState getWindowState()
+ public String getQueryParameter(String parameterName) throws IllegalArgumentException
{
- WindowState windowState = null;
-
- if(this.queryParameters != null)
+ if (parameterName == null)
{
- String[] windowStateValue = this.queryParameters.get("windowstate");
- if(windowStateValue != null)
- {
- windowState = WindowState.create(windowStateValue[0]);
- }
+ throw new IllegalArgumentException();
}
-
- if(windowState == null)
+
+ if (queryParameters != null)
{
- windowState = windowState.NORMAL;
- }
-
- return windowState;
- }
-
- /**
- *
- * @return
- */
- public Mode getWindowMode()
- {
- Mode mode = null;
-
- if(this.queryParameters != null)
- {
- String[] modeValue = this.queryParameters.get("mode");
- if(modeValue != null)
+ String[] value = this.queryParameters.get(parameterName);
+
+ //
+ if(value != null)
{
- mode = Mode.create(modeValue[0]);
+ return value[0];
}
}
-
- if(mode == null)
- {
- mode = Mode.VIEW;
- }
-
- return mode;
- }
+
+ //
+ return null;
+ }
}
Modified: modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/state/navigational/NavigationalStateContext.java
===================================================================
--- modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/state/navigational/NavigationalStateContext.java 2008-04-25 01:39:30 UTC (rev 10717)
+++ modules/presentation/trunk/presentation/src/main/java/org/jboss/portal/presentation/state/navigational/NavigationalStateContext.java 2008-04-25 22:56:30 UTC (rev 10718)
@@ -25,6 +25,7 @@
import org.jboss.portal.presentation.state.StateException;
import java.util.Set;
+import java.io.Serializable;
/**
* @author <a href="mailto:julien@jboss.org">Julien Viet</a>
@@ -33,10 +34,33 @@
public interface NavigationalStateContext
{
+ /**
+ * Returns the set of known properties or null if it does not exist for a specified object id.
+ *
+ * @param objectId the object id
+ * @return the set of property names
+ */
Set<String> getPropertyNames(String objectId);
- Object getProperty(String objectId, String key) throws IllegalArgumentException;
+ /**
+ * Returns the property value for the specified object id and key.
+ *
+ * @param objectId the object id
+ * @param key the property key
+ * @return the property value
+ * @throws IllegalArgumentException if any argument is null
+ */
+ Serializable getProperty(String objectId, String key) throws IllegalArgumentException;
- void setProperty(String objectId, String key, Object navigationalState) throws StateException, IllegalArgumentException;
+ /**
+ * Set a property value with the provided navigational state
+ *
+ * @param objectId the object id
+ * @param key the property key
+ * @param navigationalState the navigational state
+ * @throws StateException any state exception
+ * @throws IllegalArgumentException if the object id or key is null
+ */
+ void setProperty(String objectId, String key, Serializable navigationalState) throws StateException, IllegalArgumentException;
}
\ No newline at end of file
16 years
JBoss Portal SVN: r10717 - branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna.
by portal-commits@lists.jboss.org
Author: wesleyhales
Date: 2008-04-24 21:39:30 -0400 (Thu, 24 Apr 2008)
New Revision: 10717
Modified:
branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/builder.js
branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/controls.js
branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/dragdrop.js
branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/effects.js
branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/scriptaculous.js
branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/slider.js
branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/unittest.js
Log:
upgrade scriptaculous
Modified: branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/builder.js
===================================================================
--- branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/builder.js 2008-04-25 01:37:24 UTC (rev 10716)
+++ branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/builder.js 2008-04-25 01:39:30 UTC (rev 10717)
@@ -1,6 +1,6 @@
-// script.aculo.us builder.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
@@ -48,7 +48,8 @@
// attributes (or text)
if(arguments[1])
if(this._isStringOrNumber(arguments[1]) ||
- (arguments[1] instanceof Array)) {
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
this._children(element, arguments[1]);
} else {
var attrs = this._attributes(arguments[1]);
@@ -66,7 +67,7 @@
}
if(element.tagName.toUpperCase() != elementName)
element = parentElement.getElementsByTagName(elementName)[0];
- }
+ }
}
// text, or array of children
@@ -88,10 +89,14 @@
var attrs = [];
for(attribute in attributes)
attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
- '="' + attributes[attribute].toString().escapeHTML() + '"');
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'"') + '"');
return attrs.join(" ");
},
_children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
if(typeof children=='object') { // array can hold nodes and text
children.flatten().each( function(e) {
if(typeof e=='object')
@@ -101,8 +106,8 @@
element.appendChild(Builder._text(e));
});
} else
- if(Builder._isStringOrNumber(children))
- element.appendChild(Builder._text(children));
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
},
_isStringOrNumber: function(param) {
return(typeof param=='string' || typeof param=='number');
Modified: branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/controls.js
===================================================================
--- branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/controls.js 2008-04-25 01:37:24 UTC (rev 10716)
+++ branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/controls.js 2008-04-25 01:39:30 UTC (rev 10717)
@@ -1,8 +1,8 @@
-// script.aculo.us controls.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
+// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// (c) 2005, 2006 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
-// (c) 2005, 2006 Jon Tirsen (http://www.tirsen.com)
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
// Contributors:
// Richard Livsey
// Rahul Bhargava
@@ -39,22 +39,23 @@
if(typeof Effect == 'undefined')
throw("controls.js requires including script.aculo.us' effects.js library");
-var Autocompleter = {}
-Autocompleter.Base = function() {};
-Autocompleter.Base.prototype = {
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
baseInitialize: function(element, update, options) {
- this.element = $(element);
+ element = $(element)
+ this.element = element;
this.update = $(update);
this.hasFocus = false;
this.changed = false;
this.active = false;
this.index = 0;
this.entryCount = 0;
+ this.oldElementValue = this.element.value;
if(this.setOptions)
this.setOptions(options);
else
- this.options = options || {};
+ this.options = options || { };
this.options.paramName = this.options.paramName || this.element.name;
this.options.tokens = this.options.tokens || [];
@@ -76,6 +77,9 @@
if(typeof(this.options.tokens) == 'string')
this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
this.observer = null;
@@ -83,15 +87,14 @@
Element.hide(this.update);
- Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
- Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
},
show: function() {
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
if(!this.iefix &&
- (navigator.appVersion.indexOf('MSIE')>0) &&
- (navigator.userAgent.indexOf('Opera')<0) &&
+ (Prototype.Browser.IE) &&
(Element.getStyle(this.update, 'position')=='absolute')) {
new Insertion.After(this.update,
'<iframe id="' + this.update.id + '_iefix" '+
@@ -141,17 +144,17 @@
case Event.KEY_UP:
this.markPrevious();
this.render();
- if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
+ Event.stop(event);
return;
case Event.KEY_DOWN:
this.markNext();
this.render();
- if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
+ Event.stop(event);
return;
}
else
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
- (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return;
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
this.changed = true;
this.hasFocus = true;
@@ -197,7 +200,6 @@
this.index==i ?
Element.addClassName(this.getEntry(i),"selected") :
Element.removeClassName(this.getEntry(i),"selected");
-
if(this.hasFocus) {
this.show();
this.active = true;
@@ -240,21 +242,22 @@
}
var value = '';
if (this.options.select) {
- var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
} else
value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
- var lastTokenPos = this.findLastToken();
- if (lastTokenPos != -1) {
- var newValue = this.element.value.substr(0, lastTokenPos + 1);
- var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
if (whitespace)
newValue += whitespace[0];
- this.element.value = newValue + value;
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
} else {
this.element.value = value;
}
+ this.oldElementValue = this.element.value;
this.element.focus();
if (this.options.afterUpdateElement)
@@ -298,39 +301,48 @@
onObserverEvent: function() {
this.changed = false;
+ this.tokenBounds = null;
if(this.getToken().length>=this.options.minChars) {
- this.startIndicator();
this.getUpdatedChoices();
} else {
this.active = false;
this.hide();
}
+ this.oldElementValue = this.element.value;
},
getToken: function() {
- var tokenPos = this.findLastToken();
- if (tokenPos != -1)
- var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
- else
- var ret = this.element.value;
-
- return /\n/.test(ret) ? '' : ret;
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
},
- findLastToken: function() {
- var lastTokenPos = -1;
-
- for (var i=0; i<this.options.tokens.length; i++) {
- var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
- if (thisTokenPos > lastTokenPos)
- lastTokenPos = thisTokenPos;
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
}
- return lastTokenPos;
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
}
-}
+});
-Ajax.Autocompleter = Class.create();
-Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
initialize: function(element, update, url, options) {
this.baseInitialize(element, update, options);
this.options.asynchronous = true;
@@ -340,7 +352,9 @@
},
getUpdatedChoices: function() {
- entry = encodeURIComponent(this.options.paramName) + '=' +
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
encodeURIComponent(this.getToken());
this.options.parameters = this.options.callback ?
@@ -348,14 +362,13 @@
if(this.options.defaultParams)
this.options.parameters += '&' + this.options.defaultParams;
-
+
new Ajax.Request(this.url, this.options);
},
onComplete: function(request) {
this.updateChoices(request.responseText);
}
-
});
// The local array autocompleter. Used when you'd prefer to
@@ -393,8 +406,7 @@
// In that case, the other options above will not apply unless
// you support them.
-Autocompleter.Local = Class.create();
-Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
+Autocompleter.Local = Class.create(Autocompleter.Base, {
initialize: function(element, update, array, options) {
this.baseInitialize(element, update, options);
this.options.array = array;
@@ -450,13 +462,12 @@
ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
return "<ul>" + ret.join('') + "</ul>";
}
- }, options || {});
+ }, options || { });
}
});
-// AJAX in-place editor
-//
-// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd(a)tddsworld.com> (April 2007).
// Use this if you notice weird scrolling problems on some browsers,
// the DOM might be a bit confused when this gets called so do this
@@ -467,353 +478,472 @@
}, 1);
}
-Ajax.InPlaceEditor = Class.create();
-Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
-Ajax.InPlaceEditor.prototype = {
+Ajax.InPlaceEditor = Class.create({
initialize: function(element, url, options) {
this.url = url;
- this.element = $(element);
-
- this.options = Object.extend({
- paramName: "value",
- okButton: true,
- okText: "ok",
- cancelLink: true,
- cancelText: "cancel",
- savingText: "Saving...",
- clickToEditText: "Click to edit",
- okText: "ok",
- rows: 1,
- onComplete: function(transport, element) {
- new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
- },
- onFailure: function(transport) {
- alert("Error communicating with the server: " + transport.responseText.stripTags());
- },
- callback: function(form) {
- return Form.serialize(form);
- },
- handleLineBreaks: true,
- loadingText: 'Loading...',
- savingClassName: 'inplaceeditor-saving',
- loadingClassName: 'inplaceeditor-loading',
- formClassName: 'inplaceeditor-form',
- highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
- highlightendcolor: "#FFFFFF",
- externalControl: null,
- submitOnBlur: false,
- ajaxOptions: {},
- evalScripts: false
- }, options || {});
-
- if(!this.options.formId && this.element.id) {
- this.options.formId = this.element.id + "-inplaceeditor";
- if ($(this.options.formId)) {
- // there's already a form with that name, don't specify an id
- this.options.formId = null;
- }
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
}
-
- if (this.options.externalControl) {
+ if (this.options.externalControl)
this.options.externalControl = $(this.options.externalControl);
- }
-
- this.originalBackground = Element.getStyle(this.element, 'background-color');
- if (!this.originalBackground) {
- this.originalBackground = "transparent";
- }
-
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
this.element.title = this.options.clickToEditText;
-
- this.onclickListener = this.enterEditMode.bindAsEventListener(this);
- this.mouseoverListener = this.enterHover.bindAsEventListener(this);
- this.mouseoutListener = this.leaveHover.bindAsEventListener(this);
- Event.observe(this.element, 'click', this.onclickListener);
- Event.observe(this.element, 'mouseover', this.mouseoverListener);
- Event.observe(this.element, 'mouseout', this.mouseoutListener);
- if (this.options.externalControl) {
- Event.observe(this.options.externalControl, 'click', this.onclickListener);
- Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener);
- Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
- }
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
},
- enterEditMode: function(evt) {
- if (this.saving) return;
- if (this.editing) return;
- this.editing = true;
- this.onEnterEditMode();
- if (this.options.externalControl) {
- Element.hide(this.options.externalControl);
- }
- Element.hide(this.element);
- this.createForm();
- this.element.parentNode.insertBefore(this.form, this.element);
- if (!this.options.loadTextURL) Field.scrollFreeActivate(this.editField);
- // stop the event to avoid a page refresh in Safari
- if (evt) {
- Event.stop(evt);
- }
- return false;
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
},
- createForm: function() {
- this.form = document.createElement("form");
- this.form.id = this.options.formId;
- Element.addClassName(this.form, this.options.formClassName)
- this.form.onsubmit = this.onSubmit.bind(this);
-
- this.createEditField();
-
- if (this.options.textarea) {
- var br = document.createElement("br");
- this.form.appendChild(br);
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
}
-
- if (this.options.okButton) {
- okButton = document.createElement("input");
- okButton.type = "submit";
- okButton.value = this.options.okText;
- okButton.className = 'editor_ok_button';
- this.form.appendChild(okButton);
- }
-
- if (this.options.cancelLink) {
- cancelLink = document.createElement("a");
- cancelLink.href = "#";
- cancelLink.appendChild(document.createTextNode(this.options.cancelText));
- cancelLink.onclick = this.onclickCancel.bind(this);
- cancelLink.className = 'editor_cancel';
- this.form.appendChild(cancelLink);
- }
},
- hasHTMLLineBreaks: function(string) {
- if (!this.options.handleLineBreaks) return false;
- return string.match(/<br/i) || string.match(/<p>/i);
- },
- convertHTMLLineBreaks: function(string) {
- return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, "");
- },
createEditField: function() {
- var text;
- if(this.options.loadTextURL) {
- text = this.options.loadingText;
- } else {
- text = this.getText();
- }
-
- var obj = this;
-
- if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
- this.options.textarea = false;
- var textField = document.createElement("input");
- textField.obj = this;
- textField.type = "text";
- textField.name = this.options.paramName;
- textField.value = text;
- textField.style.backgroundColor = this.options.highlightcolor;
- textField.className = 'editor_field';
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
var size = this.options.size || this.options.cols || 0;
- if (size != 0) textField.size = size;
- if (this.options.submitOnBlur)
- textField.onblur = this.onSubmit.bind(this);
- this.editField = textField;
+ if (0 < size) fld.size = size;
} else {
- this.options.textarea = true;
- var textArea = document.createElement("textarea");
- textArea.obj = this;
- textArea.name = this.options.paramName;
- textArea.value = this.convertHTMLLineBreaks(text);
- textArea.rows = this.options.rows;
- textArea.cols = this.options.cols || 40;
- textArea.className = 'editor_field';
- if (this.options.submitOnBlur)
- textArea.onblur = this.onSubmit.bind(this);
- this.editField = textArea;
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
}
-
- if(this.options.loadTextURL) {
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
this.loadExternalText();
- }
- this.form.appendChild(this.editField);
+ this._form.appendChild(this._controls.editor);
},
- getText: function() {
- return this.element.innerHTML;
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
},
- loadExternalText: function() {
- Element.addClassName(this.form, this.options.loadingClassName);
- this.editField.disabled = true;
- new Ajax.Request(
- this.options.loadTextURL,
- Object.extend({
- asynchronous: true,
- onComplete: this.onLoadedExternalText.bind(this)
- }, this.options.ajaxOptions)
- );
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
},
- onLoadedExternalText: function(transport) {
- Element.removeClassName(this.form, this.options.loadingClassName);
- this.editField.disabled = false;
- this.editField.value = transport.responseText.stripTags();
- Field.scrollFreeActivate(this.editField);
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
},
- onclickCancel: function() {
- this.onComplete();
- this.leaveEditMode();
- return false;
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
},
- onFailure: function(transport) {
- this.options.onFailure(transport);
- if (this.oldInnerHTML) {
- this.element.innerHTML = this.oldInnerHTML;
- this.oldInnerHTML = null;
+ getText: function() {
+ return this.element.innerHTML;
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
}
- return false;
},
- onSubmit: function() {
- // onLoading resets these so we need to save them away for the Ajax call
- var form = this.form;
- var value = this.editField.value;
-
- // do this first, sometimes the ajax call returns before we get a chance to switch on Saving...
- // which means this will actually switch on Saving... *after* we've left edit mode causing Saving...
- // to be displayed indefinitely
- this.onLoading();
-
- if (this.options.evalScripts) {
- new Ajax.Request(
- this.url, Object.extend({
- parameters: this.options.callback(form, value),
- onComplete: this.onComplete.bind(this),
- onFailure: this.onFailure.bind(this),
- asynchronous:true,
- evalScripts:true
- }, this.options.ajaxOptions));
- } else {
- new Ajax.Updater(
- { success: this.element,
- // don't update on failure (this could be an option)
- failure: null },
- this.url, Object.extend({
- parameters: this.options.callback(form, value),
- onComplete: this.onComplete.bind(this),
- onFailure: this.onFailure.bind(this)
- }, this.options.ajaxOptions));
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
}
- // stop the event to avoid a page refresh in Safari
- if (arguments.length > 1) {
- Event.stop(arguments[0]);
- }
- return false;
+ if (e) Event.stop(e);
},
- onLoading: function() {
- this.saving = true;
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
this.removeForm();
this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
this.showSaving();
},
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
showSaving: function() {
- this.oldInnerHTML = this.element.innerHTML;
+ this._oldInnerHTML = this.element.innerHTML;
this.element.innerHTML = this.options.savingText;
- Element.addClassName(this.element, this.options.savingClassName);
- this.element.style.backgroundColor = this.originalBackground;
- Element.show(this.element);
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
},
- removeForm: function() {
- if(this.form) {
- if (this.form.parentNode) Element.remove(this.form);
- this.form = null;
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
}
},
- enterHover: function() {
- if (this.saving) return;
- this.element.style.backgroundColor = this.options.highlightcolor;
- if (this.effect) {
- this.effect.cancel();
- }
- Element.addClassName(this.element, this.options.hoverClassName)
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
},
- leaveHover: function() {
- if (this.options.backgroundColor) {
- this.element.style.backgroundColor = this.oldBackground;
- }
- Element.removeClassName(this.element, this.options.hoverClassName)
- if (this.saving) return;
- this.effect = new Effect.Highlight(this.element, {
- startcolor: this.options.highlightcolor,
- endcolor: this.options.highlightendcolor,
- restorecolor: this.originalBackground
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
});
+ new Ajax.Request(this.options.loadCollectionURL, options);
},
- leaveEditMode: function() {
- Element.removeClassName(this.element, this.options.savingClassName);
- this.removeForm();
- this.leaveHover();
- this.element.style.backgroundColor = this.originalBackground;
- Element.show(this.element);
- if (this.options.externalControl) {
- Element.show(this.options.externalControl);
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
}
- this.editing = false;
- this.saving = false;
- this.oldInnerHTML = null;
- this.onLeaveEditMode();
+ tempOption.update((text || '').stripScripts().stripTags());
},
- onComplete: function(transport) {
- this.leaveEditMode();
- this.options.onComplete.bind(this)(transport, this.element);
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
},
- onEnterEditMode: function() {},
- onLeaveEditMode: function() {},
- dispose: function() {
- if (this.oldInnerHTML) {
- this.element.innerHTML = this.oldInnerHTML;
- }
- this.leaveEditMode();
- Event.stopObserving(this.element, 'click', this.onclickListener);
- Event.stopObserving(this.element, 'mouseover', this.mouseoverListener);
- Event.stopObserving(this.element, 'mouseout', this.mouseoutListener);
- if (this.options.externalControl) {
- Event.stopObserving(this.options.externalControl, 'click', this.onclickListener);
- Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener);
- Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener);
- }
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
}
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
};
-Ajax.InPlaceCollectionEditor = Class.create();
-Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype);
-Object.extend(Ajax.InPlaceCollectionEditor.prototype, {
- createEditField: function() {
- if (!this.cached_selectTag) {
- var selectTag = document.createElement("select");
- var collection = this.options.collection || [];
- var optionTag;
- collection.each(function(e,i) {
- optionTag = document.createElement("option");
- optionTag.value = (e instanceof Array) ? e[0] : e;
- if((typeof this.options.value == 'undefined') &&
- ((e instanceof Array) ? this.element.innerHTML == e[1] : e == optionTag.value)) optionTag.selected = true;
- if(this.options.value==optionTag.value) optionTag.selected = true;
- optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e));
- selectTag.appendChild(optionTag);
- }.bind(this));
- this.cached_selectTag = selectTag;
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
}
-
- this.editField = this.cached_selectTag;
- if(this.options.loadTextURL) this.loadExternalText();
- this.form.appendChild(this.editField);
- this.options.callback = function(form, value) {
- return "value=" + encodeURIComponent(value);
- }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
}
});
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
// Delayed observer, like Form.Element.Observer,
// but waits for delay after last key input
// Ideal for live-search fields
-Form.Element.DelayedObserver = Class.create();
-Form.Element.DelayedObserver.prototype = {
+Form.Element.DelayedObserver = Class.create({
initialize: function(element, delay, callback) {
this.delay = delay || 0.5;
this.element = $(element);
@@ -832,4 +962,4 @@
this.timer = null;
this.callback(this.element, $F(this.element));
}
-};
+});
Modified: branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/dragdrop.js
===================================================================
--- branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/dragdrop.js 2008-04-25 01:37:24 UTC (rev 10716)
+++ branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/dragdrop.js 2008-04-25 01:39:30 UTC (rev 10717)
@@ -1,12 +1,12 @@
-// script.aculo.us dragdrop.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
+// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// (c) 2005, 2006 Sammi Williams (http://www.oriontransfer.co.nz, sammi(a)oriontransfer.co.nz)
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi(a)oriontransfer.co.nz)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
-if(typeof Effect == 'undefined')
+if(Object.isUndefined(Effect))
throw("dragdrop.js requires including script.aculo.us' effects.js library");
var Droppables = {
@@ -22,14 +22,13 @@
greedy: true,
hoverclass: null,
tree: false
- }, arguments[1] || {});
+ }, arguments[1] || { });
// cache containers
if(options.containment) {
options._containers = [];
var containment = options.containment;
- if((typeof containment == 'object') &&
- (containment.constructor == Array)) {
+ if(Object.isArray(containment)) {
containment.each( function(c) { options._containers.push($(c)) });
} else {
options._containers.push($(containment));
@@ -89,21 +88,23 @@
show: function(point, element) {
if(!this.drops.length) return;
- var affected = [];
+ var drop, affected = [];
- if(this.last_active) this.deactivate(this.last_active);
this.drops.each( function(drop) {
if(Droppables.isAffected(point, element, drop))
affected.push(drop);
});
- if(affected.length>0) {
+ if(affected.length>0)
drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
Position.within(drop.element, point[0], point[1]);
if(drop.onHover)
drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
- Droppables.activate(drop);
+ if (drop != this.last_active) Droppables.activate(drop);
}
},
@@ -112,8 +113,10 @@
Position.prepare();
if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
- if (this.last_active.onDrop)
- this.last_active.onDrop(element, this.last_active.element, event);
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
},
reset: function() {
@@ -221,10 +224,7 @@
/*--------------------------------------------------------------------------*/
-var Draggable = Class.create();
-Draggable._dragging = {};
-
-Draggable.prototype = {
+var Draggable = Class.create({
initialize: function(element) {
var defaults = {
handle: false,
@@ -235,7 +235,7 @@
});
},
endeffect: function(element) {
- var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0;
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
queue: {scope:'_draggable', position:'end'},
afterFinish: function(){
@@ -245,6 +245,7 @@
},
zindex: 1000,
revert: false,
+ quiet: false,
scroll: false,
scrollSensitivity: 20,
scrollSpeed: 15,
@@ -252,7 +253,7 @@
delay: 0
};
- if(!arguments[1] || typeof arguments[1].endeffect == 'undefined')
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
Object.extend(defaults, {
starteffect: function(element) {
element._opacity = Element.getOpacity(element);
@@ -261,11 +262,11 @@
}
});
- var options = Object.extend(defaults, arguments[1] || {});
+ var options = Object.extend(defaults, arguments[1] || { });
this.element = $(element);
- if(options.handle && (typeof options.handle == 'string'))
+ if(options.handle && Object.isString(options.handle))
this.handle = this.element.down('.'+options.handle, 0);
if(!this.handle) this.handle = $(options.handle);
@@ -278,7 +279,6 @@
Element.makePositioned(this.element); // fix IE
- this.delta = this.currentDelta();
this.options = options;
this.dragging = false;
@@ -300,7 +300,7 @@
},
initDrag: function(event) {
- if(typeof Draggable._dragging[this.element] != 'undefined' &&
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
Draggable._dragging[this.element]) return;
if(Event.isLeftClick(event)) {
// abort on form elements, fixes a Firefox issue
@@ -323,6 +323,8 @@
startDrag: function(event) {
this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
if(this.options.zindex) {
this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
@@ -331,7 +333,9 @@
if(this.options.ghosting) {
this._clone = this.element.cloneNode(true);
- Position.absolutize(this.element);
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this.element._originallyAbsolute)
+ Position.absolutize(this.element);
this.element.parentNode.insertBefore(this._clone, this.element);
}
@@ -353,8 +357,12 @@
updateDrag: function(event, pointer) {
if(!this.dragging) this.startDrag(event);
- Position.prepare();
- Droppables.show(pointer, this.element);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
Draggables.notify('onDrag', this, event);
this.draw(pointer);
@@ -382,30 +390,44 @@
}
// fix AppleWebKit rendering
- if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
Event.stop(event);
},
finishDrag: function(event, success) {
this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
if(this.options.ghosting) {
- Position.relativize(this.element);
+ if (!this.element._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this.element._originallyAbsolute;
Element.remove(this._clone);
this._clone = null;
}
- if(success) Droppables.fire(event, this.element);
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
Draggables.notify('onEnd', this, event);
var revert = this.options.revert;
- if(revert && typeof revert == 'function') revert = revert(this.element);
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
var d = this.currentDelta();
if(revert && this.options.reverteffect) {
- this.options.reverteffect(this.element,
- d[1]-this.delta[1], d[0]-this.delta[0]);
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
} else {
this.delta = d;
}
@@ -453,15 +475,15 @@
}.bind(this));
if(this.options.snap) {
- if(typeof this.options.snap == 'function') {
+ if(Object.isFunction(this.options.snap)) {
p = this.options.snap(p[0],p[1],this);
} else {
- if(this.options.snap instanceof Array) {
+ if(Object.isArray(this.options.snap)) {
p = p.map( function(v, i) {
- return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this))
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
} else {
p = p.map( function(v) {
- return Math.round(v/this.options.snap)*this.options.snap }.bind(this))
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
}
}}
@@ -545,12 +567,13 @@
}
return { top: T, left: L, width: W, height: H };
}
-}
+});
+Draggable._dragging = { };
+
/*--------------------------------------------------------------------------*/
-var SortableObserver = Class.create();
-SortableObserver.prototype = {
+var SortableObserver = Class.create({
initialize: function(element, observer) {
this.element = $(element);
this.observer = observer;
@@ -566,12 +589,12 @@
if(this.lastValue != Sortable.serialize(this.element))
this.observer(this.element)
}
-}
+});
var Sortable = {
SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
- sortables: {},
+ sortables: { },
_findRootElement: function(element) {
while (element.tagName.toUpperCase() != "BODY") {
@@ -614,13 +637,20 @@
delay: 0,
hoverclass: null,
ghosting: false,
+ quiet: false,
scroll: false,
scrollSensitivity: 20,
scrollSpeed: 15,
format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
onChange: Prototype.emptyFunction,
onUpdate: Prototype.emptyFunction
- }, arguments[1] || {});
+ }, arguments[1] || { });
// clear any old sortable with same element
this.destroy(element);
@@ -628,6 +658,7 @@
// build options for the draggables
var options_for_draggable = {
revert: true,
+ quiet: options.quiet,
scroll: options.scroll,
scrollSpeed: options.scrollSpeed,
scrollSensitivity: options.scrollSensitivity,
@@ -681,10 +712,9 @@
options.droppables.push(element);
}
- (this.findElements(element, options) || []).each( function(e) {
- // handles are per-draggable
- var handle = options.handle ?
- $(e).down('.'+options.handle,0) : e;
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
options.draggables.push(
new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
Droppables.add(e, options_for_droppable);
@@ -844,7 +874,7 @@
only: sortableOptions.only,
name: element.id,
format: sortableOptions.format
- }, arguments[1] || {});
+ }, arguments[1] || { });
var root = {
id: null,
@@ -868,7 +898,7 @@
sequence: function(element) {
element = $(element);
- var options = Object.extend(this.options(element), arguments[1] || {});
+ var options = Object.extend(this.options(element), arguments[1] || { });
return $(this.findElements(element, options) || []).map( function(item) {
return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
@@ -877,9 +907,9 @@
setSequence: function(element, new_sequence) {
element = $(element);
- var options = Object.extend(this.options(element), arguments[2] || {});
+ var options = Object.extend(this.options(element), arguments[2] || { });
- var nodeMap = {};
+ var nodeMap = { };
this.findElements(element, options).each( function(n) {
if (n.id.match(options.format))
nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
@@ -897,7 +927,7 @@
serialize: function(element) {
element = $(element);
- var options = Object.extend(Sortable.options(element), arguments[1] || {});
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
var name = encodeURIComponent(
(arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
@@ -921,7 +951,7 @@
return Element.isParent(child.parentNode, element);
}
-Element.findChildren = function(element, only, recursive, tagName) {
+Element.findChildren = function(element, only, recursive, tagName) {
if(!element.hasChildNodes()) return null;
tagName = tagName.toUpperCase();
if(only) only = [only].flatten();
Modified: branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/effects.js
===================================================================
--- branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/effects.js 2008-04-25 01:37:24 UTC (rev 10716)
+++ branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/effects.js 2008-04-25 01:39:30 UTC (rev 10717)
@@ -1,6 +1,6 @@
-// script.aculo.us effects.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
// Justin Palmer (http://encytemedia.com/)
// Mark Pilgrim (http://diveintomark.org/)
@@ -13,17 +13,17 @@
// returns self (or first argument) if not convertable
String.prototype.parseColor = function() {
var color = '#';
- if(this.slice(0,4) == 'rgb(') {
+ if (this.slice(0,4) == 'rgb(') {
var cols = this.slice(4,this.length-1).split(',');
var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
} else {
- if(this.slice(0,1) == '#') {
- if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
- if(this.length==7) color = this.toLowerCase();
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
}
}
- return(color.length==7 ? color : (arguments[0] || this));
-}
+ return (color.length==7 ? color : (arguments[0] || this));
+};
/*--------------------------------------------------------------------------*/
@@ -32,7 +32,7 @@
return (node.nodeType==3 ? node.nodeValue :
(node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
}).flatten().join('');
-}
+};
Element.collectTextNodesIgnoreClass = function(element, className) {
return $A($(element).childNodes).collect( function(node) {
@@ -40,26 +40,18 @@
((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
Element.collectTextNodesIgnoreClass(node, className) : ''));
}).flatten().join('');
-}
+};
Element.setContentZoom = function(element, percent) {
element = $(element);
element.setStyle({fontSize: (percent/100) + 'em'});
- if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
return element;
-}
+};
-Element.getOpacity = function(element){
- return $(element).getStyle('opacity');
-}
-
-Element.setOpacity = function(element, value){
- return $(element).setStyle({opacity:value});
-}
-
Element.getInlineOpacity = function(element){
return $(element).style.opacity || '';
-}
+};
Element.forceRerendering = function(element) {
try {
@@ -72,31 +64,63 @@
/*--------------------------------------------------------------------------*/
-Array.prototype.call = function() {
- var args = arguments;
- this.each(function(f){ f.apply(this, args) });
-}
-
-/*--------------------------------------------------------------------------*/
-
var Effect = {
_elementDoesNotExistError: {
name: 'ElementDoesNotExistError',
message: 'The specified DOM element does not exist, but is required for this effect to operate'
},
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
tagifyText: function(element) {
- if(typeof Builder == 'undefined')
- throw("Effect.tagifyText requires including script.aculo.us' builder.js library");
-
var tagifyStyle = 'position:relative';
- if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';zoom:1';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
element = $(element);
$A(element.childNodes).each( function(child) {
- if(child.nodeType==3) {
+ if (child.nodeType==3) {
child.nodeValue.toArray().each( function(character) {
element.insertBefore(
- Builder.node('span',{style: tagifyStyle},
+ new Element('span', {style: tagifyStyle}).update(
character == ' ' ? String.fromCharCode(160) : character),
child);
});
@@ -106,8 +130,8 @@
},
multiple: function(element, effect) {
var elements;
- if(((typeof element == 'object') ||
- (typeof element == 'function')) &&
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
(element.length))
elements = element;
else
@@ -116,7 +140,7 @@
var options = Object.extend({
speed: 0.1,
delay: 0.0
- }, arguments[2] || {});
+ }, arguments[2] || { });
var masterDelay = options.delay;
$A(elements).each( function(element, index) {
@@ -133,53 +157,20 @@
effect = (effect || 'appear').toLowerCase();
var options = Object.extend({
queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
- }, arguments[2] || {});
+ }, arguments[2] || { });
Effect[element.visible() ?
Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
}
};
-var Effect2 = Effect; // deprecated
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
-/* ------------- transitions ------------- */
-
-Effect.Transitions = {
- linear: Prototype.K,
- sinoidal: function(pos) {
- return (-Math.cos(pos*Math.PI)/2) + 0.5;
- },
- reverse: function(pos) {
- return 1-pos;
- },
- flicker: function(pos) {
- return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
- },
- wobble: function(pos) {
- return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
- },
- pulse: function(pos, pulses) {
- pulses = pulses || 5;
- return (
- Math.round((pos % (1/pulses)) * pulses) == 0 ?
- ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) :
- 1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2))
- );
- },
- none: function(pos) {
- return 0;
- },
- full: function(pos) {
- return 1;
- }
-};
-
/* ------------- core effects ------------- */
-Effect.ScopedQueue = Class.create();
-Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
+Effect.ScopedQueue = Class.create(Enumerable, {
initialize: function() {
this.effects = [];
- this.interval = null;
+ this.interval = null;
},
_each: function(iterator) {
this.effects._each(iterator);
@@ -187,7 +178,7 @@
add: function(effect) {
var timestamp = new Date().getTime();
- var position = (typeof effect.options.queue == 'string') ?
+ var position = Object.isString(effect.options.queue) ?
effect.options.queue : effect.options.queue.position;
switch(position) {
@@ -210,15 +201,15 @@
effect.startOn += timestamp;
effect.finishOn += timestamp;
- if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
this.effects.push(effect);
- if(!this.interval)
+ if (!this.interval)
this.interval = setInterval(this.loop.bind(this), 15);
},
remove: function(effect) {
this.effects = this.effects.reject(function(e) { return e==effect });
- if(this.effects.length == 0) {
+ if (this.effects.length == 0) {
clearInterval(this.interval);
this.interval = null;
}
@@ -226,103 +217,95 @@
loop: function() {
var timePos = new Date().getTime();
for(var i=0, len=this.effects.length;i<len;i++)
- if(this.effects[i]) this.effects[i].loop(timePos);
+ this.effects[i] && this.effects[i].loop(timePos);
}
});
Effect.Queues = {
instances: $H(),
get: function(queueName) {
- if(typeof queueName != 'string') return queueName;
+ if (!Object.isString(queueName)) return queueName;
- if(!this.instances[queueName])
- this.instances[queueName] = new Effect.ScopedQueue();
-
- return this.instances[queueName];
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
}
-}
+};
Effect.Queue = Effect.Queues.get('global');
-Effect.DefaultOptions = {
- transition: Effect.Transitions.sinoidal,
- duration: 1.0, // seconds
- fps: 60.0, // max. 60fps due to Effect.Queue implementation
- sync: false, // true for combining
- from: 0.0,
- to: 1.0,
- delay: 0.0,
- queue: 'parallel'
-}
-
-Effect.Base = function() {};
-Effect.Base.prototype = {
+Effect.Base = Class.create({
position: null,
start: function(options) {
- this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
this.currentFrame = 0;
this.state = 'idle';
this.startOn = this.options.delay*1000;
- this.finishOn = this.startOn + (this.options.duration*1000);
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
this.event('beforeStart');
- if(!this.options.sync)
- Effect.Queues.get(typeof this.options.queue == 'string' ?
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
'global' : this.options.queue.scope).add(this);
},
loop: function(timePos) {
- if(timePos >= this.startOn) {
- if(timePos >= this.finishOn) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
this.render(1.0);
this.cancel();
this.event('beforeFinish');
- if(this.finish) this.finish();
+ if (this.finish) this.finish();
this.event('afterFinish');
return;
}
- var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
- var frame = Math.round(pos * this.options.fps * this.options.duration);
- if(frame > this.currentFrame) {
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
this.render(pos);
this.currentFrame = frame;
}
}
},
- render: function(pos) {
- if(this.state == 'idle') {
- this.state = 'running';
- this.event('beforeSetup');
- if(this.setup) this.setup();
- this.event('afterSetup');
- }
- if(this.state == 'running') {
- if(this.options.transition) pos = this.options.transition(pos);
- pos *= (this.options.to-this.options.from);
- pos += this.options.from;
- this.position = pos;
- this.event('beforeUpdate');
- if(this.update) this.update(pos);
- this.event('afterUpdate');
- }
- },
cancel: function() {
- if(!this.options.sync)
- Effect.Queues.get(typeof this.options.queue == 'string' ?
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
'global' : this.options.queue.scope).remove(this);
this.state = 'finished';
},
event: function(eventName) {
- if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
- if(this.options[eventName]) this.options[eventName](this);
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
},
inspect: function() {
var data = $H();
for(property in this)
- if(typeof this[property] != 'function') data[property] = this[property];
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
}
-}
+});
-Effect.Parallel = Class.create();
-Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
+Effect.Parallel = Class.create(Effect.Base, {
initialize: function(effects) {
this.effects = effects || [];
this.start(arguments[1]);
@@ -335,35 +318,45 @@
effect.render(1.0);
effect.cancel();
effect.event('beforeFinish');
- if(effect.finish) effect.finish(position);
+ if (effect.finish) effect.finish(position);
effect.event('afterFinish');
});
}
});
-Effect.Event = Class.create();
-Object.extend(Object.extend(Effect.Event.prototype, Effect.Base.prototype), {
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
initialize: function() {
- var options = Object.extend({
- duration: 0
- }, arguments[0] || {});
- this.start(options);
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
},
update: Prototype.emptyFunction
});
-Effect.Opacity = Class.create();
-Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
+Effect.Opacity = Class.create(Effect.Base, {
initialize: function(element) {
this.element = $(element);
- if(!this.element) throw(Effect._elementDoesNotExistError);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
// make this work on IE on elements without 'layout'
- if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout))
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
this.element.setStyle({zoom: 1});
var options = Object.extend({
from: this.element.getOpacity() || 0.0,
to: 1.0
- }, arguments[1] || {});
+ }, arguments[1] || { });
this.start(options);
},
update: function(position) {
@@ -371,36 +364,30 @@
}
});
-Effect.Move = Class.create();
-Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
+Effect.Move = Class.create(Effect.Base, {
initialize: function(element) {
this.element = $(element);
- if(!this.element) throw(Effect._elementDoesNotExistError);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
x: 0,
y: 0,
mode: 'relative'
- }, arguments[1] || {});
+ }, arguments[1] || { });
this.start(options);
},
setup: function() {
- // Bug in Opera: Opera returns the "real" position of a static element or
- // relative element that does not have top/left explicitly set.
- // ==> Always set top and left for position relative elements in your stylesheets
- // (to 0 if you do not need them)
this.element.makePositioned();
this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
this.originalTop = parseFloat(this.element.getStyle('top') || '0');
- if(this.options.mode == 'absolute') {
- // absolute movement, so we need to calc deltaX and deltaY
+ if (this.options.mode == 'absolute') {
this.options.x = this.options.x - this.originalLeft;
this.options.y = this.options.y - this.originalTop;
}
},
update: function(position) {
this.element.setStyle({
- left: Math.round(this.options.x * position + this.originalLeft) + 'px',
- top: Math.round(this.options.y * position + this.originalTop) + 'px'
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
});
}
});
@@ -408,30 +395,29 @@
// for backwards compatibility
Effect.MoveBy = function(element, toTop, toLeft) {
return new Effect.Move(element,
- Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
};
-Effect.Scale = Class.create();
-Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
+Effect.Scale = Class.create(Effect.Base, {
initialize: function(element, percent) {
this.element = $(element);
- if(!this.element) throw(Effect._elementDoesNotExistError);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
scaleX: true,
scaleY: true,
scaleContent: true,
scaleFromCenter: false,
- scaleMode: 'box', // 'box' or 'contents' or {} with provided values
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
scaleFrom: 100.0,
scaleTo: percent
- }, arguments[2] || {});
+ }, arguments[2] || { });
this.start(options);
},
setup: function() {
this.restoreAfterFinish = this.options.restoreAfterFinish || false;
this.elementPositioning = this.element.getStyle('position');
- this.originalStyle = {};
+ this.originalStyle = { };
['top','left','width','height','fontSize'].each( function(k) {
this.originalStyle[k] = this.element.style[k];
}.bind(this));
@@ -441,7 +427,7 @@
var fontSize = this.element.getStyle('font-size') || '100%';
['em','px','%','pt'].each( function(fontSizeType) {
- if(fontSize.indexOf(fontSizeType)>0) {
+ if (fontSize.indexOf(fontSizeType)>0) {
this.fontSize = parseFloat(fontSize);
this.fontSizeType = fontSizeType;
}
@@ -450,62 +436,61 @@
this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
this.dims = null;
- if(this.options.scaleMode=='box')
+ if (this.options.scaleMode=='box')
this.dims = [this.element.offsetHeight, this.element.offsetWidth];
- if(/^content/.test(this.options.scaleMode))
+ if (/^content/.test(this.options.scaleMode))
this.dims = [this.element.scrollHeight, this.element.scrollWidth];
- if(!this.dims)
+ if (!this.dims)
this.dims = [this.options.scaleMode.originalHeight,
this.options.scaleMode.originalWidth];
},
update: function(position) {
var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
- if(this.options.scaleContent && this.fontSize)
+ if (this.options.scaleContent && this.fontSize)
this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
},
finish: function(position) {
- if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
},
setDimensions: function(height, width) {
- var d = {};
- if(this.options.scaleX) d.width = Math.round(width) + 'px';
- if(this.options.scaleY) d.height = Math.round(height) + 'px';
- if(this.options.scaleFromCenter) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
var topd = (height - this.dims[0])/2;
var leftd = (width - this.dims[1])/2;
- if(this.elementPositioning == 'absolute') {
- if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
- if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
} else {
- if(this.options.scaleY) d.top = -topd + 'px';
- if(this.options.scaleX) d.left = -leftd + 'px';
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
}
}
this.element.setStyle(d);
}
});
-Effect.Highlight = Class.create();
-Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
+Effect.Highlight = Class.create(Effect.Base, {
initialize: function(element) {
this.element = $(element);
- if(!this.element) throw(Effect._elementDoesNotExistError);
- var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
this.start(options);
},
setup: function() {
// Prevent executing on elements not in the layout flow
- if(this.element.getStyle('display')=='none') { this.cancel(); return; }
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
// Disable background image during the effect
- this.oldStyle = {};
+ this.oldStyle = { };
if (!this.options.keepBackgroundImage) {
this.oldStyle.backgroundImage = this.element.getStyle('background-image');
this.element.setStyle({backgroundImage: 'none'});
}
- if(!this.options.endcolor)
+ if (!this.options.endcolor)
this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
- if(!this.options.restorecolor)
+ if (!this.options.restorecolor)
this.options.restorecolor = this.element.getStyle('background-color');
// init color calculations
this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
@@ -513,7 +498,7 @@
},
update: function(position) {
this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
- return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
},
finish: function() {
this.element.setStyle(Object.extend(this.oldStyle, {
@@ -522,45 +507,37 @@
}
});
-Effect.ScrollTo = Class.create();
-Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
- initialize: function(element) {
- this.element = $(element);
- this.start(arguments[1] || {});
- },
- setup: function() {
- Position.prepare();
- var offsets = Position.cumulativeOffset(this.element);
- if(this.options.offset) offsets[1] += this.options.offset;
- var max = window.innerHeight ?
- window.height - window.innerHeight :
- document.body.scrollHeight -
- (document.documentElement.clientHeight ?
- document.documentElement.clientHeight : document.body.clientHeight);
- this.scrollStart = Position.deltaY;
- this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
- },
- update: function(position) {
- Position.prepare();
- window.scrollTo(Position.deltaX,
- this.scrollStart + (position*this.delta));
- }
-});
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
/* ------------- combination effects ------------- */
Effect.Fade = function(element) {
element = $(element);
var oldOpacity = element.getInlineOpacity();
var options = Object.extend({
- from: element.getOpacity() || 1.0,
- to: 0.0,
- afterFinishInternal: function(effect) {
- if(effect.options.to!=0) return;
- effect.element.hide().setStyle({opacity: oldOpacity});
- }}, arguments[1] || {});
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
return new Effect.Opacity(element,options);
-}
+};
Effect.Appear = function(element) {
element = $(element);
@@ -573,9 +550,9 @@
},
beforeSetup: function(effect) {
effect.element.setOpacity(effect.options.from).show();
- }}, arguments[1] || {});
+ }}, arguments[1] || { });
return new Effect.Opacity(element,options);
-}
+};
Effect.Puff = function(element) {
element = $(element);
@@ -597,9 +574,9 @@
},
afterFinishInternal: function(effect) {
effect.effects[0].element.hide().setStyle(oldStyle); }
- }, arguments[1] || {})
+ }, arguments[1] || { })
);
-}
+};
Effect.BlindUp = function(element) {
element = $(element);
@@ -611,9 +588,9 @@
afterFinishInternal: function(effect) {
effect.element.hide().undoClipping();
}
- }, arguments[1] || {})
+ }, arguments[1] || { })
);
-}
+};
Effect.BlindDown = function(element) {
element = $(element);
@@ -630,8 +607,8 @@
afterFinishInternal: function(effect) {
effect.element.undoClipping();
}
- }, arguments[1] || {}));
-}
+ }, arguments[1] || { }));
+};
Effect.SwitchOff = function(element) {
element = $(element);
@@ -652,8 +629,8 @@
}
})
}
- }, arguments[1] || {}));
-}
+ }, arguments[1] || { }));
+};
Effect.DropOut = function(element) {
element = $(element);
@@ -672,29 +649,35 @@
afterFinishInternal: function(effect) {
effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
}
- }, arguments[1] || {}));
-}
+ }, arguments[1] || { }));
+};
Effect.Shake = function(element) {
element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
var oldStyle = {
top: element.getStyle('top'),
left: element.getStyle('left') };
- return new Effect.Move(element,
- { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
- { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
- { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
- { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
- { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
- { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
effect.element.undoPositioned().setStyle(oldStyle);
}}) }}) }}) }}) }}) }});
-}
+};
Effect.SlideDown = function(element) {
element = $(element).cleanWhitespace();
@@ -710,7 +693,7 @@
afterSetup: function(effect) {
effect.element.makePositioned();
effect.element.down().makePositioned();
- if(window.opera) effect.element.setStyle({top: ''});
+ if (window.opera) effect.element.setStyle({top: ''});
effect.element.makeClipping().setStyle({height: '0px'}).show();
},
afterUpdateInternal: function(effect) {
@@ -720,23 +703,25 @@
afterFinishInternal: function(effect) {
effect.element.undoClipping().undoPositioned();
effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
- }, arguments[1] || {})
+ }, arguments[1] || { })
);
-}
+};
Effect.SlideUp = function(element) {
element = $(element).cleanWhitespace();
var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
return new Effect.Scale(element, window.opera ? 0 : 1,
Object.extend({ scaleContent: false,
scaleX: false,
scaleMode: 'box',
scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
restoreAfterFinish: true,
- beforeStartInternal: function(effect) {
+ afterSetup: function(effect) {
effect.element.makePositioned();
effect.element.down().makePositioned();
- if(window.opera) effect.element.setStyle({top: ''});
+ if (window.opera) effect.element.setStyle({top: ''});
effect.element.makeClipping().show();
},
afterUpdateInternal: function(effect) {
@@ -744,12 +729,12 @@
(effect.dims[0] - effect.element.clientHeight) + 'px' });
},
afterFinishInternal: function(effect) {
- effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: oldInnerBottom});
- effect.element.down().undoPositioned();
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
}
- }, arguments[1] || {})
+ }, arguments[1] || { })
);
-}
+};
// Bug in opera makes the TD containing this element expand for a instance after finish
Effect.Squish = function(element) {
@@ -762,7 +747,7 @@
effect.element.hide().undoClipping();
}
});
-}
+};
Effect.Grow = function(element) {
element = $(element);
@@ -771,7 +756,7 @@
moveTransition: Effect.Transitions.sinoidal,
scaleTransition: Effect.Transitions.sinoidal,
opacityTransition: Effect.Transitions.full
- }, arguments[1] || {});
+ }, arguments[1] || { });
var oldStyle = {
top: element.style.top,
left: element.style.left,
@@ -836,7 +821,7 @@
)
}
});
-}
+};
Effect.Shrink = function(element) {
element = $(element);
@@ -845,7 +830,7 @@
moveTransition: Effect.Transitions.sinoidal,
scaleTransition: Effect.Transitions.sinoidal,
opacityTransition: Effect.Transitions.none
- }, arguments[1] || {});
+ }, arguments[1] || { });
var oldStyle = {
top: element.style.top,
left: element.style.left,
@@ -890,11 +875,11 @@
effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
}, options)
);
-}
+};
Effect.Pulsate = function(element) {
element = $(element);
- var options = arguments[1] || {};
+ var options = arguments[1] || { };
var oldOpacity = element.getInlineOpacity();
var transition = options.transition || Effect.Transitions.sinoidal;
var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
@@ -903,7 +888,7 @@
Object.extend(Object.extend({ duration: 2.0, from: 0,
afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
}, options), {transition: reverser}));
-}
+};
Effect.Fold = function(element) {
element = $(element);
@@ -923,72 +908,71 @@
afterFinishInternal: function(effect) {
effect.element.hide().undoClipping().setStyle(oldStyle);
} });
- }}, arguments[1] || {}));
+ }}, arguments[1] || { }));
};
-Effect.Morph = Class.create();
-Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), {
+Effect.Morph = Class.create(Effect.Base, {
initialize: function(element) {
this.element = $(element);
- if(!this.element) throw(Effect._elementDoesNotExistError);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
- style: {}
- }, arguments[1] || {});
- if (typeof options.style == 'string') {
- if(options.style.indexOf(':') == -1) {
- var cssText = '', selector = '.' + options.style;
- $A(document.styleSheets).reverse().each(function(styleSheet) {
- if (styleSheet.cssRules) cssRules = styleSheet.cssRules;
- else if (styleSheet.rules) cssRules = styleSheet.rules;
- $A(cssRules).reverse().each(function(rule) {
- if (selector == rule.selectorText) {
- cssText = rule.style.cssText;
- throw $break;
- }
- });
- if (cssText) throw $break;
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
});
- this.style = cssText.parseStyle();
- options.afterFinishInternal = function(effect){
+ options.afterFinishInternal = function(effect) {
effect.element.addClassName(effect.options.style);
effect.transforms.each(function(transform) {
- if(transform.style != 'opacity')
- effect.element.style[transform.style.camelize()] = '';
+ effect.element.style[transform.style] = '';
});
}
- } else this.style = options.style.parseStyle();
- } else this.style = $H(options.style)
+ }
+ }
this.start(options);
},
+
setup: function(){
function parseColor(color){
- if(!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
color = color.parseColor();
return $R(0,2).map(function(i){
return parseInt( color.slice(i*2+1,i*2+3), 16 )
});
}
this.transforms = this.style.map(function(pair){
- var property = pair[0].underscore().dasherize(), value = pair[1], unit = null;
+ var property = pair[0], value = pair[1], unit = null;
- if(value.parseColor('#zzzzzz') != '#zzzzzz') {
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
value = value.parseColor();
unit = 'color';
- } else if(property == 'opacity') {
+ } else if (property == 'opacity') {
value = parseFloat(value);
- if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout))
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
this.element.setStyle({zoom: 1});
- } else if(Element.CSS_LENGTH.test(value))
- var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/),
- value = parseFloat(components[1]), unit = (components.length == 3) ? components[2] : null;
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
var originalValue = this.element.getStyle(property);
- return $H({
- style: property,
+ return {
+ style: property.camelize(),
originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
targetValue: unit=='color' ? parseColor(value) : value,
unit: unit
- });
+ };
}.bind(this)).reject(function(transform){
return (
(transform.originalValue == transform.targetValue) ||
@@ -1000,32 +984,35 @@
});
},
update: function(position) {
- var style = $H(), value = null;
- this.transforms.each(function(transform){
- value = transform.unit=='color' ?
- $R(0,2).inject('#',function(m,v,i){
- return m+(Math.round(transform.originalValue[i]+
- (transform.targetValue[i] - transform.originalValue[i])*position)).toColorPart() }) :
- transform.originalValue + Math.round(
- ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit;
- style[transform.style] = value;
- });
- this.element.setStyle(style);
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
}
});
-Effect.Transform = Class.create();
-Object.extend(Effect.Transform.prototype, {
+Effect.Transform = Class.create({
initialize: function(tracks){
this.tracks = [];
- this.options = arguments[1] || {};
+ this.options = arguments[1] || { };
this.addTracks(tracks);
},
addTracks: function(tracks){
tracks.each(function(track){
- var data = $H(track).values().first();
+ track = $H(track);
+ var data = track.values().first();
this.tracks.push($H({
- ids: $H(track).keys().first(),
+ ids: track.keys().first(),
effect: Effect.Morph,
options: { style: data }
}));
@@ -1035,8 +1022,9 @@
play: function(){
return new Effect.Parallel(
this.tracks.map(function(track){
- var elements = [$(track.ids) || $$(track.ids)].flatten();
- return elements.map(function(e){ return new track.effect(e, Object.extend({ sync:true }, track.options)) });
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
}).flatten(),
this.options
);
@@ -1056,35 +1044,79 @@
Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+String.__parseStyleElement = document.createElement('div');
String.prototype.parseStyle = function(){
- var element = Element.extend(document.createElement('div'));
- element.innerHTML = '<div style="' + this + '"></div>';
- var style = element.down().style, styleRules = $H();
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
Element.CSS_PROPERTIES.each(function(property){
- if(style[property]) styleRules[property] = style[property];
+ if (style[property]) styleRules.set(property, style[property]);
});
- if(/MSIE/.test(navigator.userAgent) && !window.opera && this.indexOf('opacity') > -1) {
- styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1];
- }
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
return styleRules;
};
-Element.morph = function(element, style) {
- new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {}));
- return element;
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
};
-['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom',
- 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each(
- function(f) { Element.Methods[f] = Element[f]; }
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
);
-Element.Methods.visualEffect = function(element, effect, options) {
- s = effect.gsub(/_/, '-').camelize();
- effect_class = s.charAt(0).toUpperCase() + s.substring(1);
- new Effect[effect_class](element, options);
- return $(element);
-};
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
-Element.addMethods();
\ No newline at end of file
+Element.addMethods(Effect.Methods);
Modified: branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/scriptaculous.js
===================================================================
--- branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/scriptaculous.js 2008-04-25 01:37:24 UTC (rev 10716)
+++ branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/scriptaculous.js 2008-04-25 01:39:30 UTC (rev 10717)
@@ -1,6 +1,6 @@
-// script.aculo.us scriptaculous.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
@@ -24,25 +24,32 @@
// For details, see the script.aculo.us web site: http://script.aculo.us/
var Scriptaculous = {
- Version: '1.7.0',
+ Version: '1.8.1',
require: function(libraryName) {
// inserting via DOM fails in Safari 2.0, so brute force approach
- document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
},
+ REQUIRED_PROTOTYPE: '1.6.0',
load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
if((typeof Prototype=='undefined') ||
(typeof Element == 'undefined') ||
(typeof Element.Methods=='undefined') ||
- parseFloat(Prototype.Version.split(".")[0] + "." +
- Prototype.Version.split(".")[1]) < 1.5)
- throw("script.aculo.us requires the Prototype JavaScript framework >= 1.5.0");
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
$A(document.getElementsByTagName("script")).findAll( function(s) {
return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
}).each( function(s) {
var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
var includes = s.src.match(/\?.*load=([a-z,]*)/);
- (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider').split(',').each(
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
function(include) { Scriptaculous.require(path+include+'.js') });
});
}
Modified: branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/slider.js
===================================================================
--- branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/slider.js 2008-04-25 01:37:24 UTC (rev 10716)
+++ branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/slider.js 2008-04-25 01:39:30 UTC (rev 10717)
@@ -1,12 +1,11 @@
-// script.aculo.us slider.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
+// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
-// Copyright (c) 2005, 2006 Marty Haught, Thomas Fuchs
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
-if(!Control) var Control = {};
-Control.Slider = Class.create();
+if (!Control) var Control = { };
// options:
// axis: 'vertical', or 'horizontal' (default)
@@ -14,18 +13,18 @@
// callbacks:
// onChange(value)
// onSlide(value)
-Control.Slider.prototype = {
+Control.Slider = Class.create({
initialize: function(handle, track, options) {
var slider = this;
- if(handle instanceof Array) {
+ if (Object.isArray(handle)) {
this.handles = handle.collect( function(e) { return $(e) });
} else {
this.handles = [$(handle)];
}
this.track = $(track);
- this.options = options || {};
+ this.options = options || { };
this.axis = this.options.axis || 'horizontal';
this.increment = this.options.increment || 1;
@@ -59,11 +58,11 @@
this.dragging = false;
this.disabled = false;
- if(this.options.disabled) this.setDisabled();
+ if (this.options.disabled) this.setDisabled();
// Allowed values array
this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
- if(this.allowedValues) {
+ if (this.allowedValues) {
this.minimum = this.allowedValues.min();
this.maximum = this.allowedValues.max();
}
@@ -76,16 +75,15 @@
this.handles.each( function(h,i) {
i = slider.handles.length-1-i;
slider.setValue(parseFloat(
- (slider.options.sliderValue instanceof Array ?
+ (Object.isArray(slider.options.sliderValue) ?
slider.options.sliderValue[i] : slider.options.sliderValue) ||
slider.range.start), i);
- Element.makePositioned(h); // fix IE
- Event.observe(h, "mousedown", slider.eventMouseDown);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
});
- Event.observe(this.track, "mousedown", this.eventMouseDown);
- Event.observe(document, "mouseup", this.eventMouseUp);
- Event.observe(document, "mousemove", this.eventMouseMove);
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
this.initialized = true;
},
@@ -105,36 +103,36 @@
this.disabled = false;
},
getNearestValue: function(value){
- if(this.allowedValues){
- if(value >= this.allowedValues.max()) return(this.allowedValues.max());
- if(value <= this.allowedValues.min()) return(this.allowedValues.min());
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
var offset = Math.abs(this.allowedValues[0] - value);
var newValue = this.allowedValues[0];
this.allowedValues.each( function(v) {
var currentOffset = Math.abs(v - value);
- if(currentOffset <= offset){
+ if (currentOffset <= offset){
newValue = v;
offset = currentOffset;
}
});
return newValue;
}
- if(value > this.range.end) return this.range.end;
- if(value < this.range.start) return this.range.start;
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
return value;
},
setValue: function(sliderValue, handleIdx){
- if(!this.active) {
+ if (!this.active) {
this.activeHandleIdx = handleIdx || 0;
this.activeHandle = this.handles[this.activeHandleIdx];
this.updateStyles();
}
handleIdx = handleIdx || this.activeHandleIdx || 0;
- if(this.initialized && this.restricted) {
- if((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
sliderValue = this.values[handleIdx-1];
- if((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
sliderValue = this.values[handleIdx+1];
}
sliderValue = this.getNearestValue(sliderValue);
@@ -145,7 +143,7 @@
this.translateToPx(sliderValue);
this.drawSpans();
- if(!this.dragging || !this.event) this.updateFinished();
+ if (!this.dragging || !this.event) this.updateFinished();
},
setValueBy: function(delta, handleIdx) {
this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
@@ -173,24 +171,24 @@
(this.track.offsetHeight != 0 ? this.track.offsetHeight :
this.track.style.height.replace(/px$/,"")) - this.alignY :
(this.track.offsetWidth != 0 ? this.track.offsetWidth :
- this.track.style.width.replace(/px$/,"")) - this.alignY);
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
},
isVertical: function(){
return (this.axis == 'vertical');
},
drawSpans: function() {
var slider = this;
- if(this.spans)
+ if (this.spans)
$R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
- if(this.options.startSpan)
+ if (this.options.startSpan)
this.setSpan(this.options.startSpan,
$R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
- if(this.options.endSpan)
+ if (this.options.endSpan)
this.setSpan(this.options.endSpan,
$R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
},
setSpan: function(span, range) {
- if(this.isVertical()) {
+ if (this.isVertical()) {
span.style.top = this.translateToPx(range.start);
span.style.height = this.translateToPx(range.end - range.start + this.range.start);
} else {
@@ -203,14 +201,14 @@
Element.addClassName(this.activeHandle, 'selected');
},
startDrag: function(event) {
- if(Event.isLeftClick(event)) {
- if(!this.disabled){
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
this.active = true;
var handle = Event.element(event);
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var track = handle;
- if(track==this.track) {
+ if (track==this.track) {
var offsets = Position.cumulativeOffset(this.track);
this.event = event;
this.setValue(this.translateToValue(
@@ -224,7 +222,7 @@
while((this.handles.indexOf(handle) == -1) && handle.parentNode)
handle = handle.parentNode;
- if(this.handles.indexOf(handle)!=-1) {
+ if (this.handles.indexOf(handle)!=-1) {
this.activeHandle = handle;
this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
this.updateStyles();
@@ -239,11 +237,10 @@
}
},
update: function(event) {
- if(this.active) {
- if(!this.dragging) this.dragging = true;
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
this.draw(event);
- // fix AppleWebKit rendering
- if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
Event.stop(event);
}
},
@@ -254,11 +251,11 @@
pointer[1] -= this.offsetY + offsets[1];
this.event = event;
this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
- if(this.initialized && this.options.onSlide)
+ if (this.initialized && this.options.onSlide)
this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
},
endDrag: function(event) {
- if(this.active && this.dragging) {
+ if (this.active && this.dragging) {
this.finishDrag(event, true);
Event.stop(event);
}
@@ -271,8 +268,8 @@
this.updateFinished();
},
updateFinished: function() {
- if(this.initialized && this.options.onChange)
+ if (this.initialized && this.options.onChange)
this.options.onChange(this.values.length>1 ? this.values : this.value, this);
this.event = null;
}
-}
\ No newline at end of file
+});
Modified: branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/unittest.js
===================================================================
--- branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/unittest.js 2008-04-25 01:37:24 UTC (rev 10716)
+++ branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/unittest.js 2008-04-25 01:39:30 UTC (rev 10717)
@@ -1,8 +1,8 @@
-// script.aculo.us unittest.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
+// script.aculo.us unittest.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// (c) 2005, 2006 Jon Tirsen (http://www.tirsen.com)
-// (c) 2005, 2006 Michael Schuerig (http://www.schuerig.de/michael/)
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// (c) 2005-2007 Michael Schuerig (http://www.schuerig.de/michael/)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
@@ -524,15 +524,19 @@
shouldNotBe: 'assertReturnsFalse',
shouldRespondTo: 'assertRespondsTo'
};
- Test.BDDMethods = {};
- for(m in METHODMAP) {
- Test.BDDMethods[m] = eval(
- 'function(){'+
- 'var args = $A(arguments);'+
- 'var scope = args.shift();'+
- 'scope.'+METHODMAP[m]+'.apply(scope,(args || []).concat([this])); }');
+ var makeAssertion = function(assertion, args, object) {
+ this[assertion].apply(this,(args || []).concat([object]));
}
- [Array.prototype, String.prototype, Number.prototype].each(
+
+ Test.BDDMethods = {};
+ $H(METHODMAP).each(function(pair) {
+ Test.BDDMethods[pair.key] = function() {
+ var args = $A(arguments);
+ var scope = args.shift();
+ makeAssertion.apply(scope, [pair.value, args, this]); };
+ });
+
+ [Array.prototype, String.prototype, Number.prototype, Boolean.prototype].each(
function(p){ Object.extend(p, Test.BDDMethods) }
);
}
16 years
JBoss Portal SVN: r10716 - in branches/JBoss_Portal_Branch_2_6/theme/src/bin: theme-test-war/core/lib and 1 other directory.
by portal-commits@lists.jboss.org
Author: wesleyhales
Date: 2008-04-24 21:37:24 -0400 (Thu, 24 Apr 2008)
New Revision: 10716
Modified:
branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/builder.js
branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/controls.js
branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/dragdrop.js
branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/effects.js
branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/prototype.js
branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/scriptaculous.js
branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/slider.js
branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/unittest.js
branches/JBoss_Portal_Branch_2_6/theme/src/bin/theme-test-war/core/lib/prototype.js
Log:
upgrade prototype and scriptaculous
Modified: branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/builder.js
===================================================================
--- branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/builder.js 2008-04-25 00:34:57 UTC (rev 10715)
+++ branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/builder.js 2008-04-25 01:37:24 UTC (rev 10716)
@@ -1,6 +1,6 @@
-// script.aculo.us builder.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
+// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
@@ -48,7 +48,8 @@
// attributes (or text)
if(arguments[1])
if(this._isStringOrNumber(arguments[1]) ||
- (arguments[1] instanceof Array)) {
+ (arguments[1] instanceof Array) ||
+ arguments[1].tagName) {
this._children(element, arguments[1]);
} else {
var attrs = this._attributes(arguments[1]);
@@ -66,7 +67,7 @@
}
if(element.tagName.toUpperCase() != elementName)
element = parentElement.getElementsByTagName(elementName)[0];
- }
+ }
}
// text, or array of children
@@ -88,10 +89,14 @@
var attrs = [];
for(attribute in attributes)
attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
- '="' + attributes[attribute].toString().escapeHTML() + '"');
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'"') + '"');
return attrs.join(" ");
},
_children: function(element, children) {
+ if(children.tagName) {
+ element.appendChild(children);
+ return;
+ }
if(typeof children=='object') { // array can hold nodes and text
children.flatten().each( function(e) {
if(typeof e=='object')
@@ -101,8 +106,8 @@
element.appendChild(Builder._text(e));
});
} else
- if(Builder._isStringOrNumber(children))
- element.appendChild(Builder._text(children));
+ if(Builder._isStringOrNumber(children))
+ element.appendChild(Builder._text(children));
},
_isStringOrNumber: function(param) {
return(typeof param=='string' || typeof param=='number');
Modified: branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/controls.js
===================================================================
--- branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/controls.js 2008-04-25 00:34:57 UTC (rev 10715)
+++ branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/controls.js 2008-04-25 01:37:24 UTC (rev 10716)
@@ -1,8 +1,8 @@
-// script.aculo.us controls.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
+// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// (c) 2005, 2006 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
-// (c) 2005, 2006 Jon Tirsen (http://www.tirsen.com)
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
// Contributors:
// Richard Livsey
// Rahul Bhargava
@@ -39,22 +39,23 @@
if(typeof Effect == 'undefined')
throw("controls.js requires including script.aculo.us' effects.js library");
-var Autocompleter = {}
-Autocompleter.Base = function() {};
-Autocompleter.Base.prototype = {
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
baseInitialize: function(element, update, options) {
- this.element = $(element);
+ element = $(element)
+ this.element = element;
this.update = $(update);
this.hasFocus = false;
this.changed = false;
this.active = false;
this.index = 0;
this.entryCount = 0;
+ this.oldElementValue = this.element.value;
if(this.setOptions)
this.setOptions(options);
else
- this.options = options || {};
+ this.options = options || { };
this.options.paramName = this.options.paramName || this.element.name;
this.options.tokens = this.options.tokens || [];
@@ -76,6 +77,9 @@
if(typeof(this.options.tokens) == 'string')
this.options.tokens = new Array(this.options.tokens);
+ // Force carriage returns as token delimiters anyway
+ if (!this.options.tokens.include('\n'))
+ this.options.tokens.push('\n');
this.observer = null;
@@ -83,15 +87,14 @@
Element.hide(this.update);
- Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
- Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
},
show: function() {
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
if(!this.iefix &&
- (navigator.appVersion.indexOf('MSIE')>0) &&
- (navigator.userAgent.indexOf('Opera')<0) &&
+ (Prototype.Browser.IE) &&
(Element.getStyle(this.update, 'position')=='absolute')) {
new Insertion.After(this.update,
'<iframe id="' + this.update.id + '_iefix" '+
@@ -141,17 +144,17 @@
case Event.KEY_UP:
this.markPrevious();
this.render();
- if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
+ Event.stop(event);
return;
case Event.KEY_DOWN:
this.markNext();
this.render();
- if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
+ Event.stop(event);
return;
}
else
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
- (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return;
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
this.changed = true;
this.hasFocus = true;
@@ -197,7 +200,6 @@
this.index==i ?
Element.addClassName(this.getEntry(i),"selected") :
Element.removeClassName(this.getEntry(i),"selected");
-
if(this.hasFocus) {
this.show();
this.active = true;
@@ -240,21 +242,22 @@
}
var value = '';
if (this.options.select) {
- var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
} else
value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
- var lastTokenPos = this.findLastToken();
- if (lastTokenPos != -1) {
- var newValue = this.element.value.substr(0, lastTokenPos + 1);
- var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
+ var bounds = this.getTokenBounds();
+ if (bounds[0] != -1) {
+ var newValue = this.element.value.substr(0, bounds[0]);
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
if (whitespace)
newValue += whitespace[0];
- this.element.value = newValue + value;
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
} else {
this.element.value = value;
}
+ this.oldElementValue = this.element.value;
this.element.focus();
if (this.options.afterUpdateElement)
@@ -298,39 +301,48 @@
onObserverEvent: function() {
this.changed = false;
+ this.tokenBounds = null;
if(this.getToken().length>=this.options.minChars) {
- this.startIndicator();
this.getUpdatedChoices();
} else {
this.active = false;
this.hide();
}
+ this.oldElementValue = this.element.value;
},
getToken: function() {
- var tokenPos = this.findLastToken();
- if (tokenPos != -1)
- var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
- else
- var ret = this.element.value;
-
- return /\n/.test(ret) ? '' : ret;
+ var bounds = this.getTokenBounds();
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
},
- findLastToken: function() {
- var lastTokenPos = -1;
-
- for (var i=0; i<this.options.tokens.length; i++) {
- var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
- if (thisTokenPos > lastTokenPos)
- lastTokenPos = thisTokenPos;
+ getTokenBounds: function() {
+ if (null != this.tokenBounds) return this.tokenBounds;
+ var value = this.element.value;
+ if (value.strip().empty()) return [-1, 0];
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
+ var prevTokenPos = -1, nextTokenPos = value.length;
+ var tp;
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+ if (tp > prevTokenPos) prevTokenPos = tp;
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
}
- return lastTokenPos;
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
}
-}
+});
-Ajax.Autocompleter = Class.create();
-Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+ var boundary = Math.min(newS.length, oldS.length);
+ for (var index = 0; index < boundary; ++index)
+ if (newS[index] != oldS[index])
+ return index;
+ return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
initialize: function(element, update, url, options) {
this.baseInitialize(element, update, options);
this.options.asynchronous = true;
@@ -340,7 +352,9 @@
},
getUpdatedChoices: function() {
- entry = encodeURIComponent(this.options.paramName) + '=' +
+ this.startIndicator();
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
encodeURIComponent(this.getToken());
this.options.parameters = this.options.callback ?
@@ -348,14 +362,13 @@
if(this.options.defaultParams)
this.options.parameters += '&' + this.options.defaultParams;
-
+
new Ajax.Request(this.url, this.options);
},
onComplete: function(request) {
this.updateChoices(request.responseText);
}
-
});
// The local array autocompleter. Used when you'd prefer to
@@ -393,8 +406,7 @@
// In that case, the other options above will not apply unless
// you support them.
-Autocompleter.Local = Class.create();
-Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
+Autocompleter.Local = Class.create(Autocompleter.Base, {
initialize: function(element, update, array, options) {
this.baseInitialize(element, update, options);
this.options.array = array;
@@ -450,13 +462,12 @@
ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
return "<ul>" + ret.join('') + "</ul>";
}
- }, options || {});
+ }, options || { });
}
});
-// AJAX in-place editor
-//
-// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd(a)tddsworld.com> (April 2007).
// Use this if you notice weird scrolling problems on some browsers,
// the DOM might be a bit confused when this gets called so do this
@@ -467,353 +478,472 @@
}, 1);
}
-Ajax.InPlaceEditor = Class.create();
-Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
-Ajax.InPlaceEditor.prototype = {
+Ajax.InPlaceEditor = Class.create({
initialize: function(element, url, options) {
this.url = url;
- this.element = $(element);
-
- this.options = Object.extend({
- paramName: "value",
- okButton: true,
- okText: "ok",
- cancelLink: true,
- cancelText: "cancel",
- savingText: "Saving...",
- clickToEditText: "Click to edit",
- okText: "ok",
- rows: 1,
- onComplete: function(transport, element) {
- new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
- },
- onFailure: function(transport) {
- alert("Error communicating with the server: " + transport.responseText.stripTags());
- },
- callback: function(form) {
- return Form.serialize(form);
- },
- handleLineBreaks: true,
- loadingText: 'Loading...',
- savingClassName: 'inplaceeditor-saving',
- loadingClassName: 'inplaceeditor-loading',
- formClassName: 'inplaceeditor-form',
- highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
- highlightendcolor: "#FFFFFF",
- externalControl: null,
- submitOnBlur: false,
- ajaxOptions: {},
- evalScripts: false
- }, options || {});
-
- if(!this.options.formId && this.element.id) {
- this.options.formId = this.element.id + "-inplaceeditor";
- if ($(this.options.formId)) {
- // there's already a form with that name, don't specify an id
- this.options.formId = null;
- }
+ this.element = element = $(element);
+ this.prepareOptions();
+ this._controls = { };
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+ Object.extend(this.options, options || { });
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if ($(this.options.formId))
+ this.options.formId = '';
}
-
- if (this.options.externalControl) {
+ if (this.options.externalControl)
this.options.externalControl = $(this.options.externalControl);
- }
-
- this.originalBackground = Element.getStyle(this.element, 'background-color');
- if (!this.originalBackground) {
- this.originalBackground = "transparent";
- }
-
+ if (!this.options.externalControl)
+ this.options.externalControlOnly = false;
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
this.element.title = this.options.clickToEditText;
-
- this.onclickListener = this.enterEditMode.bindAsEventListener(this);
- this.mouseoverListener = this.enterHover.bindAsEventListener(this);
- this.mouseoutListener = this.leaveHover.bindAsEventListener(this);
- Event.observe(this.element, 'click', this.onclickListener);
- Event.observe(this.element, 'mouseover', this.mouseoverListener);
- Event.observe(this.element, 'mouseout', this.mouseoutListener);
- if (this.options.externalControl) {
- Event.observe(this.options.externalControl, 'click', this.onclickListener);
- Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener);
- Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
- }
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+ this._boundWrapperHandler = this.wrapUp.bind(this);
+ this.registerListeners();
},
- enterEditMode: function(evt) {
- if (this.saving) return;
- if (this.editing) return;
- this.editing = true;
- this.onEnterEditMode();
- if (this.options.externalControl) {
- Element.hide(this.options.externalControl);
- }
- Element.hide(this.element);
- this.createForm();
- this.element.parentNode.insertBefore(this.form, this.element);
- if (!this.options.loadTextURL) Field.scrollFreeActivate(this.editField);
- // stop the event to avoid a page refresh in Safari
- if (evt) {
- Event.stop(evt);
- }
- return false;
+ checkForEscapeOrReturn: function(e) {
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+ if (Event.KEY_ESC == e.keyCode)
+ this.handleFormCancellation(e);
+ else if (Event.KEY_RETURN == e.keyCode)
+ this.handleFormSubmission(e);
},
- createForm: function() {
- this.form = document.createElement("form");
- this.form.id = this.options.formId;
- Element.addClassName(this.form, this.options.formClassName)
- this.form.onsubmit = this.onSubmit.bind(this);
-
- this.createEditField();
-
- if (this.options.textarea) {
- var br = document.createElement("br");
- this.form.appendChild(br);
+ createControl: function(mode, handler, extraClasses) {
+ var control = this.options[mode + 'Control'];
+ var text = this.options[mode + 'Text'];
+ if ('button' == control) {
+ var btn = document.createElement('input');
+ btn.type = 'submit';
+ btn.value = text;
+ btn.className = 'editor_' + mode + '_button';
+ if ('cancel' == mode)
+ btn.onclick = this._boundCancelHandler;
+ this._form.appendChild(btn);
+ this._controls[mode] = btn;
+ } else if ('link' == control) {
+ var link = document.createElement('a');
+ link.href = '#';
+ link.appendChild(document.createTextNode(text));
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+ link.className = 'editor_' + mode + '_link';
+ if (extraClasses)
+ link.className += ' ' + extraClasses;
+ this._form.appendChild(link);
+ this._controls[mode] = link;
}
-
- if (this.options.okButton) {
- okButton = document.createElement("input");
- okButton.type = "submit";
- okButton.value = this.options.okText;
- okButton.className = 'editor_ok_button';
- this.form.appendChild(okButton);
- }
-
- if (this.options.cancelLink) {
- cancelLink = document.createElement("a");
- cancelLink.href = "#";
- cancelLink.appendChild(document.createTextNode(this.options.cancelText));
- cancelLink.onclick = this.onclickCancel.bind(this);
- cancelLink.className = 'editor_cancel';
- this.form.appendChild(cancelLink);
- }
},
- hasHTMLLineBreaks: function(string) {
- if (!this.options.handleLineBreaks) return false;
- return string.match(/<br/i) || string.match(/<p>/i);
- },
- convertHTMLLineBreaks: function(string) {
- return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, "");
- },
createEditField: function() {
- var text;
- if(this.options.loadTextURL) {
- text = this.options.loadingText;
- } else {
- text = this.getText();
- }
-
- var obj = this;
-
- if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
- this.options.textarea = false;
- var textField = document.createElement("input");
- textField.obj = this;
- textField.type = "text";
- textField.name = this.options.paramName;
- textField.value = text;
- textField.style.backgroundColor = this.options.highlightcolor;
- textField.className = 'editor_field';
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+ var fld;
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+ fld = document.createElement('input');
+ fld.type = 'text';
var size = this.options.size || this.options.cols || 0;
- if (size != 0) textField.size = size;
- if (this.options.submitOnBlur)
- textField.onblur = this.onSubmit.bind(this);
- this.editField = textField;
+ if (0 < size) fld.size = size;
} else {
- this.options.textarea = true;
- var textArea = document.createElement("textarea");
- textArea.obj = this;
- textArea.name = this.options.paramName;
- textArea.value = this.convertHTMLLineBreaks(text);
- textArea.rows = this.options.rows;
- textArea.cols = this.options.cols || 40;
- textArea.className = 'editor_field';
- if (this.options.submitOnBlur)
- textArea.onblur = this.onSubmit.bind(this);
- this.editField = textArea;
+ fld = document.createElement('textarea');
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+ fld.cols = this.options.cols || 40;
}
-
- if(this.options.loadTextURL) {
+ fld.name = this.options.paramName;
+ fld.value = text; // No HTML breaks conversion anymore
+ fld.className = 'editor_field';
+ if (this.options.submitOnBlur)
+ fld.onblur = this._boundSubmitHandler;
+ this._controls.editor = fld;
+ if (this.options.loadTextURL)
this.loadExternalText();
- }
- this.form.appendChild(this.editField);
+ this._form.appendChild(this._controls.editor);
},
- getText: function() {
- return this.element.innerHTML;
+ createForm: function() {
+ var ipe = this;
+ function addText(mode, condition) {
+ var text = ipe.options['text' + mode + 'Controls'];
+ if (!text || condition === false) return;
+ ipe._form.appendChild(document.createTextNode(text));
+ };
+ this._form = $(document.createElement('form'));
+ this._form.id = this.options.formId;
+ this._form.addClassName(this.options.formClassName);
+ this._form.onsubmit = this._boundSubmitHandler;
+ this.createEditField();
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
+ this._form.appendChild(document.createElement('br'));
+ if (this.options.onFormCustomization)
+ this.options.onFormCustomization(this, this._form);
+ addText('Before', this.options.okControl || this.options.cancelControl);
+ this.createControl('ok', this._boundSubmitHandler);
+ addText('Between', this.options.okControl && this.options.cancelControl);
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+ addText('After', this.options.okControl || this.options.cancelControl);
},
- loadExternalText: function() {
- Element.addClassName(this.form, this.options.loadingClassName);
- this.editField.disabled = true;
- new Ajax.Request(
- this.options.loadTextURL,
- Object.extend({
- asynchronous: true,
- onComplete: this.onLoadedExternalText.bind(this)
- }, this.options.ajaxOptions)
- );
+ destroy: function() {
+ if (this._oldInnerHTML)
+ this.element.innerHTML = this._oldInnerHTML;
+ this.leaveEditMode();
+ this.unregisterListeners();
},
- onLoadedExternalText: function(transport) {
- Element.removeClassName(this.form, this.options.loadingClassName);
- this.editField.disabled = false;
- this.editField.value = transport.responseText.stripTags();
- Field.scrollFreeActivate(this.editField);
+ enterEditMode: function(e) {
+ if (this._saving || this._editing) return;
+ this._editing = true;
+ this.triggerCallback('onEnterEditMode');
+ if (this.options.externalControl)
+ this.options.externalControl.hide();
+ this.element.hide();
+ this.createForm();
+ this.element.parentNode.insertBefore(this._form, this.element);
+ if (!this.options.loadTextURL)
+ this.postProcessEditField();
+ if (e) Event.stop(e);
},
- onclickCancel: function() {
- this.onComplete();
- this.leaveEditMode();
- return false;
+ enterHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.addClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onEnterHover');
},
- onFailure: function(transport) {
- this.options.onFailure(transport);
- if (this.oldInnerHTML) {
- this.element.innerHTML = this.oldInnerHTML;
- this.oldInnerHTML = null;
+ getText: function() {
+ return this.element.innerHTML;
+ },
+ handleAJAXFailure: function(transport) {
+ this.triggerCallback('onFailure', transport);
+ if (this._oldInnerHTML) {
+ this.element.innerHTML = this._oldInnerHTML;
+ this._oldInnerHTML = null;
}
- return false;
},
- onSubmit: function() {
- // onLoading resets these so we need to save them away for the Ajax call
- var form = this.form;
- var value = this.editField.value;
-
- // do this first, sometimes the ajax call returns before we get a chance to switch on Saving...
- // which means this will actually switch on Saving... *after* we've left edit mode causing Saving...
- // to be displayed indefinitely
- this.onLoading();
-
- if (this.options.evalScripts) {
- new Ajax.Request(
- this.url, Object.extend({
- parameters: this.options.callback(form, value),
- onComplete: this.onComplete.bind(this),
- onFailure: this.onFailure.bind(this),
- asynchronous:true,
- evalScripts:true
- }, this.options.ajaxOptions));
- } else {
- new Ajax.Updater(
- { success: this.element,
- // don't update on failure (this could be an option)
- failure: null },
- this.url, Object.extend({
- parameters: this.options.callback(form, value),
- onComplete: this.onComplete.bind(this),
- onFailure: this.onFailure.bind(this)
- }, this.options.ajaxOptions));
+ handleFormCancellation: function(e) {
+ this.wrapUp();
+ if (e) Event.stop(e);
+ },
+ handleFormSubmission: function(e) {
+ var form = this._form;
+ var value = $F(this._controls.editor);
+ this.prepareSubmission();
+ var params = this.options.callback(form, value) || '';
+ if (Object.isString(params))
+ params = params.toQueryParams();
+ params.editorId = this.element.id;
+ if (this.options.htmlResponse) {
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Updater({ success: this.element }, this.url, options);
+ } else {
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: params,
+ onComplete: this._boundWrapperHandler,
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.url, options);
}
- // stop the event to avoid a page refresh in Safari
- if (arguments.length > 1) {
- Event.stop(arguments[0]);
- }
- return false;
+ if (e) Event.stop(e);
},
- onLoading: function() {
- this.saving = true;
+ leaveEditMode: function() {
+ this.element.removeClassName(this.options.savingClassName);
this.removeForm();
this.leaveHover();
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
+ if (this.options.externalControl)
+ this.options.externalControl.show();
+ this._saving = false;
+ this._editing = false;
+ this._oldInnerHTML = null;
+ this.triggerCallback('onLeaveEditMode');
+ },
+ leaveHover: function(e) {
+ if (this.options.hoverClassName)
+ this.element.removeClassName(this.options.hoverClassName);
+ if (this._saving) return;
+ this.triggerCallback('onLeaveHover');
+ },
+ loadExternalText: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this._controls.editor.disabled = true;
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._form.removeClassName(this.options.loadingClassName);
+ var text = transport.responseText;
+ if (this.options.stripLoadedTextTags)
+ text = text.stripTags();
+ this._controls.editor.value = text;
+ this._controls.editor.disabled = false;
+ this.postProcessEditField();
+ }.bind(this),
+ onFailure: this._boundFailureHandler
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+ postProcessEditField: function() {
+ var fpc = this.options.fieldPostCreation;
+ if (fpc)
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+ },
+ prepareOptions: function() {
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+ Object.extend(this.options, defs);
+ }.bind(this));
+ },
+ prepareSubmission: function() {
+ this._saving = true;
+ this.removeForm();
+ this.leaveHover();
this.showSaving();
},
+ registerListeners: function() {
+ this._listeners = { };
+ var listener;
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+ listener = this[pair.value].bind(this);
+ this._listeners[pair.key] = listener;
+ if (!this.options.externalControlOnly)
+ this.element.observe(pair.key, listener);
+ if (this.options.externalControl)
+ this.options.externalControl.observe(pair.key, listener);
+ }.bind(this));
+ },
+ removeForm: function() {
+ if (!this._form) return;
+ this._form.remove();
+ this._form = null;
+ this._controls = { };
+ },
showSaving: function() {
- this.oldInnerHTML = this.element.innerHTML;
+ this._oldInnerHTML = this.element.innerHTML;
this.element.innerHTML = this.options.savingText;
- Element.addClassName(this.element, this.options.savingClassName);
- this.element.style.backgroundColor = this.originalBackground;
- Element.show(this.element);
+ this.element.addClassName(this.options.savingClassName);
+ this.element.style.backgroundColor = this._originalBackground;
+ this.element.show();
},
- removeForm: function() {
- if(this.form) {
- if (this.form.parentNode) Element.remove(this.form);
- this.form = null;
+ triggerCallback: function(cbName, arg) {
+ if ('function' == typeof this.options[cbName]) {
+ this.options[cbName](this, arg);
}
},
- enterHover: function() {
- if (this.saving) return;
- this.element.style.backgroundColor = this.options.highlightcolor;
- if (this.effect) {
- this.effect.cancel();
- }
- Element.addClassName(this.element, this.options.hoverClassName)
+ unregisterListeners: function() {
+ $H(this._listeners).each(function(pair) {
+ if (!this.options.externalControlOnly)
+ this.element.stopObserving(pair.key, pair.value);
+ if (this.options.externalControl)
+ this.options.externalControl.stopObserving(pair.key, pair.value);
+ }.bind(this));
},
- leaveHover: function() {
- if (this.options.backgroundColor) {
- this.element.style.backgroundColor = this.oldBackground;
- }
- Element.removeClassName(this.element, this.options.hoverClassName)
- if (this.saving) return;
- this.effect = new Effect.Highlight(this.element, {
- startcolor: this.options.highlightcolor,
- endcolor: this.options.highlightendcolor,
- restorecolor: this.originalBackground
+ wrapUp: function(transport) {
+ this.leaveEditMode();
+ // Can't use triggerCallback due to backward compatibility: requires
+ // binding + direct element
+ this._boundComplete(transport, this.element);
+ }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+ dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+ initialize: function($super, element, url, options) {
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+ $super(element, url, options);
+ },
+
+ createEditField: function() {
+ var list = document.createElement('select');
+ list.name = this.options.paramName;
+ list.size = 1;
+ this._controls.editor = list;
+ this._collection = this.options.collection || [];
+ if (this.options.loadCollectionURL)
+ this.loadCollection();
+ else
+ this.checkForExternalText();
+ this._form.appendChild(this._controls.editor);
+ },
+
+ loadCollection: function() {
+ this._form.addClassName(this.options.loadingClassName);
+ this.showLoadingText(this.options.loadingCollectionText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
});
+ new Ajax.Request(this.options.loadCollectionURL, options);
},
- leaveEditMode: function() {
- Element.removeClassName(this.element, this.options.savingClassName);
- this.removeForm();
- this.leaveHover();
- this.element.style.backgroundColor = this.originalBackground;
- Element.show(this.element);
- if (this.options.externalControl) {
- Element.show(this.options.externalControl);
+
+ showLoadingText: function(text) {
+ this._controls.editor.disabled = true;
+ var tempOption = this._controls.editor.firstChild;
+ if (!tempOption) {
+ tempOption = document.createElement('option');
+ tempOption.value = '';
+ this._controls.editor.appendChild(tempOption);
+ tempOption.selected = true;
}
- this.editing = false;
- this.saving = false;
- this.oldInnerHTML = null;
- this.onLeaveEditMode();
+ tempOption.update((text || '').stripScripts().stripTags());
},
- onComplete: function(transport) {
- this.leaveEditMode();
- this.options.onComplete.bind(this)(transport, this.element);
+
+ checkForExternalText: function() {
+ this._text = this.getText();
+ if (this.options.loadTextURL)
+ this.loadExternalText();
+ else
+ this.buildOptionList();
},
- onEnterEditMode: function() {},
- onLeaveEditMode: function() {},
- dispose: function() {
- if (this.oldInnerHTML) {
- this.element.innerHTML = this.oldInnerHTML;
- }
- this.leaveEditMode();
- Event.stopObserving(this.element, 'click', this.onclickListener);
- Event.stopObserving(this.element, 'mouseover', this.mouseoverListener);
- Event.stopObserving(this.element, 'mouseout', this.mouseoutListener);
- if (this.options.externalControl) {
- Event.stopObserving(this.options.externalControl, 'click', this.onclickListener);
- Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener);
- Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener);
- }
+
+ loadExternalText: function() {
+ this.showLoadingText(this.options.loadingText);
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+ Object.extend(options, {
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
+ onComplete: Prototype.emptyFunction,
+ onSuccess: function(transport) {
+ this._text = transport.responseText.strip();
+ this.buildOptionList();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ new Ajax.Request(this.options.loadTextURL, options);
+ },
+
+ buildOptionList: function() {
+ this._form.removeClassName(this.options.loadingClassName);
+ this._collection = this._collection.map(function(entry) {
+ return 2 === entry.length ? entry : [entry, entry].flatten();
+ });
+ var marker = ('value' in this.options) ? this.options.value : this._text;
+ var textFound = this._collection.any(function(entry) {
+ return entry[0] == marker;
+ }.bind(this));
+ this._controls.editor.update('');
+ var option;
+ this._collection.each(function(entry, index) {
+ option = document.createElement('option');
+ option.value = entry[0];
+ option.selected = textFound ? entry[0] == marker : 0 == index;
+ option.appendChild(document.createTextNode(entry[1]));
+ this._controls.editor.appendChild(option);
+ }.bind(this));
+ this._controls.editor.disabled = false;
+ Field.scrollFreeActivate(this._controls.editor);
}
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only exists for a while, in order to let ****
+//**** users adapt to the new API. Read up on the new ****
+//**** API and convert your code to it ASAP! ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+ if (!options) return;
+ function fallback(name, expr) {
+ if (name in options || expr === undefined) return;
+ options[name] = expr;
+ };
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+ options.okLink == options.okButton == false ? false : undefined)));
+ fallback('highlightColor', options.highlightcolor);
+ fallback('highlightEndColor', options.highlightendcolor);
};
-Ajax.InPlaceCollectionEditor = Class.create();
-Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype);
-Object.extend(Ajax.InPlaceCollectionEditor.prototype, {
- createEditField: function() {
- if (!this.cached_selectTag) {
- var selectTag = document.createElement("select");
- var collection = this.options.collection || [];
- var optionTag;
- collection.each(function(e,i) {
- optionTag = document.createElement("option");
- optionTag.value = (e instanceof Array) ? e[0] : e;
- if((typeof this.options.value == 'undefined') &&
- ((e instanceof Array) ? this.element.innerHTML == e[1] : e == optionTag.value)) optionTag.selected = true;
- if(this.options.value==optionTag.value) optionTag.selected = true;
- optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e));
- selectTag.appendChild(optionTag);
- }.bind(this));
- this.cached_selectTag = selectTag;
+Object.extend(Ajax.InPlaceEditor, {
+ DefaultOptions: {
+ ajaxOptions: { },
+ autoRows: 3, // Use when multi-line w/ rows == 1
+ cancelControl: 'link', // 'link'|'button'|false
+ cancelText: 'cancel',
+ clickToEditText: 'Click to edit',
+ externalControl: null, // id|elt
+ externalControlOnly: false,
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
+ formClassName: 'inplaceeditor-form',
+ formId: null, // id|elt
+ highlightColor: '#ffff99',
+ highlightEndColor: '#ffffff',
+ hoverClassName: '',
+ htmlResponse: true,
+ loadingClassName: 'inplaceeditor-loading',
+ loadingText: 'Loading...',
+ okControl: 'button', // 'link'|'button'|false
+ okText: 'ok',
+ paramName: 'value',
+ rows: 1, // If 1 and multi-line, uses autoRows
+ savingClassName: 'inplaceeditor-saving',
+ savingText: 'Saving...',
+ size: 0,
+ stripLoadedTextTags: false,
+ submitOnBlur: false,
+ textAfterControls: '',
+ textBeforeControls: '',
+ textBetweenControls: ''
+ },
+ DefaultCallbacks: {
+ callback: function(form) {
+ return Form.serialize(form);
+ },
+ onComplete: function(transport, element) {
+ // For backward compatibility, this one is bound to the IPE, and passes
+ // the element directly. It was too often customized, so we don't break it.
+ new Effect.Highlight(element, {
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
+ },
+ onEnterEditMode: null,
+ onEnterHover: function(ipe) {
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
+ if (ipe._effect)
+ ipe._effect.cancel();
+ },
+ onFailure: function(transport, ipe) {
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
+ },
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+ onLeaveEditMode: null,
+ onLeaveHover: function(ipe) {
+ ipe._effect = new Effect.Highlight(ipe.element, {
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
+ });
}
-
- this.editField = this.cached_selectTag;
- if(this.options.loadTextURL) this.loadExternalText();
- this.form.appendChild(this.editField);
- this.options.callback = function(form, value) {
- return "value=" + encodeURIComponent(value);
- }
+ },
+ Listeners: {
+ click: 'enterEditMode',
+ keydown: 'checkForEscapeOrReturn',
+ mouseover: 'enterHover',
+ mouseout: 'leaveHover'
}
});
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+ loadingCollectionText: 'Loading options...'
+};
+
// Delayed observer, like Form.Element.Observer,
// but waits for delay after last key input
// Ideal for live-search fields
-Form.Element.DelayedObserver = Class.create();
-Form.Element.DelayedObserver.prototype = {
+Form.Element.DelayedObserver = Class.create({
initialize: function(element, delay, callback) {
this.delay = delay || 0.5;
this.element = $(element);
@@ -832,4 +962,4 @@
this.timer = null;
this.callback(this.element, $F(this.element));
}
-};
+});
Modified: branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/dragdrop.js
===================================================================
--- branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/dragdrop.js 2008-04-25 00:34:57 UTC (rev 10715)
+++ branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/dragdrop.js 2008-04-25 01:37:24 UTC (rev 10716)
@@ -1,12 +1,12 @@
-// script.aculo.us dragdrop.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
+// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// (c) 2005, 2006 Sammi Williams (http://www.oriontransfer.co.nz, sammi(a)oriontransfer.co.nz)
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi(a)oriontransfer.co.nz)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
-if(typeof Effect == 'undefined')
+if(Object.isUndefined(Effect))
throw("dragdrop.js requires including script.aculo.us' effects.js library");
var Droppables = {
@@ -22,14 +22,13 @@
greedy: true,
hoverclass: null,
tree: false
- }, arguments[1] || {});
+ }, arguments[1] || { });
// cache containers
if(options.containment) {
options._containers = [];
var containment = options.containment;
- if((typeof containment == 'object') &&
- (containment.constructor == Array)) {
+ if(Object.isArray(containment)) {
containment.each( function(c) { options._containers.push($(c)) });
} else {
options._containers.push($(containment));
@@ -89,21 +88,23 @@
show: function(point, element) {
if(!this.drops.length) return;
- var affected = [];
+ var drop, affected = [];
- if(this.last_active) this.deactivate(this.last_active);
this.drops.each( function(drop) {
if(Droppables.isAffected(point, element, drop))
affected.push(drop);
});
- if(affected.length>0) {
+ if(affected.length>0)
drop = Droppables.findDeepestChild(affected);
+
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+ if (drop) {
Position.within(drop.element, point[0], point[1]);
if(drop.onHover)
drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
- Droppables.activate(drop);
+ if (drop != this.last_active) Droppables.activate(drop);
}
},
@@ -112,8 +113,10 @@
Position.prepare();
if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
- if (this.last_active.onDrop)
- this.last_active.onDrop(element, this.last_active.element, event);
+ if (this.last_active.onDrop) {
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
+ }
},
reset: function() {
@@ -221,10 +224,7 @@
/*--------------------------------------------------------------------------*/
-var Draggable = Class.create();
-Draggable._dragging = {};
-
-Draggable.prototype = {
+var Draggable = Class.create({
initialize: function(element) {
var defaults = {
handle: false,
@@ -235,7 +235,7 @@
});
},
endeffect: function(element) {
- var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0;
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
queue: {scope:'_draggable', position:'end'},
afterFinish: function(){
@@ -245,6 +245,7 @@
},
zindex: 1000,
revert: false,
+ quiet: false,
scroll: false,
scrollSensitivity: 20,
scrollSpeed: 15,
@@ -252,7 +253,7 @@
delay: 0
};
- if(!arguments[1] || typeof arguments[1].endeffect == 'undefined')
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
Object.extend(defaults, {
starteffect: function(element) {
element._opacity = Element.getOpacity(element);
@@ -261,11 +262,11 @@
}
});
- var options = Object.extend(defaults, arguments[1] || {});
+ var options = Object.extend(defaults, arguments[1] || { });
this.element = $(element);
- if(options.handle && (typeof options.handle == 'string'))
+ if(options.handle && Object.isString(options.handle))
this.handle = this.element.down('.'+options.handle, 0);
if(!this.handle) this.handle = $(options.handle);
@@ -278,7 +279,6 @@
Element.makePositioned(this.element); // fix IE
- this.delta = this.currentDelta();
this.options = options;
this.dragging = false;
@@ -300,7 +300,7 @@
},
initDrag: function(event) {
- if(typeof Draggable._dragging[this.element] != 'undefined' &&
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
Draggable._dragging[this.element]) return;
if(Event.isLeftClick(event)) {
// abort on form elements, fixes a Firefox issue
@@ -323,6 +323,8 @@
startDrag: function(event) {
this.dragging = true;
+ if(!this.delta)
+ this.delta = this.currentDelta();
if(this.options.zindex) {
this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
@@ -331,7 +333,9 @@
if(this.options.ghosting) {
this._clone = this.element.cloneNode(true);
- Position.absolutize(this.element);
+ this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this.element._originallyAbsolute)
+ Position.absolutize(this.element);
this.element.parentNode.insertBefore(this._clone, this.element);
}
@@ -353,8 +357,12 @@
updateDrag: function(event, pointer) {
if(!this.dragging) this.startDrag(event);
- Position.prepare();
- Droppables.show(pointer, this.element);
+
+ if(!this.options.quiet){
+ Position.prepare();
+ Droppables.show(pointer, this.element);
+ }
+
Draggables.notify('onDrag', this, event);
this.draw(pointer);
@@ -382,30 +390,44 @@
}
// fix AppleWebKit rendering
- if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
Event.stop(event);
},
finishDrag: function(event, success) {
this.dragging = false;
+
+ if(this.options.quiet){
+ Position.prepare();
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
+ Droppables.show(pointer, this.element);
+ }
if(this.options.ghosting) {
- Position.relativize(this.element);
+ if (!this.element._originallyAbsolute)
+ Position.relativize(this.element);
+ delete this.element._originallyAbsolute;
Element.remove(this._clone);
this._clone = null;
}
- if(success) Droppables.fire(event, this.element);
+ var dropped = false;
+ if(success) {
+ dropped = Droppables.fire(event, this.element);
+ if (!dropped) dropped = false;
+ }
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
Draggables.notify('onEnd', this, event);
var revert = this.options.revert;
- if(revert && typeof revert == 'function') revert = revert(this.element);
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
var d = this.currentDelta();
if(revert && this.options.reverteffect) {
- this.options.reverteffect(this.element,
- d[1]-this.delta[1], d[0]-this.delta[0]);
+ if (dropped == 0 || revert != 'failure')
+ this.options.reverteffect(this.element,
+ d[1]-this.delta[1], d[0]-this.delta[0]);
} else {
this.delta = d;
}
@@ -453,15 +475,15 @@
}.bind(this));
if(this.options.snap) {
- if(typeof this.options.snap == 'function') {
+ if(Object.isFunction(this.options.snap)) {
p = this.options.snap(p[0],p[1],this);
} else {
- if(this.options.snap instanceof Array) {
+ if(Object.isArray(this.options.snap)) {
p = p.map( function(v, i) {
- return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this))
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
} else {
p = p.map( function(v) {
- return Math.round(v/this.options.snap)*this.options.snap }.bind(this))
+ return (v/this.options.snap).round()*this.options.snap }.bind(this))
}
}}
@@ -545,12 +567,13 @@
}
return { top: T, left: L, width: W, height: H };
}
-}
+});
+Draggable._dragging = { };
+
/*--------------------------------------------------------------------------*/
-var SortableObserver = Class.create();
-SortableObserver.prototype = {
+var SortableObserver = Class.create({
initialize: function(element, observer) {
this.element = $(element);
this.observer = observer;
@@ -566,12 +589,12 @@
if(this.lastValue != Sortable.serialize(this.element))
this.observer(this.element)
}
-}
+});
var Sortable = {
SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
- sortables: {},
+ sortables: { },
_findRootElement: function(element) {
while (element.tagName.toUpperCase() != "BODY") {
@@ -614,13 +637,20 @@
delay: 0,
hoverclass: null,
ghosting: false,
+ quiet: false,
scroll: false,
scrollSensitivity: 20,
scrollSpeed: 15,
format: this.SERIALIZE_RULE,
+
+ // these take arrays of elements or ids and can be
+ // used for better initialization performance
+ elements: false,
+ handles: false,
+
onChange: Prototype.emptyFunction,
onUpdate: Prototype.emptyFunction
- }, arguments[1] || {});
+ }, arguments[1] || { });
// clear any old sortable with same element
this.destroy(element);
@@ -628,6 +658,7 @@
// build options for the draggables
var options_for_draggable = {
revert: true,
+ quiet: options.quiet,
scroll: options.scroll,
scrollSpeed: options.scrollSpeed,
scrollSensitivity: options.scrollSensitivity,
@@ -681,10 +712,9 @@
options.droppables.push(element);
}
- (this.findElements(element, options) || []).each( function(e) {
- // handles are per-draggable
- var handle = options.handle ?
- $(e).down('.'+options.handle,0) : e;
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+ var handle = options.handles ? $(options.handles[i]) :
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
options.draggables.push(
new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
Droppables.add(e, options_for_droppable);
@@ -844,7 +874,7 @@
only: sortableOptions.only,
name: element.id,
format: sortableOptions.format
- }, arguments[1] || {});
+ }, arguments[1] || { });
var root = {
id: null,
@@ -868,7 +898,7 @@
sequence: function(element) {
element = $(element);
- var options = Object.extend(this.options(element), arguments[1] || {});
+ var options = Object.extend(this.options(element), arguments[1] || { });
return $(this.findElements(element, options) || []).map( function(item) {
return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
@@ -877,9 +907,9 @@
setSequence: function(element, new_sequence) {
element = $(element);
- var options = Object.extend(this.options(element), arguments[2] || {});
+ var options = Object.extend(this.options(element), arguments[2] || { });
- var nodeMap = {};
+ var nodeMap = { };
this.findElements(element, options).each( function(n) {
if (n.id.match(options.format))
nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
@@ -897,7 +927,7 @@
serialize: function(element) {
element = $(element);
- var options = Object.extend(Sortable.options(element), arguments[1] || {});
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
var name = encodeURIComponent(
(arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
@@ -921,7 +951,7 @@
return Element.isParent(child.parentNode, element);
}
-Element.findChildren = function(element, only, recursive, tagName) {
+Element.findChildren = function(element, only, recursive, tagName) {
if(!element.hasChildNodes()) return null;
tagName = tagName.toUpperCase();
if(only) only = [only].flatten();
Modified: branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/effects.js
===================================================================
--- branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/effects.js 2008-04-25 00:34:57 UTC (rev 10715)
+++ branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/effects.js 2008-04-25 01:37:24 UTC (rev 10716)
@@ -1,6 +1,6 @@
-// script.aculo.us effects.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
+// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
// Justin Palmer (http://encytemedia.com/)
// Mark Pilgrim (http://diveintomark.org/)
@@ -13,17 +13,17 @@
// returns self (or first argument) if not convertable
String.prototype.parseColor = function() {
var color = '#';
- if(this.slice(0,4) == 'rgb(') {
+ if (this.slice(0,4) == 'rgb(') {
var cols = this.slice(4,this.length-1).split(',');
var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
} else {
- if(this.slice(0,1) == '#') {
- if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
- if(this.length==7) color = this.toLowerCase();
+ if (this.slice(0,1) == '#') {
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
+ if (this.length==7) color = this.toLowerCase();
}
}
- return(color.length==7 ? color : (arguments[0] || this));
-}
+ return (color.length==7 ? color : (arguments[0] || this));
+};
/*--------------------------------------------------------------------------*/
@@ -32,7 +32,7 @@
return (node.nodeType==3 ? node.nodeValue :
(node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
}).flatten().join('');
-}
+};
Element.collectTextNodesIgnoreClass = function(element, className) {
return $A($(element).childNodes).collect( function(node) {
@@ -40,26 +40,18 @@
((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
Element.collectTextNodesIgnoreClass(node, className) : ''));
}).flatten().join('');
-}
+};
Element.setContentZoom = function(element, percent) {
element = $(element);
element.setStyle({fontSize: (percent/100) + 'em'});
- if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
return element;
-}
+};
-Element.getOpacity = function(element){
- return $(element).getStyle('opacity');
-}
-
-Element.setOpacity = function(element, value){
- return $(element).setStyle({opacity:value});
-}
-
Element.getInlineOpacity = function(element){
return $(element).style.opacity || '';
-}
+};
Element.forceRerendering = function(element) {
try {
@@ -72,31 +64,63 @@
/*--------------------------------------------------------------------------*/
-Array.prototype.call = function() {
- var args = arguments;
- this.each(function(f){ f.apply(this, args) });
-}
-
-/*--------------------------------------------------------------------------*/
-
var Effect = {
_elementDoesNotExistError: {
name: 'ElementDoesNotExistError',
message: 'The specified DOM element does not exist, but is required for this effect to operate'
},
+ Transitions: {
+ linear: Prototype.K,
+ sinoidal: function(pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ },
+ reverse: function(pos) {
+ return 1-pos;
+ },
+ flicker: function(pos) {
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ return pos > 1 ? 1 : pos;
+ },
+ wobble: function(pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ },
+ pulse: function(pos, pulses) {
+ pulses = pulses || 5;
+ return (
+ ((pos % (1/pulses)) * pulses).round() == 0 ?
+ ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
+ 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+ );
+ },
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ },
+ none: function(pos) {
+ return 0;
+ },
+ full: function(pos) {
+ return 1;
+ }
+ },
+ DefaultOptions: {
+ duration: 1.0, // seconds
+ fps: 100, // 100= assume 66fps max.
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+ },
tagifyText: function(element) {
- if(typeof Builder == 'undefined')
- throw("Effect.tagifyText requires including script.aculo.us' builder.js library");
-
var tagifyStyle = 'position:relative';
- if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';zoom:1';
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
element = $(element);
$A(element.childNodes).each( function(child) {
- if(child.nodeType==3) {
+ if (child.nodeType==3) {
child.nodeValue.toArray().each( function(character) {
element.insertBefore(
- Builder.node('span',{style: tagifyStyle},
+ new Element('span', {style: tagifyStyle}).update(
character == ' ' ? String.fromCharCode(160) : character),
child);
});
@@ -106,8 +130,8 @@
},
multiple: function(element, effect) {
var elements;
- if(((typeof element == 'object') ||
- (typeof element == 'function')) &&
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
(element.length))
elements = element;
else
@@ -116,7 +140,7 @@
var options = Object.extend({
speed: 0.1,
delay: 0.0
- }, arguments[2] || {});
+ }, arguments[2] || { });
var masterDelay = options.delay;
$A(elements).each( function(element, index) {
@@ -133,53 +157,20 @@
effect = (effect || 'appear').toLowerCase();
var options = Object.extend({
queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
- }, arguments[2] || {});
+ }, arguments[2] || { });
Effect[element.visible() ?
Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
}
};
-var Effect2 = Effect; // deprecated
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
-/* ------------- transitions ------------- */
-
-Effect.Transitions = {
- linear: Prototype.K,
- sinoidal: function(pos) {
- return (-Math.cos(pos*Math.PI)/2) + 0.5;
- },
- reverse: function(pos) {
- return 1-pos;
- },
- flicker: function(pos) {
- return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
- },
- wobble: function(pos) {
- return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
- },
- pulse: function(pos, pulses) {
- pulses = pulses || 5;
- return (
- Math.round((pos % (1/pulses)) * pulses) == 0 ?
- ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) :
- 1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2))
- );
- },
- none: function(pos) {
- return 0;
- },
- full: function(pos) {
- return 1;
- }
-};
-
/* ------------- core effects ------------- */
-Effect.ScopedQueue = Class.create();
-Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
+Effect.ScopedQueue = Class.create(Enumerable, {
initialize: function() {
this.effects = [];
- this.interval = null;
+ this.interval = null;
},
_each: function(iterator) {
this.effects._each(iterator);
@@ -187,7 +178,7 @@
add: function(effect) {
var timestamp = new Date().getTime();
- var position = (typeof effect.options.queue == 'string') ?
+ var position = Object.isString(effect.options.queue) ?
effect.options.queue : effect.options.queue.position;
switch(position) {
@@ -210,15 +201,15 @@
effect.startOn += timestamp;
effect.finishOn += timestamp;
- if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
this.effects.push(effect);
- if(!this.interval)
+ if (!this.interval)
this.interval = setInterval(this.loop.bind(this), 15);
},
remove: function(effect) {
this.effects = this.effects.reject(function(e) { return e==effect });
- if(this.effects.length == 0) {
+ if (this.effects.length == 0) {
clearInterval(this.interval);
this.interval = null;
}
@@ -226,103 +217,95 @@
loop: function() {
var timePos = new Date().getTime();
for(var i=0, len=this.effects.length;i<len;i++)
- if(this.effects[i]) this.effects[i].loop(timePos);
+ this.effects[i] && this.effects[i].loop(timePos);
}
});
Effect.Queues = {
instances: $H(),
get: function(queueName) {
- if(typeof queueName != 'string') return queueName;
+ if (!Object.isString(queueName)) return queueName;
- if(!this.instances[queueName])
- this.instances[queueName] = new Effect.ScopedQueue();
-
- return this.instances[queueName];
+ return this.instances.get(queueName) ||
+ this.instances.set(queueName, new Effect.ScopedQueue());
}
-}
+};
Effect.Queue = Effect.Queues.get('global');
-Effect.DefaultOptions = {
- transition: Effect.Transitions.sinoidal,
- duration: 1.0, // seconds
- fps: 60.0, // max. 60fps due to Effect.Queue implementation
- sync: false, // true for combining
- from: 0.0,
- to: 1.0,
- delay: 0.0,
- queue: 'parallel'
-}
-
-Effect.Base = function() {};
-Effect.Base.prototype = {
+Effect.Base = Class.create({
position: null,
start: function(options) {
- this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
+ function codeForEvent(options,eventName){
+ return (
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+ );
+ }
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
this.currentFrame = 0;
this.state = 'idle';
this.startOn = this.options.delay*1000;
- this.finishOn = this.startOn + (this.options.duration*1000);
+ this.finishOn = this.startOn+(this.options.duration*1000);
+ this.fromToDelta = this.options.to-this.options.from;
+ this.totalTime = this.finishOn-this.startOn;
+ this.totalFrames = this.options.fps*this.options.duration;
+
+ eval('this.render = function(pos){ '+
+ 'if (this.state=="idle"){this.state="running";'+
+ codeForEvent(this.options,'beforeSetup')+
+ (this.setup ? 'this.setup();':'')+
+ codeForEvent(this.options,'afterSetup')+
+ '};if (this.state=="running"){'+
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+ 'this.position=pos;'+
+ codeForEvent(this.options,'beforeUpdate')+
+ (this.update ? 'this.update(pos);':'')+
+ codeForEvent(this.options,'afterUpdate')+
+ '}}');
+
this.event('beforeStart');
- if(!this.options.sync)
- Effect.Queues.get(typeof this.options.queue == 'string' ?
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
'global' : this.options.queue.scope).add(this);
},
loop: function(timePos) {
- if(timePos >= this.startOn) {
- if(timePos >= this.finishOn) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
this.render(1.0);
this.cancel();
this.event('beforeFinish');
- if(this.finish) this.finish();
+ if (this.finish) this.finish();
this.event('afterFinish');
return;
}
- var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
- var frame = Math.round(pos * this.options.fps * this.options.duration);
- if(frame > this.currentFrame) {
+ var pos = (timePos - this.startOn) / this.totalTime,
+ frame = (pos * this.totalFrames).round();
+ if (frame > this.currentFrame) {
this.render(pos);
this.currentFrame = frame;
}
}
},
- render: function(pos) {
- if(this.state == 'idle') {
- this.state = 'running';
- this.event('beforeSetup');
- if(this.setup) this.setup();
- this.event('afterSetup');
- }
- if(this.state == 'running') {
- if(this.options.transition) pos = this.options.transition(pos);
- pos *= (this.options.to-this.options.from);
- pos += this.options.from;
- this.position = pos;
- this.event('beforeUpdate');
- if(this.update) this.update(pos);
- this.event('afterUpdate');
- }
- },
cancel: function() {
- if(!this.options.sync)
- Effect.Queues.get(typeof this.options.queue == 'string' ?
+ if (!this.options.sync)
+ Effect.Queues.get(Object.isString(this.options.queue) ?
'global' : this.options.queue.scope).remove(this);
this.state = 'finished';
},
event: function(eventName) {
- if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
- if(this.options[eventName]) this.options[eventName](this);
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+ if (this.options[eventName]) this.options[eventName](this);
},
inspect: function() {
var data = $H();
for(property in this)
- if(typeof this[property] != 'function') data[property] = this[property];
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
}
-}
+});
-Effect.Parallel = Class.create();
-Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
+Effect.Parallel = Class.create(Effect.Base, {
initialize: function(effects) {
this.effects = effects || [];
this.start(arguments[1]);
@@ -335,35 +318,45 @@
effect.render(1.0);
effect.cancel();
effect.event('beforeFinish');
- if(effect.finish) effect.finish(position);
+ if (effect.finish) effect.finish(position);
effect.event('afterFinish');
});
}
});
-Effect.Event = Class.create();
-Object.extend(Object.extend(Effect.Event.prototype, Effect.Base.prototype), {
+Effect.Tween = Class.create(Effect.Base, {
+ initialize: function(object, from, to) {
+ object = Object.isString(object) ? $(object) : object;
+ var args = $A(arguments), method = args.last(),
+ options = args.length == 5 ? args[3] : null;
+ this.method = Object.isFunction(method) ? method.bind(object) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
+ function(value) { object[method] = value };
+ this.start(Object.extend({ from: from, to: to }, options || { }));
+ },
+ update: function(position) {
+ this.method(position);
+ }
+});
+
+Effect.Event = Class.create(Effect.Base, {
initialize: function() {
- var options = Object.extend({
- duration: 0
- }, arguments[0] || {});
- this.start(options);
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
},
update: Prototype.emptyFunction
});
-Effect.Opacity = Class.create();
-Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
+Effect.Opacity = Class.create(Effect.Base, {
initialize: function(element) {
this.element = $(element);
- if(!this.element) throw(Effect._elementDoesNotExistError);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
// make this work on IE on elements without 'layout'
- if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout))
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
this.element.setStyle({zoom: 1});
var options = Object.extend({
from: this.element.getOpacity() || 0.0,
to: 1.0
- }, arguments[1] || {});
+ }, arguments[1] || { });
this.start(options);
},
update: function(position) {
@@ -371,36 +364,30 @@
}
});
-Effect.Move = Class.create();
-Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
+Effect.Move = Class.create(Effect.Base, {
initialize: function(element) {
this.element = $(element);
- if(!this.element) throw(Effect._elementDoesNotExistError);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
x: 0,
y: 0,
mode: 'relative'
- }, arguments[1] || {});
+ }, arguments[1] || { });
this.start(options);
},
setup: function() {
- // Bug in Opera: Opera returns the "real" position of a static element or
- // relative element that does not have top/left explicitly set.
- // ==> Always set top and left for position relative elements in your stylesheets
- // (to 0 if you do not need them)
this.element.makePositioned();
this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
this.originalTop = parseFloat(this.element.getStyle('top') || '0');
- if(this.options.mode == 'absolute') {
- // absolute movement, so we need to calc deltaX and deltaY
+ if (this.options.mode == 'absolute') {
this.options.x = this.options.x - this.originalLeft;
this.options.y = this.options.y - this.originalTop;
}
},
update: function(position) {
this.element.setStyle({
- left: Math.round(this.options.x * position + this.originalLeft) + 'px',
- top: Math.round(this.options.y * position + this.originalTop) + 'px'
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
+ top: (this.options.y * position + this.originalTop).round() + 'px'
});
}
});
@@ -408,30 +395,29 @@
// for backwards compatibility
Effect.MoveBy = function(element, toTop, toLeft) {
return new Effect.Move(element,
- Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
};
-Effect.Scale = Class.create();
-Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
+Effect.Scale = Class.create(Effect.Base, {
initialize: function(element, percent) {
this.element = $(element);
- if(!this.element) throw(Effect._elementDoesNotExistError);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
scaleX: true,
scaleY: true,
scaleContent: true,
scaleFromCenter: false,
- scaleMode: 'box', // 'box' or 'contents' or {} with provided values
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
scaleFrom: 100.0,
scaleTo: percent
- }, arguments[2] || {});
+ }, arguments[2] || { });
this.start(options);
},
setup: function() {
this.restoreAfterFinish = this.options.restoreAfterFinish || false;
this.elementPositioning = this.element.getStyle('position');
- this.originalStyle = {};
+ this.originalStyle = { };
['top','left','width','height','fontSize'].each( function(k) {
this.originalStyle[k] = this.element.style[k];
}.bind(this));
@@ -441,7 +427,7 @@
var fontSize = this.element.getStyle('font-size') || '100%';
['em','px','%','pt'].each( function(fontSizeType) {
- if(fontSize.indexOf(fontSizeType)>0) {
+ if (fontSize.indexOf(fontSizeType)>0) {
this.fontSize = parseFloat(fontSize);
this.fontSizeType = fontSizeType;
}
@@ -450,62 +436,61 @@
this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
this.dims = null;
- if(this.options.scaleMode=='box')
+ if (this.options.scaleMode=='box')
this.dims = [this.element.offsetHeight, this.element.offsetWidth];
- if(/^content/.test(this.options.scaleMode))
+ if (/^content/.test(this.options.scaleMode))
this.dims = [this.element.scrollHeight, this.element.scrollWidth];
- if(!this.dims)
+ if (!this.dims)
this.dims = [this.options.scaleMode.originalHeight,
this.options.scaleMode.originalWidth];
},
update: function(position) {
var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
- if(this.options.scaleContent && this.fontSize)
+ if (this.options.scaleContent && this.fontSize)
this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
},
finish: function(position) {
- if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
},
setDimensions: function(height, width) {
- var d = {};
- if(this.options.scaleX) d.width = Math.round(width) + 'px';
- if(this.options.scaleY) d.height = Math.round(height) + 'px';
- if(this.options.scaleFromCenter) {
+ var d = { };
+ if (this.options.scaleX) d.width = width.round() + 'px';
+ if (this.options.scaleY) d.height = height.round() + 'px';
+ if (this.options.scaleFromCenter) {
var topd = (height - this.dims[0])/2;
var leftd = (width - this.dims[1])/2;
- if(this.elementPositioning == 'absolute') {
- if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
- if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
} else {
- if(this.options.scaleY) d.top = -topd + 'px';
- if(this.options.scaleX) d.left = -leftd + 'px';
+ if (this.options.scaleY) d.top = -topd + 'px';
+ if (this.options.scaleX) d.left = -leftd + 'px';
}
}
this.element.setStyle(d);
}
});
-Effect.Highlight = Class.create();
-Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
+Effect.Highlight = Class.create(Effect.Base, {
initialize: function(element) {
this.element = $(element);
- if(!this.element) throw(Effect._elementDoesNotExistError);
- var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
+ if (!this.element) throw(Effect._elementDoesNotExistError);
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
this.start(options);
},
setup: function() {
// Prevent executing on elements not in the layout flow
- if(this.element.getStyle('display')=='none') { this.cancel(); return; }
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
// Disable background image during the effect
- this.oldStyle = {};
+ this.oldStyle = { };
if (!this.options.keepBackgroundImage) {
this.oldStyle.backgroundImage = this.element.getStyle('background-image');
this.element.setStyle({backgroundImage: 'none'});
}
- if(!this.options.endcolor)
+ if (!this.options.endcolor)
this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
- if(!this.options.restorecolor)
+ if (!this.options.restorecolor)
this.options.restorecolor = this.element.getStyle('background-color');
// init color calculations
this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
@@ -513,7 +498,7 @@
},
update: function(position) {
this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
- return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
},
finish: function() {
this.element.setStyle(Object.extend(this.oldStyle, {
@@ -522,45 +507,37 @@
}
});
-Effect.ScrollTo = Class.create();
-Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
- initialize: function(element) {
- this.element = $(element);
- this.start(arguments[1] || {});
- },
- setup: function() {
- Position.prepare();
- var offsets = Position.cumulativeOffset(this.element);
- if(this.options.offset) offsets[1] += this.options.offset;
- var max = window.innerHeight ?
- window.height - window.innerHeight :
- document.body.scrollHeight -
- (document.documentElement.clientHeight ?
- document.documentElement.clientHeight : document.body.clientHeight);
- this.scrollStart = Position.deltaY;
- this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
- },
- update: function(position) {
- Position.prepare();
- window.scrollTo(Position.deltaX,
- this.scrollStart + (position*this.delta));
- }
-});
+Effect.ScrollTo = function(element) {
+ var options = arguments[1] || { },
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset(),
+ max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+ if (options.offset) elementOffsets[1] += options.offset;
+
+ return new Effect.Tween(null,
+ scrollOffsets.top,
+ elementOffsets[1] > max ? max : elementOffsets[1],
+ options,
+ function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ );
+};
+
/* ------------- combination effects ------------- */
Effect.Fade = function(element) {
element = $(element);
var oldOpacity = element.getInlineOpacity();
var options = Object.extend({
- from: element.getOpacity() || 1.0,
- to: 0.0,
- afterFinishInternal: function(effect) {
- if(effect.options.to!=0) return;
- effect.element.hide().setStyle({opacity: oldOpacity});
- }}, arguments[1] || {});
+ from: element.getOpacity() || 1.0,
+ to: 0.0,
+ afterFinishInternal: function(effect) {
+ if (effect.options.to!=0) return;
+ effect.element.hide().setStyle({opacity: oldOpacity});
+ }
+ }, arguments[1] || { });
return new Effect.Opacity(element,options);
-}
+};
Effect.Appear = function(element) {
element = $(element);
@@ -573,9 +550,9 @@
},
beforeSetup: function(effect) {
effect.element.setOpacity(effect.options.from).show();
- }}, arguments[1] || {});
+ }}, arguments[1] || { });
return new Effect.Opacity(element,options);
-}
+};
Effect.Puff = function(element) {
element = $(element);
@@ -597,9 +574,9 @@
},
afterFinishInternal: function(effect) {
effect.effects[0].element.hide().setStyle(oldStyle); }
- }, arguments[1] || {})
+ }, arguments[1] || { })
);
-}
+};
Effect.BlindUp = function(element) {
element = $(element);
@@ -611,9 +588,9 @@
afterFinishInternal: function(effect) {
effect.element.hide().undoClipping();
}
- }, arguments[1] || {})
+ }, arguments[1] || { })
);
-}
+};
Effect.BlindDown = function(element) {
element = $(element);
@@ -630,8 +607,8 @@
afterFinishInternal: function(effect) {
effect.element.undoClipping();
}
- }, arguments[1] || {}));
-}
+ }, arguments[1] || { }));
+};
Effect.SwitchOff = function(element) {
element = $(element);
@@ -652,8 +629,8 @@
}
})
}
- }, arguments[1] || {}));
-}
+ }, arguments[1] || { }));
+};
Effect.DropOut = function(element) {
element = $(element);
@@ -672,29 +649,35 @@
afterFinishInternal: function(effect) {
effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
}
- }, arguments[1] || {}));
-}
+ }, arguments[1] || { }));
+};
Effect.Shake = function(element) {
element = $(element);
+ var options = Object.extend({
+ distance: 20,
+ duration: 0.5
+ }, arguments[1] || {});
+ var distance = parseFloat(options.distance);
+ var split = parseFloat(options.duration) / 10.0;
var oldStyle = {
top: element.getStyle('top'),
left: element.getStyle('left') };
- return new Effect.Move(element,
- { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
+ return new Effect.Move(element,
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
- { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
- { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
- { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
- { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
new Effect.Move(effect.element,
- { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
effect.element.undoPositioned().setStyle(oldStyle);
}}) }}) }}) }}) }}) }});
-}
+};
Effect.SlideDown = function(element) {
element = $(element).cleanWhitespace();
@@ -710,7 +693,7 @@
afterSetup: function(effect) {
effect.element.makePositioned();
effect.element.down().makePositioned();
- if(window.opera) effect.element.setStyle({top: ''});
+ if (window.opera) effect.element.setStyle({top: ''});
effect.element.makeClipping().setStyle({height: '0px'}).show();
},
afterUpdateInternal: function(effect) {
@@ -720,23 +703,25 @@
afterFinishInternal: function(effect) {
effect.element.undoClipping().undoPositioned();
effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
- }, arguments[1] || {})
+ }, arguments[1] || { })
);
-}
+};
Effect.SlideUp = function(element) {
element = $(element).cleanWhitespace();
var oldInnerBottom = element.down().getStyle('bottom');
+ var elementDimensions = element.getDimensions();
return new Effect.Scale(element, window.opera ? 0 : 1,
Object.extend({ scaleContent: false,
scaleX: false,
scaleMode: 'box',
scaleFrom: 100,
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
restoreAfterFinish: true,
- beforeStartInternal: function(effect) {
+ afterSetup: function(effect) {
effect.element.makePositioned();
effect.element.down().makePositioned();
- if(window.opera) effect.element.setStyle({top: ''});
+ if (window.opera) effect.element.setStyle({top: ''});
effect.element.makeClipping().show();
},
afterUpdateInternal: function(effect) {
@@ -744,12 +729,12 @@
(effect.dims[0] - effect.element.clientHeight) + 'px' });
},
afterFinishInternal: function(effect) {
- effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: oldInnerBottom});
- effect.element.down().undoPositioned();
+ effect.element.hide().undoClipping().undoPositioned();
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
}
- }, arguments[1] || {})
+ }, arguments[1] || { })
);
-}
+};
// Bug in opera makes the TD containing this element expand for a instance after finish
Effect.Squish = function(element) {
@@ -762,7 +747,7 @@
effect.element.hide().undoClipping();
}
});
-}
+};
Effect.Grow = function(element) {
element = $(element);
@@ -771,7 +756,7 @@
moveTransition: Effect.Transitions.sinoidal,
scaleTransition: Effect.Transitions.sinoidal,
opacityTransition: Effect.Transitions.full
- }, arguments[1] || {});
+ }, arguments[1] || { });
var oldStyle = {
top: element.style.top,
left: element.style.left,
@@ -836,7 +821,7 @@
)
}
});
-}
+};
Effect.Shrink = function(element) {
element = $(element);
@@ -845,7 +830,7 @@
moveTransition: Effect.Transitions.sinoidal,
scaleTransition: Effect.Transitions.sinoidal,
opacityTransition: Effect.Transitions.none
- }, arguments[1] || {});
+ }, arguments[1] || { });
var oldStyle = {
top: element.style.top,
left: element.style.left,
@@ -890,11 +875,11 @@
effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
}, options)
);
-}
+};
Effect.Pulsate = function(element) {
element = $(element);
- var options = arguments[1] || {};
+ var options = arguments[1] || { };
var oldOpacity = element.getInlineOpacity();
var transition = options.transition || Effect.Transitions.sinoidal;
var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
@@ -903,7 +888,7 @@
Object.extend(Object.extend({ duration: 2.0, from: 0,
afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
}, options), {transition: reverser}));
-}
+};
Effect.Fold = function(element) {
element = $(element);
@@ -923,72 +908,71 @@
afterFinishInternal: function(effect) {
effect.element.hide().undoClipping().setStyle(oldStyle);
} });
- }}, arguments[1] || {}));
+ }}, arguments[1] || { }));
};
-Effect.Morph = Class.create();
-Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), {
+Effect.Morph = Class.create(Effect.Base, {
initialize: function(element) {
this.element = $(element);
- if(!this.element) throw(Effect._elementDoesNotExistError);
+ if (!this.element) throw(Effect._elementDoesNotExistError);
var options = Object.extend({
- style: {}
- }, arguments[1] || {});
- if (typeof options.style == 'string') {
- if(options.style.indexOf(':') == -1) {
- var cssText = '', selector = '.' + options.style;
- $A(document.styleSheets).reverse().each(function(styleSheet) {
- if (styleSheet.cssRules) cssRules = styleSheet.cssRules;
- else if (styleSheet.rules) cssRules = styleSheet.rules;
- $A(cssRules).reverse().each(function(rule) {
- if (selector == rule.selectorText) {
- cssText = rule.style.cssText;
- throw $break;
- }
- });
- if (cssText) throw $break;
+ style: { }
+ }, arguments[1] || { });
+
+ if (!Object.isString(options.style)) this.style = $H(options.style);
+ else {
+ if (options.style.include(':'))
+ this.style = options.style.parseStyle();
+ else {
+ this.element.addClassName(options.style);
+ this.style = $H(this.element.getStyles());
+ this.element.removeClassName(options.style);
+ var css = this.element.getStyles();
+ this.style = this.style.reject(function(style) {
+ return style.value == css[style.key];
});
- this.style = cssText.parseStyle();
- options.afterFinishInternal = function(effect){
+ options.afterFinishInternal = function(effect) {
effect.element.addClassName(effect.options.style);
effect.transforms.each(function(transform) {
- if(transform.style != 'opacity')
- effect.element.style[transform.style.camelize()] = '';
+ effect.element.style[transform.style] = '';
});
}
- } else this.style = options.style.parseStyle();
- } else this.style = $H(options.style)
+ }
+ }
this.start(options);
},
+
setup: function(){
function parseColor(color){
- if(!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
color = color.parseColor();
return $R(0,2).map(function(i){
return parseInt( color.slice(i*2+1,i*2+3), 16 )
});
}
this.transforms = this.style.map(function(pair){
- var property = pair[0].underscore().dasherize(), value = pair[1], unit = null;
+ var property = pair[0], value = pair[1], unit = null;
- if(value.parseColor('#zzzzzz') != '#zzzzzz') {
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
value = value.parseColor();
unit = 'color';
- } else if(property == 'opacity') {
+ } else if (property == 'opacity') {
value = parseFloat(value);
- if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout))
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
this.element.setStyle({zoom: 1});
- } else if(Element.CSS_LENGTH.test(value))
- var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/),
- value = parseFloat(components[1]), unit = (components.length == 3) ? components[2] : null;
+ } else if (Element.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ }
var originalValue = this.element.getStyle(property);
- return $H({
- style: property,
+ return {
+ style: property.camelize(),
originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
targetValue: unit=='color' ? parseColor(value) : value,
unit: unit
- });
+ };
}.bind(this)).reject(function(transform){
return (
(transform.originalValue == transform.targetValue) ||
@@ -1000,32 +984,35 @@
});
},
update: function(position) {
- var style = $H(), value = null;
- this.transforms.each(function(transform){
- value = transform.unit=='color' ?
- $R(0,2).inject('#',function(m,v,i){
- return m+(Math.round(transform.originalValue[i]+
- (transform.targetValue[i] - transform.originalValue[i])*position)).toColorPart() }) :
- transform.originalValue + Math.round(
- ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit;
- style[transform.style] = value;
- });
- this.element.setStyle(style);
+ var style = { }, transform, i = this.transforms.length;
+ while(i--)
+ style[(transform = this.transforms[i]).style] =
+ transform.unit=='color' ? '#'+
+ (Math.round(transform.originalValue[0]+
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+ (Math.round(transform.originalValue[1]+
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+ (Math.round(transform.originalValue[2]+
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+ (transform.originalValue +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.unit === null ? '' : transform.unit);
+ this.element.setStyle(style, true);
}
});
-Effect.Transform = Class.create();
-Object.extend(Effect.Transform.prototype, {
+Effect.Transform = Class.create({
initialize: function(tracks){
this.tracks = [];
- this.options = arguments[1] || {};
+ this.options = arguments[1] || { };
this.addTracks(tracks);
},
addTracks: function(tracks){
tracks.each(function(track){
- var data = $H(track).values().first();
+ track = $H(track);
+ var data = track.values().first();
this.tracks.push($H({
- ids: $H(track).keys().first(),
+ ids: track.keys().first(),
effect: Effect.Morph,
options: { style: data }
}));
@@ -1035,8 +1022,9 @@
play: function(){
return new Effect.Parallel(
this.tracks.map(function(track){
- var elements = [$(track.ids) || $$(track.ids)].flatten();
- return elements.map(function(e){ return new track.effect(e, Object.extend({ sync:true }, track.options)) });
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+ var elements = [$(ids) || $$(ids)].flatten();
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
}).flatten(),
this.options
);
@@ -1056,35 +1044,79 @@
Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+String.__parseStyleElement = document.createElement('div');
String.prototype.parseStyle = function(){
- var element = Element.extend(document.createElement('div'));
- element.innerHTML = '<div style="' + this + '"></div>';
- var style = element.down().style, styleRules = $H();
+ var style, styleRules = $H();
+ if (Prototype.Browser.WebKit)
+ style = new Element('div',{style:this}).style;
+ else {
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+ style = String.__parseStyleElement.childNodes[0].style;
+ }
Element.CSS_PROPERTIES.each(function(property){
- if(style[property]) styleRules[property] = style[property];
+ if (style[property]) styleRules.set(property, style[property]);
});
- if(/MSIE/.test(navigator.userAgent) && !window.opera && this.indexOf('opacity') > -1) {
- styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1];
- }
+
+ if (Prototype.Browser.IE && this.include('opacity'))
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
return styleRules;
};
-Element.morph = function(element, style) {
- new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {}));
- return element;
+if (document.defaultView && document.defaultView.getComputedStyle) {
+ Element.getStyles = function(element) {
+ var css = document.defaultView.getComputedStyle($(element), null);
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+ styles[property] = css[property];
+ return styles;
+ });
+ };
+} else {
+ Element.getStyles = function(element) {
+ element = $(element);
+ var css = element.currentStyle, styles;
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
+ results[property] = css[property];
+ return results;
+ });
+ if (!styles.opacity) styles.opacity = element.getOpacity();
+ return styles;
+ };
};
-['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom',
- 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each(
- function(f) { Element.Methods[f] = Element[f]; }
+Effect.Methods = {
+ morph: function(element, style) {
+ element = $(element);
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+ return element;
+ },
+ visualEffect: function(element, effect, options) {
+ element = $(element)
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+ new Effect[klass](element, options);
+ return element;
+ },
+ highlight: function(element, options) {
+ element = $(element);
+ new Effect.Highlight(element, options);
+ return element;
+ }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+ 'pulsate shake puff squish switchOff dropOut').each(
+ function(effect) {
+ Effect.Methods[effect] = function(element, options){
+ element = $(element);
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+ return element;
+ }
+ }
);
-Element.Methods.visualEffect = function(element, effect, options) {
- s = effect.gsub(/_/, '-').camelize();
- effect_class = s.charAt(0).toUpperCase() + s.substring(1);
- new Effect[effect_class](element, options);
- return $(element);
-};
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+ function(f) { Effect.Methods[f] = Element[f]; }
+);
-Element.addMethods();
\ No newline at end of file
+Element.addMethods(Effect.Methods);
Modified: branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/prototype.js
===================================================================
--- branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/prototype.js 2008-04-25 00:34:57 UTC (rev 10715)
+++ branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/prototype.js 2008-04-25 01:37:24 UTC (rev 10716)
@@ -1,51 +1,153 @@
-/* Prototype JavaScript framework, version 1.5.0
- * (c) 2005-2007 Sam Stephenson
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style license.
- * For details, see the Prototype web site: http://prototype.conio.net/
+ * For details, see the Prototype web site: http://www.prototypejs.org/
*
-/*--------------------------------------------------------------------------*/
+ *--------------------------------------------------------------------------*/
var Prototype = {
- Version: '1.5.0',
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
BrowserFeatures: {
- XPath: !!document.evaluate
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
},
- ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
- emptyFunction: function() {},
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
K: function(x) { return x }
-}
+};
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
var Class = {
create: function() {
- return function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
this.initialize.apply(this, arguments);
}
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
}
-}
+};
-var Abstract = new Object();
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
Object.extend = function(destination, source) {
- for (var property in source) {
+ for (var property in source)
destination[property] = source[property];
- }
return destination;
-}
+};
Object.extend(Object, {
inspect: function(object) {
try {
- if (object === undefined) return 'undefined';
+ if (Object.isUndefined(object)) return 'undefined';
if (object === null) return 'null';
- return object.inspect ? object.inspect() : object.toString();
+ return object.inspect ? object.inspect() : String(object);
} catch (e) {
if (e instanceof RangeError) return '...';
throw e;
}
},
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
keys: function(object) {
var keys = [];
for (var property in object)
@@ -61,41 +163,102 @@
},
clone: function(object) {
- return Object.extend({}, object);
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
}
});
-Function.prototype.bind = function() {
- var __method = this, args = $A(arguments), object = args.shift();
- return function() {
- return __method.apply(object, args.concat($A(arguments)));
- }
-}
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
-Function.prototype.bindAsEventListener = function(object) {
- var __method = this, args = $A(arguments), object = args.shift();
- return function(event) {
- return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments)));
- }
-}
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
-Object.extend(Number.prototype, {
- toColorPart: function() {
- var digits = this.toString(16);
- if (this < 16) return '0' + digits;
- return digits;
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
},
- succ: function() {
- return this + 1;
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
},
- times: function(iterator) {
- $R(0, this, true).each(iterator);
- return this;
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
}
});
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
var Try = {
these: function() {
var returnValue;
@@ -105,17 +268,22 @@
try {
returnValue = lambda();
break;
- } catch (e) {}
+ } catch (e) { }
}
return returnValue;
}
-}
+};
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
/*--------------------------------------------------------------------------*/
-var PeriodicalExecuter = Class.create();
-PeriodicalExecuter.prototype = {
+var PeriodicalExecuter = Class.create({
initialize: function(callback, frequency) {
this.callback = callback;
this.frequency = frequency;
@@ -128,6 +296,10 @@
this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
+ execute: function() {
+ this.callback(this);
+ },
+
stop: function() {
if (!this.timer) return;
clearInterval(this.timer);
@@ -138,16 +310,26 @@
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
- this.callback(this);
+ this.execute();
} finally {
this.currentlyExecuting = false;
}
}
}
-}
-String.interpret = function(value){
- return value == null ? '' : String(value);
-}
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
Object.extend(String.prototype, {
gsub: function(pattern, replacement) {
@@ -168,7 +350,7 @@
sub: function(pattern, replacement, count) {
replacement = this.gsub.prepareReplacement(replacement);
- count = count === undefined ? 1 : count;
+ count = Object.isUndefined(count) ? 1 : count;
return this.gsub(pattern, function(match) {
if (--count < 0) return match[0];
@@ -178,14 +360,14 @@
scan: function(pattern, iterator) {
this.gsub(pattern, iterator);
- return this;
+ return String(this);
},
truncate: function(length, truncation) {
length = length || 30;
- truncation = truncation === undefined ? '...' : truncation;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
return this.length > length ?
- this.slice(0, length - truncation.length) + truncation : this;
+ this.slice(0, length - truncation.length) + truncation : String(this);
},
strip: function() {
@@ -213,35 +395,34 @@
},
escapeHTML: function() {
- var div = document.createElement('div');
- var text = document.createTextNode(this);
- div.appendChild(text);
- return div.innerHTML;
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
},
unescapeHTML: function() {
- var div = document.createElement('div');
+ var div = new Element('div');
div.innerHTML = this.stripTags();
return div.childNodes[0] ? (div.childNodes.length > 1 ?
- $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) :
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
div.childNodes[0].nodeValue) : '';
},
toQueryParams: function(separator) {
var match = this.strip().match(/([^?#]*)(#.*)?$/);
- if (!match) return {};
+ if (!match) return { };
- return match[1].split(separator || '&').inject({}, function(hash, pair) {
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
if ((pair = pair.split('='))[0]) {
- var name = decodeURIComponent(pair[0]);
- var value = pair[1] ? decodeURIComponent(pair[1]) : undefined;
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
- if (hash[name] !== undefined) {
- if (hash[name].constructor != Array)
- hash[name] = [hash[name]];
- if (value) hash[name].push(value);
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
}
- else hash[name] = value;
+ else hash[key] = value;
}
return hash;
});
@@ -256,6 +437,10 @@
String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
},
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
camelize: function() {
var parts = this.split('-'), len = parts.length;
if (len == 1) return parts[0];
@@ -270,7 +455,7 @@
return camelized;
},
- capitalize: function(){
+ capitalize: function() {
return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
},
@@ -283,52 +468,131 @@
},
inspect: function(useDoubleQuotes) {
- var escapedString = this.replace(/\\/g, '\\\\');
- if (useDoubleQuotes)
- return '"' + escapedString.replace(/"/g, '\\"') + '"';
- else
- return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
}
});
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ }
+});
+
String.prototype.gsub.prepareReplacement = function(replacement) {
- if (typeof replacement == 'function') return replacement;
+ if (Object.isFunction(replacement)) return replacement;
var template = new Template(replacement);
return function(match) { return template.evaluate(match) };
-}
+};
String.prototype.parseQuery = String.prototype.toQueryParams;
-var Template = Class.create();
-Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
-Template.prototype = {
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
initialize: function(template, pattern) {
this.template = template.toString();
- this.pattern = pattern || Template.Pattern;
+ this.pattern = pattern || Template.Pattern;
},
evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
return this.template.gsub(this.pattern, function(match) {
- var before = match[1];
+ if (object == null) return '';
+
+ var before = match[1] || '';
if (before == '\\') return match[2];
- return before + String.interpret(object[match[3]]);
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
});
}
-}
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
-var $break = new Object();
-var $continue = new Object();
+var $break = { };
var Enumerable = {
- each: function(iterator) {
+ each: function(iterator, context) {
var index = 0;
+ iterator = iterator.bind(context);
try {
this._each(function(value) {
- try {
- iterator(value, index++);
- } catch (e) {
- if (e != $continue) throw e;
- }
+ iterator(value, index++);
});
} catch (e) {
if (e != $break) throw e;
@@ -336,40 +600,45 @@
return this;
},
- eachSlice: function(number, iterator) {
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var index = -number, slices = [], array = this.toArray();
while ((index += number) < array.length)
slices.push(array.slice(index, index+number));
- return slices.map(iterator);
+ return slices.collect(iterator, context);
},
- all: function(iterator) {
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var result = true;
this.each(function(value, index) {
- result = result && !!(iterator || Prototype.K)(value, index);
+ result = result && !!iterator(value, index);
if (!result) throw $break;
});
return result;
},
- any: function(iterator) {
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var result = false;
this.each(function(value, index) {
- if (result = !!(iterator || Prototype.K)(value, index))
+ if (result = !!iterator(value, index))
throw $break;
});
return result;
},
- collect: function(iterator) {
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var results = [];
this.each(function(value, index) {
- results.push((iterator || Prototype.K)(value, index));
+ results.push(iterator(value, index));
});
return results;
},
- detect: function(iterator) {
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
var result;
this.each(function(value, index) {
if (iterator(value, index)) {
@@ -380,7 +649,8 @@
return result;
},
- findAll: function(iterator) {
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
var results = [];
this.each(function(value, index) {
if (iterator(value, index))
@@ -389,17 +659,24 @@
return results;
},
- grep: function(pattern, iterator) {
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
this.each(function(value, index) {
- var stringValue = value.toString();
- if (stringValue.match(pattern))
- results.push((iterator || Prototype.K)(value, index));
- })
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
return results;
},
include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
var found = false;
this.each(function(value) {
if (value == object) {
@@ -411,14 +688,15 @@
},
inGroupsOf: function(number, fillWith) {
- fillWith = fillWith === undefined ? null : fillWith;
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
return this.eachSlice(number, function(slice) {
while(slice.length < number) slice.push(fillWith);
return slice;
});
},
- inject: function(memo, iterator) {
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
this.each(function(value, index) {
memo = iterator(memo, value, index);
});
@@ -432,30 +710,33 @@
});
},
- max: function(iterator) {
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var result;
this.each(function(value, index) {
- value = (iterator || Prototype.K)(value, index);
- if (result == undefined || value >= result)
+ value = iterator(value, index);
+ if (result == null || value >= result)
result = value;
});
return result;
},
- min: function(iterator) {
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var result;
this.each(function(value, index) {
- value = (iterator || Prototype.K)(value, index);
- if (result == undefined || value < result)
+ value = iterator(value, index);
+ if (result == null || value < result)
result = value;
});
return result;
},
- partition: function(iterator) {
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var trues = [], falses = [];
this.each(function(value, index) {
- ((iterator || Prototype.K)(value, index) ?
+ (iterator(value, index) ?
trues : falses).push(value);
});
return [trues, falses];
@@ -463,13 +744,14 @@
pluck: function(property) {
var results = [];
- this.each(function(value, index) {
+ this.each(function(value) {
results.push(value[property]);
});
return results;
},
- reject: function(iterator) {
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
var results = [];
this.each(function(value, index) {
if (!iterator(value, index))
@@ -478,7 +760,8 @@
return results;
},
- sortBy: function(iterator) {
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
return this.map(function(value, index) {
return {value: value, criteria: iterator(value, index)};
}).sort(function(left, right) {
@@ -493,7 +776,7 @@
zip: function() {
var iterator = Prototype.K, args = $A(arguments);
- if (typeof args.last() == 'function')
+ if (Object.isFunction(args.last()))
iterator = args.pop();
var collections = [this].concat(args).map($A);
@@ -509,31 +792,42 @@
inspect: function() {
return '#<Enumerable:' + this.toArray().inspect() + '>';
}
-}
+};
Object.extend(Enumerable, {
map: Enumerable.collect,
find: Enumerable.detect,
select: Enumerable.findAll,
+ filter: Enumerable.findAll,
member: Enumerable.include,
- entries: Enumerable.toArray
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
});
-var $A = Array.from = function(iterable) {
+function $A(iterable) {
if (!iterable) return [];
- if (iterable.toArray) {
- return iterable.toArray();
- } else {
- var results = [];
- for (var i = 0, length = iterable.length; i < length; i++)
- results.push(iterable[i]);
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
return results;
- }
+ };
}
+Array.from = $A;
+
Object.extend(Array.prototype, Enumerable);
-if (!Array.prototype._reverse)
- Array.prototype._reverse = Array.prototype.reverse;
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
Object.extend(Array.prototype, {
_each: function(iterator) {
@@ -562,7 +856,7 @@
flatten: function() {
return this.inject([], function(array, value) {
- return array.concat(value && value.constructor == Array ?
+ return array.concat(Object.isArray(value) ?
value.flatten() : [value]);
});
},
@@ -574,12 +868,6 @@
});
},
- indexOf: function(object) {
- for (var i = 0, length = this.length; i < length; i++)
- if (this[i] == object) return i;
- return -1;
- },
-
reverse: function(inline) {
return (inline !== false ? this : this.toArray())._reverse();
},
@@ -588,12 +876,20 @@
return this.length > 1 ? this : this[0];
},
- uniq: function() {
- return this.inject([], function(array, value) {
- return array.include(value) ? array : array.concat([value]);
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
});
},
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
clone: function() {
return [].concat(this);
},
@@ -604,125 +900,187 @@
inspect: function() {
return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
}
});
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
Array.prototype.toArray = Array.prototype.clone;
-function $w(string){
+function $w(string) {
+ if (!Object.isString(string)) return [];
string = string.strip();
return string ? string.split(/\s+/) : [];
}
-if(window.opera){
- Array.prototype.concat = function(){
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
var array = [];
- for(var i = 0, length = this.length; i < length; i++) array.push(this[i]);
- for(var i = 0, length = arguments.length; i < length; i++) {
- if(arguments[i].constructor == Array) {
- for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
array.push(arguments[i][j]);
} else {
array.push(arguments[i]);
}
}
return array;
- }
+ };
}
-var Hash = function(obj) {
- Object.extend(this, obj || {});
-};
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
-Object.extend(Hash, {
- toQueryString: function(obj) {
- var parts = [];
+ succ: function() {
+ return this + 1;
+ },
- this.prototype._each.call(obj, function(pair) {
- if (!pair.key) return;
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
- if (pair.value && pair.value.constructor == Array) {
- var values = pair.value.compact();
- if (values.length < 2) pair.value = values.reduce();
- else {
- key = encodeURIComponent(pair.key);
- values.each(function(value) {
- value = value != undefined ? encodeURIComponent(value) : '';
- parts.push(key + '=' + encodeURIComponent(value));
- });
- return;
- }
- }
- if (pair.value == undefined) pair[1] = '';
- parts.push(pair.map(encodeURIComponent).join('='));
- });
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
- return parts.join('&');
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
}
});
-Object.extend(Hash.prototype, Enumerable);
-Object.extend(Hash.prototype, {
- _each: function(iterator) {
- for (var key in this) {
- var value = this[key];
- if (value && value == Hash.prototype[key]) continue;
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
- var pair = [key, value];
- pair.key = key;
- pair.value = value;
- iterator(pair);
- }
- },
+var Hash = Class.create(Enumerable, (function() {
- keys: function() {
- return this.pluck('key');
- },
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
- values: function() {
- return this.pluck('value');
- },
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
- merge: function(hash) {
- return $H(hash).inject(this, function(mergedHash, pair) {
- mergedHash[pair.key] = pair.value;
- return mergedHash;
- });
- },
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
- remove: function() {
- var result;
- for(var i = 0, length = arguments.length; i < length; i++) {
- var value = this[arguments[i]];
- if (value !== undefined){
- if (result === undefined) result = value;
- else {
- if (result.constructor != Array) result = [result];
- result.push(value)
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
}
- }
- delete this[arguments[i]];
- }
- return result;
- },
+ return toQueryPair(key, values);
+ }).join('&');
+ },
- toQueryString: function() {
- return Hash.toQueryString(this);
- },
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
- inspect: function() {
- return '#<Hash:{' + this.map(function(pair) {
- return pair.map(Object.inspect).join(': ');
- }).join(', ') + '}>';
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
}
-});
+})());
-function $H(object) {
- if (object && object.constructor == Hash) return object;
- return new Hash(object);
-};
-ObjectRange = Class.create();
-Object.extend(ObjectRange.prototype, Enumerable);
-Object.extend(ObjectRange.prototype, {
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
initialize: function(start, end, exclusive) {
this.start = start;
this.end = end;
@@ -748,7 +1106,7 @@
var $R = function(start, end, exclusive) {
return new ObjectRange(start, end, exclusive);
-}
+};
var Ajax = {
getTransport: function() {
@@ -760,7 +1118,7 @@
},
activeRequestCount: 0
-}
+};
Ajax.Responders = {
responders: [],
@@ -780,10 +1138,10 @@
dispatch: function(callback, request, transport, json) {
this.each(function(responder) {
- if (typeof responder[callback] == 'function') {
+ if (Object.isFunction(responder[callback])) {
try {
responder[callback].apply(responder, [request, transport, json]);
- } catch (e) {}
+ } catch (e) { }
}
});
}
@@ -792,49 +1150,45 @@
Object.extend(Ajax.Responders, Enumerable);
Ajax.Responders.register({
- onCreate: function() {
- Ajax.activeRequestCount++;
- },
- onComplete: function() {
- Ajax.activeRequestCount--;
- }
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
});
-Ajax.Base = function() {};
-Ajax.Base.prototype = {
- setOptions: function(options) {
+Ajax.Base = Class.create({
+ initialize: function(options) {
this.options = {
method: 'post',
asynchronous: true,
contentType: 'application/x-www-form-urlencoded',
encoding: 'UTF-8',
- parameters: ''
- }
- Object.extend(this.options, options || {});
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
this.options.method = this.options.method.toLowerCase();
- if (typeof this.options.parameters == 'string')
+
+ if (Object.isString(this.options.parameters))
this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
}
-}
+});
-Ajax.Request = Class.create();
-Ajax.Request.Events =
- ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
-
-Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
+Ajax.Request = Class.create(Ajax.Base, {
_complete: false,
- initialize: function(url, options) {
+ initialize: function($super, url, options) {
+ $super(options);
this.transport = Ajax.getTransport();
- this.setOptions(options);
this.request(url);
},
request: function(url) {
this.url = url;
this.method = this.options.method;
- var params = this.options.parameters;
+ var params = Object.clone(this.options.parameters);
if (!['get', 'post'].include(this.method)) {
// simulate other verbs over post
@@ -842,29 +1196,32 @@
this.method = 'post';
}
- params = Hash.toQueryString(params);
- if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_='
+ this.parameters = params;
- // when GET, append parameters to URL
- if (this.method == 'get' && params)
- this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params;
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
try {
- Ajax.Responders.dispatch('onCreate', this, this.transport);
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
this.transport.open(this.method.toUpperCase(), this.url,
this.options.asynchronous);
- if (this.options.asynchronous)
- setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
this.transport.onreadystatechange = this.onStateChange.bind(this);
this.setRequestHeaders();
- var body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
- this.transport.send(body);
-
/* Force Firefox to handle ready state 4 for synchronous requests */
if (!this.options.asynchronous && this.transport.overrideMimeType)
this.onStateChange();
@@ -905,7 +1262,7 @@
if (typeof this.options.requestHeaders == 'object') {
var extras = this.options.requestHeaders;
- if (typeof extras.push == 'function')
+ if (Object.isFunction(extras.push))
for (var i = 0, length = extras.length; i < length; i += 2)
headers[extras[i]] = extras[i+1];
else
@@ -917,32 +1274,39 @@
},
success: function() {
- return !this.transport.status
- || (this.transport.status >= 200 && this.transport.status < 300);
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
},
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
respondToReadyState: function(readyState) {
- var state = Ajax.Request.Events[readyState];
- var transport = this.transport, json = this.evalJSON();
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
if (state == 'Complete') {
try {
this._complete = true;
- (this.options['on' + this.transport.status]
+ (this.options['on' + response.status]
|| this.options['on' + (this.success() ? 'Success' : 'Failure')]
- || Prototype.emptyFunction)(transport, json);
+ || Prototype.emptyFunction)(response, response.headerJSON);
} catch (e) {
this.dispatchException(e);
}
- if ((this.getHeader('Content-type') || 'text/javascript').strip().
- match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
- this.evalResponse();
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
}
try {
- (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
- Ajax.Responders.dispatch('on' + state, this, transport, json);
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
} catch (e) {
this.dispatchException(e);
}
@@ -953,22 +1317,24 @@
}
},
- getHeader: function(name) {
- try {
- return this.transport.getResponseHeader(name);
- } catch (e) { return null }
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
},
- evalJSON: function() {
+ getHeader: function(name) {
try {
- var json = this.getHeader('X-JSON');
- return json ? eval('(' + json + ')') : null;
+ return this.transport.getResponseHeader(name) || null;
} catch (e) { return null }
},
evalResponse: function() {
try {
- return eval(this.transport.responseText);
+ return eval((this.transport.responseText || '').unfilterJSON());
} catch (e) {
this.dispatchException(e);
}
@@ -980,57 +1346,128 @@
}
});
-Ajax.Updater = Class.create();
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
-Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
- initialize: function(container, url, options) {
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
this.container = {
success: (container.success || container),
failure: (container.failure || (container.success ? null : container))
- }
+ };
- this.transport = Ajax.getTransport();
- this.setOptions(options);
-
- var onComplete = this.options.onComplete || Prototype.emptyFunction;
- this.options.onComplete = (function(transport, param) {
- this.updateContent();
- onComplete(transport, param);
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
}).bind(this);
- this.request(url);
+ $super(url, options);
},
- updateContent: function() {
- var receiver = this.container[this.success() ? 'success' : 'failure'];
- var response = this.transport.responseText;
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
- if (!this.options.evalScripts) response = response.stripScripts();
+ if (!options.evalScripts) responseText = responseText.stripScripts();
if (receiver = $(receiver)) {
- if (this.options.insertion)
- new this.options.insertion(receiver, response);
- else
- receiver.update(response);
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
}
-
- if (this.success()) {
- if (this.onComplete)
- setTimeout(this.onComplete.bind(this), 10);
- }
}
});
-Ajax.PeriodicalUpdater = Class.create();
-Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
- initialize: function(container, url, options) {
- this.setOptions(options);
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
this.onComplete = this.options.onComplete;
this.frequency = (this.options.frequency || 2);
this.decay = (this.options.decay || 1);
- this.updater = {};
+ this.updater = { };
this.container = container;
this.url = url;
@@ -1048,15 +1485,14 @@
(this.onComplete || Prototype.emptyFunction).apply(this, arguments);
},
- updateComplete: function(request) {
+ updateComplete: function(response) {
if (this.options.decay) {
- this.decay = (request.responseText == this.lastText ?
+ this.decay = (response.responseText == this.lastText ?
this.decay * this.options.decay : 1);
- this.lastText = request.responseText;
+ this.lastText = response.responseText;
}
- this.timer = setTimeout(this.onTimerEvent.bind(this),
- this.decay * this.frequency * 1000);
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
},
onTimerEvent: function() {
@@ -1069,7 +1505,7 @@
elements.push($(arguments[i]));
return elements;
}
- if (typeof element == 'string')
+ if (Object.isString(element))
element = document.getElementById(element);
return Element.extend(element);
}
@@ -1080,64 +1516,52 @@
var query = document.evaluate(expression, $(parentElement) || document,
null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0, length = query.snapshotLength; i < length; i++)
- results.push(query.snapshotItem(i));
+ results.push(Element.extend(query.snapshotItem(i)));
return results;
};
}
-document.getElementsByClassName = function(className, parentElement) {
- if (Prototype.BrowserFeatures.XPath) {
- var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
- return document._getElementsByXPath(q, parentElement);
- } else {
- var children = ($(parentElement) || document.body).getElementsByTagName('*');
- var elements = [], child;
- for (var i = 0, length = children.length; i < length; i++) {
- child = children[i];
- if (Element.hasClassName(child, className))
- elements.push(Element.extend(child));
- }
- return elements;
- }
-};
-
/*--------------------------------------------------------------------------*/
-if (!window.Element)
- var Element = new Object();
+if (!window.Node) var Node = { };
-Element.extend = function(element) {
- if (!element || _nativeExtensions || element.nodeType == 3) return element;
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
- if (!element._extended && element.tagName && element != window) {
- var methods = Object.clone(Element.Methods), cache = Element.extend.cache;
-
- if (element.tagName == 'FORM')
- Object.extend(methods, Form.Methods);
- if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))
- Object.extend(methods, Form.Element.Methods);
-
- Object.extend(methods, Element.Methods.Simulated);
-
- for (var property in methods) {
- var value = methods[property];
- if (typeof value == 'function' && !(property in element))
- element[property] = cache.findOrStore(value);
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
}
- }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
- element._extended = true;
- return element;
-};
+Element.cache = { };
-Element.extend.cache = {
- findOrStore: function(value) {
- return this[value] = this[value] || function() {
- return value.apply(null, [this].concat($A(arguments)));
- }
- }
-};
-
Element.Methods = {
visible: function(element) {
return $(element).style.display != 'none';
@@ -1165,28 +1589,78 @@
return element;
},
- update: function(element, html) {
- html = typeof html == 'undefined' ? '' : html.toString();
- $(element).innerHTML = html.stripScripts();
- setTimeout(function() {html.evalScripts()}, 10);
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
return element;
},
- replace: function(element, html) {
+ replace: function(element, content) {
element = $(element);
- html = typeof html == 'undefined' ? '' : html.toString();
- if (element.outerHTML) {
- element.outerHTML = html.stripScripts();
- } else {
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
var range = element.ownerDocument.createRange();
- range.selectNodeContents(element);
- element.parentNode.replaceChild(
- range.createContextualFragment(html.stripScripts()), element);
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
}
- setTimeout(function() {html.evalScripts()}, 10);
+ element.parentNode.replaceChild(content, element);
return element;
},
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
inspect: function(element) {
element = $(element);
var result = '<' + element.tagName.toLowerCase();
@@ -1212,9 +1686,15 @@
},
descendants: function(element) {
- return $A($(element).getElementsByTagName('*'));
+ return $(element).select("*");
},
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
immediateDescendants: function(element) {
if (!(element = $(element).firstChild)) return [];
while (element && element.nodeType != 1) element = element.nextSibling;
@@ -1236,48 +1716,95 @@
},
match: function(element, selector) {
- if (typeof selector == 'string')
+ if (Object.isString(selector))
selector = new Selector(selector);
return selector.match($(element));
},
up: function(element, expression, index) {
- return Selector.findElement($(element).ancestors(), expression, index);
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
},
down: function(element, expression, index) {
- return Selector.findElement($(element).descendants(), expression, index);
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
},
previous: function(element, expression, index) {
- return Selector.findElement($(element).previousSiblings(), expression, index);
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
},
next: function(element, expression, index) {
- return Selector.findElement($(element).nextSiblings(), expression, index);
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
},
- getElementsBySelector: function() {
+ select: function() {
var args = $A(arguments), element = $(args.shift());
return Selector.findChildElements(element, args);
},
- getElementsByClassName: function(element, className) {
- return document.getElementsByClassName(className, element);
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
},
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
readAttribute: function(element, name) {
element = $(element);
- if (document.all && !window.opera) {
- var t = Element._attributeTranslations;
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
if (t.values[name]) return t.values[name](element, name);
- if (t.names[name]) name = t.names[name];
- var attribute = element.attributes[name];
- if(attribute) return attribute.nodeValue;
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
}
return element.getAttribute(name);
},
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
getHeight: function(element) {
return $(element).getDimensions().height;
},
@@ -1293,41 +1820,30 @@
hasClassName: function(element, className) {
if (!(element = $(element))) return;
var elementClassName = element.className;
- if (elementClassName.length == 0) return false;
- if (elementClassName == className ||
- elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
- return true;
- return false;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
},
addClassName: function(element, className) {
if (!(element = $(element))) return;
- Element.classNames(element).add(className);
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
return element;
},
removeClassName: function(element, className) {
if (!(element = $(element))) return;
- Element.classNames(element).remove(className);
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
return element;
},
toggleClassName: function(element, className) {
if (!(element = $(element))) return;
- Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
- return element;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
},
- observe: function() {
- Event.observe.apply(Event, arguments);
- return $A(arguments).first();
- },
-
- stopObserving: function() {
- Event.stopObserving.apply(Event, arguments);
- return $A(arguments).first();
- },
-
// removes whitespace-only text node children
cleanWhitespace: function(element) {
element = $(element);
@@ -1342,74 +1858,77 @@
},
empty: function(element) {
- return $(element).innerHTML.match(/^\s*$/);
+ return $(element).innerHTML.blank();
},
descendantOf: function(element, ancestor) {
element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
while (element = element.parentNode)
- if (element == ancestor) return true;
+ if (element == originalAncestor) return true;
return false;
},
scrollTo: function(element) {
element = $(element);
- var pos = Position.cumulativeOffset(element);
+ var pos = element.cumulativeOffset();
window.scrollTo(pos[0], pos[1]);
return element;
},
getStyle: function(element, style) {
element = $(element);
- if (['float','cssFloat'].include(style))
- style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat');
- style = style.camelize();
+ style = style == 'float' ? 'cssFloat' : style.camelize();
var value = element.style[style];
if (!value) {
- if (document.defaultView && document.defaultView.getComputedStyle) {
- var css = document.defaultView.getComputedStyle(element, null);
- value = css ? css[style] : null;
- } else if (element.currentStyle) {
- value = element.currentStyle[style];
- }
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
}
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
- if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none'))
- value = element['offset'+style.capitalize()] + 'px';
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
- if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
- if (Element.getStyle(element, 'position') == 'static') value = 'auto';
- if(style == 'opacity') {
- if(value) return parseFloat(value);
- if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
- if(value[1]) return parseFloat(value[1]) / 100;
- return 1.0;
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
}
- return value == 'auto' ? null : value;
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
},
- setStyle: function(element, style) {
+ setOpacity: function(element, value) {
element = $(element);
- for (var name in style) {
- var value = style[name];
- if(name == 'opacity') {
- if (value == 1) {
- value = (/Gecko/.test(navigator.userAgent) &&
- !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0;
- if(/MSIE/.test(navigator.userAgent) && !window.opera)
- element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
- } else if(value === '') {
- if(/MSIE/.test(navigator.userAgent) && !window.opera)
- element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
- } else {
- if(value < 0.00001) value = 0;
- if(/MSIE/.test(navigator.userAgent) && !window.opera)
- element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') +
- 'alpha(opacity='+value*100+')';
- }
- } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat';
- element.style[name.camelize()] = value;
- }
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
return element;
},
@@ -1468,8 +1987,8 @@
makeClipping: function(element) {
element = $(element);
if (element._overflow) return element;
- element._overflow = element.style.overflow || 'auto';
- if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
element.style.overflow = 'hidden';
return element;
},
@@ -1480,393 +1999,1376 @@
element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
element._overflow = null;
return element;
- }
-};
+ },
-Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf});
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
-Element._attributeTranslations = {};
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
-Element._attributeTranslations.names = {
- colspan: "colSpan",
- rowspan: "rowSpan",
- valign: "vAlign",
- datetime: "dateTime",
- accesskey: "accessKey",
- tabindex: "tabIndex",
- enctype: "encType",
- maxlength: "maxLength",
- readonly: "readOnly",
- longdesc: "longDesc"
-};
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
-Element._attributeTranslations.values = {
- _getAttr: function(element, attribute) {
- return element.getAttribute(attribute, 2);
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
},
- _flag: function(element, attribute) {
- return $(element).hasAttribute(attribute) ? attribute : null;
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
},
- style: function(element) {
- return element.style.cssText.toLowerCase();
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
},
- title: function(element) {
- var node = element.getAttributeNode('title');
- return node.specified ? node.nodeValue : null;
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
}
};
-Object.extend(Element._attributeTranslations.values, {
- href: Element._attributeTranslations.values._getAttr,
- src: Element._attributeTranslations.values._getAttr,
- disabled: Element._attributeTranslations.values._flag,
- checked: Element._attributeTranslations.values._flag,
- readonly: Element._attributeTranslations.values._flag,
- multiple: Element._attributeTranslations.values._flag
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
});
-Element.Methods.Simulated = {
- hasAttribute: function(element, attribute) {
- var t = Element._attributeTranslations;
- attribute = t.names[attribute] || attribute;
- return $(element).getAttributeNode(attribute).specified;
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
}
};
-// IE is missing .innerHTML support for TABLE-related elements
-if (document.all && !window.opera){
- Element.Methods.update = function(element, html) {
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
element = $(element);
- html = typeof html == 'undefined' ? '' : html.toString();
- var tagName = element.tagName.toUpperCase();
- if (['THEAD','TBODY','TR','TD'].include(tagName)) {
- var div = document.createElement('div');
- switch (tagName) {
- case 'THEAD':
- case 'TBODY':
- div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>';
- depth = 2;
- break;
- case 'TR':
- div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>';
- depth = 3;
- break;
- case 'TD':
- div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>';
- depth = 4;
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
}
- $A(element.childNodes).each(function(node){
- element.removeChild(node)
- });
- depth.times(function(){ div = div.firstChild });
+ }
+ };
- $A(div.childNodes).each(
- function(node){ element.appendChild(node) });
- } else {
- element.innerHTML = html.stripScripts();
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
}
- setTimeout(function() {html.evalScripts()}, 10);
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
}
};
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
Object.extend(Element, Element.Methods);
-var _nativeExtensions = false;
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
-if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))
- ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) {
- var className = 'HTML' + tag + 'Element';
- if(window[className]) return;
- var klass = window[className] = {};
- klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__;
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
});
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
Element.addMethods = function(methods) {
- Object.extend(Element.Methods, methods || {});
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
function copy(methods, destination, onlyIfAbsent) {
onlyIfAbsent = onlyIfAbsent || false;
- var cache = Element.extend.cache;
for (var property in methods) {
var value = methods[property];
+ if (!Object.isFunction(value)) continue;
if (!onlyIfAbsent || !(property in destination))
- destination[property] = cache.findOrStore(value);
+ destination[property] = value.methodize();
}
}
- if (typeof HTMLElement != 'undefined') {
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
copy(Element.Methods, HTMLElement.prototype);
copy(Element.Methods.Simulated, HTMLElement.prototype, true);
- copy(Form.Methods, HTMLFormElement.prototype);
- [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) {
- copy(Form.Element.Methods, klass.prototype);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
});
- _nativeExtensions = true;
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
}
-}
+};
+/* Portions of the Selector class are derived from Jack Slocum�۪s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
-var Toggle = new Object();
-Toggle.display = Element.toggle;
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
-/*--------------------------------------------------------------------------*/
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
-Abstract.Insertion = function(adjacency) {
- this.adjacency = adjacency;
-}
+ var e = this.expression;
-Abstract.Insertion.prototype = {
- initialize: function(element, content) {
- this.element = $(element);
- this.content = content.stripScripts();
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
- if (this.adjacency && this.element.insertAdjacentHTML) {
- try {
- this.element.insertAdjacentHTML(this.adjacency, this.content);
- } catch (e) {
- var tagName = this.element.tagName.toUpperCase();
- if (['TBODY', 'TR'].include(tagName)) {
- this.insertContent(this.contentFromAnonymousTable());
- } else {
- throw e;
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
}
}
- } else {
- this.range = this.element.ownerDocument.createRange();
- if (this.initializeRange) this.initializeRange();
- this.insertContent([this.range.createContextualFragment(this.content)]);
}
- setTimeout(function() {content.evalScripts()}, 10);
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
},
- contentFromAnonymousTable: function() {
- var div = document.createElement('div');
- div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
- return $A(div.childNodes[0].childNodes[0].childNodes);
- }
-}
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
-var Insertion = new Object();
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
-Insertion.Before = Class.create();
-Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
- initializeRange: function() {
- this.range.setStartBefore(this.element);
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
},
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.parentNode.insertBefore(fragment, this.element);
- }).bind(this));
- }
-});
-
-Insertion.Top = Class.create();
-Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
- initializeRange: function() {
- this.range.selectNodeContents(this.element);
- this.range.collapse(true);
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
},
- insertContent: function(fragments) {
- fragments.reverse(false).each((function(fragment) {
- this.element.insertBefore(fragment, this.element.firstChild);
- }).bind(this));
- }
-});
+ match: function(element) {
+ this.tokens = [];
-Insertion.Bottom = Class.create();
-Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
- initializeRange: function() {
- this.range.selectNodeContents(this.element);
- this.range.collapse(this.element);
- },
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.appendChild(fragment);
- }).bind(this));
- }
-});
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
-Insertion.After = Class.create();
-Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
- initializeRange: function() {
- this.range.setStartAfter(this.element);
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
},
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.parentNode.insertBefore(fragment,
- this.element.nextSibling);
- }).bind(this));
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
}
});
-/*--------------------------------------------------------------------------*/
+Object.extend(Selector, {
+ _cache: { },
-Element.ClassNames = Class.create();
-Element.ClassNames.prototype = {
- initialize: function(element) {
- this.element = $(element);
- },
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
- _each: function(iterator) {
- this.element.className.split(/\s+/).select(function(name) {
- return name.length > 0;
- })._each(iterator);
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
},
- set: function(className) {
- this.element.className = className;
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
},
- add: function(classNameToAdd) {
- if (this.include(classNameToAdd)) return;
- this.set($A(this).concat(classNameToAdd).join(' '));
- },
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
- remove: function(classNameToRemove) {
- if (!this.include(classNameToRemove)) return;
- this.set($A(this).without(classNameToRemove).join(' '));
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
},
- toString: function() {
- return $A(this).join(' ');
- }
-};
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
-Object.extend(Element.ClassNames.prototype, Enumerable);
-var Selector = Class.create();
-Selector.prototype = {
- initialize: function(expression) {
- this.params = {classNames: []};
- this.expression = expression.toString().strip();
- this.parseExpression();
- this.compileMatcher();
- },
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
- parseExpression: function() {
- function abort(message) { throw 'Parse error in selector: ' + message; }
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
- if (this.expression == '') abort('empty expression');
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
- var params = this.params, expr = this.expression, match, modifier, clause, rest;
- while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
- params.attributes = params.attributes || [];
- params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
- expr = match[1];
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
}
+ },
- if (expr == '*') return this.params.wildcard = true;
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
- while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
- modifier = match[1], clause = match[2], rest = match[3];
- switch (modifier) {
- case '#': params.id = clause; break;
- case '.': params.classNames.push(clause); break;
- case '':
- case undefined: params.tagName = clause.toUpperCase(); break;
- default: abort(expr.inspect());
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
}
- expr = rest;
- }
+ },
- if (expr.length > 0) abort(expr.inspect());
- },
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
- buildMatchExpression: function() {
- var params = this.params, conditions = [], clause;
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
- if (params.wildcard)
- conditions.push('true');
- if (clause = params.id)
- conditions.push('element.readAttribute("id") == ' + clause.inspect());
- if (clause = params.tagName)
- conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
- if ((clause = params.classNames).length > 0)
- for (var i = 0, length = clause.length; i < length; i++)
- conditions.push('element.hasClassName(' + clause[i].inspect() + ')');
- if (clause = params.attributes) {
- clause.each(function(attribute) {
- var value = 'element.readAttribute(' + attribute.name.inspect() + ')';
- var splitValueBy = function(delimiter) {
- return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
}
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
- switch (attribute.operator) {
- case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break;
- case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
- case '|=': conditions.push(
- splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
- ); break;
- case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break;
- case '':
- case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break;
- default: throw 'Unknown operator ' + attribute.operator + ' in selector';
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
}
- });
- }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
- return conditions.join(' && ');
- },
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
- compileMatcher: function() {
- this.match = new Function('element', 'if (!element.tagName) return false; \
- element = $(element); \
- return ' + this.buildMatchExpression());
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
},
- findElements: function(scope) {
- var element;
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
- if (element = $(this.params.id))
- if (this.match(element))
- if (!scope || Element.childOf(element, scope))
- return [element];
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
- scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
- var results = [];
- for (var i = 0, length = scope.length; i < length; i++)
- if (this.match(element = scope[i]))
- results.push(Element.extend(element));
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
- return results;
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
},
- toString: function() {
- return this.expression;
- }
-}
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
-Object.extend(Selector, {
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
matchElements: function(elements, expression) {
- var selector = new Selector(expression);
- return elements.select(selector.match.bind(selector)).map(Element.extend);
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
},
findElement: function(elements, expression, index) {
- if (typeof expression == 'number') index = expression, expression = false;
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
return Selector.matchElements(elements, expression || '*')[index || 0];
},
findChildElements: function(element, expressions) {
- return expressions.map(function(expression) {
- return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) {
- var selector = new Selector(expr);
- return results.inject([], function(elements, result) {
- return elements.concat(selector.findElements(result || element));
- });
- });
- }).flatten();
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
}
});
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
function $$() {
return Selector.findChildElements(document, $A(arguments));
}
@@ -1876,13 +3378,19 @@
return form;
},
- serializeElements: function(elements, getHash) {
- var data = elements.inject({}, function(result, element) {
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
if (!element.disabled && element.name) {
- var key = element.name, value = $(element).getValue();
- if (value != undefined) {
- if (result[key]) {
- if (result[key].constructor != Array) result[key] = [result[key]];
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
result[key].push(value);
}
else result[key] = value;
@@ -1891,13 +3399,13 @@
return result;
});
- return getHash ? data : Hash.toQueryString(data);
+ return options.hash ? data : Object.toQueryString(data);
}
};
Form.Methods = {
- serialize: function(form, getHash) {
- return Form.serializeElements(Form.getElements(form), getHash);
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
},
getElements: function(form) {
@@ -1928,37 +3436,54 @@
disable: function(form) {
form = $(form);
- form.getElements().each(function(element) {
- element.blur();
- element.disabled = 'true';
- });
+ Form.getElements(form).invoke('disable');
return form;
},
enable: function(form) {
form = $(form);
- form.getElements().each(function(element) {
- element.disabled = '';
- });
+ Form.getElements(form).invoke('enable');
return form;
},
findFirstElement: function(form) {
- return $(form).getElements().find(function(element) {
- return element.type != 'hidden' && !element.disabled &&
- ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
});
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
},
focusFirstElement: function(form) {
form = $(form);
form.findFirstElement().activate();
return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
}
-}
+};
-Object.extend(Form, Form.Methods);
-
/*--------------------------------------------------------------------------*/
Form.Element = {
@@ -1971,7 +3496,7 @@
$(element).select();
return element;
}
-}
+};
Form.Element.Methods = {
serialize: function(element) {
@@ -1979,9 +3504,9 @@
if (!element.disabled && element.name) {
var value = element.getValue();
if (value != undefined) {
- var pair = {};
+ var pair = { };
pair[element.name] = value;
- return Hash.toQueryString(pair);
+ return Object.toQueryString(pair);
}
}
return '';
@@ -1993,6 +3518,13 @@
return Form.Element.Serializers[method](element);
},
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
clear: function(element) {
$(element).value = '';
return element;
@@ -2004,55 +3536,75 @@
activate: function(element) {
element = $(element);
- element.focus();
- if (element.select && ( element.tagName.toLowerCase() != 'input' ||
- !['button', 'reset', 'submit'].include(element.type) ) )
- element.select();
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
return element;
},
disable: function(element) {
element = $(element);
+ element.blur();
element.disabled = true;
return element;
},
enable: function(element) {
element = $(element);
- element.blur();
element.disabled = false;
return element;
}
-}
+};
-Object.extend(Form.Element, Form.Element.Methods);
+/*--------------------------------------------------------------------------*/
+
var Field = Form.Element;
-var $F = Form.Element.getValue;
+var $F = Form.Element.Methods.getValue;
/*--------------------------------------------------------------------------*/
Form.Element.Serializers = {
- input: function(element) {
+ input: function(element, value) {
switch (element.type.toLowerCase()) {
case 'checkbox':
case 'radio':
- return Form.Element.Serializers.inputSelector(element);
+ return Form.Element.Serializers.inputSelector(element, value);
default:
- return Form.Element.Serializers.textarea(element);
+ return Form.Element.Serializers.textarea(element, value);
}
},
- inputSelector: function(element) {
- return element.checked ? element.value : null;
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
},
- textarea: function(element) {
- return element.value;
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
},
- select: function(element) {
- return this[element.type == 'select-one' ?
- 'selectOne' : 'selectMany'](element);
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
},
selectOne: function(element) {
@@ -2075,45 +3627,34 @@
// extend element because hasAttribute may not be native
return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
}
-}
+};
/*--------------------------------------------------------------------------*/
-Abstract.TimedObserver = function() {}
-Abstract.TimedObserver.prototype = {
- initialize: function(element, frequency, callback) {
- this.frequency = frequency;
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
this.element = $(element);
- this.callback = callback;
-
this.lastValue = this.getValue();
- this.registerCallback();
},
- registerCallback: function() {
- setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
- },
-
- onTimerEvent: function() {
+ execute: function() {
var value = this.getValue();
- var changed = ('string' == typeof this.lastValue && 'string' == typeof value
- ? this.lastValue != value : String(this.lastValue) != String(value));
- if (changed) {
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
this.callback(this.element, value);
this.lastValue = value;
}
}
-}
+});
-Form.Element.Observer = Class.create();
-Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
getValue: function() {
return Form.Element.getValue(this.element);
}
});
-Form.Observer = Class.create();
-Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+Form.Observer = Class.create(Abstract.TimedObserver, {
getValue: function() {
return Form.serialize(this.element);
}
@@ -2121,8 +3662,7 @@
/*--------------------------------------------------------------------------*/
-Abstract.EventObserver = function() {}
-Abstract.EventObserver.prototype = {
+Abstract.EventObserver = Class.create({
initialize: function(element, callback) {
this.element = $(element);
this.callback = callback;
@@ -2143,7 +3683,7 @@
},
registerFormCallbacks: function() {
- Form.getElements(this.element).each(this.registerCallback.bind(this));
+ Form.getElements(this.element).each(this.registerCallback, this);
},
registerCallback: function(element) {
@@ -2159,24 +3699,20 @@
}
}
}
-}
+});
-Form.Element.EventObserver = Class.create();
-Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
getValue: function() {
return Form.Element.getValue(this.element);
}
});
-Form.EventObserver = Class.create();
-Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+Form.EventObserver = Class.create(Abstract.EventObserver, {
getValue: function() {
return Form.serialize(this.element);
}
});
-if (!window.Event) {
- var Event = new Object();
-}
+if (!window.Event) var Event = { };
Object.extend(Event, {
KEY_BACKSPACE: 8,
@@ -2192,102 +3728,339 @@
KEY_END: 35,
KEY_PAGEUP: 33,
KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
- element: function(event) {
- return event.target || event.srcElement;
- },
+ cache: { },
- isLeftClick: function(event) {
- return (((event.which) && (event.which == 1)) ||
- ((event.button) && (event.button == 1)));
- },
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
- pointerX: function(event) {
- return event.pageX || (event.clientX +
- (document.documentElement.scrollLeft || document.body.scrollLeft));
- },
+Event.Methods = (function() {
+ var isButton;
- pointerY: function(event) {
- return event.pageY || (event.clientY +
- (document.documentElement.scrollTop || document.body.scrollTop));
- },
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
- stop: function(event) {
- if (event.preventDefault) {
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
event.preventDefault();
event.stopPropagation();
- } else {
- event.returnValue = false;
- event.cancelBubble = true;
+ event.stopped = true;
}
- },
+ };
+})();
- // find the first node with the given tagName, starting from the
- // node the event was triggered on; traverses the DOM upwards
- findElement: function(event, tagName) {
- var element = Event.element(event);
- while (element.parentNode && (!element.tagName ||
- (element.tagName.toUpperCase() != tagName.toUpperCase())))
- element = element.parentNode;
- return element;
- },
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
- observers: false,
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
- _observeAndCache: function(element, name, observer, useCapture) {
- if (!this.observers) this.observers = [];
- if (element.addEventListener) {
- this.observers.push([element, name, observer, useCapture]);
- element.addEventListener(name, observer, useCapture);
- } else if (element.attachEvent) {
- this.observers.push([element, name, observer, useCapture]);
- element.attachEvent('on' + name, observer);
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
}
- },
+ };
+})());
- unloadCache: function() {
- if (!Event.observers) return;
- for (var i = 0, length = Event.observers.length; i < length; i++) {
- Event.stopObserving.apply(this, Event.observers[i]);
- Event.observers[i][0] = null;
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
}
- Event.observers = false;
- },
- observe: function(element, name, observer, useCapture) {
- element = $(element);
- useCapture = useCapture || false;
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
- if (name == 'keypress' &&
- (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
- || element.attachEvent))
- name = 'keydown';
+Hash.toQueryString = Object.toQueryString;
- Event._observeAndCache(element, name, observer, useCapture);
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
},
- stopObserving: function(element, name, observer, useCapture) {
- element = $(element);
- useCapture = useCapture || false;
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
- if (name == 'keypress' &&
- (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
- || element.detachEvent))
- name = 'keydown';
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
- if (element.removeEventListener) {
- element.removeEventListener(name, observer, useCapture);
- } else if (element.detachEvent) {
- try {
- element.detachEvent('on' + name, observer);
- } catch (e) {}
- }
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
}
-});
+};
-/* prevent memory leaks in IE */
-if (navigator.appVersion.match(/\bMSIE\b/))
- Event.observe(window, 'unload', Event.unloadCache, false);
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
var Position = {
// set to true if needed, warning: firefox performance problems
// NOT neeeded for page scrolling, only if draggable contained in
@@ -2307,59 +4080,13 @@
|| 0;
},
- realOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.scrollTop || 0;
- valueL += element.scrollLeft || 0;
- element = element.parentNode;
- } while (element);
- return [valueL, valueT];
- },
-
- cumulativeOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- } while (element);
- return [valueL, valueT];
- },
-
- positionedOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- if (element) {
- if(element.tagName=='BODY') break;
- var p = Element.getStyle(element, 'position');
- if (p == 'relative' || p == 'absolute') break;
- }
- } while (element);
- return [valueL, valueT];
- },
-
- offsetParent: function(element) {
- if (element.offsetParent) return element.offsetParent;
- if (element == document.body) return element;
-
- while ((element = element.parentNode) && element != document.body)
- if (Element.getStyle(element, 'position') != 'static')
- return element;
-
- return document.body;
- },
-
// caches x/y coordinate pair to use with overlap
within: function(element, x, y) {
if (this.includeScrollOffsets)
return this.withinIncludingScrolloffsets(element, x, y);
this.xcomp = x;
this.ycomp = y;
- this.offset = this.cumulativeOffset(element);
+ this.offset = Element.cumulativeOffset(element);
return (y >= this.offset[1] &&
y < this.offset[1] + element.offsetHeight &&
@@ -2368,11 +4095,11 @@
},
withinIncludingScrolloffsets: function(element, x, y) {
- var offsetcache = this.realOffset(element);
+ var offsetcache = Element.cumulativeScrollOffset(element);
this.xcomp = x + offsetcache[0] - this.deltaX;
this.ycomp = y + offsetcache[1] - this.deltaY;
- this.offset = this.cumulativeOffset(element);
+ this.offset = Element.cumulativeOffset(element);
return (this.ycomp >= this.offset[1] &&
this.ycomp < this.offset[1] + element.offsetHeight &&
@@ -2391,125 +4118,104 @@
element.offsetWidth;
},
- page: function(forElement) {
- var valueT = 0, valueL = 0;
+ // Deprecation layer -- use newer Element methods now (1.5.2).
- var element = forElement;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
+ cumulativeOffset: Element.Methods.cumulativeOffset,
- // Safari fix
- if (element.offsetParent==document.body)
- if (Element.getStyle(element,'position')=='absolute') break;
+ positionedOffset: Element.Methods.positionedOffset,
- } while (element = element.offsetParent);
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
- element = forElement;
- do {
- if (!window.opera || element.tagName=='BODY') {
- valueT -= element.scrollTop || 0;
- valueL -= element.scrollLeft || 0;
- }
- } while (element = element.parentNode);
-
- return [valueL, valueT];
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
},
- clone: function(source, target) {
- var options = Object.extend({
- setLeft: true,
- setTop: true,
- setWidth: true,
- setHeight: true,
- offsetTop: 0,
- offsetLeft: 0
- }, arguments[2] || {})
+ realOffset: Element.Methods.cumulativeScrollOffset,
- // find page position of source
- source = $(source);
- var p = Position.page(source);
+ offsetParent: Element.Methods.getOffsetParent,
- // find coordinate system to use
- target = $(target);
- var delta = [0, 0];
- var parent = null;
- // delta [0,0] will do fine with position: fixed elements,
- // position:absolute needs offsetParent deltas
- if (Element.getStyle(target,'position') == 'absolute') {
- parent = Position.offsetParent(target);
- delta = Position.page(parent);
- }
+ page: Element.Methods.viewportOffset,
- // correct by body offsets (fixes Safari)
- if (parent == document.body) {
- delta[0] -= document.body.offsetLeft;
- delta[1] -= document.body.offsetTop;
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
}
+ return elements;
+ };
- // set position
- if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
- if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
- if(options.setWidth) target.style.width = source.offsetWidth + 'px';
- if(options.setHeight) target.style.height = source.offsetHeight + 'px';
- },
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
- absolutize: function(element) {
- element = $(element);
- if (element.style.position == 'absolute') return;
- Position.prepare();
+/*--------------------------------------------------------------------------*/
- var offsets = Position.positionedOffset(element);
- var top = offsets[1];
- var left = offsets[0];
- var width = element.clientWidth;
- var height = element.clientHeight;
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
- element._originalLeft = left - parseFloat(element.style.left || 0);
- element._originalTop = top - parseFloat(element.style.top || 0);
- element._originalWidth = element.style.width;
- element._originalHeight = element.style.height;
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
- element.style.position = 'absolute';
- element.style.top = top + 'px';
- element.style.left = left + 'px';
- element.style.width = width + 'px';
- element.style.height = height + 'px';
+ set: function(className) {
+ this.element.className = className;
},
- relativize: function(element) {
- element = $(element);
- if (element.style.position == 'relative') return;
- Position.prepare();
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
- element.style.position = 'relative';
- var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
- var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
- element.style.top = top + 'px';
- element.style.left = left + 'px';
- element.style.height = element._originalHeight;
- element.style.width = element._originalWidth;
+ toString: function() {
+ return $A(this).join(' ');
}
-}
+};
-// Safari returns margins on body which is incorrect if the child is absolutely
-// positioned. For performance reasons, redefine Position.cumulativeOffset for
-// KHTML/WebKit only.
-if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
- Position.cumulativeOffset = function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- if (element.offsetParent == document.body)
- if (Element.getStyle(element, 'position') == 'absolute') break;
+Object.extend(Element.ClassNames.prototype, Enumerable);
- element = element.offsetParent;
- } while (element);
+/*--------------------------------------------------------------------------*/
- return [valueL, valueT];
- }
-}
-
Element.addMethods();
\ No newline at end of file
Modified: branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/scriptaculous.js
===================================================================
--- branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/scriptaculous.js 2008-04-25 00:34:57 UTC (rev 10715)
+++ branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/scriptaculous.js 2008-04-25 01:37:24 UTC (rev 10716)
@@ -1,6 +1,6 @@
-// script.aculo.us scriptaculous.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
+// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
@@ -24,25 +24,32 @@
// For details, see the script.aculo.us web site: http://script.aculo.us/
var Scriptaculous = {
- Version: '1.7.0',
+ Version: '1.8.1',
require: function(libraryName) {
// inserting via DOM fails in Safari 2.0, so brute force approach
- document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
},
+ REQUIRED_PROTOTYPE: '1.6.0',
load: function() {
+ function convertVersionString(versionString){
+ var r = versionString.split('.');
+ return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ }
+
if((typeof Prototype=='undefined') ||
(typeof Element == 'undefined') ||
(typeof Element.Methods=='undefined') ||
- parseFloat(Prototype.Version.split(".")[0] + "." +
- Prototype.Version.split(".")[1]) < 1.5)
- throw("script.aculo.us requires the Prototype JavaScript framework >= 1.5.0");
+ (convertVersionString(Prototype.Version) <
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+ Scriptaculous.REQUIRED_PROTOTYPE);
$A(document.getElementsByTagName("script")).findAll( function(s) {
return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
}).each( function(s) {
var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
var includes = s.src.match(/\?.*load=([a-z,]*)/);
- (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider').split(',').each(
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
function(include) { Scriptaculous.require(path+include+'.js') });
});
}
Modified: branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/slider.js
===================================================================
--- branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/slider.js 2008-04-25 00:34:57 UTC (rev 10715)
+++ branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/slider.js 2008-04-25 01:37:24 UTC (rev 10716)
@@ -1,12 +1,11 @@
-// script.aculo.us slider.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
+// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
-// Copyright (c) 2005, 2006 Marty Haught, Thomas Fuchs
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
-if(!Control) var Control = {};
-Control.Slider = Class.create();
+if (!Control) var Control = { };
// options:
// axis: 'vertical', or 'horizontal' (default)
@@ -14,18 +13,18 @@
// callbacks:
// onChange(value)
// onSlide(value)
-Control.Slider.prototype = {
+Control.Slider = Class.create({
initialize: function(handle, track, options) {
var slider = this;
- if(handle instanceof Array) {
+ if (Object.isArray(handle)) {
this.handles = handle.collect( function(e) { return $(e) });
} else {
this.handles = [$(handle)];
}
this.track = $(track);
- this.options = options || {};
+ this.options = options || { };
this.axis = this.options.axis || 'horizontal';
this.increment = this.options.increment || 1;
@@ -59,11 +58,11 @@
this.dragging = false;
this.disabled = false;
- if(this.options.disabled) this.setDisabled();
+ if (this.options.disabled) this.setDisabled();
// Allowed values array
this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
- if(this.allowedValues) {
+ if (this.allowedValues) {
this.minimum = this.allowedValues.min();
this.maximum = this.allowedValues.max();
}
@@ -76,16 +75,15 @@
this.handles.each( function(h,i) {
i = slider.handles.length-1-i;
slider.setValue(parseFloat(
- (slider.options.sliderValue instanceof Array ?
+ (Object.isArray(slider.options.sliderValue) ?
slider.options.sliderValue[i] : slider.options.sliderValue) ||
slider.range.start), i);
- Element.makePositioned(h); // fix IE
- Event.observe(h, "mousedown", slider.eventMouseDown);
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
});
- Event.observe(this.track, "mousedown", this.eventMouseDown);
- Event.observe(document, "mouseup", this.eventMouseUp);
- Event.observe(document, "mousemove", this.eventMouseMove);
+ this.track.observe("mousedown", this.eventMouseDown);
+ document.observe("mouseup", this.eventMouseUp);
+ document.observe("mousemove", this.eventMouseMove);
this.initialized = true;
},
@@ -105,36 +103,36 @@
this.disabled = false;
},
getNearestValue: function(value){
- if(this.allowedValues){
- if(value >= this.allowedValues.max()) return(this.allowedValues.max());
- if(value <= this.allowedValues.min()) return(this.allowedValues.min());
+ if (this.allowedValues){
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
var offset = Math.abs(this.allowedValues[0] - value);
var newValue = this.allowedValues[0];
this.allowedValues.each( function(v) {
var currentOffset = Math.abs(v - value);
- if(currentOffset <= offset){
+ if (currentOffset <= offset){
newValue = v;
offset = currentOffset;
}
});
return newValue;
}
- if(value > this.range.end) return this.range.end;
- if(value < this.range.start) return this.range.start;
+ if (value > this.range.end) return this.range.end;
+ if (value < this.range.start) return this.range.start;
return value;
},
setValue: function(sliderValue, handleIdx){
- if(!this.active) {
+ if (!this.active) {
this.activeHandleIdx = handleIdx || 0;
this.activeHandle = this.handles[this.activeHandleIdx];
this.updateStyles();
}
handleIdx = handleIdx || this.activeHandleIdx || 0;
- if(this.initialized && this.restricted) {
- if((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+ if (this.initialized && this.restricted) {
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
sliderValue = this.values[handleIdx-1];
- if((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
sliderValue = this.values[handleIdx+1];
}
sliderValue = this.getNearestValue(sliderValue);
@@ -145,7 +143,7 @@
this.translateToPx(sliderValue);
this.drawSpans();
- if(!this.dragging || !this.event) this.updateFinished();
+ if (!this.dragging || !this.event) this.updateFinished();
},
setValueBy: function(delta, handleIdx) {
this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
@@ -173,24 +171,24 @@
(this.track.offsetHeight != 0 ? this.track.offsetHeight :
this.track.style.height.replace(/px$/,"")) - this.alignY :
(this.track.offsetWidth != 0 ? this.track.offsetWidth :
- this.track.style.width.replace(/px$/,"")) - this.alignY);
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
},
isVertical: function(){
return (this.axis == 'vertical');
},
drawSpans: function() {
var slider = this;
- if(this.spans)
+ if (this.spans)
$R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
- if(this.options.startSpan)
+ if (this.options.startSpan)
this.setSpan(this.options.startSpan,
$R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
- if(this.options.endSpan)
+ if (this.options.endSpan)
this.setSpan(this.options.endSpan,
$R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
},
setSpan: function(span, range) {
- if(this.isVertical()) {
+ if (this.isVertical()) {
span.style.top = this.translateToPx(range.start);
span.style.height = this.translateToPx(range.end - range.start + this.range.start);
} else {
@@ -203,14 +201,14 @@
Element.addClassName(this.activeHandle, 'selected');
},
startDrag: function(event) {
- if(Event.isLeftClick(event)) {
- if(!this.disabled){
+ if (Event.isLeftClick(event)) {
+ if (!this.disabled){
this.active = true;
var handle = Event.element(event);
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var track = handle;
- if(track==this.track) {
+ if (track==this.track) {
var offsets = Position.cumulativeOffset(this.track);
this.event = event;
this.setValue(this.translateToValue(
@@ -224,7 +222,7 @@
while((this.handles.indexOf(handle) == -1) && handle.parentNode)
handle = handle.parentNode;
- if(this.handles.indexOf(handle)!=-1) {
+ if (this.handles.indexOf(handle)!=-1) {
this.activeHandle = handle;
this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
this.updateStyles();
@@ -239,11 +237,10 @@
}
},
update: function(event) {
- if(this.active) {
- if(!this.dragging) this.dragging = true;
+ if (this.active) {
+ if (!this.dragging) this.dragging = true;
this.draw(event);
- // fix AppleWebKit rendering
- if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
Event.stop(event);
}
},
@@ -254,11 +251,11 @@
pointer[1] -= this.offsetY + offsets[1];
this.event = event;
this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
- if(this.initialized && this.options.onSlide)
+ if (this.initialized && this.options.onSlide)
this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
},
endDrag: function(event) {
- if(this.active && this.dragging) {
+ if (this.active && this.dragging) {
this.finishDrag(event, true);
Event.stop(event);
}
@@ -271,8 +268,8 @@
this.updateFinished();
},
updateFinished: function() {
- if(this.initialized && this.options.onChange)
+ if (this.initialized && this.options.onChange)
this.options.onChange(this.values.length>1 ? this.values : this.value, this);
this.event = null;
}
-}
\ No newline at end of file
+});
Modified: branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/unittest.js
===================================================================
--- branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/unittest.js 2008-04-25 00:34:57 UTC (rev 10715)
+++ branches/JBoss_Portal_Branch_2_6/theme/src/bin/portal-ajax-war/dyna/unittest.js 2008-04-25 01:37:24 UTC (rev 10716)
@@ -1,8 +1,8 @@
-// script.aculo.us unittest.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
+// script.aculo.us unittest.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// (c) 2005, 2006 Jon Tirsen (http://www.tirsen.com)
-// (c) 2005, 2006 Michael Schuerig (http://www.schuerig.de/michael/)
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// (c) 2005-2007 Michael Schuerig (http://www.schuerig.de/michael/)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
@@ -524,15 +524,19 @@
shouldNotBe: 'assertReturnsFalse',
shouldRespondTo: 'assertRespondsTo'
};
- Test.BDDMethods = {};
- for(m in METHODMAP) {
- Test.BDDMethods[m] = eval(
- 'function(){'+
- 'var args = $A(arguments);'+
- 'var scope = args.shift();'+
- 'scope.'+METHODMAP[m]+'.apply(scope,(args || []).concat([this])); }');
+ var makeAssertion = function(assertion, args, object) {
+ this[assertion].apply(this,(args || []).concat([object]));
}
- [Array.prototype, String.prototype, Number.prototype].each(
+
+ Test.BDDMethods = {};
+ $H(METHODMAP).each(function(pair) {
+ Test.BDDMethods[pair.key] = function() {
+ var args = $A(arguments);
+ var scope = args.shift();
+ makeAssertion.apply(scope, [pair.value, args, this]); };
+ });
+
+ [Array.prototype, String.prototype, Number.prototype, Boolean.prototype].each(
function(p){ Object.extend(p, Test.BDDMethods) }
);
}
Modified: branches/JBoss_Portal_Branch_2_6/theme/src/bin/theme-test-war/core/lib/prototype.js
===================================================================
--- branches/JBoss_Portal_Branch_2_6/theme/src/bin/theme-test-war/core/lib/prototype.js 2008-04-25 00:34:57 UTC (rev 10715)
+++ branches/JBoss_Portal_Branch_2_6/theme/src/bin/theme-test-war/core/lib/prototype.js 2008-04-25 01:37:24 UTC (rev 10716)
@@ -1,98 +1,289 @@
-/* Prototype JavaScript framework, version 1.5.0_rc0
- * (c) 2005 Sam Stephenson <sam(a)conio.net>
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style license.
- * For details, see the Prototype web site: http://prototype.conio.net/
+ * For details, see the Prototype web site: http://www.prototypejs.org/
*
-/*--------------------------------------------------------------------------*/
+ *--------------------------------------------------------------------------*/
var Prototype = {
- Version: '1.5.0_rc0',
- ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
+ Version: '1.6.0.2',
- emptyFunction: function() {},
- K: function(x) {return x}
-}
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
var Class = {
create: function() {
- return function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
this.initialize.apply(this, arguments);
}
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
}
-}
+};
-var Abstract = new Object();
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
Object.extend = function(destination, source) {
- for (var property in source) {
+ for (var property in source)
destination[property] = source[property];
- }
return destination;
-}
+};
-Object.inspect = function(object) {
- try {
- if (object == undefined) return 'undefined';
- if (object == null) return 'null';
- return object.inspect ? object.inspect() : object.toString();
- } catch (e) {
- if (e instanceof RangeError) return '...';
- throw e;
- }
-}
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
-Function.prototype.bind = function() {
- var __method = this, args = $A(arguments), object = args.shift();
- return function() {
- return __method.apply(object, args.concat($A(arguments)));
- }
-}
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
-Function.prototype.bindAsEventListener = function(object) {
- var __method = this;
- return function(event) {
- return __method.call(object, event || window.event);
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
}
-}
+});
-Object.extend(Number.prototype, {
- toColorPart: function() {
- var digits = this.toString(16);
- if (this < 16) return '0' + digits;
- return digits;
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
},
- succ: function() {
- return this + 1;
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
},
- times: function(iterator) {
- $R(0, this, true).each(iterator);
- return this;
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
}
});
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
var Try = {
these: function() {
var returnValue;
- for (var i = 0; i < arguments.length; i++) {
+ for (var i = 0, length = arguments.length; i < length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
break;
- } catch (e) {}
+ } catch (e) { }
}
return returnValue;
}
-}
+};
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
/*--------------------------------------------------------------------------*/
-var PeriodicalExecuter = Class.create();
-PeriodicalExecuter.prototype = {
+var PeriodicalExecuter = Class.create({
initialize: function(callback, frequency) {
this.callback = callback;
this.frequency = frequency;
@@ -102,20 +293,44 @@
},
registerCallback: function() {
- setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
onTimerEvent: function() {
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
- this.callback();
+ this.execute();
} finally {
this.currentlyExecuting = false;
}
}
}
-}
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
Object.extend(String.prototype, {
gsub: function(pattern, replacement) {
var result = '', source = this, match;
@@ -124,7 +339,7 @@
while (source.length > 0) {
if (match = source.match(pattern)) {
result += source.slice(0, match.index);
- result += (replacement(match) || '').toString();
+ result += String.interpret(replacement(match));
source = source.slice(match.index + match[0].length);
} else {
result += source, source = '';
@@ -135,7 +350,7 @@
sub: function(pattern, replacement, count) {
replacement = this.gsub.prepareReplacement(replacement);
- count = count === undefined ? 1 : count;
+ count = Object.isUndefined(count) ? 1 : count;
return this.gsub(pattern, function(match) {
if (--count < 0) return match[0];
@@ -145,14 +360,14 @@
scan: function(pattern, iterator) {
this.gsub(pattern, iterator);
- return this;
+ return String(this);
},
truncate: function(length, truncation) {
length = length || 30;
- truncation = truncation === undefined ? '...' : truncation;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
return this.length > length ?
- this.slice(0, length - truncation.length) + truncation : this;
+ this.slice(0, length - truncation.length) + truncation : String(this);
},
strip: function() {
@@ -180,24 +395,36 @@
},
escapeHTML: function() {
- var div = document.createElement('div');
- var text = document.createTextNode(this);
- div.appendChild(text);
- return div.innerHTML;
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
},
unescapeHTML: function() {
- var div = document.createElement('div');
+ var div = new Element('div');
div.innerHTML = this.stripTags();
- return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
},
- toQueryParams: function() {
- var pairs = this.match(/^\??(.*)$/)[1].split('&');
- return pairs.inject({}, function(params, pairString) {
- var pair = pairString.split('=');
- params[pair[0]] = pair[1];
- return params;
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
});
},
@@ -205,90 +432,204 @@
return this.split('');
},
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
camelize: function() {
- var oStringList = this.split('-');
- if (oStringList.length == 1) return oStringList[0];
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
- var camelizedString = this.indexOf('-') == 0
- ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
- : oStringList[0];
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
- for (var i = 1, len = oStringList.length; i < len; i++) {
- var s = oStringList[i];
- camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
- }
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
- return camelizedString;
+ return camelized;
},
- inspect: function() {
- return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'";
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
}
});
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ }
+});
+
String.prototype.gsub.prepareReplacement = function(replacement) {
- if (typeof replacement == 'function') return replacement;
+ if (Object.isFunction(replacement)) return replacement;
var template = new Template(replacement);
return function(match) { return template.evaluate(match) };
-}
+};
String.prototype.parseQuery = String.prototype.toQueryParams;
-var Template = Class.create();
-Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
-Template.prototype = {
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
initialize: function(template, pattern) {
this.template = template.toString();
- this.pattern = pattern || Template.Pattern;
+ this.pattern = pattern || Template.Pattern;
},
evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
return this.template.gsub(this.pattern, function(match) {
- var before = match[1];
+ if (object == null) return '';
+
+ var before = match[1] || '';
if (before == '\\') return match[2];
- return before + (object[match[3]] || '').toString();
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
});
}
-}
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
-var $break = new Object();
-var $continue = new Object();
+var $break = { };
var Enumerable = {
- each: function(iterator) {
+ each: function(iterator, context) {
var index = 0;
+ iterator = iterator.bind(context);
try {
this._each(function(value) {
- try {
- iterator(value, index++);
- } catch (e) {
- if (e != $continue) throw e;
- }
+ iterator(value, index++);
});
} catch (e) {
if (e != $break) throw e;
}
+ return this;
},
- all: function(iterator) {
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var result = true;
this.each(function(value, index) {
- result = result && !!(iterator || Prototype.K)(value, index);
+ result = result && !!iterator(value, index);
if (!result) throw $break;
});
return result;
},
- any: function(iterator) {
- var result = true;
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
this.each(function(value, index) {
- if (result = !!(iterator || Prototype.K)(value, index))
+ if (result = !!iterator(value, index))
throw $break;
});
return result;
},
- collect: function(iterator) {
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var results = [];
this.each(function(value, index) {
results.push(iterator(value, index));
@@ -296,7 +637,8 @@
return results;
},
- detect: function (iterator) {
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
var result;
this.each(function(value, index) {
if (iterator(value, index)) {
@@ -307,7 +649,8 @@
return result;
},
- findAll: function(iterator) {
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
var results = [];
this.each(function(value, index) {
if (iterator(value, index))
@@ -316,17 +659,24 @@
return results;
},
- grep: function(pattern, iterator) {
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
this.each(function(value, index) {
- var stringValue = value.toString();
- if (stringValue.match(pattern))
- results.push((iterator || Prototype.K)(value, index));
- })
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
return results;
},
include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
var found = false;
this.each(function(value) {
if (value == object) {
@@ -337,7 +687,16 @@
return found;
},
- inject: function(memo, iterator) {
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
this.each(function(value, index) {
memo = iterator(memo, value, index);
});
@@ -346,35 +705,38 @@
invoke: function(method) {
var args = $A(arguments).slice(1);
- return this.collect(function(value) {
+ return this.map(function(value) {
return value[method].apply(value, args);
});
},
- max: function(iterator) {
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var result;
this.each(function(value, index) {
- value = (iterator || Prototype.K)(value, index);
- if (result == undefined || value >= result)
+ value = iterator(value, index);
+ if (result == null || value >= result)
result = value;
});
return result;
},
- min: function(iterator) {
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var result;
this.each(function(value, index) {
- value = (iterator || Prototype.K)(value, index);
- if (result == undefined || value < result)
+ value = iterator(value, index);
+ if (result == null || value < result)
result = value;
});
return result;
},
- partition: function(iterator) {
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var trues = [], falses = [];
this.each(function(value, index) {
- ((iterator || Prototype.K)(value, index) ?
+ (iterator(value, index) ?
trues : falses).push(value);
});
return [trues, falses];
@@ -382,13 +744,14 @@
pluck: function(property) {
var results = [];
- this.each(function(value, index) {
+ this.each(function(value) {
results.push(value[property]);
});
return results;
},
- reject: function(iterator) {
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
var results = [];
this.each(function(value, index) {
if (!iterator(value, index))
@@ -397,8 +760,9 @@
return results;
},
- sortBy: function(iterator) {
- return this.collect(function(value, index) {
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
return {value: value, criteria: iterator(value, index)};
}).sort(function(left, right) {
var a = left.criteria, b = right.criteria;
@@ -407,12 +771,12 @@
},
toArray: function() {
- return this.collect(Prototype.K);
+ return this.map();
},
zip: function() {
var iterator = Prototype.K, args = $A(arguments);
- if (typeof args.last() == 'function')
+ if (Object.isFunction(args.last()))
iterator = args.pop();
var collections = [this].concat(args).map($A);
@@ -421,38 +785,53 @@
});
},
+ size: function() {
+ return this.toArray().length;
+ },
+
inspect: function() {
return '#<Enumerable:' + this.toArray().inspect() + '>';
}
-}
+};
Object.extend(Enumerable, {
map: Enumerable.collect,
find: Enumerable.detect,
select: Enumerable.findAll,
+ filter: Enumerable.findAll,
member: Enumerable.include,
- entries: Enumerable.toArray
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
});
-var $A = Array.from = function(iterable) {
+function $A(iterable) {
if (!iterable) return [];
- if (iterable.toArray) {
- return iterable.toArray();
- } else {
- var results = [];
- for (var i = 0; i < iterable.length; i++)
- results.push(iterable[i]);
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
return results;
- }
+ };
}
+Array.from = $A;
+
Object.extend(Array.prototype, Enumerable);
-if (!Array.prototype._reverse)
- Array.prototype._reverse = Array.prototype.reverse;
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
Object.extend(Array.prototype, {
_each: function(iterator) {
- for (var i = 0; i < this.length; i++)
+ for (var i = 0, length = this.length; i < length; i++)
iterator(this[i]);
},
@@ -471,13 +850,13 @@
compact: function() {
return this.select(function(value) {
- return value != undefined || value != null;
+ return value != null;
});
},
flatten: function() {
return this.inject([], function(array, value) {
- return array.concat(value && value.constructor == Array ?
+ return array.concat(Object.isArray(value) ?
value.flatten() : [value]);
});
},
@@ -489,70 +868,219 @@
});
},
- indexOf: function(object) {
- for (var i = 0; i < this.length; i++)
- if (this[i] == object) return i;
- return -1;
- },
-
reverse: function(inline) {
return (inline !== false ? this : this.toArray())._reverse();
},
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
inspect: function() {
return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
}
});
-var Hash = {
- _each: function(iterator) {
- for (var key in this) {
- var value = this[key];
- if (typeof value == 'function') continue;
- var pair = [key, value];
- pair.key = key;
- pair.value = value;
- iterator(pair);
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
}
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
},
- keys: function() {
- return this.pluck('key');
+ succ: function() {
+ return this + 1;
},
- values: function() {
- return this.pluck('value');
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
},
- merge: function(hash) {
- return $H(hash).inject($H(this), function(mergedHash, pair) {
- mergedHash[pair.key] = pair.value;
- return mergedHash;
- });
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
},
- toQueryString: function() {
- return this.map(function(pair) {
- return pair.map(encodeURIComponent).join('=');
- }).join('&');
- },
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
- inspect: function() {
- return '#<Hash:{' + this.map(function(pair) {
- return pair.map(Object.inspect).join(': ');
- }).join(', ') + '}>';
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
}
-}
-function $H(object) {
- var hash = Object.extend({}, object || {});
- Object.extend(hash, Enumerable);
- Object.extend(hash, Hash);
- return hash;
-}
-ObjectRange = Class.create();
-Object.extend(ObjectRange.prototype, Enumerable);
-Object.extend(ObjectRange.prototype, {
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
initialize: function(start, end, exclusive) {
this.start = start;
this.end = end;
@@ -561,10 +1089,10 @@
_each: function(iterator) {
var value = this.start;
- do {
+ while (this.include(value)) {
iterator(value);
value = value.succ();
- } while (this.include(value));
+ }
},
include: function(value) {
@@ -578,7 +1106,7 @@
var $R = function(start, end, exclusive) {
return new ObjectRange(start, end, exclusive);
-}
+};
var Ajax = {
getTransport: function() {
@@ -590,7 +1118,7 @@
},
activeRequestCount: 0
-}
+};
Ajax.Responders = {
responders: [],
@@ -599,21 +1127,21 @@
this.responders._each(iterator);
},
- register: function(responderToAdd) {
- if (!this.include(responderToAdd))
- this.responders.push(responderToAdd);
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
},
- unregister: function(responderToRemove) {
- this.responders = this.responders.without(responderToRemove);
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
},
dispatch: function(callback, request, transport, json) {
this.each(function(responder) {
- if (responder[callback] && typeof responder[callback] == 'function') {
+ if (Object.isFunction(responder[callback])) {
try {
responder[callback].apply(responder, [request, transport, json]);
- } catch (e) {}
+ } catch (e) { }
}
});
}
@@ -622,218 +1150,324 @@
Object.extend(Ajax.Responders, Enumerable);
Ajax.Responders.register({
- onCreate: function() {
- Ajax.activeRequestCount++;
- },
-
- onComplete: function() {
- Ajax.activeRequestCount--;
- }
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
});
-Ajax.Base = function() {};
-Ajax.Base.prototype = {
- setOptions: function(options) {
+Ajax.Base = Class.create({
+ initialize: function(options) {
this.options = {
method: 'post',
asynchronous: true,
contentType: 'application/x-www-form-urlencoded',
- parameters: ''
- }
- Object.extend(this.options, options || {});
- },
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
- responseIsSuccess: function() {
- return this.transport.status == undefined
- || this.transport.status == 0
- || (this.transport.status >= 200 && this.transport.status < 300);
- },
+ this.options.method = this.options.method.toLowerCase();
- responseIsFailure: function() {
- return !this.responseIsSuccess();
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
}
-}
+});
-Ajax.Request = Class.create();
-Ajax.Request.Events =
- ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
-Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
- initialize: function(url, options) {
+ initialize: function($super, url, options) {
+ $super(options);
this.transport = Ajax.getTransport();
- this.setOptions(options);
this.request(url);
},
request: function(url) {
- var parameters = this.options.parameters || '';
- if (parameters.length > 0) parameters += '&_=';
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
try {
- this.url = url;
- if (this.options.method == 'get' && parameters.length > 0)
- this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
- Ajax.Responders.dispatch('onCreate', this, this.transport);
-
- this.transport.open(this.options.method, this.url,
+ this.transport.open(this.method.toUpperCase(), this.url,
this.options.asynchronous);
- if (this.options.asynchronous) {
- this.transport.onreadystatechange = this.onStateChange.bind(this);
- setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
- }
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
this.setRequestHeaders();
- var body = this.options.postBody ? this.options.postBody : parameters;
- this.transport.send(this.options.method == 'post' ? body : null);
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
- } catch (e) {
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
this.dispatchException(e);
}
},
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
setRequestHeaders: function() {
- var requestHeaders =
- ['X-Requested-With', 'XMLHttpRequest',
- 'X-Prototype-Version', Prototype.Version,
- 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*'];
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
- if (this.options.method == 'post') {
- requestHeaders.push('Content-type', this.options.contentType);
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
- /* Force "Connection: close" for Mozilla browsers to work around
- * a bug where XMLHttpReqeuest sends an incorrect Content-length
- * header. See Mozilla Bugzilla #246651.
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
*/
- if (this.transport.overrideMimeType)
- requestHeaders.push('Connection', 'close');
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
}
- if (this.options.requestHeaders)
- requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
- for (var i = 0; i < requestHeaders.length; i += 2)
- this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
- },
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
- onStateChange: function() {
- var readyState = this.transport.readyState;
- if (readyState != 1)
- this.respondToReadyState(this.transport.readyState);
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
},
- header: function(name) {
- try {
- return this.transport.getResponseHeader(name);
- } catch (e) {}
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
},
- evalJSON: function() {
+ getStatus: function() {
try {
- return eval('(' + this.header('X-JSON') + ')');
- } catch (e) {}
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
},
- evalResponse: function() {
- try {
- return eval(this.transport.responseText);
- } catch (e) {
- this.dispatchException(e);
- }
- },
-
respondToReadyState: function(readyState) {
- var event = Ajax.Request.Events[readyState];
- var transport = this.transport, json = this.evalJSON();
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
- if (event == 'Complete') {
+ if (state == 'Complete') {
try {
- (this.options['on' + this.transport.status]
- || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
- || Prototype.emptyFunction)(transport, json);
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
} catch (e) {
this.dispatchException(e);
}
- if ((this.header('Content-type') || '').match(/^text\/javascript/i))
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
this.evalResponse();
}
try {
- (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
- Ajax.Responders.dispatch('on' + event, this, transport, json);
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
} catch (e) {
this.dispatchException(e);
}
- /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
- if (event == 'Complete')
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
},
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
dispatchException: function(exception) {
(this.options.onException || Prototype.emptyFunction)(this, exception);
Ajax.Responders.dispatch('onException', this, exception);
}
});
-Ajax.Updater = Class.create();
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
-Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
- initialize: function(container, url, options) {
- this.containers = {
- success: container.success ? $(container.success) : $(container),
- failure: container.failure ? $(container.failure) :
- (container.success ? null : $(container))
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
}
- this.transport = Ajax.getTransport();
- this.setOptions(options);
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
- var onComplete = this.options.onComplete || Prototype.emptyFunction;
- this.options.onComplete = (function(transport, object) {
- this.updateContent();
- onComplete(transport, object);
- }).bind(this);
+ status: 0,
+ statusText: '',
- this.request(url);
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
},
- updateContent: function() {
- var receiver = this.responseIsSuccess() ?
- this.containers.success : this.containers.failure;
- var response = this.transport.responseText;
+ getHeader: Ajax.Request.prototype.getHeader,
- if (!this.options.evalScripts)
- response = response.stripScripts();
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
- if (receiver) {
- if (this.options.insertion) {
- new this.options.insertion(receiver, response);
- } else {
- Element.update(receiver, response);
- }
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
}
+ },
- if (this.responseIsSuccess()) {
- if (this.onComplete)
- setTimeout(this.onComplete.bind(this), 10);
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
}
}
});
-Ajax.PeriodicalUpdater = Class.create();
-Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
- initialize: function(container, url, options) {
- this.setOptions(options);
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
this.onComplete = this.options.onComplete;
this.frequency = (this.options.frequency || 2);
this.decay = (this.options.decay || 1);
- this.updater = {};
+ this.updater = { };
this.container = container;
this.url = url;
@@ -846,204 +1480,462 @@
},
stop: function() {
- this.updater.onComplete = undefined;
+ this.updater.options.onComplete = undefined;
clearTimeout(this.timer);
(this.onComplete || Prototype.emptyFunction).apply(this, arguments);
},
- updateComplete: function(request) {
+ updateComplete: function(response) {
if (this.options.decay) {
- this.decay = (request.responseText == this.lastText ?
+ this.decay = (response.responseText == this.lastText ?
this.decay * this.options.decay : 1);
- this.lastText = request.responseText;
+ this.lastText = response.responseText;
}
- this.timer = setTimeout(this.onTimerEvent.bind(this),
- this.decay * this.frequency * 1000);
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
},
onTimerEvent: function() {
this.updater = new Ajax.Updater(this.container, this.url, this.options);
}
});
-function $() {
- var results = [], element;
- for (var i = 0; i < arguments.length; i++) {
- element = arguments[i];
- if (typeof element == 'string')
- element = document.getElementById(element);
- results.push(Element.extend(element));
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
}
- return results.length < 2 ? results[0] : results;
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
}
-document.getElementsByClassName = function(className, parentElement) {
- var children = ($(parentElement) || document.body).getElementsByTagName('*');
- return $A(children).inject([], function(elements, child) {
- if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
- elements.push(Element.extend(child));
- return elements;
- });
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
}
/*--------------------------------------------------------------------------*/
-if (!window.Element)
- var Element = new Object();
+if (!window.Node) var Node = { };
-Element.extend = function(element) {
- if (!element) return;
- if (_nativeExtensions) return element;
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
- if (!element._extended && element.tagName && element != window) {
- var methods = Element.Methods, cache = Element.extend.cache;
- for (property in methods) {
- var value = methods[property];
- if (typeof value == 'function')
- element[property] = cache.findOrStore(value);
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
}
- }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
- element._extended = true;
- return element;
-}
+Element.cache = { };
-Element.extend.cache = {
- findOrStore: function(value) {
- return this[value] = this[value] || function() {
- return value.apply(null, [this].concat($A(arguments)));
- }
- }
-}
-
Element.Methods = {
visible: function(element) {
return $(element).style.display != 'none';
},
- toggle: function() {
- for (var i = 0; i < arguments.length; i++) {
- var element = $(arguments[i]);
- Element[Element.visible(element) ? 'hide' : 'show'](element);
- }
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
},
- hide: function() {
- for (var i = 0; i < arguments.length; i++) {
- var element = $(arguments[i]);
- element.style.display = 'none';
- }
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
},
- show: function() {
- for (var i = 0; i < arguments.length; i++) {
- var element = $(arguments[i]);
- element.style.display = '';
- }
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
},
remove: function(element) {
element = $(element);
element.parentNode.removeChild(element);
+ return element;
},
- update: function(element, html) {
- $(element).innerHTML = html.stripScripts();
- setTimeout(function() {html.evalScripts()}, 10);
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
},
- replace: function(element, html) {
+ replace: function(element, content) {
element = $(element);
- if (element.outerHTML) {
- element.outerHTML = html.stripScripts();
- } else {
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
var range = element.ownerDocument.createRange();
- range.selectNodeContents(element);
- element.parentNode.replaceChild(
- range.createContextualFragment(html.stripScripts()), element);
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
}
- setTimeout(function() {html.evalScripts()}, 10);
+ element.parentNode.replaceChild(content, element);
+ return element;
},
- getHeight: function(element) {
+ insert: function(element, insertions) {
element = $(element);
- return element.offsetHeight;
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
},
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
classNames: function(element) {
return new Element.ClassNames(element);
},
hasClassName: function(element, className) {
if (!(element = $(element))) return;
- return Element.classNames(element).include(className);
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
},
addClassName: function(element, className) {
if (!(element = $(element))) return;
- return Element.classNames(element).add(className);
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
},
removeClassName: function(element, className) {
if (!(element = $(element))) return;
- return Element.classNames(element).remove(className);
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
},
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
// removes whitespace-only text node children
cleanWhitespace: function(element) {
element = $(element);
- for (var i = 0; i < element.childNodes.length; i++) {
- var node = element.childNodes[i];
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
- Element.remove(node);
+ element.removeChild(node);
+ node = nextNode;
}
+ return element;
},
empty: function(element) {
- return $(element).innerHTML.match(/^\s*$/);
+ return $(element).innerHTML.blank();
},
- childOf: function(element, ancestor) {
+ descendantOf: function(element, ancestor) {
element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
while (element = element.parentNode)
- if (element == ancestor) return true;
+ if (element == originalAncestor) return true;
return false;
},
scrollTo: function(element) {
element = $(element);
- var x = element.x ? element.x : element.offsetLeft,
- y = element.y ? element.y : element.offsetTop;
- window.scrollTo(x, y);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
},
getStyle: function(element, style) {
element = $(element);
- var value = element.style[style.camelize()];
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
if (!value) {
- if (document.defaultView && document.defaultView.getComputedStyle) {
- var css = document.defaultView.getComputedStyle(element, null);
- value = css ? css.getPropertyValue(style) : null;
- } else if (element.currentStyle) {
- value = element.currentStyle[style.camelize()];
- }
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
}
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
- if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
- if (Element.getStyle(element, 'position') == 'static') value = 'auto';
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
- return value == 'auto' ? null : value;
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
},
- setStyle: function(element, style) {
+ setOpacity: function(element, value) {
element = $(element);
- for (var name in style)
- element.style[name.camelize()] = style[name];
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
},
getDimensions: function(element) {
element = $(element);
- if (Element.getStyle(element, 'display') != 'none')
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
return {width: element.offsetWidth, height: element.offsetHeight};
// All *Width and *Height properties give 0 on elements with display none,
@@ -1051,12 +1943,13 @@
var els = element.style;
var originalVisibility = els.visibility;
var originalPosition = els.position;
+ var originalDisplay = els.display;
els.visibility = 'hidden';
els.position = 'absolute';
- els.display = '';
+ els.display = 'block';
var originalWidth = element.clientWidth;
var originalHeight = element.clientHeight;
- els.display = 'none';
+ els.display = originalDisplay;
els.position = originalPosition;
els.visibility = originalVisibility;
return {width: originalWidth, height: originalHeight};
@@ -1075,6 +1968,7 @@
element.style.left = 0;
}
}
+ return element;
},
undoPositioned: function(element) {
@@ -1087,518 +1981,1680 @@
element.style.bottom =
element.style.right = '';
}
+ return element;
},
makeClipping: function(element) {
element = $(element);
- if (element._overflow) return;
- element._overflow = element.style.overflow;
- if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
element.style.overflow = 'hidden';
+ return element;
},
undoClipping: function(element) {
element = $(element);
- if (element._overflow) return;
- element.style.overflow = element._overflow;
- element._overflow = undefined;
- }
-}
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
-Object.extend(Element, Element.Methods);
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
-var _nativeExtensions = false;
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
-if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
- var HTMLElement = {}
- HTMLElement.prototype = document.createElement('div').__proto__;
-}
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
-Element.addMethods = function(methods) {
- Object.extend(Element.Methods, methods || {});
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
- if(typeof HTMLElement != 'undefined') {
- var methods = Element.Methods, cache = Element.extend.cache;
- for (property in methods) {
- var value = methods[property];
- if (typeof value == 'function')
- HTMLElement.prototype[property] = cache.findOrStore(value);
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
}
- _nativeExtensions = true;
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
}
-}
+};
-Element.addMethods();
+Element.Methods.identify.counter = 1;
-var Toggle = new Object();
-Toggle.display = Element.toggle;
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
-/*--------------------------------------------------------------------------*/
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
-Abstract.Insertion = function(adjacency) {
- this.adjacency = adjacency;
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
}
-Abstract.Insertion.prototype = {
- initialize: function(element, content) {
- this.element = $(element);
- this.content = content.stripScripts();
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
- if (this.adjacency && this.element.insertAdjacentHTML) {
- try {
- this.element.insertAdjacentHTML(this.adjacency, this.content);
- } catch (e) {
- var tagName = this.element.tagName.toLowerCase();
- if (tagName == 'tbody' || tagName == 'tr') {
- this.insertContent(this.contentFromAnonymousTable());
- } else {
- throw e;
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
}
}
- } else {
- this.range = this.element.ownerDocument.createRange();
- if (this.initializeRange) this.initializeRange();
- this.insertContent([this.range.createContextualFragment(this.content)]);
}
+ };
- setTimeout(function() {content.evalScripts()}, 10);
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
},
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
- contentFromAnonymousTable: function() {
- var div = document.createElement('div');
- div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
- return $A(div.childNodes[0].childNodes[0].childNodes);
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
}
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
}
-var Insertion = new Object();
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
-Insertion.Before = Class.create();
-Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
- initializeRange: function() {
- this.range.setStartBefore(this.element);
- },
+ var Methods = { }, ByTag = Element.Methods.ByTag;
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.parentNode.insertBefore(fragment, this.element);
- }).bind(this));
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
}
-});
-Insertion.Top = Class.create();
-Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
- initializeRange: function() {
- this.range.selectNodeContents(this.element);
- this.range.collapse(true);
- },
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
- insertContent: function(fragments) {
- fragments.reverse(false).each((function(fragment) {
- this.element.insertBefore(fragment, this.element.firstChild);
- }).bind(this));
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
}
-});
-Insertion.Bottom = Class.create();
-Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
- initializeRange: function() {
- this.range.selectNodeContents(this.element);
- this.range.collapse(this.element);
- },
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.appendChild(fragment);
- }).bind(this));
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
}
-});
-Insertion.After = Class.create();
-Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
- initializeRange: function() {
- this.range.setStartAfter(this.element);
- },
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.parentNode.insertBefore(fragment,
- this.element.nextSibling);
- }).bind(this));
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
}
-});
-/*--------------------------------------------------------------------------*/
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
-Element.ClassNames = Class.create();
-Element.ClassNames.prototype = {
- initialize: function(element) {
- this.element = $(element);
- },
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
- _each: function(iterator) {
- this.element.className.split(/\s+/).select(function(name) {
- return name.length > 0;
- })._each(iterator);
- },
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
- set: function(className) {
- this.element.className = className;
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
},
- add: function(classNameToAdd) {
- if (this.include(classNameToAdd)) return;
- this.set(this.toArray().concat(classNameToAdd).join(' '));
+ getWidth: function() {
+ return this.getDimensions().width;
},
- remove: function(classNameToRemove) {
- if (!this.include(classNameToRemove)) return;
- this.set(this.select(function(className) {
- return className != classNameToRemove;
- }).join(' '));
+ getHeight: function() {
+ return this.getDimensions().height;
},
- toString: function() {
- return this.toArray().join(' ');
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
}
-}
+};
+/* Portions of the Selector class are derived from Jack Slocum�۪s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
-Object.extend(Element.ClassNames.prototype, Enumerable);
-var Selector = Class.create();
-Selector.prototype = {
+var Selector = Class.create({
initialize: function(expression) {
- this.params = {classNames: []};
- this.expression = expression.toString().strip();
- this.parseExpression();
+ this.expression = expression.strip();
this.compileMatcher();
},
- parseExpression: function() {
- function abort(message) { throw 'Parse error in selector: ' + message; }
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
- if (this.expression == '') abort('empty expression');
+ var e = this.expression;
- var params = this.params, expr = this.expression, match, modifier, clause, rest;
- while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
- params.attributes = params.attributes || [];
- params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
- expr = match[1];
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
}
- if (expr == '*') return this.params.wildcard = true;
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
- while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
- modifier = match[1], clause = match[2], rest = match[3];
- switch (modifier) {
- case '#': params.id = clause; break;
- case '.': params.classNames.push(clause); break;
- case '':
- case undefined: params.tagName = clause.toUpperCase(); break;
- default: abort(expr.inspect());
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
}
- expr = rest;
}
- if (expr.length > 0) abort(expr.inspect());
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
},
- buildMatchExpression: function() {
- var params = this.params, conditions = [], clause;
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
- if (params.wildcard)
- conditions.push('true');
- if (clause = params.id)
- conditions.push('element.id == ' + clause.inspect());
- if (clause = params.tagName)
- conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
- if ((clause = params.classNames).length > 0)
- for (var i = 0; i < clause.length; i++)
- conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
- if (clause = params.attributes) {
- clause.each(function(attribute) {
- var value = 'element.getAttribute(' + attribute.name.inspect() + ')';
- var splitValueBy = function(delimiter) {
- return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
- }
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
- switch (attribute.operator) {
- case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break;
- case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
- case '|=': conditions.push(
- splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
- ); break;
- case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break;
- case '':
- case undefined: conditions.push(value + ' != null'); break;
- default: throw 'Unknown operator ' + attribute.operator + ' in selector';
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
}
- });
+ }
}
- return conditions.join(' && ');
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
},
- compileMatcher: function() {
- this.match = new Function('element', 'if (!element.tagName) return false; \
- return ' + this.buildMatchExpression());
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
},
- findElements: function(scope) {
- var element;
+ match: function(element) {
+ this.tokens = [];
- if (element = $(this.params.id))
- if (this.match(element))
- if (!scope || Element.childOf(element, scope))
- return [element];
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
- scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
- var results = [];
- for (var i = 0; i < scope.length; i++)
- if (this.match(element = scope[i]))
- results.push(Element.extend(element));
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
- return results;
+ return match;
},
toString: function() {
return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
}
-}
+});
-function $$() {
- return $A(arguments).map(function(expression) {
- return expression.strip().split(/\s+/).inject([null], function(results, expr) {
- var selector = new Selector(expr);
- return results.map(selector.findElements.bind(selector)).flatten();
- });
- }).flatten();
-}
-var Field = {
- clear: function() {
- for (var i = 0; i < arguments.length; i++)
- $(arguments[i]).value = '';
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
},
- focus: function(element) {
- $(element).focus();
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
},
- present: function() {
- for (var i = 0; i < arguments.length; i++)
- if ($(arguments[i]).value == '') return false;
- return true;
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
},
- select: function(element) {
- $(element).select();
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
},
- activate: function(element) {
- element = $(element);
- element.focus();
- if (element.select)
- element.select();
- }
-}
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
-/*--------------------------------------------------------------------------*/
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
-var Form = {
- serialize: function(form) {
- var elements = Form.getElements($(form));
- var queryComponents = new Array();
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
- for (var i = 0; i < elements.length; i++) {
- var queryComponent = Form.Element.serialize(elements[i]);
- if (queryComponent)
- queryComponents.push(queryComponent);
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
}
+ },
- return queryComponents.join('&');
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
},
- getElements: function(form) {
- form = $(form);
- var elements = new Array();
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
- for (var tagName in Form.Element.Serializers) {
- var tagElements = form.getElementsByTagName(tagName);
- for (var j = 0; j < tagElements.length; j++)
- elements.push(tagElements[j]);
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
}
- return elements;
+ return Selector.matchElements(elements, expression || '*')[index || 0];
},
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
getInputs: function(form, typeName, name) {
form = $(form);
var inputs = form.getElementsByTagName('input');
- if (!typeName && !name)
- return inputs;
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
- var matchingInputs = new Array();
- for (var i = 0; i < inputs.length; i++) {
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
var input = inputs[i];
- if ((typeName && input.type != typeName) ||
- (name && input.name != name))
+ if ((typeName && input.type != typeName) || (name && input.name != name))
continue;
- matchingInputs.push(input);
+ matchingInputs.push(Element.extend(input));
}
return matchingInputs;
},
disable: function(form) {
- var elements = Form.getElements(form);
- for (var i = 0; i < elements.length; i++) {
- var element = elements[i];
- element.blur();
- element.disabled = 'true';
- }
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
},
enable: function(form) {
- var elements = Form.getElements(form);
- for (var i = 0; i < elements.length; i++) {
- var element = elements[i];
- element.disabled = '';
- }
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
},
findFirstElement: function(form) {
- return Form.getElements(form).find(function(element) {
- return element.type != 'hidden' && !element.disabled &&
- ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
});
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
},
focusFirstElement: function(form) {
- Field.activate(Form.findFirstElement(form));
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
},
- reset: function(form) {
- $(form).reset();
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
}
-}
+};
+/*--------------------------------------------------------------------------*/
+
Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
serialize: function(element) {
element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
var method = element.tagName.toLowerCase();
- var parameter = Form.Element.Serializers[method](element);
+ return Form.Element.Serializers[method](element);
+ },
- if (parameter) {
- var key = encodeURIComponent(parameter[0]);
- if (key.length == 0) return;
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
- if (parameter[1].constructor != Array)
- parameter[1] = [parameter[1]];
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
- return parameter[1].map(function(value) {
- return key + '=' + encodeURIComponent(value);
- }).join('&');
- }
+ present: function(element) {
+ return $(element).value != '';
},
- getValue: function(element) {
+ activate: function(element) {
element = $(element);
- var method = element.tagName.toLowerCase();
- var parameter = Form.Element.Serializers[method](element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
- if (parameter)
- return parameter[1];
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
}
-}
+};
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
Form.Element.Serializers = {
- input: function(element) {
+ input: function(element, value) {
switch (element.type.toLowerCase()) {
- case 'submit':
- case 'hidden':
- case 'password':
- case 'text':
- return Form.Element.Serializers.textarea(element);
case 'checkbox':
case 'radio':
- return Form.Element.Serializers.inputSelector(element);
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
}
- return false;
},
- inputSelector: function(element) {
- if (element.checked)
- return [element.name, element.value];
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
},
- textarea: function(element) {
- return [element.name, element.value];
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
},
- select: function(element) {
- return Form.Element.Serializers[element.type == 'select-one' ?
- 'selectOne' : 'selectMany'](element);
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
},
selectOne: function(element) {
- var value = '', opt, index = element.selectedIndex;
- if (index >= 0) {
- opt = element.options[index];
- value = opt.value || opt.text;
- }
- return [element.name, value];
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
},
selectMany: function(element) {
- var value = [];
- for (var i = 0; i < element.length; i++) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
var opt = element.options[i];
- if (opt.selected)
- value.push(opt.value || opt.text);
+ if (opt.selected) values.push(this.optionValue(opt));
}
- return [element.name, value];
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
}
-}
+};
/*--------------------------------------------------------------------------*/
-var $F = Form.Element.getValue;
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.TimedObserver = function() {}
-Abstract.TimedObserver.prototype = {
- initialize: function(element, frequency, callback) {
- this.frequency = frequency;
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
this.element = $(element);
- this.callback = callback;
-
this.lastValue = this.getValue();
- this.registerCallback();
},
- registerCallback: function() {
- setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
- },
-
- onTimerEvent: function() {
+ execute: function() {
var value = this.getValue();
- if (this.lastValue != value) {
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
this.callback(this.element, value);
this.lastValue = value;
}
}
-}
+});
-Form.Element.Observer = Class.create();
-Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
getValue: function() {
return Form.Element.getValue(this.element);
}
});
-Form.Observer = Class.create();
-Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+Form.Observer = Class.create(Abstract.TimedObserver, {
getValue: function() {
return Form.serialize(this.element);
}
@@ -1606,8 +3662,7 @@
/*--------------------------------------------------------------------------*/
-Abstract.EventObserver = function() {}
-Abstract.EventObserver.prototype = {
+Abstract.EventObserver = Class.create({
initialize: function(element, callback) {
this.element = $(element);
this.callback = callback;
@@ -1628,9 +3683,7 @@
},
registerFormCallbacks: function() {
- var elements = Form.getElements(this.element);
- for (var i = 0; i < elements.length; i++)
- this.registerCallback(elements[i]);
+ Form.getElements(this.element).each(this.registerCallback, this);
},
registerCallback: function(element) {
@@ -1640,34 +3693,26 @@
case 'radio':
Event.observe(element, 'click', this.onElementEvent.bind(this));
break;
- case 'password':
- case 'text':
- case 'textarea':
- case 'select-one':
- case 'select-multiple':
+ default:
Event.observe(element, 'change', this.onElementEvent.bind(this));
break;
}
}
}
-}
+});
-Form.Element.EventObserver = Class.create();
-Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
getValue: function() {
return Form.Element.getValue(this.element);
}
});
-Form.EventObserver = Class.create();
-Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+Form.EventObserver = Class.create(Abstract.EventObserver, {
getValue: function() {
return Form.serialize(this.element);
}
});
-if (!window.Event) {
- var Event = new Object();
-}
+if (!window.Event) var Event = { };
Object.extend(Event, {
KEY_BACKSPACE: 8,
@@ -1679,100 +3724,343 @@
KEY_RIGHT: 39,
KEY_DOWN: 40,
KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
- element: function(event) {
- return event.target || event.srcElement;
- },
+ cache: { },
- isLeftClick: function(event) {
- return (((event.which) && (event.which == 1)) ||
- ((event.button) && (event.button == 1)));
- },
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
- pointerX: function(event) {
- return event.pageX || (event.clientX +
- (document.documentElement.scrollLeft || document.body.scrollLeft));
- },
+Event.Methods = (function() {
+ var isButton;
- pointerY: function(event) {
- return event.pageY || (event.clientY +
- (document.documentElement.scrollTop || document.body.scrollTop));
- },
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
- stop: function(event) {
- if (event.preventDefault) {
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
event.preventDefault();
event.stopPropagation();
- } else {
- event.returnValue = false;
- event.cancelBubble = true;
+ event.stopped = true;
}
- },
+ };
+})();
- // find the first node with the given tagName, starting from the
- // node the event was triggered on; traverses the DOM upwards
- findElement: function(event, tagName) {
- var element = Event.element(event);
- while (element.parentNode && (!element.tagName ||
- (element.tagName.toUpperCase() != tagName.toUpperCase())))
- element = element.parentNode;
- return element;
- },
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
- observers: false,
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
- _observeAndCache: function(element, name, observer, useCapture) {
- if (!this.observers) this.observers = [];
- if (element.addEventListener) {
- this.observers.push([element, name, observer, useCapture]);
- element.addEventListener(name, observer, useCapture);
- } else if (element.attachEvent) {
- this.observers.push([element, name, observer, useCapture]);
- element.attachEvent('on' + name, observer);
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
}
- },
+ };
+})());
- unloadCache: function() {
- if (!Event.observers) return;
- for (var i = 0; i < Event.observers.length; i++) {
- Event.stopObserving.apply(this, Event.observers[i]);
- Event.observers[i][0] = null;
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
}
- Event.observers = false;
- },
- observe: function(element, name, observer, useCapture) {
- var element = $(element);
- useCapture = useCapture || false;
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
- if (name == 'keypress' &&
- (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
- || element.attachEvent))
- name = 'keydown';
+Hash.toQueryString = Object.toQueryString;
- this._observeAndCache(element, name, observer, useCapture);
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
},
- stopObserving: function(element, name, observer, useCapture) {
- var element = $(element);
- useCapture = useCapture || false;
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
- if (name == 'keypress' &&
- (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
- || element.detachEvent))
- name = 'keydown';
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
- if (element.removeEventListener) {
- element.removeEventListener(name, observer, useCapture);
- } else if (element.detachEvent) {
- element.detachEvent('on' + name, observer);
- }
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
}
-});
+};
-/* prevent memory leaks in IE */
-if (navigator.appVersion.match(/\bMSIE\b/))
- Event.observe(window, 'unload', Event.unloadCache, false);
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
var Position = {
// set to true if needed, warning: firefox performance problems
// NOT neeeded for page scrolling, only if draggable contained in
@@ -1792,58 +4080,13 @@
|| 0;
},
- realOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.scrollTop || 0;
- valueL += element.scrollLeft || 0;
- element = element.parentNode;
- } while (element);
- return [valueL, valueT];
- },
-
- cumulativeOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- } while (element);
- return [valueL, valueT];
- },
-
- positionedOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- if (element) {
- p = Element.getStyle(element, 'position');
- if (p == 'relative' || p == 'absolute') break;
- }
- } while (element);
- return [valueL, valueT];
- },
-
- offsetParent: function(element) {
- if (element.offsetParent) return element.offsetParent;
- if (element == document.body) return element;
-
- while ((element = element.parentNode) && element != document.body)
- if (Element.getStyle(element, 'position') != 'static')
- return element;
-
- return document.body;
- },
-
// caches x/y coordinate pair to use with overlap
within: function(element, x, y) {
if (this.includeScrollOffsets)
return this.withinIncludingScrolloffsets(element, x, y);
this.xcomp = x;
this.ycomp = y;
- this.offset = this.cumulativeOffset(element);
+ this.offset = Element.cumulativeOffset(element);
return (y >= this.offset[1] &&
y < this.offset[1] + element.offsetHeight &&
@@ -1852,11 +4095,11 @@
},
withinIncludingScrolloffsets: function(element, x, y) {
- var offsetcache = this.realOffset(element);
+ var offsetcache = Element.cumulativeScrollOffset(element);
this.xcomp = x + offsetcache[0] - this.deltaX;
this.ycomp = y + offsetcache[1] - this.deltaY;
- this.offset = this.cumulativeOffset(element);
+ this.offset = Element.cumulativeOffset(element);
return (this.ycomp >= this.offset[1] &&
this.ycomp < this.offset[1] + element.offsetHeight &&
@@ -1875,132 +4118,104 @@
element.offsetWidth;
},
- clone: function(source, target) {
- source = $(source);
- target = $(target);
- target.style.position = 'absolute';
- var offsets = this.cumulativeOffset(source);
- target.style.top = offsets[1] + 'px';
- target.style.left = offsets[0] + 'px';
- target.style.width = source.offsetWidth + 'px';
- target.style.height = source.offsetHeight + 'px';
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
},
- page: function(forElement) {
- var valueT = 0, valueL = 0;
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
- var element = forElement;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
+ realOffset: Element.Methods.cumulativeScrollOffset,
- // Safari fix
- if (element.offsetParent==document.body)
- if (Element.getStyle(element,'position')=='absolute') break;
+ offsetParent: Element.Methods.getOffsetParent,
- } while (element = element.offsetParent);
+ page: Element.Methods.viewportOffset,
- element = forElement;
- do {
- valueT -= element.scrollTop || 0;
- valueL -= element.scrollLeft || 0;
- } while (element = element.parentNode);
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
- return [valueL, valueT];
- },
+/*--------------------------------------------------------------------------*/
- clone: function(source, target) {
- var options = Object.extend({
- setLeft: true,
- setTop: true,
- setWidth: true,
- setHeight: true,
- offsetTop: 0,
- offsetLeft: 0
- }, arguments[2] || {})
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
- // find page position of source
- source = $(source);
- var p = Position.page(source);
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
- // find coordinate system to use
- target = $(target);
- var delta = [0, 0];
- var parent = null;
- // delta [0,0] will do fine with position: fixed elements,
- // position:absolute needs offsetParent deltas
- if (Element.getStyle(target,'position') == 'absolute') {
- parent = Position.offsetParent(target);
- delta = Position.page(parent);
- }
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
- // correct by body offsets (fixes Safari)
- if (parent == document.body) {
- delta[0] -= document.body.offsetLeft;
- delta[1] -= document.body.offsetTop;
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
}
+ return elements;
+ };
- // set position
- if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
- if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
- if(options.setWidth) target.style.width = source.offsetWidth + 'px';
- if(options.setHeight) target.style.height = source.offsetHeight + 'px';
- },
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
- absolutize: function(element) {
- element = $(element);
- if (element.style.position == 'absolute') return;
- Position.prepare();
+/*--------------------------------------------------------------------------*/
- var offsets = Position.positionedOffset(element);
- var top = offsets[1];
- var left = offsets[0];
- var width = element.clientWidth;
- var height = element.clientHeight;
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
- element._originalLeft = left - parseFloat(element.style.left || 0);
- element._originalTop = top - parseFloat(element.style.top || 0);
- element._originalWidth = element.style.width;
- element._originalHeight = element.style.height;
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
- element.style.position = 'absolute';
- element.style.top = top + 'px';;
- element.style.left = left + 'px';;
- element.style.width = width + 'px';;
- element.style.height = height + 'px';;
+ set: function(className) {
+ this.element.className = className;
},
- relativize: function(element) {
- element = $(element);
- if (element.style.position == 'relative') return;
- Position.prepare();
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
- element.style.position = 'relative';
- var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
- var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
- element.style.top = top + 'px';
- element.style.left = left + 'px';
- element.style.height = element._originalHeight;
- element.style.width = element._originalWidth;
+ toString: function() {
+ return $A(this).join(' ');
}
-}
+};
-// Safari returns margins on body which is incorrect if the child is absolutely
-// positioned. For performance reasons, redefine Position.cumulativeOffset for
-// KHTML/WebKit only.
-if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
- Position.cumulativeOffset = function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- if (element.offsetParent == document.body)
- if (Element.getStyle(element, 'position') == 'absolute') break;
+Object.extend(Element.ClassNames.prototype, Enumerable);
- element = element.offsetParent;
- } while (element);
+/*--------------------------------------------------------------------------*/
- return [valueL, valueT];
- }
-}
\ No newline at end of file
+Element.addMethods();
\ No newline at end of file
16 years
JBoss Portal SVN: r10715 - in branches/JBoss_Portal_Branch_2_7: core-admin/src/resources/portal-admin-war/jsf/common and 3 other directories.
by portal-commits@lists.jboss.org
Author: wesleyhales
Date: 2008-04-24 20:34:57 -0400 (Thu, 24 Apr 2008)
New Revision: 10715
Modified:
branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/WEB-INF/tags/boxes.xhtml
branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/jsf/common/editPageLayout.xhtml
branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/jsf/common/showPortletDetails.xhtml
branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/jsf/dashboard/dashboard.xhtml
branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/prototype.js
branches/JBoss_Portal_Branch_2_7/theme/src/bin/theme-test-war/core/lib/prototype.js
Log:
fix window name problem and upgrade prototype.js
Modified: branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/WEB-INF/tags/boxes.xhtml
===================================================================
--- branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/WEB-INF/tags/boxes.xhtml 2008-04-24 13:49:28 UTC (rev 10714)
+++ branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/WEB-INF/tags/boxes.xhtml 2008-04-25 00:34:57 UTC (rev 10715)
@@ -10,5 +10,4 @@
</div>
<b class="xbottom"><b class="xb4"/><b class="xb3"/><b class="xb2"/><b class="xb1"/></b>
</div>
-
</ui:composition>
\ No newline at end of file
Modified: branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/jsf/common/editPageLayout.xhtml
===================================================================
--- branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/jsf/common/editPageLayout.xhtml 2008-04-24 13:49:28 UTC (rev 10714)
+++ branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/jsf/common/editPageLayout.xhtml 2008-04-25 00:34:57 UTC (rev 10715)
@@ -24,7 +24,7 @@
<label for="windowName">
<span class="portlet-form-field-label admin-label">Window Name:</span>
<h:inputText id="windowName" value="#{pageManager.windowName}"
- styleClass="portlet-form-input-field"/>
+ styleClass="portlet-form-input-field id-window-name"/>
</label>
<h:message for="windowName" errorClass="portlet-msg-error"/>
</h:form>
@@ -46,7 +46,7 @@
id="instanceId"
value="#{pageManager.selectedContentType}"
styleClass="portlet-form-field contentType"
- onchange="document.getElementById('abc:windowNameCopy').value = document.getElementById('windowForm:windowName').value;
+ onchange="document.getElementById('abc:windowNameCopy').value = document.getElementsByClassName('id-window-name')[0].value;
document.getElementById('abc').submit(); ">
<f:selectItems value="#{pageManager.contentTypeItems}"/>
</h:selectOneMenu>
@@ -73,7 +73,7 @@
initialMode="edit_content"
initialWindowState="normal"
renderParameters="#{pageManager.selectedRenderParameters}"
- onClick="url.setParameter('windowName', document.getElementById('windowForm:windowName').value);"/>
+ onClick="url.setParameter('windowName', document.getElementsByClassName('id-window-name')[0].value);"/>
</td>
</tr>
</table>
@@ -102,7 +102,7 @@
<tr>
<td valign="top">
<h:commandButton
- onclick="document.getElementById('blah').value=document.getElementById('windowForm:windowName').value"
+ onclick="document.getElementById('blah').value=document.getElementsByClassName('id-window-name')[0].value"
value="Add" id="a_#{regionName}"
actionListener="#{pageManager.assignWindows}"
styleClass="portlet-form-button layout-button"/>
Modified: branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/jsf/common/showPortletDetails.xhtml
===================================================================
--- branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/jsf/common/showPortletDetails.xhtml 2008-04-24 13:49:28 UTC (rev 10714)
+++ branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/jsf/common/showPortletDetails.xhtml 2008-04-25 00:34:57 UTC (rev 10715)
@@ -1,13 +1,11 @@
-<div
- xmlns:ui="http://java.sun.com/jsf/facelets"
- xmlns:h="http://java.sun.com/jsf/html"
- xmlns:f="http://java.sun.com/jsf/core"
- xmlns:c="http://java.sun.com/jstl/core"
- xmlns:a4j="http://richfaces.org/a4j"
- xmlns:rich="http://richfaces.org/rich"
- xmlns:portal="http://www.jboss.org/portal">
+<div xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:c="http://java.sun.com/jstl/core"
+ xmlns:a4j="http://richfaces.org/a4j"
+ xmlns:rich="http://richfaces.org/rich"
+ xmlns:portal="http://www.jboss.org/portal">
<h:form>
-
<div class="details-container">
<div class="full-width details-header">
<div class="main-header">
Modified: branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/jsf/dashboard/dashboard.xhtml
===================================================================
--- branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/jsf/dashboard/dashboard.xhtml 2008-04-24 13:49:28 UTC (rev 10714)
+++ branches/JBoss_Portal_Branch_2_7/core-admin/src/resources/portal-admin-war/jsf/dashboard/dashboard.xhtml 2008-04-25 00:34:57 UTC (rev 10715)
@@ -62,12 +62,12 @@
</tr>
<tr>
<td class="portlet-section-body" align="center">
- <h:form id="page_selector_form" style="padding:0;margin:0">
+ <h:form id="page_selector_form" style="padding:0;margin:0" styleClass="id_page_selector_form">
Select: <h:selectOneMenu
id="pageNameSelector"
value="#{dashboard.selectedPageName}"
styleClass="portlet-form-field"
- onchange="document.getElementById('page_selector_form').submit()">
+ onchange="document.getElementsByClassName('page_selector_form')[0].submit()">
<f:selectItems value="#{dashboard.pageItems}"/>
</h:selectOneMenu>
</h:form>
Modified: branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/prototype.js
===================================================================
--- branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/prototype.js 2008-04-24 13:49:28 UTC (rev 10714)
+++ branches/JBoss_Portal_Branch_2_7/theme/src/bin/portal-ajax-war/dyna/prototype.js 2008-04-25 00:34:57 UTC (rev 10715)
@@ -1,51 +1,153 @@
-/* Prototype JavaScript framework, version 1.5.0
- * (c) 2005-2007 Sam Stephenson
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style license.
- * For details, see the Prototype web site: http://prototype.conio.net/
+ * For details, see the Prototype web site: http://www.prototypejs.org/
*
-/*--------------------------------------------------------------------------*/
+ *--------------------------------------------------------------------------*/
var Prototype = {
- Version: '1.5.0',
+ Version: '1.6.0.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
BrowserFeatures: {
- XPath: !!document.evaluate
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
},
- ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
- emptyFunction: function() {},
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
K: function(x) { return x }
-}
+};
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
var Class = {
create: function() {
- return function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
this.initialize.apply(this, arguments);
}
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
}
-}
+};
-var Abstract = new Object();
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
Object.extend = function(destination, source) {
- for (var property in source) {
+ for (var property in source)
destination[property] = source[property];
- }
return destination;
-}
+};
Object.extend(Object, {
inspect: function(object) {
try {
- if (object === undefined) return 'undefined';
+ if (Object.isUndefined(object)) return 'undefined';
if (object === null) return 'null';
- return object.inspect ? object.inspect() : object.toString();
+ return object.inspect ? object.inspect() : String(object);
} catch (e) {
if (e instanceof RangeError) return '...';
throw e;
}
},
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
keys: function(object) {
var keys = [];
for (var property in object)
@@ -61,41 +163,102 @@
},
clone: function(object) {
- return Object.extend({}, object);
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
}
});
-Function.prototype.bind = function() {
- var __method = this, args = $A(arguments), object = args.shift();
- return function() {
- return __method.apply(object, args.concat($A(arguments)));
- }
-}
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
-Function.prototype.bindAsEventListener = function(object) {
- var __method = this, args = $A(arguments), object = args.shift();
- return function(event) {
- return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments)));
- }
-}
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
-Object.extend(Number.prototype, {
- toColorPart: function() {
- var digits = this.toString(16);
- if (this < 16) return '0' + digits;
- return digits;
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
},
- succ: function() {
- return this + 1;
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
},
- times: function(iterator) {
- $R(0, this, true).each(iterator);
- return this;
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
}
});
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
var Try = {
these: function() {
var returnValue;
@@ -105,17 +268,22 @@
try {
returnValue = lambda();
break;
- } catch (e) {}
+ } catch (e) { }
}
return returnValue;
}
-}
+};
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
/*--------------------------------------------------------------------------*/
-var PeriodicalExecuter = Class.create();
-PeriodicalExecuter.prototype = {
+var PeriodicalExecuter = Class.create({
initialize: function(callback, frequency) {
this.callback = callback;
this.frequency = frequency;
@@ -128,6 +296,10 @@
this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
+ execute: function() {
+ this.callback(this);
+ },
+
stop: function() {
if (!this.timer) return;
clearInterval(this.timer);
@@ -138,16 +310,26 @@
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
- this.callback(this);
+ this.execute();
} finally {
this.currentlyExecuting = false;
}
}
}
-}
-String.interpret = function(value){
- return value == null ? '' : String(value);
-}
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
Object.extend(String.prototype, {
gsub: function(pattern, replacement) {
@@ -168,7 +350,7 @@
sub: function(pattern, replacement, count) {
replacement = this.gsub.prepareReplacement(replacement);
- count = count === undefined ? 1 : count;
+ count = Object.isUndefined(count) ? 1 : count;
return this.gsub(pattern, function(match) {
if (--count < 0) return match[0];
@@ -178,14 +360,14 @@
scan: function(pattern, iterator) {
this.gsub(pattern, iterator);
- return this;
+ return String(this);
},
truncate: function(length, truncation) {
length = length || 30;
- truncation = truncation === undefined ? '...' : truncation;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
return this.length > length ?
- this.slice(0, length - truncation.length) + truncation : this;
+ this.slice(0, length - truncation.length) + truncation : String(this);
},
strip: function() {
@@ -213,35 +395,34 @@
},
escapeHTML: function() {
- var div = document.createElement('div');
- var text = document.createTextNode(this);
- div.appendChild(text);
- return div.innerHTML;
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
},
unescapeHTML: function() {
- var div = document.createElement('div');
+ var div = new Element('div');
div.innerHTML = this.stripTags();
return div.childNodes[0] ? (div.childNodes.length > 1 ?
- $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) :
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
div.childNodes[0].nodeValue) : '';
},
toQueryParams: function(separator) {
var match = this.strip().match(/([^?#]*)(#.*)?$/);
- if (!match) return {};
+ if (!match) return { };
- return match[1].split(separator || '&').inject({}, function(hash, pair) {
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
if ((pair = pair.split('='))[0]) {
- var name = decodeURIComponent(pair[0]);
- var value = pair[1] ? decodeURIComponent(pair[1]) : undefined;
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
- if (hash[name] !== undefined) {
- if (hash[name].constructor != Array)
- hash[name] = [hash[name]];
- if (value) hash[name].push(value);
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
}
- else hash[name] = value;
+ else hash[key] = value;
}
return hash;
});
@@ -256,6 +437,10 @@
String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
},
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
camelize: function() {
var parts = this.split('-'), len = parts.length;
if (len == 1) return parts[0];
@@ -270,7 +455,7 @@
return camelized;
},
- capitalize: function(){
+ capitalize: function() {
return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
},
@@ -283,52 +468,131 @@
},
inspect: function(useDoubleQuotes) {
- var escapedString = this.replace(/\\/g, '\\\\');
- if (useDoubleQuotes)
- return '"' + escapedString.replace(/"/g, '\\"') + '"';
- else
- return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
}
});
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ }
+});
+
String.prototype.gsub.prepareReplacement = function(replacement) {
- if (typeof replacement == 'function') return replacement;
+ if (Object.isFunction(replacement)) return replacement;
var template = new Template(replacement);
return function(match) { return template.evaluate(match) };
-}
+};
String.prototype.parseQuery = String.prototype.toQueryParams;
-var Template = Class.create();
-Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
-Template.prototype = {
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
initialize: function(template, pattern) {
this.template = template.toString();
- this.pattern = pattern || Template.Pattern;
+ this.pattern = pattern || Template.Pattern;
},
evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
return this.template.gsub(this.pattern, function(match) {
- var before = match[1];
+ if (object == null) return '';
+
+ var before = match[1] || '';
if (before == '\\') return match[2];
- return before + String.interpret(object[match[3]]);
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
});
}
-}
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
-var $break = new Object();
-var $continue = new Object();
+var $break = { };
var Enumerable = {
- each: function(iterator) {
+ each: function(iterator, context) {
var index = 0;
+ iterator = iterator.bind(context);
try {
this._each(function(value) {
- try {
- iterator(value, index++);
- } catch (e) {
- if (e != $continue) throw e;
- }
+ iterator(value, index++);
});
} catch (e) {
if (e != $break) throw e;
@@ -336,40 +600,45 @@
return this;
},
- eachSlice: function(number, iterator) {
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var index = -number, slices = [], array = this.toArray();
while ((index += number) < array.length)
slices.push(array.slice(index, index+number));
- return slices.map(iterator);
+ return slices.collect(iterator, context);
},
- all: function(iterator) {
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var result = true;
this.each(function(value, index) {
- result = result && !!(iterator || Prototype.K)(value, index);
+ result = result && !!iterator(value, index);
if (!result) throw $break;
});
return result;
},
- any: function(iterator) {
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var result = false;
this.each(function(value, index) {
- if (result = !!(iterator || Prototype.K)(value, index))
+ if (result = !!iterator(value, index))
throw $break;
});
return result;
},
- collect: function(iterator) {
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var results = [];
this.each(function(value, index) {
- results.push((iterator || Prototype.K)(value, index));
+ results.push(iterator(value, index));
});
return results;
},
- detect: function(iterator) {
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
var result;
this.each(function(value, index) {
if (iterator(value, index)) {
@@ -380,7 +649,8 @@
return result;
},
- findAll: function(iterator) {
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
var results = [];
this.each(function(value, index) {
if (iterator(value, index))
@@ -389,17 +659,24 @@
return results;
},
- grep: function(pattern, iterator) {
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
this.each(function(value, index) {
- var stringValue = value.toString();
- if (stringValue.match(pattern))
- results.push((iterator || Prototype.K)(value, index));
- })
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
return results;
},
include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
var found = false;
this.each(function(value) {
if (value == object) {
@@ -411,14 +688,15 @@
},
inGroupsOf: function(number, fillWith) {
- fillWith = fillWith === undefined ? null : fillWith;
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
return this.eachSlice(number, function(slice) {
while(slice.length < number) slice.push(fillWith);
return slice;
});
},
- inject: function(memo, iterator) {
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
this.each(function(value, index) {
memo = iterator(memo, value, index);
});
@@ -432,30 +710,33 @@
});
},
- max: function(iterator) {
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var result;
this.each(function(value, index) {
- value = (iterator || Prototype.K)(value, index);
- if (result == undefined || value >= result)
+ value = iterator(value, index);
+ if (result == null || value >= result)
result = value;
});
return result;
},
- min: function(iterator) {
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var result;
this.each(function(value, index) {
- value = (iterator || Prototype.K)(value, index);
- if (result == undefined || value < result)
+ value = iterator(value, index);
+ if (result == null || value < result)
result = value;
});
return result;
},
- partition: function(iterator) {
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var trues = [], falses = [];
this.each(function(value, index) {
- ((iterator || Prototype.K)(value, index) ?
+ (iterator(value, index) ?
trues : falses).push(value);
});
return [trues, falses];
@@ -463,13 +744,14 @@
pluck: function(property) {
var results = [];
- this.each(function(value, index) {
+ this.each(function(value) {
results.push(value[property]);
});
return results;
},
- reject: function(iterator) {
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
var results = [];
this.each(function(value, index) {
if (!iterator(value, index))
@@ -478,7 +760,8 @@
return results;
},
- sortBy: function(iterator) {
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
return this.map(function(value, index) {
return {value: value, criteria: iterator(value, index)};
}).sort(function(left, right) {
@@ -493,7 +776,7 @@
zip: function() {
var iterator = Prototype.K, args = $A(arguments);
- if (typeof args.last() == 'function')
+ if (Object.isFunction(args.last()))
iterator = args.pop();
var collections = [this].concat(args).map($A);
@@ -509,31 +792,42 @@
inspect: function() {
return '#<Enumerable:' + this.toArray().inspect() + '>';
}
-}
+};
Object.extend(Enumerable, {
map: Enumerable.collect,
find: Enumerable.detect,
select: Enumerable.findAll,
+ filter: Enumerable.findAll,
member: Enumerable.include,
- entries: Enumerable.toArray
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
});
-var $A = Array.from = function(iterable) {
+function $A(iterable) {
if (!iterable) return [];
- if (iterable.toArray) {
- return iterable.toArray();
- } else {
- var results = [];
- for (var i = 0, length = iterable.length; i < length; i++)
- results.push(iterable[i]);
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
return results;
- }
+ };
}
+Array.from = $A;
+
Object.extend(Array.prototype, Enumerable);
-if (!Array.prototype._reverse)
- Array.prototype._reverse = Array.prototype.reverse;
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
Object.extend(Array.prototype, {
_each: function(iterator) {
@@ -562,7 +856,7 @@
flatten: function() {
return this.inject([], function(array, value) {
- return array.concat(value && value.constructor == Array ?
+ return array.concat(Object.isArray(value) ?
value.flatten() : [value]);
});
},
@@ -574,12 +868,6 @@
});
},
- indexOf: function(object) {
- for (var i = 0, length = this.length; i < length; i++)
- if (this[i] == object) return i;
- return -1;
- },
-
reverse: function(inline) {
return (inline !== false ? this : this.toArray())._reverse();
},
@@ -588,12 +876,20 @@
return this.length > 1 ? this : this[0];
},
- uniq: function() {
- return this.inject([], function(array, value) {
- return array.include(value) ? array : array.concat([value]);
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
});
},
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
clone: function() {
return [].concat(this);
},
@@ -604,125 +900,187 @@
inspect: function() {
return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
}
});
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
Array.prototype.toArray = Array.prototype.clone;
-function $w(string){
+function $w(string) {
+ if (!Object.isString(string)) return [];
string = string.strip();
return string ? string.split(/\s+/) : [];
}
-if(window.opera){
- Array.prototype.concat = function(){
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
var array = [];
- for(var i = 0, length = this.length; i < length; i++) array.push(this[i]);
- for(var i = 0, length = arguments.length; i < length; i++) {
- if(arguments[i].constructor == Array) {
- for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
array.push(arguments[i][j]);
} else {
array.push(arguments[i]);
}
}
return array;
- }
+ };
}
-var Hash = function(obj) {
- Object.extend(this, obj || {});
-};
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
-Object.extend(Hash, {
- toQueryString: function(obj) {
- var parts = [];
+ succ: function() {
+ return this + 1;
+ },
- this.prototype._each.call(obj, function(pair) {
- if (!pair.key) return;
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
- if (pair.value && pair.value.constructor == Array) {
- var values = pair.value.compact();
- if (values.length < 2) pair.value = values.reduce();
- else {
- key = encodeURIComponent(pair.key);
- values.each(function(value) {
- value = value != undefined ? encodeURIComponent(value) : '';
- parts.push(key + '=' + encodeURIComponent(value));
- });
- return;
- }
- }
- if (pair.value == undefined) pair[1] = '';
- parts.push(pair.map(encodeURIComponent).join('='));
- });
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
- return parts.join('&');
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
}
});
-Object.extend(Hash.prototype, Enumerable);
-Object.extend(Hash.prototype, {
- _each: function(iterator) {
- for (var key in this) {
- var value = this[key];
- if (value && value == Hash.prototype[key]) continue;
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
- var pair = [key, value];
- pair.key = key;
- pair.value = value;
- iterator(pair);
- }
- },
+var Hash = Class.create(Enumerable, (function() {
- keys: function() {
- return this.pluck('key');
- },
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
- values: function() {
- return this.pluck('value');
- },
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
- merge: function(hash) {
- return $H(hash).inject(this, function(mergedHash, pair) {
- mergedHash[pair.key] = pair.value;
- return mergedHash;
- });
- },
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
- remove: function() {
- var result;
- for(var i = 0, length = arguments.length; i < length; i++) {
- var value = this[arguments[i]];
- if (value !== undefined){
- if (result === undefined) result = value;
- else {
- if (result.constructor != Array) result = [result];
- result.push(value)
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
}
- }
- delete this[arguments[i]];
- }
- return result;
- },
+ return toQueryPair(key, values);
+ }).join('&');
+ },
- toQueryString: function() {
- return Hash.toQueryString(this);
- },
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
- inspect: function() {
- return '#<Hash:{' + this.map(function(pair) {
- return pair.map(Object.inspect).join(': ');
- }).join(', ') + '}>';
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
}
-});
+})());
-function $H(object) {
- if (object && object.constructor == Hash) return object;
- return new Hash(object);
-};
-ObjectRange = Class.create();
-Object.extend(ObjectRange.prototype, Enumerable);
-Object.extend(ObjectRange.prototype, {
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
initialize: function(start, end, exclusive) {
this.start = start;
this.end = end;
@@ -748,7 +1106,7 @@
var $R = function(start, end, exclusive) {
return new ObjectRange(start, end, exclusive);
-}
+};
var Ajax = {
getTransport: function() {
@@ -760,7 +1118,7 @@
},
activeRequestCount: 0
-}
+};
Ajax.Responders = {
responders: [],
@@ -780,10 +1138,10 @@
dispatch: function(callback, request, transport, json) {
this.each(function(responder) {
- if (typeof responder[callback] == 'function') {
+ if (Object.isFunction(responder[callback])) {
try {
responder[callback].apply(responder, [request, transport, json]);
- } catch (e) {}
+ } catch (e) { }
}
});
}
@@ -792,49 +1150,45 @@
Object.extend(Ajax.Responders, Enumerable);
Ajax.Responders.register({
- onCreate: function() {
- Ajax.activeRequestCount++;
- },
- onComplete: function() {
- Ajax.activeRequestCount--;
- }
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
});
-Ajax.Base = function() {};
-Ajax.Base.prototype = {
- setOptions: function(options) {
+Ajax.Base = Class.create({
+ initialize: function(options) {
this.options = {
method: 'post',
asynchronous: true,
contentType: 'application/x-www-form-urlencoded',
encoding: 'UTF-8',
- parameters: ''
- }
- Object.extend(this.options, options || {});
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
this.options.method = this.options.method.toLowerCase();
- if (typeof this.options.parameters == 'string')
+
+ if (Object.isString(this.options.parameters))
this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
}
-}
+});
-Ajax.Request = Class.create();
-Ajax.Request.Events =
- ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
-
-Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
+Ajax.Request = Class.create(Ajax.Base, {
_complete: false,
- initialize: function(url, options) {
+ initialize: function($super, url, options) {
+ $super(options);
this.transport = Ajax.getTransport();
- this.setOptions(options);
this.request(url);
},
request: function(url) {
this.url = url;
this.method = this.options.method;
- var params = this.options.parameters;
+ var params = Object.clone(this.options.parameters);
if (!['get', 'post'].include(this.method)) {
// simulate other verbs over post
@@ -842,29 +1196,32 @@
this.method = 'post';
}
- params = Hash.toQueryString(params);
- if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_='
+ this.parameters = params;
- // when GET, append parameters to URL
- if (this.method == 'get' && params)
- this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params;
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
try {
- Ajax.Responders.dispatch('onCreate', this, this.transport);
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
this.transport.open(this.method.toUpperCase(), this.url,
this.options.asynchronous);
- if (this.options.asynchronous)
- setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
this.transport.onreadystatechange = this.onStateChange.bind(this);
this.setRequestHeaders();
- var body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
- this.transport.send(body);
-
/* Force Firefox to handle ready state 4 for synchronous requests */
if (!this.options.asynchronous && this.transport.overrideMimeType)
this.onStateChange();
@@ -905,7 +1262,7 @@
if (typeof this.options.requestHeaders == 'object') {
var extras = this.options.requestHeaders;
- if (typeof extras.push == 'function')
+ if (Object.isFunction(extras.push))
for (var i = 0, length = extras.length; i < length; i += 2)
headers[extras[i]] = extras[i+1];
else
@@ -917,32 +1274,39 @@
},
success: function() {
- return !this.transport.status
- || (this.transport.status >= 200 && this.transport.status < 300);
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
},
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
respondToReadyState: function(readyState) {
- var state = Ajax.Request.Events[readyState];
- var transport = this.transport, json = this.evalJSON();
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
if (state == 'Complete') {
try {
this._complete = true;
- (this.options['on' + this.transport.status]
+ (this.options['on' + response.status]
|| this.options['on' + (this.success() ? 'Success' : 'Failure')]
- || Prototype.emptyFunction)(transport, json);
+ || Prototype.emptyFunction)(response, response.headerJSON);
} catch (e) {
this.dispatchException(e);
}
- if ((this.getHeader('Content-type') || 'text/javascript').strip().
- match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
- this.evalResponse();
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
}
try {
- (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
- Ajax.Responders.dispatch('on' + state, this, transport, json);
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
} catch (e) {
this.dispatchException(e);
}
@@ -953,22 +1317,24 @@
}
},
- getHeader: function(name) {
- try {
- return this.transport.getResponseHeader(name);
- } catch (e) { return null }
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
},
- evalJSON: function() {
+ getHeader: function(name) {
try {
- var json = this.getHeader('X-JSON');
- return json ? eval('(' + json + ')') : null;
+ return this.transport.getResponseHeader(name) || null;
} catch (e) { return null }
},
evalResponse: function() {
try {
- return eval(this.transport.responseText);
+ return eval((this.transport.responseText || '').unfilterJSON());
} catch (e) {
this.dispatchException(e);
}
@@ -980,57 +1346,128 @@
}
});
-Ajax.Updater = Class.create();
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
-Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
- initialize: function(container, url, options) {
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
this.container = {
success: (container.success || container),
failure: (container.failure || (container.success ? null : container))
- }
+ };
- this.transport = Ajax.getTransport();
- this.setOptions(options);
-
- var onComplete = this.options.onComplete || Prototype.emptyFunction;
- this.options.onComplete = (function(transport, param) {
- this.updateContent();
- onComplete(transport, param);
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
}).bind(this);
- this.request(url);
+ $super(url, options);
},
- updateContent: function() {
- var receiver = this.container[this.success() ? 'success' : 'failure'];
- var response = this.transport.responseText;
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
- if (!this.options.evalScripts) response = response.stripScripts();
+ if (!options.evalScripts) responseText = responseText.stripScripts();
if (receiver = $(receiver)) {
- if (this.options.insertion)
- new this.options.insertion(receiver, response);
- else
- receiver.update(response);
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
}
-
- if (this.success()) {
- if (this.onComplete)
- setTimeout(this.onComplete.bind(this), 10);
- }
}
});
-Ajax.PeriodicalUpdater = Class.create();
-Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
- initialize: function(container, url, options) {
- this.setOptions(options);
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
this.onComplete = this.options.onComplete;
this.frequency = (this.options.frequency || 2);
this.decay = (this.options.decay || 1);
- this.updater = {};
+ this.updater = { };
this.container = container;
this.url = url;
@@ -1048,15 +1485,14 @@
(this.onComplete || Prototype.emptyFunction).apply(this, arguments);
},
- updateComplete: function(request) {
+ updateComplete: function(response) {
if (this.options.decay) {
- this.decay = (request.responseText == this.lastText ?
+ this.decay = (response.responseText == this.lastText ?
this.decay * this.options.decay : 1);
- this.lastText = request.responseText;
+ this.lastText = response.responseText;
}
- this.timer = setTimeout(this.onTimerEvent.bind(this),
- this.decay * this.frequency * 1000);
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
},
onTimerEvent: function() {
@@ -1069,7 +1505,7 @@
elements.push($(arguments[i]));
return elements;
}
- if (typeof element == 'string')
+ if (Object.isString(element))
element = document.getElementById(element);
return Element.extend(element);
}
@@ -1080,64 +1516,52 @@
var query = document.evaluate(expression, $(parentElement) || document,
null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0, length = query.snapshotLength; i < length; i++)
- results.push(query.snapshotItem(i));
+ results.push(Element.extend(query.snapshotItem(i)));
return results;
};
}
-document.getElementsByClassName = function(className, parentElement) {
- if (Prototype.BrowserFeatures.XPath) {
- var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
- return document._getElementsByXPath(q, parentElement);
- } else {
- var children = ($(parentElement) || document.body).getElementsByTagName('*');
- var elements = [], child;
- for (var i = 0, length = children.length; i < length; i++) {
- child = children[i];
- if (Element.hasClassName(child, className))
- elements.push(Element.extend(child));
- }
- return elements;
- }
-};
-
/*--------------------------------------------------------------------------*/
-if (!window.Element)
- var Element = new Object();
+if (!window.Node) var Node = { };
-Element.extend = function(element) {
- if (!element || _nativeExtensions || element.nodeType == 3) return element;
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
- if (!element._extended && element.tagName && element != window) {
- var methods = Object.clone(Element.Methods), cache = Element.extend.cache;
-
- if (element.tagName == 'FORM')
- Object.extend(methods, Form.Methods);
- if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))
- Object.extend(methods, Form.Element.Methods);
-
- Object.extend(methods, Element.Methods.Simulated);
-
- for (var property in methods) {
- var value = methods[property];
- if (typeof value == 'function' && !(property in element))
- element[property] = cache.findOrStore(value);
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
}
- }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
- element._extended = true;
- return element;
-};
+Element.cache = { };
-Element.extend.cache = {
- findOrStore: function(value) {
- return this[value] = this[value] || function() {
- return value.apply(null, [this].concat($A(arguments)));
- }
- }
-};
-
Element.Methods = {
visible: function(element) {
return $(element).style.display != 'none';
@@ -1165,28 +1589,78 @@
return element;
},
- update: function(element, html) {
- html = typeof html == 'undefined' ? '' : html.toString();
- $(element).innerHTML = html.stripScripts();
- setTimeout(function() {html.evalScripts()}, 10);
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
return element;
},
- replace: function(element, html) {
+ replace: function(element, content) {
element = $(element);
- html = typeof html == 'undefined' ? '' : html.toString();
- if (element.outerHTML) {
- element.outerHTML = html.stripScripts();
- } else {
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
var range = element.ownerDocument.createRange();
- range.selectNodeContents(element);
- element.parentNode.replaceChild(
- range.createContextualFragment(html.stripScripts()), element);
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
}
- setTimeout(function() {html.evalScripts()}, 10);
+ element.parentNode.replaceChild(content, element);
return element;
},
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
inspect: function(element) {
element = $(element);
var result = '<' + element.tagName.toLowerCase();
@@ -1212,9 +1686,15 @@
},
descendants: function(element) {
- return $A($(element).getElementsByTagName('*'));
+ return $(element).select("*");
},
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
immediateDescendants: function(element) {
if (!(element = $(element).firstChild)) return [];
while (element && element.nodeType != 1) element = element.nextSibling;
@@ -1236,48 +1716,95 @@
},
match: function(element, selector) {
- if (typeof selector == 'string')
+ if (Object.isString(selector))
selector = new Selector(selector);
return selector.match($(element));
},
up: function(element, expression, index) {
- return Selector.findElement($(element).ancestors(), expression, index);
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
},
down: function(element, expression, index) {
- return Selector.findElement($(element).descendants(), expression, index);
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
},
previous: function(element, expression, index) {
- return Selector.findElement($(element).previousSiblings(), expression, index);
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
},
next: function(element, expression, index) {
- return Selector.findElement($(element).nextSiblings(), expression, index);
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
},
- getElementsBySelector: function() {
+ select: function() {
var args = $A(arguments), element = $(args.shift());
return Selector.findChildElements(element, args);
},
- getElementsByClassName: function(element, className) {
- return document.getElementsByClassName(className, element);
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
},
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
readAttribute: function(element, name) {
element = $(element);
- if (document.all && !window.opera) {
- var t = Element._attributeTranslations;
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
if (t.values[name]) return t.values[name](element, name);
- if (t.names[name]) name = t.names[name];
- var attribute = element.attributes[name];
- if(attribute) return attribute.nodeValue;
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
}
return element.getAttribute(name);
},
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
getHeight: function(element) {
return $(element).getDimensions().height;
},
@@ -1293,41 +1820,30 @@
hasClassName: function(element, className) {
if (!(element = $(element))) return;
var elementClassName = element.className;
- if (elementClassName.length == 0) return false;
- if (elementClassName == className ||
- elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
- return true;
- return false;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
},
addClassName: function(element, className) {
if (!(element = $(element))) return;
- Element.classNames(element).add(className);
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
return element;
},
removeClassName: function(element, className) {
if (!(element = $(element))) return;
- Element.classNames(element).remove(className);
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
return element;
},
toggleClassName: function(element, className) {
if (!(element = $(element))) return;
- Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
- return element;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
},
- observe: function() {
- Event.observe.apply(Event, arguments);
- return $A(arguments).first();
- },
-
- stopObserving: function() {
- Event.stopObserving.apply(Event, arguments);
- return $A(arguments).first();
- },
-
// removes whitespace-only text node children
cleanWhitespace: function(element) {
element = $(element);
@@ -1342,74 +1858,77 @@
},
empty: function(element) {
- return $(element).innerHTML.match(/^\s*$/);
+ return $(element).innerHTML.blank();
},
descendantOf: function(element, ancestor) {
element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
while (element = element.parentNode)
- if (element == ancestor) return true;
+ if (element == originalAncestor) return true;
return false;
},
scrollTo: function(element) {
element = $(element);
- var pos = Position.cumulativeOffset(element);
+ var pos = element.cumulativeOffset();
window.scrollTo(pos[0], pos[1]);
return element;
},
getStyle: function(element, style) {
element = $(element);
- if (['float','cssFloat'].include(style))
- style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat');
- style = style.camelize();
+ style = style == 'float' ? 'cssFloat' : style.camelize();
var value = element.style[style];
if (!value) {
- if (document.defaultView && document.defaultView.getComputedStyle) {
- var css = document.defaultView.getComputedStyle(element, null);
- value = css ? css[style] : null;
- } else if (element.currentStyle) {
- value = element.currentStyle[style];
- }
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
}
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
- if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none'))
- value = element['offset'+style.capitalize()] + 'px';
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
- if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
- if (Element.getStyle(element, 'position') == 'static') value = 'auto';
- if(style == 'opacity') {
- if(value) return parseFloat(value);
- if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
- if(value[1]) return parseFloat(value[1]) / 100;
- return 1.0;
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
}
- return value == 'auto' ? null : value;
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
},
- setStyle: function(element, style) {
+ setOpacity: function(element, value) {
element = $(element);
- for (var name in style) {
- var value = style[name];
- if(name == 'opacity') {
- if (value == 1) {
- value = (/Gecko/.test(navigator.userAgent) &&
- !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0;
- if(/MSIE/.test(navigator.userAgent) && !window.opera)
- element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
- } else if(value === '') {
- if(/MSIE/.test(navigator.userAgent) && !window.opera)
- element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
- } else {
- if(value < 0.00001) value = 0;
- if(/MSIE/.test(navigator.userAgent) && !window.opera)
- element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') +
- 'alpha(opacity='+value*100+')';
- }
- } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat';
- element.style[name.camelize()] = value;
- }
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
return element;
},
@@ -1468,8 +1987,8 @@
makeClipping: function(element) {
element = $(element);
if (element._overflow) return element;
- element._overflow = element.style.overflow || 'auto';
- if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
element.style.overflow = 'hidden';
return element;
},
@@ -1480,393 +1999,1376 @@
element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
element._overflow = null;
return element;
- }
-};
+ },
-Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf});
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
-Element._attributeTranslations = {};
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
-Element._attributeTranslations.names = {
- colspan: "colSpan",
- rowspan: "rowSpan",
- valign: "vAlign",
- datetime: "dateTime",
- accesskey: "accessKey",
- tabindex: "tabIndex",
- enctype: "encType",
- maxlength: "maxLength",
- readonly: "readOnly",
- longdesc: "longDesc"
-};
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
-Element._attributeTranslations.values = {
- _getAttr: function(element, attribute) {
- return element.getAttribute(attribute, 2);
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
},
- _flag: function(element, attribute) {
- return $(element).hasAttribute(attribute) ? attribute : null;
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
},
- style: function(element) {
- return element.style.cssText.toLowerCase();
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
},
- title: function(element) {
- var node = element.getAttributeNode('title');
- return node.specified ? node.nodeValue : null;
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
}
};
-Object.extend(Element._attributeTranslations.values, {
- href: Element._attributeTranslations.values._getAttr,
- src: Element._attributeTranslations.values._getAttr,
- disabled: Element._attributeTranslations.values._flag,
- checked: Element._attributeTranslations.values._flag,
- readonly: Element._attributeTranslations.values._flag,
- multiple: Element._attributeTranslations.values._flag
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
});
-Element.Methods.Simulated = {
- hasAttribute: function(element, attribute) {
- var t = Element._attributeTranslations;
- attribute = t.names[attribute] || attribute;
- return $(element).getAttributeNode(attribute).specified;
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
}
};
-// IE is missing .innerHTML support for TABLE-related elements
-if (document.all && !window.opera){
- Element.Methods.update = function(element, html) {
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
+}
+
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
element = $(element);
- html = typeof html == 'undefined' ? '' : html.toString();
- var tagName = element.tagName.toUpperCase();
- if (['THEAD','TBODY','TR','TD'].include(tagName)) {
- var div = document.createElement('div');
- switch (tagName) {
- case 'THEAD':
- case 'TBODY':
- div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>';
- depth = 2;
- break;
- case 'TR':
- div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>';
- depth = 3;
- break;
- case 'TD':
- div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>';
- depth = 4;
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
}
- $A(element.childNodes).each(function(node){
- element.removeChild(node)
- });
- depth.times(function(){ div = div.firstChild });
+ }
+ };
- $A(div.childNodes).each(
- function(node){ element.appendChild(node) });
- } else {
- element.innerHTML = html.stripScripts();
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
}
- setTimeout(function() {html.evalScripts()}, 10);
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
}
};
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
Object.extend(Element, Element.Methods);
-var _nativeExtensions = false;
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
-if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))
- ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) {
- var className = 'HTML' + tag + 'Element';
- if(window[className]) return;
- var klass = window[className] = {};
- klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__;
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
});
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
Element.addMethods = function(methods) {
- Object.extend(Element.Methods, methods || {});
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
function copy(methods, destination, onlyIfAbsent) {
onlyIfAbsent = onlyIfAbsent || false;
- var cache = Element.extend.cache;
for (var property in methods) {
var value = methods[property];
+ if (!Object.isFunction(value)) continue;
if (!onlyIfAbsent || !(property in destination))
- destination[property] = cache.findOrStore(value);
+ destination[property] = value.methodize();
}
}
- if (typeof HTMLElement != 'undefined') {
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
copy(Element.Methods, HTMLElement.prototype);
copy(Element.Methods.Simulated, HTMLElement.prototype, true);
- copy(Form.Methods, HTMLFormElement.prototype);
- [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) {
- copy(Form.Element.Methods, klass.prototype);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
});
- _nativeExtensions = true;
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
}
-}
+};
+/* Portions of the Selector class are derived from Jack Slocum�۪s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
-var Toggle = new Object();
-Toggle.display = Element.toggle;
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
-/*--------------------------------------------------------------------------*/
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
-Abstract.Insertion = function(adjacency) {
- this.adjacency = adjacency;
-}
+ var e = this.expression;
-Abstract.Insertion.prototype = {
- initialize: function(element, content) {
- this.element = $(element);
- this.content = content.stripScripts();
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
- if (this.adjacency && this.element.insertAdjacentHTML) {
- try {
- this.element.insertAdjacentHTML(this.adjacency, this.content);
- } catch (e) {
- var tagName = this.element.tagName.toUpperCase();
- if (['TBODY', 'TR'].include(tagName)) {
- this.insertContent(this.contentFromAnonymousTable());
- } else {
- throw e;
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
}
}
- } else {
- this.range = this.element.ownerDocument.createRange();
- if (this.initializeRange) this.initializeRange();
- this.insertContent([this.range.createContextualFragment(this.content)]);
}
- setTimeout(function() {content.evalScripts()}, 10);
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
},
- contentFromAnonymousTable: function() {
- var div = document.createElement('div');
- div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
- return $A(div.childNodes[0].childNodes[0].childNodes);
- }
-}
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
-var Insertion = new Object();
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
-Insertion.Before = Class.create();
-Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
- initializeRange: function() {
- this.range.setStartBefore(this.element);
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
},
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.parentNode.insertBefore(fragment, this.element);
- }).bind(this));
- }
-});
-
-Insertion.Top = Class.create();
-Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
- initializeRange: function() {
- this.range.selectNodeContents(this.element);
- this.range.collapse(true);
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
},
- insertContent: function(fragments) {
- fragments.reverse(false).each((function(fragment) {
- this.element.insertBefore(fragment, this.element.firstChild);
- }).bind(this));
- }
-});
+ match: function(element) {
+ this.tokens = [];
-Insertion.Bottom = Class.create();
-Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
- initializeRange: function() {
- this.range.selectNodeContents(this.element);
- this.range.collapse(this.element);
- },
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.appendChild(fragment);
- }).bind(this));
- }
-});
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
-Insertion.After = Class.create();
-Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
- initializeRange: function() {
- this.range.setStartAfter(this.element);
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
},
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.parentNode.insertBefore(fragment,
- this.element.nextSibling);
- }).bind(this));
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
}
});
-/*--------------------------------------------------------------------------*/
+Object.extend(Selector, {
+ _cache: { },
-Element.ClassNames = Class.create();
-Element.ClassNames.prototype = {
- initialize: function(element) {
- this.element = $(element);
- },
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
- _each: function(iterator) {
- this.element.className.split(/\s+/).select(function(name) {
- return name.length > 0;
- })._each(iterator);
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
},
- set: function(className) {
- this.element.className = className;
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
},
- add: function(classNameToAdd) {
- if (this.include(classNameToAdd)) return;
- this.set($A(this).concat(classNameToAdd).join(' '));
- },
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
- remove: function(classNameToRemove) {
- if (!this.include(classNameToRemove)) return;
- this.set($A(this).without(classNameToRemove).join(' '));
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
},
- toString: function() {
- return $A(this).join(' ');
- }
-};
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
-Object.extend(Element.ClassNames.prototype, Enumerable);
-var Selector = Class.create();
-Selector.prototype = {
- initialize: function(expression) {
- this.params = {classNames: []};
- this.expression = expression.toString().strip();
- this.parseExpression();
- this.compileMatcher();
- },
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
- parseExpression: function() {
- function abort(message) { throw 'Parse error in selector: ' + message; }
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
- if (this.expression == '') abort('empty expression');
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
- var params = this.params, expr = this.expression, match, modifier, clause, rest;
- while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
- params.attributes = params.attributes || [];
- params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
- expr = match[1];
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
}
+ },
- if (expr == '*') return this.params.wildcard = true;
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
- while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
- modifier = match[1], clause = match[2], rest = match[3];
- switch (modifier) {
- case '#': params.id = clause; break;
- case '.': params.classNames.push(clause); break;
- case '':
- case undefined: params.tagName = clause.toUpperCase(); break;
- default: abort(expr.inspect());
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
}
- expr = rest;
- }
+ },
- if (expr.length > 0) abort(expr.inspect());
- },
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
- buildMatchExpression: function() {
- var params = this.params, conditions = [], clause;
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
- if (params.wildcard)
- conditions.push('true');
- if (clause = params.id)
- conditions.push('element.readAttribute("id") == ' + clause.inspect());
- if (clause = params.tagName)
- conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
- if ((clause = params.classNames).length > 0)
- for (var i = 0, length = clause.length; i < length; i++)
- conditions.push('element.hasClassName(' + clause[i].inspect() + ')');
- if (clause = params.attributes) {
- clause.each(function(attribute) {
- var value = 'element.readAttribute(' + attribute.name.inspect() + ')';
- var splitValueBy = function(delimiter) {
- return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
}
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
- switch (attribute.operator) {
- case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break;
- case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
- case '|=': conditions.push(
- splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
- ); break;
- case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break;
- case '':
- case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break;
- default: throw 'Unknown operator ' + attribute.operator + ' in selector';
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
}
- });
- }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
- return conditions.join(' && ');
- },
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
- compileMatcher: function() {
- this.match = new Function('element', 'if (!element.tagName) return false; \
- element = $(element); \
- return ' + this.buildMatchExpression());
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
},
- findElements: function(scope) {
- var element;
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
- if (element = $(this.params.id))
- if (this.match(element))
- if (!scope || Element.childOf(element, scope))
- return [element];
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
- scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
- var results = [];
- for (var i = 0, length = scope.length; i < length; i++)
- if (this.match(element = scope[i]))
- results.push(Element.extend(element));
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
- return results;
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
},
- toString: function() {
- return this.expression;
- }
-}
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
-Object.extend(Selector, {
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
matchElements: function(elements, expression) {
- var selector = new Selector(expression);
- return elements.select(selector.match.bind(selector)).map(Element.extend);
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
},
findElement: function(elements, expression, index) {
- if (typeof expression == 'number') index = expression, expression = false;
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
return Selector.matchElements(elements, expression || '*')[index || 0];
},
findChildElements: function(element, expressions) {
- return expressions.map(function(expression) {
- return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) {
- var selector = new Selector(expr);
- return results.inject([], function(elements, result) {
- return elements.concat(selector.findElements(result || element));
- });
- });
- }).flatten();
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
}
});
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
function $$() {
return Selector.findChildElements(document, $A(arguments));
}
@@ -1876,13 +3378,19 @@
return form;
},
- serializeElements: function(elements, getHash) {
- var data = elements.inject({}, function(result, element) {
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
if (!element.disabled && element.name) {
- var key = element.name, value = $(element).getValue();
- if (value != undefined) {
- if (result[key]) {
- if (result[key].constructor != Array) result[key] = [result[key]];
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
result[key].push(value);
}
else result[key] = value;
@@ -1891,13 +3399,13 @@
return result;
});
- return getHash ? data : Hash.toQueryString(data);
+ return options.hash ? data : Object.toQueryString(data);
}
};
Form.Methods = {
- serialize: function(form, getHash) {
- return Form.serializeElements(Form.getElements(form), getHash);
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
},
getElements: function(form) {
@@ -1928,37 +3436,54 @@
disable: function(form) {
form = $(form);
- form.getElements().each(function(element) {
- element.blur();
- element.disabled = 'true';
- });
+ Form.getElements(form).invoke('disable');
return form;
},
enable: function(form) {
form = $(form);
- form.getElements().each(function(element) {
- element.disabled = '';
- });
+ Form.getElements(form).invoke('enable');
return form;
},
findFirstElement: function(form) {
- return $(form).getElements().find(function(element) {
- return element.type != 'hidden' && !element.disabled &&
- ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
});
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
},
focusFirstElement: function(form) {
form = $(form);
form.findFirstElement().activate();
return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
}
-}
+};
-Object.extend(Form, Form.Methods);
-
/*--------------------------------------------------------------------------*/
Form.Element = {
@@ -1971,7 +3496,7 @@
$(element).select();
return element;
}
-}
+};
Form.Element.Methods = {
serialize: function(element) {
@@ -1979,9 +3504,9 @@
if (!element.disabled && element.name) {
var value = element.getValue();
if (value != undefined) {
- var pair = {};
+ var pair = { };
pair[element.name] = value;
- return Hash.toQueryString(pair);
+ return Object.toQueryString(pair);
}
}
return '';
@@ -1993,6 +3518,13 @@
return Form.Element.Serializers[method](element);
},
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
clear: function(element) {
$(element).value = '';
return element;
@@ -2004,55 +3536,75 @@
activate: function(element) {
element = $(element);
- element.focus();
- if (element.select && ( element.tagName.toLowerCase() != 'input' ||
- !['button', 'reset', 'submit'].include(element.type) ) )
- element.select();
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
return element;
},
disable: function(element) {
element = $(element);
+ element.blur();
element.disabled = true;
return element;
},
enable: function(element) {
element = $(element);
- element.blur();
element.disabled = false;
return element;
}
-}
+};
-Object.extend(Form.Element, Form.Element.Methods);
+/*--------------------------------------------------------------------------*/
+
var Field = Form.Element;
-var $F = Form.Element.getValue;
+var $F = Form.Element.Methods.getValue;
/*--------------------------------------------------------------------------*/
Form.Element.Serializers = {
- input: function(element) {
+ input: function(element, value) {
switch (element.type.toLowerCase()) {
case 'checkbox':
case 'radio':
- return Form.Element.Serializers.inputSelector(element);
+ return Form.Element.Serializers.inputSelector(element, value);
default:
- return Form.Element.Serializers.textarea(element);
+ return Form.Element.Serializers.textarea(element, value);
}
},
- inputSelector: function(element) {
- return element.checked ? element.value : null;
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
},
- textarea: function(element) {
- return element.value;
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
},
- select: function(element) {
- return this[element.type == 'select-one' ?
- 'selectOne' : 'selectMany'](element);
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
},
selectOne: function(element) {
@@ -2075,45 +3627,34 @@
// extend element because hasAttribute may not be native
return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
}
-}
+};
/*--------------------------------------------------------------------------*/
-Abstract.TimedObserver = function() {}
-Abstract.TimedObserver.prototype = {
- initialize: function(element, frequency, callback) {
- this.frequency = frequency;
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
this.element = $(element);
- this.callback = callback;
-
this.lastValue = this.getValue();
- this.registerCallback();
},
- registerCallback: function() {
- setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
- },
-
- onTimerEvent: function() {
+ execute: function() {
var value = this.getValue();
- var changed = ('string' == typeof this.lastValue && 'string' == typeof value
- ? this.lastValue != value : String(this.lastValue) != String(value));
- if (changed) {
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
this.callback(this.element, value);
this.lastValue = value;
}
}
-}
+});
-Form.Element.Observer = Class.create();
-Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
getValue: function() {
return Form.Element.getValue(this.element);
}
});
-Form.Observer = Class.create();
-Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+Form.Observer = Class.create(Abstract.TimedObserver, {
getValue: function() {
return Form.serialize(this.element);
}
@@ -2121,8 +3662,7 @@
/*--------------------------------------------------------------------------*/
-Abstract.EventObserver = function() {}
-Abstract.EventObserver.prototype = {
+Abstract.EventObserver = Class.create({
initialize: function(element, callback) {
this.element = $(element);
this.callback = callback;
@@ -2143,7 +3683,7 @@
},
registerFormCallbacks: function() {
- Form.getElements(this.element).each(this.registerCallback.bind(this));
+ Form.getElements(this.element).each(this.registerCallback, this);
},
registerCallback: function(element) {
@@ -2159,24 +3699,20 @@
}
}
}
-}
+});
-Form.Element.EventObserver = Class.create();
-Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
getValue: function() {
return Form.Element.getValue(this.element);
}
});
-Form.EventObserver = Class.create();
-Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+Form.EventObserver = Class.create(Abstract.EventObserver, {
getValue: function() {
return Form.serialize(this.element);
}
});
-if (!window.Event) {
- var Event = new Object();
-}
+if (!window.Event) var Event = { };
Object.extend(Event, {
KEY_BACKSPACE: 8,
@@ -2192,102 +3728,339 @@
KEY_END: 35,
KEY_PAGEUP: 33,
KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
- element: function(event) {
- return event.target || event.srcElement;
- },
+ cache: { },
- isLeftClick: function(event) {
- return (((event.which) && (event.which == 1)) ||
- ((event.button) && (event.button == 1)));
- },
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
- pointerX: function(event) {
- return event.pageX || (event.clientX +
- (document.documentElement.scrollLeft || document.body.scrollLeft));
- },
+Event.Methods = (function() {
+ var isButton;
- pointerY: function(event) {
- return event.pageY || (event.clientY +
- (document.documentElement.scrollTop || document.body.scrollTop));
- },
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
- stop: function(event) {
- if (event.preventDefault) {
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
event.preventDefault();
event.stopPropagation();
- } else {
- event.returnValue = false;
- event.cancelBubble = true;
+ event.stopped = true;
}
- },
+ };
+})();
- // find the first node with the given tagName, starting from the
- // node the event was triggered on; traverses the DOM upwards
- findElement: function(event, tagName) {
- var element = Event.element(event);
- while (element.parentNode && (!element.tagName ||
- (element.tagName.toUpperCase() != tagName.toUpperCase())))
- element = element.parentNode;
- return element;
- },
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
- observers: false,
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
- _observeAndCache: function(element, name, observer, useCapture) {
- if (!this.observers) this.observers = [];
- if (element.addEventListener) {
- this.observers.push([element, name, observer, useCapture]);
- element.addEventListener(name, observer, useCapture);
- } else if (element.attachEvent) {
- this.observers.push([element, name, observer, useCapture]);
- element.attachEvent('on' + name, observer);
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
}
- },
+ };
+})());
- unloadCache: function() {
- if (!Event.observers) return;
- for (var i = 0, length = Event.observers.length; i < length; i++) {
- Event.stopObserving.apply(this, Event.observers[i]);
- Event.observers[i][0] = null;
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
}
- Event.observers = false;
- },
- observe: function(element, name, observer, useCapture) {
- element = $(element);
- useCapture = useCapture || false;
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
- if (name == 'keypress' &&
- (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
- || element.attachEvent))
- name = 'keydown';
+Hash.toQueryString = Object.toQueryString;
- Event._observeAndCache(element, name, observer, useCapture);
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
},
- stopObserving: function(element, name, observer, useCapture) {
- element = $(element);
- useCapture = useCapture || false;
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
- if (name == 'keypress' &&
- (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
- || element.detachEvent))
- name = 'keydown';
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
- if (element.removeEventListener) {
- element.removeEventListener(name, observer, useCapture);
- } else if (element.detachEvent) {
- try {
- element.detachEvent('on' + name, observer);
- } catch (e) {}
- }
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
}
-});
+};
-/* prevent memory leaks in IE */
-if (navigator.appVersion.match(/\bMSIE\b/))
- Event.observe(window, 'unload', Event.unloadCache, false);
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
var Position = {
// set to true if needed, warning: firefox performance problems
// NOT neeeded for page scrolling, only if draggable contained in
@@ -2307,59 +4080,13 @@
|| 0;
},
- realOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.scrollTop || 0;
- valueL += element.scrollLeft || 0;
- element = element.parentNode;
- } while (element);
- return [valueL, valueT];
- },
-
- cumulativeOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- } while (element);
- return [valueL, valueT];
- },
-
- positionedOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- if (element) {
- if(element.tagName=='BODY') break;
- var p = Element.getStyle(element, 'position');
- if (p == 'relative' || p == 'absolute') break;
- }
- } while (element);
- return [valueL, valueT];
- },
-
- offsetParent: function(element) {
- if (element.offsetParent) return element.offsetParent;
- if (element == document.body) return element;
-
- while ((element = element.parentNode) && element != document.body)
- if (Element.getStyle(element, 'position') != 'static')
- return element;
-
- return document.body;
- },
-
// caches x/y coordinate pair to use with overlap
within: function(element, x, y) {
if (this.includeScrollOffsets)
return this.withinIncludingScrolloffsets(element, x, y);
this.xcomp = x;
this.ycomp = y;
- this.offset = this.cumulativeOffset(element);
+ this.offset = Element.cumulativeOffset(element);
return (y >= this.offset[1] &&
y < this.offset[1] + element.offsetHeight &&
@@ -2368,11 +4095,11 @@
},
withinIncludingScrolloffsets: function(element, x, y) {
- var offsetcache = this.realOffset(element);
+ var offsetcache = Element.cumulativeScrollOffset(element);
this.xcomp = x + offsetcache[0] - this.deltaX;
this.ycomp = y + offsetcache[1] - this.deltaY;
- this.offset = this.cumulativeOffset(element);
+ this.offset = Element.cumulativeOffset(element);
return (this.ycomp >= this.offset[1] &&
this.ycomp < this.offset[1] + element.offsetHeight &&
@@ -2391,125 +4118,104 @@
element.offsetWidth;
},
- page: function(forElement) {
- var valueT = 0, valueL = 0;
+ // Deprecation layer -- use newer Element methods now (1.5.2).
- var element = forElement;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
+ cumulativeOffset: Element.Methods.cumulativeOffset,
- // Safari fix
- if (element.offsetParent==document.body)
- if (Element.getStyle(element,'position')=='absolute') break;
+ positionedOffset: Element.Methods.positionedOffset,
- } while (element = element.offsetParent);
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
- element = forElement;
- do {
- if (!window.opera || element.tagName=='BODY') {
- valueT -= element.scrollTop || 0;
- valueL -= element.scrollLeft || 0;
- }
- } while (element = element.parentNode);
-
- return [valueL, valueT];
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
},
- clone: function(source, target) {
- var options = Object.extend({
- setLeft: true,
- setTop: true,
- setWidth: true,
- setHeight: true,
- offsetTop: 0,
- offsetLeft: 0
- }, arguments[2] || {})
+ realOffset: Element.Methods.cumulativeScrollOffset,
- // find page position of source
- source = $(source);
- var p = Position.page(source);
+ offsetParent: Element.Methods.getOffsetParent,
- // find coordinate system to use
- target = $(target);
- var delta = [0, 0];
- var parent = null;
- // delta [0,0] will do fine with position: fixed elements,
- // position:absolute needs offsetParent deltas
- if (Element.getStyle(target,'position') == 'absolute') {
- parent = Position.offsetParent(target);
- delta = Position.page(parent);
- }
+ page: Element.Methods.viewportOffset,
- // correct by body offsets (fixes Safari)
- if (parent == document.body) {
- delta[0] -= document.body.offsetLeft;
- delta[1] -= document.body.offsetTop;
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
}
+ return elements;
+ };
- // set position
- if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
- if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
- if(options.setWidth) target.style.width = source.offsetWidth + 'px';
- if(options.setHeight) target.style.height = source.offsetHeight + 'px';
- },
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
- absolutize: function(element) {
- element = $(element);
- if (element.style.position == 'absolute') return;
- Position.prepare();
+/*--------------------------------------------------------------------------*/
- var offsets = Position.positionedOffset(element);
- var top = offsets[1];
- var left = offsets[0];
- var width = element.clientWidth;
- var height = element.clientHeight;
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
- element._originalLeft = left - parseFloat(element.style.left || 0);
- element._originalTop = top - parseFloat(element.style.top || 0);
- element._originalWidth = element.style.width;
- element._originalHeight = element.style.height;
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
- element.style.position = 'absolute';
- element.style.top = top + 'px';
- element.style.left = left + 'px';
- element.style.width = width + 'px';
- element.style.height = height + 'px';
+ set: function(className) {
+ this.element.className = className;
},
- relativize: function(element) {
- element = $(element);
- if (element.style.position == 'relative') return;
- Position.prepare();
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
- element.style.position = 'relative';
- var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
- var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
- element.style.top = top + 'px';
- element.style.left = left + 'px';
- element.style.height = element._originalHeight;
- element.style.width = element._originalWidth;
+ toString: function() {
+ return $A(this).join(' ');
}
-}
+};
-// Safari returns margins on body which is incorrect if the child is absolutely
-// positioned. For performance reasons, redefine Position.cumulativeOffset for
-// KHTML/WebKit only.
-if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
- Position.cumulativeOffset = function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- if (element.offsetParent == document.body)
- if (Element.getStyle(element, 'position') == 'absolute') break;
+Object.extend(Element.ClassNames.prototype, Enumerable);
- element = element.offsetParent;
- } while (element);
+/*--------------------------------------------------------------------------*/
- return [valueL, valueT];
- }
-}
-
Element.addMethods();
\ No newline at end of file
Modified: branches/JBoss_Portal_Branch_2_7/theme/src/bin/theme-test-war/core/lib/prototype.js
===================================================================
--- branches/JBoss_Portal_Branch_2_7/theme/src/bin/theme-test-war/core/lib/prototype.js 2008-04-24 13:49:28 UTC (rev 10714)
+++ branches/JBoss_Portal_Branch_2_7/theme/src/bin/theme-test-war/core/lib/prototype.js 2008-04-25 00:34:57 UTC (rev 10715)
@@ -1,98 +1,289 @@
-/* Prototype JavaScript framework, version 1.5.0_rc0
- * (c) 2005 Sam Stephenson <sam(a)conio.net>
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style license.
- * For details, see the Prototype web site: http://prototype.conio.net/
+ * For details, see the Prototype web site: http://www.prototypejs.org/
*
-/*--------------------------------------------------------------------------*/
+ *--------------------------------------------------------------------------*/
var Prototype = {
- Version: '1.5.0_rc0',
- ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
+ Version: '1.6.0.2',
- emptyFunction: function() {},
- K: function(x) {return x}
-}
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
var Class = {
create: function() {
- return function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
this.initialize.apply(this, arguments);
}
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
}
-}
+};
-var Abstract = new Object();
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
Object.extend = function(destination, source) {
- for (var property in source) {
+ for (var property in source)
destination[property] = source[property];
- }
return destination;
-}
+};
-Object.inspect = function(object) {
- try {
- if (object == undefined) return 'undefined';
- if (object == null) return 'null';
- return object.inspect ? object.inspect() : object.toString();
- } catch (e) {
- if (e instanceof RangeError) return '...';
- throw e;
- }
-}
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (Object.isUndefined(object)) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : String(object);
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
-Function.prototype.bind = function() {
- var __method = this, args = $A(arguments), object = args.shift();
- return function() {
- return __method.apply(object, args.concat($A(arguments)));
- }
-}
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
-Function.prototype.bindAsEventListener = function(object) {
- var __method = this;
- return function(event) {
- return __method.call(object, event || window.event);
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (!Object.isUndefined(value))
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
}
-}
+});
-Object.extend(Number.prototype, {
- toColorPart: function() {
- var digits = this.toString(16);
- if (this < 16) return '0' + digits;
- return digits;
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
},
- succ: function() {
- return this + 1;
+ bind: function() {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
},
- times: function(iterator) {
- $R(0, this, true).each(iterator);
- return this;
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
}
});
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
var Try = {
these: function() {
var returnValue;
- for (var i = 0; i < arguments.length; i++) {
+ for (var i = 0, length = arguments.length; i < length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
break;
- } catch (e) {}
+ } catch (e) { }
}
return returnValue;
}
-}
+};
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
/*--------------------------------------------------------------------------*/
-var PeriodicalExecuter = Class.create();
-PeriodicalExecuter.prototype = {
+var PeriodicalExecuter = Class.create({
initialize: function(callback, frequency) {
this.callback = callback;
this.frequency = frequency;
@@ -102,20 +293,44 @@
},
registerCallback: function() {
- setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
onTimerEvent: function() {
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
- this.callback();
+ this.execute();
} finally {
this.currentlyExecuting = false;
}
}
}
-}
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
Object.extend(String.prototype, {
gsub: function(pattern, replacement) {
var result = '', source = this, match;
@@ -124,7 +339,7 @@
while (source.length > 0) {
if (match = source.match(pattern)) {
result += source.slice(0, match.index);
- result += (replacement(match) || '').toString();
+ result += String.interpret(replacement(match));
source = source.slice(match.index + match[0].length);
} else {
result += source, source = '';
@@ -135,7 +350,7 @@
sub: function(pattern, replacement, count) {
replacement = this.gsub.prepareReplacement(replacement);
- count = count === undefined ? 1 : count;
+ count = Object.isUndefined(count) ? 1 : count;
return this.gsub(pattern, function(match) {
if (--count < 0) return match[0];
@@ -145,14 +360,14 @@
scan: function(pattern, iterator) {
this.gsub(pattern, iterator);
- return this;
+ return String(this);
},
truncate: function(length, truncation) {
length = length || 30;
- truncation = truncation === undefined ? '...' : truncation;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
return this.length > length ?
- this.slice(0, length - truncation.length) + truncation : this;
+ this.slice(0, length - truncation.length) + truncation : String(this);
},
strip: function() {
@@ -180,24 +395,36 @@
},
escapeHTML: function() {
- var div = document.createElement('div');
- var text = document.createTextNode(this);
- div.appendChild(text);
- return div.innerHTML;
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
},
unescapeHTML: function() {
- var div = document.createElement('div');
+ var div = new Element('div');
div.innerHTML = this.stripTags();
- return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
},
- toQueryParams: function() {
- var pairs = this.match(/^\??(.*)$/)[1].split('&');
- return pairs.inject({}, function(params, pairString) {
- var pair = pairString.split('=');
- params[pair[0]] = pair[1];
- return params;
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
});
},
@@ -205,90 +432,204 @@
return this.split('');
},
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
camelize: function() {
- var oStringList = this.split('-');
- if (oStringList.length == 1) return oStringList[0];
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
- var camelizedString = this.indexOf('-') == 0
- ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
- : oStringList[0];
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
- for (var i = 1, len = oStringList.length; i < len; i++) {
- var s = oStringList[i];
- camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
- }
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
- return camelizedString;
+ return camelized;
},
- inspect: function() {
- return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'";
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this;
+ if (str.blank()) return false;
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
}
});
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ }
+});
+
String.prototype.gsub.prepareReplacement = function(replacement) {
- if (typeof replacement == 'function') return replacement;
+ if (Object.isFunction(replacement)) return replacement;
var template = new Template(replacement);
return function(match) { return template.evaluate(match) };
-}
+};
String.prototype.parseQuery = String.prototype.toQueryParams;
-var Template = Class.create();
-Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
-Template.prototype = {
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
initialize: function(template, pattern) {
this.template = template.toString();
- this.pattern = pattern || Template.Pattern;
+ this.pattern = pattern || Template.Pattern;
},
evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
return this.template.gsub(this.pattern, function(match) {
- var before = match[1];
+ if (object == null) return '';
+
+ var before = match[1] || '';
if (before == '\\') return match[2];
- return before + (object[match[3]] || '').toString();
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+ match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
});
}
-}
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
-var $break = new Object();
-var $continue = new Object();
+var $break = { };
var Enumerable = {
- each: function(iterator) {
+ each: function(iterator, context) {
var index = 0;
+ iterator = iterator.bind(context);
try {
this._each(function(value) {
- try {
- iterator(value, index++);
- } catch (e) {
- if (e != $continue) throw e;
- }
+ iterator(value, index++);
});
} catch (e) {
if (e != $break) throw e;
}
+ return this;
},
- all: function(iterator) {
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var result = true;
this.each(function(value, index) {
- result = result && !!(iterator || Prototype.K)(value, index);
+ result = result && !!iterator(value, index);
if (!result) throw $break;
});
return result;
},
- any: function(iterator) {
- var result = true;
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
this.each(function(value, index) {
- if (result = !!(iterator || Prototype.K)(value, index))
+ if (result = !!iterator(value, index))
throw $break;
});
return result;
},
- collect: function(iterator) {
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var results = [];
this.each(function(value, index) {
results.push(iterator(value, index));
@@ -296,7 +637,8 @@
return results;
},
- detect: function (iterator) {
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
var result;
this.each(function(value, index) {
if (iterator(value, index)) {
@@ -307,7 +649,8 @@
return result;
},
- findAll: function(iterator) {
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
var results = [];
this.each(function(value, index) {
if (iterator(value, index))
@@ -316,17 +659,24 @@
return results;
},
- grep: function(pattern, iterator) {
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
this.each(function(value, index) {
- var stringValue = value.toString();
- if (stringValue.match(pattern))
- results.push((iterator || Prototype.K)(value, index));
- })
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
return results;
},
include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
var found = false;
this.each(function(value) {
if (value == object) {
@@ -337,7 +687,16 @@
return found;
},
- inject: function(memo, iterator) {
+ inGroupsOf: function(number, fillWith) {
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
this.each(function(value, index) {
memo = iterator(memo, value, index);
});
@@ -346,35 +705,38 @@
invoke: function(method) {
var args = $A(arguments).slice(1);
- return this.collect(function(value) {
+ return this.map(function(value) {
return value[method].apply(value, args);
});
},
- max: function(iterator) {
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var result;
this.each(function(value, index) {
- value = (iterator || Prototype.K)(value, index);
- if (result == undefined || value >= result)
+ value = iterator(value, index);
+ if (result == null || value >= result)
result = value;
});
return result;
},
- min: function(iterator) {
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var result;
this.each(function(value, index) {
- value = (iterator || Prototype.K)(value, index);
- if (result == undefined || value < result)
+ value = iterator(value, index);
+ if (result == null || value < result)
result = value;
});
return result;
},
- partition: function(iterator) {
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
var trues = [], falses = [];
this.each(function(value, index) {
- ((iterator || Prototype.K)(value, index) ?
+ (iterator(value, index) ?
trues : falses).push(value);
});
return [trues, falses];
@@ -382,13 +744,14 @@
pluck: function(property) {
var results = [];
- this.each(function(value, index) {
+ this.each(function(value) {
results.push(value[property]);
});
return results;
},
- reject: function(iterator) {
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
var results = [];
this.each(function(value, index) {
if (!iterator(value, index))
@@ -397,8 +760,9 @@
return results;
},
- sortBy: function(iterator) {
- return this.collect(function(value, index) {
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
return {value: value, criteria: iterator(value, index)};
}).sort(function(left, right) {
var a = left.criteria, b = right.criteria;
@@ -407,12 +771,12 @@
},
toArray: function() {
- return this.collect(Prototype.K);
+ return this.map();
},
zip: function() {
var iterator = Prototype.K, args = $A(arguments);
- if (typeof args.last() == 'function')
+ if (Object.isFunction(args.last()))
iterator = args.pop();
var collections = [this].concat(args).map($A);
@@ -421,38 +785,53 @@
});
},
+ size: function() {
+ return this.toArray().length;
+ },
+
inspect: function() {
return '#<Enumerable:' + this.toArray().inspect() + '>';
}
-}
+};
Object.extend(Enumerable, {
map: Enumerable.collect,
find: Enumerable.detect,
select: Enumerable.findAll,
+ filter: Enumerable.findAll,
member: Enumerable.include,
- entries: Enumerable.toArray
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
});
-var $A = Array.from = function(iterable) {
+function $A(iterable) {
if (!iterable) return [];
- if (iterable.toArray) {
- return iterable.toArray();
- } else {
- var results = [];
- for (var i = 0; i < iterable.length; i++)
- results.push(iterable[i]);
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ $A = function(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length || 0, results = new Array(length);
+ while (length--) results[length] = iterable[length];
return results;
- }
+ };
}
+Array.from = $A;
+
Object.extend(Array.prototype, Enumerable);
-if (!Array.prototype._reverse)
- Array.prototype._reverse = Array.prototype.reverse;
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
Object.extend(Array.prototype, {
_each: function(iterator) {
- for (var i = 0; i < this.length; i++)
+ for (var i = 0, length = this.length; i < length; i++)
iterator(this[i]);
},
@@ -471,13 +850,13 @@
compact: function() {
return this.select(function(value) {
- return value != undefined || value != null;
+ return value != null;
});
},
flatten: function() {
return this.inject([], function(array, value) {
- return array.concat(value && value.constructor == Array ?
+ return array.concat(Object.isArray(value) ?
value.flatten() : [value]);
});
},
@@ -489,70 +868,219 @@
});
},
- indexOf: function(object) {
- for (var i = 0; i < this.length; i++)
- if (this[i] == object) return i;
- return -1;
- },
-
reverse: function(inline) {
return (inline !== false ? this : this.toArray())._reverse();
},
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
inspect: function() {
return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (!Object.isUndefined(value)) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
}
});
-var Hash = {
- _each: function(iterator) {
- for (var key in this) {
- var value = this[key];
- if (typeof value == 'function') continue;
- var pair = [key, value];
- pair.key = key;
- pair.value = value;
- iterator(pair);
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
}
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
},
- keys: function() {
- return this.pluck('key');
+ succ: function() {
+ return this + 1;
},
- values: function() {
- return this.pluck('value');
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
},
- merge: function(hash) {
- return $H(hash).inject($H(this), function(mergedHash, pair) {
- mergedHash[pair.key] = pair.value;
- return mergedHash;
- });
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
},
- toQueryString: function() {
- return this.map(function(pair) {
- return pair.map(encodeURIComponent).join('=');
- }).join('&');
- },
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
- inspect: function() {
- return '#<Hash:{' + this.map(function(pair) {
- return pair.map(Object.inspect).join(': ');
- }).join(', ') + '}>';
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
}
-}
-function $H(object) {
- var hash = Object.extend({}, object || {});
- Object.extend(hash, Enumerable);
- Object.extend(hash, Hash);
- return hash;
-}
-ObjectRange = Class.create();
-Object.extend(ObjectRange.prototype, Enumerable);
-Object.extend(ObjectRange.prototype, {
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: function(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
initialize: function(start, end, exclusive) {
this.start = start;
this.end = end;
@@ -561,10 +1089,10 @@
_each: function(iterator) {
var value = this.start;
- do {
+ while (this.include(value)) {
iterator(value);
value = value.succ();
- } while (this.include(value));
+ }
},
include: function(value) {
@@ -578,7 +1106,7 @@
var $R = function(start, end, exclusive) {
return new ObjectRange(start, end, exclusive);
-}
+};
var Ajax = {
getTransport: function() {
@@ -590,7 +1118,7 @@
},
activeRequestCount: 0
-}
+};
Ajax.Responders = {
responders: [],
@@ -599,21 +1127,21 @@
this.responders._each(iterator);
},
- register: function(responderToAdd) {
- if (!this.include(responderToAdd))
- this.responders.push(responderToAdd);
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
},
- unregister: function(responderToRemove) {
- this.responders = this.responders.without(responderToRemove);
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
},
dispatch: function(callback, request, transport, json) {
this.each(function(responder) {
- if (responder[callback] && typeof responder[callback] == 'function') {
+ if (Object.isFunction(responder[callback])) {
try {
responder[callback].apply(responder, [request, transport, json]);
- } catch (e) {}
+ } catch (e) { }
}
});
}
@@ -622,218 +1150,324 @@
Object.extend(Ajax.Responders, Enumerable);
Ajax.Responders.register({
- onCreate: function() {
- Ajax.activeRequestCount++;
- },
-
- onComplete: function() {
- Ajax.activeRequestCount--;
- }
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
});
-Ajax.Base = function() {};
-Ajax.Base.prototype = {
- setOptions: function(options) {
+Ajax.Base = Class.create({
+ initialize: function(options) {
this.options = {
method: 'post',
asynchronous: true,
contentType: 'application/x-www-form-urlencoded',
- parameters: ''
- }
- Object.extend(this.options, options || {});
- },
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
- responseIsSuccess: function() {
- return this.transport.status == undefined
- || this.transport.status == 0
- || (this.transport.status >= 200 && this.transport.status < 300);
- },
+ this.options.method = this.options.method.toLowerCase();
- responseIsFailure: function() {
- return !this.responseIsSuccess();
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ else if (Object.isHash(this.options.parameters))
+ this.options.parameters = this.options.parameters.toObject();
}
-}
+});
-Ajax.Request = Class.create();
-Ajax.Request.Events =
- ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
-Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
- initialize: function(url, options) {
+ initialize: function($super, url, options) {
+ $super(options);
this.transport = Ajax.getTransport();
- this.setOptions(options);
this.request(url);
},
request: function(url) {
- var parameters = this.options.parameters || '';
- if (parameters.length > 0) parameters += '&_=';
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
try {
- this.url = url;
- if (this.options.method == 'get' && parameters.length > 0)
- this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
- Ajax.Responders.dispatch('onCreate', this, this.transport);
-
- this.transport.open(this.options.method, this.url,
+ this.transport.open(this.method.toUpperCase(), this.url,
this.options.asynchronous);
- if (this.options.asynchronous) {
- this.transport.onreadystatechange = this.onStateChange.bind(this);
- setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
- }
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
this.setRequestHeaders();
- var body = this.options.postBody ? this.options.postBody : parameters;
- this.transport.send(this.options.method == 'post' ? body : null);
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
- } catch (e) {
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
this.dispatchException(e);
}
},
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
setRequestHeaders: function() {
- var requestHeaders =
- ['X-Requested-With', 'XMLHttpRequest',
- 'X-Prototype-Version', Prototype.Version,
- 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*'];
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
- if (this.options.method == 'post') {
- requestHeaders.push('Content-type', this.options.contentType);
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
- /* Force "Connection: close" for Mozilla browsers to work around
- * a bug where XMLHttpReqeuest sends an incorrect Content-length
- * header. See Mozilla Bugzilla #246651.
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
*/
- if (this.transport.overrideMimeType)
- requestHeaders.push('Connection', 'close');
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
}
- if (this.options.requestHeaders)
- requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
- for (var i = 0; i < requestHeaders.length; i += 2)
- this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
- },
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
- onStateChange: function() {
- var readyState = this.transport.readyState;
- if (readyState != 1)
- this.respondToReadyState(this.transport.readyState);
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
},
- header: function(name) {
- try {
- return this.transport.getResponseHeader(name);
- } catch (e) {}
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
},
- evalJSON: function() {
+ getStatus: function() {
try {
- return eval('(' + this.header('X-JSON') + ')');
- } catch (e) {}
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
},
- evalResponse: function() {
- try {
- return eval(this.transport.responseText);
- } catch (e) {
- this.dispatchException(e);
- }
- },
-
respondToReadyState: function(readyState) {
- var event = Ajax.Request.Events[readyState];
- var transport = this.transport, json = this.evalJSON();
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
- if (event == 'Complete') {
+ if (state == 'Complete') {
try {
- (this.options['on' + this.transport.status]
- || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
- || Prototype.emptyFunction)(transport, json);
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
} catch (e) {
this.dispatchException(e);
}
- if ((this.header('Content-type') || '').match(/^text\/javascript/i))
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && this.isSameOrigin() && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
this.evalResponse();
}
try {
- (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
- Ajax.Responders.dispatch('on' + event, this, transport, json);
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
} catch (e) {
this.dispatchException(e);
}
- /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
- if (event == 'Complete')
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
},
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name) || null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
dispatchException: function(exception) {
(this.options.onException || Prototype.emptyFunction)(this, exception);
Ajax.Responders.dispatch('onException', this, exception);
}
});
-Ajax.Updater = Class.create();
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
-Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
- initialize: function(container, url, options) {
- this.containers = {
- success: container.success ? $(container.success) : $(container),
- failure: container.failure ? $(container.failure) :
- (container.success ? null : $(container))
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
}
- this.transport = Ajax.getTransport();
- this.setOptions(options);
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
- var onComplete = this.options.onComplete || Prototype.emptyFunction;
- this.options.onComplete = (function(transport, object) {
- this.updateContent();
- onComplete(transport, object);
- }).bind(this);
+ status: 0,
+ statusText: '',
- this.request(url);
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
},
- updateContent: function() {
- var receiver = this.responseIsSuccess() ?
- this.containers.success : this.containers.failure;
- var response = this.transport.responseText;
+ getHeader: Ajax.Request.prototype.getHeader,
- if (!this.options.evalScripts)
- response = response.stripScripts();
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
- if (receiver) {
- if (this.options.insertion) {
- new this.options.insertion(receiver, response);
- } else {
- Element.update(receiver, response);
- }
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
}
+ },
- if (this.responseIsSuccess()) {
- if (this.onComplete)
- setTimeout(this.onComplete.bind(this), 10);
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
+ this.responseText.blank())
+ return null;
+ try {
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
+ } catch (e) {
+ this.request.dispatchException(e);
}
}
});
-Ajax.PeriodicalUpdater = Class.create();
-Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
- initialize: function(container, url, options) {
- this.setOptions(options);
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = Object.clone(options);
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, json) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, json);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
this.onComplete = this.options.onComplete;
this.frequency = (this.options.frequency || 2);
this.decay = (this.options.decay || 1);
- this.updater = {};
+ this.updater = { };
this.container = container;
this.url = url;
@@ -846,204 +1480,462 @@
},
stop: function() {
- this.updater.onComplete = undefined;
+ this.updater.options.onComplete = undefined;
clearTimeout(this.timer);
(this.onComplete || Prototype.emptyFunction).apply(this, arguments);
},
- updateComplete: function(request) {
+ updateComplete: function(response) {
if (this.options.decay) {
- this.decay = (request.responseText == this.lastText ?
+ this.decay = (response.responseText == this.lastText ?
this.decay * this.options.decay : 1);
- this.lastText = request.responseText;
+ this.lastText = response.responseText;
}
- this.timer = setTimeout(this.onTimerEvent.bind(this),
- this.decay * this.frequency * 1000);
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
},
onTimerEvent: function() {
this.updater = new Ajax.Updater(this.container, this.url, this.options);
}
});
-function $() {
- var results = [], element;
- for (var i = 0; i < arguments.length; i++) {
- element = arguments[i];
- if (typeof element == 'string')
- element = document.getElementById(element);
- results.push(Element.extend(element));
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
}
- return results.length < 2 ? results[0] : results;
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
}
-document.getElementsByClassName = function(className, parentElement) {
- var children = ($(parentElement) || document.body).getElementsByTagName('*');
- return $A(children).inject([], function(elements, child) {
- if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
- elements.push(Element.extend(child));
- return elements;
- });
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
}
/*--------------------------------------------------------------------------*/
-if (!window.Element)
- var Element = new Object();
+if (!window.Node) var Node = { };
-Element.extend = function(element) {
- if (!element) return;
- if (_nativeExtensions) return element;
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
- if (!element._extended && element.tagName && element != window) {
- var methods = Element.Methods, cache = Element.extend.cache;
- for (property in methods) {
- var value = methods[property];
- if (typeof value == 'function')
- element[property] = cache.findOrStore(value);
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
}
- }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
- element._extended = true;
- return element;
-}
+Element.cache = { };
-Element.extend.cache = {
- findOrStore: function(value) {
- return this[value] = this[value] || function() {
- return value.apply(null, [this].concat($A(arguments)));
- }
- }
-}
-
Element.Methods = {
visible: function(element) {
return $(element).style.display != 'none';
},
- toggle: function() {
- for (var i = 0; i < arguments.length; i++) {
- var element = $(arguments[i]);
- Element[Element.visible(element) ? 'hide' : 'show'](element);
- }
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
},
- hide: function() {
- for (var i = 0; i < arguments.length; i++) {
- var element = $(arguments[i]);
- element.style.display = 'none';
- }
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
},
- show: function() {
- for (var i = 0; i < arguments.length; i++) {
- var element = $(arguments[i]);
- element.style.display = '';
- }
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
},
remove: function(element) {
element = $(element);
element.parentNode.removeChild(element);
+ return element;
},
- update: function(element, html) {
- $(element).innerHTML = html.stripScripts();
- setTimeout(function() {html.evalScripts()}, 10);
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
},
- replace: function(element, html) {
+ replace: function(element, content) {
element = $(element);
- if (element.outerHTML) {
- element.outerHTML = html.stripScripts();
- } else {
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
var range = element.ownerDocument.createRange();
- range.selectNodeContents(element);
- element.parentNode.replaceChild(
- range.createContextualFragment(html.stripScripts()), element);
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
}
- setTimeout(function() {html.evalScripts()}, 10);
+ element.parentNode.replaceChild(content, element);
+ return element;
},
- getHeight: function(element) {
+ insert: function(element, insertions) {
element = $(element);
- return element.offsetHeight;
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, insert, tagName, childNodes;
+
+ for (var position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ insert = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
},
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $(element).select("*");
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = Object.isUndefined(value) ? true : value;
+
+ for (var attr in attributes) {
+ name = t.names[attr] || attr;
+ value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
classNames: function(element) {
return new Element.ClassNames(element);
},
hasClassName: function(element, className) {
if (!(element = $(element))) return;
- return Element.classNames(element).include(className);
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
},
addClassName: function(element, className) {
if (!(element = $(element))) return;
- return Element.classNames(element).add(className);
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
},
removeClassName: function(element, className) {
if (!(element = $(element))) return;
- return Element.classNames(element).remove(className);
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
},
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
// removes whitespace-only text node children
cleanWhitespace: function(element) {
element = $(element);
- for (var i = 0; i < element.childNodes.length; i++) {
- var node = element.childNodes[i];
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
- Element.remove(node);
+ element.removeChild(node);
+ node = nextNode;
}
+ return element;
},
empty: function(element) {
- return $(element).innerHTML.match(/^\s*$/);
+ return $(element).innerHTML.blank();
},
- childOf: function(element, ancestor) {
+ descendantOf: function(element, ancestor) {
element = $(element), ancestor = $(ancestor);
+ var originalAncestor = ancestor;
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
+ }
+
while (element = element.parentNode)
- if (element == ancestor) return true;
+ if (element == originalAncestor) return true;
return false;
},
scrollTo: function(element) {
element = $(element);
- var x = element.x ? element.x : element.offsetLeft,
- y = element.y ? element.y : element.offsetTop;
- window.scrollTo(x, y);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
},
getStyle: function(element, style) {
element = $(element);
- var value = element.style[style.camelize()];
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
if (!value) {
- if (document.defaultView && document.defaultView.getComputedStyle) {
- var css = document.defaultView.getComputedStyle(element, null);
- value = css ? css.getPropertyValue(style) : null;
- } else if (element.currentStyle) {
- value = element.currentStyle[style.camelize()];
- }
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
}
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
- if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
- if (Element.getStyle(element, 'position') == 'static') value = 'auto';
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
- return value == 'auto' ? null : value;
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
},
- setStyle: function(element, style) {
+ setOpacity: function(element, value) {
element = $(element);
- for (var name in style)
- element.style[name.camelize()] = style[name];
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
},
getDimensions: function(element) {
element = $(element);
- if (Element.getStyle(element, 'display') != 'none')
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
return {width: element.offsetWidth, height: element.offsetHeight};
// All *Width and *Height properties give 0 on elements with display none,
@@ -1051,12 +1943,13 @@
var els = element.style;
var originalVisibility = els.visibility;
var originalPosition = els.position;
+ var originalDisplay = els.display;
els.visibility = 'hidden';
els.position = 'absolute';
- els.display = '';
+ els.display = 'block';
var originalWidth = element.clientWidth;
var originalHeight = element.clientHeight;
- els.display = 'none';
+ els.display = originalDisplay;
els.position = originalPosition;
els.visibility = originalVisibility;
return {width: originalWidth, height: originalHeight};
@@ -1075,6 +1968,7 @@
element.style.left = 0;
}
}
+ return element;
},
undoPositioned: function(element) {
@@ -1087,518 +1981,1680 @@
element.style.bottom =
element.style.right = '';
}
+ return element;
},
makeClipping: function(element) {
element = $(element);
- if (element._overflow) return;
- element._overflow = element.style.overflow;
- if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
element.style.overflow = 'hidden';
+ return element;
},
undoClipping: function(element) {
element = $(element);
- if (element._overflow) return;
- element.style.overflow = element._overflow;
- element._overflow = undefined;
- }
-}
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
-Object.extend(Element, Element.Methods);
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
-var _nativeExtensions = false;
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
-if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
- var HTMLElement = {}
- HTMLElement.prototype = document.createElement('div').__proto__;
-}
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
-Element.addMethods = function(methods) {
- Object.extend(Element.Methods, methods || {});
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
- if(typeof HTMLElement != 'undefined') {
- var methods = Element.Methods, cache = Element.extend.cache;
- for (property in methods) {
- var value = methods[property];
- if (typeof value == 'function')
- HTMLElement.prototype[property] = cache.findOrStore(value);
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
}
- _nativeExtensions = true;
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
}
-}
+};
-Element.addMethods();
+Element.Methods.identify.counter = 1;
-var Toggle = new Object();
-Toggle.display = Element.toggle;
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
-/*--------------------------------------------------------------------------*/
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
-Abstract.Insertion = function(adjacency) {
- this.adjacency = adjacency;
+if (Prototype.Browser.Opera) {
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+ function(proceed, element, style) {
+ switch (style) {
+ case 'left': case 'top': case 'right': case 'bottom':
+ if (proceed(element, 'position') === 'static') return null;
+ case 'height': case 'width':
+ // returns '0px' for hidden elements; we want it to return null
+ if (!Element.visible(element)) return null;
+
+ // returns the border-box dimensions rather than the content-box
+ // dimensions, so we subtract padding and borders from the value
+ var dim = parseInt(proceed(element, style), 10);
+
+ if (dim !== element['offset' + style.capitalize()])
+ return dim + 'px';
+
+ var properties;
+ if (style === 'height') {
+ properties = ['border-top-width', 'padding-top',
+ 'padding-bottom', 'border-bottom-width'];
+ }
+ else {
+ properties = ['border-left-width', 'padding-left',
+ 'padding-right', 'border-right-width'];
+ }
+ return properties.inject(dim, function(memo, property) {
+ var val = proceed(element, property);
+ return val === null ? memo : memo - parseInt(val, 10);
+ }) + 'px';
+ default: return proceed(element, style);
+ }
+ }
+ );
+
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+ function(proceed, element, attribute) {
+ if (attribute === 'title') return element.title;
+ return proceed(element, attribute);
+ }
+ );
}
-Abstract.Insertion.prototype = {
- initialize: function(element, content) {
- this.element = $(element);
- this.content = content.stripScripts();
+else if (Prototype.Browser.IE) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
- if (this.adjacency && this.element.insertAdjacentHTML) {
- try {
- this.element.insertAdjacentHTML(this.adjacency, this.content);
- } catch (e) {
- var tagName = this.element.tagName.toLowerCase();
- if (tagName == 'tbody' || tagName == 'tr') {
- this.insertContent(this.contentFromAnonymousTable());
- } else {
- throw e;
+ $w('positionedOffset viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ offsetParent.setStyle({ zoom: 1 });
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
}
}
- } else {
- this.range = this.element.ownerDocument.createRange();
- if (this.initializeRange) this.initializeRange();
- this.insertContent([this.range.createContextualFragment(this.content)]);
}
+ };
- setTimeout(function() {content.evalScripts()}, 10);
+ Element._attributeTranslations.write = {
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
},
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ bottom: function(element, node) {
+ element.appendChild(node);
+ },
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
- contentFromAnonymousTable: function() {
- var div = document.createElement('div');
- div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
- return $A(div.childNodes[0].childNodes[0].childNodes);
+(function() {
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
}
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
}
-var Insertion = new Object();
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
-Insertion.Before = Class.create();
-Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
- initializeRange: function() {
- this.range.setStartBefore(this.element);
- },
+ var Methods = { }, ByTag = Element.Methods.ByTag;
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.parentNode.insertBefore(fragment, this.element);
- }).bind(this));
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
}
-});
-Insertion.Top = Class.create();
-Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
- initializeRange: function() {
- this.range.selectNodeContents(this.element);
- this.range.collapse(true);
- },
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
- insertContent: function(fragments) {
- fragments.reverse(false).each((function(fragment) {
- this.element.insertBefore(fragment, this.element.firstChild);
- }).bind(this));
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
}
-});
-Insertion.Bottom = Class.create();
-Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
- initializeRange: function() {
- this.range.selectNodeContents(this.element);
- this.range.collapse(this.element);
- },
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.appendChild(fragment);
- }).bind(this));
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
}
-});
-Insertion.After = Class.create();
-Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
- initializeRange: function() {
- this.range.setStartAfter(this.element);
- },
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.parentNode.insertBefore(fragment,
- this.element.nextSibling);
- }).bind(this));
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
}
-});
-/*--------------------------------------------------------------------------*/
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
-Element.ClassNames = Class.create();
-Element.ClassNames.prototype = {
- initialize: function(element) {
- this.element = $(element);
- },
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
- _each: function(iterator) {
- this.element.className.split(/\s+/).select(function(name) {
- return name.length > 0;
- })._each(iterator);
- },
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
- set: function(className) {
- this.element.className = className;
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ var B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
+ (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
+ });
+ return dimensions;
},
- add: function(classNameToAdd) {
- if (this.include(classNameToAdd)) return;
- this.set(this.toArray().concat(classNameToAdd).join(' '));
+ getWidth: function() {
+ return this.getDimensions().width;
},
- remove: function(classNameToRemove) {
- if (!this.include(classNameToRemove)) return;
- this.set(this.select(function(className) {
- return className != classNameToRemove;
- }).join(' '));
+ getHeight: function() {
+ return this.getDimensions().height;
},
- toString: function() {
- return this.toArray().join(' ');
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
}
-}
+};
+/* Portions of the Selector class are derived from Jack Slocum�۪s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
-Object.extend(Element.ClassNames.prototype, Enumerable);
-var Selector = Class.create();
-Selector.prototype = {
+var Selector = Class.create({
initialize: function(expression) {
- this.params = {classNames: []};
- this.expression = expression.toString().strip();
- this.parseExpression();
+ this.expression = expression.strip();
this.compileMatcher();
},
- parseExpression: function() {
- function abort(message) { throw 'Parse error in selector: ' + message; }
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
- if (this.expression == '') abort('empty expression');
+ var e = this.expression;
- var params = this.params, expr = this.expression, match, modifier, clause, rest;
- while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
- params.attributes = params.attributes || [];
- params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
- expr = match[1];
+ // Safari 3 chokes on :*-of-type and :empty
+ if (Prototype.Browser.WebKit &&
+ (e.include("-of-type") || e.include(":empty")))
+ return false;
+
+ // XPath can't do namespaced attributes, nor can it read
+ // the "checked" property from DOM nodes
+ if ((/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return false;
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ if (this.shouldUseXPath())
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
}
- if (expr == '*') return this.params.wildcard = true;
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
- while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
- modifier = match[1], clause = match[2], rest = match[3];
- switch (modifier) {
- case '#': params.id = clause; break;
- case '.': params.classNames.push(clause); break;
- case '':
- case undefined: params.tagName = clause.toUpperCase(); break;
- default: abort(expr.inspect());
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
}
- expr = rest;
}
- if (expr.length > 0) abort(expr.inspect());
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
},
- buildMatchExpression: function() {
- var params = this.params, conditions = [], clause;
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
- if (params.wildcard)
- conditions.push('true');
- if (clause = params.id)
- conditions.push('element.id == ' + clause.inspect());
- if (clause = params.tagName)
- conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
- if ((clause = params.classNames).length > 0)
- for (var i = 0; i < clause.length; i++)
- conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
- if (clause = params.attributes) {
- clause.each(function(attribute) {
- var value = 'element.getAttribute(' + attribute.name.inspect() + ')';
- var splitValueBy = function(delimiter) {
- return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
- }
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
- switch (attribute.operator) {
- case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break;
- case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
- case '|=': conditions.push(
- splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
- ); break;
- case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break;
- case '':
- case undefined: conditions.push(value + ' != null'); break;
- default: throw 'Unknown operator ' + attribute.operator + ' in selector';
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
}
- });
+ }
}
- return conditions.join(' && ');
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
},
- compileMatcher: function() {
- this.match = new Function('element', 'if (!element.tagName) return false; \
- return ' + this.buildMatchExpression());
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
},
- findElements: function(scope) {
- var element;
+ match: function(element) {
+ this.tokens = [];
- if (element = $(this.params.id))
- if (this.match(element))
- if (!scope || Element.childOf(element, scope))
- return [element];
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
- scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
- var results = [];
- for (var i = 0; i < scope.length; i++)
- if (this.match(element = scope[i]))
- results.push(Element.extend(element));
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
- return results;
+ return match;
},
toString: function() {
return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
}
-}
+});
-function $$() {
- return $A(arguments).map(function(expression) {
- return expression.strip().split(/\s+/).inject([null], function(results, expr) {
- var selector = new Selector(expr);
- return results.map(selector.findElements.bind(selector)).flatten();
- });
- }).flatten();
-}
-var Field = {
- clear: function() {
- for (var i = 0; i < arguments.length; i++)
- $(arguments[i]).value = '';
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: function(m) {
+ m[1] = m[1].toLowerCase();
+ return new Template("[@#{1}]").evaluate(m);
+ },
+ attr: function(m) {
+ m[1] = m[1].toLowerCase();
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
},
- focus: function(element) {
- $(element).focus();
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
},
- present: function() {
- for (var i = 0; i < arguments.length; i++)
- if ($(arguments[i]).value == '') return false;
- return true;
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
},
- select: function(element) {
- $(element).select();
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+ }
},
- activate: function(element) {
- element = $(element);
- element.focus();
- if (element.select)
- element.select();
- }
-}
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
-/*--------------------------------------------------------------------------*/
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = _true;
+ return nodes;
+ },
-var Form = {
- serialize: function(form) {
- var elements = Form.getElements($(form));
- var queryComponents = new Array();
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._countedByPrototype = undefined;
+ return nodes;
+ },
- for (var i = 0; i < elements.length; i++) {
- var queryComponent = Form.Element.serialize(elements[i]);
- if (queryComponent)
- queryComponents.push(queryComponent);
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._countedByPrototype = Prototype.emptyFunction;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ var uTagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator, combinator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
}
+ },
- return queryComponents.join('&');
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._countedByPrototype) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._countedByPrototype) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
},
- getElements: function(form) {
- form = $(form);
- var elements = new Array();
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
- for (var tagName in Form.Element.Serializers) {
- var tagElements = form.getElementsByTagName(tagName);
- for (var j = 0; j < tagElements.length; j++)
- elements.push(tagElements[j]);
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = $$(expression), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._countedByPrototype) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
}
- return elements;
+ return Selector.matchElements(elements, expression || '*')[index || 0];
},
+ findChildElements: function(element, expressions) {
+ expressions = Selector.split(expressions.join(','));
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+if (Prototype.Browser.IE) {
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
+}
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (Object.isUndefined(options.hash)) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
getInputs: function(form, typeName, name) {
form = $(form);
var inputs = form.getElementsByTagName('input');
- if (!typeName && !name)
- return inputs;
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
- var matchingInputs = new Array();
- for (var i = 0; i < inputs.length; i++) {
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
var input = inputs[i];
- if ((typeName && input.type != typeName) ||
- (name && input.name != name))
+ if ((typeName && input.type != typeName) || (name && input.name != name))
continue;
- matchingInputs.push(input);
+ matchingInputs.push(Element.extend(input));
}
return matchingInputs;
},
disable: function(form) {
- var elements = Form.getElements(form);
- for (var i = 0; i < elements.length; i++) {
- var element = elements[i];
- element.blur();
- element.disabled = 'true';
- }
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
},
enable: function(form) {
- var elements = Form.getElements(form);
- for (var i = 0; i < elements.length; i++) {
- var element = elements[i];
- element.disabled = '';
- }
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
},
findFirstElement: function(form) {
- return Form.getElements(form).find(function(element) {
- return element.type != 'hidden' && !element.disabled &&
- ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
});
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
},
focusFirstElement: function(form) {
- Field.activate(Form.findFirstElement(form));
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
},
- reset: function(form) {
- $(form).reset();
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
}
-}
+};
+/*--------------------------------------------------------------------------*/
+
Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
serialize: function(element) {
element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
var method = element.tagName.toLowerCase();
- var parameter = Form.Element.Serializers[method](element);
+ return Form.Element.Serializers[method](element);
+ },
- if (parameter) {
- var key = encodeURIComponent(parameter[0]);
- if (key.length == 0) return;
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
- if (parameter[1].constructor != Array)
- parameter[1] = [parameter[1]];
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
- return parameter[1].map(function(value) {
- return key + '=' + encodeURIComponent(value);
- }).join('&');
- }
+ present: function(element) {
+ return $(element).value != '';
},
- getValue: function(element) {
+ activate: function(element) {
element = $(element);
- var method = element.tagName.toLowerCase();
- var parameter = Form.Element.Serializers[method](element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
- if (parameter)
- return parameter[1];
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
}
-}
+};
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
Form.Element.Serializers = {
- input: function(element) {
+ input: function(element, value) {
switch (element.type.toLowerCase()) {
- case 'submit':
- case 'hidden':
- case 'password':
- case 'text':
- return Form.Element.Serializers.textarea(element);
case 'checkbox':
case 'radio':
- return Form.Element.Serializers.inputSelector(element);
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
}
- return false;
},
- inputSelector: function(element) {
- if (element.checked)
- return [element.name, element.value];
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
},
- textarea: function(element) {
- return [element.name, element.value];
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
},
- select: function(element) {
- return Form.Element.Serializers[element.type == 'select-one' ?
- 'selectOne' : 'selectMany'](element);
+ select: function(element, index) {
+ if (Object.isUndefined(index))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
},
selectOne: function(element) {
- var value = '', opt, index = element.selectedIndex;
- if (index >= 0) {
- opt = element.options[index];
- value = opt.value || opt.text;
- }
- return [element.name, value];
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
},
selectMany: function(element) {
- var value = [];
- for (var i = 0; i < element.length; i++) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
var opt = element.options[i];
- if (opt.selected)
- value.push(opt.value || opt.text);
+ if (opt.selected) values.push(this.optionValue(opt));
}
- return [element.name, value];
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
}
-}
+};
/*--------------------------------------------------------------------------*/
-var $F = Form.Element.getValue;
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.TimedObserver = function() {}
-Abstract.TimedObserver.prototype = {
- initialize: function(element, frequency, callback) {
- this.frequency = frequency;
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
this.element = $(element);
- this.callback = callback;
-
this.lastValue = this.getValue();
- this.registerCallback();
},
- registerCallback: function() {
- setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
- },
-
- onTimerEvent: function() {
+ execute: function() {
var value = this.getValue();
- if (this.lastValue != value) {
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
this.callback(this.element, value);
this.lastValue = value;
}
}
-}
+});
-Form.Element.Observer = Class.create();
-Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
getValue: function() {
return Form.Element.getValue(this.element);
}
});
-Form.Observer = Class.create();
-Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
+Form.Observer = Class.create(Abstract.TimedObserver, {
getValue: function() {
return Form.serialize(this.element);
}
@@ -1606,8 +3662,7 @@
/*--------------------------------------------------------------------------*/
-Abstract.EventObserver = function() {}
-Abstract.EventObserver.prototype = {
+Abstract.EventObserver = Class.create({
initialize: function(element, callback) {
this.element = $(element);
this.callback = callback;
@@ -1628,9 +3683,7 @@
},
registerFormCallbacks: function() {
- var elements = Form.getElements(this.element);
- for (var i = 0; i < elements.length; i++)
- this.registerCallback(elements[i]);
+ Form.getElements(this.element).each(this.registerCallback, this);
},
registerCallback: function(element) {
@@ -1640,34 +3693,26 @@
case 'radio':
Event.observe(element, 'click', this.onElementEvent.bind(this));
break;
- case 'password':
- case 'text':
- case 'textarea':
- case 'select-one':
- case 'select-multiple':
+ default:
Event.observe(element, 'change', this.onElementEvent.bind(this));
break;
}
}
}
-}
+});
-Form.Element.EventObserver = Class.create();
-Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
getValue: function() {
return Form.Element.getValue(this.element);
}
});
-Form.EventObserver = Class.create();
-Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
+Form.EventObserver = Class.create(Abstract.EventObserver, {
getValue: function() {
return Form.serialize(this.element);
}
});
-if (!window.Event) {
- var Event = new Object();
-}
+if (!window.Event) var Event = { };
Object.extend(Event, {
KEY_BACKSPACE: 8,
@@ -1679,100 +3724,343 @@
KEY_RIGHT: 39,
KEY_DOWN: 40,
KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
- element: function(event) {
- return event.target || event.srcElement;
- },
+ cache: { },
- isLeftClick: function(event) {
- return (((event.which) && (event.which == 1)) ||
- ((event.button) && (event.button == 1)));
- },
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
- pointerX: function(event) {
- return event.pageX || (event.clientX +
- (document.documentElement.scrollLeft || document.body.scrollLeft));
- },
+Event.Methods = (function() {
+ var isButton;
- pointerY: function(event) {
- return event.pageY || (event.clientY +
- (document.documentElement.scrollTop || document.body.scrollTop));
- },
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
- stop: function(event) {
- if (event.preventDefault) {
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ if (!expression) return element;
+ var elements = [element].concat(element.ancestors());
+ return Selector.findElement(elements, expression, 0);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
event.preventDefault();
event.stopPropagation();
- } else {
- event.returnValue = false;
- event.cancelBubble = true;
+ event.stopped = true;
}
- },
+ };
+})();
- // find the first node with the given tagName, starting from the
- // node the event was triggered on; traverses the DOM upwards
- findElement: function(event, tagName) {
- var element = Event.element(event);
- while (element.parentNode && (!element.tagName ||
- (element.tagName.toUpperCase() != tagName.toUpperCase())))
- element = element.parentNode;
- return element;
- },
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
- observers: false,
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
- _observeAndCache: function(element, name, observer, useCapture) {
- if (!this.observers) this.observers = [];
- if (element.addEventListener) {
- this.observers.push([element, name, observer, useCapture]);
- element.addEventListener(name, observer, useCapture);
- } else if (element.attachEvent) {
- this.observers.push([element, name, observer, useCapture]);
- element.attachEvent('on' + name, observer);
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._prototypeEventID) return element._prototypeEventID[0];
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._prototypeEventID = [++arguments.callee.id];
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event);
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ var event;
+ if (document.createEvent) {
+ event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return Event.extend(event);
}
- },
+ };
+})());
- unloadCache: function() {
- if (!Event.observers) return;
- for (var i = 0; i < Event.observers.length; i++) {
- Event.stopObserving.apply(this, Event.observers[i]);
- Event.observers[i][0] = null;
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer;
+
+ function fireContentLoadedEvent() {
+ if (document.loaded) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ document.loaded = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
}
- Event.observers = false;
- },
- observe: function(element, name, observer, useCapture) {
- var element = $(element);
- useCapture = useCapture || false;
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
- if (name == 'keypress' &&
- (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
- || element.attachEvent))
- name = 'keydown';
+Hash.toQueryString = Object.toQueryString;
- this._observeAndCache(element, name, observer, useCapture);
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
},
- stopObserving: function(element, name, observer, useCapture) {
- var element = $(element);
- useCapture = useCapture || false;
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
- if (name == 'keypress' &&
- (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
- || element.detachEvent))
- name = 'keydown';
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
- if (element.removeEventListener) {
- element.removeEventListener(name, observer, useCapture);
- } else if (element.detachEvent) {
- element.detachEvent('on' + name, observer);
- }
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
}
-});
+};
-/* prevent memory leaks in IE */
-if (navigator.appVersion.match(/\bMSIE\b/))
- Event.observe(window, 'unload', Event.unloadCache, false);
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
var Position = {
// set to true if needed, warning: firefox performance problems
// NOT neeeded for page scrolling, only if draggable contained in
@@ -1792,58 +4080,13 @@
|| 0;
},
- realOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.scrollTop || 0;
- valueL += element.scrollLeft || 0;
- element = element.parentNode;
- } while (element);
- return [valueL, valueT];
- },
-
- cumulativeOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- } while (element);
- return [valueL, valueT];
- },
-
- positionedOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- if (element) {
- p = Element.getStyle(element, 'position');
- if (p == 'relative' || p == 'absolute') break;
- }
- } while (element);
- return [valueL, valueT];
- },
-
- offsetParent: function(element) {
- if (element.offsetParent) return element.offsetParent;
- if (element == document.body) return element;
-
- while ((element = element.parentNode) && element != document.body)
- if (Element.getStyle(element, 'position') != 'static')
- return element;
-
- return document.body;
- },
-
// caches x/y coordinate pair to use with overlap
within: function(element, x, y) {
if (this.includeScrollOffsets)
return this.withinIncludingScrolloffsets(element, x, y);
this.xcomp = x;
this.ycomp = y;
- this.offset = this.cumulativeOffset(element);
+ this.offset = Element.cumulativeOffset(element);
return (y >= this.offset[1] &&
y < this.offset[1] + element.offsetHeight &&
@@ -1852,11 +4095,11 @@
},
withinIncludingScrolloffsets: function(element, x, y) {
- var offsetcache = this.realOffset(element);
+ var offsetcache = Element.cumulativeScrollOffset(element);
this.xcomp = x + offsetcache[0] - this.deltaX;
this.ycomp = y + offsetcache[1] - this.deltaY;
- this.offset = this.cumulativeOffset(element);
+ this.offset = Element.cumulativeOffset(element);
return (this.ycomp >= this.offset[1] &&
this.ycomp < this.offset[1] + element.offsetHeight &&
@@ -1875,132 +4118,104 @@
element.offsetWidth;
},
- clone: function(source, target) {
- source = $(source);
- target = $(target);
- target.style.position = 'absolute';
- var offsets = this.cumulativeOffset(source);
- target.style.top = offsets[1] + 'px';
- target.style.left = offsets[0] + 'px';
- target.style.width = source.offsetWidth + 'px';
- target.style.height = source.offsetHeight + 'px';
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
},
- page: function(forElement) {
- var valueT = 0, valueL = 0;
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
- var element = forElement;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
+ realOffset: Element.Methods.cumulativeScrollOffset,
- // Safari fix
- if (element.offsetParent==document.body)
- if (Element.getStyle(element,'position')=='absolute') break;
+ offsetParent: Element.Methods.getOffsetParent,
- } while (element = element.offsetParent);
+ page: Element.Methods.viewportOffset,
- element = forElement;
- do {
- valueT -= element.scrollTop || 0;
- valueL -= element.scrollLeft || 0;
- } while (element = element.parentNode);
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
- return [valueL, valueT];
- },
+/*--------------------------------------------------------------------------*/
- clone: function(source, target) {
- var options = Object.extend({
- setLeft: true,
- setTop: true,
- setWidth: true,
- setHeight: true,
- offsetTop: 0,
- offsetLeft: 0
- }, arguments[2] || {})
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
- // find page position of source
- source = $(source);
- var p = Position.page(source);
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
- // find coordinate system to use
- target = $(target);
- var delta = [0, 0];
- var parent = null;
- // delta [0,0] will do fine with position: fixed elements,
- // position:absolute needs offsetParent deltas
- if (Element.getStyle(target,'position') == 'absolute') {
- parent = Position.offsetParent(target);
- delta = Position.page(parent);
- }
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
- // correct by body offsets (fixes Safari)
- if (parent == document.body) {
- delta[0] -= document.body.offsetLeft;
- delta[1] -= document.body.offsetTop;
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
}
+ return elements;
+ };
- // set position
- if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
- if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
- if(options.setWidth) target.style.width = source.offsetWidth + 'px';
- if(options.setHeight) target.style.height = source.offsetHeight + 'px';
- },
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
- absolutize: function(element) {
- element = $(element);
- if (element.style.position == 'absolute') return;
- Position.prepare();
+/*--------------------------------------------------------------------------*/
- var offsets = Position.positionedOffset(element);
- var top = offsets[1];
- var left = offsets[0];
- var width = element.clientWidth;
- var height = element.clientHeight;
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
- element._originalLeft = left - parseFloat(element.style.left || 0);
- element._originalTop = top - parseFloat(element.style.top || 0);
- element._originalWidth = element.style.width;
- element._originalHeight = element.style.height;
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
- element.style.position = 'absolute';
- element.style.top = top + 'px';;
- element.style.left = left + 'px';;
- element.style.width = width + 'px';;
- element.style.height = height + 'px';;
+ set: function(className) {
+ this.element.className = className;
},
- relativize: function(element) {
- element = $(element);
- if (element.style.position == 'relative') return;
- Position.prepare();
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
- element.style.position = 'relative';
- var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
- var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
- element.style.top = top + 'px';
- element.style.left = left + 'px';
- element.style.height = element._originalHeight;
- element.style.width = element._originalWidth;
+ toString: function() {
+ return $A(this).join(' ');
}
-}
+};
-// Safari returns margins on body which is incorrect if the child is absolutely
-// positioned. For performance reasons, redefine Position.cumulativeOffset for
-// KHTML/WebKit only.
-if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
- Position.cumulativeOffset = function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- if (element.offsetParent == document.body)
- if (Element.getStyle(element, 'position') == 'absolute') break;
+Object.extend(Element.ClassNames.prototype, Enumerable);
- element = element.offsetParent;
- } while (element);
+/*--------------------------------------------------------------------------*/
- return [valueL, valueT];
- }
-}
\ No newline at end of file
+Element.addMethods();
\ No newline at end of file
16 years
JBoss Portal SVN: r10714 - maven/jboss-portal-parent/tags/JBP_PORTAL_PARENT_1_0_0.
by portal-commits@lists.jboss.org
Author: thomas.heute(a)jboss.com
Date: 2008-04-24 09:49:28 -0400 (Thu, 24 Apr 2008)
New Revision: 10714
Modified:
maven/jboss-portal-parent/tags/JBP_PORTAL_PARENT_1_0_0/pom.xml
Log:
Tagging 1.0.0
Modified: maven/jboss-portal-parent/tags/JBP_PORTAL_PARENT_1_0_0/pom.xml
===================================================================
--- maven/jboss-portal-parent/tags/JBP_PORTAL_PARENT_1_0_0/pom.xml 2008-04-24 13:47:50 UTC (rev 10713)
+++ maven/jboss-portal-parent/tags/JBP_PORTAL_PARENT_1_0_0/pom.xml 2008-04-24 13:49:28 UTC (rev 10714)
@@ -10,7 +10,7 @@
<artifactId>jboss-portal-parent</artifactId>
<packaging>pom</packaging>
<name>JBoss Portal Parent POM</name>
- <version>1-SNAPSHOT</version>
+ <version>1.0.0</version>
<url>http://labs.jboss.com/jbossportal</url>
16 years
JBoss Portal SVN: r10713 - maven/jboss-portal-parent/tags.
by portal-commits@lists.jboss.org
Author: thomas.heute(a)jboss.com
Date: 2008-04-24 09:47:50 -0400 (Thu, 24 Apr 2008)
New Revision: 10713
Added:
maven/jboss-portal-parent/tags/JBP_PORTAL_PARENT_1_0_0/
Log:
Taggin module parent
Copied: maven/jboss-portal-parent/tags/JBP_PORTAL_PARENT_1_0_0 (from rev 10712, maven/jboss-portal-parent/trunk)
16 years
JBoss Portal SVN: r10711 - modules/identity/tags/JBP_IDENTITY_1_0_3/build.
by portal-commits@lists.jboss.org
Author: thomas.heute(a)jboss.com
Date: 2008-04-24 09:35:28 -0400 (Thu, 24 Apr 2008)
New Revision: 10711
Modified:
modules/identity/tags/JBP_IDENTITY_1_0_3/build/build-thirdparty.xml
modules/identity/tags/JBP_IDENTITY_1_0_3/build/build.xml
Log:
Tagging as GA, use common 1.2.0
Modified: modules/identity/tags/JBP_IDENTITY_1_0_3/build/build-thirdparty.xml
===================================================================
--- modules/identity/tags/JBP_IDENTITY_1_0_3/build/build-thirdparty.xml 2008-04-24 13:32:35 UTC (rev 10710)
+++ modules/identity/tags/JBP_IDENTITY_1_0_3/build/build-thirdparty.xml 2008-04-24 13:35:28 UTC (rev 10711)
@@ -47,7 +47,7 @@
are pushed to the http://repository.jboss.com site.
-->
- <componentref name="jboss-portal/modules/common" version="1.1.0"/>
+ <componentref name="jboss-portal/modules/common" version="1.2.0"/>
<componentref name="jboss-portal/modules/test" version="1.0.1"/>
<componentref name="apache-log4j" version="1.2.8"/>
<componentref name="apache-logging" version="1.0.5.SP1-jboss"/>
Modified: modules/identity/tags/JBP_IDENTITY_1_0_3/build/build.xml
===================================================================
--- modules/identity/tags/JBP_IDENTITY_1_0_3/build/build.xml 2008-04-24 13:32:35 UTC (rev 10710)
+++ modules/identity/tags/JBP_IDENTITY_1_0_3/build/build.xml 2008-04-24 13:35:28 UTC (rev 10711)
@@ -62,7 +62,7 @@
<property name="version.major" value="1"/>
<property name="version.minor" value="0"/>
<property name="version.revision" value="3"/>
- <property name="version.tag" value="SNAPSHOT"/>
+ <property name="version.tag" value="GA"/>
<property name="version.name" value=""/>
<!-- This must be set to the CVS tag for any release -->
16 years
JBoss Portal SVN: r10710 - modules/identity/tags.
by portal-commits@lists.jboss.org
Author: thomas.heute(a)jboss.com
Date: 2008-04-24 09:32:35 -0400 (Thu, 24 Apr 2008)
New Revision: 10710
Added:
modules/identity/tags/JBP_IDENTITY_1_0_3/
Log:
Tagging identity
Copied: modules/identity/tags/JBP_IDENTITY_1_0_3 (from rev 10709, modules/identity/branches/JBP_IDENTITY_BRANCH_1_0)
16 years