JBoss Rich Faces SVN: r14825 - in framework/trunk: api and 8 other directories.
by richfaces-svn-commits@lists.jboss.org
Author: nbelaevski
Date: 2009-07-07 20:01:28 -0400 (Tue, 07 Jul 2009)
New Revision: 14825
Added:
framework/trunk/api/src/
framework/trunk/impl/generatescript.xml
framework/trunk/impl/src/
framework/trunk/test-base/src/
Removed:
framework/trunk/api/src/main/java/org/ajax4jsf/model/QueueImpl.java
framework/trunk/impl/src/main/java/org/ajax4jsf/context/SAXEndElementEvent.java
framework/trunk/impl/src/main/java/org/ajax4jsf/context/SAXStartElementEvent.java
framework/trunk/impl/src/main/java/org/ajax4jsf/context/SAXTextEvent.java
framework/trunk/impl/src/main/java/org/ajax4jsf/model/
framework/trunk/impl/src/main/java/org/ajax4jsf/resource/image/DiffusionFilterOp.java
framework/trunk/impl/src/main/java/org/ajax4jsf/resource/image/GIFEncoder.java
framework/trunk/impl/src/main/java/org/ajax4jsf/resource/image/Quantize.java
framework/trunk/impl/src/main/java/org/richfaces/model/ExtendedDataTableModifiableModel.java
framework/trunk/impl/src/main/java/org/richfaces/model/ExtendedTableDataModelWrapper.java
Modified:
framework/trunk/api/pom.xml
framework/trunk/impl/pom.xml
framework/trunk/pom.xml
framework/trunk/test-base/pom.xml
framework/trunk/version-matrix/pom.xml
Log:
- framework moved into new build system
- legacy classes removed: SAX*Event, QueueImpl and GIF SPI
Modified: framework/trunk/api/pom.xml
===================================================================
--- framework/trunk/api/pom.xml 2009-07-07 23:36:18 UTC (rev 14824)
+++ framework/trunk/api/pom.xml 2009-07-08 00:01:28 UTC (rev 14825)
@@ -15,4 +15,30 @@
<artifactId>richfaces-api</artifactId>
<name>Java Server Faces AJAX framework API</name>
+ <dependencies>
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ <version>3.2</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-beanutils</groupId>
+ <artifactId>commons-beanutils</artifactId>
+ <version>1.7.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>2.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <version>2.4</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
</project>
\ No newline at end of file
Copied: framework/trunk/api/src (from rev 14808, branches/jsf2.0/framework/api/src)
Deleted: framework/trunk/api/src/main/java/org/ajax4jsf/model/QueueImpl.java
===================================================================
--- branches/jsf2.0/framework/api/src/main/java/org/ajax4jsf/model/QueueImpl.java 2009-07-07 13:08:56 UTC (rev 14808)
+++ framework/trunk/api/src/main/java/org/ajax4jsf/model/QueueImpl.java 2009-07-08 00:01:28 UTC (rev 14825)
@@ -1,96 +0,0 @@
-package org.ajax4jsf.model;
-
-import javax.el.ValueExpression;
-import javax.faces.context.FacesContext;
-
-/**
- * @author Konstantin Mishin
- *
- */
-public class QueueImpl implements Queue {
-
- private FacesContext context;
-
- private ValueExpression nameExpression;
-
- private ValueExpression requestDelayExpression;
-
- private ValueExpression timeoutExpression;
-
- private ValueExpression ignoreDupResponsesExpression;
-
- private ValueExpression limitToListExpression;
-
- public QueueImpl() {
- this(null);
- }
-
- public QueueImpl(FacesContext context) {
- if(context == null) {
- this.context = FacesContext.getCurrentInstance();
- } else {
- this.context = context;
- }
- }
-
- public String getName() {
- String name = null;
- if (nameExpression != null) {
- name = (String) nameExpression.getValue(context.getELContext());
- }
- return name;
- }
-
- public Integer getRequestDelay() {
- Integer requestDelay = null;
- if (requestDelayExpression != null) {
- requestDelay = (Integer) requestDelayExpression.getValue(context.getELContext());
- }
- return requestDelay;
- }
-
- public Integer getTimeout() {
- Integer timeout = null;
- if (timeoutExpression != null) {
- timeout = (Integer) timeoutExpression.getValue(context.getELContext());
- }
- return timeout;
- }
-
- public Boolean getIgnoreDupResponses() {
- Boolean ignoreDupResponses = null;
- if (ignoreDupResponsesExpression != null) {
- ignoreDupResponses = (Boolean) ignoreDupResponsesExpression.getValue(context.getELContext());
- }
- return ignoreDupResponses;
- }
-
- public Boolean getLimitToList() {
- Boolean limitToList = null;
- if (limitToListExpression != null) {
- limitToList = (Boolean) limitToListExpression.getValue(context.getELContext());
- }
- return limitToList;
- }
-
- public void setNameExpression(ValueExpression nameExpression) {
- this.nameExpression = nameExpression;
- }
-
- public void setRequestDelayExpression(ValueExpression requestDelayExpression) {
- this.requestDelayExpression = requestDelayExpression;
- }
-
- public void setTimeoutExpression(ValueExpression timeoutExpression) {
- this.timeoutExpression = timeoutExpression;
- }
-
- public void setIgnoreDupResponsesExpression(
- ValueExpression ignoreDupResponsesExpression) {
- this.ignoreDupResponsesExpression = ignoreDupResponsesExpression;
- }
-
- public void setLimitToListExpression(ValueExpression limitToListExpression) {
- this.limitToListExpression = limitToListExpression;
- }
-}
Copied: framework/trunk/impl/generatescript.xml (from rev 14817, branches/jsf2.0/framework/impl/generatescript.xml)
===================================================================
--- framework/trunk/impl/generatescript.xml (rev 0)
+++ framework/trunk/impl/generatescript.xml 2009-07-08 00:01:28 UTC (rev 14825)
@@ -0,0 +1,157 @@
+<?xml version="1.0"?>
+<!-- ======================================================================
+ 12.11.2005 23:40:43
+
+ assemblescripts
+ Assemble all javaScript library files to one AJAXJSF.js
+
+ shura
+ ====================================================================== -->
+<project name="assemblescripts" default="assembly">
+ <description>
+ Assemble all javaScript library files to one AJAXJSF.js
+ </description>
+
+ <property name="scripts-path" value="org/ajax4jsf/javascript/scripts"></property>
+ <property name="prototype-scripts-path" value="org/ajax4jsf/javascript/scripts"></property>
+ <property name="scriptaculous-scripts-path" value="org/richfaces/renderkit/html/scripts/scriptaculous"></property>
+ <property name="jquery-scripts-path" value="org/richfaces/renderkit/html/scripts/jquery"></property>
+
+ <property name="target-dir" value="${project.build.directory}/javascript"></property>
+
+ <property name="scripts.dir"
+ value="${target-dir}/${scripts-path}"
+ />
+ <property name="prototype.scripts.dir"
+ value="${target-dir}/${prototype-scripts-path}"
+ />
+ <property name="script" value="AJAX.js" />
+
+ <property name="script.rico" value="rico.js"></property>
+ <property name="script.aculo" value="scriptaculo.js"></property>
+ <property name="script.scriptaculous" value="scriptaculous.js"></property>
+ <property name="scriptaculous.scripts.dir"
+ value="${target-dir}/${scriptaculous-scripts-path}"/>
+ <property name="jquery.scripts.dir"
+ value="${target-dir}/${jquery-scripts-path}"/>
+
+ <property name="script.prototype" value="prototype.js"></property>
+ <property name="script.jquery" value="jquery.js"></property>
+
+ <property name="script.imagecache" value="imagecache.js"></property>
+ <property name="script.dnd" value="dnd.js"></property>
+ <property name="script.css-rules" value="css-rules.js"></property>
+ <filelist id="imagecache" dir="${basedir}/src/main/javascript/ajaxjsf" files="imagecache.js"></filelist>
+<!--
+ <filelist id="prototype"
+ dir="${basedir}/src/main/javascript/prototype"
+ files="empty.js,base.js,string.js,enumerable.js,array.js,hash.js,range.js"
+ >
+-->
+ <filelist id="jquery"
+ dir="${basedir}/src/main/javascript/jquery"
+ files="jquery-1.3.2.js,../memory.js,patches.js">
+ </filelist>
+
+ <filelist id="scriptaculous"
+ dir="${basedir}/src/main/javascript/scriptaculous"
+ files="builder.js,effects.js,dragdrop.js,controls.js,slider.js,sound.js" >
+ </filelist>
+
+
+ <filelist id="prototype"
+ dir="${basedir}/src/main/javascript/prototype"
+ files="prototype-1.6.0.3.js,../memory.js,patches.js">
+ </filelist>
+
+
+ <filelist id="dnd"
+ dir="${basedir}/src/main/javascript/dnd"
+ files="prolog.js,dnd.js,epilog.js">
+ </filelist>
+
+ <filelist id="ajaxjsf" dir="${basedir}/src/main/javascript/ajaxjsf" files="prolog.js,sarissa.js,JSFAJAX.js,queue.js,log4ajax.js,epilog.js,../memory.js"></filelist>
+ <!-- =================================
+ target: assemble
+ ================================= -->
+ <target name="assembly"
+ depends="depends"
+ description="--> Assemble all javaScript library files to one AJAXJSF.js"
+ >
+ <concat append="false"
+ binary="false"
+ destfile="${scripts.dir}/${script}"
+ fixlastline="yes"
+ eol="unix"
+ >
+ <filelist refid="ajaxjsf">
+ </filelist>
+ </concat>
+ <concat append="false"
+ binary="false"
+ destfile="${scripts.dir}/${script.imagecache}"
+ fixlastline="yes"
+ eol="unix"
+ >
+ <filelist refid="imagecache"/>
+ </concat>
+ <concat append="false"
+ binary="false"
+ destfile="${scripts.dir}/${script.dnd}"
+ fixlastline="yes"
+ eol="unix"
+ >
+ <filelist refid="dnd"/>
+ </concat>
+ <concat append="false"
+ binary="false"
+ destfile="${prototype.scripts.dir}/${script.prototype}"
+ fixlastline="yes"
+ eol="unix">
+ <filelist refid="prototype">
+ </filelist>
+ </concat>
+ <concat append="false"
+ binary="false"
+ destfile="${scriptaculous.scripts.dir}/${script.scriptaculous}"
+ fixlastline="yes"
+ eol="unix"
+ >
+ <filelist refid="scriptaculous"></filelist>
+ </concat>
+
+ <concat append="false"
+ binary="false"
+ destfile="${jquery.scripts.dir}/${script.jquery}"
+ fixlastline="yes"
+ eol="unix"
+ >
+ <filelist refid="jquery"></filelist>
+ </concat>
+
+
+ <copy todir="${prototype.scripts.dir}" file="${basedir}/src/main/javascript/ajaxjsf/smartposition.js">
+ </copy>
+ <copy todir="${scriptaculous.scripts.dir}">
+ <fileset dir="${basedir}/src/main/javascript/scriptaculous"></fileset>
+ </copy>
+ </target>
+
+
+ <!-- =================================
+ target: fixeol
+ ================================= -->
+ <target name="fixeol" depends="depends" description="--> Fix CR/LF in files">
+ <fixcrlf srcdir="${basedir}" includes="*.js" eol="unix">
+ </fixcrlf>
+ </target>
+
+
+ <!-- - - - - - - - - - - - - - - - - -
+ target: depends
+ - - - - - - - - - - - - - - - - - -->
+ <target name="depends">
+ </target>
+
+</project>
+
Modified: framework/trunk/impl/pom.xml
===================================================================
--- framework/trunk/impl/pom.xml 2009-07-07 23:36:18 UTC (rev 14824)
+++ framework/trunk/impl/pom.xml 2009-07-08 00:01:28 UTC (rev 14825)
@@ -13,13 +13,138 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.richfaces.framework</groupId>
<artifactId>richfaces-impl</artifactId>
- <name>JSF ajax framework implementation</name>
+ <name>JSF ajax framework implementation</name>
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>target/javascript</directory>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>javacc-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>javacc</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>javascript</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <tasks>
+ <ant antfile="${basedir}/generatescript.xml" inheritRefs="true">
+ <target name="assembly" />
+ <property name="target-dir" value="${project.build.directory}/javascript" />
+ </ant>
+ </tasks>
+ <resourceRoot>${project.build.directory}/javascript</resourceRoot>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.richfaces.cdk</groupId>
+ <artifactId>maven-javascript-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>compress</goal>
+ </goals>
+ <configuration>
+ <nosuffix>false</nosuffix>
+ <outputDirectory>${project.build.directory}/compressed/</outputDirectory>
+ <aggregations>
+ <aggregation>
+ <insertNewLine>true</insertNewLine>
+ <output>${project.build.outputDirectory}/org/ajax4jsf/framework.pack.js</output>
+ <includes>
+ <include>${project.build.directory}/compressed/org/ajax4jsf/javascript/scripts/prototype-min.js</include>
+ <include>${project.build.directory}/compressed/org/ajax4jsf/javascript/scripts/AJAX-min.js</include>
+ <include>${project.build.directory}/compressed/org/richfaces/renderkit/html/scripts/scriptaculous/scriptaculous-min.js</include>
+ <include>${project.build.directory}/compressed/org/richfaces/renderkit/html/scripts/jquery/jquery-min.js</include>
+ <include>${project.build.directory}/compressed/org/richfaces/renderkit/html/scripts/jquery.utils-min.js</include>
+ <include>${project.build.directory}/compressed/org/ajax4jsf/javascript/scripts/dnd-min.js</include>
+ <include>**/*-min.js</include>
+ </includes>
+ <excludes>
+ <exclude>**/*.pack.js</exclude>
+ <exclude>**/scriptaculous/*.js</exclude>
+ <exclude>**/extend-min.js</exclude>
+ <exclude>**/jquery.jcarousel-min.js</exclude>
+ <exclude>**/compressed.css</exclude>
+ </excludes>
+ </aggregation>
+ </aggregations>
+ <resources>
+ <resource>
+ <directory>target/javascript</directory>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ <execution>
+ <id>jslint</id>
+ <phase>test</phase>
+ <goals>
+ <goal>jslint</goal>
+ </goals>
+ <configuration>
+ <includes>
+ <include>**/framework.pack.js</include>
+ </includes>
+ <resources>
+ <resource>
+ <directory>${project.build.outputDirectory}</directory>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>richfaces-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-digester</groupId>
+ <artifactId>commons-digester</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>opensymphony</groupId>
+ <artifactId>oscache</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.nekohtml</groupId>
+ <artifactId>nekohtml</artifactId>
+ <optional>true</optional>
+ </dependency>
</dependencies>
</project>
\ No newline at end of file
Copied: framework/trunk/impl/src (from rev 14807, branches/jsf2.0/framework/impl/src)
Deleted: framework/trunk/impl/src/main/java/org/ajax4jsf/context/SAXEndElementEvent.java
===================================================================
--- branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/context/SAXEndElementEvent.java 2009-07-07 12:45:54 UTC (rev 14807)
+++ framework/trunk/impl/src/main/java/org/ajax4jsf/context/SAXEndElementEvent.java 2009-07-08 00:01:28 UTC (rev 14825)
@@ -1,49 +0,0 @@
-/**
- * License Agreement.
- *
- * JBoss RichFaces - Ajax4jsf Component Library
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.ajax4jsf.context;
-
-
-/**
- * Created 19.07.2008
- * @author Nick Belaevski
- * @since 3.2.2
- */
-
-public class SAXEndElementEvent {
-
- private String name;
-
- public SAXEndElementEvent(String name) {
- super();
-
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- @Override
- public String toString() {
- return "</" + name + ">";
- }
-}
Deleted: framework/trunk/impl/src/main/java/org/ajax4jsf/context/SAXStartElementEvent.java
===================================================================
--- branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/context/SAXStartElementEvent.java 2009-07-07 12:45:54 UTC (rev 14807)
+++ framework/trunk/impl/src/main/java/org/ajax4jsf/context/SAXStartElementEvent.java 2009-07-08 00:01:28 UTC (rev 14825)
@@ -1,80 +0,0 @@
-/**
- * License Agreement.
- *
- * JBoss RichFaces - Ajax4jsf Component Library
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.ajax4jsf.context;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Created 19.07.2008
- * @author Nick Belaevski
- * @since 3.2.2
- */
-
-public class SAXStartElementEvent {
-
- private String name;
-
- private Map<String, String> attributes;
-
- /**
- * Constructor that parses string into map for usage in unit tests
- * @param name
- * @param attributesString
- */
- public SAXStartElementEvent(String name, String attributesString) {
- super();
- this.name = name;
-
- Map<String, String> attributes = null;
- if (attributesString != null) {
- attributes = new HashMap<String, String>();
- String[] split = attributesString.split(",");
- for (String s : split) {
- String[] split2 = s.split("=");
-
- attributes.put(split2[0], split2[1]);
- }
- }
-
- this.attributes = attributes;
- }
-
- public SAXStartElementEvent(String name, Map<String, String> attributes) {
- super();
- this.name = name;
- this.attributes = attributes;
- }
-
- public String getName() {
- return name;
- }
-
- public Map<String, String> getAttributes() {
- return attributes;
- }
-
- @Override
- public String toString() {
- return "<" + name + " " + attributes + " >";
- }
-}
Deleted: framework/trunk/impl/src/main/java/org/ajax4jsf/context/SAXTextEvent.java
===================================================================
--- branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/context/SAXTextEvent.java 2009-07-07 12:45:54 UTC (rev 14807)
+++ framework/trunk/impl/src/main/java/org/ajax4jsf/context/SAXTextEvent.java 2009-07-08 00:01:28 UTC (rev 14825)
@@ -1,46 +0,0 @@
-/**
- * License Agreement.
- *
- * JBoss RichFaces - Ajax4jsf Component Library
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.ajax4jsf.context;
-
-/**
- * Created 19.07.2008
- * @author Nick Belaevski
- * @since 3.2.2
- */
-
-public class SAXTextEvent {
- private String text;
-
- public SAXTextEvent(String text) {
- super();
- this.text = text;
- }
-
- public String getText() {
- return text;
- }
-
- @Override
- public String toString() {
- return "'" + text + "'";
- }
-}
Deleted: framework/trunk/impl/src/main/java/org/ajax4jsf/resource/image/DiffusionFilterOp.java
===================================================================
--- branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/resource/image/DiffusionFilterOp.java 2009-07-07 12:45:54 UTC (rev 14807)
+++ framework/trunk/impl/src/main/java/org/ajax4jsf/resource/image/DiffusionFilterOp.java 2009-07-08 00:01:28 UTC (rev 14825)
@@ -1,268 +0,0 @@
-/**
- * License Agreement.
- *
- * Rich Faces - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * Helma License Notice
- *
- * The contents of this file are subject to the Helma License
- * Version 2.0 (the "License"). You may not use this file except in
- * compliance with the License. A copy of the License is available at
- * http://adele.helma.org/download/helma/license.txt
- *
- * Copyright 1998-2003 Helma Software. All Rights Reserved.
- *
- * $RCSfile: DiffusionFilterOp.java,v $
- * $Author: alexsmirnov $
- * $Revision: 1.1.2.1 $
- * $Date: 2007/01/09 18:59:06 $
- */
-
-/*
- * Code from com.jhlabs.image.DiffusionFilter, Java Image Processing
- * Copyright (C) Jerry Huxtable 1998
- * http://www.jhlabs.com/ip/
- *
- * Conversion to a BufferedImageOp inspired by:
- * http://www.peter-cockerell.net:8080/java/FloydSteinberg/FloydSteinbergFil...
- *
- */
-
-package org.ajax4jsf.resource.image;
-
-import java.awt.RenderingHints;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.BufferedImageOp;
-import java.awt.image.ColorModel;
-import java.awt.image.DataBufferByte;
-import java.awt.image.DataBufferInt;
-import java.awt.image.IndexColorModel;
-
-import org.ajax4jsf.Messages;
-
-public class DiffusionFilterOp implements BufferedImageOp {
-
- protected final static int[] diffusionMatrix = {
- 0, 0, 0,
- 0, 0, 7,
- 3, 5, 1,
- };
-
- private int[] matrix;
- private int sum;
- private boolean serpentine = true;
- private int[] colorMap;
-
- /**
- * Construct a DiffusionFilter
- */
- public DiffusionFilterOp() {
- setMatrix(diffusionMatrix);
- }
-
- /**
- * Set whether to use a serpentine pattern for return or not. This can reduce 'avalanche' artifacts in the output.
- * @param serpentine true to use serpentine pattern
- */
- public void setSerpentine(boolean serpentine) {
- this.serpentine = serpentine;
- }
-
- /**
- * Return the serpentine setting
- * @return the current setting
- */
- public boolean getSerpentine() {
- return serpentine;
- }
-
- public void setMatrix(int[] matrix) {
- this.matrix = matrix;
- sum = 0;
- for (int i = 0; i < matrix.length; i++)
- sum += matrix[i];
- }
-
- public int[] getMatrix() {
- return matrix;
- }
-
- /**
- * Do the filter operation
- *
- * @param src The source BufferedImage. Can be any type.
- * @param dst The destination image. If not null, must be of type TYPE_BYTE_INDEXED
- * @return A dithered version of src in a BufferedImage of type TYPE_BYTE_INDEXED
- */
- public BufferedImage filter(BufferedImage src, BufferedImage dst) {
-
- // If there's no dest. create one
- if (dst == null)
- dst = createCompatibleDestImage(src, null);
-
- // Otherwise check that the provided dest is an indexed image
- else if (dst.getType() != BufferedImage.TYPE_BYTE_INDEXED) {
- throw new IllegalArgumentException(Messages.getMessage(Messages.BUFFER_TYPE_ERROR));
- }
-
- DataBufferByte dstBuffer = (DataBufferByte) dst.getRaster().getDataBuffer();
- byte dstData[] = dstBuffer.getData();
-
- // Other things to test are pixel bit strides, scanline stride and transfer type
- // Same goes for the source image
-
- IndexColorModel icm = (IndexColorModel) dst.getColorModel();
- colorMap = new int[icm.getMapSize()];
- icm.getRGBs(colorMap);
-
- int width = src.getWidth();
- int height = src.getHeight();
-
- DataBufferInt srcBuffer = (DataBufferInt) src.getRaster().getDataBuffer();
- int srcData[] = srcBuffer.getData();
-
- // This is the offset into the buffer of the current source pixel
- int index = 0;
-
- // Loop through each pixel
- for (int y = 0; y < height; y++) {
- boolean reverse = serpentine && (y & 1) == 1;
- int direction;
- if (reverse) {
- index = y * width + width - 1;
- direction = -1;
- } else {
- index = y * width;
- direction = 1;
- }
- for (int x = 0; x < width; x++) {
- int rgb1 = srcData[index];
- int a1 = (rgb1 >> 24) & 0xff;
- int r1 = (rgb1 >> 16) & 0xff;
- int g1 = (rgb1 >> 8) & 0xff;
- int b1 = rgb1 & 0xff;
-
- int idx = findIndex(r1, g1, b1, a1);
- dstData[index] = (byte) idx;
-
- int rgb2 = colorMap[idx];
- int a2 = (rgb2 >> 24) & 0xff;
- int r2 = (rgb2 >> 16) & 0xff;
- int g2 = (rgb2 >> 8) & 0xff;
- int b2 = rgb2 & 0xff;
-
- int er = r1 - r2;
- int eg = g1 - g2;
- int eb = b1 - b2;
- int ea = a1 - a2;
-
- for (int i = -1; i <= 1; i++) {
- int iy = i + y;
- if (0 <= iy && iy < height) {
- for (int j = -1; j <= 1; j++) {
- int jx = j + x;
- if (0 <= jx && jx < width) {
- int w;
- if (reverse)
- w = matrix[(i + 1) * 3 - j + 1];
- else
- w = matrix[(i + 1) * 3 + j + 1];
- if (w != 0) {
- int k = reverse ? index - j : index + j;
- rgb1 = srcData[k];
- a1 = ((rgb1 >> 24) & 0xff) + ea * w / sum;
- r1 = ((rgb1 >> 16) & 0xff) + er * w / sum;
- g1 = ((rgb1 >> 8) & 0xff) + eg * w / sum;
- b1 = (rgb1 & 0xff) + eb * w / sum;
-
- srcData[k] = ((clamp(a1) << 24) | clamp(r1) << 16)
- | (clamp(g1) << 8) | clamp(b1);
- }
- }
- }
- }
- }
- index += direction;
- }
- }
-
- return dst;
- }
-
- private static int clamp(int c) {
- if (c < 0)
- return 0;
- if (c > 255)
- return 255;
- return c;
- }
-
- int findIndex(int r1, int g1, int b1, int a1)
- throws ArrayIndexOutOfBoundsException {
- int idx = 0;
- long dist = Long.MAX_VALUE;
- for (int i = 0; i < colorMap.length; i++) {
- int rgb2 = colorMap[i];
- int a2 = (rgb2 >> 24) & 0xff;
- int r2 = (rgb2 >> 16) & 0xff;
- int g2 = (rgb2 >> 8) & 0xff;
- int b2 = rgb2 & 0xff;
-
- int da = a1 - a2;
- int dr = r1 - r2;
- int dg = g1 - g2;
- int db = b1 - b2;
-
- long newdist = da * da + dr * dr + dg * dg + db * db;
- if (newdist < dist) {
- idx = i;
- dist = newdist;
- }
- }
- return idx;
- }
-
- // This always returns an indexed image
- public BufferedImage createCompatibleDestImage(BufferedImage src,
- ColorModel destCM) {
- return new BufferedImage(src.getWidth(), src.getHeight(),
- BufferedImage.TYPE_BYTE_INDEXED);
- }
-
- // There are no rendering hints
- public RenderingHints getRenderingHints() {
- return null;
- }
-
- // No transformation, so return the source point
- public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
- if (dstPt == null)
- dstPt = new Point2D.Float();
- dstPt.setLocation(srcPt.getX(), srcPt.getY());
- return dstPt;
- }
-
- // No transformation, so return the source bounds
- public Rectangle2D getBounds2D(BufferedImage src) {
- return src.getRaster().getBounds();
- }
-}
\ No newline at end of file
Deleted: framework/trunk/impl/src/main/java/org/ajax4jsf/resource/image/GIFEncoder.java
===================================================================
--- branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/resource/image/GIFEncoder.java 2009-07-07 12:45:54 UTC (rev 14807)
+++ framework/trunk/impl/src/main/java/org/ajax4jsf/resource/image/GIFEncoder.java 2009-07-08 00:01:28 UTC (rev 14825)
@@ -1,554 +0,0 @@
-/**
- * License Agreement.
- *
- * Rich Faces - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * Helma License Notice
- *
- * The contents of this file are subject to the Helma License
- * Version 2.0 (the "License"). You may not use this file except in
- * compliance with the License. A copy of the License is available at
- * http://adele.helma.org/download/helma/license.txt
- *
- * Copyright 1998-2003 Helma Software. All Rights Reserved.
- *
- * $RCSfile: GIFEncoder.java,v $
- * $Author: alexsmirnov $
- * $Revision: 1.1.2.1 $
- * $Date: 2007/01/09 18:59:03 $
- */
-
-/*
- * The GIF encoding routines are based on the Acme libary
- *
- * The following addaptions and extensions were added by Joerg Lehni:
- *
- * - encode now directly works on BufferedImage objects, the ImageEncoder
- * and ImageConsumer oriented frameworks has been removed.
- * - Only BufferedImages with IndexColorModel are taken, so no more
- * palette optimization with IntHashtable objects are necessary. If the
- * BufferedImage is in wrong format, helma.image.Quantizie is used to
- * convert it into a index based image.
- * - This version is much less space consuming as it only takes one sample
- * row of the rastered image at a time into memory during compression.
- * - The overall time for color reduction and gif compression should
- * therefore be greatly reduced.
- *
- * Acme Disclaimer:
- *
- * Transparency handling and variable bit size courtesy of Jack Palevich.
- *
- * Copyright (C)1996,1998 by Jef Poskanzer <jef(a)acme.com>. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * Visit the ACME Labs Java page for up-to-date versions of this and other
- * fine Java utilities: http://www.acme.com/java/
- *
- * GifEncoder is adapted from ppmtogif, which is based on GIFENCOD by David
- * Rowley <mgardi(a)watdscu.waterloo.edu>. Lempel-Zim compression
- * based on "compress".
- *
- */
-
-package org.ajax4jsf.resource.image;
-
-import java.awt.image.BufferedImage;
-import java.awt.image.IndexColorModel;
-import java.awt.image.Raster;
-import java.io.DataOutput;
-import java.io.IOException;
-
-public class GIFEncoder {
- private boolean interlace = false;
-
- private int width, height;
- private Raster raster;
- // DataOutput is used for compatibility with ImageIO (see helma.image.imageio.gif.GIFImageWriter)
- // otherwise, OutputStream would make much more sense here:
- private DataOutput out;
-
- private int curx, cury;
- private int countdown;
- private int pass;
- private int[] row;
-
- public void encode(BufferedImage bi, DataOutput out) throws IOException {
- encode(bi, out, false, null);
- }
-
- public void encode(BufferedImage bi, DataOutput out, boolean interlace,
- String comment) throws IOException {
- this.out = out;
- this.interlace = interlace;
-
- // make sure it's index colors:
- if (bi.getType() != BufferedImage.TYPE_BYTE_INDEXED)
- bi = Quantize.process(bi, 256, false, true);
-
- raster = bi.getRaster();
-
- width = bi.getWidth();
- height = bi.getHeight();
-
- int numPixels = width * height;
-
- IndexColorModel icm = (IndexColorModel) bi.getColorModel();
- int transparentIndex = icm.getTransparentPixel();
- int numColors = icm.getMapSize();
-
- // Figure out how many bits to use.
- int bitsPerPixel;
- if (numColors <= 2)
- bitsPerPixel = 1;
- else if (numColors <= 4)
- bitsPerPixel = 2;
- else if (numColors <= 16)
- bitsPerPixel = 4;
- else
- bitsPerPixel = 8;
-
- int initCodeSize;
-
- // Calculate number of bits we are expecting
- countdown = numPixels;
-
- // Indicate which pass we are on (if interlace)
- pass = 0;
-
- // The initial code size
- if (bitsPerPixel <= 1)
- initCodeSize = 2;
- else
- initCodeSize = bitsPerPixel;
-
- // Set up the current x and y position
- curx = 0;
- cury = 0;
- row = new int[width];
-
- // Write the Magic header
- writeString("GIF89a");
-
- // Write out the screen width and height
- writeWord(width);
- writeWord(height);
-
- // Indicate that there is a global colour map
- byte flags = (byte) 0x80; // Yes, there is a color map
- // OR in the resolution
- flags |= (byte) ((8 - 1) << 4);
- // Not sorted
- // OR in the Bits per Pixel
- flags |= (byte) ((bitsPerPixel - 1));
- // Write it out
- out.write(flags);
-
- // Write out the Background colour
- out.write((byte) 0);
-
- // Pixel aspect ratio - 1:1.
- //out.write((byte) 49);
- // Java's GIF reader currently has a bug, if the aspect ratio byte is
- // not zero it throws an ImageFormatException. It doesn't know that
- // 49 means a 1:1 aspect ratio. Well, whatever, zero works with all
- // the other decoders I've tried so it probably doesn't hurt.
- out.write((byte) 0);
-
- // Write out the Global Colour Map
- // Turn colors into colormap entries.
- int mapSize = 1 << bitsPerPixel;
- byte[] reds = new byte[mapSize], greens = new byte[mapSize], blues = new byte[mapSize];
- icm.getReds(reds);
- icm.getGreens(greens);
- icm.getBlues(blues);
-
- for (int i = 0; i < mapSize; ++i) {
- out.write(reds[i]);
- out.write(greens[i]);
- out.write(blues[i]);
- }
-
- // Write out extension for transparent colour index, if necessary.
- if (transparentIndex != -1) {
- out.write((byte) '!');
- out.write((byte) 0xf9);
- out.write((byte) 4);
- out.write((byte) 1);
- out.write((byte) 0);
- out.write((byte) 0);
- out.write((byte) transparentIndex);
- out.write((byte) 0);
- }
-
- // Write an Image separator
- out.write((byte) ',');
-
- // Write the Image header
- writeWord(0); // leftOfs
- writeWord(0); // topOfs
- writeWord(width);
- writeWord(height);
-
- // Write out whether or not the image is interlaced
- if (interlace)
- out.write((byte) 0x40);
- else
- out.write((byte) 0x00);
-
- // Write out the initial code size
- out.write((byte) initCodeSize);
-
- // Go and actually compress the data
- compress(initCodeSize + 1);
-
- // Write out a Zero-length packet (to end the series)
- out.write((byte) 0);
-
- // Write out the comment
- if (comment != null && comment.length() > 0) {
- out.write((byte) 0x21);
- out.write((byte) 0xFE);
- out.write((byte) comment.length());
- writeString(comment);
- out.write((byte) 0);
- }
-
- // Write the GIF file terminator
- out.write((byte) ';');
- }
-
- // Return the next pixel from the image
- int getNextPixel() throws IOException {
- if (countdown == 0)
- return -1;
-
- --countdown;
-
- if (curx == 0)
- row = raster.getSamples(0, cury, width, 1, 0, row);
- int index = row[curx];
-
- // Bump the current X position
- ++curx;
-
- // If we are at the end of a scan line, set curx back to the beginning
- // If we are interlaced, bump the cury to the appropriate spot,
- // otherwise, just increment it.
- if (curx == width) {
- curx = 0;
-
- if (!interlace) {
- ++cury;
- } else {
- switch (pass) {
- case 0:
- cury += 8;
- if (cury >= height) {
- ++pass;
- cury = 4;
- }
- break;
-
- case 1:
- cury += 8;
- if (cury >= height) {
- ++pass;
- cury = 2;
- }
- break;
-
- case 2:
- cury += 4;
- if (cury >= height) {
- ++pass;
- cury = 1;
- }
- break;
-
- case 3:
- cury += 2;
- break;
- }
- }
- }
- return index;
- }
-
- void writeString(String str) throws IOException {
- byte[] buf = str.getBytes();
- out.write(buf);
- }
-
- // Write out a word to the GIF file
- void writeWord(int w) throws IOException {
- out.write((byte) (w & 0xff));
- out.write((byte) ((w >> 8) & 0xff));
- }
-
- // GIFCOMPR.C - GIF Image compression routines
- //
- // Lempel-Ziv compression based on 'compress'. GIF modifications by
- // David Rowley (mgardi(a)watdcsu.waterloo.edu)
-
- // General DEFINEs
-
- static final int BITS = 12;
-
- static final int HASH_SIZE = 5003; // 80% occupancy
-
- // GIF Image compression - modified 'compress'
- //
- // Based on: compress.c - File compression ala IEEE Computer, June 1984.
- //
- // By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
- // Jim McKie (decvax!mcvax!jim)
- // Steve Davies (decvax!vax135!petsd!peora!srd)
- // Ken Turkowski (decvax!decwrl!turtlevax!ken)
- // James A. Woods (decvax!ihnp4!ames!jaw)
- // Joe Orost (decvax!vax135!petsd!joe)
-
- private int numBits; // number of bits/code
- private int maxBits = BITS; // user settable max # bits/code
- private int maxCode; // maximum code, given numBits
- private int maxMaxCode = 1 << BITS; // should NEVER generate this code
-
- final int getMaxCode(int numBits) {
- return (1 << numBits) - 1;
- }
-
- private int[] hashTable = new int[HASH_SIZE];
- private int[] codeTable = new int[HASH_SIZE];
-
- private int freeEntry = 0; // first unused entry
-
- // block compression parameters -- after all codes are used up,
- // and compression rate changes, start over.
- private boolean clearFlag = false;
-
- // Algorithm: use open addressing double hashing (no chaining) on the
- // prefix code / next character combination. We do a variant of Knuth's
- // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
- // secondary probe. Here, the modular division first probe is gives way
- // to a faster exclusive-or manipulation. Also do block compression with
- // an adaptive reset, whereby the code table is cleared when the compression
- // ratio decreases, but after the table fills. The variable-length output
- // codes are re-sized at this point, and a special CLEAR code is generated
- // for the decompressor. Late addition: construct the table according to
- // file size for noticeable speed improvement on small files. Please direct
- // questions about this implementation to ames!jaw.
-
- private int initBits;
-
- private int clearCode;
- private int EOFCode;
-
- void compress(int initBits) throws IOException {
- // Set up the globals: initBits - initial number of bits
- this.initBits = initBits;
-
- // Set up the necessary values
- clearFlag = false;
- numBits = initBits;
- maxCode = getMaxCode(numBits);
-
- clearCode = 1 << (initBits - 1);
- EOFCode = clearCode + 1;
- freeEntry = clearCode + 2;
-
- charInit();
-
- int ent = getNextPixel();
-
- int hashShift = 0;
- for (int fcode = HASH_SIZE; fcode < 65536; fcode *= 2)
- ++hashShift;
- hashShift = 8 - hashShift; // set hash code range bound
-
- clearHash(); // clear hash table
-
- output(clearCode);
-
- int c;
- outerLoop: while ((c = getNextPixel()) != -1) {
- int fcode = (c << maxBits) + ent;
- int i = (c << hashShift) ^ ent; // xor hashing
-
- if (hashTable[i] == fcode) {
- ent = codeTable[i];
- continue;
- } else if (hashTable[i] >= 0) { // non-empty slot
- int disp = HASH_SIZE - i; // secondary hash (after G. Knott)
- if (i == 0)
- disp = 1;
- do {
- if ((i -= disp) < 0)
- i += HASH_SIZE;
-
- if (hashTable[i] == fcode) {
- ent = codeTable[i];
- continue outerLoop;
- }
- } while (hashTable[i] >= 0);
- }
- output(ent);
- ent = c;
- if (freeEntry < maxMaxCode) {
- codeTable[i] = freeEntry++; // code -> hashtable
- hashTable[i] = fcode;
- } else
- clearBlock();
- }
- // Put out the final code.
- output(ent);
- output(EOFCode);
- }
-
- // output
- //
- // Output the given code.
- // Inputs:
- // code: A numBits-bit integer. If == -1, then EOF. This assumes
- // that numBits =< wordsize - 1.
- // Outputs:
- // Outputs code to the file.
- // Assumptions:
- // Chars are 8 bits long.
- // Algorithm:
- // Maintain a BITS character long buffer (so that 8 codes will
- // fit in it exactly). Use the VAX insv instruction to insert each
- // code in turn. When the buffer fills up empty it and start over.
-
- int curAccum = 0;
- int curBits = 0;
-
- int masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F,
- 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF,
- 0x7FFF, 0xFFFF };
-
- void output(int code) throws IOException {
- curAccum &= masks[curBits];
-
- if (curBits > 0)
- curAccum |= (code << curBits);
- else
- curAccum = code;
-
- curBits += numBits;
-
- while (curBits >= 8) {
- charOut((byte) (curAccum & 0xff));
- curAccum >>= 8;
- curBits -= 8;
- }
-
- // If the next entry is going to be too big for the code size,
- // then increase it, if possible.
- if (freeEntry > maxCode || clearFlag) {
- if (clearFlag) {
- maxCode = getMaxCode(numBits = initBits);
- clearFlag = false;
- } else {
- ++numBits;
- if (numBits == maxBits)
- maxCode = maxMaxCode;
- else
- maxCode = getMaxCode(numBits);
- }
- }
-
- if (code == EOFCode) {
- // At EOF, write the rest of the buffer.
- while (curBits > 0) {
- charOut((byte) (curAccum & 0xff));
- curAccum >>= 8;
- curBits -= 8;
- }
-
- charFlush();
- }
- }
-
- // Clear out the hash table
-
- // table clear for block compress
- void clearBlock() throws IOException {
- clearHash();
- freeEntry = clearCode + 2;
- clearFlag = true;
-
- output(clearCode);
- }
-
- // reset code table
- void clearHash() {
- for (int i = 0; i < HASH_SIZE; ++i)
- hashTable[i] = -1;
- }
-
- // GIF Specific routines
-
- // Number of characters so far in this 'packet'
- private int a_count;
-
- // Set up the 'byte output' routine
- void charInit() {
- a_count = 0;
- }
-
- // Define the storage for the packet accumulator
- private byte[] accum = new byte[256];
-
- // Add a character to the end of the current packet, and if it is 254
- // characters, flush the packet to disk.
- void charOut(byte c) throws IOException {
- accum[a_count++] = c;
- if (a_count >= 254)
- charFlush();
- }
-
- // Flush the packet to disk, and reset the accumulator
- void charFlush() throws IOException {
- if (a_count > 0) {
- out.write(a_count);
- out.write(accum, 0, a_count);
- a_count = 0;
- }
- }
-}
\ No newline at end of file
Deleted: framework/trunk/impl/src/main/java/org/ajax4jsf/resource/image/Quantize.java
===================================================================
--- branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/resource/image/Quantize.java 2009-07-07 12:45:54 UTC (rev 14807)
+++ framework/trunk/impl/src/main/java/org/ajax4jsf/resource/image/Quantize.java 2009-07-08 00:01:28 UTC (rev 14825)
@@ -1,840 +0,0 @@
-/**
- * License Agreement.
- *
- * Rich Faces - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * Helma License Notice
- *
- * The contents of this file are subject to the Helma License
- * Version 2.0 (the "License"). You may not use this file except in
- * compliance with the License. A copy of the License is available at
- * http://adele.helma.org/download/helma/license.txt
- *
- * Copyright 1998-2003 Helma Software. All Rights Reserved.
- *
- * $RCSfile: Quantize.java,v $
- * $Author: alexsmirnov $
- * $Revision: 1.1.2.1 $
- * $Date: 2007/01/09 18:59:05 $
- */
-
-package org.ajax4jsf.resource.image;
-
-import java.awt.image.BufferedImage;
-import java.awt.image.DataBufferByte;
-import java.awt.image.DataBufferInt;
-import java.awt.image.IndexColorModel;
-
-/*
- * @(#)Quantize.java 0.90 9/19/00 Adam Doppelt
- *
- * Modifications by Joerg Lehni:
- *
- * - Support for alpha-channels.
- * - Returns a BufferedImage of TYPE_BYTE_INDEXED with a IndexColorModel.
- * - Dithering of images through helma.image.DiffusionFilterOp by setting
- * the dither parameter to true.
- * - Support for a transparent color, which is correctly rendered by GIFEncoder.
- * All pixels with alpha < 0x80 are converted to this color when the parameter
- * alphaToBitmask is set to true.
- * - Removed the SQUARES lookup tables as multiplications of integer values
- * shouldn't take more than one clock nowadays anyhow.
- */
-
-/**
- * An efficient color quantization algorithm, adapted from the C++
- * implementation quantize.c in <a
- * href="http://www.imagemagick.org/">ImageMagick</a>. The pixels for
- * an image are placed into an oct tree. The oct tree is reduced in
- * size, and the pixels from the original image are reassigned to the
- * nodes in the reduced tree.<p>
- *
- * Here is the copyright notice from ImageMagick:
- *
- * <pre>
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Permission is hereby granted, free of charge, to any person obtaining a %
-% copy of this software and associated documentation files ("ImageMagick"), %
-% to deal in ImageMagick without restriction, including without limitation %
-% the rights to use, copy, modify, merge, publish, distribute, sublicense, %
-% and/or sell copies of ImageMagick, and to permit persons to whom the %
-% ImageMagick is furnished to do so, subject to the following conditions: %
-% %
-% The above copyright notice and this permission notice shall be included in %
-% all copies or substantial portions of ImageMagick. %
-% %
-% The software is provided "as is", without warranty of any kind, express or %
-% implied, including but not limited to the warranties of merchantability, %
-% fitness for a particular purpose and noninfringement. In no event shall %
-% E. I. du Pont de Nemours and Company be liable for any claim, damages or %
-% other liability, whether in an action of contract, tort or otherwise, %
-% arising from, out of or in connection with ImageMagick or the use or other %
-% dealings in ImageMagick. %
-% %
-% Except as contained in this notice, the name of the E. I. du Pont de %
-% Nemours and Company shall not be used in advertising or otherwise to %
-% promote the sale, use or other dealings in ImageMagick without prior %
-% written authorization from the E. I. du Pont de Nemours and Company. %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-</pre>
- *
- *
- * @version 0.90 19 Sep 2000
- * @author <a href="http://www.gurge.com/amd/">Adam Doppelt</a>
- */
-public class Quantize {
-
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% %
-% %
-% QQQ U U AAA N N TTTTT IIIII ZZZZZ EEEEE %
-% Q Q U U A A NN N T I ZZ E %
-% Q Q U U AAAAA N N N T I ZZZ EEEEE %
-% Q QQ U U A A N NN T I ZZ E %
-% QQQQ UUU A A N N T IIIII ZZZZZ EEEEE %
-% %
-% %
-% Reduce the Number of Unique Colors in an Image %
-% %
-% %
-% Software Design %
-% John Cristy %
-% July 1992 %
-% %
-% %
-% Copyright 1998 E. I. du Pont de Nemours and Company %
-% %
-% Permission is hereby granted, free of charge, to any person obtaining a %
-% copy of this software and associated documentation files ("ImageMagick"), %
-% to deal in ImageMagick without restriction, including without limitation %
-% the rights to use, copy, modify, merge, publish, distribute, sublicense, %
-% and/or sell copies of ImageMagick, and to permit persons to whom the %
-% ImageMagick is furnished to do so, subject to the following conditions: %
-% %
-% The above copyright notice and this permission notice shall be included in %
-% all copies or substantial portions of ImageMagick. %
-% %
-% The software is provided "as is", without warranty of any kind, express or %
-% implied, including but not limited to the warranties of merchantability, %
-% fitness for a particular purpose and noninfringement. In no event shall %
-% E. I. du Pont de Nemours and Company be liable for any claim, damages or %
-% other liability, whether in an action of contract, tort or otherwise, %
-% arising from, out of or in connection with ImageMagick or the use or other %
-% dealings in ImageMagick. %
-% %
-% Except as contained in this notice, the name of the E. I. du Pont de %
-% Nemours and Company shall not be used in advertising or otherwise to %
-% promote the sale, use or other dealings in ImageMagick without prior %
-% written authorization from the E. I. du Pont de Nemours and Company. %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-% Realism in computer graphics typically requires using 24 bits/pixel to
-% generate an image. Yet many graphic display devices do not contain
-% the amount of memory necessary to match the spatial and color
-% resolution of the human eye. The QUANTIZE program takes a 24 bit
-% image and reduces the number of colors so it can be displayed on
-% raster device with less bits per pixel. In most instances, the
-% quantized image closely resembles the original reference image.
-%
-% A reduction of colors in an image is also desirable for image
-% transmission and real-time animation.
-%
-% Function Quantize takes a standard RGB or monochrome images and quantizes
-% them down to some fixed number of colors.
-%
-% For purposes of color allocation, an image is a set of n pixels, where
-% each pixel is a point in RGB space. RGB space is a 3-dimensional
-% vector space, and each pixel, pi, is defined by an ordered triple of
-% red, green, and blue coordinates, (ri, gi, bi).
-%
-% Each primary color component (red, green, or blue) represents an
-% intensity which varies linearly from 0 to a maximum value, cmax, which
-% corresponds to full saturation of that color. Color allocation is
-% defined over a domain consisting of the cube in RGB space with
-% opposite vertices at (0,0,0) and (cmax,cmax,cmax). QUANTIZE requires
-% cmax = 255.
-%
-% The algorithm maps this domain onto a tree in which each node
-% represents a cube within that domain. In the following discussion
-% these cubes are defined by the coordinate of two opposite vertices:
-% The vertex nearest the origin in RGB space and the vertex farthest
-% from the origin.
-%
-% The tree's root node represents the the entire domain, (0,0,0) through
-% (cmax,cmax,cmax). Each lower level in the tree is generated by
-% subdividing one node's cube into eight smaller cubes of equal size.
-% This corresponds to bisecting the parent cube with planes passing
-% through the midpoints of each edge.
-%
-% The basic algorithm operates in three phases: Classification,
-% Reduction, and Assignment. Classification builds a color
-% description tree for the image. Reduction collapses the tree until
-% the number it represents, at most, the number of colors desired in the
-% output image. Assignment defines the output image's color map and
-% sets each pixel's color by reclassification in the reduced tree.
-% Our goal is to minimize the numerical discrepancies between the original
-% colors and quantized colors (quantization error).
-%
-% Classification begins by initializing a color description tree of
-% sufficient depth to represent each possible input color in a leaf.
-% However, it is impractical to generate a fully-formed color
-% description tree in the classification phase for realistic values of
-% cmax. If colors components in the input image are quantized to k-bit
-% precision, so that cmax= 2k-1, the tree would need k levels below the
-% root node to allow representing each possible input color in a leaf.
-% This becomes prohibitive because the tree's total number of nodes is
-% 1 + sum(i=1,k,8k).
-%
-% A complete tree would require 19,173,961 nodes for k = 8, cmax = 255.
-% Therefore, to avoid building a fully populated tree, QUANTIZE: (1)
-% Initializes data structures for nodes only as they are needed; (2)
-% Chooses a maximum depth for the tree as a function of the desired
-% number of colors in the output image (currently log2(colorMap size)).
-%
-% For each pixel in the input image, classification scans downward from
-% the root of the color description tree. At each level of the tree it
-% identifies the single node which represents a cube in RGB space
-% containing the pixel's color. It updates the following data for each
-% such node:
-%
-% n1: Number of pixels whose color is contained in the RGB cube
-% which this node represents;
-%
-% n2: Number of pixels whose color is not represented in a node at
-% lower depth in the tree; initially, n2 = 0 for all nodes except
-% leaves of the tree.
-%
-% Sr, Sg, Sb: Sums of the red, green, and blue component values for
-% all pixels not classified at a lower depth. The combination of
-% these sums and n2 will ultimately characterize the mean color of a
-% set of pixels represented by this node.
-%
-% E: The distance squared in RGB space between each pixel contained
-% within a node and the nodes' center. This represents the quantization
-% error for a node.
-%
-% Reduction repeatedly prunes the tree until the number of nodes with
-% n2 > 0 is less than or equal to the maximum number of colors allowed
-% in the output image. On any given iteration over the tree, it selects
-% those nodes whose E count is minimal for pruning and merges their
-% color statistics upward. It uses a pruning threshold, Ep, to govern
-% node selection as follows:
-%
-% Ep = 0
-% while number of nodes with (n2 > 0) > required maximum number of colors
-% prune all nodes such that E <= Ep
-% Set Ep to minimum E in remaining nodes
-%
-% This has the effect of minimizing any quantization error when merging
-% two nodes together.
-%
-% When a node to be pruned has offspring, the pruning procedure invokes
-% itself recursively in order to prune the tree from the leaves upward.
-% n2, Sr, Sg, and Sb in a node being pruned are always added to the
-% corresponding data in that node's parent. This retains the pruned
-% node's color characteristics for later averaging.
-%
-% For each node, n2 pixels exist for which that node represents the
-% smallest volume in RGB space containing those pixel's colors. When n2
-% > 0 the node will uniquely define a color in the output image. At the
-% beginning of reduction, n2 = 0 for all nodes except a the leaves of
-% the tree which represent colors present in the input image.
-%
-% The other pixel count, n1, indicates the total number of colors
-% within the cubic volume which the node represents. This includes n1 -
-% n2 pixels whose colors should be defined by nodes at a lower level in
-% the tree.
-%
-% Assignment generates the output image from the pruned tree. The
-% outpu t image consists of two parts: (1) A color map, which is an
-% array of color descriptions (RGB triples) for each color present in
-% the output image; (2) A pixel array, which represents each pixel as
-% an index into the color map array.
-%
-% First, the assignment phase makes one pass over the pruned color
-% description tree to establish the image's color map. For each node
-% with n2 > 0, it divides Sr, Sg, and Sb by n2 . This produces the
-% mean color of all pixels that classify no lower than this node. Each
-% of these colors becomes an entry in the color map.
-%
-% Finally, the assignment phase reclassifies each pixel in the pruned
-% tree to identify the deepest node containing the pixel's color. The
-% pixel's value in the pixel array becomes the index of this node's mean
-% color in the color map.
-%
-% With the permission of USC Information Sciences Institute, 4676 Admiralty
-% Way, Marina del Rey, California 90292, this code was adapted from module
-% ALCOLS written by Paul Raveling.
-%
-% The names of ISI and USC are not used in advertising or publicity
-% pertaining to distribution of the software without prior specific
-% written permission from ISI.
-%
-*/
-
- final static boolean QUICK = false;
-
- final static int MAX_RGB = 255;
- final static int MAX_NODES = 266817;
- final static int MAX_TREE_DEPTH = 8;
- final static int MAX_CHILDREN = 16;
-
- /**
- * Reduce the image to the given number of colors. The pixels are reduced in
- * place.
- *
- * @return The new color palette.
- */
- public static BufferedImage process(BufferedImage source, int maxColors,
- boolean dither, boolean alphaToBitmask) {
- int type = source.getType();
- int[] pixels;
- // try to get the direct pixels of the BufferedImage
- // this works for images of type INT_RGB, INT_ARGB and INT_ARGB_PRE
- // for all others, a new array with rgb pixels is created!
- if (type == BufferedImage.TYPE_INT_RGB
- || type == BufferedImage.TYPE_INT_ARGB
- || type == BufferedImage.TYPE_INT_ARGB_PRE) {
- pixels = ((DataBufferInt) source.getRaster().getDataBuffer()).getData();
- } else {
- pixels = source.getRGB(0, 0, source.getWidth(), source.getHeight(), null, 0, source.getWidth());
- }
- Cube cube = new Cube(source, pixels, maxColors, dither, alphaToBitmask);
- cube.classification();
- cube.reduction();
- return cube.assignment();
- }
-
- static class Cube {
- BufferedImage source;
- int[] pixels;
- int maxColors;
- byte colorMap[][];
-
- Node root;
- int depth;
-
- boolean dither;
- boolean alphaToBitmask;
- boolean addTransparency;
- // firstColor is set to 1 when when addTransparency is true!
- int firstColor = 0;
-
- // counter for the number of colors in the cube. this gets
- // recalculated often.
- int numColors;
-
- // counter for the number of nodes in the tree
- int numNodes;
-
- Cube(BufferedImage source, int[] pixels, int maxColors, boolean dither,
- boolean alphaToBitmask) {
- this.source = source;
- this.pixels = pixels;
- this.maxColors = maxColors;
- this.dither = dither;
- this.alphaToBitmask = alphaToBitmask;
-
- int i = maxColors;
- // tree_depth = log maxColors
- // 4
- for (depth = 1; i != 0; depth++) {
- i /= 4;
- }
- if (depth > 1) {
- --depth;
- }
- if (depth > MAX_TREE_DEPTH) {
- depth = MAX_TREE_DEPTH;
- } else if (depth < 2) {
- depth = 2;
- }
-
- root = new Node(this);
- }
-
- /*
- * Procedure Classification begins by initializing a color description
- * tree of sufficient depth to represent each possible input color in a
- * leaf. However, it is impractical to generate a fully-formed color
- * description tree in the classification phase for realistic values of
- * cmax. If colors components in the input image are quantized to k-bit
- * precision, so that cmax= 2k-1, the tree would need k levels below the
- * root node to allow representing each possible input color in a leaf.
- * This becomes prohibitive because the tree's total number of nodes is
- * 1 + sum(i=1,k,8k).
- *
- * A complete tree would require 19,173,961 nodes for k = 8, cmax = 255.
- * Therefore, to avoid building a fully populated tree, QUANTIZE: (1)
- * Initializes data structures for nodes only as they are needed; (2)
- * Chooses a maximum depth for the tree as a function of the desired
- * number of colors in the output image (currently log2(colorMap size)).
- *
- * For each pixel in the input image, classification scans downward from
- * the root of the color description tree. At each level of the tree it
- * identifies the single node which represents a cube in RGB space
- * containing It updates the following data for each such node:
- *
- * numPixels : Number of pixels whose color is contained in the RGB cube
- * which this node represents;
- *
- * unique : Number of pixels whose color is not represented in a node at
- * lower depth in the tree; initially, n2 = 0 for all nodes except
- * leaves of the tree.
- *
- * totalRed/green/blue : Sums of the red, green, and blue component
- * values for all pixels not classified at a lower depth. The
- * combination of these sums and n2 will ultimately characterize the
- * mean color of a set of pixels represented by this node.
- */
- void classification() {
- addTransparency = false;
- firstColor = 0;
- for (int i = 0; i < pixels.length; i++) {
- int pixel = pixels[i];
- int red = (pixel >> 16) & 0xff;
- int green = (pixel >> 8) & 0xff;
- int blue = (pixel >> 0) & 0xff;
- int alpha = (pixel >> 24) & 0xff;
- if (alphaToBitmask)
- alpha = alpha < 0x80 ? 0 : 0xff;
-
- if (alpha > 0) {
- // a hard limit on the number of nodes in the tree
- if (numNodes > MAX_NODES) {
- // System.out.println("pruning");
- root.pruneLevel();
- --depth;
- }
-
- // walk the tree to depth, increasing the
- // numPixels count for each node
- Node node = root;
- for (int level = 1; level <= depth; ++level) {
- int id = (((red > node.midRed ? 1 : 0) << 0)
- | ((green > node.midGreen ? 1 : 0) << 1)
- | ((blue > node.midBlue ? 1 : 0) << 2) | ((alpha > node.midAlpha ? 1
- : 0) << 3));
- if (node.children[id] == null) {
- node = new Node(node, id, level);
- } else {
- node = node.children[id];
- }
- node.numPixels++;
- }
-
- ++node.unique;
- node.totalRed += red;
- node.totalGreen += green;
- node.totalBlue += blue;
- node.totalAlpha += alpha;
- } else if (!addTransparency) {
- addTransparency = true;
- numColors++;
- firstColor = 1; // start at 1 as 0 will be the transparent
- // color
- }
- }
- }
-
- /*
- * reduction repeatedly prunes the tree until the number of nodes with
- * unique > 0 is less than or equal to the maximum number of colors
- * allowed in the output image.
- *
- * When a node to be pruned has offspring, the pruning procedure invokes
- * itself recursively in order to prune the tree from the leaves upward.
- * The statistics of the node being pruned are always added to the
- * corresponding data in that node's parent. This retains the pruned
- * node's color characteristics for later averaging.
- */
- void reduction() {
- int threshold = 1;
- while (numColors > maxColors) {
- numColors = firstColor;
- threshold = root.reduce(threshold, Integer.MAX_VALUE);
- }
- }
-
- /**
- * The result of a closest color search.
- */
- static class Search {
- int distance;
- int colorIndex;
- }
-
- /*
- * Procedure assignment generates the output image from the pruned tree.
- * The output image consists of two parts: (1) A color map, which is an
- * array of color descriptions (RGB triples) for each color present in
- * the output image; (2) A pixel array, which represents each pixel as
- * an index into the color map array.
- *
- * First, the assignment phase makes one pass over the pruned color
- * description tree to establish the image's color map. For each node
- * with n2 > 0, it divides Sr, Sg, and Sb by n2. This produces the mean
- * color of all pixels that classify no lower than this node. Each of
- * these colors becomes an entry in the color map.
- *
- * Finally, the assignment phase reclassifies each pixel in the pruned
- * tree to identify the deepest node containing the pixel's color. The
- * pixel's value in the pixel array becomes the index of this node's
- * mean color in the color map.
- */
- BufferedImage assignment() {
- colorMap = new byte[4][numColors];
-
- if (addTransparency) {
- // if a transparency color is added, firstColor was set to 1,
- // so color 0 can be used for this
- colorMap[0][0] = 0;
- colorMap[1][0] = 0;
- colorMap[2][0] = 0;
- colorMap[3][0] = 0;
- }
- numColors = firstColor;
- root.mapColors();
-
- // determine bit depth for palette
- int depth;
- for (depth = 1; depth <= 8; depth++)
- if ((1 << depth) >= numColors)
- break;
-
- // create the right color model, depending on transparency settings:
- IndexColorModel icm;
- if (alphaToBitmask) {
- if (addTransparency)
- icm = new IndexColorModel(depth, numColors, colorMap[0],
- colorMap[1], colorMap[2], 0);
- else
- icm = new IndexColorModel(depth, numColors, colorMap[0],
- colorMap[1], colorMap[2]);
- } else {
- icm = new IndexColorModel(depth, numColors, colorMap[0],
- colorMap[1], colorMap[2], colorMap[3]);
- }
- // create the indexed BufferedImage:
- BufferedImage dest = new BufferedImage(source.getWidth(),
- source.getHeight(), BufferedImage.TYPE_BYTE_INDEXED, icm);
-
- boolean firstOut = true;
- if (dither)
- new DiffusionFilterOp().filter(source, dest);
- else {
- Search search = new Search();
- // convert to indexed color
- byte[] dst = ((DataBufferByte) dest.getRaster().getDataBuffer()).getData();
-
- for (int i = 0; i < pixels.length; i++) {
- int pixel = pixels[i];
- int red = (pixel >> 16) & 0xff;
- int green = (pixel >> 8) & 0xff;
- int blue = (pixel >> 0) & 0xff;
- int alpha = (pixel >> 24) & 0xff;
-
- if (alphaToBitmask)
- alpha = alpha < 128 ? 0 : 0xff;
-
- // this is super weird: on some systems, transparent pixels are
- // not calculated correctly if the following block is taken out.
- // the bug is very strange, isn't related to the code (compiler error?)
- // but doesn't allways happen. as soon as it does, though, it doesn't
- // seem to want to go away.
- // This happened at various times on my two different debian systems
- // and i never found out how to really fix it. the following line seems to
- // prevent it from happening, but i wonder wether there's a better way
- // to fix it.
- // it looks as if the command forces alpha to take on correct values.
- // Until now I only knew of effects like that in quantum mechanics...
- if (i == 0) {
- String fix = "" + alpha;
- }
-
- if (alpha == 0 && addTransparency) {
- dst[i] = 0; // transparency color is at 0
- } else {
- // walk the tree to find the cube containing that color
- Node node = root;
- for (;;) {
- int id = (((red > node.midRed ? 1 : 0) << 0)
- | ((green > node.midGreen ? 1 : 0) << 1)
- | ((blue > node.midBlue ? 1 : 0) << 2) | ((alpha > node.midAlpha ? 1
- : 0) << 3));
- if (node.children[id] == null) {
- break;
- }
- node = node.children[id];
- }
-
- if (QUICK) {
- // if QUICK is set, just use that
- // node. Strictly speaking, this isn't
- // necessarily best match.
- dst[i] = (byte) node.colorIndex;
- } else {
- // Find the closest color.
- search.distance = Integer.MAX_VALUE;
- node.parent.closestColor(red, green, blue, alpha,
- search);
- dst[i] = (byte) search.colorIndex;
- }
- }
- }
- }
- return dest;
- }
-
- /**
- * A single Node in the tree.
- */
- static class Node {
- Cube cube;
-
- // parent node
- Node parent;
-
- // children nodes
- Node children[];
- int numChildren;
-
- // our index within our parent
- int id;
- // our level within the tree
- int level;
- // our color midpoint
- int midRed;
- int midGreen;
- int midBlue;
- int midAlpha;
-
- // the pixel count for this node and all children
- int numPixels;
-
- // the pixel count for this node
- int unique;
- // the sum of all pixels contained in this node
- int totalRed;
- int totalGreen;
- int totalBlue;
- int totalAlpha;
-
- // used to build the colorMap
- int colorIndex;
-
- Node(Cube cube) {
- this.cube = cube;
- this.parent = this;
- this.children = new Node[MAX_CHILDREN];
- this.id = 0;
- this.level = 0;
-
- this.numPixels = Integer.MAX_VALUE;
-
- this.midRed = (MAX_RGB + 1) >> 1;
- this.midGreen = (MAX_RGB + 1) >> 1;
- this.midBlue = (MAX_RGB + 1) >> 1;
- this.midAlpha = (MAX_RGB + 1) >> 1;
- }
-
- Node(Node parent, int id, int level) {
- this.cube = parent.cube;
- this.parent = parent;
- this.children = new Node[MAX_CHILDREN];
- this.id = id;
- this.level = level;
-
- // add to the cube
- ++cube.numNodes;
- if (level == cube.depth) {
- ++cube.numColors;
- }
-
- // add to the parent
- ++parent.numChildren;
- parent.children[id] = this;
-
- // figure out our midpoint
- int bi = (1 << (MAX_TREE_DEPTH - level)) >> 1;
- midRed = parent.midRed + ((id & 1) > 0 ? bi : -bi);
- midGreen = parent.midGreen + ((id & 2) > 0 ? bi : -bi);
- midBlue = parent.midBlue + ((id & 4) > 0 ? bi : -bi);
- midAlpha = parent.midAlpha + ((id & 8) > 0 ? bi : -bi);
- }
-
- /**
- * Remove this children node, and make sure our parent absorbs our
- * pixel statistics.
- */
- void pruneChild() {
- --parent.numChildren;
- parent.unique += unique;
- parent.totalRed += totalRed;
- parent.totalGreen += totalGreen;
- parent.totalBlue += totalBlue;
- parent.totalAlpha += totalAlpha;
- parent.children[id] = null;
- --cube.numNodes;
- cube = null;
- parent = null;
- }
-
- /**
- * Prune the lowest layer of the tree.
- */
- void pruneLevel() {
- if (numChildren != 0) {
- for (int id = 0; id < MAX_CHILDREN; id++) {
- if (children[id] != null) {
- children[id].pruneLevel();
- }
- }
- }
- if (level == cube.depth) {
- pruneChild();
- }
- }
-
- /**
- * Remove any nodes that have fewer than threshold pixels. Also, as
- * long as we're walking the tree: - figure out the color with the
- * fewest pixels - recalculate the total number of colors in the
- * tree
- */
- int reduce(int threshold, int nextThreshold) {
- if (numChildren != 0) {
- for (int id = 0; id < MAX_CHILDREN; id++) {
- if (children[id] != null) {
- nextThreshold = children[id].reduce(threshold,
- nextThreshold);
- }
- }
- }
- if (numPixels <= threshold) {
- pruneChild();
- } else {
- if (unique != 0) {
- cube.numColors++;
- }
- if (numPixels < nextThreshold) {
- nextThreshold = numPixels;
- }
- }
- return nextThreshold;
- }
-
- /*
- * mapColors traverses the color cube tree and notes each colorMap
- * entry. A colorMap entry is any node in the color cube tree where
- * the number of unique colors is not zero.
- */
- void mapColors() {
- if (numChildren != 0) {
- for (int id = 0; id < MAX_CHILDREN; id++) {
- if (children[id] != null) {
- children[id].mapColors();
- }
- }
- }
- if (unique != 0) {
- int add = unique >> 1;
- cube.colorMap[0][cube.numColors] = (byte) ((totalRed + add) / unique);
- cube.colorMap[1][cube.numColors] = (byte) ((totalGreen + add) / unique);
- cube.colorMap[2][cube.numColors] = (byte) ((totalBlue + add) / unique);
- cube.colorMap[3][cube.numColors] = (byte) ((totalAlpha + add) / unique);
- colorIndex = cube.numColors++;
- }
- }
-
- /*
- * ClosestColor traverses the color cube tree at a particular node
- * and determines which colorMap entry best represents the input
- * color.
- */
- void closestColor(int red, int green, int blue, int alpha,
- Search search) {
- if (numChildren != 0) {
- for (int id = 0; id < MAX_CHILDREN; id++) {
- if (children[id] != null) {
- children[id].closestColor(red, green, blue, alpha,
- search);
- }
- }
- }
-
- if (unique != 0) {
- int distance = distance(
- cube.colorMap[0][colorIndex] & 0xff,
- cube.colorMap[1][colorIndex] & 0xff,
- cube.colorMap[2][colorIndex] & 0xff,
- cube.colorMap[3][colorIndex] & 0xff, red, green, blue,
- alpha);
- if (distance < search.distance) {
- search.distance = distance;
- search.colorIndex = colorIndex;
- }
- }
- }
-
- /**
- * Figure out the distance between this node and som color.
- */
- final static int distance(int r1, int g1, int b1, int a1, int r2,
- int g2, int b2, int a2) {
- int da = a1 - a2;
- int dr = r1 - r2;
- int dg = g1 - g2;
- int db = b1 - b2;
-
- return da * da + dr * dr + dg * dg + db * db;
-// return (SQUARES[r1 - r2 + MAX_RGB] +
-// SQUARES[g1 - g2 + MAX_RGB] +
-// SQUARES[b1 - b2 + MAX_RGB] +
-// SQUARES[a1 - a2 + MAX_RGB]);
- }
-
- public String toString() {
- StringBuffer buf = new StringBuffer();
- if (parent == this) {
- buf.append("root");
- } else {
- buf.append("node");
- }
- buf.append(' ');
- buf.append(level);
- buf.append(" [");
- buf.append(midRed);
- buf.append(',');
- buf.append(midGreen);
- buf.append(',');
- buf.append(midBlue);
- buf.append(',');
- buf.append(midAlpha);
- buf.append(']');
- return new String(buf);
- }
- }
- }
-}
\ No newline at end of file
Deleted: framework/trunk/impl/src/main/java/org/richfaces/model/ExtendedDataTableModifiableModel.java
===================================================================
--- branches/jsf2.0/framework/impl/src/main/java/org/richfaces/model/ExtendedDataTableModifiableModel.java 2009-07-07 12:45:54 UTC (rev 14807)
+++ framework/trunk/impl/src/main/java/org/richfaces/model/ExtendedDataTableModifiableModel.java 2009-07-08 00:01:28 UTC (rev 14825)
@@ -1,196 +0,0 @@
-/**
- *
- */
-package org.richfaces.model;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import javax.faces.context.FacesContext;
-import javax.faces.model.DataModelListener;
-
-import org.ajax4jsf.model.DataVisitor;
-import org.ajax4jsf.model.ExtendedDataModel;
-import org.ajax4jsf.model.Range;
-import org.ajax4jsf.model.SequenceRange;
-import org.ajax4jsf.model.SerializableDataModel;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.richfaces.model.FilterField;
-import org.richfaces.model.SortField2;
-import org.richfaces.model.impl.expressive.JavaBeanWrapper;
-import org.richfaces.model.impl.expressive.ObjectWrapperFactory;
-import org.richfaces.model.impl.expressive.WrappedBeanComparator2;
-import org.richfaces.model.impl.expressive.WrappedBeanFilter;
-
-/**
- * @author pawelgo
- *
- */
-public class ExtendedDataTableModifiableModel<T> extends ExtendedDataModel {
-
- private static final Log log = LogFactory.getLog(ExtendedDataTableModifiableModel.class);
-
- private ExtendedDataModel delegate;
-
- private ExtendedTableDataModel<T> originalModel;
-
- private ExtendedDataModel modifiedModel;
-
- private String var;
-
- private List<FilterField> filterFields;
- private List<SortField2> sortFields;
-
- /**
- * @param originalModel
- * @param var
- * @param filterFields
- * @param sortFields
- */
- public ExtendedDataTableModifiableModel(ExtendedTableDataModel<T> originalModel,
- String var, List<FilterField> filterFields,
- List<SortField2> sortFields) {
- this.originalModel = originalModel;
- this.delegate = originalModel;
- this.var = var;
- this.filterFields = filterFields;
- this.sortFields = sortFields;
- }
-
- public void addDataModelListener(DataModelListener listener) {
- originalModel.addDataModelListener(listener);
- }
-
- public DataModelListener[] getDataModelListeners() {
- return originalModel.getDataModelListeners();
- }
-
- public int getRowCount() {
- return delegate.getRowCount();
- }
-
- public Object getRowData() {
- return delegate.getRowData();
- }
-
- public int getRowIndex() {
- return delegate.getRowIndex();
- }
-
- public Object getRowKey() {
- return delegate.getRowKey();
- }
-
- public SerializableDataModel getSerializableModel(Range range) {
- return delegate.getSerializableModel(range);
- }
-
- public Object getWrappedData() {
- return delegate.getWrappedData();
- }
-
- public boolean isRowAvailable() {
- return delegate.isRowAvailable();
- }
-
- public void removeDataModelListener(DataModelListener listener) {
- delegate.removeDataModelListener(listener);
- }
-
- public void setRowIndex(int rowIndex) {
- delegate.setRowIndex(rowIndex);
- }
-
- public void setRowKey(Object key) {
- delegate.setRowKey(key);
- }
-
- public void setWrappedData(Object data) {
- delegate.setWrappedData(data);
- }
-
- @SuppressWarnings("unchecked")
- public void walk(FacesContext context, DataVisitor visitor, Range range,
- Object argument) throws IOException {
-
- if (shouldSort() || shouldFilter()) {
- if (modifiedModel == null) {
- modifiedModel = new ExtendedTableDataModelWrapper<T>(originalModel.getDataProvider(), (List<T>) prepareCollection());
- }
- delegate = modifiedModel;
- } else {
- delegate = originalModel;
- }
-
- delegate.walk(context, visitor, range, argument);
- }
-
- private boolean shouldSort() {
- return sortFields != null && !sortFields.isEmpty();
- }
-
- private boolean shouldFilter() {
- return filterFields != null && !filterFields.isEmpty();
- }
-
- private List<?> prepareCollection() {
- int rowCount = originalModel.getRowCount();
- final List<Object> collection;
-
- if (rowCount > 0) {
- collection = new ArrayList<Object>(rowCount);
- } else {
- collection = new ArrayList<Object>();
- }
-
- FacesContext context = FacesContext.getCurrentInstance();
- try {
-
- originalModel.walk(context, new DataVisitor() {
- public void process(FacesContext context, Object rowKey,
- Object argument) throws IOException {
- originalModel.setRowKey(rowKey);
- if (originalModel.isRowAvailable()) {
- collection.add(originalModel.getRowData());
- }
- }
- }, new SequenceRange(0, -1),
- null);
- } catch (IOException e) {
- log.error(e.getMessage(), e);
- }
-
- List<Object> modifedcollection = collection;
-
- if (shouldFilter()) {
- List <Object> filteredCollection = new ArrayList<Object>();
- ObjectWrapperFactory wrapperFactory = new ObjectWrapperFactory(
- context, var, filterFields);
- WrappedBeanFilter wrappedBeanFilter = new WrappedBeanFilter(filterFields);
- wrapperFactory.wrapList(modifedcollection);
- for (Object object : modifedcollection) {
- if(wrappedBeanFilter.accept((JavaBeanWrapper)object)) {
- filteredCollection.add(object);
- }
- }
- modifedcollection = filteredCollection;
- wrapperFactory.unwrapList(modifedcollection);
- }
-
- if (shouldSort()) {
- ObjectWrapperFactory wrapperFactory = new ObjectWrapperFactory(
- context, var, sortFields);
- WrappedBeanComparator2 wrappedBeanComparator = new WrappedBeanComparator2(
- sortFields);
- wrapperFactory.wrapList(modifedcollection);
- Collections.sort(modifedcollection, wrappedBeanComparator);
- wrapperFactory.unwrapList(modifedcollection);
- }
- return modifedcollection;
-
- }
-
-}
Deleted: framework/trunk/impl/src/main/java/org/richfaces/model/ExtendedTableDataModelWrapper.java
===================================================================
--- branches/jsf2.0/framework/impl/src/main/java/org/richfaces/model/ExtendedTableDataModelWrapper.java 2009-07-07 12:45:54 UTC (rev 14807)
+++ framework/trunk/impl/src/main/java/org/richfaces/model/ExtendedTableDataModelWrapper.java 2009-07-08 00:01:28 UTC (rev 14825)
@@ -1,40 +0,0 @@
-/**
- *
- */
-package org.richfaces.model;
-
-import java.util.List;
-
-/**
- * @author pawelgo
- *
- */
-public class ExtendedTableDataModelWrapper<T> extends ExtendedTableDataModel<T> {
-
- private static final long serialVersionUID = 6932958007982793632L;
-
- protected List<T> wrappedList;
-
- /**
- *
- * @param dataProvider
- * @param wrappedList
- */
- public ExtendedTableDataModelWrapper(DataProvider<T> dataProvider, List<T> wrappedList) {
- super(dataProvider);
- this.wrappedList = wrappedList;
- }
-
- protected List<T> loadData(int startRow, int endRow) {
- //return super.loadData(startRow, endRow);
- return wrappedList.subList(startRow, endRow);
- }
-
- public int getRowCount() {
- return wrappedList.size();
- }
-
-
-
-
-}
Modified: framework/trunk/pom.xml
===================================================================
--- framework/trunk/pom.xml 2009-07-07 23:36:18 UTC (rev 14824)
+++ framework/trunk/pom.xml 2009-07-08 00:01:28 UTC (rev 14825)
@@ -74,8 +74,8 @@
<modules>
<module>version-matrix</module>
<module>api</module>
+ <module>impl</module>
<module>test-base</module>
- <module>impl</module>
</modules>
</project>
\ No newline at end of file
Modified: framework/trunk/test-base/pom.xml
===================================================================
--- framework/trunk/test-base/pom.xml 2009-07-07 23:36:18 UTC (rev 14824)
+++ framework/trunk/test-base/pom.xml 2009-07-08 00:01:28 UTC (rev 14825)
@@ -22,6 +22,100 @@
<artifactId>jsf-impl</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.htmlunit</groupId>
+ <artifactId>htmlunit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-httpclient</groupId>
+ <artifactId>commons-httpclient</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.htmlunit</groupId>
+ <artifactId>htmlunit-core-js</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.cssparser</groupId>
+ <artifactId>cssparser</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>net.sourceforge.nekohtml</groupId>
+ <artifactId>nekohtml</artifactId>
+
+ <!-- TODO: move exclusions to VM? -->
+ <exclusions>
+ <exclusion>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ </exclusion>
+ <!--
+ <exclusion> <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId> </exclusion>
+ -->
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>javax.el</groupId>
+ <artifactId>el-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.el</groupId>
+ <artifactId>el-ri</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet.jsp</groupId>
+ <artifactId>jsp-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>jstl</groupId>
+ <artifactId>jstl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>jsr250-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>xalan</groupId>
+ <artifactId>xalan</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>de.berlios.jsunit</groupId>
+ <artifactId>jsunit</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>rhino</groupId>
+ <artifactId>js</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
</dependencies>
</project>
\ No newline at end of file
Copied: framework/trunk/test-base/src (from rev 14798, branches/jsf2.0/framework/jsf-test/src)
Modified: framework/trunk/version-matrix/pom.xml
===================================================================
--- framework/trunk/version-matrix/pom.xml 2009-07-07 23:36:18 UTC (rev 14824)
+++ framework/trunk/version-matrix/pom.xml 2009-07-08 00:01:28 UTC (rev 14825)
@@ -80,9 +80,62 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
- <version>4.4</version>
+ <version>4.6</version>
</dependency>
<dependency>
+ <groupId>net.sourceforge.htmlunit</groupId>
+ <artifactId>htmlunit</artifactId>
+ <version>2.5</version>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.htmlunit</groupId>
+ <artifactId>htmlunit-core-js</artifactId>
+ <version>2.5</version>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.cssparser</groupId>
+ <artifactId>cssparser</artifactId>
+ <version>0.9.5</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>1.4</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.4</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-httpclient</groupId>
+ <artifactId>commons-httpclient</artifactId>
+ <version>3.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>net.sourceforge.nekohtml</groupId>
+ <artifactId>nekohtml</artifactId>
+ <version>1.9.12</version>
+ </dependency>
+ <dependency>
+ <groupId>xalan</groupId>
+ <artifactId>xalan</artifactId>
+ <version>2.7.1</version>
+ <exclusions>
+ <exclusion>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>de.berlios.jsunit</groupId>
+ <artifactId>jsunit</artifactId>
+ <version>1.3</version>
+ </dependency>
+
+ <dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.0.0-SNAPSHOT</version>
@@ -107,20 +160,99 @@
<version>2.1</version>
</dependency>
<dependency>
+ <groupId>jstl</groupId>
+ <artifactId>jstl</artifactId>
+ <version>1.2</version>
+ </dependency>
+ <dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
+ <version>1.2</version>
+ </dependency>
+ <!-- end -->
+ <dependency>
+ <groupId>javax.el</groupId>
+ <artifactId>el-ri</artifactId>
+ <version>1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>
+
+ <!-- TODO: remove commons dependencies -->
<dependency>
- <groupId>jstl</groupId>
- <artifactId>jstl</artifactId>
- <version>1.2</version>
+ <groupId>commons-digester</groupId>
+ <artifactId>commons-digester</artifactId>
+ <version>1.8.1</version>
</dependency>
- <!-- end -->
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ <version>3.2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-beanutils</groupId>
+ <artifactId>commons-beanutils</artifactId>
+ <version>1.7.0</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.1.1</version>
+ </dependency>
+ <!-- -->
+
+ <!-- TODO: legacy dependnecies -->
+ <dependency>
+ <groupId>opensymphony</groupId>
+ <artifactId>oscache</artifactId>
+ <version>2.3</version>
+ </dependency>
+ <!-- dependency>
+ <groupId>nekohtml</groupId>
+ <artifactId>nekohtml</artifactId>
+ <version>0.9.5</version>
+ </dependency -->
+ <!-- -->
+
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>2.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <version>2.4</version>
+ </dependency>
+
</dependencies>
</dependencyManagement>
<build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>javacc-maven-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ </plugin>
+
+ <!-- TODO: change to the current CDK version -->
+ <plugin>
+ <groupId>org.richfaces.cdk</groupId>
+ <artifactId>maven-javascript-plugin</artifactId>
+ <version>3.3.1.GA</version>
+ </plugin>
+ <!-- -->
+
+ </plugins>
+ </pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
15 years, 2 months
JBoss Rich Faces SVN: r14822 - in framework/trunk: api and 2 other directories.
by richfaces-svn-commits@lists.jboss.org
Author: nbelaevski
Date: 2009-07-07 19:33:41 -0400 (Tue, 07 Jul 2009)
New Revision: 14822
Modified:
framework/trunk/api/pom.xml
framework/trunk/pom.xml
framework/trunk/test-base/pom.xml
framework/trunk/version-matrix/pom.xml
Log:
framework's pom.xml updated:
- added dev.java.net Maven repo
- groupId change javax.faces -> com.sun.faces
- excess plugins removed
Modified: framework/trunk/api/pom.xml
===================================================================
--- framework/trunk/api/pom.xml 2009-07-07 23:22:12 UTC (rev 14821)
+++ framework/trunk/api/pom.xml 2009-07-07 23:33:41 UTC (rev 14822)
@@ -13,6 +13,6 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.richfaces.framework</groupId>
<artifactId>richfaces-api</artifactId>
- <name>JSF ajax framework API</name>
-
+ <name>Java Server Faces AJAX framework API</name>
+
</project>
\ No newline at end of file
Modified: framework/trunk/pom.xml
===================================================================
--- framework/trunk/pom.xml 2009-07-07 23:22:12 UTC (rev 14821)
+++ framework/trunk/pom.xml 2009-07-07 23:33:41 UTC (rev 14822)
@@ -5,74 +5,74 @@
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
- <groupId>org.richfaces</groupId>
+ <groupId>org.richfaces</groupId>
<artifactId>framework-version-matrix</artifactId>
<version>4.0.0-SNAPSHOT</version>
- <relativePath>version-matrix/pom.xml</relativePath>
+ <relativePath>version-matrix/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.richfaces</groupId>
<artifactId>framework</artifactId>
- <name>JSF ajax framework</name>
+ <name>JSF ajax framework</name>
<packaging>pom</packaging>
-
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.richfaces.framework</groupId>
- <artifactId>richfaces-api</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.richfaces.framework</groupId>
- <artifactId>richfaces-impl</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.richfaces.framework</groupId>
- <artifactId>richfaces-test-base</artifactId>
- <version>${project.version}</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.richfaces.framework</groupId>
+ <artifactId>richfaces-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.richfaces.framework</groupId>
+ <artifactId>richfaces-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.richfaces.framework</groupId>
+ <artifactId>richfaces-test-base</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
- <scope>test</scope>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
- <scope>provided</scope>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
- <scope>provided</scope>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
- <scope>provided</scope>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
- <scope>provided</scope>
+ <scope>provided</scope>
</dependency>
<dependency>
- <groupId>javax.faces</groupId>
+ <groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
- <scope>provided</scope>
- </dependency>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
<modules>
- <module>version-matrix</module>
+ <module>version-matrix</module>
<module>api</module>
<module>test-base</module>
<module>impl</module>
Modified: framework/trunk/test-base/pom.xml
===================================================================
--- framework/trunk/test-base/pom.xml 2009-07-07 23:22:12 UTC (rev 14821)
+++ framework/trunk/test-base/pom.xml 2009-07-07 23:33:41 UTC (rev 14822)
@@ -9,18 +9,18 @@
<artifactId>framework</artifactId>
<version>4.0.0-SNAPSHOT</version>
</parent>
-
+
<modelVersion>4.0.0</modelVersion>
<groupId>org.richfaces.framework</groupId>
<artifactId>richfaces-test-base</artifactId>
<packaging>jar</packaging>
- <name>ajax4jsf test framework</name>
+ <name>ajax4jsf test framework</name>
<dependencies>
<dependency>
- <groupId>javax.faces</groupId>
+ <groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
- <scope>provided</scope>
+ <scope>provided</scope>
</dependency>
</dependencies>
Modified: framework/trunk/version-matrix/pom.xml
===================================================================
--- framework/trunk/version-matrix/pom.xml 2009-07-07 23:22:12 UTC (rev 14821)
+++ framework/trunk/version-matrix/pom.xml 2009-07-07 23:33:41 UTC (rev 14822)
@@ -1,181 +1,161 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <scm>
- <developerConnection>scm:svn:https://svn.jboss.org/repos/richfaces/</developerConnection>
- <connection>scm:svn:http://anonsvn.jboss.org/repos/richfaces/</connection>
- <url>http://fisheye.jboss.org/browse/RichFaces</url>
- </scm>
+ <scm>
+ <developerConnection>scm:svn:https://svn.jboss.org/repos/richfaces/framework</developerConnection>
+ <connection>scm:svn:http://anonsvn.jboss.org/repos/richfaces/framework</connection>
+ <url>http://fisheye.jboss.org/browse/RichFaces</url>
+ </scm>
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.richfaces</groupId>
- <artifactId>framework-version-matrix</artifactId>
- <version>4.0.0-SNAPSHOT</version>
- <packaging>pom</packaging>
- <name>JSF ajax framework version matrix</name>
+ <modelVersion>4.0.0</modelVersion>
+ <!-- TODO: org.richfaces.framework/version-matrix? -->
+ <groupId>org.richfaces</groupId>
+ <artifactId>framework-version-matrix</artifactId>
+ <version>4.0.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>JSF ajax framework version matrix</name>
- <repositories>
- <repository>
- <id>repository.jboss.org</id>
- <releases>
- <enabled>true</enabled>
- </releases>
- <snapshots>
- <enabled>false</enabled>
- </snapshots>
- <url>http://repository.jboss.org/maven2</url>
- </repository>
- <repository>
- <id>snapshots.jboss.org</id>
- <releases>
- <enabled>false</enabled>
- </releases>
- <snapshots>
- <enabled>true</enabled>
- <updatePolicy>never</updatePolicy>
- </snapshots>
- <url>http://snapshots.jboss.org/maven2</url>
- </repository>
- </repositories>
+ <repositories>
+ <repository>
+ <releases />
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ <id>maven-repository2.dev.java.net</id>
+ <name>Java.net Repository for Maven 2</name>
+ <url>http://download.java.net/maven/2</url>
+ </repository>
+
+ <repository>
+ <id>repository.jboss.org</id>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ <url>http://repository.jboss.org/maven2</url>
+ </repository>
+ <repository>
+ <id>snapshots.jboss.org</id>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ <updatePolicy>never</updatePolicy>
+ </snapshots>
+ <url>http://snapshots.jboss.org/maven2</url>
+ </repository>
+ </repositories>
- <pluginRepositories>
- <pluginRepository>
- <id>repository.jboss.org</id>
- <releases>
- <enabled>true</enabled>
- </releases>
- <snapshots>
- <enabled>false</enabled>
- </snapshots>
- <url>http://repository.jboss.org/maven2</url>
- </pluginRepository>
- <pluginRepository>
- <id>snapshots.jboss.org</id>
- <releases>
- <enabled>false</enabled>
- </releases>
- <snapshots>
- <enabled>true</enabled>
- <updatePolicy>never</updatePolicy>
- </snapshots>
- <url>http://snapshots.jboss.org/maven2</url>
- </pluginRepository>
- </pluginRepositories>
+ <pluginRepositories>
+ <pluginRepository>
+ <id>repository.jboss.org</id>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ <url>http://repository.jboss.org/maven2</url>
+ </pluginRepository>
+ <pluginRepository>
+ <id>snapshots.jboss.org</id>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ <updatePolicy>never</updatePolicy>
+ </snapshots>
+ <url>http://snapshots.jboss.org/maven2</url>
+ </pluginRepository>
+ </pluginRepositories>
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.4</version>
- </dependency>
- <dependency>
- <groupId>javax.faces</groupId>
- <artifactId>jsf-api</artifactId>
- <version>2.0.0-PR2_3</version>
- </dependency>
- <dependency>
- <groupId>javax.faces</groupId>
- <artifactId>jsf-impl</artifactId>
- <version>2.0.0-PR2_3</version>
- </dependency>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.faces</groupId>
+ <artifactId>jsf-api</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.faces</groupId>
+ <artifactId>jsf-impl</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </dependency>
- <!-- Dependencies of JSF 2.0 -->
- <!-- Included because of http://jira.codehaus.org/browse/MNG-2205 -->
- <!-- start -->
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>servlet-api</artifactId>
- <version>2.5</version>
- </dependency>
- <dependency>
- <groupId>javax.servlet.jsp</groupId>
- <artifactId>jsp-api</artifactId>
- <version>2.1</version>
- </dependency>
- <dependency>
- <groupId>javax.el</groupId>
- <artifactId>el-api</artifactId>
- <version>1.0</version>
- </dependency>
- <dependency>
- <groupId>jstl</groupId>
- <artifactId>jstl</artifactId>
- <version>1.2</version>
- </dependency>
- <!-- end -->
-
- <!-- Archetypes dependency -->
- <!-- start -->
- <dependency>
- <groupId>org.apache.maven.archetype</groupId>
- <artifactId>archetype-packaging</artifactId>
- <version>2.0-alpha-4</version>
- </dependency>
- <!-- end -->
- </dependencies>
- </dependencyManagement>
+ <!-- Dependencies of JSF 2.0 -->
+ <!-- Included because of http://jira.codehaus.org/browse/MNG-2205 -->
+ <!-- start -->
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet.jsp</groupId>
+ <artifactId>jsp-api</artifactId>
+ <version>2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.el</groupId>
+ <artifactId>el-api</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>jstl</groupId>
+ <artifactId>jstl</artifactId>
+ <version>1.2</version>
+ </dependency>
+ <!-- end -->
+ </dependencies>
+ </dependencyManagement>
- <build>
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-dependency-plugin</artifactId>
- <version>2.1</version>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>xml-maven-plugin</artifactId>
- <version>1.0-beta-2</version>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-archetype-plugin</artifactId>
- <version>2.0-alpha-4</version>
- <extensions>true</extensions>
- </plugin>
- </plugins>
- </pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-enforcer-plugin</artifactId>
- <version>1.0-beta-1</version>
- <executions>
- <execution>
- <id>enforce-versions</id>
- <goals>
- <goal>enforce</goal>
- </goals>
- <configuration>
- <rules>
- <requireMavenVersion>
- <version>2.1.0</version>
- </requireMavenVersion>
- </rules>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <artifactId>maven-eclipse-plugin</artifactId>
- <configuration>
- <wtpversion>2.0</wtpversion>
- <downloadSources>true</downloadSources>
- </configuration>
- </plugin>
- <plugin>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>1.5</source>
- <target>1.5</target>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
-
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <version>1.0-beta-1</version>
+ <executions>
+ <execution>
+ <id>enforce-versions</id>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ <configuration>
+ <rules>
+ <requireMavenVersion>
+ <version>2.1.0</version>
+ </requireMavenVersion>
+ </rules>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-eclipse-plugin</artifactId>
+ <configuration>
+ <wtpversion>2.0</wtpversion>
+ <downloadSources>true</downloadSources>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
\ No newline at end of file
15 years, 2 months
JBoss Rich Faces SVN: r14821 - branches/jsf2.0/framework/jsf-test.
by richfaces-svn-commits@lists.jboss.org
Author: nbelaevski
Date: 2009-07-07 19:22:12 -0400 (Tue, 07 Jul 2009)
New Revision: 14821
Modified:
branches/jsf2.0/framework/jsf-test/pom.xml
Log:
Reintegrated community/3.3.x into JSF 2.0 branch
Modified: branches/jsf2.0/framework/jsf-test/pom.xml
===================================================================
--- branches/jsf2.0/framework/jsf-test/pom.xml 2009-07-07 23:21:53 UTC (rev 14820)
+++ branches/jsf2.0/framework/jsf-test/pom.xml 2009-07-07 23:22:12 UTC (rev 14821)
@@ -5,12 +5,12 @@
<groupId>org.richfaces</groupId>
<version>4.0.0-SNAPSHOT</version>
</parent>
+
<modelVersion>4.0.0</modelVersion>
<groupId>org.richfaces.framework</groupId>
<artifactId>jsf-test</artifactId>
<name>jsf-test</name>
- <version>4.0.0-SNAPSHOT</version>
- <url>http://maven.apache.org</url>
+
<dependencies>
<dependency>
<groupId>junit</groupId>
15 years, 2 months
JBoss Rich Faces SVN: r14820 - branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource.
by richfaces-svn-commits@lists.jboss.org
Author: nbelaevski
Date: 2009-07-07 19:21:53 -0400 (Tue, 07 Jul 2009)
New Revision: 14820
Added:
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/CachedResourceImpl.java
Modified:
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceImpl.java
Log:
Reintegrated community/3.3.x into JSF 2.0 branch
Added: branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/CachedResourceImpl.java
===================================================================
--- branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/CachedResourceImpl.java (rev 0)
+++ branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/CachedResourceImpl.java 2009-07-07 23:21:53 UTC (rev 14820)
@@ -0,0 +1,124 @@
+/**
+ *
+ */
+package org.richfaces.resource;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.faces.application.Resource;
+import javax.faces.context.FacesContext;
+
+import org.richfaces.util.Util;
+
+/**
+ * @author Nick Belaevski
+ * @since 4.0
+ */
+public class CachedResourceImpl extends ResourceImpl {
+
+ private Map<String, String> headers;
+
+ private byte[] content;
+
+ private String entityTag;
+
+ private Date lastModified;
+
+ private void initializeFromHeaders() {
+ this.entityTag = null;
+ this.lastModified = null;
+
+ for (Entry<String, String> headerEntry: headers.entrySet()) {
+ String headerKey = headerEntry.getKey().toLowerCase(Locale.US);
+ if ("etag".equals(headerKey)) {
+ this.entityTag = headerEntry.getValue();
+ } else if ("last-modified".equals(headerKey)) {
+ this.lastModified = Util.parseHttpDate(headerEntry.getValue());
+ }
+ }
+
+ }
+
+ private byte[] readContent(InputStream is) throws IOException {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ try {
+ Util.copyStreamContent(is, os);
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ os.close();
+ }
+
+ return os.toByteArray();
+ }
+
+ public void initialize(Resource resource) {
+ setResourceName(resource.getResourceName());
+ this.headers = resource.getResponseHeaders();
+
+ initializeFromHeaders();
+ try {
+ this.content = readContent(resource.getInputStream());
+ } catch (IOException e) {
+ e.printStackTrace();
+ // TODO: handle exception
+ }
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ return new ByteArrayInputStream(content);
+ }
+
+ @Override
+ public String getRequestPath() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Map<String, String> getResponseHeaders() {
+ return new HashMap<String, String>(headers);
+ }
+
+ @Override
+ public URL getURL() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getContentType(FacesContext context) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isCacheable(FacesContext context) {
+ return true;
+ }
+
+ @Override
+ protected String getEntityTag(FacesContext context) {
+ return entityTag;
+ }
+
+ @Override
+ protected Date getLastModified(FacesContext context) {
+ return lastModified;
+ }
+
+}
Modified: branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceImpl.java
===================================================================
--- branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceImpl.java 2009-07-07 19:35:55 UTC (rev 14819)
+++ branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceImpl.java 2009-07-07 23:21:53 UTC (rev 14820)
@@ -127,7 +127,7 @@
*/
public abstract String getContentType(FacesContext context);
- public String getEntityTag(FacesContext context) {
+ protected String getEntityTag(FacesContext context) {
int contentLength = getContentLength(context);
Date lastModified = getLastModified(context);
@@ -280,24 +280,15 @@
private static final Pattern ETAG_PATTERN = Pattern.compile("(?:W/)?\"([^\"]+)\"(?:,\\s*)?");
- private boolean userCopyIsStale(FacesContext context) {
- Date serverLastModified = getLastModified(context);
- if (serverLastModified == null) {
+ private boolean userCopyIsStale(Date lastModified, Date modifiedCondition) {
+ if (lastModified == null || modifiedCondition == null) {
return true;
}
- String headerValue = context.getExternalContext().getRequestHeaderMap().get("If-Modified-Since");
- Date clientLastModified = Util.parseHttpDate(headerValue);
- if (clientLastModified == null) {
- return true;
- }
-
// 1000 ms due to round
// modification
// time to seconds.
- long serverLastModifiedTime = serverLastModified.getTime() - 1000;
-
- return serverLastModifiedTime > clientLastModified.getTime();
+ return (lastModified.getTime() - modifiedCondition.getTime()) > 1000;
}
@Override
@@ -309,21 +300,30 @@
ExternalContext externalContext = context.getExternalContext();
Map<String, String> requestHeaderMap = externalContext.getRequestHeaderMap();
- String ifNoneMatch = requestHeaderMap.get("If-None-Match");
- if (ifNoneMatch != null) {
- Matcher eTagMatcher = ETAG_PATTERN.matcher(ifNoneMatch);
+ String matchCondition = requestHeaderMap.get("If-None-Match");
+ String modifiedCondition = requestHeaderMap.get("If-Modified-Since");
+
+ String resourceEntityTag = getEntityTag(context);
+
+ if (matchCondition != null) {
+ Matcher eTagMatcher = ETAG_PATTERN.matcher(matchCondition);
while (eTagMatcher.find()) {
- String eTag = eTagMatcher.group(1);
+ String conditionEntityTag = eTagMatcher.group(1);
- if (eTag.equals(getEntityTag(context))) {
- return userCopyIsStale(context);
+ if (conditionEntityTag.equals(resourceEntityTag)) {
+ if (modifiedCondition == null) {
+ return false;
+ } else {
+ return userCopyIsStale(getLastModified(context),
+ Util.parseHttpDate(modifiedCondition));
+ }
}
}
return true;
}
- return userCopyIsStale(context);
+ return userCopyIsStale(getLastModified(context), Util.parseHttpDate(modifiedCondition));
}
}
15 years, 2 months
JBoss Rich Faces SVN: r14819 - branches/community/3.3.X/docs/userguide/en/src/main/docbook/included.
by richfaces-svn-commits@lists.jboss.org
Author: artdaw
Date: 2009-07-07 15:35:55 -0400 (Tue, 07 Jul 2009)
New Revision: 14819
Modified:
branches/community/3.3.X/docs/userguide/en/src/main/docbook/included/support.xml
Log:
https://jira.jboss.org/jira/browse/RF-7340 - <a4j:support> was reviewed
Modified: branches/community/3.3.X/docs/userguide/en/src/main/docbook/included/support.xml
===================================================================
--- branches/community/3.3.X/docs/userguide/en/src/main/docbook/included/support.xml 2009-07-07 19:13:33 UTC (rev 14818)
+++ branches/community/3.3.X/docs/userguide/en/src/main/docbook/included/support.xml 2009-07-07 19:35:55 UTC (rev 14819)
@@ -194,8 +194,12 @@
<property>"oncomplete"</property>
</emphasis>
attributes the <emphasis role="bold"><property><a4j:support></property></emphasis> component
- allows to use JavaScript calls before an Ajax request
- and after an Ajax response respectively.
+ allows to use JavaScript calls before and after an Ajax request
+ respectively.
+ Actuallly the JavaScript specified in the <emphasis><property>"oncomplete"</property></emphasis> attribute
+ will be executed in any case whether the Ajax request is completed successfully or not.
+ </para>
+ <para>
You can easily add confirmation dialog for the planet select box and colorize
<emphasis role="bold"><property><h:dataTable></property></emphasis> after the Ajax response:
</para>
15 years, 2 months
JBoss Rich Faces SVN: r14818 - in branches/community/3.3.X/docs/userguide/en/src/main: resources/images and 1 other directory.
by richfaces-svn-commits@lists.jboss.org
Author: artdaw
Date: 2009-07-07 15:13:33 -0400 (Tue, 07 Jul 2009)
New Revision: 14818
Added:
branches/community/3.3.X/docs/userguide/en/src/main/resources/images/supportSample.png
Modified:
branches/community/3.3.X/docs/userguide/en/src/main/docbook/included/support.desc.xml
branches/community/3.3.X/docs/userguide/en/src/main/docbook/included/support.xml
Log:
https://jira.jboss.org/jira/browse/RF-7340 - <a4j:support> was reviewed
Modified: branches/community/3.3.X/docs/userguide/en/src/main/docbook/included/support.desc.xml
===================================================================
--- branches/community/3.3.X/docs/userguide/en/src/main/docbook/included/support.desc.xml 2009-07-07 18:11:35 UTC (rev 14817)
+++ branches/community/3.3.X/docs/userguide/en/src/main/docbook/included/support.desc.xml 2009-07-07 19:13:33 UTC (rev 14818)
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='UTF-8'?>
-<root>
+<section>
<section>
<sectioninfo>
<keywordset>
@@ -9,8 +9,16 @@
</sectioninfo>
<title>Description</title>
- <para>The <emphasis role="bold"><property><a4j:support></property></emphasis> component enriches any existing JSF or RichFaces component with an Ajax capability by generating an asynchronous Ajax requests for them.
- The requests are invoked by definite user activity and used for updating and re-rendering page contents partially after a response from server.
+ <para>
+ The <emphasis role="bold"><property><a4j:support></property></emphasis> component
+ is the most important core component in the RichFaces library.
+ It enriches any existing non-Ajax JSF or RichFaces component with an Ajax capability.
+ All the other RichFaces Ajax components are based on the same principles
+ <emphasis role="bold"><property><a4j:support></property></emphasis> has.
+ <!--
+ The requests are invoked by definite user activity and used for updating
+ and re-rendering page contents partially after a response from server.
+ -->
</para>
</section>
-</root>
\ No newline at end of file
+</section>
\ No newline at end of file
Modified: branches/community/3.3.X/docs/userguide/en/src/main/docbook/included/support.xml
===================================================================
--- branches/community/3.3.X/docs/userguide/en/src/main/docbook/included/support.xml 2009-07-07 18:11:35 UTC (rev 14817)
+++ branches/community/3.3.X/docs/userguide/en/src/main/docbook/included/support.xml 2009-07-07 19:13:33 UTC (rev 14818)
@@ -1,64 +1,75 @@
<?xml version='1.0' encoding='UTF-8'?>
-<chapter>
- <chapterinfo>
- <keywordset>
- <keyword>a4j:support</keyword>
- </keywordset>
- </chapterinfo>
- <table>
- <title>Component identification parameters</title>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Name</entry>
- <entry>Value</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>component-type</entry>
- <entry>org.ajax4jsf.Support</entry>
- </row>
- <row>
- <entry>component-family</entry>
- <entry>org.ajax4jsf.AjaxSupport</entry>
- </row>
- <row>
- <entry>component-class</entry>
- <entry>org.ajax4jsf.component.html.HtmlAjaxSupport</entry>
- </row>
- <row>
- <entry>renderer-type</entry>
- <entry>org.ajax4jsf.components.AjaxSupportRenderer</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <section>
- <title>Creating the Component with a Page Tag</title>
- <para>To create the simplest variant on a page nest the <emphasis role="bold"><property><a4j:support></property></emphasis> into a component that is needed an Ajax functionality.
- Specify an event that will trigger an Ajax request and the components to be rerendered after a response from server.</para>
- <para>
- <emphasis role="bold">Example:</emphasis>
- </para>
- <programlisting role="XML"><![CDATA[<h:inputText value="#{bean.text}">
+<section>
+ <sectioninfo>
+ <keywordset>
+ <keyword>a4j:support</keyword>
+ </keywordset>
+ </sectioninfo>
+ <table>
+ <title>Component identification parameters</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Value</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>component-type</entry>
+ <entry>org.ajax4jsf.Support</entry>
+ </row>
+ <row>
+ <entry>component-family</entry>
+ <entry>org.ajax4jsf.AjaxSupport</entry>
+ </row>
+ <row>
+ <entry>component-class</entry>
+ <entry>org.ajax4jsf.component.html.HtmlAjaxSupport</entry>
+ </row>
+ <row>
+ <entry>renderer-type</entry>
+ <entry>org.ajax4jsf.components.AjaxSupportRenderer</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <section>
+ <title>Creating the Component with a Page Tag</title>
+ <para>
+ To create the simplest variant on a page you should put
+ <emphasis role="bold">
+ <property><a4j:support></property>
+ </emphasis>
+ as a nested element into the component that you want to enhance with
+ Ajax functionality.
+ You should also specify an event that will trigger
+ an Ajax request.
+ </para>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+ <programlisting role="XML"><![CDATA[<h:inputText value="#{bean.text}">
<a4j:support event="onkeyup" reRender="repeater"/>
</h:inputText>
<h:outputText id="repeater" value="#{bean.text}"/>]]></programlisting>
+ </section>
- <para>On every key-up event occuring inside the input field the <emphasis role="bold"><property><a4j:support></property></emphasis> generates an Ajax request that submits the whole Form.
- The value for the <code>bean.text</code> will be updated in the model and the component with the <code>repeater</code> ID will be redrawn according to a new data after server responce.
- </para>
- </section>
-
- <section>
- <title>Creating the Component Dynamically Using Java</title>
- <para>In order to add the <emphasis role="bold"><property><a4j:support></property></emphasis> in Java code you should add it as <emphasis><property>facet</property></emphasis>, not children:</para>
- <para>
- <emphasis role="bold">Example:</emphasis>
- </para>
- <programlisting role="JAVA"><![CDATA[HtmlInputText inputText = new HtmlInputText();
+ <section>
+ <title>Creating the Component Dynamically Using Java</title>
+ <para>
+ In order to add the
+ <emphasis role="bold">
+ <property><a4j:support></property>
+ </emphasis>
+ in Java code you should add it as
+ <property>facet</property>
+ , not as a child:
+ </para>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+ <programlisting role="JAVA"><![CDATA[HtmlInputText inputText = new HtmlInputText();
...
HtmlAjaxSupport ajaxSupport = new HtmlAjaxSupport();
ajaxSupport.setActionExpression(FacesContext.getCurrentInstance().getApplication().getExpressionFactory().createMethodExpression(
@@ -67,151 +78,191 @@
ajaxSupport.setReRender("output");
inputText.getFacets().put("a4jsupport", ajaxSupport);
]]></programlisting>
- </section>
-
- <section>
- <title>Details of Usage</title>
- <para>
- The <emphasis role="bold"><property><a4j:support></property></emphasis> component created on a page as following
- </para>
-
- <programlisting role="XML"><![CDATA[<h:inputText value="#{bean.text}">
+ </section>
+
+ <section>
+ <title>Details of Usage</title>
+ <para>
+ The <emphasis role="bold">
+ <property><a4j:support></property>
+ </emphasis>
+ component has two key attributes:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ mandatory
+ <emphasis><property>"event"</property></emphasis> attribute that defines the JavaScript event
+ the Ajax support will be attached to
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis><property>"reRender"</property></emphasis> attribute that defines id(s)
+ of JSF component(s) that should be rerendered after an Ajax request
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ As mentioned above the <emphasis role="bold"><property><a4j:support></property></emphasis> component
+ adds Ajax capability to non-Ajax JSF components.
+ Let's create ajaxed <emphasis role="bold"><property><h:selectOneMenu></property></emphasis> called
+ "Planets and Their Moons".
+ </para>
+ <para>
+ We begin with the common behavior description. When a page is rendered you see only one select box with the list of planets.
+ When you select a planet the <emphasis role="bold"><property><h:dataTable></property></emphasis>
+ containig moons of the selected planet appears.
+ </para>
+ <para>
+ In other words we need <emphasis role="bold"><property><h:selectOneMenu></property></emphasis>
+ with the nested <emphasis role="bold"><property><a4j:support></property></emphasis> component that
+ is attached to the <property>onchange</property> event.
+ </para>
+ <para>
+ When an Ajax response comes back the <emphasis role="bold"><property><h:dataTable></property></emphasis>
+ is re-rendered on the server side and updated on the client.
+ </para>
+ <programlisting role="XML"><![CDATA[...
+<h:form id="planetsForm">
+ <h:outputLabel value="Select the planet:" for="planets" />
+ <h:selectOneMenu id="planets" value="#{planetsMoons.currentPlanet}" valueChangeListener="#{planetsMoons.planetChanged}">
+ <f:selectItems value="#{planetsMoons.planetsList}" />
+ <a4j:support event="onchange" reRender="moons" />
+ </h:selectOneMenu>
+ <h:dataTable id="moons" value="#{planetsMoons.moonsList}" var="item">
+ <h:column>
+ <h:outputText value="#{item}"/>
+ </h:column>
+ </h:dataTable>
+</h:form>
+...]]></programlisting>
+ <para>
+ Finally we need a backing bean:
+ </para>
+ <programlisting role="JAVA"><![CDATA[...
+public class PlanetsMoons {
+ private String currentPlanet="";
+ public List<SelectItem> planetsList = new ArrayList<SelectItem>();
+ public List<String> moonsList = new ArrayList<String>();
+ private static final String [] EARTH = {"The Moon"};
+ private static final String [] MARS = {"Deimos", "Phobos"};
+ private static final String [] JUPITER = {"Europa", "Gamymede", "Callisto"};
+
+ public PlanetsMoons() {
+ SelectItem item = new SelectItem("earth", "Earth");
+ planetsList.add(item);
+ item = new SelectItem("mars", "Mars");
+ planetsList.add(item);
+ item = new SelectItem("jupiter", "Jupiter");
+ planetsList.add(item);
+ }
+
+ public void planetChanged(ValueChangeEvent event){
+ moonsList.clear();
+ String[] currentItems;
+ if (((String)event.getNewValue()).equals("earth")) {
+ currentItems = EARTH;
+ }else if(((String)event.getNewValue()).equals("mars")){
+ currentItems = MARS;
+ }else{
+ currentItems = JUPITER;
+ }
+ for (int i = 0; i < currentItems.length; i++) {
+ moonsList.add(currentItems[i]);
+ }
+ }
+
+ //Getters and Setters
+ ...
+}
+]]></programlisting>
+ <para>
+ There are two properties <code>planetsList</code> and <code>moonsList</code>.
+ The <code>planetsList</code> is filled with planets names in the constructor.
+ After you select the planet,
+ the <code>planetChanged()</code> listener is called and
+ the <code>moonsList</code> is populated with proper values of moons.
+ </para>
+ <para>
+ With the help of
+ <emphasis>
+ <property>"onsubmit"</property>
+ </emphasis>
+ and
+ <emphasis>
+ <property>"oncomplete"</property>
+ </emphasis>
+ attributes the <emphasis role="bold"><property><a4j:support></property></emphasis> component
+ allows to use JavaScript calls before an Ajax request
+ and after an Ajax response respectively.
+ You can easily add confirmation dialog for the planet select box and colorize
+ <emphasis role="bold"><property><h:dataTable></property></emphasis> after the Ajax response:
+ </para>
+ <programlisting role="XML"><![CDATA[...
+<h:form id="planetsForm">
+ <h:outputLabel value="Select the planet:" for="planets" />
+ <h:selectOneMenu id="planets" value="#{planetsMoons.currentPlanet}" valueChangeListener="#{planetsMoons.planetChanged}">
+ <f:selectItems value="#{planetsMoons.planetsList}" />
+ <a4j:support event="onchange" reRender="moons"
+ onsubmit="if(!confirm('Are you sure to change the planet?')) {form.reset(); return false;}"
+ oncomplete="document.getElementById('planetsForm:moonsPanel').style.backgroundColor='#c8dcf9';" />
+ </h:selectOneMenu>
+ <h:dataTable id="moons" value="#{planetsMoons.moonsList}" var="item">
+ <h:column>
+ <h:outputText value="#{item}"/>
+ </h:column>
+ </h:dataTable>
+</h:form>
+...]]></programlisting>
+ <para>
+ There is the result:
+ </para>
+ <figure>
+ <title>
+ "Planets and Their Moons"
+ </title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/supportSample.png"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ Information about the
+ <emphasis>
+ <property>"process"</property>
+ </emphasis>
+ attribute usage you can find in the "
+ <link linkend="process">Decide what to process</link>
+ " guide section.
+ </para>
+
+ <note>
+ <title>Tip:</title>
+ <para>
+ The
+ <emphasis role="bold">
+ <property><a4j:support></property>
+ </emphasis>
+ component created on a page as following
+ </para>
+ <programlisting role="XML"><![CDATA[<h:inputText value="#{bean.text}">
<a4j:support event="onkeyup" reRender="output" action="#{bean.action}"/>
</h:inputText>]]></programlisting>
-
- <para>is decoded in HTML as</para>
-
- <programlisting role="XML"><![CDATA[<input onkeyup="A4J.AJAX.Submit( Some request parameters )"/>]]></programlisting>
-
- <para>The <emphasis><property>"onkeyup"</property></emphasis> event calls an utility RichFaces method that submits Form by creating special marks for the RichFaces filter informing that it is an Ajax request.
- Any quantity of supports that define component behavior could be added to a component.
- </para>
-
- <note>
- <para>A lot of RichFaces components comes with built-in Ajax support (read the Guide to find out what exactly) and have no need in the <emphasis role="bold"><property><a4j:support></property></emphasis>.
- </para>
- </note>
-
- <para>With the help of <emphasis><property>"onsubmit"</property></emphasis> and <emphasis><property>"oncomplete"</property></emphasis> attributes the component allows using JavaScript before
- (for request sending conditions checking) and after an Ajax response processing termination (for performance of user-defined activities on the client).
- </para>
-
- <para>
- <emphasis role="bold">Example:</emphasis></para><programlisting role="XML"><![CDATA[<h:selectOneMenu value="#{bean.text}">
- <f:selectItem itemValue="First Item" itemLabel="First Item"/>
- <f:selectItem itemValue=" Second Item" itemLabel="Second Item"/>
- <f:selectItem itemValue=" Third Item" itemLabel="Third Item"/>
- <a4j:support event="onblur" reRender="panel" onsubmit="if(!confirm('Are you sure to change the option ?')) {form.reset(); return false;}" oncomplete="alert('Value succesfully stored')"/>
-</h:selectOneMenu>]]></programlisting>
-
- <para>
- In example there is the condition checking (confirm) is used before request sending and message printing after the request processing is over.
- </para>
-
- <para>The component allows different Ajax request managing ways for its various optimization in particular conditions such as:
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">limitation of the submit area and updating area for the request</emphasis>
- </para>
- <para>
- <emphasis><property>"ajaxSingle"</property></emphasis> is an attribute that allows submission on the server only component sending a request as if the component presented on a separate form;
- </para>
-
- <para>
- <emphasis><property>"limitToList"</property></emphasis> is an attribute that allows to limit areas, which are updated after the responses;
- only these components defined in the <emphasis><property>"reRender"</property></emphasis>attribute are updated;
- </para>
- </listitem>
- </itemizedlist>
- </para>
-
- <para>
- <emphasis role="bold">Example 1:</emphasis>
- </para>
- <programlisting role="XML"><![CDATA[<h:form>
- <h:inputText value="#{person.name}">
- <a4j:support event="onkeyup" reRender="test" ajaxSingle="true"/>
- </h:inputText>
- <h:inputText value="#{person.middleName}"/>
-</form>]]></programlisting>
-
- <para>
- In this example the request contains only the input component causes the request generation and not all the components contained on a form (because <code>ajaxSingle="true"</code>).
- </para>
-
- <para>
- <emphasis role="bold">Example 2:</emphasis>
- </para>
- <programlisting role="XML"><![CDATA[<h:form>
- <a4j:outputPanel ajaxRendered="true">
- <h:messages/>
- </a4j:outputPanel>
- <h:inputText value="#{person.name}">
- <a4j:support event="onkeyup" reRender="test" limitToList="true"/>
- </h:inputText>
- <h:outputText value="#{person.name}" id="test"/>
-</form>]]></programlisting>
-
- <para>
- In this example the component <emphasis role="bold"><property><h:messages></property></emphasis> is always updated (as it capturing all Ajax requests,
- located in ajaxRendered <emphasis role="bold"><property><a4j:outputPanel></property></emphasis>), except the case when a response is sent from the input component from the example.
- On sending this component marks that updating area is limited to the defined in it components,
- it means that on its usage with <code>limitToList="true"</code> the only component updated is the one with <code>id="test"</code>.
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">limitation of requests frequency and updates quantity after the responses</emphasis>
- </para>
-
- <para>
- <emphasis><property>"requestDelay"</property></emphasis> is an attribute that defines a time interval in seconds minimally permissible between responses;
- </para>
-
- <para>
- <emphasis><property>"eventsQueue"</property></emphasis> is an attribute for naming of the queue where the next response is kept in till its processing,
- but if the next event comes in till this time is over, the waiting event is taken away, replacing with a new one;
- </para>
-
- <para>
- <emphasis><property>"ignoreDupResponces"</property></emphasis> is an attribute that allows to disable any updates on the client after an Ajax request if another Ajax request is already sent;
- </para>
-
- <para>
- <emphasis><property>"timeout"</property></emphasis> is an attribute that allows to set a time interval in millisecond to define a maximum time period of response wait time.
- In case of the interval interaction, a new request is sent and the previous one is canceled.
- Postprocessing of a response isn't performed.
- </para>
- <para>
- <emphasis role="bold">Example:</emphasis>
- </para>
- <programlisting role="XML"><![CDATA[<h:form>
- <h:inputText value="#{person.name}">
- <a4j:support event="onkeyup" reRender="test" requestDelay="1000" ignoreDupResponces="true" eventsQueue="myQueue"/>
- </h:inputText>
- <h:outputText value="#{person.name}" id="test"/>
-</form>]]></programlisting>
-
- <para>This example clearly shows mentioned above attributes.
- If quick typing in a text field happens, every next requests sending is delayed for a second and requests quantity is reduced.
- The requests are kept in the queue till its the sending.
- Moreover, if the next request is already sent, the rerendering after the previous request is banned, and it helps to avoid unnecessary processing on the client.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Information about the <emphasis><property>"process"</property></emphasis> attribute usage you can find in the "<link linkend="process">Decide what to process</link>" guide section.
- </para>
- </section>
-
- <section>
- <title>Relevant resources links</title>
- <para>
- Visit <ulink url="http://livedemo.exadel.com/richfaces-demo/richfaces/support.jsf?c=support"><a4j:support> demo page</ulink> at RichFaces live demo for examples of component usage and their sources.
- </para>
-
- </section>
-</chapter>
+ <para>is decoded in HTML as</para>
+ <programlisting role="XML"><![CDATA[<input onkeyup="A4J.AJAX.Submit( Some request parameters )"/>]]></programlisting>
+ </note>
+ </section>
+ <section>
+ <title>Relevant resources links</title>
+ <para>
+ Visit
+ <ulink
+ url="http://livedemo.exadel.com/richfaces-demo/richfaces/support.jsf?c=support"><a4j:support> demo page</ulink>
+ at RichFaces live demo for examples of component usage and their
+ sources.
+ </para>
+
+ </section>
+</section>
Added: branches/community/3.3.X/docs/userguide/en/src/main/resources/images/supportSample.png
===================================================================
(Binary files differ)
Property changes on: branches/community/3.3.X/docs/userguide/en/src/main/resources/images/supportSample.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
15 years, 2 months
JBoss Rich Faces SVN: r14817 - in branches/jsf2.0/framework/impl: src/main/javascript and 19 other directories.
by richfaces-svn-commits@lists.jboss.org
Author: nbelaevski
Date: 2009-07-07 14:11:35 -0400 (Tue, 07 Jul 2009)
New Revision: 14817
Added:
branches/jsf2.0/framework/impl/src/main/javascript/ajaxjsf/queue.js
branches/jsf2.0/framework/impl/src/main/javascript/jquery/jquery-1.3.1.js
branches/jsf2.0/framework/impl/src/main/javascript/jquery/jquery-1.3.2.js
branches/jsf2.0/framework/impl/src/main/javascript/prototype/prototype-1.6.0.3.js
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/io/parser/FastBufferOutputStreamTest.java
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/io/parser/FastBufferWriterTest.java
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/renderkit/
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/renderkit/RendererUtilsTest.java
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/resource/
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/resource/cached/
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/resource/cached/DualLRUMapTest.java
branches/jsf2.0/framework/impl/src/test/java/org/richfaces/json/
branches/jsf2.0/framework/impl/src/test/java/org/richfaces/json/SerializationTest.java
Removed:
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/renderkit/RendererUtilsTest.java
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/resource/cached/
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/resource/cached/DualLRUMapTest.java
branches/jsf2.0/framework/impl/src/test/java/org/richfaces/json/SerializationTest.java
Modified:
branches/jsf2.0/framework/impl/generatescript.xml
branches/jsf2.0/framework/impl/pom.xml
branches/jsf2.0/framework/impl/src/main/javascript/ajaxjsf/JSFAJAX.js
branches/jsf2.0/framework/impl/src/main/javascript/ajaxjsf/sarissa.js
branches/jsf2.0/framework/impl/src/main/javascript/jquery/jquery-1.2.6.js
branches/jsf2.0/framework/impl/src/main/javascript/jquery/patches.js
branches/jsf2.0/framework/impl/src/main/javascript/memory.js
branches/jsf2.0/framework/impl/src/main/javascript/prototype/patches.js
branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/builder.js
branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/controls.js
branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/dragdrop.js
branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/effects.js
branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/scriptaculous.js
branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/slider.js
branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/sound.js
branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/unittest.js
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/FacesConfigTest.java
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/MockServletContext.java
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/MockXmlReader.java
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/StateHandlerTest.java
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/WebXMLTest.java
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/WebappHandlerTest.java
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/event/EventsQueueTest.java
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/framework/ajax/xmlfilter/nekko/HtmlCorrectionFilterTestCase.java
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/io/parser/FastParserTest.java
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/javascript/JSMinTest.java
branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/util/LRUMapTest.java
branches/jsf2.0/framework/impl/src/test/java/org/richfaces/component/util/ComponentUtilTest.java
branches/jsf2.0/framework/impl/src/test/resources/WEB-INF/web.xml
Log:
Reintegrated community/3.3.x into JSF 2.0 branch
Modified: branches/jsf2.0/framework/impl/generatescript.xml
===================================================================
--- branches/jsf2.0/framework/impl/generatescript.xml 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/generatescript.xml 2009-07-07 18:11:35 UTC (rev 14817)
@@ -50,7 +50,7 @@
-->
<filelist id="jquery"
dir="${basedir}/src/main/javascript/jquery"
- files="jquery-1.2.6.js,noConflict.js,../memory.js,patches.js">
+ files="jquery-1.3.2.js,../memory.js,patches.js">
</filelist>
<filelist id="scriptaculous"
@@ -61,7 +61,7 @@
<filelist id="prototype"
dir="${basedir}/src/main/javascript/prototype"
- files="prototype-1.6.0.2.js,../memory.js,patches.js">
+ files="prototype-1.6.0.3.js,../memory.js,patches.js">
</filelist>
@@ -70,7 +70,7 @@
files="prolog.js,dnd.js,epilog.js">
</filelist>
- <filelist id="ajaxjsf" dir="${basedir}/src/main/javascript/ajaxjsf" files="prolog.js,sarissa.js,JSFAJAX.js,log4ajax.js,epilog.js,../memory.js"></filelist>
+ <filelist id="ajaxjsf" dir="${basedir}/src/main/javascript/ajaxjsf" files="prolog.js,sarissa.js,JSFAJAX.js,queue.js,log4ajax.js,epilog.js,../memory.js"></filelist>
<!-- =================================
target: assemble
================================= -->
Modified: branches/jsf2.0/framework/impl/pom.xml
===================================================================
--- branches/jsf2.0/framework/impl/pom.xml 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/pom.xml 2009-07-07 18:11:35 UTC (rev 14817)
@@ -5,11 +5,12 @@
<groupId>org.richfaces</groupId>
<version>4.0.0-SNAPSHOT</version>
</parent>
+
<modelVersion>4.0.0</modelVersion>
<groupId>org.richfaces.framework</groupId>
<artifactId>richfaces-impl</artifactId>
<name>Java Server Faces AJAX framework implementation</name>
- <version>4.0.0-SNAPSHOT</version>
+
<build>
<resources>
<resource>
@@ -74,6 +75,7 @@
<include>${project.build.directory}/compressed/org/ajax4jsf/javascript/scripts/AJAX-min.js</include>
<include>${project.build.directory}/compressed/org/richfaces/renderkit/html/scripts/scriptaculous/scriptaculous-min.js</include>
<include>${project.build.directory}/compressed/org/richfaces/renderkit/html/scripts/jquery/jquery-min.js</include>
+ <include>${project.build.directory}/compressed/org/richfaces/renderkit/html/scripts/jquery.utils-min.js</include>
<include>${project.build.directory}/compressed/org/ajax4jsf/javascript/scripts/dnd-min.js</include>
<include>**/*-min.js</include>
</includes>
@@ -149,7 +151,7 @@
<dependency>
<groupId>commons-digester</groupId>
<artifactId>commons-digester</artifactId>
- <version>1.8</version>
+ <version>1.8.1</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
Modified: branches/jsf2.0/framework/impl/src/main/javascript/ajaxjsf/JSFAJAX.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/ajaxjsf/JSFAJAX.js 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/main/javascript/ajaxjsf/JSFAJAX.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -10,11 +10,18 @@
A4J.AJAX = {};
+A4J.AJAX.VIEW_ROOT_ID = "_viewRoot";
+
+A4J.AJAX.Stub = function() {};
+
+A4J.AJAX.isWebKit = navigator.userAgent.search(/( AppleWebKit\/)([^ ]+)/) != -1;
+
/**
* XMLHttp transport class - incapsulate most of client-specifiv functions for call server requests.
*/
A4J.AJAX.XMLHttpRequest = function(query){
this._query = query;
+
// Store document element, to check page replacement.
this._documentElement = window.document.documentElement;
};
@@ -53,13 +60,29 @@
this._request.onreadystatechange = function(){
if(window.document.documentElement != _this._documentElement){
LOG.warn("Page for current request have been unloaded - abort processing" );
- _this.abort();
+
+ if(!_this._status_stopped) {
+ //end status early
+ A4J.AJAX.status(_this.containerId, _this.options.status, false);
+ _this._status_stopped = true;
+ }
+
+ _this.abort();
+
return;
};
- if(_this._aborted){return;};
+
LOG.debug("Reqest state : "+_this._request.readyState );
if (_this._request.readyState == 4 ) {
- LOG.debug("Reqest end with state 4");
+ if(_this._aborted){
+ //this will be true just once for request - no need to track state of status
+ A4J.AJAX.status(_this.containerId, _this.options.status, false);
+ A4J.AJAX.popQueue(_this);
+
+ return;
+ };
+
+ LOG.debug("Reqest end with state 4");
if(_this._timeoutID){
window.clearTimeout(_this._timeoutID);
}
@@ -122,14 +145,19 @@
if(this._timeout > 0){
this._timeoutID = window.setTimeout(function(){
LOG.warn("request stopped due to timeout");
+
if(!_this._aborted){
- A4J.AJAX.status(_this.containerId,_this.options.status,false);
+// A4J.AJAX.status(_this.containerId,_this.options.status,false);
if(typeof(A4J.AJAX.onAbort) == "function"){
A4J.AJAX.onAbort(_this);
}
}
_this._aborted=true;
+
+ //IE doesn't call onreadystatechange by abort() invocation as other browsers do, unify this
+ _this._request.onreadystatechange = A4J.AJAX.Stub;
_this._request.abort();
+
if(_this._onerror){
_this._errorMessage = "Request timeout";
_this._onerror(_this,500,_this._errorMessage);
@@ -144,24 +172,16 @@
},
abort: function(){
- if(!this._aborted){
- A4J.AJAX.status(this.containerId,this.options.status,false);
- if(typeof(A4J.AJAX.onAbort) == "function"){
- A4J.AJAX.onAbort(this);
- }
- }
- this._aborted=true;
- if(this._request){
- try{
-// this._request.abort();
- if(this._timeoutID){
- window.clearTimeout(this._timeoutID);
- }
- } catch (e){
- LOG.warn("Exception for abort current request "+e.Message);
+ this._oncomplete_aborted = true;
+
+ if(!this._aborted){
+ if(typeof(A4J.AJAX.onAbort) == "function"){
+ A4J.AJAX.onAbort(this);
}
}
+ this._aborted=true;
},
+
getResponseText : function(){
try {
return this._request.responseText;
@@ -288,7 +308,31 @@
}
return data;
},
+
+ _evaluateScript: function(node) {
+ var includeComments = !A4J.AJAX.isXhtmlScriptMode();
+ var newscript = A4J.AJAX.getText(node, includeComments) ; // TODO - Mozilla disable innerHTML in XML page ..."";
+
+ try {
+ LOG.debug("Evaluate script replaced area in document: ", newscript);
+ if (window.execScript) {
+ window.execScript( newscript );
+ } else {
+ window.eval(newscript);
+ }
+ LOG.debug("Script evaluation succeeded");
+ } catch(e){
+ LOG.error("ERROR Evaluate script: Error name: " + e.name + e.message?". Error message: "+e.message:"");
+ }
+ },
+ evaluateQueueScript: function() {
+ var queueScript = this.getElementById('org.ajax4jsf.queue_script');
+ if (queueScript) {
+ this._evaluateScript(queueScript);
+ }
+ },
+
evalScripts : function(node, isLast){
var newscripts = this.getElementsByTagName("script",node);
LOG.debug("Scripts in updated part count : " + newscripts.length);
@@ -296,26 +340,14 @@
var _this = this;
window.setTimeout(function() {
for (var i = 0; i < newscripts.length; i++){
- var includeComments = !A4J.AJAX.isXhtmlScriptMode();
- var newscript = A4J.AJAX.getText(newscripts[i], includeComments) ; // TODO - Mozilla disable innerHTML in XML page ..."";
-
- try {
- LOG.debug("Evaluate script replaced area in document: ", newscript);
- if (window.execScript) {
- window.execScript( newscript );
- } else {
- window.eval(newscript);
- }
- } catch(e){
- LOG.error("ERROR Evaluate script: Error name: " + e.name + e.message?". Error message: "+e.message:"");
- }
+ _this._evaluateScript(newscripts[i]);
}
newscripts = null;
if (isLast)
{
_this.doFinish();
- _this = undefined;
}
+ _this = undefined;
}, 0);
} else
{
@@ -345,27 +377,76 @@
// Remove unload prototype events for a removed elements.
if (window.RichFaces && window.RichFaces.Memory) {
- window.RichFaces.Memory.clean(oldnode);
+ window.RichFaces.Memory.clean(oldnode, true);
}
var anchor = oldnode.parentNode;
- if(!window.opera && oldnode.outerHTML && !oldnode.tagName.match( /(tbody|thead|tfoot|tr|th|td)/i ) ){
+ if(!window.opera && !A4J.AJAX.isWebkitBreakingAmps() && oldnode.outerHTML && !oldnode.tagName.match( /(tbody|thead|tfoot|tr|th|td)/i ) ){
LOG.debug("Replace content of node by outerHTML()");
- try {
- oldnode.innerHTML = "";
- } catch(e){
- LOG.error("Error to clear node content by innerHTML "+e.message);
- Sarissa.clearChildNodes(oldnode);
+ if (!Sarissa._SARISSA_IS_IE || oldnode.tagName.toLowerCase()!="table") {
+ try {
+ oldnode.innerHTML = "";
+ } catch(e){
+ LOG.error("Error to clear node content by innerHTML "+e.message);
+ Sarissa.clearChildNodes(oldnode);
+ }
}
oldnode.outerHTML = new XMLSerializer().serializeToString(newnode);
} else {
- var importednode ;
// need to check for firstChild due to opera 8 bug with hasChildNodes
Sarissa.clearChildNodes(oldnode);
- importednode = window.document.importNode(newnode, true);
+
+ if (A4J.AJAX.isWebKit) {
+ try {
+ newnode.normalize();
+ } catch (e) {
+ LOG.error("Node normalization failed " + e.message);
+ }
+ }
+
+ var importednode = window.document.importNode(newnode, true);
//importednode.innerHTML = importednode.innerHTML;
LOG.debug("Replace content of node by replaceChild()");
- anchor.replaceChild(importednode,oldnode);
+
+ var oldGetElementById = null;
+
+ A4J.AJAX.TestReplacedGetElementByIdVisibility();
+ if (!A4J.AJAX._testReplacedGetElementByIdVisibility) {
+ LOG.debug("Temporarily substituting document.getElementById() to work around WebKit issue");
+ oldGetElementById = document.getElementById;
+ document.getElementById = function(id) {
+ var elt = oldGetElementById.apply(document, arguments);
+ if (!elt) {
+ var id = arguments[0];
+
+ LOG.debug("Element [@id='" + id + "'] was not found in document, trying to locate XPath match");
+
+ try {
+ var result = importednode.ownerDocument.evaluate("//*[@id='" + id + "']",
+ importednode, null, XPathResult.ANY_UNORDERED_NODE_TYPE);
+
+ if (result) {
+ elt = result.singleNodeValue;
+ }
+
+ LOG.debug("XPath located: " + elt);
+ } catch (e) {
+ LOG.error("Error locating [@id='" + id + "'] element: " + e.message);
+ }
+ }
+
+ return elt;
+ };
+ }
+
+ try {
+ anchor.replaceChild(importednode,oldnode);
+ } finally {
+ if (oldGetElementById) {
+ LOG.debug("Restoring document.getElementById()");
+ document.getElementById = oldGetElementById;
+ }
+ }
}
// re-execute all script fragments in imported subtree...
@@ -544,8 +625,6 @@
}
};
-// eventsQueues for ajax submit events.
-A4J.AJAX._eventsQueues={};
//Listeners should be notified
A4J.AJAX.Listener = function(onafterajax){
@@ -582,13 +661,19 @@
A4J.AJAX._headTransformers.push(listener);
};
+A4J.AJAX.SetZeroRequestDelay = function(options) {
+ if (typeof options.requestDelay == "undefined") {
+ options.requestDelay = 0;
+ }
+};
+
// pollers timerId's
A4J.AJAX._pollers = {};
/*
*
*
*/
-A4J.AJAX.Poll = function( containerId, form, options ) {
+A4J.AJAX.Poll = function(form, options) {
A4J.AJAX.StopPoll(options.pollId);
if(!options.onerror){
options.onerror = function(req,status,message){
@@ -596,16 +681,25 @@
A4J.AJAX.onError(req,status,message);
}
// For error, re-submit request.
- A4J.AJAX.Poll(containerId,form,options);
+ A4J.AJAX.Poll(form,options);
};
}
+
+ if (!options.onqueuerequestdrop) {
+ options.onqueuerequestdrop = function() {
+ A4J.AJAX.Poll(form,options);
+ };
+ }
+
+ A4J.AJAX.SetZeroRequestDelay(options);
+
A4J.AJAX._pollers[options.pollId] = window.setTimeout(function(){
A4J.AJAX._pollers[options.pollId]=undefined;
if((typeof(options.onsubmit) == 'function') && (options.onsubmit()==false)){
// Onsubmit disable current poll, start next interval.
- A4J.AJAX.Poll(containerId,form,options);
+ A4J.AJAX.Poll(form,options);
} else {
- A4J.AJAX.SubmitRequest(containerId,form,null,options);
+ A4J.AJAX.Submit(form,null,options);
}
},options.pollinterval);
};
@@ -621,12 +715,17 @@
*
*
*/
-A4J.AJAX.Push = function( containerId, form, options ) {
+A4J.AJAX.Push = function(form, options) {
A4J.AJAX.StopPush(options.pushId);
options.onerror = function(){
// For error, re-submit request.
- A4J.AJAX.Push(containerId,form,options);
+ A4J.AJAX.Push(form, options);
};
+
+ options.onqueuerequestdrop = function() {
+ LOG.debug("Push main request dropped from queue");
+ };
+
A4J.AJAX._pollers[options.pushId] = window.setTimeout(function(){
var request = new XMLHttpRequest();
request.onreadystatechange = function(){
@@ -634,7 +733,8 @@
try {
if(request.status == 200){
if(request.getResponseHeader("Ajax-Push-Status")=="READY"){
- A4J.AJAX.SubmitRequest(containerId,form||options.dummyForm,null,options);
+ A4J.AJAX.SetZeroRequestDelay(options);
+ A4J.AJAX.Submit(form||options.dummyForm,null,options);
}
}
} catch(e){
@@ -644,10 +744,10 @@
request=null;
A4J.AJAX._pollers[options.pushId] = null;
// Re-send request.
- A4J.AJAX.Push( containerId, form, options );
+ A4J.AJAX.Push(form, options);
}
}
- A4J.AJAX.SendPush( request,options );
+ A4J.AJAX.SendPush(request, options);
},options.pushinterval);
};
@@ -682,7 +782,7 @@
}
-A4J.AJAX.SubmitForm = function( containerId, form, options ) {
+A4J.AJAX.SubmitForm = function(form, options) {
var opt = A4J.AJAX.CloneObject(options);
// Setup active control if form submitted by button.
if(A4J._formInput){
@@ -691,12 +791,17 @@
A4J._formInput = null;
opt.submitByForm=true;
}
- A4J.AJAX.Submit(containerId,form,null,opt);
+ A4J.AJAX.Submit(form,null,opt);
}
-// Submit or put in queue request. It not full queues - framework perform waiting only one request to same queue, new events simple replace last.
-// If request for same queue already performed, replace with current parameters.
-A4J.AJAX.Submit = function( containerId, form, evt , options ) {
+/**
+ * This method should be deprecated and maybe even removed?
+ */
+A4J.AJAX.SubmiteventsQueue = function( eventsQueue ) {
+ eventsQueue.submit();
+};
+
+A4J.AJAX.CloneEvent = function(evt) {
var domEvt;
evt = evt || window.event || null;
if(evt){
@@ -708,63 +813,11 @@
}
LOG.debug("Have Event "+domEvt+" with properties: target: "+domEvt.target+", srcElement: "+domEvt.srcElement+", type: "+domEvt.type);
}
- if(options.eventsQueue){
- var eventsQueue = A4J.AJAX._eventsQueues[options.eventsQueue];
- if( eventsQueue ) {
- var eventsCount = eventsQueue.options.eventsCount||1;
- eventsQueue.wait=true;
- eventsQueue.containerId=containerId;
- eventsQueue.form=form;
- eventsQueue.domEvt=domEvt;
- eventsQueue.options=options;
- eventsQueue.options.eventsCount = eventsCount+1;
- if(options.ignoreDupResponses && eventsQueue.request){
- LOG.debug("Abort uncompleted request in queue "+options.eventsQueue);
- eventsQueue.request.abort();
- eventsQueue.request=false;
- eventsQueue.wait=false;
- if( options.requestDelay ){
- window.setTimeout(function() {
- LOG.debug("End delay waiting, make request in queue "+options.eventsQueue);
- A4J.AJAX.SubmiteventsQueue(A4J.AJAX._eventsQueues[options.eventsQueue]);
- },options.requestDelay);
- LOG.debug("Create new waiting for request in queue "+options.eventsQueue);
- return;
- }
- } else {
- LOG.debug("Put new event to queue "+options.eventsQueue);
- return;
- }
- } else {
- var queue = { wait : false, containerId : containerId , form : form, domEvt : domEvt, options : options};
- A4J.AJAX._eventsQueues[options.eventsQueue] = queue;
- if( options.requestDelay ){
- window.setTimeout(function() {
- LOG.debug("End delay waiting, make request in queue "+options.eventsQueue);
- A4J.AJAX.SubmiteventsQueue(A4J.AJAX._eventsQueues[options.eventsQueue]);
- },options.requestDelay);
- LOG.debug("Event occurs, create waiting for request in queue "+options.eventsQueue);
- return;
- }
- }
- }
- A4J.AJAX.SubmitRequest( containerId, form, domEvt , options );
+
+ return domEvt;
};
-A4J.AJAX.SubmiteventsQueue = function( eventsQueue ) {
- // Clear wait flag to avoid resend same request.
- eventsQueue.wait=false;
- A4J.AJAX.SubmitRequest( eventsQueue.containerId, eventsQueue.form ,eventsQueue.domEvt , eventsQueue.options );
-};
- // Main request submitting functions.
- // parameters :
- // form - HtmlForm object for submit.
- // control - form element, called request, or, clientID for JSF view.
- // affected - Array of ID's for DOM Objects, updated after request. Override
- // list of updated areas in response.
- // statusID - DOM id request status tags.
- // oncomplete - function for call after complete request.
-A4J.AJAX.SubmitRequest = function( containerId, formId ,domEvt , options ) {
+A4J.AJAX.PrepareQuery = function(formId, domEvt, options) {
// Process listeners.
for(var li = 0; li < A4J.AJAX._listeners.length; li++){
var listener = A4J.AJAX._listeners[li];
@@ -773,7 +826,7 @@
}
}
// First - run onsubmit event for client-side validation.
- LOG.debug("NEW AJAX REQUEST !!! with form :"+formId );
+ LOG.debug("Query preparation for form '" + formId + "' requested");
// var form = A4J.AJAX.locateForm(event);
var form = window.document.getElementById(formId);
if( (!form || form.nodeName.toUpperCase() != "FORM") && domEvt ) {
@@ -789,7 +842,7 @@
return false;
};
};
- var tosend = new A4J.Query(containerId, form);
+ var tosend = new A4J.Query(options.containerId, form);
tosend.appendFormControls(options.single, options.control);
//appending options.control moved to appendFormControls
//if(options.control){
@@ -798,19 +851,25 @@
if(options.parameters){
tosend.appendParameters(options.parameters);
};
- if(options.eventsCount){
- tosend.appendParameter("AJAX:EVENTS_COUNT",options.eventsCount);
- };
if(options.actionUrl){
tosend.setActionUrl(options.actionUrl);
};
- // build xxxHttpRequest. by Sarissa / JSHttpRequest class always defined.
- var req = new A4J.AJAX.XMLHttpRequest(tosend);
+
+ return tosend;
+};
+
+A4J.AJAX.SubmitQuery = function (query, options, domEvt) {
+ // build xxxHttpRequest. by Sarissa / JSHttpRequest class always defined.
+ var req = new A4J.AJAX.XMLHttpRequest(query);
+ var form = query._form;
+ var containerId = query._containerId;
+
req.options = options;
req.containerId = containerId;
req.domEvt = domEvt;
req.form = form;
+
if(options.timeout){
req.setRequestTimeout(options.timeout);
};
@@ -823,22 +882,71 @@
} else if(typeof(A4J.AJAX.onError)== "function"){
req._onerror = A4J.AJAX.onError;
}
+
+ var _queueonerror = options.queueonerror;
+ if (_queueonerror) {
+ var _onerror = req._onerror;
+ if (_onerror) {
+ req._onerror = function() {
+ _queueonerror.apply(this, arguments);
+ _onerror.apply(this, arguments);
+ };
+ } else {
+ req._onerror = _queueonerror;
+ }
+ }
+
req.onfinish = A4J.AJAX.finishRequest;
- A4J.AJAX.status(containerId,options.status,true);
+ LOG.debug("NEW AJAX REQUEST !!! with form: " + (form.id || form.name || form));
+
+ A4J.AJAX.status(containerId,options.status,true);
req.send();
- if(options.eventsQueue){
- var eventsQueue = A4J.AJAX._eventsQueues[options.eventsQueue];
- if( eventsQueue ) {
- eventsQueue.request=req;
- }
+
+ return req;
+};
+
+//Submit or put in queue request. It not full queues - framework perform waiting only one request to same queue, new events simple replace last.
+//If request for same queue already performed, replace with current parameters.
+A4J.AJAX.Submit = function(formId, event , options ) {
+ var domEvt = A4J.AJAX.CloneEvent(event);
+ var query = A4J.AJAX.PrepareQuery(formId, domEvt, options);
+ if (query) {
+ var queue = A4J.AJAX.EventQueue.getOrCreateQueue(options, formId);
+
+ if (queue) {
+ queue.push(query, options, domEvt);
+ } else {
+ A4J.AJAX.SubmitQuery(query, options, domEvt);
+ }
}
-
+
return false;
- };
+};
+
+ // Main request submitting functions.
+ // parameters :
+ // form - HtmlForm object for submit.
+ // control - form element, called request, or, clientID for JSF view.
+ // affected - Array of ID's for DOM Objects, updated after request. Override
+ // list of updated areas in response.
+ // statusID - DOM id request status tags.
+ // oncomplete - function for call after complete request.
+A4J.AJAX.SubmitRequest = function(formId, event, options ) {
+ var domEvt = A4J.AJAX.CloneEvent(event);
+ var query = A4J.AJAX.PrepareQuery(formId, domEvt, options);
+ if (query) {
+ A4J.AJAX.SubmitQuery(query, options, domEvt);
+ }
+
+ return false;
+};
+
A4J.AJAX.processResponseAfterUpdateHeadElements = function (req, ids)
{
+ req.evaluateQueueScript();
+
for ( var k =0; k < ids.length ; k++ ) {
var id = ids[k];
LOG.debug("Update page part from call parameter for ID " + id);
@@ -880,9 +988,19 @@
if(req.getParserStatus() == Sarissa.PARSED_OK){
// perform beforeupdate if exists
- if(options.onbeforedomupdate){
- LOG.debug( "Call request onbeforedomupdate function before replacing elemements" );
- options.onbeforedomupdate(req, req.domEvt, req.getJSON('_ajax:data'));
+ if(options.onbeforedomupdate || options.queueonbeforedomupdate){
+ var event = req.domEvt;
+ var data = req.getJSON('_ajax:data');
+
+ LOG.debug( "Call local onbeforedomupdate function before replacing elemements" );
+
+ if (options.onbeforedomupdate) {
+ options.onbeforedomupdate(req, event, data);
+ }
+
+ if (options.queueonbeforedomupdate) {
+ options.queueonbeforedomupdate(req, event, data);
+ }
}
var idsFromResponse = req.getResponseHeader("Ajax-Update-Ids");
@@ -1002,27 +1120,42 @@
var oldDocOpen = window.document.open;
if (isIE) {
LOG.debug("setup custom document.open method");
- window.document.open = function() {
- oldDocOpen.apply(this, arguments);
+ window.document.open = function(sUrl, sName, sFeatures, bReplace) {
+ oldDocOpen(sUrl, sName, sFeatures, bReplace);
}
}
// /maksimkaszynski
window.setTimeout(function() {
var isDocOpen=false;
try {
- window.document.open(req.getContentType(),true);
- LOG.debug("window.document has opened for writing");
+ var contentType = req.getContentType();
+ var responseText = isIE ?
+ req.getResponseText().replace(/(<script(?!\s+src=))/igm, "$1 defer ") :
+ req.getResponseText();
+
+ window.document.open(contentType, "replace");
+ if (window.LOG) {
+ LOG.debug("window.document has opened for writing");
+ }
isDocOpen=true;
- window.document.write(req.getResponseText());
- LOG.debug("window.document has been writed");
+
+ window.document.write(responseText);
+
+ if (window.LOG) {
+ LOG.debug("window.document has been writed");
+ }
window.document.close();
- LOG.debug("window.document has been closed for writing");
+ if (window.LOG) {
+ LOG.debug("window.document has been closed for writing");
+ }
if(isIE){
// For Ie , scripts on page not activated.
window.location.reload(false);
}
} catch(e) {
- LOG.debug("exception during write page content "+e.Message);
+ if (window.LOG) {
+ LOG.debug("exception during write page content "+e.Message);
+ }
if(isDocOpen){
window.document.close();
}
@@ -1030,12 +1163,16 @@
// Use dom manipulation instead.
var oDomDoc = (new DOMParser()).parseFromString(req.getResponseText(), "text/xml");
if(Sarissa.getParseErrorText(oDomDoc) == Sarissa.PARSED_OK){
- LOG.debug("response has parsed as DOM documnet.");
+ if (window.LOG) {
+ LOG.debug("response has parsed as DOM documnet.");
+ }
Sarissa.clearChildNodes(window.document.documentElement);
var docNodes = oDomDoc.documentElement.childNodes;
for(var i = 0;i<docNodes.length;i++){
if(docNodes[i].nodeType == 1){
- LOG.debug("append new node in document");
+ if (window.LOG) {
+ LOG.debug("append new node in document");
+ }
var node = window.document.importNode(docNodes[i], true);
window.document.documentElement.appendChild(node);
}
@@ -1045,13 +1182,17 @@
// window.RichFaces.Memory.clean(oldnode);
//}
} else {
- LOG.error("Error parsing response",Sarissa.getParseErrorText(oDomDoc));
+ if (window.LOG) {
+ LOG.error("Error parsing response",Sarissa.getParseErrorText(oDomDoc));
+ }
}
// TODO - scripts reloading ?
} finally {
window.document.open = oldDocOpen;
}
- LOG.debug("page content has been replaced");
+ if (window.LOG) {
+ LOG.debug("page content has been replaced");
+ }
},0);
}
@@ -1064,6 +1205,8 @@
LOG.debug("Input in response: "+newinput.getAttribute("name"));
for(var j = 0 ; j < inputs.length; j++){
var input = inputs[j];
+ input.setAttribute("autocomplete", "off");
+
if(input.name == newinput.getAttribute("name")){
LOG.debug("Found same input on page with type: "+input.type);
input.value = newinput.getAttribute("value");
@@ -1077,55 +1220,105 @@
*
*/
A4J.AJAX.finishRequest = function(request){
- var options = request.options;
- // we can set listener for complete request - for example,
- // it can shedule next request for update page.
- var oncomp = request.getElementById('org.ajax4jsf.oncomplete');
- if(oncomp) {
- LOG.debug( "Call request oncomplete function after processing updates" );
- window.setTimeout(function(){
- var event = request.domEvt;
- var data = request.getJSON('_ajax:data');
- try {
- var newscript = Sarissa.getText(oncomp,true);
- var oncomplete = new Function("request","event","data",newscript);
- var target = null;
+ var options = request.options;
+
+ if (!request._oncomplete_aborted) {
+ // we can set listener for complete request - for example,
+ // it can shedule next request for update page.
+ var oncomp;
+
+ //FIXME: IE doesn't allow to read data from request if it's been aborted
+ //so it's possible that different browsers will follow different branches
+ //of execution for the identical request conditions
+ try {
+ oncomp = request.getElementById('org.ajax4jsf.oncomplete');
+ } catch (e) {
+ LOG.warn("Error reading oncomplete from request " + e.message);
+ }
+
+ if(oncomp) {
+ LOG.debug( "Call request oncomplete function after processing updates" );
+ window.setTimeout(function(){
+ var event = request.domEvt;
+
+ var data;
+ try {
+ data = request.getJSON('_ajax:data');
+ } catch (e) {
+ LOG.warn("Error reading data from request " + e.message);
+ }
+
+ try {
+ var target = null;
if (event) {
- target = event.target ? event.target : event.srcElement;
- };
+ target = event.target ? event.target : event.srcElement;
+ }
+
+ var newscript = Sarissa.getText(oncomp,true);
+ var oncomplete = new Function("request","event","data",newscript);
oncomplete.call(target,request,event,data);
- } catch(e){
- LOG.error('Error evaluate oncomplete function '+e.Message);
- }
-// mark status object ( if any ) for complete request ;
- A4J.AJAX.status(request.containerId,options.status,false);},
- 0);
- } else if(options.oncomplete){
- LOG.debug( "Call component oncomplete function after processing updates" );
- window.setTimeout(function(){
- options.oncomplete(request,request.domEvt,request.getJSON('_ajax:data'));
- // mark status object ( if any ) for complete request ;
- A4J.AJAX.status(request.containerId,options.status,false);},
- 0);
-
- } else {
- // mark status object ( if any ) for complete request ;
+
+ if (options.queueoncomplete) {
+ options.queueoncomplete.call(target, request, event, data);
+ }
+
+ } catch (e) {
+ LOG.error('Error evaluate oncomplete function '+e.Message);
+ }
+
+ // mark status object ( if any ) for complete request ;
+ A4J.AJAX.status(request.containerId,options.status,false);},
+ 0);
+ } else if (options.oncomplete || options.queueoncomplete){
+ LOG.debug( "Call local oncomplete function after processing updates" );
+ window.setTimeout(function(){
+ var event = request.domEvt;
+
+ var data;
+ try {
+ data = request.getJSON('_ajax:data');
+ } catch (e) {
+ LOG.warn("Error reading data from request " + e.message);
+ }
+
+ if (options.oncomplete) {
+ options.oncomplete(request, event, data);
+ }
+
+ if (options.queueoncomplete) {
+ options.queueoncomplete(request, event, data);
+ }
+
+ // mark status object ( if any ) for complete request ;
+ A4J.AJAX.status(request.containerId,options.status,false);},
+ 0);
+
+ } else {
+ LOG.debug( "Processing updates finished, no oncomplete function to call" );
+
+ setTimeout(function() {
+ // mark status object ( if any ) for complete request ;
+ A4J.AJAX.status(request.containerId,options.status,false);
+ }, 0)
+ }
+ } else {
+ LOG.debug("Aborted request, won't call oncomplete at all" );
+
+ setTimeout(function() {
+ // mark status object ( if any ) for complete request ;
A4J.AJAX.status(request.containerId,options.status,false);
- }
- // If we have events in queue - send next request.
- if(options.eventsQueue){
- var eventsQueue = A4J.AJAX._eventsQueues[options.eventsQueue];
- if( eventsQueue ) {
- if(eventsQueue.wait){
- LOG.debug("Queue not empty, execute next request in queue "+options.eventsQueue);
- A4J.AJAX.SubmiteventsQueue(eventsQueue);
- } else {
- A4J.AJAX._eventsQueues[options.eventsQueue]=false;
- }
- }
- }
- };
+ }, 0)
+ }
+ A4J.AJAX.popQueue(request);
+};
+
+A4J.AJAX.popQueue = function(request) {
+ if (request.shouldNotifyQueue && request.queue) {
+ request.queue.pop();
+ }
+};
+
A4J.AJAX.getCursorPos = function(inp){
if(inp.selectionEnd != null)
@@ -1171,30 +1364,39 @@
// on stop - inverse.
A4J.AJAX.status = function(regionID,targetID,start){
try {
- var elem;
targetID = targetID || regionID +":status";
A4J.AJAX._requestsCounts[targetID]=(A4J.AJAX._requestsCounts[targetID]||0)+(start?1:-1);
- if(A4J.AJAX._requestsCounts[targetID]>0){
- elem = document.getElementById(targetID+".stop");
- if(elem){elem.style.display="none";}
- elem = document.getElementById(targetID+".start");
- if(elem){
- elem.style.display="";
- if(typeof(elem.onstart) == 'function'){
- elem.onstart();
- }
+
+ var startElem = document.getElementById(targetID + ".start");
+ var stopElem = document.getElementById(targetID + ".stop");
+
+ if(A4J.AJAX._requestsCounts[targetID] > 0){
+ if (stopElem) {
+ stopElem.style.display = "none";
}
- }else{
- elem = document.getElementById(targetID+".start");
- if(elem){elem.style.display="none";}
- elem = document.getElementById(targetID+".stop");
- if(elem){
- elem.style.display="";
- if(typeof(elem.onstop) == 'function'){
- elem.onstop();
- }
+
+ if (startElem) {
+ startElem.style.display = "";
}
+ } else {
+ if (startElem) {
+ startElem.style.display = "none";
+ }
+
+ if (stopElem) {
+ stopElem.style.display = "";
+ }
}
+
+ if (start) {
+ if (startElem && (typeof(startElem.onstart) == 'function')) {
+ startElem.onstart();
+ }
+ } else {
+ if (stopElem && (typeof(stopElem.onstop) == 'function')) {
+ stopElem.onstop();
+ }
+ }
} catch(e){
LOG.error("Exception on status change: ");
}
@@ -1204,11 +1406,13 @@
// Class for build query string.
-A4J.Query = function(containerId,form){
- // For detect AJAX Request.
- this._query = {AJAXREQUEST : containerId};
+A4J.Query = function(containerId, form){
+ var containerIdOrDefault = containerId || A4J.AJAX.VIEW_ROOT_ID;
+ // For detect AJAX Request.
+ this._query = {AJAXREQUEST : containerIdOrDefault};
this._oldSubmit = null ;
- this._form = form ;
+ this._form = form;
+ this._containerId = containerIdOrDefault;
this._actionUrl = ( this._form.action)?this._form.action:this._form;
};
@@ -1264,7 +1468,7 @@
},
radio : function(control){
- this._check_query(control);
+ this._radio_query(control);
},
checkbox : function(control){
@@ -1402,18 +1606,30 @@
getQueryString : function() {
var qs = "";
var iname ;
+ var querySegments = [];
+ var paramName;
for ( var k in this._query ){
if(typeof Object.prototype[k] == 'undefined'){
iname = this._query[k];
+ paramName = this._encode(k);
if( iname instanceof Object ){
for ( var l=0; l< iname.length; l++ ) {
- qs += this._encode(k) + "=" + this._encode(iname[l]) + "&";
+ querySegments.push(paramName);
+ querySegments.push("=");
+ querySegments.push(this._encode(iname[l]));
+ querySegments.push("&");
}
} else {
- qs += this._encode(k) + "=" + this._encode(iname) + "&";
+ querySegments.push(paramName);
+ querySegments.push("=");
+ querySegments.push(this._encode(iname));
+ querySegments.push("&");
}
}
}
+
+ qs = querySegments.join("");
+
LOG.debug("QueryString: "+qs);
return qs;
},
@@ -1443,6 +1659,12 @@
}
},
+ _radio_query : function(control) {
+ if( control.checked ) {
+ this.appendParameter(control.name, control.value?control.value:"");
+ }
+ },
+
// Append parameter to query. if name exist, append to array of parameters
appendParameter: function(cname,value){
if( ! this._query[cname] ){
@@ -1487,6 +1709,23 @@
return s;
}
+A4J.AJAX.isWebkitBreakingAmps = function() {
+ //RF-4429
+ if (!this._webkitBreakingAmps) {
+ var elt = document.createElement("div");
+ elt.innerHTML = "<a href='#a=a&b=b'>link</a>";
+
+ var link = elt.firstChild;
+ if (link && link.getAttribute && /&b=b$/.test(link.getAttribute('href'))) {
+ this._webkitBreakingAmps = 2;
+ } else {
+ this._webkitBreakingAmps = 1;
+ }
+ }
+
+ return this._webkitBreakingAmps > 1;
+};
+
A4J.AJAX.isXhtmlScriptMode = function() {
if (!this._xhtmlScriptMode) {
var elt = document.createElement("div");
@@ -1537,7 +1776,7 @@
var xmlString = "<html xmlns='http://www.w3.org/1999/xhtml'><sc"+"ript>A4J.AJAX._scriptEvaluated=true;</scr"+"ipt></html>";
oDomDoc = (new DOMParser()).parseFromString(xmlString, "text/xml");
var _script=oDomDoc.getElementsByTagName("script")[0];
- if(!window.opera && _span.outerHTML){
+ if (!window.opera && !A4J.AJAX.isWebkitBreakingAmps() && _span.outerHTML) {
_span.outerHTML = new XMLSerializer().serializeToString(_script);
} else {
var importednode ;
@@ -1549,3 +1788,29 @@
}
A4J.AJAX._scriptTested = true;
}
+
+A4J.AJAX.TestReplacedGetElementByIdVisibility = function() {
+ if (!A4J.AJAX._replacedGetElementByIdVisibilityTested) {
+ A4J.AJAX._replacedGetElementByIdVisibilityTested = true;
+ A4J.AJAX._testReplacedGetElementByIdVisibility = true;
+
+ A4J.AJAX.TestScriptEvaluation();
+ if (A4J.AJAX._scriptEvaluated) {
+ try {
+ var _span = document.createElement("span");
+ document.body.appendChild(_span);
+
+ var xmlString = "<html xmlns='http://www.w3.org/1999/xhtml'><span id='_A4J_AJAX_TestReplacedGetElementByIdVisibility'><sc"+"ript>A4J.AJAX._testReplacedGetElementByIdVisibility = !!(document.getElementById('_A4J_AJAX_TestReplacedGetElementByIdVisibility'));</scr"+"ipt></span></html>";
+ oDomDoc = (new DOMParser()).parseFromString(xmlString, "text/xml");
+ var _newSpan = oDomDoc.getElementsByTagName("span")[0];
+
+ var importednode;
+ importednode = window.document.importNode(_newSpan, true);
+ document.body.replaceChild(importednode,_span);
+ document.body.removeChild(importednode);
+ } catch (e) {
+ LOG.error("Error testing replaced elements getElementById() visibility: " + e.message);
+ }
+ }
+ }
+};
Copied: branches/jsf2.0/framework/impl/src/main/javascript/ajaxjsf/queue.js (from rev 14238, trunk/framework/impl/src/main/javascript/ajaxjsf/queue.js)
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/ajaxjsf/queue.js (rev 0)
+++ branches/jsf2.0/framework/impl/src/main/javascript/ajaxjsf/queue.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -0,0 +1,476 @@
+A4J.AJAX._eventQueues = {};
+
+//queue constructor
+A4J.AJAX.EventQueue = function() {
+ var DROP_NEW = 'dropNew';
+ var DROP_NEXT = 'dropNext';
+ var FIRE_NEW = 'fireNew';
+ var FIRE_NEXT = 'fireNext';
+
+ var extend = function(target, source) {
+ for (var property in source) {
+ target[property] = source[property];
+ }
+ };
+
+ var extendOptions = function(options) {
+ var opts = {};
+
+ for (var name in options) {
+ opts[name] = options[name];
+ }
+
+ for (var name in this.requestOptions) {
+ if (typeof opts[name] == 'undefined') {
+ opts[name] = this.requestOptions[name];
+ }
+ }
+
+ return opts;
+ };
+
+ var QueueEntry = function() {
+ var ctor = function(queue, query, options, event) {
+ this.queue = queue;
+ this.query = query;
+ this.options = options;
+ this.event = event;
+
+ this.similarityGroupingId = this.options.similarityGroupingId;
+ this.eventsCount = 1;
+ };
+
+ extend(ctor.prototype, {
+
+ isIgnoreDupResponses: function() {
+ return this.options.ignoreDupResponses;
+ },
+
+ getSimilarityGroupingId: function() {
+ return this.similarityGroupingId;
+ },
+
+ setSimilarityGroupingId: function(id) {
+ this.similarityGroupingId = id;
+ },
+
+ submit: function() {
+ this.query.appendParameter("AJAX:EVENTS_COUNT", this.eventsCount);
+ this.request = A4J.AJAX.SubmitQuery(this.query, this.options, this.event)
+
+ var queue = this.queue; // TODO: move to next line
+ this.request.queue = queue;
+
+ return this.request;
+ },
+
+ abort: function() {
+ if (this.request && !this.aborted) {
+ //tell request not to notify queue after its processing finished
+ //request.queue = undefined
+ //is not ok for this case because user might want to obtain queue in any event handler
+
+ //RF-5788
+ this.aborted = true;
+ //this.request.shouldNotifyQueue = false;
+ this.request.abort();
+ //this.request = undefined;
+ }
+ },
+
+ ondrop: function() {
+ var callback = this.options.onqueuerequestdrop;
+ if (callback) {
+ callback.call(this.queue, this.query, this.options, this.event);
+ }
+ },
+
+ onRequestDelayPassed: function() {
+ this.readyToSubmit = true;
+ this.queue.submitFirst();
+ },
+
+ startTimer: function() {
+ var delay = this.options.requestDelay;
+
+ LOG.debug("Queue will wait " + (delay || 0) + "ms before submit");
+
+ if (delay) {
+ var _this = this;
+ this.timer = setTimeout(function() {
+ try {
+ _this.onRequestDelayPassed();
+ } finally {
+ _this.timer = undefined;
+ _this = undefined;
+ }
+ }, delay);
+ } else {
+ this.onRequestDelayPassed();
+ }
+ },
+
+ stopTimer: function() {
+ if (this.timer) {
+ clearTimeout(this.timer);
+ this.timer = undefined;
+ }
+ },
+
+ clearEntry: function() {
+ this.stopTimer();
+ if (this.request) {
+ this.request.shouldNotifyQueue = false;
+ this.request = undefined;
+ }
+ },
+
+ getEventsCount: function() {
+ return this.eventsCount;
+ },
+
+ setEventsCount: function(newCount) {
+ this.eventsCount = newCount;
+ },
+
+ getEventArguments: function() {
+ return [this.query, this.options, this.event];
+ }
+ });
+
+ return ctor;
+ }();
+
+ var Queue = function(name, queueOptions, requestOptions) {
+ this.items = new Array();
+
+ this.name = name;
+ this.queueOptions = queueOptions || {};
+ this.requestOptions = requestOptions || {};
+ };
+
+ extend(Queue.prototype, {
+
+ submitFirst: function() {
+ var firstItem = this.items[0];
+ if (firstItem) {
+ if (!firstItem.request) {
+ if (firstItem.readyToSubmit) {
+ LOG.debug("Queue '" + this.name + "' will submit request NOW");
+
+ var req = firstItem.submit();
+
+ //see entry.abort() method for more details about this assignment
+ req.shouldNotifyQueue = true;
+
+ if (this.requestOptions.queueonsubmit) {
+ this.requestOptions.queueonsubmit.call(this, req);
+ }
+ } else {
+ LOG.debug("First item is not ready to be submitted yet");
+ }
+ }
+ } else {
+ LOG.debug("Queue is empty now");
+ }
+ },
+
+ getSize: function() {
+ return this.items.length;
+ },
+
+ getMaximumSize: function() {
+ return this.queueOptions.size;
+ },
+
+ isFull: function() {
+ return this.getSize() == this.getMaximumSize();
+ },
+
+ getSizeExceededBehavior: function() {
+ var policy = this.queueOptions.sizeExceededBehavior;
+ if (!policy) {
+ policy = DROP_NEXT;
+ }
+
+ return policy;
+ },
+
+ queue: function(entry) {
+ this.items.push(entry);
+
+ if (this.queueOptions.onrequestqueue) {
+ LOG.debug("Call onrequestqueue handler");
+ this.queueOptions.onrequestqueue.apply(this, entry.getEventArguments());
+ }
+ },
+
+ dequeue: function() {
+ var entry = this.items.shift();
+
+ if (this.queueOptions.onrequestdequeue) {
+ LOG.debug("Call onrequestdequeue handler");
+ this.queueOptions.onrequestdequeue.apply(this, entry.getEventArguments());
+ }
+ },
+
+ push: function(query, opts, event) {
+ var options = extendOptions.call(this, opts);
+
+ var entry = new QueueEntry(this, query, options, event);
+ var similarityGroupingId = entry.getSimilarityGroupingId();
+
+ var lastIdx = this.items.length - 1;
+ var last = this.items[lastIdx];
+ var handled = false;
+
+ if (last) {
+ if (last.getSimilarityGroupingId() == similarityGroupingId) {
+ LOG.debug("Similar request currently in queue '" + this.name + "'");
+
+ if (last.request) {
+ LOG.debug("Request has already beeen sent to server");
+ if (entry.isIgnoreDupResponses()) {
+ LOG.debug("Duplicate responses ignore requested");
+
+ if (!this.isFull()) {
+ last.abort();
+
+ LOG.debug("Response for the current request will be ignored");
+
+ /* Change for - RF-5788 - wait current request to complete even if ignore duplicate is true
+ //remove last (that is actually first) from queue - will be safer to do that in LinkedList
+ this.dequeue();
+ */
+ } else {
+ LOG.debug("Queue is full, cannot set to ignore response for the current request");
+ }
+
+ }
+ } else {
+ LOG.debug("Combine similar requests and reset timer");
+
+ handled = true;
+ last.stopTimer();
+ entry.setEventsCount(last.getEventsCount() + 1);
+
+ this.items[lastIdx] = entry;
+ entry.startTimer();
+ }
+ } else {
+ LOG.debug("Last queue entry is not the last anymore. Stopping requestDelay timer and marking entry as ready for submission")
+
+ last.stopTimer();
+ last.setSimilarityGroupingId(undefined);
+ last.readyToSubmit = true;
+ }
+ }
+
+ if (!handled) {
+ if (this.isFull()) {
+ LOG.debug("Queue '" + this.name + "' is currently full")
+
+ var b = this.getSizeExceededBehavior();
+
+ var nextIdx = 0;
+ while (this.items[nextIdx] && this.items[nextIdx].request) {
+ nextIdx++;
+ }
+
+ if (this.queueOptions.onsizeexceeded) {
+ this.queueOptions.onsizeexceeded.apply(this, entry.getEventArguments());
+ }
+ // TODO: create one function that will be implement this functionality // function (behaviorFlag, entry): should return handled flag
+ if (b == DROP_NEW) {
+ LOG.debug("Queue '" + this.name + "' is going to drop new item");
+
+ entry.ondrop();
+
+ handled = true;
+ } else if (b == DROP_NEXT) {
+ LOG.debug("Queue '" + this.name + "' is going to drop [" + nextIdx + "] item that is the next one");
+
+ var nextEntry = this.items.splice(nextIdx, 1)[0];
+ if (nextEntry) {
+ LOG.debug("Item dropped from queue");
+
+ nextEntry.stopTimer();
+
+ nextEntry.ondrop();
+ } else {
+ LOG.debug("There's no such item, will handle new request instead");
+
+ entry.ondrop();
+
+ handled = true;
+ }
+ } else if (b == FIRE_NEW) {
+ LOG.debug("Queue '" + this.name + "' will submit new request");
+
+ entry.submit();
+ handled = true;
+ } else if (b == FIRE_NEXT) {
+ LOG.debug("Queue '" + this.name + "' is going to drop and fire immediately [" + nextIdx + "] item that is the next one");
+
+ var nextEntry = this.items.splice(nextIdx, 1)[0];
+ if (nextEntry) {
+ LOG.debug("Item dropped from queue");
+ nextEntry.stopTimer();
+ nextEntry.submit();
+ } else {
+ LOG.debug("There's no such item, will handle new request instead");
+ entry.submit();
+ handled = true;
+ }
+ }
+ }
+
+ this.submitFirst();
+ }
+
+ if (!handled) {
+ this.queue(entry);
+
+ LOG.debug("New request added to queue '" + this.name + "'. Queue similarityGroupingId changed to " + similarityGroupingId);
+
+ entry.startTimer();
+ }
+ },
+
+ pop: function() {
+ LOG.debug("After request: queue '" + this.name + "'");
+
+ this.dequeue();
+
+ LOG.debug("There are " + this.items.length + " requests more in this queue");
+
+ this.submitFirst();
+ },
+
+ clear: function() {
+ var length = this.items.length;
+ for ( var i = 0; i < this.items.length; i++) {
+ this.items[i].clearEntry();
+ }
+
+ this.items.splice(0, length);
+ }
+ });
+
+ return Queue;
+}();
+
+A4J.AJAX.EventQueue.DEFAULT_QUEUE_NAME = "org.richfaces.queue.global";
+
+A4J.AJAX.EventQueue.getQueue = function(name) {
+ return A4J.AJAX._eventQueues[name];
+};
+
+A4J.AJAX.EventQueue.getQueues = function() {
+ return A4J.AJAX._eventQueues;
+};
+
+A4J.AJAX.EventQueue.addQueue = function(queue) {
+ var name = queue.name;
+
+ if (A4J.AJAX._eventQueues[name]) {
+ throw "Queue already registered";
+ } else {
+ LOG.debug("Adding queue '" + name + "' to queues registry");
+ A4J.AJAX._eventQueues[name] = queue;
+ }
+};
+
+A4J.AJAX.EventQueue.removeQueue = function(name) {
+ var queue = A4J.AJAX._eventQueues[name];
+
+ if (queue) {
+ queue.clear();
+ }
+
+ delete A4J.AJAX._eventQueues[name];
+};
+
+A4J.AJAX.EventQueue.getOrCreateQueue = function(){
+ var qualifyName = function(name, prefix) {
+ if (prefix) {
+ return prefix + ":" + name;
+ } else {
+ return name;
+ }
+ };
+
+ var qualifyNamespace = function(name, prefix) {
+ if (prefix) {
+ return prefix + name;
+ } else {
+ return name;
+ }
+ };
+
+ return function(options, formId) {
+ var queueName = options.eventsQueue;
+ var namespace = options.namespace;
+
+ var formQueueName;
+ var viewQueueName;
+ var implicitQueueName;
+
+ if (queueName) {
+ LOG.debug("Look up queue with name '" + queueName + "'");
+
+ formQueueName = qualifyName(queueName, formId);
+ viewQueueName = qualifyNamespace(queueName, namespace);
+
+ implicitQueueName = viewQueueName;
+ } else {
+ LOG.debug("Look up queue with default name");
+
+ formQueueName = formId;
+ viewQueueName = qualifyNamespace(A4J.AJAX.EventQueue.DEFAULT_QUEUE_NAME, namespace);
+
+ implicitQueueName = options.implicitEventsQueue;
+ }
+
+ var queue = A4J.AJAX._eventQueues[formQueueName];
+ if (!queue) {
+ queue = A4J.AJAX._eventQueues[viewQueueName];
+ if (!queue) {
+ if (implicitQueueName) {
+ queue = A4J.AJAX._eventQueues[implicitQueueName];
+ if (!queue) {
+ LOG.debug("Creating new transient queue '" + implicitQueueName + "' with default settings");
+ queue = new A4J.AJAX.EventQueue(implicitQueueName);
+ queue._transient = true;
+
+ A4J.AJAX.EventQueue.addQueue(queue);
+ } else {
+ LOG.debug("Found transient queue '" + implicitQueueName + "'");
+ }
+ }
+ } else {
+ LOG.debug("Found view queue '" + viewQueueName + "'");
+ }
+ } else {
+ LOG.debug("Found form queue '" + formQueueName + "'");
+ }
+
+ return queue;
+ }
+}();
+
+(function () {
+ var observer = function() {
+ var queues = A4J.AJAX.EventQueue.getQueues();
+ for (var queueName in queues) {
+ var queue = queues[queueName];
+ queue.clear();
+ }
+ };
+
+ if (window.addEventListener) {
+ window.addEventListener("unload", observer, false);
+ } else {
+ window.attachEvent("onunload", observer);
+ }
+})();
\ No newline at end of file
Modified: branches/jsf2.0/framework/impl/src/main/javascript/ajaxjsf/sarissa.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/ajaxjsf/sarissa.js 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/main/javascript/ajaxjsf/sarissa.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -121,6 +121,9 @@
// anyway as IE7 hardcodes it to MSXML3.0 causing version problems
// between different activex controls
//if(!window.XMLHttpRequest){
+
+ Sarissa.originalXMLHttpRequest = window.XMLHttpRequest;
+
/**
* Emulate XMLHttpRequest
* @constructor
@@ -481,7 +484,17 @@
if((typeof(document.importNode) == "undefined") && Sarissa._SARISSA_IS_IE){
try{
- /**
+ var importTable = {
+ TBODY: ['<table>', '</table>' ],
+ THEAD: ['<table>', '</table>' ],
+ TFOOT: ['<table>', '</table>' ],
+ TR: ['<table><tbody>', '</tbody></table>' ],
+ TH: ['<table><thead><tr>', '</tr></thead></table>'],
+ TD: ['<table><tbody><tr>', '</tr></tbody></table>'],
+ OPTION: ['<select>', '</select>' ]
+ };
+
+ /**
* Implementation of importNode for the context window document in IE.
* If <code>oNode</code> is a TextNode, <code>bChildren</code> is ignored.
* @param oNode the Node to import
@@ -494,33 +507,53 @@
return document.createTextNode(oNode.data);
}
else {
- var tbody = false;
- if(oNode.nodeName == "tbody" && oNode.parentNode){
- oNode = oNode.parentNode;
- tbody = true;
- }
- else if(oNode.nodeName == "tbody" || oNode.nodeName == "tr"){
- tmp = document.createElement("tr");
- }
- else if(oNode.nodeName == "td"){
- tmp = document.createElement("tr");
- }
- else if(oNode.nodeName == "option"){
- tmp = document.createElement("select");
- }
- if(!tmp){
- tmp = document.createElement("div");
- }
- if(bChildren){
- tmp.innerHTML = oNode.xml ? oNode.xml : oNode.outerHTML;
- }else{
- tmp.innerHTML = oNode.xml ? oNode.cloneNode(false).xml : oNode.cloneNode(false).outerHTML;
- }
- if (tbody) {
- return tmp.firstChild.tBodies[0];
+ var tagName = oNode.nodeName.toUpperCase();
+ var wrapper = importTable[tagName];
+
+ var nodeHtml;
+ if (bChildren) {
+ nodeHtml = oNode.xml ? oNode.xml : oNode.outerHTML;
} else {
- return tmp.getElementsByTagName("*")[0];
+ nodeHtml = oNode.xml ? oNode.cloneNode(false).xml : oNode.cloneNode(false).outerHTML;
}
+
+ var wrapperElt = document.createElement("div");
+ if (wrapper) {
+ nodeHtml = wrapper[0] + nodeHtml + wrapper[1];
+ }
+
+ wrapperElt.innerHTML = nodeHtml;
+
+ //Breadth-first search
+ var stack = new Array(wrapperElt.firstChild);
+ var result;
+
+ while (!result) {
+ var newStack = new Array();
+
+ for (var i = 0; i < stack.length && !result; i++) {
+ var elt = stack[i];
+ while (elt) {
+ if (elt.tagName /* we can meet text nodes */ &&
+ elt.tagName.toUpperCase() == tagName) {
+
+ result = elt;
+ break;
+ } else {
+ if (elt.firstChild) {
+ newStack.push(elt.firstChild);
+ }
+
+ elt = elt.nextSibling;
+ }
+ }
+ }
+
+ stack = newStack;
+ }
+ //Breadth-first search end
+
+ return result;
}
};
}catch(e){ }
Modified: branches/jsf2.0/framework/impl/src/main/javascript/jquery/jquery-1.2.6.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/jquery/jquery-1.2.6.js 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/main/javascript/jquery/jquery-1.2.6.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -601,7 +601,7 @@
return target;
};
-var expando = "jQuery" + now(), uuid = 0, windowData = {},
+var expando = jQuery.expando = "jQuery" + now(), uuid = 0, windowData = {},
// exclude the following css properties to add px
exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
// cache defaultView
Copied: branches/jsf2.0/framework/impl/src/main/javascript/jquery/jquery-1.3.1.js (from rev 14238, trunk/framework/impl/src/main/javascript/jquery/jquery-1.3.1.js)
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/jquery/jquery-1.3.1.js (rev 0)
+++ branches/jsf2.0/framework/impl/src/main/javascript/jquery/jquery-1.3.1.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -0,0 +1,4257 @@
+/*!
+ * jQuery JavaScript Library v1.3.1
+ * http://jquery.com/
+ *
+ * Copyright (c) 2009 John Resig
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ *
+ * Date: 2009-01-21 20:42:16 -0500 (Wed, 21 Jan 2009)
+ * Revision: 6158
+ */
+(function(){
+
+var
+ // Will speed up references to window, and allows munging its name.
+ window = this,
+ // Will speed up references to undefined, and allows munging its name.
+ undefined,
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+ // Map over the $ in case of overwrite
+ _$ = window.$,
+
+ jQuery = window.jQuery = window.$ = function( selector, context ) {
+ // added for RichFaces components
+ if (arguments[0] == arguments.callee) {
+ return arguments.callee;
+ }
+
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context );
+ },
+
+ // A simple way to check for HTML strings or ID strings
+ // (both of which we optimize for)
+ quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
+ // Is it a simple selector
+ isSimple = /^.[^:#\[\.,]*$/;
+
+jQuery.fn = jQuery.prototype = {
+ init: function( selector, context ) {
+ // Make sure that a selection was provided
+ selector = selector || document;
+
+ // Handle $(DOMElement)
+ if ( selector.nodeType ) {
+ this[0] = selector;
+ this.length = 1;
+ this.context = selector;
+ return this;
+ }
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ // Are we dealing with HTML string or an ID?
+ var match = quickExpr.exec( selector );
+
+ // Verify a match, and that no context was specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] )
+ selector = jQuery.clean( [ match[1] ], context );
+
+ // HANDLE: $("#id")
+ else {
+ var elem = document.getElementById( match[3] );
+
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem && elem.id != match[3] )
+ return jQuery().find( selector );
+
+ // Otherwise, we inject the element directly into the jQuery object
+ var ret = jQuery( elem || [] );
+ ret.context = document;
+ ret.selector = selector;
+ return ret;
+ }
+
+ // HANDLE: $(expr, [context])
+ // (which is just equivalent to: $(content).find(expr)
+ } else
+ return jQuery( context ).find( selector );
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) )
+ return jQuery( document ).ready( selector );
+
+ // Make sure that old selector state is passed along
+ if ( selector.selector && selector.context ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return this.setArray(jQuery.makeArray(selector));
+ },
+
+ // Start with an empty selector
+ selector: "",
+
+ // The current version of jQuery being used
+ jquery: "1.3.1",
+
+ // The number of elements contained in the matched element set
+ size: function() {
+ return this.length;
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num === undefined ?
+
+ // Return a 'clean' array
+ jQuery.makeArray( this ) :
+
+ // Return just the object
+ this[ num ];
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems, name, selector ) {
+ // Build a new jQuery matched element set
+ var ret = jQuery( elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+
+ ret.context = this.context;
+
+ if ( name === "find" )
+ ret.selector = this.selector + (this.selector ? " " : "") + selector;
+ else if ( name )
+ ret.selector = this.selector + "." + name + "(" + selector + ")";
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Force the current matched set of elements to become
+ // the specified array of elements (destroying the stack in the process)
+ // You should use pushStack() in order to do this, but maintain the stack
+ setArray: function( elems ) {
+ // Resetting the length to 0, then using the native Array push
+ // is a super-fast way to populate an object with array-like properties
+ this.length = 0;
+ Array.prototype.push.apply( this, elems );
+
+ return this;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem && elem.jquery ? elem[0] : elem
+ , this );
+ },
+
+ attr: function( name, value, type ) {
+ var options = name;
+
+ // Look for the case where we're accessing a style value
+ if ( typeof name === "string" )
+ if ( value === undefined )
+ return this[0] && jQuery[ type || "attr" ]( this[0], name );
+
+ else {
+ options = {};
+ options[ name ] = value;
+ }
+
+ // Check to see if we're setting style values
+ return this.each(function(i){
+ // Set all the styles
+ for ( name in options )
+ jQuery.attr(
+ type ?
+ this.style :
+ this,
+ name, jQuery.prop( this, options[ name ], type, i, name )
+ );
+ });
+ },
+
+ css: function( key, value ) {
+ // ignore negative width and height values
+ if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
+ value = undefined;
+ return this.attr( key, value, "curCSS" );
+ },
+
+ text: function( text ) {
+ if ( typeof text !== "object" && text != null )
+ return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+
+ var ret = "";
+
+ jQuery.each( text || this, function(){
+ jQuery.each( this.childNodes, function(){
+ if ( this.nodeType != 8 )
+ ret += this.nodeType != 1 ?
+ this.nodeValue :
+ jQuery.fn.text( [ this ] );
+ });
+ });
+
+ return ret;
+ },
+
+ wrapAll: function( html ) {
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).clone();
+
+ if ( this[0].parentNode )
+ wrap.insertBefore( this[0] );
+
+ wrap.map(function(){
+ var elem = this;
+
+ while ( elem.firstChild )
+ elem = elem.firstChild;
+
+ return elem;
+ }).append(this);
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ return this.each(function(){
+ jQuery( this ).contents().wrapAll( html );
+ });
+ },
+
+ wrap: function( html ) {
+ return this.each(function(){
+ jQuery( this ).wrapAll( html );
+ });
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, function(elem){
+ if (this.nodeType == 1)
+ this.appendChild( elem );
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, function(elem){
+ if (this.nodeType == 1)
+ this.insertBefore( elem, this.firstChild );
+ });
+ },
+
+ before: function() {
+ return this.domManip(arguments, false, function(elem){
+ this.parentNode.insertBefore( elem, this );
+ });
+ },
+
+ after: function() {
+ return this.domManip(arguments, false, function(elem){
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ });
+ },
+
+ end: function() {
+ return this.prevObject || jQuery( [] );
+ },
+
+ // For internal use only.
+ // Behaves like an Array's .push method, not like a jQuery method.
+ push: [].push,
+
+ find: function( selector ) {
+ if ( this.length === 1 && !/,/.test(selector) ) {
+ var ret = this.pushStack( [], "find", selector );
+ ret.length = 0;
+ jQuery.find( selector, this[0], ret );
+ return ret;
+ } else {
+ var elems = jQuery.map(this, function(elem){
+ return jQuery.find( selector, elem );
+ });
+
+ return this.pushStack( /[^+>] [^+>]/.test( selector ) ?
+ jQuery.unique( elems ) :
+ elems, "find", selector );
+ }
+ },
+
+ clone: function( events ) {
+ // Do the clone
+ var ret = this.map(function(){
+ if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
+ // IE copies events bound via attachEvent when
+ // using cloneNode. Calling detachEvent on the
+ // clone will also remove the events from the orignal
+ // In order to get around this, we use innerHTML.
+ // Unfortunately, this means some modifications to
+ // attributes in IE that are actually only stored
+ // as properties will not be copied (such as the
+ // the name attribute on an input).
+ var clone = this.cloneNode(true),
+ container = document.createElement("div");
+ container.appendChild(clone);
+ return jQuery.clean([container.innerHTML])[0];
+ } else
+ return this.cloneNode(true);
+ });
+
+ // Need to set the expando to null on the cloned set if it exists
+ // removeData doesn't work here, IE removes it from the original as well
+ // this is primarily for IE but the data expando shouldn't be copied over in any browser
+ var clone = ret.find("*").andSelf().each(function(){
+ if ( this[ expando ] !== undefined )
+ this[ expando ] = null;
+ });
+
+ // Copy the events from the original to the clone
+ if ( events === true )
+ this.find("*").andSelf().each(function(i){
+ if (this.nodeType == 3)
+ return;
+ var events = jQuery.data( this, "events" );
+
+ for ( var type in events )
+ for ( var handler in events[ type ] )
+ jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
+ });
+
+ // Return the cloned set
+ return ret;
+ },
+
+ filter: function( selector ) {
+ return this.pushStack(
+ jQuery.isFunction( selector ) &&
+ jQuery.grep(this, function(elem, i){
+ return selector.call( elem, i );
+ }) ||
+
+ jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
+ return elem.nodeType === 1;
+ }) ), "filter", selector );
+ },
+
+ closest: function( selector ) {
+ var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null;
+
+ return this.map(function(){
+ var cur = this;
+ while ( cur && cur.ownerDocument ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) )
+ return cur;
+ cur = cur.parentNode;
+ }
+ });
+ },
+
+ not: function( selector ) {
+ if ( typeof selector === "string" )
+ // test special case where just one selector is passed in
+ if ( isSimple.test( selector ) )
+ return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
+ else
+ selector = jQuery.multiFilter( selector, this );
+
+ var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
+ return this.filter(function() {
+ return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
+ });
+ },
+
+ add: function( selector ) {
+ return this.pushStack( jQuery.unique( jQuery.merge(
+ this.get(),
+ typeof selector === "string" ?
+ jQuery( selector ) :
+ jQuery.makeArray( selector )
+ )));
+ },
+
+ is: function( selector ) {
+ return !!selector && jQuery.multiFilter( selector, this ).length > 0;
+ },
+
+ hasClass: function( selector ) {
+ return !!selector && this.is( "." + selector );
+ },
+
+ val: function( value ) {
+ if ( value === undefined ) {
+ var elem = this[0];
+
+ if ( elem ) {
+ if( jQuery.nodeName( elem, 'option' ) )
+ return (elem.attributes.value || {}).specified ? elem.value : elem.text;
+
+ // We need to handle select boxes special
+ if ( jQuery.nodeName( elem, "select" ) ) {
+ var index = elem.selectedIndex,
+ values = [],
+ options = elem.options,
+ one = elem.type == "select-one";
+
+ // Nothing was selected
+ if ( index < 0 )
+ return null;
+
+ // Loop through all the selected options
+ for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+ var option = options[ i ];
+
+ if ( option.selected ) {
+ // Get the specifc value for the option
+ value = jQuery(option).val();
+
+ // We don't need an array for one selects
+ if ( one )
+ return value;
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ }
+
+ // Everything else, we just grab the value
+ return (elem.value || "").replace(/\r/g, "");
+
+ }
+
+ return undefined;
+ }
+
+ if ( typeof value === "number" )
+ value += '';
+
+ return this.each(function(){
+ if ( this.nodeType != 1 )
+ return;
+
+ if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
+ this.checked = (jQuery.inArray(this.value, value) >= 0 ||
+ jQuery.inArray(this.name, value) >= 0);
+
+ else if ( jQuery.nodeName( this, "select" ) ) {
+ var values = jQuery.makeArray(value);
+
+ jQuery( "option", this ).each(function(){
+ this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
+ jQuery.inArray( this.text, values ) >= 0);
+ });
+
+ if ( !values.length )
+ this.selectedIndex = -1;
+
+ } else
+ this.value = value;
+ });
+ },
+
+ html: function( value ) {
+ return value === undefined ?
+ (this[0] ?
+ this[0].innerHTML :
+ null) :
+ this.empty().append( value );
+ },
+
+ replaceWith: function( value ) {
+ return this.after( value ).remove();
+ },
+
+ eq: function( i ) {
+ return this.slice( i, +i + 1 );
+ },
+
+ slice: function() {
+ return this.pushStack( Array.prototype.slice.apply( this, arguments ),
+ "slice", Array.prototype.slice.call(arguments).join(",") );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function(elem, i){
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ andSelf: function() {
+ return this.add( this.prevObject );
+ },
+
+ domManip: function( args, table, callback ) {
+ if ( this[0] ) {
+ var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
+ scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
+ first = fragment.firstChild,
+ extra = this.length > 1 ? fragment.cloneNode(true) : fragment;
+
+ if ( first )
+ for ( var i = 0, l = this.length; i < l; i++ )
+ callback.call( root(this[i], first), i > 0 ? extra.cloneNode(true) : fragment );
+
+ if ( scripts )
+ jQuery.each( scripts, evalScript );
+ }
+
+ return this;
+
+ function root( elem, cur ) {
+ return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
+ (elem.getElementsByTagName("tbody")[0] ||
+ elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+ elem;
+ }
+ }
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+function evalScript( i, elem ) {
+ if ( elem.src )
+ jQuery.ajax({
+ url: elem.src,
+ async: false,
+ dataType: "script"
+ });
+
+ else
+ jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+
+ if ( elem.parentNode )
+ elem.parentNode.removeChild( elem );
+}
+
+function now(){
+ return +new Date;
+}
+
+jQuery.extend = jQuery.fn.extend = function() {
+ // copy reference to target object
+ var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) )
+ target = {};
+
+ // extend jQuery itself if only one argument is passed
+ if ( length == i ) {
+ target = this;
+ --i;
+ }
+
+ for ( ; i < length; i++ )
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null )
+ // Extend the base object
+ for ( var name in options ) {
+ var src = target[ name ], copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy )
+ continue;
+
+ // Recurse if we're merging object values
+ if ( deep && copy && typeof copy === "object" && !copy.nodeType )
+ target[ name ] = jQuery.extend( deep,
+ // Never move original objects, clone them
+ src || ( copy.length != null ? [ ] : { } )
+ , copy );
+
+ // Don't bring in undefined values
+ else if ( copy !== undefined )
+ target[ name ] = copy;
+
+ }
+
+ // Return the modified object
+ return target;
+};
+
+// exclude the following css properties to add px
+var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
+ // cache defaultView
+ defaultView = document.defaultView || {},
+ toString = Object.prototype.toString;
+
+jQuery.extend({
+ noConflict: function( deep ) {
+ window.$ = _$;
+
+ if ( deep )
+ window.jQuery = _jQuery;
+
+ return jQuery;
+ },
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return toString.call(obj) === "[object Function]";
+ },
+
+ isArray: function( obj ) {
+ return toString.call(obj) === "[object Array]";
+ },
+
+ // check if an element is in a (or is an) XML document
+ isXMLDoc: function( elem ) {
+ return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
+ !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
+ },
+
+ // Evalulates a script in a global context
+ globalEval: function( data ) {
+ data = jQuery.trim( data );
+
+ if ( data ) {
+ // Inspired by code by Andrea Giammarchi
+ // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom...
+ var head = document.getElementsByTagName("head")[0] || document.documentElement,
+ script = document.createElement("script");
+
+ script.type = "text/javascript";
+ if ( jQuery.support.scriptEval )
+ script.appendChild( document.createTextNode( data ) );
+ else
+ script.text = data;
+
+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
+ // This arises when a base node is used (#2709).
+ head.insertBefore( script, head.firstChild );
+ head.removeChild( script );
+ }
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
+ },
+
+ // args is for internal usage only
+ each: function( object, callback, args ) {
+ var name, i = 0, length = object.length;
+
+ if ( args ) {
+ if ( length === undefined ) {
+ for ( name in object )
+ if ( callback.apply( object[ name ], args ) === false )
+ break;
+ } else
+ for ( ; i < length; )
+ if ( callback.apply( object[ i++ ], args ) === false )
+ break;
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( length === undefined ) {
+ for ( name in object )
+ if ( callback.call( object[ name ], name, object[ name ] ) === false )
+ break;
+ } else
+ for ( var value = object[0];
+ i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
+ }
+
+ return object;
+ },
+
+ prop: function( elem, value, type, i, name ) {
+ // Handle executable functions
+ if ( jQuery.isFunction( value ) )
+ value = value.call( elem, i );
+
+ // Handle passing in a number to a CSS property
+ return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
+ value + "px" :
+ value;
+ },
+
+ className: {
+ // internal only, use addClass("class")
+ add: function( elem, classNames ) {
+ jQuery.each((classNames || "").split(/\s+/), function(i, className){
+ if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
+ elem.className += (elem.className ? " " : "") + className;
+ });
+ },
+
+ // internal only, use removeClass("class")
+ remove: function( elem, classNames ) {
+ if (elem.nodeType == 1)
+ elem.className = classNames !== undefined ?
+ jQuery.grep(elem.className.split(/\s+/), function(className){
+ return !jQuery.className.has( classNames, className );
+ }).join(" ") :
+ "";
+ },
+
+ // internal only, use hasClass("class")
+ has: function( elem, className ) {
+ return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
+ }
+ },
+
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback ) {
+ var old = {};
+ // Remember the old values, and insert the new ones
+ for ( var name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ callback.call( elem );
+
+ // Revert the old values
+ for ( var name in options )
+ elem.style[ name ] = old[ name ];
+ },
+
+ css: function( elem, name, force ) {
+ if ( name == "width" || name == "height" ) {
+ var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
+
+ function getWH() {
+ val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
+ var padding = 0, border = 0;
+ jQuery.each( which, function() {
+ padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
+ border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
+ });
+ val -= Math.round(padding + border);
+ }
+
+ if ( jQuery(elem).is(":visible") )
+ getWH();
+ else
+ jQuery.swap( elem, props, getWH );
+
+ return Math.max(0, val);
+ }
+
+ return jQuery.curCSS( elem, name, force );
+ },
+
+ curCSS: function( elem, name, force ) {
+ var ret, style = elem.style;
+
+ // We need to handle opacity special in IE
+ if ( name == "opacity" && !jQuery.support.opacity ) {
+ ret = jQuery.attr( style, "opacity" );
+
+ return ret == "" ?
+ "1" :
+ ret;
+ }
+
+ // Make sure we're using the right name for getting the float value
+ if ( name.match( /float/i ) )
+ name = styleFloat;
+
+ if ( !force && style && style[ name ] )
+ ret = style[ name ];
+
+ else if ( defaultView.getComputedStyle ) {
+
+ // Only "float" is needed here
+ if ( name.match( /float/i ) )
+ name = "float";
+
+ name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
+
+ var computedStyle = defaultView.getComputedStyle( elem, null );
+
+ if ( computedStyle )
+ ret = computedStyle.getPropertyValue( name );
+
+ // We should always get a number back from opacity
+ if ( name == "opacity" && ret == "" )
+ ret = "1";
+
+ } else if ( elem.currentStyle ) {
+ var camelCase = name.replace(/\-(\w)/g, function(all, letter){
+ return letter.toUpperCase();
+ });
+
+ ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
+ // Remember the original values
+ var left = style.left, rsLeft = elem.runtimeStyle.left;
+
+ // Put in the new values to get a computed value out
+ elem.runtimeStyle.left = elem.currentStyle.left;
+ style.left = ret || 0;
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ elem.runtimeStyle.left = rsLeft;
+ }
+ }
+
+ return ret;
+ },
+
+ clean: function( elems, context, fragment ) {
+ context = context || document;
+
+ // !context.createElement fails in IE with an error but returns typeof 'object'
+ if ( typeof context.createElement === "undefined" )
+ context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+
+ // If a single string is passed in and it's a single tag
+ // just do a createElement and skip the rest
+ if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
+ var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
+ if ( match )
+ return [ context.createElement( match[1] ) ];
+ }
+
+ var ret = [], scripts = [], div = context.createElement("div");
+
+ jQuery.each(elems, function(i, elem){
+ if ( typeof elem === "number" )
+ elem += '';
+
+ if ( !elem )
+ return;
+
+ // Convert html string into DOM nodes
+ if ( typeof elem === "string" ) {
+ // Fix "XHTML"-style tags in all browsers
+ elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
+ return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
+ all :
+ front + "></" + tag + ">";
+ });
+
+ // Trim whitespace, otherwise indexOf won't work as expected
+ var tags = jQuery.trim( elem ).toLowerCase();
+
+ var wrap =
+ // option or optgroup
+ !tags.indexOf("<opt") &&
+ [ 1, "<select multiple='multiple'>", "</select>" ] ||
+
+ !tags.indexOf("<leg") &&
+ [ 1, "<fieldset>", "</fieldset>" ] ||
+
+ tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
+ [ 1, "<table>", "</table>" ] ||
+
+ !tags.indexOf("<tr") &&
+ [ 2, "<table><tbody>", "</tbody></table>" ] ||
+
+ // <thead> matched above
+ (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
+ [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
+
+ !tags.indexOf("<col") &&
+ [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
+
+ // IE can't serialize <link> and <script> tags normally
+ !jQuery.support.htmlSerialize &&
+ [ 1, "div<div>", "</div>" ] ||
+
+ [ 0, "", "" ];
+
+ // Go to html and back, then peel off extra wrappers
+ div.innerHTML = wrap[1] + elem + wrap[2];
+
+ // Move to the right depth
+ while ( wrap[0]-- )
+ div = div.lastChild;
+
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !jQuery.support.tbody ) {
+
+ // String was a <table>, *may* have spurious <tbody>
+ var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
+ div.firstChild && div.firstChild.childNodes :
+
+ // String was a bare <thead> or <tfoot>
+ wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
+ div.childNodes :
+ [];
+
+ for ( var j = tbody.length - 1; j >= 0 ; --j )
+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
+
+ }
+
+ // IE completely kills leading whitespace when innerHTML is used
+ if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
+ div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
+
+ elem = jQuery.makeArray( div.childNodes );
+ }
+
+ if ( elem.nodeType )
+ ret.push( elem );
+ else
+ ret = jQuery.merge( ret, elem );
+
+ });
+
+ if ( fragment ) {
+ for ( var i = 0; ret[i]; i++ ) {
+ if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+ scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+ } else {
+ if ( ret[i].nodeType === 1 )
+ ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
+ fragment.appendChild( ret[i] );
+ }
+ }
+
+ return scripts;
+ }
+
+ return ret;
+ },
+
+ attr: function( elem, name, value ) {
+ // don't set attributes on text and comment nodes
+ if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
+ return undefined;
+
+ var notxml = !jQuery.isXMLDoc( elem ),
+ // Whether we are setting (or getting)
+ set = value !== undefined;
+
+ // Try to normalize/fix the name
+ name = notxml && jQuery.props[ name ] || name;
+
+ // Only do all the following if this is a node (faster for style)
+ // IE elem.getAttribute passes even for style
+ if ( elem.tagName ) {
+
+ // These attributes require special treatment
+ var special = /href|src|style/.test( name );
+
+ // Safari mis-reports the default selected property of a hidden option
+ // Accessing the parent's selectedIndex property fixes it
+ if ( name == "selected" && elem.parentNode )
+ elem.parentNode.selectedIndex;
+
+ // If applicable, access the attribute via the DOM 0 way
+ if ( name in elem && notxml && !special ) {
+ if ( set ){
+ // We can't allow the type property to be changed (since it causes problems in IE)
+ if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
+ throw "type property can't be changed";
+
+ elem[ name ] = value;
+ }
+
+ // browsers index elements by id/name on forms, give priority to attributes.
+ if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
+ return elem.getAttributeNode( name ).nodeValue;
+
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabi...
+ if ( name == "tabIndex" ) {
+ var attributeNode = elem.getAttributeNode( "tabIndex" );
+ return attributeNode && attributeNode.specified
+ ? attributeNode.value
+ : elem.nodeName.match(/(button|input|object|select|textarea)/i)
+ ? 0
+ : elem.nodeName.match(/^(a|area)$/i) && elem.href
+ ? 0
+ : undefined;
+ }
+
+ return elem[ name ];
+ }
+
+ if ( !jQuery.support.style && notxml && name == "style" )
+ return jQuery.attr( elem.style, "cssText", value );
+
+ if ( set )
+ // convert the value to a string (all browsers do this but IE) see #1070
+ elem.setAttribute( name, "" + value );
+
+ var attr = !jQuery.support.hrefNormalized && notxml && special
+ // Some attributes require a special call on IE
+ ? elem.getAttribute( name, 2 )
+ : elem.getAttribute( name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return attr === null ? undefined : attr;
+ }
+
+ // elem is actually elem.style ... set the style
+
+ // IE uses filters for opacity
+ if ( !jQuery.support.opacity && name == "opacity" ) {
+ if ( set ) {
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ elem.zoom = 1;
+
+ // Set the alpha filter to set the opacity
+ elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
+ (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
+ }
+
+ return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
+ (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
+ "";
+ }
+
+ name = name.replace(/-([a-z])/ig, function(all, letter){
+ return letter.toUpperCase();
+ });
+
+ if ( set )
+ elem[ name ] = value;
+
+ return elem[ name ];
+ },
+
+ trim: function( text ) {
+ return (text || "").replace( /^\s+|\s+$/g, "" );
+ },
+
+ makeArray: function( array ) {
+ var ret = [];
+
+ if( array != null ){
+ var i = array.length;
+ // The window, strings (and functions) also have 'length'
+ if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
+ ret[0] = array;
+ else
+ while( i )
+ ret[--i] = array[i];
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, array ) {
+ for ( var i = 0, length = array.length; i < length; i++ )
+ // Use === because on IE, window == document
+ if ( array[ i ] === elem )
+ return i;
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ // We have to loop this way because IE & Opera overwrite the length
+ // expando of getElementsByTagName
+ var i = 0, elem, pos = first.length;
+ // Also, we need to make sure that the correct elements are being returned
+ // (IE returns comment nodes in a '*' query)
+ if ( !jQuery.support.getAll ) {
+ while ( (elem = second[ i++ ]) != null )
+ if ( elem.nodeType != 8 )
+ first[ pos++ ] = elem;
+
+ } else
+ while ( (elem = second[ i++ ]) != null )
+ first[ pos++ ] = elem;
+
+ return first;
+ },
+
+ unique: function( array ) {
+ var ret = [], done = {};
+
+ try {
+
+ for ( var i = 0, length = array.length; i < length; i++ ) {
+ var id = jQuery.data( array[ i ] );
+
+ if ( !done[ id ] ) {
+ done[ id ] = true;
+ ret.push( array[ i ] );
+ }
+ }
+
+ } catch( e ) {
+ ret = array;
+ }
+
+ return ret;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var ret = [];
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( var i = 0, length = elems.length; i < length; i++ )
+ if ( !inv != !callback( elems[ i ], i ) )
+ ret.push( elems[ i ] );
+
+ return ret;
+ },
+
+ map: function( elems, callback ) {
+ var ret = [];
+
+ // Go through the array, translating each of the items to their
+ // new value (or values).
+ for ( var i = 0, length = elems.length; i < length; i++ ) {
+ var value = callback( elems[ i ], i );
+
+ if ( value != null )
+ ret[ ret.length ] = value;
+ }
+
+ return ret.concat.apply( [], ret );
+ }
+});
+
+// Use of jQuery.browser is deprecated.
+// It's included for backwards compatibility and plugins,
+// although they should work to migrate away.
+
+var userAgent = navigator.userAgent.toLowerCase();
+
+// Figure out what browser is being used
+jQuery.browser = {
+ version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
+ safari: /webkit/.test( userAgent ),
+ opera: /opera/.test( userAgent ),
+ msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
+ mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
+};
+
+jQuery.each({
+ parent: function(elem){return elem.parentNode;},
+ parents: function(elem){return jQuery.dir(elem,"parentNode");},
+ next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
+ prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
+ nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
+ prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
+ siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
+ children: function(elem){return jQuery.sibling(elem.firstChild);},
+ contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
+}, function(name, fn){
+ jQuery.fn[ name ] = function( selector ) {
+ var ret = jQuery.map( this, fn );
+
+ if ( selector && typeof selector == "string" )
+ ret = jQuery.multiFilter( selector, ret );
+
+ return this.pushStack( jQuery.unique( ret ), name, selector );
+ };
+});
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function(name, original){
+ jQuery.fn[ name ] = function() {
+ var args = arguments;
+
+ return this.each(function(){
+ for ( var i = 0, length = args.length; i < length; i++ )
+ jQuery( args[ i ] )[ original ]( this );
+ });
+ };
+});
+
+jQuery.each({
+ removeAttr: function( name ) {
+ jQuery.attr( this, name, "" );
+ if (this.nodeType == 1)
+ this.removeAttribute( name );
+ },
+
+ addClass: function( classNames ) {
+ jQuery.className.add( this, classNames );
+ },
+
+ removeClass: function( classNames ) {
+ jQuery.className.remove( this, classNames );
+ },
+
+ toggleClass: function( classNames, state ) {
+ if( typeof state !== "boolean" )
+ state = !jQuery.className.has( this, classNames );
+ jQuery.className[ state ? "add" : "remove" ]( this, classNames );
+ },
+
+ remove: function( selector ) {
+ if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
+ // Prevent memory leaks
+ jQuery( "*", this ).add([this]).each(function(){
+ jQuery.event.remove(this);
+ jQuery.removeData(this);
+ });
+ if (this.parentNode)
+ this.parentNode.removeChild( this );
+ }
+ },
+
+ empty: function() {
+ // Remove element nodes and prevent memory leaks
+ jQuery( ">*", this ).remove();
+
+ // Remove any remaining nodes
+ while ( this.firstChild )
+ this.removeChild( this.firstChild );
+ }
+}, function(name, fn){
+ jQuery.fn[ name ] = function(){
+ return this.each( fn, arguments );
+ };
+});
+
+// Helper function used by the dimensions and offset modules
+function num(elem, prop) {
+ return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
+}
+var expando = jQuery.expando = "jQuery" + now(), uuid = 0, windowData = {};
+
+jQuery.extend({
+ cache: {},
+
+ data: function( elem, name, data ) {
+ elem = elem == window ?
+ windowData :
+ elem;
+
+ var id = elem[ expando ];
+
+ // Compute a unique ID for the element
+ if ( !id )
+ id = elem[ expando ] = ++uuid;
+
+ // Only generate the data cache if we're
+ // trying to access or manipulate it
+ if ( name && !jQuery.cache[ id ] )
+ jQuery.cache[ id ] = {};
+
+ // Prevent overriding the named cache with undefined values
+ if ( data !== undefined )
+ jQuery.cache[ id ][ name ] = data;
+
+ // Return the named cache data, or the ID for the element
+ return name ?
+ jQuery.cache[ id ][ name ] :
+ id;
+ },
+
+ removeData: function( elem, name ) {
+ elem = elem == window ?
+ windowData :
+ elem;
+
+ var id = elem[ expando ];
+
+ // If we want to remove a specific section of the element's data
+ if ( name ) {
+ if ( jQuery.cache[ id ] ) {
+ // Remove the section of cache data
+ delete jQuery.cache[ id ][ name ];
+
+ // If we've removed all the data, remove the element's cache
+ name = "";
+
+ for ( name in jQuery.cache[ id ] )
+ break;
+
+ if ( !name )
+ jQuery.removeData( elem );
+ }
+
+ // Otherwise, we want to remove all of the element's data
+ } else {
+ // Clean up the element expando
+ try {
+ delete elem[ expando ];
+ } catch(e){
+ // IE has trouble directly removing the expando
+ // but it's ok with using removeAttribute
+ if ( elem.removeAttribute )
+ elem.removeAttribute( expando );
+ }
+
+ // Completely remove the data cache
+ delete jQuery.cache[ id ];
+ }
+ },
+ queue: function( elem, type, data ) {
+ if ( elem ){
+
+ type = (type || "fx") + "queue";
+
+ var q = jQuery.data( elem, type );
+
+ if ( !q || jQuery.isArray(data) )
+ q = jQuery.data( elem, type, jQuery.makeArray(data) );
+ else if( data )
+ q.push( data );
+
+ }
+ return q;
+ },
+
+ dequeue: function( elem, type ){
+ var queue = jQuery.queue( elem, type ),
+ fn = queue.shift();
+
+ if( !type || type === "fx" )
+ fn = queue[0];
+
+ if( fn !== undefined )
+ fn.call(elem);
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ){
+ var parts = key.split(".");
+ parts[1] = parts[1] ? "." + parts[1] : "";
+
+ if ( value === undefined ) {
+ var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+ if ( data === undefined && this.length )
+ data = jQuery.data( this[0], key );
+
+ return data === undefined && parts[1] ?
+ this.data( parts[0] ) :
+ data;
+ } else
+ return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
+ jQuery.data( this, key, value );
+ });
+ },
+
+ removeData: function( key ){
+ return this.each(function(){
+ jQuery.removeData( this, key );
+ });
+ },
+ queue: function(type, data){
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ }
+
+ if ( data === undefined )
+ return jQuery.queue( this[0], type );
+
+ return this.each(function(){
+ var queue = jQuery.queue( this, type, data );
+
+ if( type == "fx" && queue.length == 1 )
+ queue[0].call(this);
+ });
+ },
+ dequeue: function(type){
+ return this.each(function(){
+ jQuery.dequeue( this, type );
+ });
+ }
+});/*!
+ * Sizzle CSS Selector Engine - v0.9.3
+ * Copyright 2009, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ * More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]+['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g,
+ done = 0,
+ toString = Object.prototype.toString;
+
+var Sizzle = function(selector, context, results, seed) {
+ results = results || [];
+ context = context || document;
+
+ if ( context.nodeType !== 1 && context.nodeType !== 9 )
+ return [];
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ var parts = [], m, set, checkSet, check, mode, extra, prune = true;
+
+ // Reset the position of the chunker regexp (start from head)
+ chunker.lastIndex = 0;
+
+ while ( (m = chunker.exec(selector)) !== null ) {
+ parts.push( m[1] );
+
+ if ( m[2] ) {
+ extra = RegExp.rightContext;
+ break;
+ }
+ }
+
+ if ( parts.length > 1 && origPOS.exec( selector ) ) {
+ if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+ set = posProcess( parts[0] + parts[1], context );
+ } else {
+ set = Expr.relative[ parts[0] ] ?
+ [ context ] :
+ Sizzle( parts.shift(), context );
+
+ while ( parts.length ) {
+ selector = parts.shift();
+
+ if ( Expr.relative[ selector ] )
+ selector += parts.shift();
+
+ set = posProcess( selector, set );
+ }
+ }
+ } else {
+ var ret = seed ?
+ { expr: parts.pop(), set: makeArray(seed) } :
+ Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
+ set = Sizzle.filter( ret.expr, ret.set );
+
+ if ( parts.length > 0 ) {
+ checkSet = makeArray(set);
+ } else {
+ prune = false;
+ }
+
+ while ( parts.length ) {
+ var cur = parts.pop(), pop = cur;
+
+ if ( !Expr.relative[ cur ] ) {
+ cur = "";
+ } else {
+ pop = parts.pop();
+ }
+
+ if ( pop == null ) {
+ pop = context;
+ }
+
+ Expr.relative[ cur ]( checkSet, pop, isXML(context) );
+ }
+ }
+
+ if ( !checkSet ) {
+ checkSet = set;
+ }
+
+ if ( !checkSet ) {
+ throw "Syntax error, unrecognized expression: " + (cur || selector);
+ }
+
+ if ( toString.call(checkSet) === "[object Array]" ) {
+ if ( !prune ) {
+ results.push.apply( results, checkSet );
+ } else if ( context.nodeType === 1 ) {
+ for ( var i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
+ results.push( set[i] );
+ }
+ }
+ } else {
+ for ( var i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+ results.push( set[i] );
+ }
+ }
+ }
+ } else {
+ makeArray( checkSet, results );
+ }
+
+ if ( extra ) {
+ Sizzle( extra, context, results, seed );
+ }
+
+ return results;
+};
+
+Sizzle.matches = function(expr, set){
+ return Sizzle(expr, null, null, set);
+};
+
+Sizzle.find = function(expr, context, isXML){
+ var set, match;
+
+ if ( !expr ) {
+ return [];
+ }
+
+ for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
+ var type = Expr.order[i], match;
+
+ if ( (match = Expr.match[ type ].exec( expr )) ) {
+ var left = RegExp.leftContext;
+
+ if ( left.substr( left.length - 1 ) !== "\\" ) {
+ match[1] = (match[1] || "").replace(/\\/g, "");
+ set = Expr.find[ type ]( match, context, isXML );
+ if ( set != null ) {
+ expr = expr.replace( Expr.match[ type ], "" );
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !set ) {
+ set = context.getElementsByTagName("*");
+ }
+
+ return {set: set, expr: expr};
+};
+
+Sizzle.filter = function(expr, set, inplace, not){
+ var old = expr, result = [], curLoop = set, match, anyFound;
+
+ while ( expr && set.length ) {
+ for ( var type in Expr.filter ) {
+ if ( (match = Expr.match[ type ].exec( expr )) != null ) {
+ var filter = Expr.filter[ type ], found, item;
+ anyFound = false;
+
+ if ( curLoop == result ) {
+ result = [];
+ }
+
+ if ( Expr.preFilter[ type ] ) {
+ match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not );
+
+ if ( !match ) {
+ anyFound = found = true;
+ } else if ( match === true ) {
+ continue;
+ }
+ }
+
+ if ( match ) {
+ for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
+ if ( item ) {
+ found = filter( item, match, i, curLoop );
+ var pass = not ^ !!found;
+
+ if ( inplace && found != null ) {
+ if ( pass ) {
+ anyFound = true;
+ } else {
+ curLoop[i] = false;
+ }
+ } else if ( pass ) {
+ result.push( item );
+ anyFound = true;
+ }
+ }
+ }
+ }
+
+ if ( found !== undefined ) {
+ if ( !inplace ) {
+ curLoop = result;
+ }
+
+ expr = expr.replace( Expr.match[ type ], "" );
+
+ if ( !anyFound ) {
+ return [];
+ }
+
+ break;
+ }
+ }
+ }
+
+ expr = expr.replace(/\s*,\s*/, "");
+
+ // Improper expression
+ if ( expr == old ) {
+ if ( anyFound == null ) {
+ throw "Syntax error, unrecognized expression: " + expr;
+ } else {
+ break;
+ }
+ }
+
+ old = expr;
+ }
+
+ return curLoop;
+};
+
+var Expr = Sizzle.selectors = {
+ order: [ "ID", "NAME", "TAG" ],
+ match: {
+ ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
+ CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
+ NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
+ ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
+ TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
+ CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
+ POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
+ PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
+ },
+ attrMap: {
+ "class": "className",
+ "for": "htmlFor"
+ },
+ attrHandle: {
+ href: function(elem){
+ return elem.getAttribute("href");
+ }
+ },
+ relative: {
+ "+": function(checkSet, part){
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ var cur = elem.previousSibling;
+ while ( cur && cur.nodeType !== 1 ) {
+ cur = cur.previousSibling;
+ }
+ checkSet[i] = typeof part === "string" ?
+ cur || false :
+ cur === part;
+ }
+ }
+
+ if ( typeof part === "string" ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ },
+ ">": function(checkSet, part, isXML){
+ if ( typeof part === "string" && !/\W/.test(part) ) {
+ part = isXML ? part : part.toUpperCase();
+
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ var parent = elem.parentNode;
+ checkSet[i] = parent.nodeName === part ? parent : false;
+ }
+ }
+ } else {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ checkSet[i] = typeof part === "string" ?
+ elem.parentNode :
+ elem.parentNode === part;
+ }
+ }
+
+ if ( typeof part === "string" ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ }
+ },
+ "": function(checkSet, part, isXML){
+ var doneName = "done" + (done++), checkFn = dirCheck;
+
+ if ( !part.match(/\W/) ) {
+ var nodeCheck = part = isXML ? part : part.toUpperCase();
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
+ },
+ "~": function(checkSet, part, isXML){
+ var doneName = "done" + (done++), checkFn = dirCheck;
+
+ if ( typeof part === "string" && !part.match(/\W/) ) {
+ var nodeCheck = part = isXML ? part : part.toUpperCase();
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
+ }
+ },
+ find: {
+ ID: function(match, context, isXML){
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+ return m ? [m] : [];
+ }
+ },
+ NAME: function(match, context, isXML){
+ if ( typeof context.getElementsByName !== "undefined" && !isXML ) {
+ return context.getElementsByName(match[1]);
+ }
+ },
+ TAG: function(match, context){
+ return context.getElementsByTagName(match[1]);
+ }
+ },
+ preFilter: {
+ CLASS: function(match, curLoop, inplace, result, not){
+ match = " " + match[1].replace(/\\/g, "") + " ";
+
+ var elem;
+ for ( var i = 0; (elem = curLoop[i]) != null; i++ ) {
+ if ( elem ) {
+ if ( not ^ (" " + elem.className + " ").indexOf(match) >= 0 ) {
+ if ( !inplace )
+ result.push( elem );
+ } else if ( inplace ) {
+ curLoop[i] = false;
+ }
+ }
+ }
+
+ return false;
+ },
+ ID: function(match){
+ return match[1].replace(/\\/g, "");
+ },
+ TAG: function(match, curLoop){
+ for ( var i = 0; curLoop[i] === false; i++ ){}
+ return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
+ },
+ CHILD: function(match){
+ if ( match[1] == "nth" ) {
+ // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+ var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+ match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
+ !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+ // calculate the numbers (first)n+(last) including if they are negative
+ match[2] = (test[1] + (test[2] || 1)) - 0;
+ match[3] = test[3] - 0;
+ }
+
+ // TODO: Move to normal caching system
+ match[0] = "done" + (done++);
+
+ return match;
+ },
+ ATTR: function(match){
+ var name = match[1].replace(/\\/g, "");
+
+ if ( Expr.attrMap[name] ) {
+ match[1] = Expr.attrMap[name];
+ }
+
+ if ( match[2] === "~=" ) {
+ match[4] = " " + match[4] + " ";
+ }
+
+ return match;
+ },
+ PSEUDO: function(match, curLoop, inplace, result, not){
+ if ( match[1] === "not" ) {
+ // If we're dealing with a complex expression, or a simple one
+ if ( match[3].match(chunker).length > 1 ) {
+ match[3] = Sizzle(match[3], null, null, curLoop);
+ } else {
+ var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+ if ( !inplace ) {
+ result.push.apply( result, ret );
+ }
+ return false;
+ }
+ } else if ( Expr.match.POS.test( match[0] ) ) {
+ return true;
+ }
+
+ return match;
+ },
+ POS: function(match){
+ match.unshift( true );
+ return match;
+ }
+ },
+ filters: {
+ enabled: function(elem){
+ return elem.disabled === false && elem.type !== "hidden";
+ },
+ disabled: function(elem){
+ return elem.disabled === true;
+ },
+ checked: function(elem){
+ return elem.checked === true;
+ },
+ selected: function(elem){
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ elem.parentNode.selectedIndex;
+ return elem.selected === true;
+ },
+ parent: function(elem){
+ return !!elem.firstChild;
+ },
+ empty: function(elem){
+ return !elem.firstChild;
+ },
+ has: function(elem, i, match){
+ return !!Sizzle( match[3], elem ).length;
+ },
+ header: function(elem){
+ return /h\d/i.test( elem.nodeName );
+ },
+ text: function(elem){
+ return "text" === elem.type;
+ },
+ radio: function(elem){
+ return "radio" === elem.type;
+ },
+ checkbox: function(elem){
+ return "checkbox" === elem.type;
+ },
+ file: function(elem){
+ return "file" === elem.type;
+ },
+ password: function(elem){
+ return "password" === elem.type;
+ },
+ submit: function(elem){
+ return "submit" === elem.type;
+ },
+ image: function(elem){
+ return "image" === elem.type;
+ },
+ reset: function(elem){
+ return "reset" === elem.type;
+ },
+ button: function(elem){
+ return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
+ },
+ input: function(elem){
+ return /input|select|textarea|button/i.test(elem.nodeName);
+ }
+ },
+ setFilters: {
+ first: function(elem, i){
+ return i === 0;
+ },
+ last: function(elem, i, match, array){
+ return i === array.length - 1;
+ },
+ even: function(elem, i){
+ return i % 2 === 0;
+ },
+ odd: function(elem, i){
+ return i % 2 === 1;
+ },
+ lt: function(elem, i, match){
+ return i < match[3] - 0;
+ },
+ gt: function(elem, i, match){
+ return i > match[3] - 0;
+ },
+ nth: function(elem, i, match){
+ return match[3] - 0 == i;
+ },
+ eq: function(elem, i, match){
+ return match[3] - 0 == i;
+ }
+ },
+ filter: {
+ CHILD: function(elem, match){
+ var type = match[1], parent = elem.parentNode;
+
+ var doneName = match[0];
+
+ if ( parent && (!parent[ doneName ] || !elem.nodeIndex) ) {
+ var count = 1;
+
+ for ( var node = parent.firstChild; node; node = node.nextSibling ) {
+ if ( node.nodeType == 1 ) {
+ node.nodeIndex = count++;
+ }
+ }
+
+ parent[ doneName ] = count - 1;
+ }
+
+ if ( type == "first" ) {
+ return elem.nodeIndex == 1;
+ } else if ( type == "last" ) {
+ return elem.nodeIndex == parent[ doneName ];
+ } else if ( type == "only" ) {
+ return parent[ doneName ] == 1;
+ } else if ( type == "nth" ) {
+ var add = false, first = match[2], last = match[3];
+
+ if ( first == 1 && last == 0 ) {
+ return true;
+ }
+
+ if ( first == 0 ) {
+ if ( elem.nodeIndex == last ) {
+ add = true;
+ }
+ } else if ( (elem.nodeIndex - last) % first == 0 && (elem.nodeIndex - last) / first >= 0 ) {
+ add = true;
+ }
+
+ return add;
+ }
+ },
+ PSEUDO: function(elem, match, i, array){
+ var name = match[1], filter = Expr.filters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+ } else if ( name === "contains" ) {
+ return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
+ } else if ( name === "not" ) {
+ var not = match[3];
+
+ for ( var i = 0, l = not.length; i < l; i++ ) {
+ if ( not[i] === elem ) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ },
+ ID: function(elem, match){
+ return elem.nodeType === 1 && elem.getAttribute("id") === match;
+ },
+ TAG: function(elem, match){
+ return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
+ },
+ CLASS: function(elem, match){
+ return match.test( elem.className );
+ },
+ ATTR: function(elem, match){
+ var result = Expr.attrHandle[ match[1] ] ? Expr.attrHandle[ match[1] ]( elem ) : elem[ match[1] ] || elem.getAttribute( match[1] ), value = result + "", type = match[2], check = match[4];
+ return result == null ?
+ type === "!=" :
+ type === "=" ?
+ value === check :
+ type === "*=" ?
+ value.indexOf(check) >= 0 :
+ type === "~=" ?
+ (" " + value + " ").indexOf(check) >= 0 :
+ !match[4] ?
+ result :
+ type === "!=" ?
+ value != check :
+ type === "^=" ?
+ value.indexOf(check) === 0 :
+ type === "$=" ?
+ value.substr(value.length - check.length) === check :
+ type === "|=" ?
+ value === check || value.substr(0, check.length + 1) === check + "-" :
+ false;
+ },
+ POS: function(elem, match, i, array){
+ var name = match[2], filter = Expr.setFilters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+ }
+ }
+ }
+};
+
+var origPOS = Expr.match.POS;
+
+for ( var type in Expr.match ) {
+ Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
+}
+
+var makeArray = function(array, results) {
+ array = Array.prototype.slice.call( array );
+
+ if ( results ) {
+ results.push.apply( results, array );
+ return results;
+ }
+
+ return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+try {
+ Array.prototype.slice.call( document.documentElement.childNodes );
+
+// Provide a fallback method if it does not work
+} catch(e){
+ makeArray = function(array, results) {
+ var ret = results || [];
+
+ if ( toString.call(array) === "[object Array]" ) {
+ Array.prototype.push.apply( ret, array );
+ } else {
+ if ( typeof array.length === "number" ) {
+ for ( var i = 0, l = array.length; i < l; i++ ) {
+ ret.push( array[i] );
+ }
+ } else {
+ for ( var i = 0; array[i]; i++ ) {
+ ret.push( array[i] );
+ }
+ }
+ }
+
+ return ret;
+ };
+}
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+ // We're going to inject a fake input element with a specified name
+ var form = document.createElement("form"),
+ id = "script" + (new Date).getTime();
+ form.innerHTML = "<input name='" + id + "'/>";
+
+ // Inject it into the root element, check its status, and remove it quickly
+ var root = document.documentElement;
+ root.insertBefore( form, root.firstChild );
+
+ // The workaround has to do additional checks after a getElementById
+ // Which slows things down for other browsers (hence the branching)
+ if ( !!document.getElementById( id ) ) {
+ Expr.find.ID = function(match, context, isXML){
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+ return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
+ }
+ };
+
+ Expr.filter.ID = function(elem, match){
+ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+ return elem.nodeType === 1 && node && node.nodeValue === match;
+ };
+ }
+
+ root.removeChild( form );
+})();
+
+(function(){
+ // Check to see if the browser returns only elements
+ // when doing getElementsByTagName("*")
+
+ // Create a fake element
+ var div = document.createElement("div");
+ div.appendChild( document.createComment("") );
+
+ // Make sure no comments are found
+ if ( div.getElementsByTagName("*").length > 0 ) {
+ Expr.find.TAG = function(match, context){
+ var results = context.getElementsByTagName(match[1]);
+
+ // Filter out possible comments
+ if ( match[1] === "*" ) {
+ var tmp = [];
+
+ for ( var i = 0; results[i]; i++ ) {
+ if ( results[i].nodeType === 1 ) {
+ tmp.push( results[i] );
+ }
+ }
+
+ results = tmp;
+ }
+
+ return results;
+ };
+ }
+
+ // Check to see if an attribute returns normalized href attributes
+ div.innerHTML = "<a href='#'></a>";
+ if ( div.firstChild && div.firstChild.getAttribute("href") !== "#" ) {
+ Expr.attrHandle.href = function(elem){
+ return elem.getAttribute("href", 2);
+ };
+ }
+})();
+
+if ( document.querySelectorAll ) (function(){
+ var oldSizzle = Sizzle, div = document.createElement("div");
+ div.innerHTML = "<p class='TEST'></p>";
+
+ // Safari can't handle uppercase or unicode characters when
+ // in quirks mode.
+ if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+ return;
+ }
+
+ Sizzle = function(query, context, extra, seed){
+ context = context || document;
+
+ // Only use querySelectorAll on non-XML documents
+ // (ID selectors don't work in non-HTML documents)
+ if ( !seed && context.nodeType === 9 && !isXML(context) ) {
+ try {
+ return makeArray( context.querySelectorAll(query), extra );
+ } catch(e){}
+ }
+
+ return oldSizzle(query, context, extra, seed);
+ };
+
+ Sizzle.find = oldSizzle.find;
+ Sizzle.filter = oldSizzle.filter;
+ Sizzle.selectors = oldSizzle.selectors;
+ Sizzle.matches = oldSizzle.matches;
+})();
+
+if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) {
+ Expr.order.splice(1, 0, "CLASS");
+ Expr.find.CLASS = function(match, context) {
+ return context.getElementsByClassName(match[1]);
+ };
+}
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ elem = elem[dir];
+ var match = false;
+
+ while ( elem && elem.nodeType ) {
+ var done = elem[doneName];
+ if ( done ) {
+ match = checkSet[ done ];
+ break;
+ }
+
+ if ( elem.nodeType === 1 && !isXML )
+ elem[doneName] = i;
+
+ if ( elem.nodeName === cur ) {
+ match = elem;
+ break;
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ elem = elem[dir];
+ var match = false;
+
+ while ( elem && elem.nodeType ) {
+ if ( elem[doneName] ) {
+ match = checkSet[ elem[doneName] ];
+ break;
+ }
+
+ if ( elem.nodeType === 1 ) {
+ if ( !isXML )
+ elem[doneName] = i;
+
+ if ( typeof cur !== "string" ) {
+ if ( elem === cur ) {
+ match = true;
+ break;
+ }
+
+ } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+ match = elem;
+ break;
+ }
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+var contains = document.compareDocumentPosition ? function(a, b){
+ return a.compareDocumentPosition(b) & 16;
+} : function(a, b){
+ return a !== b && (a.contains ? a.contains(b) : true);
+};
+
+var isXML = function(elem){
+ return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
+ !!elem.ownerDocument && isXML( elem.ownerDocument );
+};
+
+var posProcess = function(selector, context){
+ var tmpSet = [], later = "", match,
+ root = context.nodeType ? [context] : context;
+
+ // Position selectors must be done after the filter
+ // And so must :not(positional) so we move all PSEUDOs to the end
+ while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+ later += match[0];
+ selector = selector.replace( Expr.match.PSEUDO, "" );
+ }
+
+ selector = Expr.relative[selector] ? selector + "*" : selector;
+
+ for ( var i = 0, l = root.length; i < l; i++ ) {
+ Sizzle( selector, root[i], tmpSet );
+ }
+
+ return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+jQuery.find = Sizzle;
+jQuery.filter = Sizzle.filter;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+
+Sizzle.selectors.filters.hidden = function(elem){
+ return "hidden" === elem.type ||
+ jQuery.css(elem, "display") === "none" ||
+ jQuery.css(elem, "visibility") === "hidden";
+};
+
+Sizzle.selectors.filters.visible = function(elem){
+ return "hidden" !== elem.type &&
+ jQuery.css(elem, "display") !== "none" &&
+ jQuery.css(elem, "visibility") !== "hidden";
+};
+
+Sizzle.selectors.filters.animated = function(elem){
+ return jQuery.grep(jQuery.timers, function(fn){
+ return elem === fn.elem;
+ }).length;
+};
+
+jQuery.multiFilter = function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return Sizzle.matches(expr, elems);
+};
+
+jQuery.dir = function( elem, dir ){
+ var matched = [], cur = elem[dir];
+ while ( cur && cur != document ) {
+ if ( cur.nodeType == 1 )
+ matched.push( cur );
+ cur = cur[dir];
+ }
+ return matched;
+};
+
+jQuery.nth = function(cur, result, dir, elem){
+ result = result || 1;
+ var num = 0;
+
+ for ( ; cur; cur = cur[dir] )
+ if ( cur.nodeType == 1 && ++num == result )
+ break;
+
+ return cur;
+};
+
+jQuery.sibling = function(n, elem){
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType == 1 && n != elem )
+ r.push( n );
+ }
+
+ return r;
+};
+
+return;
+
+window.Sizzle = Sizzle;
+
+})();
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code originated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+ // Bind an event to an element
+ // Original by Dean Edwards
+ add: function(elem, types, handler, data) {
+ if ( elem.nodeType == 3 || elem.nodeType == 8 )
+ return;
+
+ // For whatever reason, IE has trouble passing the window object
+ // around, causing it to be cloned in the process
+ if ( elem.setInterval && elem != window )
+ elem = window;
+
+ // Make sure that the function being executed has a unique ID
+ if ( !handler.guid )
+ handler.guid = this.guid++;
+
+ // if data is passed, bind to handler
+ if ( data !== undefined ) {
+ // Create temporary function pointer to original handler
+ var fn = handler;
+
+ // Create unique handler function, wrapped around original handler
+ handler = this.proxy( fn );
+
+ // Store data in unique handler
+ handler.data = data;
+ }
+
+ // Init the element's event structure
+ var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
+ handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
+ // Handle the second event of a trigger and when
+ // an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
+ jQuery.event.handle.apply(arguments.callee.elem, arguments) :
+ undefined;
+ });
+ // Add elem as a property of the handle function
+ // This is to prevent a memory leak with non-native
+ // event in IE.
+ handle.elem = elem;
+
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ jQuery.each(types.split(/\s+/), function(index, type) {
+ // Namespaced event handlers
+ var namespaces = type.split(".");
+ type = namespaces.shift();
+ handler.type = namespaces.slice().sort().join(".");
+
+ // Get the current list of functions bound to this event
+ var handlers = events[type];
+
+ if ( jQuery.event.specialAll[type] )
+ jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
+
+ // Init the event handler queue
+ if (!handlers) {
+ handlers = events[type] = {};
+
+ // Check for a special event handler
+ // Only use addEventListener/attachEvent if the special
+ // events handler returns false
+ if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
+ // Bind the global event handler to the element
+ if (elem.addEventListener)
+ elem.addEventListener(type, handle, false);
+ else if (elem.attachEvent)
+ elem.attachEvent("on" + type, handle);
+ }
+ }
+
+ // Add the function to the element's handler list
+ handlers[handler.guid] = handler;
+
+ // Keep track of which events have been used, for global triggering
+ jQuery.event.global[type] = true;
+ });
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ guid: 1,
+ global: {},
+
+ // Detach an event or set of events from an element
+ remove: function(elem, types, handler) {
+ // don't do events on text and comment nodes
+ if ( elem.nodeType == 3 || elem.nodeType == 8 )
+ return;
+
+ var events = jQuery.data(elem, "events"), ret, index;
+
+ if ( events ) {
+ // Unbind all events for the element
+ if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
+ for ( var type in events )
+ this.remove( elem, type + (types || "") );
+ else {
+ // types is actually an event object here
+ if ( types.type ) {
+ handler = types.handler;
+ types = types.type;
+ }
+
+ // Handle multiple events seperated by a space
+ // jQuery(...).unbind("mouseover mouseout", fn);
+ jQuery.each(types.split(/\s+/), function(index, type){
+ // Namespaced event handlers
+ var namespaces = type.split(".");
+ type = namespaces.shift();
+ var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+
+ if ( events[type] ) {
+ // remove the given handler for the given type
+ if ( handler )
+ delete events[type][handler.guid];
+
+ // remove all handlers for the given type
+ else
+ for ( var handle in events[type] )
+ // Handle the removal of namespaced events
+ if ( namespace.test(events[type][handle].type) )
+ delete events[type][handle];
+
+ if ( jQuery.event.specialAll[type] )
+ jQuery.event.specialAll[type].teardown.call(elem, namespaces);
+
+ // remove generic event handler if no more handlers exist
+ for ( ret in events[type] ) break;
+ if ( !ret ) {
+ if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
+ if (elem.removeEventListener)
+ elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
+ else if (elem.detachEvent)
+ elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
+ }
+ ret = null;
+ delete events[type];
+ }
+ }
+ });
+ }
+
+ // Remove the expando if it's no longer used
+ for ( ret in events ) break;
+ if ( !ret ) {
+ var handle = jQuery.data( elem, "handle" );
+ if ( handle ) handle.elem = null;
+ jQuery.removeData( elem, "events" );
+ jQuery.removeData( elem, "handle" );
+ }
+ }
+ },
+
+ // bubbling is internal
+ trigger: function( event, data, elem, bubbling ) {
+ // Event object or event type
+ var type = event.type || event;
+
+ if( !bubbling ){
+ event = typeof event === "object" ?
+ // jQuery.Event object
+ event[expando] ? event :
+ // Object literal
+ jQuery.extend( jQuery.Event(type), event ) :
+ // Just the event type (string)
+ jQuery.Event(type);
+
+ if ( type.indexOf("!") >= 0 ) {
+ event.type = type = type.slice(0, -1);
+ event.exclusive = true;
+ }
+
+ // Handle a global trigger
+ if ( !elem ) {
+ // Don't bubble custom events when global (to avoid too much overhead)
+ event.stopPropagation();
+ // Only trigger if we've ever bound an event for it
+ if ( this.global[type] )
+ jQuery.each( jQuery.cache, function(){
+ if ( this.events && this.events[type] )
+ jQuery.event.trigger( event, data, this.handle.elem );
+ });
+ }
+
+ // Handle triggering a single element
+
+ // don't do events on text and comment nodes
+ if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
+ return undefined;
+
+ // Clean up in case it is reused
+ event.result = undefined;
+ event.target = elem;
+
+ // Clone the incoming data, if any
+ data = jQuery.makeArray(data);
+ data.unshift( event );
+ }
+
+ event.currentTarget = elem;
+
+ // Trigger the event, it is assumed that "handle" is a function
+ var handle = jQuery.data(elem, "handle");
+ if ( handle )
+ handle.apply( elem, data );
+
+ // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
+ if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
+ event.result = false;
+
+ // Trigger the native events (except for clicks on links)
+ if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
+ this.triggered = true;
+ try {
+ elem[ type ]();
+ // prevent IE from throwing an error for some hidden elements
+ } catch (e) {}
+ }
+
+ this.triggered = false;
+
+ if ( !event.isPropagationStopped() ) {
+ var parent = elem.parentNode || elem.ownerDocument;
+ if ( parent )
+ jQuery.event.trigger(event, data, parent, true);
+ }
+ },
+
+ handle: function(event) {
+ // returned undefined or false
+ var all, handlers;
+
+ event = arguments[0] = jQuery.event.fix( event || window.event );
+
+ // Namespaced event handlers
+ var namespaces = event.type.split(".");
+ event.type = namespaces.shift();
+
+ // Cache this now, all = true means, any handler
+ all = !namespaces.length && !event.exclusive;
+
+ var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+
+ handlers = ( jQuery.data(this, "events") || {} )[event.type];
+
+ for ( var j in handlers ) {
+ var handler = handlers[j];
+
+ // Filter the functions by class
+ if ( all || namespace.test(handler.type) ) {
+ // Pass in a reference to the handler function itself
+ // So that we can later remove it
+ event.handler = handler;
+ event.data = handler.data;
+
+ var ret = handler.apply(this, arguments);
+
+ if( ret !== undefined ){
+ event.result = ret;
+ if ( ret === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+
+ if( event.isImmediatePropagationStopped() )
+ break;
+
+ }
+ }
+ },
+
+ props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+
+ fix: function(event) {
+ if ( event[expando] )
+ return event;
+
+ // store a copy of the original event object
+ // and "clone" to set read-only properties
+ var originalEvent = event;
+ event = jQuery.Event( originalEvent );
+
+ for ( var i = this.props.length, prop; i; ){
+ prop = this.props[ --i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Fix target property, if necessary
+ if ( !event.target )
+ event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+
+ // check if target is a textnode (safari)
+ if ( event.target.nodeType == 3 )
+ event.target = event.target.parentNode;
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && event.fromElement )
+ event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && event.clientX != null ) {
+ var doc = document.documentElement, body = document.body;
+ event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
+ event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
+ }
+
+ // Add which for key events
+ if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
+ event.which = event.charCode || event.keyCode;
+
+ // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+ if ( !event.metaKey && event.ctrlKey )
+ event.metaKey = event.ctrlKey;
+
+ // Add which for click: 1 == left; 2 == middle; 3 == right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && event.button )
+ event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+
+ return event;
+ },
+
+ proxy: function( fn, proxy ){
+ proxy = proxy || function(){ return fn.apply(this, arguments); };
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
+ // So proxy can be declared as an argument
+ return proxy;
+ },
+
+ special: {
+ ready: {
+ // Make sure the ready event is setup
+ setup: bindReady,
+ teardown: function() {}
+ }
+ },
+
+ specialAll: {
+ live: {
+ setup: function( selector, namespaces ){
+ jQuery.event.add( this, namespaces[0], liveHandler );
+ },
+ teardown: function( namespaces ){
+ if ( namespaces.length ) {
+ var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
+
+ jQuery.each( (jQuery.data(this, "events").live || {}), function(){
+ if ( name.test(this.type) )
+ remove++;
+ });
+
+ if ( remove < 1 )
+ jQuery.event.remove( this, namespaces[0], liveHandler );
+ }
+ }
+ }
+ }
+};
+
+jQuery.Event = function( src ){
+ // Allow instantiation without the 'new' keyword
+ if( !this.preventDefault )
+ return new jQuery.Event(src);
+
+ // Event object
+ if( src && src.type ){
+ this.originalEvent = src;
+ this.type = src.type;
+ // Event type
+ }else
+ this.type = src;
+
+ // timeStamp is buggy for some events on Firefox(#3843)
+ // So we won't rely on the native value
+ this.timeStamp = now();
+
+ // Mark it as fixed
+ this[expando] = true;
+};
+
+function returnFalse(){
+ return false;
+}
+function returnTrue(){
+ return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-bind...
+jQuery.Event.prototype = {
+ preventDefault: function() {
+ this.isDefaultPrevented = returnTrue;
+
+ var e = this.originalEvent;
+ if( !e )
+ return;
+ // if preventDefault exists run it on the original event
+ if (e.preventDefault)
+ e.preventDefault();
+ // otherwise set the returnValue property of the original event to false (IE)
+ e.returnValue = false;
+ },
+ stopPropagation: function() {
+ this.isPropagationStopped = returnTrue;
+
+ var e = this.originalEvent;
+ if( !e )
+ return;
+ // if stopPropagation exists run it on the original event
+ if (e.stopPropagation)
+ e.stopPropagation();
+ // otherwise set the cancelBubble property of the original event to true (IE)
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation:function(){
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ },
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse
+};
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function(event) {
+ // Check if mouse(over|out) are still within the same parent element
+ var parent = event.relatedTarget;
+ // Traverse up the tree
+ while ( parent && parent != this )
+ try { parent = parent.parentNode; }
+ catch(e) { parent = this; }
+
+ if( parent != this ){
+ // set the correct event type
+ event.type = event.data;
+ // handle event if we actually just moused on to a non sub-element
+ jQuery.event.handle.apply( this, arguments );
+ }
+};
+
+jQuery.each({
+ mouseover: 'mouseenter',
+ mouseout: 'mouseleave'
+}, function( orig, fix ){
+ jQuery.event.special[ fix ] = {
+ setup: function(){
+ jQuery.event.add( this, orig, withinElement, fix );
+ },
+ teardown: function(){
+ jQuery.event.remove( this, orig, withinElement );
+ }
+ };
+});
+
+jQuery.fn.extend({
+ bind: function( type, data, fn ) {
+ return type == "unload" ? this.one(type, data, fn) : this.each(function(){
+ jQuery.event.add( this, type, fn || data, fn && data );
+ });
+ },
+
+ one: function( type, data, fn ) {
+ var one = jQuery.event.proxy( fn || data, function(event) {
+ jQuery(this).unbind(event, one);
+ return (fn || data).apply( this, arguments );
+ });
+ return this.each(function(){
+ jQuery.event.add( this, type, one, fn && data);
+ });
+ },
+
+ unbind: function( type, fn ) {
+ return this.each(function(){
+ jQuery.event.remove( this, type, fn );
+ });
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function(){
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+
+ triggerHandler: function( type, data ) {
+ if( this[0] ){
+ var event = jQuery.Event(type);
+ event.preventDefault();
+ event.stopPropagation();
+ jQuery.event.trigger( event, data, this[0] );
+ return event.result;
+ }
+ },
+
+ toggle: function( fn ) {
+ // Save reference to arguments for access in closure
+ var args = arguments, i = 1;
+
+ // link all the functions, so any of them can unbind this click handler
+ while( i < args.length )
+ jQuery.event.proxy( fn, args[i++] );
+
+ return this.click( jQuery.event.proxy( fn, function(event) {
+ // Figure out which function to execute
+ this.lastToggle = ( this.lastToggle || 0 ) % i;
+
+ // Make sure that clicks stop
+ event.preventDefault();
+
+ // and execute the function
+ return args[ this.lastToggle++ ].apply( this, arguments ) || false;
+ }));
+ },
+
+ hover: function(fnOver, fnOut) {
+ return this.mouseenter(fnOver).mouseleave(fnOut);
+ },
+
+ ready: function(fn) {
+ // Attach the listeners
+ bindReady();
+
+ // If the DOM is already ready
+ if ( jQuery.isReady )
+ // Execute the function immediately
+ fn.call( document, jQuery );
+
+ // Otherwise, remember the function for later
+ else
+ // Add the function to the wait list
+ jQuery.readyList.push( fn );
+
+ return this;
+ },
+
+ live: function( type, fn ){
+ var proxy = jQuery.event.proxy( fn );
+ proxy.guid += this.selector + type;
+
+ jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
+
+ return this;
+ },
+
+ die: function( type, fn ){
+ jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
+ return this;
+ }
+});
+
+function liveHandler( event ){
+ var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
+ stop = true,
+ elems = [];
+
+ jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
+ if ( check.test(fn.type) ) {
+ var elem = jQuery(event.target).closest(fn.data)[0];
+ if ( elem )
+ elems.push({ elem: elem, fn: fn });
+ }
+ });
+
+ jQuery.each(elems, function(){
+ if ( this.fn.call(this.elem, event, this.fn.data) === false )
+ stop = false;
+ });
+
+ return stop;
+}
+
+function liveConvert(type, selector){
+ return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
+}
+
+jQuery.extend({
+ isReady: false,
+ readyList: [],
+ // Handle when the DOM is ready
+ ready: function() {
+ // Make sure that the DOM is not already loaded
+ if ( !jQuery.isReady ) {
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If there are functions bound, to execute
+ if ( jQuery.readyList ) {
+ // Execute all of them
+ jQuery.each( jQuery.readyList, function(){
+ this.call( document, jQuery );
+ });
+
+ // Reset the list of functions
+ jQuery.readyList = null;
+ }
+
+ // Trigger any bound ready events
+ jQuery(document).triggerHandler("ready");
+ }
+ }
+});
+
+var readyBound = false;
+
+function bindReady(){
+ if ( readyBound ) return;
+ readyBound = true;
+
+ // Mozilla, Opera and webkit nightlies currently support this event
+ if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", function(){
+ document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
+ jQuery.ready();
+ }, false );
+
+ // If IE event model is used
+ } else if ( document.attachEvent ) {
+ // ensure firing before onload,
+ // maybe late but safe also for iframes
+ document.attachEvent("onreadystatechange", function(){
+ if ( document.readyState === "complete" ) {
+ document.detachEvent( "onreadystatechange", arguments.callee );
+ jQuery.ready();
+ }
+ });
+
+ // If IE and not an iframe
+ // continually check to see if the document is ready
+ if ( document.documentElement.doScroll && typeof window.frameElement === "undefined" ) (function(){
+ if ( jQuery.isReady ) return;
+
+ try {
+ // If IE is used, use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ document.documentElement.doScroll("left");
+ } catch( error ) {
+ setTimeout( arguments.callee, 0 );
+ return;
+ }
+
+ // and execute any waiting functions
+ jQuery.ready();
+ })();
+ }
+
+ // A fallback to window.onload, that will always work
+ jQuery.event.add( window, "load", jQuery.ready );
+}
+
+jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
+ "mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
+ "change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
+
+ // Handle event binding
+ jQuery.fn[name] = function(fn){
+ return fn ? this.bind(name, fn) : this.trigger(name);
+ };
+});
+
+// Prevent memory leaks in IE
+// And prevent errors on refresh with events like mouseover in other browsers
+// Window isn't included so as not to unbind existing unload events
+jQuery( window ).bind( 'unload', function(){
+ for ( var id in jQuery.cache )
+ // Skip the window
+ if ( id != 1 && jQuery.cache[ id ].handle )
+ jQuery.event.remove( jQuery.cache[ id ].handle.elem );
+});
+(function(){
+
+ jQuery.support = {};
+
+ var root = document.documentElement,
+ script = document.createElement("script"),
+ div = document.createElement("div"),
+ id = "script" + (new Date).getTime();
+
+ div.style.display = "none";
+ div.innerHTML = ' <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';
+
+ var all = div.getElementsByTagName("*"),
+ a = div.getElementsByTagName("a")[0];
+
+ // Can't get basic test support
+ if ( !all || !all.length || !a ) {
+ return;
+ }
+
+ jQuery.support = {
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: div.firstChild.nodeType == 3,
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName("tbody").length,
+
+ // Make sure that you can get all elements in an <object> element
+ // IE 7 always returns no results
+ objectAll: !!div.getElementsByTagName("object")[0]
+ .getElementsByTagName("*").length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName("link").length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText insted)
+ style: /red/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: a.getAttribute("href") === "/a",
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ opacity: a.style.opacity === "0.5",
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Will be defined later
+ scriptEval: false,
+ noCloneEvent: true,
+ boxModel: null
+ };
+
+ script.type = "text/javascript";
+ try {
+ script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
+ } catch(e){}
+
+ root.insertBefore( script, root.firstChild );
+
+ // Make sure that the execution of code works by injecting a script
+ // tag with appendChild/createTextNode
+ // (IE doesn't support this, fails, and uses .text instead)
+ if ( window[ id ] ) {
+ jQuery.support.scriptEval = true;
+ delete window[ id ];
+ }
+
+ root.removeChild( script );
+
+ if ( div.attachEvent && div.fireEvent ) {
+ div.attachEvent("onclick", function(){
+ // Cloning a node shouldn't copy over any
+ // bound event handlers (IE does this)
+ jQuery.support.noCloneEvent = false;
+ div.detachEvent("onclick", arguments.callee);
+ });
+ div.cloneNode(true).fireEvent("onclick");
+ }
+
+ // Figure out if the W3C box model works as expected
+ // document.body must exist before we can do this
+ jQuery(function(){
+ var div = document.createElement("div");
+ div.style.width = "1px";
+ div.style.paddingLeft = "1px";
+
+ document.body.appendChild( div );
+ jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
+ document.body.removeChild( div );
+ });
+})();
+
+var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
+
+jQuery.props = {
+ "for": "htmlFor",
+ "class": "className",
+ "float": styleFloat,
+ cssFloat: styleFloat,
+ styleFloat: styleFloat,
+ readonly: "readOnly",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ rowspan: "rowSpan",
+ tabindex: "tabIndex"
+};
+jQuery.fn.extend({
+ // Keep a copy of the old load
+ _load: jQuery.fn.load,
+
+ load: function( url, params, callback ) {
+ if ( typeof url !== "string" )
+ return this._load( url );
+
+ var off = url.indexOf(" ");
+ if ( off >= 0 ) {
+ var selector = url.slice(off, url.length);
+ url = url.slice(0, off);
+ }
+
+ // Default to a GET request
+ var type = "GET";
+
+ // If the second parameter was provided
+ if ( params )
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+ // We assume that it's the callback
+ callback = params;
+ params = null;
+
+ // Otherwise, build a param string
+ } else if( typeof params === "object" ) {
+ params = jQuery.param( params );
+ type = "POST";
+ }
+
+ var self = this;
+
+ // Request the remote document
+ jQuery.ajax({
+ url: url,
+ type: type,
+ dataType: "html",
+ data: params,
+ complete: function(res, status){
+ // If successful, inject the HTML into all the matched elements
+ if ( status == "success" || status == "notmodified" )
+ // See if a selector was specified
+ self.html( selector ?
+ // Create a dummy div to hold the results
+ jQuery("<div/>")
+ // inject the contents of the document in, removing the scripts
+ // to avoid any 'Permission Denied' errors in IE
+ .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
+
+ // Locate the specified elements
+ .find(selector) :
+
+ // If not, just inject the full result
+ res.responseText );
+
+ if( callback )
+ self.each( callback, [res.responseText, status, res] );
+ }
+ });
+ return this;
+ },
+
+ serialize: function() {
+ return jQuery.param(this.serializeArray());
+ },
+ serializeArray: function() {
+ return this.map(function(){
+ return this.elements ? jQuery.makeArray(this.elements) : this;
+ })
+ .filter(function(){
+ return this.name && !this.disabled &&
+ (this.checked || /select|textarea/i.test(this.nodeName) ||
+ /text|hidden|password/i.test(this.type));
+ })
+ .map(function(i, elem){
+ var val = jQuery(this).val();
+ return val == null ? null :
+ jQuery.isArray(val) ?
+ jQuery.map( val, function(val, i){
+ return {name: elem.name, value: val};
+ }) :
+ {name: elem.name, value: val};
+ }).get();
+ }
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
+ jQuery.fn[o] = function(f){
+ return this.bind(o, f);
+ };
+});
+
+var jsc = now();
+
+jQuery.extend({
+
+ get: function( url, data, callback, type ) {
+ // shift arguments if data argument was ommited
+ if ( jQuery.isFunction( data ) ) {
+ callback = data;
+ data = null;
+ }
+
+ return jQuery.ajax({
+ type: "GET",
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get(url, null, callback, "script");
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get(url, data, callback, "json");
+ },
+
+ post: function( url, data, callback, type ) {
+ if ( jQuery.isFunction( data ) ) {
+ callback = data;
+ data = {};
+ }
+
+ return jQuery.ajax({
+ type: "POST",
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ },
+
+ ajaxSetup: function( settings ) {
+ jQuery.extend( jQuery.ajaxSettings, settings );
+ },
+
+ ajaxSettings: {
+ url: location.href,
+ global: true,
+ type: "GET",
+ contentType: "application/x-www-form-urlencoded",
+ processData: true,
+ async: true,
+ /*
+ timeout: 0,
+ data: null,
+ username: null,
+ password: null,
+ */
+ // Create the request object; Microsoft failed to properly
+ // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
+ // This function can be overriden by calling jQuery.ajaxSetup
+ xhr:function(){
+ return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
+ },
+ accepts: {
+ xml: "application/xml, text/xml",
+ html: "text/html",
+ script: "text/javascript, application/javascript",
+ json: "application/json, text/javascript",
+ text: "text/plain",
+ _default: "*/*"
+ }
+ },
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+
+ ajax: function( s ) {
+ // Extend the settings, but re-extend 's' so that it can be
+ // checked again later (in the test suite, specifically)
+ s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
+
+ var jsonp, jsre = /=\?(&|$)/g, status, data,
+ type = s.type.toUpperCase();
+
+ // convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" )
+ s.data = jQuery.param(s.data);
+
+ // Handle JSONP Parameter Callbacks
+ if ( s.dataType == "jsonp" ) {
+ if ( type == "GET" ) {
+ if ( !s.url.match(jsre) )
+ s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+ } else if ( !s.data || !s.data.match(jsre) )
+ s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+ s.dataType = "json";
+ }
+
+ // Build temporary JSONP function
+ if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
+ jsonp = "jsonp" + jsc++;
+
+ // Replace the =? sequence both in the query string and the data
+ if ( s.data )
+ s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+ s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+ // We need to make sure
+ // that a JSONP style response is executed properly
+ s.dataType = "script";
+
+ // Handle JSONP-style loading
+ window[ jsonp ] = function(tmp){
+ data = tmp;
+ success();
+ complete();
+ // Garbage collect
+ window[ jsonp ] = undefined;
+ try{ delete window[ jsonp ]; } catch(e){}
+ if ( head )
+ head.removeChild( script );
+ };
+ }
+
+ if ( s.dataType == "script" && s.cache == null )
+ s.cache = false;
+
+ if ( s.cache === false && type == "GET" ) {
+ var ts = now();
+ // try replacing _= if it is there
+ var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
+ // if nothing was replaced, add timestamp to the end
+ s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
+ }
+
+ // If data is available, append data to url for get requests
+ if ( s.data && type == "GET" ) {
+ s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
+
+ // IE likes to send both get and post data, prevent this
+ s.data = null;
+ }
+
+ // Watch for a new set of requests
+ if ( s.global && ! jQuery.active++ )
+ jQuery.event.trigger( "ajaxStart" );
+
+ // Matches an absolute URL, and saves the domain
+ var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
+
+ // If we're requesting a remote document
+ // and trying to load JSON or Script with a GET
+ if ( s.dataType == "script" && type == "GET" && parts
+ && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
+
+ var head = document.getElementsByTagName("head")[0];
+ var script = document.createElement("script");
+ script.src = s.url;
+ if (s.scriptCharset)
+ script.charset = s.scriptCharset;
+
+ // Handle Script loading
+ if ( !jsonp ) {
+ var done = false;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function(){
+ if ( !done && (!this.readyState ||
+ this.readyState == "loaded" || this.readyState == "complete") ) {
+ done = true;
+ success();
+ complete();
+ head.removeChild( script );
+ }
+ };
+ }
+
+ head.appendChild(script);
+
+ // We handle everything using the script element injection
+ return undefined;
+ }
+
+ var requestDone = false;
+
+ // Create the request object
+ var xhr = s.xhr();
+
+ // Open the socket
+ // Passing null username, generates a login popup on Opera (#2865)
+ if( s.username )
+ xhr.open(type, s.url, s.async, s.username, s.password);
+ else
+ xhr.open(type, s.url, s.async);
+
+ // Need an extra try/catch for cross domain requests in Firefox 3
+ try {
+ // Set the correct header, if data is being sent
+ if ( s.data )
+ xhr.setRequestHeader("Content-Type", s.contentType);
+
+ // Set the If-Modified-Since header, if ifModified mode.
+ if ( s.ifModified )
+ xhr.setRequestHeader("If-Modified-Since",
+ jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
+
+ // Set header so the called script knows that it's an XMLHttpRequest
+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+
+ // Set the Accepts header for the server, depending on the dataType
+ xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
+ s.accepts[ s.dataType ] + ", */*" :
+ s.accepts._default );
+ } catch(e){}
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
+ // Handle the global AJAX counter
+ if ( s.global && ! --jQuery.active )
+ jQuery.event.trigger( "ajaxStop" );
+ // close opended socket
+ xhr.abort();
+ return false;
+ }
+
+ if ( s.global )
+ jQuery.event.trigger("ajaxSend", [xhr, s]);
+
+ // Wait for a response to come back
+ var onreadystatechange = function(isTimeout){
+ // The request was aborted, clear the interval and decrement jQuery.active
+ if (xhr.readyState == 0) {
+ if (ival) {
+ // clear poll interval
+ clearInterval(ival);
+ ival = null;
+ // Handle the global AJAX counter
+ if ( s.global && ! --jQuery.active )
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ // The transfer is complete and the data is available, or the request timed out
+ } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
+ requestDone = true;
+
+ // clear poll interval
+ if (ival) {
+ clearInterval(ival);
+ ival = null;
+ }
+
+ status = isTimeout == "timeout" ? "timeout" :
+ !jQuery.httpSuccess( xhr ) ? "error" :
+ s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
+ "success";
+
+ if ( status == "success" ) {
+ // Watch for, and catch, XML document parse errors
+ try {
+ // process the data (runs the xml through httpData regardless of callback)
+ data = jQuery.httpData( xhr, s.dataType, s );
+ } catch(e) {
+ status = "parsererror";
+ }
+ }
+
+ // Make sure that the request was successful or notmodified
+ if ( status == "success" ) {
+ // Cache Last-Modified header, if ifModified mode.
+ var modRes;
+ try {
+ modRes = xhr.getResponseHeader("Last-Modified");
+ } catch(e) {} // swallow exception thrown by FF if header is not available
+
+ if ( s.ifModified && modRes )
+ jQuery.lastModified[s.url] = modRes;
+
+ // JSONP handles its own success callback
+ if ( !jsonp )
+ success();
+ } else
+ jQuery.handleError(s, xhr, status);
+
+ // Fire the complete handlers
+ complete();
+
+ if ( isTimeout )
+ xhr.abort();
+
+ // Stop memory leaks
+ if ( s.async )
+ xhr = null;
+ }
+ };
+
+ if ( s.async ) {
+ // don't attach the handler to the request, just poll it instead
+ var ival = setInterval(onreadystatechange, 13);
+
+ // Timeout checker
+ if ( s.timeout > 0 )
+ setTimeout(function(){
+ // Check to see if the request is still happening
+ if ( xhr && !requestDone )
+ onreadystatechange( "timeout" );
+ }, s.timeout);
+ }
+
+ // Send the data
+ try {
+ xhr.send(s.data);
+ } catch(e) {
+ jQuery.handleError(s, xhr, null, e);
+ }
+
+ // firefox 1.5 doesn't fire statechange for sync requests
+ if ( !s.async )
+ onreadystatechange();
+
+ function success(){
+ // If a local callback was specified, fire it and pass it the data
+ if ( s.success )
+ s.success( data, status );
+
+ // Fire the global callback
+ if ( s.global )
+ jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
+ }
+
+ function complete(){
+ // Process result
+ if ( s.complete )
+ s.complete(xhr, status);
+
+ // The request was completed
+ if ( s.global )
+ jQuery.event.trigger( "ajaxComplete", [xhr, s] );
+
+ // Handle the global AJAX counter
+ if ( s.global && ! --jQuery.active )
+ jQuery.event.trigger( "ajaxStop" );
+ }
+
+ // return XMLHttpRequest to allow aborting the request etc.
+ return xhr;
+ },
+
+ handleError: function( s, xhr, status, e ) {
+ // If a local callback was specified, fire it
+ if ( s.error ) s.error( xhr, status, e );
+
+ // Fire the global callback
+ if ( s.global )
+ jQuery.event.trigger( "ajaxError", [xhr, s, e] );
+ },
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Determines if an XMLHttpRequest was successful or not
+ httpSuccess: function( xhr ) {
+ try {
+ // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+ return !xhr.status && location.protocol == "file:" ||
+ ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
+ } catch(e){}
+ return false;
+ },
+
+ // Determines if an XMLHttpRequest returns NotModified
+ httpNotModified: function( xhr, url ) {
+ try {
+ var xhrRes = xhr.getResponseHeader("Last-Modified");
+
+ // Firefox always returns 200. check Last-Modified date
+ return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
+ } catch(e){}
+ return false;
+ },
+
+ httpData: function( xhr, type, s ) {
+ var ct = xhr.getResponseHeader("content-type"),
+ xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
+ data = xml ? xhr.responseXML : xhr.responseText;
+
+ if ( xml && data.documentElement.tagName == "parsererror" )
+ throw "parsererror";
+
+ // Allow a pre-filtering function to sanitize the response
+ // s != null is checked to keep backwards compatibility
+ if( s && s.dataFilter )
+ data = s.dataFilter( data, type );
+
+ // The filter can actually parse the response
+ if( typeof data === "string" ){
+
+ // If the type is "script", eval it in global context
+ if ( type == "script" )
+ jQuery.globalEval( data );
+
+ // Get the JavaScript object, if JSON is used.
+ if ( type == "json" )
+ data = window["eval"]("(" + data + ")");
+ }
+
+ return data;
+ },
+
+ // Serialize an array of form elements or a set of
+ // key/values into a query string
+ param: function( a ) {
+ var s = [ ];
+
+ function add( key, value ){
+ s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
+ };
+
+ // If an array was passed in, assume that it is an array
+ // of form elements
+ if ( jQuery.isArray(a) || a.jquery )
+ // Serialize the form elements
+ jQuery.each( a, function(){
+ add( this.name, this.value );
+ });
+
+ // Otherwise, assume that it's an object of key/value pairs
+ else
+ // Serialize the key/values
+ for ( var j in a )
+ // If the value is an array then the key names need to be repeated
+ if ( jQuery.isArray(a[j]) )
+ jQuery.each( a[j], function(){
+ add( j, this );
+ });
+ else
+ add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
+
+ // Return the resulting serialization
+ return s.join("&").replace(/%20/g, "+");
+ }
+
+});
+var elemdisplay = {},
+ timerId,
+ fxAttrs = [
+ // height animations
+ [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+ // width animations
+ [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+ // opacity animations
+ [ "opacity" ]
+ ];
+
+function genFx( type, num ){
+ var obj = {};
+ jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
+ obj[ this ] = type;
+ });
+ return obj;
+}
+
+jQuery.fn.extend({
+ show: function(speed,callback){
+ if ( speed ) {
+ return this.animate( genFx("show", 3), speed, callback);
+ } else {
+ for ( var i = 0, l = this.length; i < l; i++ ){
+ var old = jQuery.data(this[i], "olddisplay");
+
+ this[i].style.display = old || "";
+
+ if ( jQuery.css(this[i], "display") === "none" ) {
+ var tagName = this[i].tagName, display;
+
+ if ( elemdisplay[ tagName ] ) {
+ display = elemdisplay[ tagName ];
+ } else {
+ var elem = jQuery("<" + tagName + " />").appendTo("body");
+
+ display = elem.css("display");
+ if ( display === "none" )
+ display = "block";
+
+ elem.remove();
+
+ elemdisplay[ tagName ] = display;
+ }
+
+ this[i].style.display = jQuery.data(this[i], "olddisplay", display);
+ }
+ }
+
+ return this;
+ }
+ },
+
+ hide: function(speed,callback){
+ if ( speed ) {
+ return this.animate( genFx("hide", 3), speed, callback);
+ } else {
+ for ( var i = 0, l = this.length; i < l; i++ ){
+ var old = jQuery.data(this[i], "olddisplay");
+ if ( !old && old !== "none" )
+ jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
+ this[i].style.display = "none";
+ }
+ return this;
+ }
+ },
+
+ // Save the old toggle function
+ _toggle: jQuery.fn.toggle,
+
+ toggle: function( fn, fn2 ){
+ var bool = typeof fn === "boolean";
+
+ return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
+ this._toggle.apply( this, arguments ) :
+ fn == null || bool ?
+ this.each(function(){
+ var state = bool ? fn : jQuery(this).is(":hidden");
+ jQuery(this)[ state ? "show" : "hide" ]();
+ }) :
+ this.animate(genFx("toggle", 3), fn, fn2);
+ },
+
+ fadeTo: function(speed,to,callback){
+ return this.animate({opacity: to}, speed, callback);
+ },
+
+ animate: function( prop, speed, easing, callback ) {
+ var optall = jQuery.speed(speed, easing, callback);
+
+ return this[ optall.queue === false ? "each" : "queue" ](function(){
+
+ var opt = jQuery.extend({}, optall), p,
+ hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
+ self = this;
+
+ for ( p in prop ) {
+ if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
+ return opt.complete.call(this);
+
+ if ( ( p == "height" || p == "width" ) && this.style ) {
+ // Store display property
+ opt.display = jQuery.css(this, "display");
+
+ // Make sure that nothing sneaks out
+ opt.overflow = this.style.overflow;
+ }
+ }
+
+ if ( opt.overflow != null )
+ this.style.overflow = "hidden";
+
+ opt.curAnim = jQuery.extend({}, prop);
+
+ jQuery.each( prop, function(name, val){
+ var e = new jQuery.fx( self, opt, name );
+
+ if ( /toggle|show|hide/.test(val) )
+ e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+ else {
+ var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
+ start = e.cur(true) || 0;
+
+ if ( parts ) {
+ var end = parseFloat(parts[2]),
+ unit = parts[3] || "px";
+
+ // We need to compute starting value
+ if ( unit != "px" ) {
+ self.style[ name ] = (end || 1) + unit;
+ start = ((end || 1) / e.cur(true)) * start;
+ self.style[ name ] = start + unit;
+ }
+
+ // If a +=/-= token was provided, we're doing a relative animation
+ if ( parts[1] )
+ end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
+
+ e.custom( start, end, unit );
+ } else
+ e.custom( start, val, "" );
+ }
+ });
+
+ // For JS strict compliance
+ return true;
+ });
+ },
+
+ stop: function(clearQueue, gotoEnd){
+ var timers = jQuery.timers;
+
+ if (clearQueue)
+ this.queue([]);
+
+ this.each(function(){
+ // go in reverse order so anything added to the queue during the loop is ignored
+ for ( var i = timers.length - 1; i >= 0; i-- )
+ if ( timers[i].elem == this ) {
+ if (gotoEnd)
+ // force the next step to be the last
+ timers[i](true);
+ timers.splice(i, 1);
+ }
+ });
+
+ // start the next in the queue if the last step wasn't forced
+ if (!gotoEnd)
+ this.dequeue();
+
+ return this;
+ }
+
+});
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx("show", 1),
+ slideUp: genFx("hide", 1),
+ slideToggle: genFx("toggle", 1),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" }
+}, function( name, props ){
+ jQuery.fn[ name ] = function( speed, callback ){
+ return this.animate( props, speed, callback );
+ };
+});
+
+jQuery.extend({
+
+ speed: function(speed, easing, fn) {
+ var opt = typeof speed === "object" ? speed : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
+
+ // Queueing
+ opt.old = opt.complete;
+ opt.complete = function(){
+ if ( opt.queue !== false )
+ jQuery(this).dequeue();
+ if ( jQuery.isFunction( opt.old ) )
+ opt.old.call( this );
+ };
+
+ return opt;
+ },
+
+ easing: {
+ linear: function( p, n, firstNum, diff ) {
+ return firstNum + diff * p;
+ },
+ swing: function( p, n, firstNum, diff ) {
+ return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+ }
+ },
+
+ timers: [],
+
+ fx: function( elem, options, prop ){
+ this.options = options;
+ this.elem = elem;
+ this.prop = prop;
+
+ if ( !options.orig )
+ options.orig = {};
+ }
+
+});
+
+jQuery.fx.prototype = {
+
+ // Simple function for setting a style value
+ update: function(){
+ if ( this.options.step )
+ this.options.step.call( this.elem, this.now, this );
+
+ (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+
+ // Set display property to block for height/width animations
+ if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
+ this.elem.style.display = "block";
+ },
+
+ // Get the current size
+ cur: function(force){
+ if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
+ return this.elem[ this.prop ];
+
+ var r = parseFloat(jQuery.css(this.elem, this.prop, force));
+ return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
+ },
+
+ // Start an animation from one number to another
+ custom: function(from, to, unit){
+ this.startTime = now();
+ this.start = from;
+ this.end = to;
+ this.unit = unit || this.unit || "px";
+ this.now = this.start;
+ this.pos = this.state = 0;
+
+ var self = this;
+ function t(gotoEnd){
+ return self.step(gotoEnd);
+ }
+
+ t.elem = this.elem;
+
+ if ( t() && jQuery.timers.push(t) == 1 ) {
+ timerId = setInterval(function(){
+ var timers = jQuery.timers;
+
+ for ( var i = 0; i < timers.length; i++ )
+ if ( !timers[i]() )
+ timers.splice(i--, 1);
+
+ if ( !timers.length ) {
+ clearInterval( timerId );
+ }
+ }, 13);
+ }
+ },
+
+ // Simple 'show' function
+ show: function(){
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+ this.options.show = true;
+
+ // Begin the animation
+ // Make sure that we start at a small width/height to avoid any
+ // flash of content
+ this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
+
+ // Start by showing the element
+ jQuery(this.elem).show();
+ },
+
+ // Simple 'hide' function
+ hide: function(){
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+ this.options.hide = true;
+
+ // Begin the animation
+ this.custom(this.cur(), 0);
+ },
+
+ // Each step of an animation
+ step: function(gotoEnd){
+ var t = now();
+
+ if ( gotoEnd || t >= this.options.duration + this.startTime ) {
+ this.now = this.end;
+ this.pos = this.state = 1;
+ this.update();
+
+ this.options.curAnim[ this.prop ] = true;
+
+ var done = true;
+ for ( var i in this.options.curAnim )
+ if ( this.options.curAnim[i] !== true )
+ done = false;
+
+ if ( done ) {
+ if ( this.options.display != null ) {
+ // Reset the overflow
+ this.elem.style.overflow = this.options.overflow;
+
+ // Reset the display
+ this.elem.style.display = this.options.display;
+ if ( jQuery.css(this.elem, "display") == "none" )
+ this.elem.style.display = "block";
+ }
+
+ // Hide the element if the "hide" operation was done
+ if ( this.options.hide )
+ jQuery(this.elem).hide();
+
+ // Reset the properties, if the item has been hidden or shown
+ if ( this.options.hide || this.options.show )
+ for ( var p in this.options.curAnim )
+ jQuery.attr(this.elem.style, p, this.options.orig[p]);
+
+ // Execute the complete function
+ this.options.complete.call( this.elem );
+ }
+
+ return false;
+ } else {
+ var n = t - this.startTime;
+ this.state = n / this.options.duration;
+
+ // Perform the easing function, defaults to swing
+ this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
+ this.now = this.start + ((this.end - this.start) * this.pos);
+
+ // Perform the next step of the animation
+ this.update();
+ }
+
+ return true;
+ }
+
+};
+
+jQuery.extend( jQuery.fx, {
+ speeds:{
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+ },
+ step: {
+
+ opacity: function(fx){
+ jQuery.attr(fx.elem.style, "opacity", fx.now);
+ },
+
+ _default: function(fx){
+ if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
+ fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+ else
+ fx.elem[ fx.prop ] = fx.now;
+ }
+ }
+});
+if ( document.documentElement["getBoundingClientRect"] )
+ jQuery.fn.offset = function() {
+ if ( !this[0] ) return { top: 0, left: 0 };
+ if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
+ var box = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
+ clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
+ top = box.top + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop,
+ left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
+ return { top: top, left: left };
+ };
+else
+ jQuery.fn.offset = function() {
+ if ( !this[0] ) return { top: 0, left: 0 };
+ if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
+ jQuery.offset.initialized || jQuery.offset.initialize();
+
+ var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
+ doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
+ body = doc.body, defaultView = doc.defaultView,
+ prevComputedStyle = defaultView.getComputedStyle(elem, null),
+ top = elem.offsetTop, left = elem.offsetLeft,
+ isAbsolute = prevComputedStyle.position === "absolute"; //RF: added by rf-team
+
+ while ( (elem = elem.parentNode) && elem !== body && elem !== docElem && prevComputedStyle.position !== "fixed" ) {
+ computedStyle = defaultView.getComputedStyle(elem, null);
+
+ //RF: added by rf-team
+ if ( (!isAbsolute && prevComputedStyle.position === "static") /* add scroll for statically positioned elements */ ||
+ prevComputedStyle.position === "relative" /* not sure we need this - have to test */ ||
+ elem === offsetParent /* add scroll offset of offsetParent element */ ) {
+ top -= elem.scrollTop, left -= elem.scrollLeft;
+ isAbsolute = prevComputedStyle.position === "absolute";
+ }
+ //RF: end
+
+ if ( elem === offsetParent ) {
+ top += elem.offsetTop, left += elem.offsetLeft;
+ if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
+ top += parseInt( computedStyle.borderTopWidth, 10) || 0,
+ left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+ prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
+ }
+ if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
+ top += parseInt( computedStyle.borderTopWidth, 10) || 0,
+ left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+ prevComputedStyle = computedStyle;
+ }
+
+ if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
+ top += body.offsetTop,
+ left += body.offsetLeft;
+
+ if ( prevComputedStyle.position === "fixed" )
+ top += Math.max(docElem.scrollTop, body.scrollTop),
+ left += Math.max(docElem.scrollLeft, body.scrollLeft);
+
+
+ return { top: top, left: left };
+ };
+
+jQuery.offset = {
+ initialize: function() {
+ if ( this.initialized ) return;
+ var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
+ html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';
+
+ rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
+ for ( prop in rules ) container.style[prop] = rules[prop];
+
+ container.innerHTML = html;
+ body.insertBefore(container, body.firstChild);
+ innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
+
+ this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
+ this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
+
+ innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
+ this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
+
+ body.style.marginTop = '1px';
+ this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
+ body.style.marginTop = bodyMarginTop;
+
+ body.removeChild(container);
+ this.initialized = true;
+ },
+
+ bodyOffset: function(body) {
+ jQuery.offset.initialized || jQuery.offset.initialize();
+ var top = body.offsetTop, left = body.offsetLeft;
+ if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
+ top += parseInt( jQuery.curCSS(body, 'marginTop', true), 10 ) || 0,
+ left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
+ return { top: top, left: left };
+ }
+};
+
+
+jQuery.fn.extend({
+ position: function() {
+ var left = 0, top = 0, results;
+
+ if ( this[0] ) {
+ // Get *real* offsetParent
+ var offsetParent = this.offsetParent(),
+
+ // Get correct offsets
+ offset = this.offset(),
+ parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+ // Subtract element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ offset.top -= num( this, 'marginTop' );
+ offset.left -= num( this, 'marginLeft' );
+
+ // Add offsetParent borders
+ parentOffset.top += num( offsetParent, 'borderTopWidth' );
+ parentOffset.left += num( offsetParent, 'borderLeftWidth' );
+
+ // Subtract the two offsets
+ results = {
+ top: offset.top - parentOffset.top,
+ left: offset.left - parentOffset.left
+ };
+ }
+
+ return results;
+ },
+
+ offsetParent: function() {
+ var offsetParent = this[0].offsetParent || document.body;
+ while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
+ offsetParent = offsetParent.offsetParent;
+ return jQuery(offsetParent);
+ }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ['Left', 'Top'], function(i, name) {
+ var method = 'scroll' + name;
+
+ jQuery.fn[ method ] = function(val) {
+ if (!this[0]) return null;
+
+ return val !== undefined ?
+
+ // Set the scroll offset
+ this.each(function() {
+ this == window || this == document ?
+ window.scrollTo(
+ !i ? val : jQuery(window).scrollLeft(),
+ i ? val : jQuery(window).scrollTop()
+ ) :
+ this[ method ] = val;
+ }) :
+
+ // Return the scroll offset
+ this[0] == window || this[0] == document ?
+ self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
+ jQuery.boxModel && document.documentElement[ method ] ||
+ document.body[ method ] :
+ this[0][ method ];
+ };
+});
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function(i, name){
+
+ var tl = i ? "Left" : "Top", // top or left
+ br = i ? "Right" : "Bottom"; // bottom or right
+
+ // innerHeight and innerWidth
+ jQuery.fn["inner" + name] = function(){
+ return this[ name.toLowerCase() ]() +
+ num(this, "padding" + tl) +
+ num(this, "padding" + br);
+ };
+
+ // outerHeight and outerWidth
+ jQuery.fn["outer" + name] = function(margin) {
+ return this["inner" + name]() +
+ num(this, "border" + tl + "Width") +
+ num(this, "border" + br + "Width") +
+ (margin ?
+ num(this, "margin" + tl) + num(this, "margin" + br) : 0);
+ };
+
+ var type = name.toLowerCase();
+
+ jQuery.fn[ type ] = function( size ) {
+ // Get window width or height
+ return this[0] == window ?
+ // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+ document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
+ document.body[ "client" + name ] :
+
+ // Get document width or height
+ this[0] == document ?
+ // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+ Math.max(
+ document.documentElement["client" + name],
+ document.body["scroll" + name], document.documentElement["scroll" + name],
+ document.body["offset" + name], document.documentElement["offset" + name]
+ ) :
+
+ // Get or set width or height on the element
+ size === undefined ?
+ // Get width or height on the element
+ (this.length ? jQuery.css( this[0], type ) : null) :
+
+ // Set the width or height on the element (default to pixels if value is unitless)
+ this.css( type, typeof size === "string" ? size : size + "px" );
+ };
+
+});})();
Copied: branches/jsf2.0/framework/impl/src/main/javascript/jquery/jquery-1.3.2.js (from rev 14238, trunk/framework/impl/src/main/javascript/jquery/jquery-1.3.2.js)
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/jquery/jquery-1.3.2.js (rev 0)
+++ branches/jsf2.0/framework/impl/src/main/javascript/jquery/jquery-1.3.2.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -0,0 +1,4412 @@
+/*!
+ * jQuery JavaScript Library v1.3.2
+ * http://jquery.com/
+ *
+ * Copyright (c) 2009 John Resig
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ *
+ * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
+ * Revision: 6246
+ */
+(function(){
+
+var
+ // Will speed up references to window, and allows munging its name.
+ window = this,
+ // Will speed up references to undefined, and allows munging its name.
+ undefined,
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+ // Map over the $ in case of overwrite
+ _$ = window.$,
+
+ jQuery = window.jQuery = window.j$ = function( selector, context ) {
+ // RF: added for RichFaces components
+ if (arguments[0] == arguments.callee) {
+ return arguments.callee;
+ }
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context );
+ },
+
+ // A simple way to check for HTML strings or ID strings
+ // (both of which we optimize for)
+ quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
+ // Is it a simple selector
+ isSimple = /^.[^:#\[\.,]*$/;
+
+jQuery.fn = jQuery.prototype = {
+ init: function( selector, context ) {
+ // Make sure that a selection was provided
+ selector = selector || document;
+
+ // Handle $(DOMElement)
+ if ( selector.nodeType ) {
+ this[0] = selector;
+ this.length = 1;
+ this.context = selector;
+ return this;
+ }
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ // Are we dealing with HTML string or an ID?
+ var match = quickExpr.exec( selector );
+
+ // Verify a match, and that no context was specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] )
+ selector = jQuery.clean( [ match[1] ], context );
+
+ // HANDLE: $("#id")
+ else {
+ var elem = document.getElementById( match[3] );
+
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem && elem.id != match[3] )
+ return jQuery().find( selector );
+
+ // Otherwise, we inject the element directly into the jQuery object
+ var ret = jQuery( elem || [] );
+ ret.context = document;
+ ret.selector = selector;
+ return ret;
+ }
+
+ // HANDLE: $(expr, [context])
+ // (which is just equivalent to: $(content).find(expr)
+ } else
+ return jQuery( context ).find( selector );
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) )
+ return jQuery( document ).ready( selector );
+
+ // Make sure that old selector state is passed along
+ if ( selector.selector && selector.context ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return this.setArray(jQuery.isArray( selector ) ?
+ selector :
+ jQuery.makeArray(selector));
+ },
+
+ // Start with an empty selector
+ selector: "",
+
+ // The current version of jQuery being used
+ jquery: "1.3.2",
+
+ // The number of elements contained in the matched element set
+ size: function() {
+ return this.length;
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num === undefined ?
+
+ // Return a 'clean' array
+ Array.prototype.slice.call( this ) :
+
+ // Return just the object
+ this[ num ];
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems, name, selector ) {
+ // Build a new jQuery matched element set
+ var ret = jQuery( elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+
+ ret.context = this.context;
+
+ if ( name === "find" )
+ ret.selector = this.selector + (this.selector ? " " : "") + selector;
+ else if ( name )
+ ret.selector = this.selector + "." + name + "(" + selector + ")";
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Force the current matched set of elements to become
+ // the specified array of elements (destroying the stack in the process)
+ // You should use pushStack() in order to do this, but maintain the stack
+ setArray: function( elems ) {
+ // Resetting the length to 0, then using the native Array push
+ // is a super-fast way to populate an object with array-like properties
+ this.length = 0;
+ Array.prototype.push.apply( this, elems );
+
+ return this;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem && elem.jquery ? elem[0] : elem
+ , this );
+ },
+
+ attr: function( name, value, type ) {
+ var options = name;
+
+ // Look for the case where we're accessing a style value
+ if ( typeof name === "string" )
+ if ( value === undefined )
+ return this[0] && jQuery[ type || "attr" ]( this[0], name );
+
+ else {
+ options = {};
+ options[ name ] = value;
+ }
+
+ // Check to see if we're setting style values
+ return this.each(function(i){
+ // Set all the styles
+ for ( name in options )
+ jQuery.attr(
+ type ?
+ this.style :
+ this,
+ name, jQuery.prop( this, options[ name ], type, i, name )
+ );
+ });
+ },
+
+ css: function( key, value ) {
+ // ignore negative width and height values
+ if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
+ value = undefined;
+ return this.attr( key, value, "curCSS" );
+ },
+
+ text: function( text ) {
+ if ( typeof text !== "object" && text != null )
+ return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+
+ var ret = "";
+
+ jQuery.each( text || this, function(){
+ jQuery.each( this.childNodes, function(){
+ if ( this.nodeType != 8 )
+ ret += this.nodeType != 1 ?
+ this.nodeValue :
+ jQuery.fn.text( [ this ] );
+ });
+ });
+
+ return ret;
+ },
+
+ wrapAll: function( html ) {
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).clone();
+
+ if ( this[0].parentNode )
+ wrap.insertBefore( this[0] );
+
+ wrap.map(function(){
+ var elem = this;
+
+ while ( elem.firstChild )
+ elem = elem.firstChild;
+
+ return elem;
+ }).append(this);
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ return this.each(function(){
+ jQuery( this ).contents().wrapAll( html );
+ });
+ },
+
+ wrap: function( html ) {
+ return this.each(function(){
+ jQuery( this ).wrapAll( html );
+ });
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, function(elem){
+ if (this.nodeType == 1)
+ this.appendChild( elem );
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, function(elem){
+ if (this.nodeType == 1)
+ this.insertBefore( elem, this.firstChild );
+ });
+ },
+
+ before: function() {
+ return this.domManip(arguments, false, function(elem){
+ this.parentNode.insertBefore( elem, this );
+ });
+ },
+
+ after: function() {
+ return this.domManip(arguments, false, function(elem){
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ });
+ },
+
+ end: function() {
+ return this.prevObject || jQuery( [] );
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: [].push,
+ sort: [].sort,
+ splice: [].splice,
+
+ find: function( selector ) {
+ if ( this.length === 1 ) {
+ var ret = this.pushStack( [], "find", selector );
+ ret.length = 0;
+ jQuery.find( selector, this[0], ret );
+ return ret;
+ } else {
+ return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){
+ return jQuery.find( selector, elem );
+ })), "find", selector );
+ }
+ },
+
+ clone: function( events ) {
+ // Do the clone
+ var ret = this.map(function(){
+ if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
+ // IE copies events bound via attachEvent when
+ // using cloneNode. Calling detachEvent on the
+ // clone will also remove the events from the orignal
+ // In order to get around this, we use innerHTML.
+ // Unfortunately, this means some modifications to
+ // attributes in IE that are actually only stored
+ // as properties will not be copied (such as the
+ // the name attribute on an input).
+ var html = this.outerHTML;
+ if ( !html ) {
+ var div = this.ownerDocument.createElement("div");
+ div.appendChild( this.cloneNode(true) );
+ html = div.innerHTML;
+ }
+
+ return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
+ } else
+ return this.cloneNode(true);
+ });
+
+ // Copy the events from the original to the clone
+ if ( events === true ) {
+ var orig = this.find("*").andSelf(), i = 0;
+
+ ret.find("*").andSelf().each(function(){
+ if ( this.nodeName !== orig[i].nodeName )
+ return;
+
+ var events = jQuery.data( orig[i], "events" );
+
+ for ( var type in events ) {
+ for ( var handler in events[ type ] ) {
+ jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
+ }
+ }
+
+ i++;
+ });
+ }
+
+ // Return the cloned set
+ return ret;
+ },
+
+ filter: function( selector ) {
+ return this.pushStack(
+ jQuery.isFunction( selector ) &&
+ jQuery.grep(this, function(elem, i){
+ return selector.call( elem, i );
+ }) ||
+
+ jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
+ return elem.nodeType === 1;
+ }) ), "filter", selector );
+ },
+
+ closest: function( selector ) {
+ var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
+ closer = 0;
+
+ return this.map(function(){
+ var cur = this;
+ while ( cur && cur.ownerDocument ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
+ jQuery.data(cur, "closest", closer);
+ return cur;
+ }
+ cur = cur.parentNode;
+ closer++;
+ }
+ });
+ },
+
+ not: function( selector ) {
+ if ( typeof selector === "string" )
+ // test special case where just one selector is passed in
+ if ( isSimple.test( selector ) )
+ return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
+ else
+ selector = jQuery.multiFilter( selector, this );
+
+ var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
+ return this.filter(function() {
+ return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
+ });
+ },
+
+ add: function( selector ) {
+ return this.pushStack( jQuery.unique( jQuery.merge(
+ this.get(),
+ typeof selector === "string" ?
+ jQuery( selector ) :
+ jQuery.makeArray( selector )
+ )));
+ },
+
+ is: function( selector ) {
+ return !!selector && jQuery.multiFilter( selector, this ).length > 0;
+ },
+
+ hasClass: function( selector ) {
+ return !!selector && this.is( "." + selector );
+ },
+
+ val: function( value ) {
+ if ( value === undefined ) {
+ var elem = this[0];
+
+ if ( elem ) {
+ if( jQuery.nodeName( elem, 'option' ) )
+ return (elem.attributes.value || {}).specified ? elem.value : elem.text;
+
+ // We need to handle select boxes special
+ if ( jQuery.nodeName( elem, "select" ) ) {
+ var index = elem.selectedIndex,
+ values = [],
+ options = elem.options,
+ one = elem.type == "select-one";
+
+ // Nothing was selected
+ if ( index < 0 )
+ return null;
+
+ // Loop through all the selected options
+ for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+ var option = options[ i ];
+
+ if ( option.selected ) {
+ // Get the specifc value for the option
+ value = jQuery(option).val();
+
+ // We don't need an array for one selects
+ if ( one )
+ return value;
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ }
+
+ // Everything else, we just grab the value
+ return (elem.value || "").replace(/\r/g, "");
+
+ }
+
+ return undefined;
+ }
+
+ if ( typeof value === "number" )
+ value += '';
+
+ return this.each(function(){
+ if ( this.nodeType != 1 )
+ return;
+
+ if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
+ this.checked = (jQuery.inArray(this.value, value) >= 0 ||
+ jQuery.inArray(this.name, value) >= 0);
+
+ else if ( jQuery.nodeName( this, "select" ) ) {
+ var values = jQuery.makeArray(value);
+
+ jQuery( "option", this ).each(function(){
+ this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
+ jQuery.inArray( this.text, values ) >= 0);
+ });
+
+ if ( !values.length )
+ this.selectedIndex = -1;
+
+ } else
+ this.value = value;
+ });
+ },
+
+ html: function( value ) {
+ return value === undefined ?
+ (this[0] ?
+ this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
+ null) :
+ this.empty().append( value );
+ },
+
+ replaceWith: function( value ) {
+ return this.after( value ).remove();
+ },
+
+ eq: function( i ) {
+ return this.slice( i, +i + 1 );
+ },
+
+ slice: function() {
+ return this.pushStack( Array.prototype.slice.apply( this, arguments ),
+ "slice", Array.prototype.slice.call(arguments).join(",") );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function(elem, i){
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ andSelf: function() {
+ return this.add( this.prevObject );
+ },
+
+ domManip: function( args, table, callback ) {
+ if ( this[0] ) {
+ var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
+ scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
+ first = fragment.firstChild;
+
+ if ( first )
+ for ( var i = 0, l = this.length; i < l; i++ )
+ callback.call( root(this[i], first), this.length > 1 || i > 0 ?
+ fragment.cloneNode(true) : fragment );
+
+ if ( scripts )
+ jQuery.each( scripts, evalScript );
+ }
+
+ return this;
+
+ function root( elem, cur ) {
+ return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
+ (elem.getElementsByTagName("tbody")[0] ||
+ elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+ elem;
+ }
+ }
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+function evalScript( i, elem ) {
+ if ( elem.src )
+ jQuery.ajax({
+ url: elem.src,
+ async: false,
+ dataType: "script"
+ });
+
+ else
+ jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+
+ if ( elem.parentNode )
+ elem.parentNode.removeChild( elem );
+}
+
+function now(){
+ return +new Date;
+}
+
+jQuery.extend = jQuery.fn.extend = function() {
+ // copy reference to target object
+ var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) )
+ target = {};
+
+ // extend jQuery itself if only one argument is passed
+ if ( length == i ) {
+ target = this;
+ --i;
+ }
+
+ for ( ; i < length; i++ )
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null )
+ // Extend the base object
+ for ( var name in options ) {
+ var src = target[ name ], copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy )
+ continue;
+
+ // Recurse if we're merging object values
+ if ( deep && copy && typeof copy === "object" && !copy.nodeType )
+ target[ name ] = jQuery.extend( deep,
+ // Never move original objects, clone them
+ src || ( copy.length != null ? [ ] : { } )
+ , copy );
+
+ // Don't bring in undefined values
+ else if ( copy !== undefined )
+ target[ name ] = copy;
+
+ }
+
+ // Return the modified object
+ return target;
+};
+
+// exclude the following css properties to add px
+var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
+ // cache defaultView
+ defaultView = document.defaultView || {},
+ toString = Object.prototype.toString;
+
+jQuery.extend({
+ noConflict: function( deep ) {
+ window.$ = _$;
+
+ if ( deep )
+ window.jQuery = _jQuery;
+
+ return jQuery;
+ },
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return toString.call(obj) === "[object Function]";
+ },
+
+ isArray: function( obj ) {
+ return toString.call(obj) === "[object Array]";
+ },
+
+ // check if an element is in a (or is an) XML document
+ isXMLDoc: function( elem ) {
+ return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
+ !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
+ },
+
+ // Evalulates a script in a global context
+ globalEval: function( data ) {
+ if ( data && /\S/.test(data) ) {
+ // Inspired by code by Andrea Giammarchi
+ // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom...
+ var head = document.getElementsByTagName("head")[0] || document.documentElement,
+ script = document.createElement("script");
+
+ script.type = "text/javascript";
+ if ( jQuery.support.scriptEval )
+ script.appendChild( document.createTextNode( data ) );
+ else
+ script.text = data;
+
+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
+ // This arises when a base node is used (#2709).
+ head.insertBefore( script, head.firstChild );
+ head.removeChild( script );
+ }
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
+ },
+
+ // args is for internal usage only
+ each: function( object, callback, args ) {
+ var name, i = 0, length = object.length;
+
+ if ( args ) {
+ if ( length === undefined ) {
+ for ( name in object )
+ if ( callback.apply( object[ name ], args ) === false )
+ break;
+ } else
+ for ( ; i < length; )
+ if ( callback.apply( object[ i++ ], args ) === false )
+ break;
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( length === undefined ) {
+ for ( name in object )
+ if ( callback.call( object[ name ], name, object[ name ] ) === false )
+ break;
+ } else
+ for ( var value = object[0];
+ i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
+ }
+
+ return object;
+ },
+
+ prop: function( elem, value, type, i, name ) {
+ // Handle executable functions
+ if ( jQuery.isFunction( value ) )
+ value = value.call( elem, i );
+
+ // Handle passing in a number to a CSS property
+ return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
+ value + "px" :
+ value;
+ },
+
+ className: {
+ // internal only, use addClass("class")
+ add: function( elem, classNames ) {
+ jQuery.each((classNames || "").split(/\s+/), function(i, className){
+ if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
+ elem.className += (elem.className ? " " : "") + className;
+ });
+ },
+
+ // internal only, use removeClass("class")
+ remove: function( elem, classNames ) {
+ if (elem.nodeType == 1)
+ elem.className = classNames !== undefined ?
+ jQuery.grep(elem.className.split(/\s+/), function(className){
+ return !jQuery.className.has( classNames, className );
+ }).join(" ") :
+ "";
+ },
+
+ // internal only, use hasClass("class")
+ has: function( elem, className ) {
+ return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
+ }
+ },
+
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback ) {
+ var old = {};
+ // Remember the old values, and insert the new ones
+ for ( var name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ callback.call( elem );
+
+ // Revert the old values
+ for ( var name in options )
+ elem.style[ name ] = old[ name ];
+ },
+
+ css: function( elem, name, force, extra ) {
+ if ( name == "width" || name == "height" ) {
+ var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
+
+ function getWH() {
+ val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
+
+ if ( extra === "border" )
+ return;
+
+ jQuery.each( which, function() {
+ if ( !extra )
+ val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
+ if ( extra === "margin" )
+ val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
+ else
+ val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
+ });
+ }
+
+ if ( elem.offsetWidth !== 0 )
+ getWH();
+ else
+ jQuery.swap( elem, props, getWH );
+
+ return Math.max(0, Math.round(val));
+ }
+
+ return jQuery.curCSS( elem, name, force );
+ },
+
+ curCSS: function( elem, name, force ) {
+ var ret, style = elem.style;
+
+ // We need to handle opacity special in IE
+ if ( name == "opacity" && !jQuery.support.opacity ) {
+ ret = jQuery.attr( style, "opacity" );
+
+ return ret == "" ?
+ "1" :
+ ret;
+ }
+
+ // Make sure we're using the right name for getting the float value
+ if ( name.match( /float/i ) )
+ name = styleFloat;
+
+ if ( !force && style && style[ name ] )
+ ret = style[ name ];
+
+ else if ( defaultView.getComputedStyle ) {
+
+ // Only "float" is needed here
+ if ( name.match( /float/i ) )
+ name = "float";
+
+ name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
+
+ var computedStyle = defaultView.getComputedStyle( elem, null );
+
+ if ( computedStyle )
+ ret = computedStyle.getPropertyValue( name );
+
+ // We should always get a number back from opacity
+ if ( name == "opacity" && ret == "" )
+ ret = "1";
+
+ } else if ( elem.currentStyle ) {
+ var camelCase = name.replace(/\-(\w)/g, function(all, letter){
+ return letter.toUpperCase();
+ });
+
+ ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
+ // Remember the original values
+ var left = style.left, rsLeft = elem.runtimeStyle.left;
+
+ // Put in the new values to get a computed value out
+ elem.runtimeStyle.left = elem.currentStyle.left;
+ style.left = ret || 0;
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ elem.runtimeStyle.left = rsLeft;
+ }
+ }
+
+ return ret;
+ },
+
+ clean: function( elems, context, fragment ) {
+ context = context || document;
+
+ // !context.createElement fails in IE with an error but returns typeof 'object'
+ if ( typeof context.createElement === "undefined" )
+ context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+
+ // If a single string is passed in and it's a single tag
+ // just do a createElement and skip the rest
+ if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
+ var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
+ if ( match )
+ return [ context.createElement( match[1] ) ];
+ }
+
+ var ret = [], scripts = [], div = context.createElement("div");
+
+ jQuery.each(elems, function(i, elem){
+ if ( typeof elem === "number" )
+ elem += '';
+
+ if ( !elem )
+ return;
+
+ // Convert html string into DOM nodes
+ if ( typeof elem === "string" ) {
+ // Fix "XHTML"-style tags in all browsers
+ elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
+ return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
+ all :
+ front + "></" + tag + ">";
+ });
+
+ // Trim whitespace, otherwise indexOf won't work as expected
+ var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
+
+ var wrap =
+ // option or optgroup
+ !tags.indexOf("<opt") &&
+ [ 1, "<select multiple='multiple'>", "</select>" ] ||
+
+ !tags.indexOf("<leg") &&
+ [ 1, "<fieldset>", "</fieldset>" ] ||
+
+ tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
+ [ 1, "<table>", "</table>" ] ||
+
+ !tags.indexOf("<tr") &&
+ [ 2, "<table><tbody>", "</tbody></table>" ] ||
+
+ // <thead> matched above
+ (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
+ [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
+
+ !tags.indexOf("<col") &&
+ [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
+
+ // IE can't serialize <link> and <script> tags normally
+ !jQuery.support.htmlSerialize &&
+ [ 1, "div<div>", "</div>" ] ||
+
+ [ 0, "", "" ];
+
+ // Go to html and back, then peel off extra wrappers
+ div.innerHTML = wrap[1] + elem + wrap[2];
+
+ // Move to the right depth
+ while ( wrap[0]-- )
+ div = div.lastChild;
+
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !jQuery.support.tbody ) {
+
+ // String was a <table>, *may* have spurious <tbody>
+ var hasBody = /<tbody/i.test(elem),
+ tbody = !tags.indexOf("<table") && !hasBody ?
+ div.firstChild && div.firstChild.childNodes :
+
+ // String was a bare <thead> or <tfoot>
+ wrap[1] == "<table>" && !hasBody ?
+ div.childNodes :
+ [];
+
+ for ( var j = tbody.length - 1; j >= 0 ; --j )
+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
+
+ }
+
+ // IE completely kills leading whitespace when innerHTML is used
+ if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
+ div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
+
+ elem = jQuery.makeArray( div.childNodes );
+ }
+
+ if ( elem.nodeType )
+ ret.push( elem );
+ else
+ ret = jQuery.merge( ret, elem );
+
+ });
+
+ if ( fragment ) {
+ for ( var i = 0; ret[i]; i++ ) {
+ if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+ scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+ } else {
+ if ( ret[i].nodeType === 1 )
+ ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
+ fragment.appendChild( ret[i] );
+ }
+ }
+
+ return scripts;
+ }
+
+ return ret;
+ },
+
+ attr: function( elem, name, value ) {
+ // don't set attributes on text and comment nodes
+ if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
+ return undefined;
+
+ var notxml = !jQuery.isXMLDoc( elem ),
+ // Whether we are setting (or getting)
+ set = value !== undefined;
+
+ // Try to normalize/fix the name
+ name = notxml && jQuery.props[ name ] || name;
+
+ // Only do all the following if this is a node (faster for style)
+ // IE elem.getAttribute passes even for style
+ if ( elem.tagName ) {
+
+ // These attributes require special treatment
+ var special = /href|src|style/.test( name );
+
+ // Safari mis-reports the default selected property of a hidden option
+ // Accessing the parent's selectedIndex property fixes it
+ if ( name == "selected" && elem.parentNode )
+ elem.parentNode.selectedIndex;
+
+ // If applicable, access the attribute via the DOM 0 way
+ if ( name in elem && notxml && !special ) {
+ if ( set ){
+ // We can't allow the type property to be changed (since it causes problems in IE)
+ if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
+ throw "type property can't be changed";
+
+ elem[ name ] = value;
+ }
+
+ // browsers index elements by id/name on forms, give priority to attributes.
+ if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
+ return elem.getAttributeNode( name ).nodeValue;
+
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabi...
+ if ( name == "tabIndex" ) {
+ var attributeNode = elem.getAttributeNode( "tabIndex" );
+ return attributeNode && attributeNode.specified
+ ? attributeNode.value
+ : elem.nodeName.match(/(button|input|object|select|textarea)/i)
+ ? 0
+ : elem.nodeName.match(/^(a|area)$/i) && elem.href
+ ? 0
+ : undefined;
+ }
+
+ return elem[ name ];
+ }
+
+ if ( !jQuery.support.style && notxml && name == "style" )
+ return jQuery.attr( elem.style, "cssText", value );
+
+ if ( set )
+ // convert the value to a string (all browsers do this but IE) see #1070
+ elem.setAttribute( name, "" + value );
+
+ var attr = !jQuery.support.hrefNormalized && notxml && special
+ // Some attributes require a special call on IE
+ ? elem.getAttribute( name, 2 )
+ : elem.getAttribute( name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return attr === null ? undefined : attr;
+ }
+
+ // elem is actually elem.style ... set the style
+
+ // IE uses filters for opacity
+ if ( !jQuery.support.opacity && name == "opacity" ) {
+ if ( set ) {
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ elem.zoom = 1;
+
+ // Set the alpha filter to set the opacity
+ elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
+ (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
+ }
+
+ return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
+ (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
+ "";
+ }
+
+ name = name.replace(/-([a-z])/ig, function(all, letter){
+ return letter.toUpperCase();
+ });
+
+ if ( set )
+ elem[ name ] = value;
+
+ return elem[ name ];
+ },
+
+ trim: function( text ) {
+ return (text || "").replace( /^\s+|\s+$/g, "" );
+ },
+
+ makeArray: function( array ) {
+ var ret = [];
+
+ if( array != null ){
+ var i = array.length;
+ // The window, strings (and functions) also have 'length'
+ if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
+ ret[0] = array;
+ else
+ while( i )
+ ret[--i] = array[i];
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, array ) {
+ for ( var i = 0, length = array.length; i < length; i++ )
+ // Use === because on IE, window == document
+ if ( array[ i ] === elem )
+ return i;
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ // We have to loop this way because IE & Opera overwrite the length
+ // expando of getElementsByTagName
+ var i = 0, elem, pos = first.length;
+ // Also, we need to make sure that the correct elements are being returned
+ // (IE returns comment nodes in a '*' query)
+ if ( !jQuery.support.getAll ) {
+ while ( (elem = second[ i++ ]) != null )
+ if ( elem.nodeType != 8 )
+ first[ pos++ ] = elem;
+
+ } else
+ while ( (elem = second[ i++ ]) != null )
+ first[ pos++ ] = elem;
+
+ return first;
+ },
+
+ unique: function( array ) {
+ var ret = [], done = {};
+
+ try {
+
+ for ( var i = 0, length = array.length; i < length; i++ ) {
+ var id = jQuery.data( array[ i ] );
+
+ if ( !done[ id ] ) {
+ done[ id ] = true;
+ ret.push( array[ i ] );
+ }
+ }
+
+ } catch( e ) {
+ ret = array;
+ }
+
+ return ret;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var ret = [];
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( var i = 0, length = elems.length; i < length; i++ )
+ if ( !inv != !callback( elems[ i ], i ) )
+ ret.push( elems[ i ] );
+
+ return ret;
+ },
+
+ map: function( elems, callback ) {
+ var ret = [];
+
+ // Go through the array, translating each of the items to their
+ // new value (or values).
+ for ( var i = 0, length = elems.length; i < length; i++ ) {
+ var value = callback( elems[ i ], i );
+
+ if ( value != null )
+ ret[ ret.length ] = value;
+ }
+
+ return ret.concat.apply( [], ret );
+ }
+});
+
+// Use of jQuery.browser is deprecated.
+// It's included for backwards compatibility and plugins,
+// although they should work to migrate away.
+
+var userAgent = navigator.userAgent.toLowerCase();
+
+// Figure out what browser is being used
+jQuery.browser = {
+ version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
+ safari: /webkit/.test( userAgent ),
+ opera: /opera/.test( userAgent ),
+ msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
+ mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
+};
+
+jQuery.each({
+ parent: function(elem){return elem.parentNode;},
+ parents: function(elem){return jQuery.dir(elem,"parentNode");},
+ next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
+ prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
+ nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
+ prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
+ siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
+ children: function(elem){return jQuery.sibling(elem.firstChild);},
+ contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
+}, function(name, fn){
+ jQuery.fn[ name ] = function( selector ) {
+ var ret = jQuery.map( this, fn );
+
+ if ( selector && typeof selector == "string" )
+ ret = jQuery.multiFilter( selector, ret );
+
+ return this.pushStack( jQuery.unique( ret ), name, selector );
+ };
+});
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function(name, original){
+ jQuery.fn[ name ] = function( selector ) {
+ var ret = [], insert = jQuery( selector );
+
+ for ( var i = 0, l = insert.length; i < l; i++ ) {
+ var elems = (i > 0 ? this.clone(true) : this).get();
+ jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
+ ret = ret.concat( elems );
+ }
+
+ return this.pushStack( ret, name, selector );
+ };
+});
+
+jQuery.each({
+ removeAttr: function( name ) {
+ jQuery.attr( this, name, "" );
+ if (this.nodeType == 1)
+ this.removeAttribute( name );
+ },
+
+ addClass: function( classNames ) {
+ jQuery.className.add( this, classNames );
+ },
+
+ removeClass: function( classNames ) {
+ jQuery.className.remove( this, classNames );
+ },
+
+ toggleClass: function( classNames, state ) {
+ if( typeof state !== "boolean" )
+ state = !jQuery.className.has( this, classNames );
+ jQuery.className[ state ? "add" : "remove" ]( this, classNames );
+ },
+
+ remove: function( selector ) {
+ if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
+ // Prevent memory leaks
+ jQuery( "*", this ).add([this]).each(function(){
+ jQuery.event.remove(this);
+ jQuery.removeData(this);
+ });
+ if (this.parentNode)
+ this.parentNode.removeChild( this );
+ }
+ },
+
+ empty: function() {
+ // Remove element nodes and prevent memory leaks
+ jQuery(this).children().remove();
+
+ // Remove any remaining nodes
+ while ( this.firstChild )
+ this.removeChild( this.firstChild );
+ }
+}, function(name, fn){
+ jQuery.fn[ name ] = function(){
+ return this.each( fn, arguments );
+ };
+});
+
+// Helper function used by the dimensions and offset modules
+function num(elem, prop) {
+ return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
+}
+var expando = jQuery.expando = "jQuery" + now(), uuid = 0, windowData = {};
+
+jQuery.extend({
+ cache: {},
+
+ data: function( elem, name, data ) {
+ elem = elem == window ?
+ windowData :
+ elem;
+
+ var id = elem[ expando ];
+
+ // Compute a unique ID for the element
+ if ( !id )
+ id = elem[ expando ] = ++uuid;
+
+ // Only generate the data cache if we're
+ // trying to access or manipulate it
+ if ( name && !jQuery.cache[ id ] )
+ jQuery.cache[ id ] = {};
+
+ // Prevent overriding the named cache with undefined values
+ if ( data !== undefined )
+ jQuery.cache[ id ][ name ] = data;
+
+ // Return the named cache data, or the ID for the element
+ return name ?
+ jQuery.cache[ id ][ name ] :
+ id;
+ },
+
+ removeData: function( elem, name ) {
+ elem = elem == window ?
+ windowData :
+ elem;
+
+ var id = elem[ expando ];
+
+ // If we want to remove a specific section of the element's data
+ if ( name ) {
+ if ( jQuery.cache[ id ] ) {
+ // Remove the section of cache data
+ delete jQuery.cache[ id ][ name ];
+
+ // If we've removed all the data, remove the element's cache
+ name = "";
+
+ for ( name in jQuery.cache[ id ] )
+ break;
+
+ if ( !name )
+ jQuery.removeData( elem );
+ }
+
+ // Otherwise, we want to remove all of the element's data
+ } else {
+ // Clean up the element expando
+ try {
+ delete elem[ expando ];
+ } catch(e){
+ // IE has trouble directly removing the expando
+ // but it's ok with using removeAttribute
+ if ( elem.removeAttribute )
+ elem.removeAttribute( expando );
+ }
+
+ // Completely remove the data cache
+ delete jQuery.cache[ id ];
+ }
+ },
+ queue: function( elem, type, data ) {
+ if ( elem ){
+
+ type = (type || "fx") + "queue";
+
+ var q = jQuery.data( elem, type );
+
+ if ( !q || jQuery.isArray(data) )
+ q = jQuery.data( elem, type, jQuery.makeArray(data) );
+ else if( data )
+ q.push( data );
+
+ }
+ return q;
+ },
+
+ dequeue: function( elem, type ){
+ var queue = jQuery.queue( elem, type ),
+ fn = queue.shift();
+
+ if( !type || type === "fx" )
+ fn = queue[0];
+
+ if( fn !== undefined )
+ fn.call(elem);
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ){
+ var parts = key.split(".");
+ parts[1] = parts[1] ? "." + parts[1] : "";
+
+ if ( value === undefined ) {
+ var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+ if ( data === undefined && this.length )
+ data = jQuery.data( this[0], key );
+
+ return data === undefined && parts[1] ?
+ this.data( parts[0] ) :
+ data;
+ } else
+ return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
+ jQuery.data( this, key, value );
+ });
+ },
+
+ removeData: function( key ){
+ return this.each(function(){
+ jQuery.removeData( this, key );
+ });
+ },
+ queue: function(type, data){
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ }
+
+ if ( data === undefined )
+ return jQuery.queue( this[0], type );
+
+ return this.each(function(){
+ var queue = jQuery.queue( this, type, data );
+
+ if( type == "fx" && queue.length == 1 )
+ queue[0].call(this);
+ });
+ },
+ dequeue: function(type){
+ return this.each(function(){
+ jQuery.dequeue( this, type );
+ });
+ }
+});/*!
+ * Sizzle CSS Selector Engine - v0.9.3
+ * Copyright 2009, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ * More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
+ done = 0,
+ toString = Object.prototype.toString;
+
+var Sizzle = function(selector, context, results, seed) {
+ results = results || [];
+ context = context || document;
+
+ if ( context.nodeType !== 1 && context.nodeType !== 9 )
+ return [];
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ var parts = [], m, set, checkSet, check, mode, extra, prune = true;
+
+ // Reset the position of the chunker regexp (start from head)
+ chunker.lastIndex = 0;
+
+ while ( (m = chunker.exec(selector)) !== null ) {
+ parts.push( m[1] );
+
+ if ( m[2] ) {
+ extra = RegExp.rightContext;
+ break;
+ }
+ }
+
+ if ( parts.length > 1 && origPOS.exec( selector ) ) {
+ if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+ set = posProcess( parts[0] + parts[1], context );
+ } else {
+ set = Expr.relative[ parts[0] ] ?
+ [ context ] :
+ Sizzle( parts.shift(), context );
+
+ while ( parts.length ) {
+ selector = parts.shift();
+
+ if ( Expr.relative[ selector ] )
+ selector += parts.shift();
+
+ set = posProcess( selector, set );
+ }
+ }
+ } else {
+ var ret = seed ?
+ { expr: parts.pop(), set: makeArray(seed) } :
+ Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
+ set = Sizzle.filter( ret.expr, ret.set );
+
+ if ( parts.length > 0 ) {
+ checkSet = makeArray(set);
+ } else {
+ prune = false;
+ }
+
+ while ( parts.length ) {
+ var cur = parts.pop(), pop = cur;
+
+ if ( !Expr.relative[ cur ] ) {
+ cur = "";
+ } else {
+ pop = parts.pop();
+ }
+
+ if ( pop == null ) {
+ pop = context;
+ }
+
+ Expr.relative[ cur ]( checkSet, pop, isXML(context) );
+ }
+ }
+
+ if ( !checkSet ) {
+ checkSet = set;
+ }
+
+ if ( !checkSet ) {
+ throw "Syntax error, unrecognized expression: " + (cur || selector);
+ }
+
+ if ( toString.call(checkSet) === "[object Array]" ) {
+ if ( !prune ) {
+ results.push.apply( results, checkSet );
+ } else if ( context.nodeType === 1 ) {
+ for ( var i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
+ results.push( set[i] );
+ }
+ }
+ } else {
+ for ( var i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+ results.push( set[i] );
+ }
+ }
+ }
+ } else {
+ makeArray( checkSet, results );
+ }
+
+ if ( extra ) {
+ Sizzle( extra, context, results, seed );
+
+ if ( sortOrder ) {
+ hasDuplicate = false;
+ results.sort(sortOrder);
+
+ if ( hasDuplicate ) {
+ for ( var i = 1; i < results.length; i++ ) {
+ if ( results[i] === results[i-1] ) {
+ results.splice(i--, 1);
+ }
+ }
+ }
+ }
+ }
+
+ return results;
+};
+
+Sizzle.matches = function(expr, set){
+ return Sizzle(expr, null, null, set);
+};
+
+Sizzle.find = function(expr, context, isXML){
+ var set, match;
+
+ if ( !expr ) {
+ return [];
+ }
+
+ for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
+ var type = Expr.order[i], match;
+
+ if ( (match = Expr.match[ type ].exec( expr )) ) {
+ var left = RegExp.leftContext;
+
+ if ( left.substr( left.length - 1 ) !== "\\" ) {
+ match[1] = (match[1] || "").replace(/\\/g, "");
+ set = Expr.find[ type ]( match, context, isXML );
+ if ( set != null ) {
+ expr = expr.replace( Expr.match[ type ], "" );
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !set ) {
+ set = context.getElementsByTagName("*");
+ }
+
+ return {set: set, expr: expr};
+};
+
+Sizzle.filter = function(expr, set, inplace, not){
+ var old = expr, result = [], curLoop = set, match, anyFound,
+ isXMLFilter = set && set[0] && isXML(set[0]);
+
+ while ( expr && set.length ) {
+ for ( var type in Expr.filter ) {
+ if ( (match = Expr.match[ type ].exec( expr )) != null ) {
+ var filter = Expr.filter[ type ], found, item;
+ anyFound = false;
+
+ if ( curLoop == result ) {
+ result = [];
+ }
+
+ if ( Expr.preFilter[ type ] ) {
+ match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+
+ if ( !match ) {
+ anyFound = found = true;
+ } else if ( match === true ) {
+ continue;
+ }
+ }
+
+ if ( match ) {
+ for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
+ if ( item ) {
+ found = filter( item, match, i, curLoop );
+ var pass = not ^ !!found;
+
+ if ( inplace && found != null ) {
+ if ( pass ) {
+ anyFound = true;
+ } else {
+ curLoop[i] = false;
+ }
+ } else if ( pass ) {
+ result.push( item );
+ anyFound = true;
+ }
+ }
+ }
+ }
+
+ if ( found !== undefined ) {
+ if ( !inplace ) {
+ curLoop = result;
+ }
+
+ expr = expr.replace( Expr.match[ type ], "" );
+
+ if ( !anyFound ) {
+ return [];
+ }
+
+ break;
+ }
+ }
+ }
+
+ // Improper expression
+ if ( expr == old ) {
+ if ( anyFound == null ) {
+ throw "Syntax error, unrecognized expression: " + expr;
+ } else {
+ break;
+ }
+ }
+
+ old = expr;
+ }
+
+ return curLoop;
+};
+
+var Expr = Sizzle.selectors = {
+ order: [ "ID", "NAME", "TAG" ],
+ match: {
+ ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
+ CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
+ NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
+ ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
+ TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
+ CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
+ POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
+ PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
+ },
+ attrMap: {
+ "class": "className",
+ "for": "htmlFor"
+ },
+ attrHandle: {
+ href: function(elem){
+ return elem.getAttribute("href");
+ }
+ },
+ relative: {
+ "+": function(checkSet, part, isXML){
+ var isPartStr = typeof part === "string",
+ isTag = isPartStr && !/\W/.test(part),
+ isPartStrNotTag = isPartStr && !isTag;
+
+ if ( isTag && !isXML ) {
+ part = part.toUpperCase();
+ }
+
+ for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+ if ( (elem = checkSet[i]) ) {
+ while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+
+ checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
+ elem || false :
+ elem === part;
+ }
+ }
+
+ if ( isPartStrNotTag ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ },
+ ">": function(checkSet, part, isXML){
+ var isPartStr = typeof part === "string";
+
+ if ( isPartStr && !/\W/.test(part) ) {
+ part = isXML ? part : part.toUpperCase();
+
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ var parent = elem.parentNode;
+ checkSet[i] = parent.nodeName === part ? parent : false;
+ }
+ }
+ } else {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ checkSet[i] = isPartStr ?
+ elem.parentNode :
+ elem.parentNode === part;
+ }
+ }
+
+ if ( isPartStr ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ }
+ },
+ "": function(checkSet, part, isXML){
+ var doneName = done++, checkFn = dirCheck;
+
+ if ( !part.match(/\W/) ) {
+ var nodeCheck = part = isXML ? part : part.toUpperCase();
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
+ },
+ "~": function(checkSet, part, isXML){
+ var doneName = done++, checkFn = dirCheck;
+
+ if ( typeof part === "string" && !part.match(/\W/) ) {
+ var nodeCheck = part = isXML ? part : part.toUpperCase();
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
+ }
+ },
+ find: {
+ ID: function(match, context, isXML){
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+ return m ? [m] : [];
+ }
+ },
+ NAME: function(match, context, isXML){
+ if ( typeof context.getElementsByName !== "undefined" ) {
+ var ret = [], results = context.getElementsByName(match[1]);
+
+ for ( var i = 0, l = results.length; i < l; i++ ) {
+ if ( results[i].getAttribute("name") === match[1] ) {
+ ret.push( results[i] );
+ }
+ }
+
+ return ret.length === 0 ? null : ret;
+ }
+ },
+ TAG: function(match, context){
+ return context.getElementsByTagName(match[1]);
+ }
+ },
+ preFilter: {
+ CLASS: function(match, curLoop, inplace, result, not, isXML){
+ match = " " + match[1].replace(/\\/g, "") + " ";
+
+ if ( isXML ) {
+ return match;
+ }
+
+ for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+ if ( elem ) {
+ if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
+ if ( !inplace )
+ result.push( elem );
+ } else if ( inplace ) {
+ curLoop[i] = false;
+ }
+ }
+ }
+
+ return false;
+ },
+ ID: function(match){
+ return match[1].replace(/\\/g, "");
+ },
+ TAG: function(match, curLoop){
+ for ( var i = 0; curLoop[i] === false; i++ ){}
+ return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
+ },
+ CHILD: function(match){
+ if ( match[1] == "nth" ) {
+ // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+ var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+ match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
+ !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+ // calculate the numbers (first)n+(last) including if they are negative
+ match[2] = (test[1] + (test[2] || 1)) - 0;
+ match[3] = test[3] - 0;
+ }
+
+ // TODO: Move to normal caching system
+ match[0] = done++;
+
+ return match;
+ },
+ ATTR: function(match, curLoop, inplace, result, not, isXML){
+ var name = match[1].replace(/\\/g, "");
+
+ if ( !isXML && Expr.attrMap[name] ) {
+ match[1] = Expr.attrMap[name];
+ }
+
+ if ( match[2] === "~=" ) {
+ match[4] = " " + match[4] + " ";
+ }
+
+ return match;
+ },
+ PSEUDO: function(match, curLoop, inplace, result, not){
+ if ( match[1] === "not" ) {
+ // If we're dealing with a complex expression, or a simple one
+ if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
+ match[3] = Sizzle(match[3], null, null, curLoop);
+ } else {
+ var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+ if ( !inplace ) {
+ result.push.apply( result, ret );
+ }
+ return false;
+ }
+ } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+ return true;
+ }
+
+ return match;
+ },
+ POS: function(match){
+ match.unshift( true );
+ return match;
+ }
+ },
+ filters: {
+ enabled: function(elem){
+ return elem.disabled === false && elem.type !== "hidden";
+ },
+ disabled: function(elem){
+ return elem.disabled === true;
+ },
+ checked: function(elem){
+ return elem.checked === true;
+ },
+ selected: function(elem){
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ elem.parentNode.selectedIndex;
+ return elem.selected === true;
+ },
+ parent: function(elem){
+ return !!elem.firstChild;
+ },
+ empty: function(elem){
+ return !elem.firstChild;
+ },
+ has: function(elem, i, match){
+ return !!Sizzle( match[3], elem ).length;
+ },
+ header: function(elem){
+ return /h\d/i.test( elem.nodeName );
+ },
+ text: function(elem){
+ return "text" === elem.type;
+ },
+ radio: function(elem){
+ return "radio" === elem.type;
+ },
+ checkbox: function(elem){
+ return "checkbox" === elem.type;
+ },
+ file: function(elem){
+ return "file" === elem.type;
+ },
+ password: function(elem){
+ return "password" === elem.type;
+ },
+ submit: function(elem){
+ return "submit" === elem.type;
+ },
+ image: function(elem){
+ return "image" === elem.type;
+ },
+ reset: function(elem){
+ return "reset" === elem.type;
+ },
+ button: function(elem){
+ return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
+ },
+ input: function(elem){
+ return /input|select|textarea|button/i.test(elem.nodeName);
+ }
+ },
+ setFilters: {
+ first: function(elem, i){
+ return i === 0;
+ },
+ last: function(elem, i, match, array){
+ return i === array.length - 1;
+ },
+ even: function(elem, i){
+ return i % 2 === 0;
+ },
+ odd: function(elem, i){
+ return i % 2 === 1;
+ },
+ lt: function(elem, i, match){
+ return i < match[3] - 0;
+ },
+ gt: function(elem, i, match){
+ return i > match[3] - 0;
+ },
+ nth: function(elem, i, match){
+ return match[3] - 0 == i;
+ },
+ eq: function(elem, i, match){
+ return match[3] - 0 == i;
+ }
+ },
+ filter: {
+ PSEUDO: function(elem, match, i, array){
+ var name = match[1], filter = Expr.filters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+ } else if ( name === "contains" ) {
+ return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
+ } else if ( name === "not" ) {
+ var not = match[3];
+
+ for ( var i = 0, l = not.length; i < l; i++ ) {
+ if ( not[i] === elem ) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ },
+ CHILD: function(elem, match){
+ var type = match[1], node = elem;
+ switch (type) {
+ case 'only':
+ case 'first':
+ while (node = node.previousSibling) {
+ if ( node.nodeType === 1 ) return false;
+ }
+ if ( type == 'first') return true;
+ node = elem;
+ case 'last':
+ while (node = node.nextSibling) {
+ if ( node.nodeType === 1 ) return false;
+ }
+ return true;
+ case 'nth':
+ var first = match[2], last = match[3];
+
+ if ( first == 1 && last == 0 ) {
+ return true;
+ }
+
+ var doneName = match[0],
+ parent = elem.parentNode;
+
+ if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
+ var count = 0;
+ for ( node = parent.firstChild; node; node = node.nextSibling ) {
+ if ( node.nodeType === 1 ) {
+ node.nodeIndex = ++count;
+ }
+ }
+ parent.sizcache = doneName;
+ }
+
+ var diff = elem.nodeIndex - last;
+ if ( first == 0 ) {
+ return diff == 0;
+ } else {
+ return ( diff % first == 0 && diff / first >= 0 );
+ }
+ }
+ },
+ ID: function(elem, match){
+ return elem.nodeType === 1 && elem.getAttribute("id") === match;
+ },
+ TAG: function(elem, match){
+ return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
+ },
+ CLASS: function(elem, match){
+ return (" " + (elem.className || elem.getAttribute("class")) + " ")
+ .indexOf( match ) > -1;
+ },
+ ATTR: function(elem, match){
+ var name = match[1],
+ result = Expr.attrHandle[ name ] ?
+ Expr.attrHandle[ name ]( elem ) :
+ elem[ name ] != null ?
+ elem[ name ] :
+ elem.getAttribute( name ),
+ value = result + "",
+ type = match[2],
+ check = match[4];
+
+ return result == null ?
+ type === "!=" :
+ type === "=" ?
+ value === check :
+ type === "*=" ?
+ value.indexOf(check) >= 0 :
+ type === "~=" ?
+ (" " + value + " ").indexOf(check) >= 0 :
+ !check ?
+ value && result !== false :
+ type === "!=" ?
+ value != check :
+ type === "^=" ?
+ value.indexOf(check) === 0 :
+ type === "$=" ?
+ value.substr(value.length - check.length) === check :
+ type === "|=" ?
+ value === check || value.substr(0, check.length + 1) === check + "-" :
+ false;
+ },
+ POS: function(elem, match, i, array){
+ var name = match[2], filter = Expr.setFilters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+ }
+ }
+ }
+};
+
+var origPOS = Expr.match.POS;
+
+for ( var type in Expr.match ) {
+ Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
+}
+
+var makeArray = function(array, results) {
+ array = Array.prototype.slice.call( array );
+
+ if ( results ) {
+ results.push.apply( results, array );
+ return results;
+ }
+
+ return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+try {
+ Array.prototype.slice.call( document.documentElement.childNodes );
+
+// Provide a fallback method if it does not work
+} catch(e){
+ makeArray = function(array, results) {
+ var ret = results || [];
+
+ if ( toString.call(array) === "[object Array]" ) {
+ Array.prototype.push.apply( ret, array );
+ } else {
+ if ( typeof array.length === "number" ) {
+ for ( var i = 0, l = array.length; i < l; i++ ) {
+ ret.push( array[i] );
+ }
+ } else {
+ for ( var i = 0; array[i]; i++ ) {
+ ret.push( array[i] );
+ }
+ }
+ }
+
+ return ret;
+ };
+}
+
+var sortOrder;
+
+if ( document.documentElement.compareDocumentPosition ) {
+ sortOrder = function( a, b ) {
+ var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
+ if ( ret === 0 ) {
+ hasDuplicate = true;
+ }
+ return ret;
+ };
+} else if ( "sourceIndex" in document.documentElement ) {
+ sortOrder = function( a, b ) {
+ var ret = a.sourceIndex - b.sourceIndex;
+ if ( ret === 0 ) {
+ hasDuplicate = true;
+ }
+ return ret;
+ };
+} else if ( document.createRange ) {
+ sortOrder = function( a, b ) {
+ var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
+ aRange.selectNode(a);
+ aRange.collapse(true);
+ bRange.selectNode(b);
+ bRange.collapse(true);
+ var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
+ if ( ret === 0 ) {
+ hasDuplicate = true;
+ }
+ return ret;
+ };
+}
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+ // We're going to inject a fake input element with a specified name
+ var form = document.createElement("form"),
+ id = "script" + (new Date).getTime();
+ form.innerHTML = "<input name='" + id + "'/>";
+
+ // Inject it into the root element, check its status, and remove it quickly
+ var root = document.documentElement;
+ root.insertBefore( form, root.firstChild );
+
+ // The workaround has to do additional checks after a getElementById
+ // Which slows things down for other browsers (hence the branching)
+ if ( !!document.getElementById( id ) ) {
+ Expr.find.ID = function(match, context, isXML){
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+ return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
+ }
+ };
+
+ Expr.filter.ID = function(elem, match){
+ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+ return elem.nodeType === 1 && node && node.nodeValue === match;
+ };
+ }
+
+ root.removeChild( form );
+})();
+
+(function(){
+ // Check to see if the browser returns only elements
+ // when doing getElementsByTagName("*")
+
+ // Create a fake element
+ var div = document.createElement("div");
+ div.appendChild( document.createComment("") );
+
+ // Make sure no comments are found
+ if ( div.getElementsByTagName("*").length > 0 ) {
+ Expr.find.TAG = function(match, context){
+ var results = context.getElementsByTagName(match[1]);
+
+ // Filter out possible comments
+ if ( match[1] === "*" ) {
+ var tmp = [];
+
+ for ( var i = 0; results[i]; i++ ) {
+ if ( results[i].nodeType === 1 ) {
+ tmp.push( results[i] );
+ }
+ }
+
+ results = tmp;
+ }
+
+ return results;
+ };
+ }
+
+ // Check to see if an attribute returns normalized href attributes
+ div.innerHTML = "<a href='#'></a>";
+ if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+ div.firstChild.getAttribute("href") !== "#" ) {
+ Expr.attrHandle.href = function(elem){
+ return elem.getAttribute("href", 2);
+ };
+ }
+})();
+
+if ( document.querySelectorAll ) (function(){
+ var oldSizzle = Sizzle, div = document.createElement("div");
+ div.innerHTML = "<p class='TEST'></p>";
+
+ // Safari can't handle uppercase or unicode characters when
+ // in quirks mode.
+ if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+ return;
+ }
+
+ Sizzle = function(query, context, extra, seed){
+ context = context || document;
+
+ // Only use querySelectorAll on non-XML documents
+ // (ID selectors don't work in non-HTML documents)
+ if ( !seed && context.nodeType === 9 && !isXML(context) ) {
+ try {
+ return makeArray( context.querySelectorAll(query), extra );
+ } catch(e){}
+ }
+
+ return oldSizzle(query, context, extra, seed);
+ };
+
+ Sizzle.find = oldSizzle.find;
+ Sizzle.filter = oldSizzle.filter;
+ Sizzle.selectors = oldSizzle.selectors;
+ Sizzle.matches = oldSizzle.matches;
+})();
+
+if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
+ var div = document.createElement("div");
+ div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+
+ // Opera can't find a second classname (in 9.6)
+ if ( div.getElementsByClassName("e").length === 0 )
+ return;
+
+ // Safari caches class attributes, doesn't catch changes (in 3.2)
+ div.lastChild.className = "e";
+
+ if ( div.getElementsByClassName("e").length === 1 )
+ return;
+
+ Expr.order.splice(1, 0, "CLASS");
+ Expr.find.CLASS = function(match, context, isXML) {
+ if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+ return context.getElementsByClassName(match[1]);
+ }
+ };
+})();
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ var sibDir = dir == "previousSibling" && !isXML;
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ if ( sibDir && elem.nodeType === 1 ){
+ elem.sizcache = doneName;
+ elem.sizset = i;
+ }
+ elem = elem[dir];
+ var match = false;
+
+ while ( elem ) {
+ if ( elem.sizcache === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 && !isXML ){
+ elem.sizcache = doneName;
+ elem.sizset = i;
+ }
+
+ if ( elem.nodeName === cur ) {
+ match = elem;
+ break;
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ var sibDir = dir == "previousSibling" && !isXML;
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+ if ( elem ) {
+ if ( sibDir && elem.nodeType === 1 ) {
+ elem.sizcache = doneName;
+ elem.sizset = i;
+ }
+ elem = elem[dir];
+ var match = false;
+
+ while ( elem ) {
+ if ( elem.sizcache === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 ) {
+ if ( !isXML ) {
+ elem.sizcache = doneName;
+ elem.sizset = i;
+ }
+ if ( typeof cur !== "string" ) {
+ if ( elem === cur ) {
+ match = true;
+ break;
+ }
+
+ } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+ match = elem;
+ break;
+ }
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+var contains = document.compareDocumentPosition ? function(a, b){
+ return a.compareDocumentPosition(b) & 16;
+} : function(a, b){
+ return a !== b && (a.contains ? a.contains(b) : true);
+};
+
+var isXML = function(elem){
+ return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
+ !!elem.ownerDocument && isXML( elem.ownerDocument );
+};
+
+var posProcess = function(selector, context){
+ var tmpSet = [], later = "", match,
+ root = context.nodeType ? [context] : context;
+
+ // Position selectors must be done after the filter
+ // And so must :not(positional) so we move all PSEUDOs to the end
+ while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+ later += match[0];
+ selector = selector.replace( Expr.match.PSEUDO, "" );
+ }
+
+ selector = Expr.relative[selector] ? selector + "*" : selector;
+
+ for ( var i = 0, l = root.length; i < l; i++ ) {
+ Sizzle( selector, root[i], tmpSet );
+ }
+
+ return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+jQuery.find = Sizzle;
+jQuery.filter = Sizzle.filter;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+
+Sizzle.selectors.filters.hidden = function(elem){
+ return elem.offsetWidth === 0 || elem.offsetHeight === 0;
+};
+
+Sizzle.selectors.filters.visible = function(elem){
+ return elem.offsetWidth > 0 || elem.offsetHeight > 0;
+};
+
+Sizzle.selectors.filters.animated = function(elem){
+ return jQuery.grep(jQuery.timers, function(fn){
+ return elem === fn.elem;
+ }).length;
+};
+
+jQuery.multiFilter = function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return Sizzle.matches(expr, elems);
+};
+
+jQuery.dir = function( elem, dir ){
+ var matched = [], cur = elem[dir];
+ while ( cur && cur != document ) {
+ if ( cur.nodeType == 1 )
+ matched.push( cur );
+ cur = cur[dir];
+ }
+ return matched;
+};
+
+jQuery.nth = function(cur, result, dir, elem){
+ result = result || 1;
+ var num = 0;
+
+ for ( ; cur; cur = cur[dir] )
+ if ( cur.nodeType == 1 && ++num == result )
+ break;
+
+ return cur;
+};
+
+jQuery.sibling = function(n, elem){
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType == 1 && n != elem )
+ r.push( n );
+ }
+
+ return r;
+};
+
+return;
+
+window.Sizzle = Sizzle;
+
+})();
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code originated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+ // Bind an event to an element
+ // Original by Dean Edwards
+ add: function(elem, types, handler, data) {
+ if ( elem.nodeType == 3 || elem.nodeType == 8 )
+ return;
+
+ // For whatever reason, IE has trouble passing the window object
+ // around, causing it to be cloned in the process
+ if ( elem.setInterval && elem != window )
+ elem = window;
+
+ // Make sure that the function being executed has a unique ID
+ if ( !handler.guid )
+ handler.guid = this.guid++;
+
+ // if data is passed, bind to handler
+ if ( data !== undefined ) {
+ // Create temporary function pointer to original handler
+ var fn = handler;
+
+ // Create unique handler function, wrapped around original handler
+ handler = this.proxy( fn );
+
+ // Store data in unique handler
+ handler.data = data;
+ }
+
+ // Init the element's event structure
+ var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
+ handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
+ // Handle the second event of a trigger and when
+ // an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
+ jQuery.event.handle.apply(arguments.callee.elem, arguments) :
+ undefined;
+ });
+ // Add elem as a property of the handle function
+ // This is to prevent a memory leak with non-native
+ // event in IE.
+ handle.elem = elem;
+
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ jQuery.each(types.split(/\s+/), function(index, type) {
+ // Namespaced event handlers
+ var namespaces = type.split(".");
+ type = namespaces.shift();
+ handler.type = namespaces.slice().sort().join(".");
+
+ // Get the current list of functions bound to this event
+ var handlers = events[type];
+
+ if ( jQuery.event.specialAll[type] )
+ jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
+
+ // Init the event handler queue
+ if (!handlers) {
+ handlers = events[type] = {};
+
+ // Check for a special event handler
+ // Only use addEventListener/attachEvent if the special
+ // events handler returns false
+ if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
+ // Bind the global event handler to the element
+ if (elem.addEventListener)
+ elem.addEventListener(type, handle, false);
+ else if (elem.attachEvent)
+ elem.attachEvent("on" + type, handle);
+ }
+ }
+
+ // Add the function to the element's handler list
+ handlers[handler.guid] = handler;
+
+ // Keep track of which events have been used, for global triggering
+ jQuery.event.global[type] = true;
+ });
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ guid: 1,
+ global: {},
+
+ // Detach an event or set of events from an element
+ remove: function(elem, types, handler) {
+ // don't do events on text and comment nodes
+ if ( elem.nodeType == 3 || elem.nodeType == 8 )
+ return;
+
+ var events = jQuery.data(elem, "events"), ret, index;
+
+ if ( events ) {
+ // Unbind all events for the element
+ if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
+ for ( var type in events )
+ this.remove( elem, type + (types || "") );
+ else {
+ // types is actually an event object here
+ if ( types.type ) {
+ handler = types.handler;
+ types = types.type;
+ }
+
+ // Handle multiple events seperated by a space
+ // jQuery(...).unbind("mouseover mouseout", fn);
+ jQuery.each(types.split(/\s+/), function(index, type){
+ // Namespaced event handlers
+ var namespaces = type.split(".");
+ type = namespaces.shift();
+ var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+
+ if ( events[type] ) {
+ // remove the given handler for the given type
+ if ( handler )
+ delete events[type][handler.guid];
+
+ // remove all handlers for the given type
+ else
+ for ( var handle in events[type] )
+ // Handle the removal of namespaced events
+ if ( namespace.test(events[type][handle].type) )
+ delete events[type][handle];
+
+ if ( jQuery.event.specialAll[type] )
+ jQuery.event.specialAll[type].teardown.call(elem, namespaces);
+
+ // remove generic event handler if no more handlers exist
+ for ( ret in events[type] ) break;
+ if ( !ret ) {
+ if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
+ if (elem.removeEventListener)
+ elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
+ else if (elem.detachEvent)
+ elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
+ }
+ ret = null;
+ delete events[type];
+ }
+ }
+ });
+ }
+
+ // Remove the expando if it's no longer used
+ for ( ret in events ) break;
+ if ( !ret ) {
+ var handle = jQuery.data( elem, "handle" );
+ if ( handle ) handle.elem = null;
+ jQuery.removeData( elem, "events" );
+ jQuery.removeData( elem, "handle" );
+ }
+ }
+ },
+
+ // bubbling is internal
+ trigger: function( event, data, elem, bubbling ) {
+ // Event object or event type
+ var type = event.type || event;
+
+ if( !bubbling ){
+ event = typeof event === "object" ?
+ // jQuery.Event object
+ event[expando] ? event :
+ // Object literal
+ jQuery.extend( jQuery.Event(type), event ) :
+ // Just the event type (string)
+ jQuery.Event(type);
+
+ if ( type.indexOf("!") >= 0 ) {
+ event.type = type = type.slice(0, -1);
+ event.exclusive = true;
+ }
+
+ // Handle a global trigger
+ if ( !elem ) {
+ // Don't bubble custom events when global (to avoid too much overhead)
+ event.stopPropagation();
+ // Only trigger if we've ever bound an event for it
+ if ( this.global[type] )
+ jQuery.each( jQuery.cache, function(){
+ if ( this.events && this.events[type] )
+ jQuery.event.trigger( event, data, this.handle.elem );
+ });
+ }
+
+ // Handle triggering a single element
+
+ // don't do events on text and comment nodes
+ if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
+ return undefined;
+
+ // Clean up in case it is reused
+ event.result = undefined;
+ event.target = elem;
+
+ // Clone the incoming data, if any
+ data = jQuery.makeArray(data);
+ data.unshift( event );
+ }
+
+ event.currentTarget = elem;
+
+ // Trigger the event, it is assumed that "handle" is a function
+ var handle = jQuery.data(elem, "handle");
+ if ( handle )
+ handle.apply( elem, data );
+
+ // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
+ if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
+ event.result = false;
+
+ // Trigger the native events (except for clicks on links)
+ if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
+ this.triggered = true;
+ try {
+ elem[ type ]();
+ // prevent IE from throwing an error for some hidden elements
+ } catch (e) {}
+ }
+
+ this.triggered = false;
+
+ if ( !event.isPropagationStopped() ) {
+ var parent = elem.parentNode || elem.ownerDocument;
+ if ( parent )
+ jQuery.event.trigger(event, data, parent, true);
+ }
+ },
+
+ handle: function(event) {
+ // returned undefined or false
+ var all, handlers;
+
+ event = arguments[0] = jQuery.event.fix( event || window.event );
+ event.currentTarget = this;
+
+ // Namespaced event handlers
+ var namespaces = event.type.split(".");
+ event.type = namespaces.shift();
+
+ // Cache this now, all = true means, any handler
+ all = !namespaces.length && !event.exclusive;
+
+ var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+
+ handlers = ( jQuery.data(this, "events") || {} )[event.type];
+
+ for ( var j in handlers ) {
+ var handler = handlers[j];
+
+ // Filter the functions by class
+ if ( all || namespace.test(handler.type) ) {
+ // Pass in a reference to the handler function itself
+ // So that we can later remove it
+ event.handler = handler;
+ event.data = handler.data;
+
+ var ret = handler.apply(this, arguments);
+
+ if( ret !== undefined ){
+ event.result = ret;
+ if ( ret === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+
+ if( event.isImmediatePropagationStopped() )
+ break;
+
+ }
+ }
+ },
+
+ props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+
+ fix: function(event) {
+ if ( event[expando] )
+ return event;
+
+ // store a copy of the original event object
+ // and "clone" to set read-only properties
+ var originalEvent = event;
+ event = jQuery.Event( originalEvent );
+
+ for ( var i = this.props.length, prop; i; ){
+ prop = this.props[ --i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Fix target property, if necessary
+ if ( !event.target )
+ event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+
+ // check if target is a textnode (safari)
+ if ( event.target.nodeType == 3 )
+ event.target = event.target.parentNode;
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && event.fromElement )
+ event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && event.clientX != null ) {
+ var doc = document.documentElement, body = document.body;
+ event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
+ event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
+ }
+
+ // Add which for key events
+ if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
+ event.which = event.charCode || event.keyCode;
+
+ // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+ if ( !event.metaKey && event.ctrlKey )
+ event.metaKey = event.ctrlKey;
+
+ // Add which for click: 1 == left; 2 == middle; 3 == right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && event.button )
+ event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+
+ return event;
+ },
+
+ proxy: function( fn, proxy ){
+ proxy = proxy || function(){ return fn.apply(this, arguments); };
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
+ // So proxy can be declared as an argument
+ return proxy;
+ },
+
+ special: {
+ ready: {
+ // Make sure the ready event is setup
+ setup: bindReady,
+ teardown: function() {}
+ }
+ },
+
+ specialAll: {
+ live: {
+ setup: function( selector, namespaces ){
+ jQuery.event.add( this, namespaces[0], liveHandler );
+ },
+ teardown: function( namespaces ){
+ if ( namespaces.length ) {
+ var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
+
+ jQuery.each( (jQuery.data(this, "events").live || {}), function(){
+ if ( name.test(this.type) )
+ remove++;
+ });
+
+ if ( remove < 1 )
+ jQuery.event.remove( this, namespaces[0], liveHandler );
+ }
+ }
+ }
+ }
+};
+
+jQuery.Event = function( src ){
+ // Allow instantiation without the 'new' keyword
+ if( !this.preventDefault )
+ return new jQuery.Event(src);
+
+ // Event object
+ if( src && src.type ){
+ this.originalEvent = src;
+ this.type = src.type;
+ // Event type
+ }else
+ this.type = src;
+
+ // timeStamp is buggy for some events on Firefox(#3843)
+ // So we won't rely on the native value
+ this.timeStamp = now();
+
+ // Mark it as fixed
+ this[expando] = true;
+};
+
+function returnFalse(){
+ return false;
+}
+function returnTrue(){
+ return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-bind...
+jQuery.Event.prototype = {
+ preventDefault: function() {
+ this.isDefaultPrevented = returnTrue;
+
+ var e = this.originalEvent;
+ if( !e )
+ return;
+ // if preventDefault exists run it on the original event
+ if (e.preventDefault)
+ e.preventDefault();
+ // otherwise set the returnValue property of the original event to false (IE)
+ e.returnValue = false;
+ },
+ stopPropagation: function() {
+ this.isPropagationStopped = returnTrue;
+
+ var e = this.originalEvent;
+ if( !e )
+ return;
+ // if stopPropagation exists run it on the original event
+ if (e.stopPropagation)
+ e.stopPropagation();
+ // otherwise set the cancelBubble property of the original event to true (IE)
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation:function(){
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ },
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse
+};
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function(event) {
+ // Check if mouse(over|out) are still within the same parent element
+ var parent = event.relatedTarget;
+ // Traverse up the tree
+ while ( parent && parent != this )
+ try { parent = parent.parentNode; }
+ catch(e) { parent = this; }
+
+ if( parent != this ){
+ // set the correct event type
+ event.type = event.data;
+ // handle event if we actually just moused on to a non sub-element
+ jQuery.event.handle.apply( this, arguments );
+ }
+};
+
+jQuery.each({
+ mouseover: 'mouseenter',
+ mouseout: 'mouseleave'
+}, function( orig, fix ){
+ jQuery.event.special[ fix ] = {
+ setup: function(){
+ jQuery.event.add( this, orig, withinElement, fix );
+ },
+ teardown: function(){
+ jQuery.event.remove( this, orig, withinElement );
+ }
+ };
+});
+
+jQuery.fn.extend({
+ bind: function( type, data, fn ) {
+ return type == "unload" ? this.one(type, data, fn) : this.each(function(){
+ jQuery.event.add( this, type, fn || data, fn && data );
+ });
+ },
+
+ one: function( type, data, fn ) {
+ var one = jQuery.event.proxy( fn || data, function(event) {
+ jQuery(this).unbind(event, one);
+ return (fn || data).apply( this, arguments );
+ });
+ return this.each(function(){
+ jQuery.event.add( this, type, one, fn && data);
+ });
+ },
+
+ unbind: function( type, fn ) {
+ return this.each(function(){
+ jQuery.event.remove( this, type, fn );
+ });
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function(){
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+
+ triggerHandler: function( type, data ) {
+ if( this[0] ){
+ var event = jQuery.Event(type);
+ event.preventDefault();
+ event.stopPropagation();
+ jQuery.event.trigger( event, data, this[0] );
+ return event.result;
+ }
+ },
+
+ toggle: function( fn ) {
+ // Save reference to arguments for access in closure
+ var args = arguments, i = 1;
+
+ // link all the functions, so any of them can unbind this click handler
+ while( i < args.length )
+ jQuery.event.proxy( fn, args[i++] );
+
+ return this.click( jQuery.event.proxy( fn, function(event) {
+ // Figure out which function to execute
+ this.lastToggle = ( this.lastToggle || 0 ) % i;
+
+ // Make sure that clicks stop
+ event.preventDefault();
+
+ // and execute the function
+ return args[ this.lastToggle++ ].apply( this, arguments ) || false;
+ }));
+ },
+
+ hover: function(fnOver, fnOut) {
+ return this.mouseenter(fnOver).mouseleave(fnOut);
+ },
+
+ ready: function(fn) {
+ // Attach the listeners
+ bindReady();
+
+ // If the DOM is already ready
+ if ( jQuery.isReady )
+ // Execute the function immediately
+ fn.call( document, jQuery );
+
+ // Otherwise, remember the function for later
+ else
+ // Add the function to the wait list
+ jQuery.readyList.push( fn );
+
+ return this;
+ },
+
+ live: function( type, fn ){
+ var proxy = jQuery.event.proxy( fn );
+ proxy.guid += this.selector + type;
+
+ jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
+
+ return this;
+ },
+
+ die: function( type, fn ){
+ jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
+ return this;
+ }
+});
+
+function liveHandler( event ){
+ var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
+ stop = true,
+ elems = [];
+
+ jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
+ if ( check.test(fn.type) ) {
+ var elem = jQuery(event.target).closest(fn.data)[0];
+ if ( elem )
+ elems.push({ elem: elem, fn: fn });
+ }
+ });
+
+ elems.sort(function(a,b) {
+ return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
+ });
+
+ jQuery.each(elems, function(){
+ if ( this.fn.call(this.elem, event, this.fn.data) === false )
+ return (stop = false);
+ });
+
+ return stop;
+}
+
+function liveConvert(type, selector){
+ return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
+}
+
+jQuery.extend({
+ isReady: false,
+ readyList: [],
+ // Handle when the DOM is ready
+ ready: function() {
+ // Make sure that the DOM is not already loaded
+ if ( !jQuery.isReady ) {
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If there are functions bound, to execute
+ if ( jQuery.readyList ) {
+ // Execute all of them
+ jQuery.each( jQuery.readyList, function(){
+ this.call( document, jQuery );
+ });
+
+ // Reset the list of functions
+ jQuery.readyList = null;
+ }
+
+ // Trigger any bound ready events
+ jQuery(document).triggerHandler("ready");
+ }
+ }
+});
+
+var readyBound = false;
+
+function bindReady(){
+ if ( readyBound ) return;
+ readyBound = true;
+
+ // Mozilla, Opera and webkit nightlies currently support this event
+ if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", function(){
+ document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
+ jQuery.ready();
+ }, false );
+
+ // If IE event model is used
+ } else if ( document.attachEvent ) {
+ // ensure firing before onload,
+ // maybe late but safe also for iframes
+ document.attachEvent("onreadystatechange", function(){
+ if ( document.readyState === "complete" ) {
+ document.detachEvent( "onreadystatechange", arguments.callee );
+ jQuery.ready();
+ }
+ });
+
+ // If IE and not an iframe
+ // continually check to see if the document is ready
+ if ( document.documentElement.doScroll && window == window.top ) (function(){
+ if ( jQuery.isReady ) return;
+
+ try {
+ // If IE is used, use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ document.documentElement.doScroll("left");
+ } catch( error ) {
+ setTimeout( arguments.callee, 0 );
+ return;
+ }
+
+ // and execute any waiting functions
+ jQuery.ready();
+ })();
+ }
+
+ // A fallback to window.onload, that will always work
+ jQuery.event.add( window, "load", jQuery.ready );
+}
+
+jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
+ "mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
+ "change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
+
+ // Handle event binding
+ jQuery.fn[name] = function(fn){
+ return fn ? this.bind(name, fn) : this.trigger(name);
+ };
+});
+
+// Prevent memory leaks in IE
+// And prevent errors on refresh with events like mouseover in other browsers
+// Window isn't included so as not to unbind existing unload events
+jQuery( window ).bind( 'unload', function(){
+ for ( var id in jQuery.cache )
+ // Skip the window
+ if ( id != 1 && jQuery.cache[ id ].handle )
+ jQuery.event.remove( jQuery.cache[ id ].handle.elem );
+});
+(function(){
+
+ jQuery.support = {};
+
+ var root = document.documentElement,
+ script = document.createElement("script"),
+ div = document.createElement("div"),
+ id = "script" + (new Date).getTime();
+
+ div.style.display = "none";
+ div.innerHTML = ' <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';
+
+ var all = div.getElementsByTagName("*"),
+ a = div.getElementsByTagName("a")[0];
+
+ // Can't get basic test support
+ if ( !all || !all.length || !a ) {
+ return;
+ }
+
+ jQuery.support = {
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: div.firstChild.nodeType == 3,
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName("tbody").length,
+
+ // Make sure that you can get all elements in an <object> element
+ // IE 7 always returns no results
+ objectAll: !!div.getElementsByTagName("object")[0]
+ .getElementsByTagName("*").length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName("link").length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText insted)
+ style: /red/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: a.getAttribute("href") === "/a",
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ opacity: a.style.opacity === "0.5",
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Will be defined later
+ scriptEval: false,
+ noCloneEvent: true,
+ boxModel: null
+ };
+
+ script.type = "text/javascript";
+ try {
+ script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
+ } catch(e){}
+
+ root.insertBefore( script, root.firstChild );
+
+ // Make sure that the execution of code works by injecting a script
+ // tag with appendChild/createTextNode
+ // (IE doesn't support this, fails, and uses .text instead)
+ if ( window[ id ] ) {
+ jQuery.support.scriptEval = true;
+ delete window[ id ];
+ }
+
+ root.removeChild( script );
+
+ if ( div.attachEvent && div.fireEvent ) {
+ div.attachEvent("onclick", function(){
+ // Cloning a node shouldn't copy over any
+ // bound event handlers (IE does this)
+ jQuery.support.noCloneEvent = false;
+ div.detachEvent("onclick", arguments.callee);
+ });
+ div.cloneNode(true).fireEvent("onclick");
+ }
+
+ // Figure out if the W3C box model works as expected
+ // document.body must exist before we can do this
+ jQuery(function(){
+ var div = document.createElement("div");
+ div.style.width = div.style.paddingLeft = "1px";
+
+ document.body.appendChild( div );
+ jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
+ document.body.removeChild( div ).style.display = 'none';
+ });
+})();
+
+var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
+
+jQuery.props = {
+ "for": "htmlFor",
+ "class": "className",
+ "float": styleFloat,
+ cssFloat: styleFloat,
+ styleFloat: styleFloat,
+ readonly: "readOnly",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ rowspan: "rowSpan",
+ tabindex: "tabIndex"
+};
+jQuery.fn.extend({
+ // Keep a copy of the old load
+ _load: jQuery.fn.load,
+
+ load: function( url, params, callback ) {
+ if ( typeof url !== "string" )
+ return this._load( url );
+
+ var off = url.indexOf(" ");
+ if ( off >= 0 ) {
+ var selector = url.slice(off, url.length);
+ url = url.slice(0, off);
+ }
+
+ // Default to a GET request
+ var type = "GET";
+
+ // If the second parameter was provided
+ if ( params )
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+ // We assume that it's the callback
+ callback = params;
+ params = null;
+
+ // Otherwise, build a param string
+ } else if( typeof params === "object" ) {
+ params = jQuery.param( params );
+ type = "POST";
+ }
+
+ var self = this;
+
+ // Request the remote document
+ jQuery.ajax({
+ url: url,
+ type: type,
+ dataType: "html",
+ data: params,
+ complete: function(res, status){
+ // If successful, inject the HTML into all the matched elements
+ if ( status == "success" || status == "notmodified" )
+ // See if a selector was specified
+ self.html( selector ?
+ // Create a dummy div to hold the results
+ jQuery("<div/>")
+ // inject the contents of the document in, removing the scripts
+ // to avoid any 'Permission Denied' errors in IE
+ .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
+
+ // Locate the specified elements
+ .find(selector) :
+
+ // If not, just inject the full result
+ res.responseText );
+
+ if( callback )
+ self.each( callback, [res.responseText, status, res] );
+ }
+ });
+ return this;
+ },
+
+ serialize: function() {
+ return jQuery.param(this.serializeArray());
+ },
+ serializeArray: function() {
+ return this.map(function(){
+ return this.elements ? jQuery.makeArray(this.elements) : this;
+ })
+ .filter(function(){
+ return this.name && !this.disabled &&
+ (this.checked || /select|textarea/i.test(this.nodeName) ||
+ /text|hidden|password|search/i.test(this.type));
+ })
+ .map(function(i, elem){
+ var val = jQuery(this).val();
+ return val == null ? null :
+ jQuery.isArray(val) ?
+ jQuery.map( val, function(val, i){
+ return {name: elem.name, value: val};
+ }) :
+ {name: elem.name, value: val};
+ }).get();
+ }
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
+ jQuery.fn[o] = function(f){
+ return this.bind(o, f);
+ };
+});
+
+var jsc = now();
+
+jQuery.extend({
+
+ get: function( url, data, callback, type ) {
+ // shift arguments if data argument was ommited
+ if ( jQuery.isFunction( data ) ) {
+ callback = data;
+ data = null;
+ }
+
+ return jQuery.ajax({
+ type: "GET",
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get(url, null, callback, "script");
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get(url, data, callback, "json");
+ },
+
+ post: function( url, data, callback, type ) {
+ if ( jQuery.isFunction( data ) ) {
+ callback = data;
+ data = {};
+ }
+
+ return jQuery.ajax({
+ type: "POST",
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ },
+
+ ajaxSetup: function( settings ) {
+ jQuery.extend( jQuery.ajaxSettings, settings );
+ },
+
+ ajaxSettings: {
+ url: location.href,
+ global: true,
+ type: "GET",
+ contentType: "application/x-www-form-urlencoded",
+ processData: true,
+ async: true,
+ /*
+ timeout: 0,
+ data: null,
+ username: null,
+ password: null,
+ */
+ // Create the request object; Microsoft failed to properly
+ // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
+ // This function can be overriden by calling jQuery.ajaxSetup
+ xhr:function(){
+ return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
+ },
+ accepts: {
+ xml: "application/xml, text/xml",
+ html: "text/html",
+ script: "text/javascript, application/javascript",
+ json: "application/json, text/javascript",
+ text: "text/plain",
+ _default: "*/*"
+ }
+ },
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+
+ ajax: function( s ) {
+ // Extend the settings, but re-extend 's' so that it can be
+ // checked again later (in the test suite, specifically)
+ s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
+
+ var jsonp, jsre = /=\?(&|$)/g, status, data,
+ type = s.type.toUpperCase();
+
+ // convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" )
+ s.data = jQuery.param(s.data);
+
+ // Handle JSONP Parameter Callbacks
+ if ( s.dataType == "jsonp" ) {
+ if ( type == "GET" ) {
+ if ( !s.url.match(jsre) )
+ s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+ } else if ( !s.data || !s.data.match(jsre) )
+ s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+ s.dataType = "json";
+ }
+
+ // Build temporary JSONP function
+ if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
+ jsonp = "jsonp" + jsc++;
+
+ // Replace the =? sequence both in the query string and the data
+ if ( s.data )
+ s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+ s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+ // We need to make sure
+ // that a JSONP style response is executed properly
+ s.dataType = "script";
+
+ // Handle JSONP-style loading
+ window[ jsonp ] = function(tmp){
+ data = tmp;
+ success();
+ complete();
+ // Garbage collect
+ window[ jsonp ] = undefined;
+ try{ delete window[ jsonp ]; } catch(e){}
+ if ( head )
+ head.removeChild( script );
+ };
+ }
+
+ if ( s.dataType == "script" && s.cache == null )
+ s.cache = false;
+
+ if ( s.cache === false && type == "GET" ) {
+ var ts = now();
+ // try replacing _= if it is there
+ var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
+ // if nothing was replaced, add timestamp to the end
+ s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
+ }
+
+ // If data is available, append data to url for get requests
+ if ( s.data && type == "GET" ) {
+ s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
+
+ // IE likes to send both get and post data, prevent this
+ s.data = null;
+ }
+
+ // Watch for a new set of requests
+ if ( s.global && ! jQuery.active++ )
+ jQuery.event.trigger( "ajaxStart" );
+
+ // Matches an absolute URL, and saves the domain
+ var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
+
+ // If we're requesting a remote document
+ // and trying to load JSON or Script with a GET
+ if ( s.dataType == "script" && type == "GET" && parts
+ && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
+
+ var head = document.getElementsByTagName("head")[0];
+ var script = document.createElement("script");
+ script.src = s.url;
+ if (s.scriptCharset)
+ script.charset = s.scriptCharset;
+
+ // Handle Script loading
+ if ( !jsonp ) {
+ var done = false;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function(){
+ if ( !done && (!this.readyState ||
+ this.readyState == "loaded" || this.readyState == "complete") ) {
+ done = true;
+ success();
+ complete();
+
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
+ head.removeChild( script );
+ }
+ };
+ }
+
+ head.appendChild(script);
+
+ // We handle everything using the script element injection
+ return undefined;
+ }
+
+ var requestDone = false;
+
+ // Create the request object
+ var xhr = s.xhr();
+
+ // Open the socket
+ // Passing null username, generates a login popup on Opera (#2865)
+ if( s.username )
+ xhr.open(type, s.url, s.async, s.username, s.password);
+ else
+ xhr.open(type, s.url, s.async);
+
+ // Need an extra try/catch for cross domain requests in Firefox 3
+ try {
+ // Set the correct header, if data is being sent
+ if ( s.data )
+ xhr.setRequestHeader("Content-Type", s.contentType);
+
+ // Set the If-Modified-Since header, if ifModified mode.
+ if ( s.ifModified )
+ xhr.setRequestHeader("If-Modified-Since",
+ jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
+
+ // Set header so the called script knows that it's an XMLHttpRequest
+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+
+ // Set the Accepts header for the server, depending on the dataType
+ xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
+ s.accepts[ s.dataType ] + ", */*" :
+ s.accepts._default );
+ } catch(e){}
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
+ // Handle the global AJAX counter
+ if ( s.global && ! --jQuery.active )
+ jQuery.event.trigger( "ajaxStop" );
+ // close opended socket
+ xhr.abort();
+ return false;
+ }
+
+ if ( s.global )
+ jQuery.event.trigger("ajaxSend", [xhr, s]);
+
+ // Wait for a response to come back
+ var onreadystatechange = function(isTimeout){
+ // The request was aborted, clear the interval and decrement jQuery.active
+ if (xhr.readyState == 0) {
+ if (ival) {
+ // clear poll interval
+ clearInterval(ival);
+ ival = null;
+ // Handle the global AJAX counter
+ if ( s.global && ! --jQuery.active )
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ // The transfer is complete and the data is available, or the request timed out
+ } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
+ requestDone = true;
+
+ // clear poll interval
+ if (ival) {
+ clearInterval(ival);
+ ival = null;
+ }
+
+ status = isTimeout == "timeout" ? "timeout" :
+ !jQuery.httpSuccess( xhr ) ? "error" :
+ s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
+ "success";
+
+ if ( status == "success" ) {
+ // Watch for, and catch, XML document parse errors
+ try {
+ // process the data (runs the xml through httpData regardless of callback)
+ data = jQuery.httpData( xhr, s.dataType, s );
+ } catch(e) {
+ status = "parsererror";
+ }
+ }
+
+ // Make sure that the request was successful or notmodified
+ if ( status == "success" ) {
+ // Cache Last-Modified header, if ifModified mode.
+ var modRes;
+ try {
+ modRes = xhr.getResponseHeader("Last-Modified");
+ } catch(e) {} // swallow exception thrown by FF if header is not available
+
+ if ( s.ifModified && modRes )
+ jQuery.lastModified[s.url] = modRes;
+
+ // JSONP handles its own success callback
+ if ( !jsonp )
+ success();
+ } else
+ jQuery.handleError(s, xhr, status);
+
+ // Fire the complete handlers
+ complete();
+
+ if ( isTimeout )
+ xhr.abort();
+
+ // Stop memory leaks
+ if ( s.async )
+ xhr = null;
+ }
+ };
+
+ if ( s.async ) {
+ // don't attach the handler to the request, just poll it instead
+ var ival = setInterval(onreadystatechange, 13);
+
+ // Timeout checker
+ if ( s.timeout > 0 )
+ setTimeout(function(){
+ // Check to see if the request is still happening
+ if ( xhr && !requestDone )
+ onreadystatechange( "timeout" );
+ }, s.timeout);
+ }
+
+ // Send the data
+ try {
+ xhr.send(s.data);
+ } catch(e) {
+ jQuery.handleError(s, xhr, null, e);
+ }
+
+ // firefox 1.5 doesn't fire statechange for sync requests
+ if ( !s.async )
+ onreadystatechange();
+
+ function success(){
+ // If a local callback was specified, fire it and pass it the data
+ if ( s.success )
+ s.success( data, status );
+
+ // Fire the global callback
+ if ( s.global )
+ jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
+ }
+
+ function complete(){
+ // Process result
+ if ( s.complete )
+ s.complete(xhr, status);
+
+ // The request was completed
+ if ( s.global )
+ jQuery.event.trigger( "ajaxComplete", [xhr, s] );
+
+ // Handle the global AJAX counter
+ if ( s.global && ! --jQuery.active )
+ jQuery.event.trigger( "ajaxStop" );
+ }
+
+ // return XMLHttpRequest to allow aborting the request etc.
+ return xhr;
+ },
+
+ handleError: function( s, xhr, status, e ) {
+ // If a local callback was specified, fire it
+ if ( s.error ) s.error( xhr, status, e );
+
+ // Fire the global callback
+ if ( s.global )
+ jQuery.event.trigger( "ajaxError", [xhr, s, e] );
+ },
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Determines if an XMLHttpRequest was successful or not
+ httpSuccess: function( xhr ) {
+ try {
+ // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+ return !xhr.status && location.protocol == "file:" ||
+ ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
+ } catch(e){}
+ return false;
+ },
+
+ // Determines if an XMLHttpRequest returns NotModified
+ httpNotModified: function( xhr, url ) {
+ try {
+ var xhrRes = xhr.getResponseHeader("Last-Modified");
+
+ // Firefox always returns 200. check Last-Modified date
+ return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
+ } catch(e){}
+ return false;
+ },
+
+ httpData: function( xhr, type, s ) {
+ var ct = xhr.getResponseHeader("content-type"),
+ xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
+ data = xml ? xhr.responseXML : xhr.responseText;
+
+ if ( xml && data.documentElement.tagName == "parsererror" )
+ throw "parsererror";
+
+ // Allow a pre-filtering function to sanitize the response
+ // s != null is checked to keep backwards compatibility
+ if( s && s.dataFilter )
+ data = s.dataFilter( data, type );
+
+ // The filter can actually parse the response
+ if( typeof data === "string" ){
+
+ // If the type is "script", eval it in global context
+ if ( type == "script" )
+ jQuery.globalEval( data );
+
+ // Get the JavaScript object, if JSON is used.
+ if ( type == "json" )
+ data = window["eval"]("(" + data + ")");
+ }
+
+ return data;
+ },
+
+ // Serialize an array of form elements or a set of
+ // key/values into a query string
+ param: function( a ) {
+ var s = [ ];
+
+ function add( key, value ){
+ s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
+ };
+
+ // If an array was passed in, assume that it is an array
+ // of form elements
+ if ( jQuery.isArray(a) || a.jquery )
+ // Serialize the form elements
+ jQuery.each( a, function(){
+ add( this.name, this.value );
+ });
+
+ // Otherwise, assume that it's an object of key/value pairs
+ else
+ // Serialize the key/values
+ for ( var j in a )
+ // If the value is an array then the key names need to be repeated
+ if ( jQuery.isArray(a[j]) )
+ jQuery.each( a[j], function(){
+ add( j, this );
+ });
+ else
+ add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
+
+ // Return the resulting serialization
+ return s.join("&").replace(/%20/g, "+");
+ }
+
+});
+var elemdisplay = {},
+ timerId,
+ fxAttrs = [
+ // height animations
+ [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+ // width animations
+ [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+ // opacity animations
+ [ "opacity" ]
+ ];
+
+function genFx( type, num ){
+ var obj = {};
+ jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
+ obj[ this ] = type;
+ });
+ return obj;
+}
+
+jQuery.fn.extend({
+ show: function(speed,callback){
+ if ( speed ) {
+ return this.animate( genFx("show", 3), speed, callback);
+ } else {
+ for ( var i = 0, l = this.length; i < l; i++ ){
+ var old = jQuery.data(this[i], "olddisplay");
+
+ this[i].style.display = old || "";
+
+ if ( jQuery.css(this[i], "display") === "none" ) {
+ var tagName = this[i].tagName, display;
+
+ if ( elemdisplay[ tagName ] ) {
+ display = elemdisplay[ tagName ];
+ } else {
+ var elem = jQuery("<" + tagName + " />").appendTo("body");
+
+ display = elem.css("display");
+ if ( display === "none" )
+ display = "block";
+
+ elem.remove();
+
+ elemdisplay[ tagName ] = display;
+ }
+
+ jQuery.data(this[i], "olddisplay", display);
+ }
+ }
+
+ // Set the display of the elements in a second loop
+ // to avoid the constant reflow
+ for ( var i = 0, l = this.length; i < l; i++ ){
+ this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
+ }
+
+ return this;
+ }
+ },
+
+ hide: function(speed,callback){
+ if ( speed ) {
+ return this.animate( genFx("hide", 3), speed, callback);
+ } else {
+ for ( var i = 0, l = this.length; i < l; i++ ){
+ var old = jQuery.data(this[i], "olddisplay");
+ if ( !old && old !== "none" )
+ jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
+ }
+
+ // Set the display of the elements in a second loop
+ // to avoid the constant reflow
+ for ( var i = 0, l = this.length; i < l; i++ ){
+ this[i].style.display = "none";
+ }
+
+ return this;
+ }
+ },
+
+ // Save the old toggle function
+ _toggle: jQuery.fn.toggle,
+
+ toggle: function( fn, fn2 ){
+ var bool = typeof fn === "boolean";
+
+ return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
+ this._toggle.apply( this, arguments ) :
+ fn == null || bool ?
+ this.each(function(){
+ var state = bool ? fn : jQuery(this).is(":hidden");
+ jQuery(this)[ state ? "show" : "hide" ]();
+ }) :
+ this.animate(genFx("toggle", 3), fn, fn2);
+ },
+
+ fadeTo: function(speed,to,callback){
+ return this.animate({opacity: to}, speed, callback);
+ },
+
+ animate: function( prop, speed, easing, callback ) {
+ var optall = jQuery.speed(speed, easing, callback);
+
+ return this[ optall.queue === false ? "each" : "queue" ](function(){
+
+ var opt = jQuery.extend({}, optall), p,
+ hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
+ self = this;
+
+ for ( p in prop ) {
+ if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
+ return opt.complete.call(this);
+
+ if ( ( p == "height" || p == "width" ) && this.style ) {
+ // Store display property
+ opt.display = jQuery.css(this, "display");
+
+ // Make sure that nothing sneaks out
+ opt.overflow = this.style.overflow;
+ }
+ }
+
+ if ( opt.overflow != null )
+ this.style.overflow = "hidden";
+
+ opt.curAnim = jQuery.extend({}, prop);
+
+ jQuery.each( prop, function(name, val){
+ var e = new jQuery.fx( self, opt, name );
+
+ if ( /toggle|show|hide/.test(val) )
+ e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+ else {
+ var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
+ start = e.cur(true) || 0;
+
+ if ( parts ) {
+ var end = parseFloat(parts[2]),
+ unit = parts[3] || "px";
+
+ // We need to compute starting value
+ if ( unit != "px" ) {
+ self.style[ name ] = (end || 1) + unit;
+ start = ((end || 1) / e.cur(true)) * start;
+ self.style[ name ] = start + unit;
+ }
+
+ // If a +=/-= token was provided, we're doing a relative animation
+ if ( parts[1] )
+ end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
+
+ e.custom( start, end, unit );
+ } else
+ e.custom( start, val, "" );
+ }
+ });
+
+ // For JS strict compliance
+ return true;
+ });
+ },
+
+ stop: function(clearQueue, gotoEnd){
+ var timers = jQuery.timers;
+
+ if (clearQueue)
+ this.queue([]);
+
+ this.each(function(){
+ // go in reverse order so anything added to the queue during the loop is ignored
+ for ( var i = timers.length - 1; i >= 0; i-- )
+ if ( timers[i].elem == this ) {
+ if (gotoEnd)
+ // force the next step to be the last
+ timers[i](true);
+ timers.splice(i, 1);
+ }
+ });
+
+ // start the next in the queue if the last step wasn't forced
+ if (!gotoEnd)
+ this.dequeue();
+
+ return this;
+ }
+
+});
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx("show", 1),
+ slideUp: genFx("hide", 1),
+ slideToggle: genFx("toggle", 1),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" }
+}, function( name, props ){
+ jQuery.fn[ name ] = function( speed, callback ){
+ return this.animate( props, speed, callback );
+ };
+});
+
+jQuery.extend({
+
+ speed: function(speed, easing, fn) {
+ var opt = typeof speed === "object" ? speed : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
+
+ // Queueing
+ opt.old = opt.complete;
+ opt.complete = function(){
+ if ( opt.queue !== false )
+ jQuery(this).dequeue();
+ if ( jQuery.isFunction( opt.old ) )
+ opt.old.call( this );
+ };
+
+ return opt;
+ },
+
+ easing: {
+ linear: function( p, n, firstNum, diff ) {
+ return firstNum + diff * p;
+ },
+ swing: function( p, n, firstNum, diff ) {
+ return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+ }
+ },
+
+ timers: [],
+
+ fx: function( elem, options, prop ){
+ this.options = options;
+ this.elem = elem;
+ this.prop = prop;
+
+ if ( !options.orig )
+ options.orig = {};
+ }
+
+});
+
+jQuery.fx.prototype = {
+
+ // Simple function for setting a style value
+ update: function(){
+ if ( this.options.step )
+ this.options.step.call( this.elem, this.now, this );
+
+ (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+
+ // Set display property to block for height/width animations
+ if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
+ this.elem.style.display = "block";
+ },
+
+ // Get the current size
+ cur: function(force){
+ if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
+ return this.elem[ this.prop ];
+
+ var r = parseFloat(jQuery.css(this.elem, this.prop, force));
+ return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
+ },
+
+ // Start an animation from one number to another
+ custom: function(from, to, unit){
+ this.startTime = now();
+ this.start = from;
+ this.end = to;
+ this.unit = unit || this.unit || "px";
+ this.now = this.start;
+ this.pos = this.state = 0;
+
+ var self = this;
+ function t(gotoEnd){
+ return self.step(gotoEnd);
+ }
+
+ t.elem = this.elem;
+
+ if ( t() && jQuery.timers.push(t) && !timerId ) {
+ timerId = setInterval(function(){
+ var timers = jQuery.timers;
+
+ for ( var i = 0; i < timers.length; i++ )
+ if ( !timers[i]() )
+ timers.splice(i--, 1);
+
+ if ( !timers.length ) {
+ clearInterval( timerId );
+ timerId = undefined;
+ }
+ }, 13);
+ }
+ },
+
+ // Simple 'show' function
+ show: function(){
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+ this.options.show = true;
+
+ // Begin the animation
+ // Make sure that we start at a small width/height to avoid any
+ // flash of content
+ this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
+
+ // Start by showing the element
+ jQuery(this.elem).show();
+ },
+
+ // Simple 'hide' function
+ hide: function(){
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+ this.options.hide = true;
+
+ // Begin the animation
+ this.custom(this.cur(), 0);
+ },
+
+ // Each step of an animation
+ step: function(gotoEnd){
+ var t = now();
+
+ if ( gotoEnd || t >= this.options.duration + this.startTime ) {
+ this.now = this.end;
+ this.pos = this.state = 1;
+ this.update();
+
+ this.options.curAnim[ this.prop ] = true;
+
+ var done = true;
+ for ( var i in this.options.curAnim )
+ if ( this.options.curAnim[i] !== true )
+ done = false;
+
+ if ( done ) {
+ if ( this.options.display != null ) {
+ // Reset the overflow
+ this.elem.style.overflow = this.options.overflow;
+
+ // Reset the display
+ this.elem.style.display = this.options.display;
+ if ( jQuery.css(this.elem, "display") == "none" )
+ this.elem.style.display = "block";
+ }
+
+ // Hide the element if the "hide" operation was done
+ if ( this.options.hide )
+ jQuery(this.elem).hide();
+
+ // Reset the properties, if the item has been hidden or shown
+ if ( this.options.hide || this.options.show )
+ for ( var p in this.options.curAnim )
+ jQuery.attr(this.elem.style, p, this.options.orig[p]);
+
+ // Execute the complete function
+ this.options.complete.call( this.elem );
+ }
+
+ return false;
+ } else {
+ var n = t - this.startTime;
+ this.state = n / this.options.duration;
+
+ // Perform the easing function, defaults to swing
+ this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
+ this.now = this.start + ((this.end - this.start) * this.pos);
+
+ // Perform the next step of the animation
+ this.update();
+ }
+
+ return true;
+ }
+
+};
+
+jQuery.extend( jQuery.fx, {
+ speeds:{
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+ },
+ step: {
+
+ opacity: function(fx){
+ jQuery.attr(fx.elem.style, "opacity", fx.now);
+ },
+
+ _default: function(fx){
+ if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
+ fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+ else
+ fx.elem[ fx.prop ] = fx.now;
+ }
+ }
+});
+if ( document.documentElement["getBoundingClientRect"] )
+ jQuery.fn.offset = function() {
+ if ( !this[0] ) return { top: 0, left: 0 };
+ if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
+ var box = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
+ clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
+ top = box.top + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop,
+ left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
+ return { top: top, left: left };
+ };
+else
+ jQuery.fn.offset = function() {
+ if ( !this[0] ) return { top: 0, left: 0 };
+ if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
+ jQuery.offset.initialized || jQuery.offset.initialize();
+
+ var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
+ doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
+ body = doc.body, defaultView = doc.defaultView,
+ prevComputedStyle = defaultView.getComputedStyle(elem, null),
+ top = elem.offsetTop, left = elem.offsetLeft,
+ isAbsolute = prevComputedStyle.position === "absolute"; //RF: added by rf-team
+
+ while ( (elem = elem.parentNode) && elem !== body && elem !== docElem && prevComputedStyle.position !== "fixed" ) {
+ computedStyle = defaultView.getComputedStyle(elem, null);
+
+ //RF: added by rf-team
+ if ( (!isAbsolute && prevComputedStyle.position === "static") /* add scroll for statically positioned elements */ ||
+ prevComputedStyle.position === "relative" /* not sure we need this - have to test */ ||
+ elem === offsetParent /* add scroll offset of offsetParent element */ ) {
+ top -= elem.scrollTop, left -= elem.scrollLeft;
+ isAbsolute = prevComputedStyle.position === "absolute";
+ }
+ //RF: end
+
+ if ( elem === offsetParent ) {
+ top += elem.offsetTop, left += elem.offsetLeft;
+ if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
+ top += parseInt( computedStyle.borderTopWidth, 10) || 0,
+ left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+ prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
+ }
+ if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
+ top += parseInt( computedStyle.borderTopWidth, 10) || 0,
+ left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+ prevComputedStyle = computedStyle;
+ }
+
+ if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
+ top += body.offsetTop,
+ left += body.offsetLeft;
+
+ if ( prevComputedStyle.position === "fixed" )
+ top += Math.max(docElem.scrollTop, body.scrollTop),
+ left += Math.max(docElem.scrollLeft, body.scrollLeft);
+
+
+ return { top: top, left: left };
+ };
+
+jQuery.offset = {
+ initialize: function() {
+ if ( this.initialized ) return;
+ var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
+ html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';
+
+ rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
+ for ( prop in rules ) container.style[prop] = rules[prop];
+
+ container.innerHTML = html;
+ body.insertBefore(container, body.firstChild);
+ innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
+
+ this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
+ this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
+
+ innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
+ this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
+
+ body.style.marginTop = '1px';
+ this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
+ body.style.marginTop = bodyMarginTop;
+
+ body.removeChild(container);
+ this.initialized = true;
+ },
+
+ bodyOffset: function(body) {
+ jQuery.offset.initialized || jQuery.offset.initialize();
+ var top = body.offsetTop, left = body.offsetLeft;
+ if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
+ top += parseInt( jQuery.curCSS(body, 'marginTop', true), 10 ) || 0,
+ left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
+ return { top: top, left: left };
+ }
+};
+
+
+jQuery.fn.extend({
+ position: function() {
+ var left = 0, top = 0, results;
+
+ if ( this[0] ) {
+ // Get *real* offsetParent
+ var offsetParent = this.offsetParent(),
+
+ // Get correct offsets
+ offset = this.offset(),
+ parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+ // Subtract element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ offset.top -= num( this, 'marginTop' );
+ offset.left -= num( this, 'marginLeft' );
+
+ // Add offsetParent borders
+ parentOffset.top += num( offsetParent, 'borderTopWidth' );
+ parentOffset.left += num( offsetParent, 'borderLeftWidth' );
+
+ // Subtract the two offsets
+ results = {
+ top: offset.top - parentOffset.top,
+ left: offset.left - parentOffset.left
+ };
+ }
+
+ return results;
+ },
+
+ offsetParent: function() {
+ var offsetParent = this[0].offsetParent || document.body;
+ while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
+ offsetParent = offsetParent.offsetParent;
+ return jQuery(offsetParent);
+ }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ['Left', 'Top'], function(i, name) {
+ var method = 'scroll' + name;
+
+ jQuery.fn[ method ] = function(val) {
+ if (!this[0]) return null;
+
+ return val !== undefined ?
+
+ // Set the scroll offset
+ this.each(function() {
+ this == window || this == document ?
+ window.scrollTo(
+ !i ? val : jQuery(window).scrollLeft(),
+ i ? val : jQuery(window).scrollTop()
+ ) :
+ this[ method ] = val;
+ }) :
+
+ // Return the scroll offset
+ this[0] == window || this[0] == document ?
+ self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
+ jQuery.boxModel && document.documentElement[ method ] ||
+ document.body[ method ] :
+ this[0][ method ];
+ };
+});
+
+(function() {
+ var safariCompatMode;
+ var getCompatMode = function() {
+ var compatMode = document.compatMode;
+ if (!compatMode && jQuery.browser.safari) {
+ if (!safariCompatMode) {
+ //detect compatMode as described in http://code.google.com/p/doctype/wiki/ArticleCompatMode
+ var width = jQuery(document.createElement("div")).attr('style', 'position:absolute;width:0;height:0;width:1')
+ .css('width');
+ safariCompatMode = compatMode = (width == '1px' ? 'BackCompat' : 'CSS1Compat');
+ } else {
+ compatMode = safariCompatMode;
+ }
+ }
+
+ return compatMode;
+ };
+
+
+ // Create innerHeight, innerWidth, outerHeight and outerWidth methods
+ jQuery.each([ "Height", "Width" ], function(i, name){
+
+ var tl = i ? "Left" : "Top", // top or left
+ br = i ? "Right" : "Bottom", // bottom or right
+ lower = name.toLowerCase();
+
+ // innerHeight and innerWidth
+ jQuery.fn["inner" + name] = function(){
+ return this[0] ?
+ jQuery.css( this[0], lower, false, "padding" ) :
+ null;
+ };
+
+ // outerHeight and outerWidth
+ jQuery.fn["outer" + name] = function(margin) {
+ return this[0] ?
+ jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) :
+ null;
+ };
+
+ var type = name.toLowerCase();
+
+ jQuery.fn[ type ] = function( size ) {
+ // Get window width or height
+ return this[0] == window ?
+ // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+ getCompatMode() == "CSS1Compat" && document.documentElement[ "client" + name ] ||
+ document.body[ "client" + name ] :
+
+ // Get document width or height
+ this[0] == document ?
+ // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+ Math.max(
+ document.documentElement["client" + name],
+ document.body["scroll" + name], document.documentElement["scroll" + name],
+ document.body["offset" + name], document.documentElement["offset" + name]
+ ) :
+
+ // Get or set width or height on the element
+ size === undefined ?
+ // Get width or height on the element
+ (this.length ? jQuery.css( this[0], type ) : null) :
+
+ // Set the width or height on the element (default to pixels if value is unitless)
+ this.css( type, typeof size === "string" ? size : size + "px" );
+ };
+
+ });
+}());
+})();
Modified: branches/jsf2.0/framework/impl/src/main/javascript/jquery/patches.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/jquery/patches.js 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/main/javascript/jquery/patches.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -16,9 +16,10 @@
// };
if (window.RichFaces && window.RichFaces.Memory) {
- window.RichFaces.Memory.addCleaner("jquery", function(node) {
+ window.RichFaces.Memory.addCleaner("jquery", function(node, isAjax) {
if (node && node[oldJQuery.expando]) {
oldJQuery.event.remove(node);
+ oldJQuery.removeData(node);
}
});
}
Modified: branches/jsf2.0/framework/impl/src/main/javascript/memory.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/memory.js 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/main/javascript/memory.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -6,21 +6,30 @@
if (!window.RichFaces.Memory) {
window.RichFaces.Memory = {
- cleaners: {},
+ nodeCleaners: {},
+ componentCleaners: {},
addCleaner: function (name, cleaner) {
- this.cleaners[name] = cleaner;
+ this.nodeCleaners[name] = cleaner;
},
- applyCleaners: function (node) {
- for (var name in this.cleaners) {
- this.cleaners[name](node);
+ addComponentCleaner: function (name, cleaner, checker) {
+ this.componentCleaners[name] = {cleaner: cleaner, checker: checker};
+ },
+
+ applyCleaners: function (node, isAjax, componentNodes) {
+ for (var name in this.nodeCleaners) {
+ this.nodeCleaners[name](node, isAjax);
}
+ for (var name in this.componentCleaners) {
+ if (this.componentCleaners[name].checker(node, isAjax))
+ componentNodes.push(node);
+ }
},
- clean: function (oldNode) {
+ _clean: function (oldNode, isAjax, componentNodes) {
if (oldNode) {
- this.applyCleaners(oldNode);
+ this.applyCleaners(oldNode, isAjax, componentNodes);
//node.all is quicker than recursive traversing
//window doesn't have "all" attribute
@@ -31,20 +40,36 @@
var length = all.length;
for (var counter = 0; counter < length; counter++ ) {
- this.applyCleaners(all[counter]);
+ this.applyCleaners(all[counter], isAjax, componentNodes);
}
} else {
var node = oldNode.firstChild;
while (node) {
- this.clean(node);
+ this._clean(node, isAjax, componentNodes);
node = node.nextSibling;
}
}
}
+ },
+
+ _cleanComponentNodes: function (oldNodes, isAjax) {
+ for (var i=0; i<oldNodes.length; i++) {
+ var node = oldNodes[i];
+ for (var name in this.componentCleaners) {
+ this.componentCleaners[name].cleaner(node, isAjax);
+ }
+ }
+ },
+
+ clean: function (oldNode, isAjax) {
+ var componentNodes = [];
+ this._clean(oldNode, isAjax, componentNodes);
+ this._cleanComponentNodes(componentNodes, isAjax);
+ componentNodes = null;
}
};
- window.RichFaces.Memory.addCleaner("richfaces", function(node) {
+ window.RichFaces.Memory.addComponentCleaner("richfaces", function(node, isAjax) {
var component = node.component;
if (component) {
var destructorName = component["rich:destructor"];
@@ -52,10 +77,12 @@
if (destructorName) {
var destructor = component[destructorName];
if (destructor) {
- destructor.call(component);
+ destructor.call(component, isAjax);
}
}
}
+ }, function(node, isAjax) {
+ return (node.component && node.component["rich:destructor"]);
});
if (window.attachEvent) {
Modified: branches/jsf2.0/framework/impl/src/main/javascript/prototype/patches.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/prototype/patches.js 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/main/javascript/prototype/patches.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -63,7 +63,7 @@
};
if (window.RichFaces && window.RichFaces.Memory) {
- window.RichFaces.Memory.addCleaner("prototype", function(node) {
+ window.RichFaces.Memory.addCleaner("prototype", function(node, isAjax) {
var eventID = node._prototypeEventID ? node._prototypeEventID[0] : undefined;
if (eventID) {
var cache = Event.cache[eventID];
Copied: branches/jsf2.0/framework/impl/src/main/javascript/prototype/prototype-1.6.0.3.js (from rev 14238, trunk/framework/impl/src/main/javascript/prototype/prototype-1.6.0.3.js)
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/prototype/prototype-1.6.0.3.js (rev 0)
+++ branches/jsf2.0/framework/impl/src/main/javascript/prototype/prototype-1.6.0.3.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -0,0 +1,4365 @@
+/* Prototype JavaScript framework, version 1.6.0.3
+ * (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://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0.3',
+
+ Browser: {
+ IE: !!(window.attachEvent &&
+ navigator.userAgent.indexOf('Opera') === -1),
+ Opera: navigator.userAgent.indexOf('Opera') > -1,
+ 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,
+ SelectorsAPI: !!document.querySelector,
+ 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() {
+ 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;
+ }
+};
+
+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 = (function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method);
+
+ value.valueOf = method.valueOf.bind(method);
+ value.toString = method.toString.bind(method);
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+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;
+ }
+ },
+
+ 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)
+ 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(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1]
+ .replace(/\s+/g, '').split(',');
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ 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)));
+ }
+ },
+
+ 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);
+ },
+
+ defer: function() {
+ var args = [0.01].concat($A(arguments));
+ return this.delay.apply(this, args);
+ },
+
+ 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)));
+ };
+ }
+});
+
+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, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ 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.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;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = Object.isUndefined(count) ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ var result = (scriptTag.match(matchOne) || ['', ''])[1];
+ result = result.replace(/</,"<").replace(/\s*<!--[^\r\n]*/, "");
+ return result;
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ 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 }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ 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;
+ });
+ },
+
+ toArray: function() {
+ 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 parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ 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.stripTags().replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(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;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ 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 = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ try {
+ this._each(function(value) {
+ iterator.call(context, value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ var index = -number, slices = [], array = this.toArray();
+ if (number < 1) return array;
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator.call(context, value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator.call(context, value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator.call(context, value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ var result;
+ this.each(function(value, index) {
+ if (iterator.call(context, value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator.call(context, value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator || Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator.call(context, 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) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ 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) {
+ this.each(function(value, index) {
+ memo = iterator.call(context, memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator.call(context, value, index);
+ if (result == null || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator.call(context, value, index);
+ if (result == null || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator || Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator.call(context, value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator.call(context, value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ return this.map(function(value, index) {
+ return {
+ value: value,
+ criteria: iterator.call(context, value, index)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ 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,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ 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 [];
+ // In Safari, only use the `toArray` method if it's not a NodeList.
+ // A NodeList is a function, has an function `item` property, and a numeric
+ // `length` property. Adapted from Google Doctype.
+ if (!(typeof iterable === 'function' && typeof iterable.length ===
+ 'number' && typeof iterable.item === 'function') && 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;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ 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(', ') + ']';
+ }
+});
+
+// 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);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator, context) {
+ $R(0, this, true).each(iterator, context);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$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));
+ }
+
+ 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) {
+ // simulating poorly supported hasOwnProperty
+ if (this._object[key] !== Object.prototype[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.inject([], function(results, pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return results.concat(values.map(toQueryPair.curry(key)));
+ } else results.push(toQueryPair(key, values));
+ return results;
+ }).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;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+
+ 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.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ 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 {
+ 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) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* 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 headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* 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 &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ 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 });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ 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], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ 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);
+ }
+
+ 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)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ 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.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+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))
+ };
+
+ 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.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ 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 $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+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.Node) var Node = { };
+
+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
+ });
+}
+
+(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 || { });
+ if (element) this.Element.prototype = element.prototype;
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ element = $(element);
+ element.style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ element = $(element);
+ element.style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ 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, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ 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();
+ $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(element, 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;
+ 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;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ 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);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (ancestor.contains)
+ return ancestor.contains(element) && ancestor !== element;
+
+ while (element = element.parentNode)
+ if (element == ancestor) return true;
+
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value || value == 'auto') {
+ 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;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ 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;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ 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,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (Prototype.Browser.Opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ 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;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ // RF: added by PY
+ if($(element).getStyle('position') == 'fixed') {
+ var pageOffsets = document.viewport.getScrollOffsets();
+ valueT += pageOffsets[1] + element.offsetTop;
+ valueL += pageOffsets[0] + element.offsetLeft;
+ break;
+ } else {
+ // RF: end
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } // RF: added by PY
+ } while (element);
+ return Element._returnOffset(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.toUpperCase() == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p !== 'static') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return element;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ 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;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return element;
+ // 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
+ && Object.isElement(element)/* changed by Nick - http://dev.rubyonrails.org/ticket/11007 */)
+ 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 && (element.tagName.toUpperCase() == 'BODY'))) {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ // RF: added by PY
+ if(!Prototype.Browser.WebKit && Element.getStyle(element, 'position') == 'fixed') {
+ break;
+ }
+ // RF: end
+ }
+ } while ((element = element.parentNode) && element.tagName); // RF: changed by PY
+
+ 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;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+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);
+ // IE throws an error if element is not in document
+ try { element.offsetParent }
+ catch(e) { return $(document.body) }
+ 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);
+ try { element.offsetParent }
+ catch(e) { return Element._returnOffset(0,0) }
+ 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.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
+ function(proceed, element) {
+ try { element.offsetParent }
+ catch(e) { return Element._returnOffset(0,0) }
+ return proceed(element);
+ }
+ );
+
+ 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;
+ }
+ }
+ }
+ };
+
+ 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 frameBorder').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.toUpperCase() == '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);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div')['__proto__']) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div')['__proto__'];
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+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.toUpperCase(), 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)
+ });
+ }
+
+ 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;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ 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);
+ }
+
+ 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 = { }, B = Prototype.Browser;
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ if (B.WebKit && !document.evaluate) {
+ // Safari <3.0 needs self.innerWidth/Height
+ dimensions[d] = self['inner' + D];
+ } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
+ // Opera <9.5 needs document.body.clientWidth/Height
+ dimensions[d] = document.body['client' + D]
+ } else {
+ dimensions[d] = document.documentElement['client' + D];
+ }
+ });
+ 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 Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+
+ if (this.shouldUseSelectorsAPI()) {
+ this.mode = 'selectorsAPI';
+ } else if (this.shouldUseXPath()) {
+ this.mode = 'xpath';
+ this.compileXPathMatcher();
+ } else {
+ this.mode = "normal";
+ this.compileMatcher();
+ }
+
+ },
+
+ shouldUseXPath: function() {
+ if (!Prototype.BrowserFeatures.XPath) return false;
+
+ var e = this.expression;
+
+ // 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(e))
+ return false;
+
+ return true;
+ },
+
+ shouldUseSelectorsAPI: function() {
+ if (!Prototype.BrowserFeatures.SelectorsAPI) return false;
+
+ if (!Selector._div) Selector._div = new Element('div');
+
+ // Make sure the browser treats the selector as valid. Test on an
+ // isolated element to minimize cost of this check.
+ try {
+ Selector._div.querySelector(this.expression);
+ } catch(e) {
+ return false;
+ }
+
+ return true;
+ },
+
+ compileMatcher: function() {
+ 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;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ 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;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ var e = this.expression, results;
+
+ switch (this.mode) {
+ case 'selectorsAPI':
+ // querySelectorAll queries document-wide, then filters to descendants
+ // of the context element. That's not what we want.
+ // Add an explicit context to the selector if necessary.
+ if (root !== document) {
+ var oldId = root.id, id = $(root).identify();
+
+ // https://jira.jboss.org/jira/browse/RF-5416
+ e = "#" + id.replace(/:/g, '\\:') + " " + e
+ //e = "#" + id + " " + e;
+ }
+
+ results = $A(root.querySelectorAll(e)).map(Element.extend);
+ root.id = oldId;
+
+ return results;
+ case 'xpath':
+ return document._getElementsByXPath(this.xpath, root);
+ default:
+ return this.matcher(root);
+ }
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ 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 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;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+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)]",
+ 'checked': "[@checked]",
+ 'disabled': "[(@disabled) and (@type!='hidden')]",
+ 'enabled': "[not(@disabled) and (@type!='hidden')]",
+ '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 });
+ }
+ }
+ }
+ },
+
+ 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";'
+ },
+
+ 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]+:)?[\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // 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]);
+ }
+ },
+
+ 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;
+ },
+
+ 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++;
+ }
+ },
+
+ // 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);
+ }
+ },
+
+ 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) 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 && (!node.type || node.type !== 'hidden'))
+ 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;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); },
+ '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
+ '*=': function(nv, v) { return nv == v || nv && nv.include(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() + '-'); }
+ },
+
+ 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 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 != 'file' && (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 $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ 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);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+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();
+ 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;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ 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.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, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (Object.isUndefined(value)) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, value) {
+ if (Object.isUndefined(value))
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, currentValue, single = !Object.isArray(value);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ currentValue = this.optionValue(opt);
+ if (single) {
+ if (currentValue == value) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = value.include(currentValue);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ 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) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ 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(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ 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);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } 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) {
+ event = Event.extend(event);
+
+ var node = event.target,
+ type = event.type,
+ currentTarget = event.currentTarget;
+
+ if (currentTarget && currentTarget.tagName) {
+ // Firefox screws up the "click" event when moving between radio buttons
+ // via arrow keys. It also screws up the "load" and "error" events on images,
+ // reporting the document as the target instead of the original image.
+ if (type === 'load' || type === 'error' ||
+ (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
+ && currentTarget.type === 'radio'))
+ node = currentTarget;
+ }
+ if (node.nodeType == Node.TEXT_NODE) node = node.parentNode;
+ return Element.extend(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) {
+ var docElement = document.documentElement,
+ body = document.body || { scrollLeft: 0, scrollTop: 0 };
+ return {
+ x: event.pageX || (event.clientX +
+ (docElement.scrollLeft || body.scrollLeft) -
+ (docElement.clientLeft || 0)),
+ y: event.pageY || (event.clientY +
+ (docElement.scrollTop || body.scrollTop) -
+ (docElement.clientTop || 0))
+ };
+ },
+
+ 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();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true; if (this._stopPropagation) { this._stopPropagation() } }, //RF: changed by Nick
+ preventDefault: function() { this.returnValue = false; if (this._preventDefault) { this._preventDefault() } }, //RF: changed by Nick
+ inspect: function() { return "[object Event]" }
+ });
+
+ 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
+ });
+
+ event._stopPropagation = event.stopPropagation; //RF: added by Nick
+ event._preventDefault = event.preventDefault; //RF: added by Nick
+
+ 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));
+ }
+
+ //commented by Nick for RichFaces
+ /*
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+
+ // Internet Explorer needs to remove event handlers on page unload
+ // in order to avoid memory leaks.
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+ */
+ //commented
+
+ // Safari has a dummy event handler on page unload so that it won't
+ // use its bfcache. Safari <= 3.1 has an issue with restoring the "document"
+ // object when page is returned to via the back button using its bfcache.
+ if (Prototype.Browser.WebKit) {
+ window.addEventListener('unload', Prototype.emptyFunction, false);
+ }
+
+ return {
+ //added by Nick for RichFaces
+ getDOMEventName: getDOMEventName,
+ //added
+
+ 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);
+ }
+ };
+})());
+
+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);
+ }
+
+ } else {
+ // added by Pavel Yaschenko // http://jira.jboss.com/jira/browse/RF-3879
+
+ // for 1.6.0.3
+ if (document.loaded) return;
+
+ if (document.readyState != "complete") { // added by Pavel Yaschenko
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ var contentLoadedScript = $("__onDOMContentLoaded");
+
+ //modified by Nick Belaevski - RF-3745
+ if (contentLoadedScript) {
+ contentLoadedScript.onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+ //modified by Nick Belaevski
+ } // added by Pavel Yaschenko
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+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
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // 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 = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // 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);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ 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;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods();
\ No newline at end of file
Modified: branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/builder.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/builder.js 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/builder.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,6 +1,6 @@
-// script.aculo.us builder.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+// script.aculo.us builder.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
-// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Copyright (c) 2005-2008 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/
@@ -26,7 +26,7 @@
// due to a Firefox bug
node: function(elementName) {
elementName = elementName.toUpperCase();
-
+
// try innerHTML approach
var parentTag = this.NODEMAP[elementName] || 'div';
var parentElement = document.createElement(parentTag);
@@ -34,14 +34,14 @@
parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
} catch(e) {}
var element = parentElement.firstChild || null;
-
+
// see if browser added wrapping tags
if(element && (element.tagName.toUpperCase() != elementName))
element = element.getElementsByTagName(elementName)[0];
-
+
// fallback to createElement approach
if(!element) element = document.createElement(elementName);
-
+
// abort if nothing could be created
if(!element) return;
@@ -62,19 +62,19 @@
// workaround firefox 1.0.X bug
if(!element) {
element = document.createElement(elementName);
- for(attr in arguments[1])
+ for(attr in arguments[1])
element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
}
if(element.tagName.toUpperCase() != elementName)
element = parentElement.getElementsByTagName(elementName)[0];
}
- }
+ }
// text, or array of children
if(arguments[2])
this._children(element, arguments[2]);
- return element;
+ return $(element);
},
_text: function(text) {
return document.createTextNode(text);
@@ -100,7 +100,7 @@
if(typeof children=='object') { // array can hold nodes and text
children.flatten().each( function(e) {
if(typeof e=='object')
- element.appendChild(e)
+ element.appendChild(e);
else
if(Builder._isStringOrNumber(e))
element.appendChild(Builder._text(e));
@@ -117,20 +117,20 @@
$(element).update(html.strip());
return element.down();
},
- dump: function(scope) {
- if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
-
+ dump: function(scope) {
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
+
var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
"BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
"FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
"KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
"PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
"TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
-
- tags.each( function(tag){
- scope[tag] = function() {
- return Builder.node.apply(Builder, [tag].concat($A(arguments)));
- }
+
+ tags.each( function(tag){
+ scope[tag] = function() {
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
+ };
});
}
-}
+};
\ No newline at end of file
Modified: branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/controls.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/controls.js 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/controls.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,24 +1,24 @@
-// script.aculo.us controls.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+// script.aculo.us controls.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
-// 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)
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
// Contributors:
// Richard Livsey
// Rahul Bhargava
// Rob Wills
-//
+//
// 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/
-// Autocompleter.Base handles all the autocompletion functionality
+// Autocompleter.Base handles all the autocompletion functionality
// that's independent of the data source for autocompletion. This
// includes drawing the autocompletion menu, observing keyboard
// and mouse events, and similar.
//
-// Specific autocompleters need to provide, at the very least,
+// Specific autocompleters need to provide, at the very least,
// a getUpdatedChoices function that will be invoked every time
-// the text inside the monitored textbox changes. This method
+// the text inside the monitored textbox changes. This method
// should get the text for which to provide autocompletion by
// invoking this.getToken(), NOT by directly accessing
// this.element.value. This is to allow incremental tokenized
@@ -32,23 +32,23 @@
// will incrementally autocomplete with a comma as the token.
// Additionally, ',' in the above example can be replaced with
// a token array, e.g. { tokens: [',', '\n'] } which
-// enables autocompletion on multiple tokens. This is most
-// useful when one of the tokens is \n (a newline), as it
+// enables autocompletion on multiple tokens. This is most
+// useful when one of the tokens is \n (a newline), as it
// allows smart autocompletion after linebreaks.
if(typeof Effect == 'undefined')
throw("controls.js requires including script.aculo.us' effects.js library");
-var Autocompleter = { }
+var Autocompleter = { };
Autocompleter.Base = Class.create({
baseInitialize: function(element, update, options) {
- element = $(element)
- this.element = element;
- this.update = $(update);
- this.hasFocus = false;
- this.changed = false;
- this.active = false;
- this.index = 0;
+ 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;
@@ -61,28 +61,28 @@
this.options.tokens = this.options.tokens || [];
this.options.frequency = this.options.frequency || 0.4;
this.options.minChars = this.options.minChars || 1;
- this.options.onShow = this.options.onShow ||
- function(element, update){
+ this.options.onShow = this.options.onShow ||
+ function(element, update){
if(!update.style.position || update.style.position=='absolute') {
update.style.position = 'absolute';
Position.clone(element, update, {
- setHeight: false,
+ setHeight: false,
offsetTop: element.offsetHeight
});
}
Effect.Appear(update,{duration:0.15});
};
- this.options.onHide = this.options.onHide ||
+ this.options.onHide = this.options.onHide ||
function(element, update){ new Effect.Fade(update,{duration:0.15}) };
- if(typeof(this.options.tokens) == 'string')
+ 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;
-
+
this.element.setAttribute('autocomplete','off');
Element.hide(this.update);
@@ -93,10 +93,10 @@
show: function() {
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
- if(!this.iefix &&
+ if(!this.iefix &&
(Prototype.Browser.IE) &&
(Element.getStyle(this.update, 'position')=='absolute')) {
- new Insertion.After(this.update,
+ new Insertion.After(this.update,
'<iframe id="' + this.update.id + '_iefix" '+
'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
@@ -104,7 +104,7 @@
}
if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
},
-
+
fixIEOverlapping: function() {
Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
this.iefix.style.zIndex = 1;
@@ -152,15 +152,15 @@
Event.stop(event);
return;
}
- else
- if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
+ else
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
(Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
this.changed = true;
this.hasFocus = true;
if(this.observer) clearTimeout(this.observer);
- this.observer =
+ this.observer =
setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
},
@@ -172,35 +172,35 @@
onHover: function(event) {
var element = Event.findElement(event, 'LI');
- if(this.index != element.autocompleteIndex)
+ if(this.index != element.autocompleteIndex)
{
this.index = element.autocompleteIndex;
this.render();
}
Event.stop(event);
},
-
+
onClick: function(event) {
var element = Event.findElement(event, 'LI');
this.index = element.autocompleteIndex;
this.selectEntry();
this.hide();
},
-
+
onBlur: function(event) {
// needed to make click events working
setTimeout(this.hide.bind(this), 250);
this.hasFocus = false;
- this.active = false;
- },
-
+ this.active = false;
+ },
+
render: function() {
if(this.entryCount > 0) {
for (var i = 0; i < this.entryCount; i++)
- this.index==i ?
- Element.addClassName(this.getEntry(i),"selected") :
+ this.index==i ?
+ Element.addClassName(this.getEntry(i),"selected") :
Element.removeClassName(this.getEntry(i),"selected");
- if(this.hasFocus) {
+ if(this.hasFocus) {
this.show();
this.active = true;
}
@@ -209,27 +209,27 @@
this.hide();
}
},
-
+
markPrevious: function() {
- if(this.index > 0) this.index--
+ if(this.index > 0) this.index--;
else this.index = this.entryCount-1;
this.getEntry(this.index).scrollIntoView(true);
},
-
+
markNext: function() {
- if(this.index < this.entryCount-1) this.index++
+ if(this.index < this.entryCount-1) this.index++;
else this.index = 0;
this.getEntry(this.index).scrollIntoView(false);
},
-
+
getEntry: function(index) {
return this.update.firstChild.childNodes[index];
},
-
+
getCurrentEntry: function() {
return this.getEntry(this.index);
},
-
+
selectEntry: function() {
this.active = false;
this.updateElement(this.getCurrentEntry());
@@ -246,7 +246,7 @@
if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
} else
value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
-
+
var bounds = this.getTokenBounds();
if (bounds[0] != -1) {
var newValue = this.element.value.substr(0, bounds[0]);
@@ -259,7 +259,7 @@
}
this.oldElementValue = this.element.value;
this.element.focus();
-
+
if (this.options.afterUpdateElement)
this.options.afterUpdateElement(this.element, selectedElement);
},
@@ -271,20 +271,20 @@
Element.cleanWhitespace(this.update.down());
if(this.update.firstChild && this.update.down().childNodes) {
- this.entryCount =
+ this.entryCount =
this.update.down().childNodes.length;
for (var i = 0; i < this.entryCount; i++) {
var entry = this.getEntry(i);
entry.autocompleteIndex = i;
this.addObservers(entry);
}
- } else {
+ } else {
this.entryCount = 0;
}
this.stopIndicator();
this.index = 0;
-
+
if(this.entryCount==1 && this.options.autoSelect) {
this.selectEntry();
this.hide();
@@ -300,7 +300,7 @@
},
onObserverEvent: function() {
- this.changed = false;
+ this.changed = false;
this.tokenBounds = null;
if(this.getToken().length>=this.options.minChars) {
this.getUpdatedChoices();
@@ -353,16 +353,16 @@
getUpdatedChoices: function() {
this.startIndicator();
-
- var entry = encodeURIComponent(this.options.paramName) + '=' +
+
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
encodeURIComponent(this.getToken());
this.options.parameters = this.options.callback ?
this.options.callback(this.element, entry) : entry;
- if(this.options.defaultParams)
+ if(this.options.defaultParams)
this.options.parameters += '&' + this.options.defaultParams;
-
+
new Ajax.Request(this.url, this.options);
},
@@ -384,7 +384,7 @@
// - choices - How many autocompletion choices to offer
//
// - partialSearch - If false, the autocompleter will match entered
-// text only at the beginning of strings in the
+// text only at the beginning of strings in the
// autocomplete array. Defaults to true, which will
// match text at the beginning of any *word* in the
// strings in the autocomplete array. If you want to
@@ -401,7 +401,7 @@
// - ignoreCase - Whether to ignore case when autocompleting.
// Defaults to true.
//
-// It's possible to pass in a custom function as the 'selector'
+// It's possible to pass in a custom function as the 'selector'
// option, if you prefer to write your own autocompletion logic.
// In that case, the other options above will not apply unless
// you support them.
@@ -429,20 +429,20 @@
var entry = instance.getToken();
var count = 0;
- for (var i = 0; i < instance.options.array.length &&
- ret.length < instance.options.choices ; i++) {
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
var elem = instance.options.array[i];
- var foundPos = instance.options.ignoreCase ?
- elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
elem.indexOf(entry);
while (foundPos != -1) {
- if (foundPos == 0 && elem.length != entry.length) {
- ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
+ if (foundPos == 0 && elem.length != entry.length) {
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
elem.substr(entry.length) + "</li>");
break;
- } else if (entry.length >= instance.options.partialChars &&
+ } else if (entry.length >= instance.options.partialChars &&
instance.options.partialSearch && foundPos != -1) {
if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
@@ -452,14 +452,14 @@
}
}
- foundPos = instance.options.ignoreCase ?
- elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
elem.indexOf(entry, foundPos + 1);
}
}
if (partial.length)
- ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length));
return "<ul>" + ret.join('') + "</ul>";
}
}, options || { });
@@ -476,7 +476,7 @@
setTimeout(function() {
Field.activate(field);
}, 1);
-}
+};
Ajax.InPlaceEditor = Class.create({
initialize: function(element, url, options) {
@@ -606,7 +606,7 @@
this.triggerCallback('onEnterHover');
},
getText: function() {
- return this.element.innerHTML;
+ return this.element.innerHTML.unescapeHTML();
},
handleAJAXFailure: function(transport) {
this.triggerCallback('onFailure', transport);
@@ -782,7 +782,7 @@
onSuccess: function(transport) {
var js = transport.responseText.strip();
if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
- throw 'Server returned an invalid collection representation.';
+ throw('Server returned an invalid collection representation.');
this._collection = eval(js);
this.checkForExternalText();
}.bind(this),
@@ -939,7 +939,7 @@
loadingCollectionText: 'Loading options...'
};
-// Delayed observer, like Form.Element.Observer,
+// Delayed observer, like Form.Element.Observer,
// but waits for delay after last key input
// Ideal for live-search fields
@@ -949,7 +949,7 @@
this.element = $(element);
this.callback = callback;
this.timer = null;
- this.lastValue = $F(this.element);
+ this.lastValue = $F(this.element);
Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
},
delayedListener: function(event) {
@@ -962,4 +962,4 @@
this.timer = null;
this.callback(this.element, $F(this.element));
}
-});
+});
\ No newline at end of file
Modified: branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/dragdrop.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/dragdrop.js 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/dragdrop.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,8 +1,8 @@
-// script.aculo.us dragdrop.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+// script.aculo.us dragdrop.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
-// 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)
-//
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2008 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/
@@ -34,7 +34,7 @@
options._containers.push($(containment));
}
}
-
+
if(options.accept) options.accept = [options.accept].flatten();
Element.makePositioned(element); // fix IE
@@ -42,34 +42,34 @@
this.drops.push(options);
},
-
+
findDeepestChild: function(drops) {
deepest = drops[0];
-
+
for (i = 1; i < drops.length; ++i)
if (Element.isParent(drops[i].element, deepest.element))
deepest = drops[i];
-
+
return deepest;
},
isContained: function(element, drop) {
var containmentNode;
if(drop.tree) {
- containmentNode = element.treeNode;
+ containmentNode = element.treeNode;
} else {
containmentNode = element.parentNode;
}
return drop._containers.detect(function(c) { return containmentNode == c });
},
-
+
isAffected: function(point, element, drop) {
return (
(drop.element!=element) &&
((!drop._containers) ||
this.isContained(element, drop)) &&
((!drop.accept) ||
- (Element.classNames(element).detect(
+ (Element.classNames(element).detect(
function(v) { return drop.accept.include(v) } ) )) &&
Position.within(drop.element, point[0], point[1]) );
},
@@ -89,12 +89,12 @@
show: function(point, element) {
if(!this.drops.length) return;
var drop, affected = [];
-
+
this.drops.each( function(drop) {
if(Droppables.isAffected(point, element, drop))
affected.push(drop);
});
-
+
if(affected.length>0)
drop = Droppables.findDeepestChild(affected);
@@ -103,7 +103,7 @@
Position.within(drop.element, point[0], point[1]);
if(drop.onHover)
drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
-
+
if (drop != this.last_active) Droppables.activate(drop);
}
},
@@ -114,8 +114,8 @@
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);
- return true;
+ this.last_active.onDrop(element, this.last_active.element, event);
+ return true;
}
},
@@ -123,25 +123,25 @@
if(this.last_active)
this.deactivate(this.last_active);
}
-}
+};
var Draggables = {
drags: [],
observers: [],
-
+
register: function(draggable) {
if(this.drags.length == 0) {
this.eventMouseUp = this.endDrag.bindAsEventListener(this);
this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
this.eventKeypress = this.keyPress.bindAsEventListener(this);
-
+
Event.observe(document, "mouseup", this.eventMouseUp);
Event.observe(document, "mousemove", this.eventMouseMove);
Event.observe(document, "keypress", this.eventKeypress);
}
this.drags.push(draggable);
},
-
+
unregister: function(draggable) {
this.drags = this.drags.reject(function(d) { return d==draggable });
if(this.drags.length == 0) {
@@ -150,24 +150,24 @@
Event.stopObserving(document, "keypress", this.eventKeypress);
}
},
-
+
activate: function(draggable) {
- if(draggable.options.delay) {
- this._timeout = setTimeout(function() {
- Draggables._timeout = null;
- window.focus();
- Draggables.activeDraggable = draggable;
- }.bind(this), draggable.options.delay);
+ if(draggable.options.delay) {
+ this._timeout = setTimeout(function() {
+ Draggables._timeout = null;
+ window.focus();
+ Draggables.activeDraggable = draggable;
+ }.bind(this), draggable.options.delay);
} else {
window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
this.activeDraggable = draggable;
}
},
-
+
deactivate: function() {
this.activeDraggable = null;
},
-
+
updateDrag: function(event) {
if(!this.activeDraggable) return;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
@@ -175,36 +175,36 @@
// the same coordinates, prevent needless redrawing (moz bug?)
if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
this._lastPointer = pointer;
-
+
this.activeDraggable.updateDrag(event, pointer);
},
-
+
endDrag: function(event) {
- if(this._timeout) {
- clearTimeout(this._timeout);
- this._timeout = null;
+ if(this._timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = null;
}
if(!this.activeDraggable) return;
this._lastPointer = null;
this.activeDraggable.endDrag(event);
this.activeDraggable = null;
},
-
+
keyPress: function(event) {
if(this.activeDraggable)
this.activeDraggable.keyPress(event);
},
-
+
addObserver: function(observer) {
this.observers.push(observer);
this._cacheObserverCallbacks();
},
-
+
removeObserver: function(element) { // element instead of observer fixes mem leaks
this.observers = this.observers.reject( function(o) { return o.element==element });
this._cacheObserverCallbacks();
},
-
+
notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
if(this[eventName+'Count'] > 0)
this.observers.each( function(o) {
@@ -212,7 +212,7 @@
});
if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
},
-
+
_cacheObserverCallbacks: function() {
['onStart','onEnd','onDrag'].each( function(eventName) {
Draggables[eventName+'Count'] = Draggables.observers.select(
@@ -220,7 +220,7 @@
).length;
});
}
-}
+};
/*--------------------------------------------------------------------------*/
@@ -236,12 +236,12 @@
},
endeffect: function(element) {
var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
- new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
queue: {scope:'_draggable', position:'end'},
- afterFinish: function(){
- Draggable._dragging[element] = false
+ afterFinish: function(){
+ Draggable._dragging[element] = false
}
- });
+ });
},
zindex: 1000,
revert: false,
@@ -252,57 +252,57 @@
snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
delay: 0
};
-
+
if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
Object.extend(defaults, {
starteffect: function(element) {
element._opacity = Element.getOpacity(element);
Draggable._dragging[element] = true;
- new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
}
});
-
+
var options = Object.extend(defaults, arguments[1] || { });
this.element = $(element);
-
+
if(options.handle && Object.isString(options.handle))
this.handle = this.element.down('.'+options.handle, 0);
-
+
if(!this.handle) this.handle = $(options.handle);
if(!this.handle) this.handle = this.element;
-
+
if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
options.scroll = $(options.scroll);
this._isScrollChild = Element.childOf(this.element, options.scroll);
}
- Element.makePositioned(this.element); // fix IE
+ Element.makePositioned(this.element); // fix IE
this.options = options;
- this.dragging = false;
+ this.dragging = false;
this.eventMouseDown = this.initDrag.bindAsEventListener(this);
Event.observe(this.handle, "mousedown", this.eventMouseDown);
-
+
Draggables.register(this);
},
-
+
destroy: function() {
Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
Draggables.unregister(this);
},
-
+
currentDelta: function() {
return([
parseInt(Element.getStyle(this.element,'left') || '0'),
parseInt(Element.getStyle(this.element,'top') || '0')]);
},
-
+
initDrag: function(event) {
if(!Object.isUndefined(Draggable._dragging[this.element]) &&
Draggable._dragging[this.element]) return;
- if(Event.isLeftClick(event)) {
+ if(Event.isLeftClick(event)) {
// abort on form elements, fixes a Firefox issue
var src = Event.element(event);
if((tag_name = src.tagName.toUpperCase()) && (
@@ -311,34 +311,34 @@
tag_name=='OPTION' ||
tag_name=='BUTTON' ||
tag_name=='TEXTAREA')) return;
-
+
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var pos = Position.cumulativeOffset(this.element);
this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
-
+
Draggables.activate(this);
Event.stop(event);
}
},
-
+
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);
this.element.style.zIndex = this.options.zindex;
}
-
+
if(this.options.ghosting) {
this._clone = this.element.cloneNode(true);
- this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
- if (!this.element._originallyAbsolute)
+ this._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+ if (!this._originallyAbsolute)
Position.absolutize(this.element);
this.element.parentNode.insertBefore(this._clone, this.element);
}
-
+
if(this.options.scroll) {
if (this.options.scroll == window) {
var where = this._getWindowScroll(this.options.scroll);
@@ -349,28 +349,28 @@
this.originalScrollTop = this.options.scroll.scrollTop;
}
}
-
+
Draggables.notify('onStart', this, event);
-
+
if(this.options.starteffect) this.options.starteffect(this.element);
},
-
+
updateDrag: function(event, pointer) {
if(!this.dragging) this.startDrag(event);
-
+
if(!this.options.quiet){
Position.prepare();
Droppables.show(pointer, this.element);
}
-
+
Draggables.notify('onDrag', this, event);
-
+
this.draw(pointer);
if(this.options.change) this.options.change(this);
-
+
if(this.options.scroll) {
this.stopScrolling();
-
+
var p;
if (this.options.scroll == window) {
with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
@@ -388,16 +388,16 @@
if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
this.startScrolling(speed);
}
-
+
// fix AppleWebKit rendering
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)];
@@ -405,24 +405,24 @@
}
if(this.options.ghosting) {
- if (!this.element._originallyAbsolute)
+ if (!this._originallyAbsolute)
Position.relativize(this.element);
- delete this.element._originallyAbsolute;
+ delete this._originallyAbsolute;
Element.remove(this._clone);
this._clone = null;
}
- var dropped = false;
- if(success) {
- dropped = Droppables.fire(event, this.element);
- if (!dropped) dropped = false;
+ 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 && Object.isFunction(revert)) revert = revert(this.element);
-
+
var d = this.currentDelta();
if(revert && this.options.reverteffect) {
if (dropped == 0 || revert != 'failure')
@@ -435,67 +435,67 @@
if(this.options.zindex)
this.element.style.zIndex = this.originalZ;
- if(this.options.endeffect)
+ if(this.options.endeffect)
this.options.endeffect(this.element);
-
+
Draggables.deactivate(this);
Droppables.reset();
},
-
+
keyPress: function(event) {
if(event.keyCode!=Event.KEY_ESC) return;
this.finishDrag(event, false);
Event.stop(event);
},
-
+
endDrag: function(event) {
if(!this.dragging) return;
this.stopScrolling();
this.finishDrag(event, true);
Event.stop(event);
},
-
+
draw: function(point) {
var pos = Position.cumulativeOffset(this.element);
if(this.options.ghosting) {
var r = Position.realOffset(this.element);
pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
}
-
+
var d = this.currentDelta();
pos[0] -= d[0]; pos[1] -= d[1];
-
+
if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
}
-
- var p = [0,1].map(function(i){
- return (point[i]-pos[i]-this.offset[i])
+
+ var p = [0,1].map(function(i){
+ return (point[i]-pos[i]-this.offset[i])
}.bind(this));
-
+
if(this.options.snap) {
if(Object.isFunction(this.options.snap)) {
p = this.options.snap(p[0],p[1],this);
} else {
if(Object.isArray(this.options.snap)) {
p = p.map( function(v, i) {
- return (v/this.options.snap[i]).round()*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 (v/this.options.snap).round()*this.options.snap }.bind(this))
+ return (v/this.options.snap).round()*this.options.snap }.bind(this));
}
}}
-
+
var style = this.element.style;
if((!this.options.constraint) || (this.options.constraint=='horizontal'))
style.left = p[0] + "px";
if((!this.options.constraint) || (this.options.constraint=='vertical'))
style.top = p[1] + "px";
-
+
if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
},
-
+
stopScrolling: function() {
if(this.scrollInterval) {
clearInterval(this.scrollInterval);
@@ -503,14 +503,14 @@
Draggables._lastScrollPointer = null;
}
},
-
+
startScrolling: function(speed) {
if(!(speed[0] || speed[1])) return;
this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
this.lastScrolled = new Date();
this.scrollInterval = setInterval(this.scroll.bind(this), 10);
},
-
+
scroll: function() {
var current = new Date();
var delta = current - this.lastScrolled;
@@ -526,7 +526,7 @@
this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
}
-
+
Position.prepare();
Droppables.show(Draggables._lastPointer, this.element);
Draggables.notify('onDrag', this);
@@ -540,10 +540,10 @@
Draggables._lastScrollPointer[1] = 0;
this.draw(Draggables._lastScrollPointer);
}
-
+
if(this.options.change) this.options.change(this);
},
-
+
_getWindowScroll: function(w) {
var T, L, W, H;
with (w.document) {
@@ -562,7 +562,7 @@
H = documentElement.clientHeight;
} else {
W = body.offsetWidth;
- H = body.offsetHeight
+ H = body.offsetHeight;
}
}
return { top: T, left: L, width: W, height: H };
@@ -579,11 +579,11 @@
this.observer = observer;
this.lastValue = Sortable.serialize(this.element);
},
-
+
onStart: function() {
this.lastValue = Sortable.serialize(this.element);
},
-
+
onEnd: function() {
Sortable.unmark();
if(this.lastValue != Sortable.serialize(this.element))
@@ -593,11 +593,11 @@
var Sortable = {
SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
-
+
sortables: { },
-
+
_findRootElement: function(element) {
- while (element.tagName.toUpperCase() != "BODY") {
+ while (element.tagName.toUpperCase() != "BODY") {
if(element.id && Sortable.sortables[element.id]) return element;
element = element.parentNode;
}
@@ -608,22 +608,23 @@
if(!element) return;
return Sortable.sortables[element.id];
},
-
+
destroy: function(element){
- var s = Sortable.options(element);
-
+ element = $(element);
+ var s = Sortable.sortables[element.id];
+
if(s) {
Draggables.removeObserver(s.element);
s.droppables.each(function(d){ Droppables.remove(d) });
s.draggables.invoke('destroy');
-
+
delete Sortable.sortables[s.element.id];
}
},
create: function(element) {
element = $(element);
- var options = Object.extend({
+ var options = Object.extend({
element: element,
tag: 'li', // assumes li children, override with tag: 'tagname'
dropOnEmpty: false,
@@ -637,17 +638,17 @@
delay: 0,
hoverclass: null,
ghosting: false,
- quiet: false,
+ quiet: false,
scroll: false,
scrollSensitivity: 20,
scrollSpeed: 15,
format: this.SERIALIZE_RULE,
-
- // these take arrays of elements or ids and can be
+
+ // 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] || { });
@@ -684,24 +685,24 @@
if(options.zindex)
options_for_draggable.zindex = options.zindex;
- // build options for the droppables
+ // build options for the droppables
var options_for_droppable = {
overlap: options.overlap,
containment: options.containment,
tree: options.tree,
hoverclass: options.hoverclass,
onHover: Sortable.onHover
- }
-
+ };
+
var options_for_tree = {
onHover: Sortable.onEmptyHover,
overlap: options.overlap,
containment: options.containment,
hoverclass: options.hoverclass
- }
+ };
// fix for gecko engine
- Element.cleanWhitespace(element);
+ Element.cleanWhitespace(element);
options.draggables = [];
options.droppables = [];
@@ -714,14 +715,14 @@
(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.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);
if(options.tree) e.treeNode = element;
- options.droppables.push(e);
+ options.droppables.push(e);
});
-
+
if(options.tree) {
(Sortable.findTreeElements(element, options) || []).each( function(e) {
Droppables.add(e, options_for_tree);
@@ -743,7 +744,7 @@
return Element.findChildren(
element, options.only, options.tree ? true : false, options.tag);
},
-
+
findTreeElements: function(element, options) {
return Element.findChildren(
element, options.only, options.tree ? true : false, options.treeTag);
@@ -760,7 +761,7 @@
var oldParentNode = element.parentNode;
element.style.visibility = "hidden"; // fix gecko rendering
dropon.parentNode.insertBefore(element, dropon);
- if(dropon.parentNode!=oldParentNode)
+ if(dropon.parentNode!=oldParentNode)
Sortable.options(oldParentNode).onChange(element);
Sortable.options(dropon.parentNode).onChange(element);
}
@@ -771,26 +772,26 @@
var oldParentNode = element.parentNode;
element.style.visibility = "hidden"; // fix gecko rendering
dropon.parentNode.insertBefore(element, nextElement);
- if(dropon.parentNode!=oldParentNode)
+ if(dropon.parentNode!=oldParentNode)
Sortable.options(oldParentNode).onChange(element);
Sortable.options(dropon.parentNode).onChange(element);
}
}
},
-
+
onEmptyHover: function(element, dropon, overlap) {
var oldParentNode = element.parentNode;
var droponOptions = Sortable.options(dropon);
-
+
if(!Element.isParent(dropon, element)) {
var index;
-
+
var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
var child = null;
-
+
if(children) {
var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
-
+
for (index = 0; index < children.length; index += 1) {
if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
offset -= Element.offsetSize (children[index], droponOptions.overlap);
@@ -803,9 +804,9 @@
}
}
}
-
+
dropon.insertBefore(element, child);
-
+
Sortable.options(oldParentNode).onChange(element);
droponOptions.onChange(element);
}
@@ -818,34 +819,34 @@
mark: function(dropon, position) {
// mark on ghosting only
var sortable = Sortable.options(dropon.parentNode);
- if(sortable && !sortable.ghosting) return;
+ if(sortable && !sortable.ghosting) return;
if(!Sortable._marker) {
- Sortable._marker =
+ Sortable._marker =
($('dropmarker') || Element.extend(document.createElement('DIV'))).
hide().addClassName('dropmarker').setStyle({position:'absolute'});
document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
- }
+ }
var offsets = Position.cumulativeOffset(dropon);
Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
-
+
if(position=='after')
- if(sortable.overlap == 'horizontal')
+ if(sortable.overlap == 'horizontal')
Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
else
Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
-
+
Sortable._marker.show();
},
-
+
_tree: function(element, options, parent) {
var children = Sortable.findElements(element, options) || [];
-
+
for (var i = 0; i < children.length; ++i) {
var match = children[i].id.match(options.format);
if (!match) continue;
-
+
var child = {
id: encodeURIComponent(match ? match[1] : null),
element: element,
@@ -853,16 +854,16 @@
children: [],
position: parent.children.length,
container: $(children[i]).down(options.treeTag)
- }
-
+ };
+
/* Get the element containing the children and recurse over it */
if (child.container)
- this._tree(child.container, options, child)
-
+ this._tree(child.container, options, child);
+
parent.children.push (child);
}
- return parent;
+ return parent;
},
tree: function(element) {
@@ -875,15 +876,15 @@
name: element.id,
format: sortableOptions.format
}, arguments[1] || { });
-
+
var root = {
id: null,
parent: null,
children: [],
container: element,
position: 0
- }
-
+ };
+
return Sortable._tree(element, options, root);
},
@@ -899,7 +900,7 @@
sequence: function(element) {
element = $(element);
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] : '';
});
@@ -908,14 +909,14 @@
setSequence: function(element, new_sequence) {
element = $(element);
var options = Object.extend(this.options(element), arguments[2] || { });
-
+
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];
n.parentNode.removeChild(n);
});
-
+
new_sequence.each(function(ident) {
var n = nodeMap[ident];
if (n) {
@@ -924,16 +925,16 @@
}
});
},
-
+
serialize: function(element) {
element = $(element);
var options = Object.extend(Sortable.options(element), arguments[1] || { });
var name = encodeURIComponent(
(arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
-
+
if (options.tree) {
return Sortable.tree(element, arguments[1]).children.map( function (item) {
- return [name + Sortable._constructIndex(item) + "[id]=" +
+ return [name + Sortable._constructIndex(item) + "[id]=" +
encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
}).flatten().join('&');
} else {
@@ -942,16 +943,16 @@
}).join('&');
}
}
-}
+};
// Returns true if child is contained within element
Element.isParent = function(child, element) {
if (!child.parentNode || child == element) return false;
if (child.parentNode == element) return true;
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();
@@ -967,8 +968,8 @@
});
return (elements.length>0 ? elements.flatten() : []);
-}
+};
Element.offsetSize = function (element, type) {
return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
-}
+};
\ No newline at end of file
Modified: branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/effects.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/effects.js 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/effects.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,50 +1,50 @@
-// script.aculo.us effects.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+// script.aculo.us effects.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
-// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
// Justin Palmer (http://encytemedia.com/)
// Mark Pilgrim (http://diveintomark.org/)
// Martin Bialasinki
-//
+//
// 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/
+// For details, see the script.aculo.us web site: http://script.aculo.us/
-// converts rgb() and #xxx to #xxxxxx format,
-// returns self (or first argument) if not convertable
-String.prototype.parseColor = function() {
+// converts rgb() and #xxx to #xxxxxx format,
+// returns self (or first argument) if not convertable
+String.prototype.parseColor = function() {
var color = '#';
- 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();
- }
- }
- return (color.length==7 ? color : (arguments[0] || this));
+ 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();
+ }
+ }
+ return (color.length==7 ? color : (arguments[0] || this));
};
/*--------------------------------------------------------------------------*/
-Element.collectTextNodes = function(element) {
+Element.collectTextNodes = function(element) {
return $A($(element).childNodes).collect( function(node) {
- return (node.nodeType==3 ? node.nodeValue :
+ return (node.nodeType==3 ? node.nodeValue :
(node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
}).flatten().join('');
};
-Element.collectTextNodesIgnoreClass = function(element, className) {
+Element.collectTextNodesIgnoreClass = function(element, className) {
return $A($(element).childNodes).collect( function(node) {
- return (node.nodeType==3 ? node.nodeValue :
- ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
+ return (node.nodeType==3 ? node.nodeValue :
+ ((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'});
+ element = $(element);
+ element.setStyle({fontSize: (percent/100) + 'em'});
if (Prototype.Browser.WebKit) window.scrollBy(0,0);
return element;
};
@@ -72,28 +72,23 @@
Transitions: {
linear: Prototype.K,
sinoidal: function(pos) {
- return (-Math.cos(pos*Math.PI)/2) + 0.5;
+ return (-Math.cos(pos*Math.PI)/2) + .5;
},
reverse: function(pos) {
return 1-pos;
},
flicker: function(pos) {
- var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+ var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4;
return pos > 1 ? 1 : pos;
},
wobble: function(pos) {
- return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + .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())
- );
+ pulse: function(pos, pulses) {
+ return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5;
},
- spring: function(pos) {
- return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
+ spring: function(pos) {
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
},
none: function(pos) {
return 0;
@@ -114,14 +109,14 @@
tagifyText: function(element) {
var tagifyStyle = 'position:relative';
if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
-
+
element = $(element);
$A(element.childNodes).each( function(child) {
if (child.nodeType==3) {
child.nodeValue.toArray().each( function(character) {
element.insertBefore(
new Element('span', {style: tagifyStyle}).update(
- character == ' ' ? String.fromCharCode(160) : character),
+ character == ' ' ? String.fromCharCode(160) : character),
child);
});
Element.remove(child);
@@ -130,13 +125,13 @@
},
multiple: function(element, effect) {
var elements;
- if (((typeof element == 'object') ||
- Object.isFunction(element)) &&
+ if (((typeof element == 'object') ||
+ Object.isFunction(element)) &&
(element.length))
elements = element;
else
elements = $(element).childNodes;
-
+
var options = Object.extend({
speed: 0.1,
delay: 0.0
@@ -158,7 +153,7 @@
var options = Object.extend({
queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
}, arguments[2] || { });
- Effect[element.visible() ?
+ Effect[element.visible() ?
Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
}
};
@@ -170,20 +165,20 @@
Effect.ScopedQueue = Class.create(Enumerable, {
initialize: function() {
this.effects = [];
- this.interval = null;
+ this.interval = null;
},
_each: function(iterator) {
this.effects._each(iterator);
},
add: function(effect) {
var timestamp = new Date().getTime();
-
- var position = Object.isString(effect.options.queue) ?
+
+ var position = Object.isString(effect.options.queue) ?
effect.options.queue : effect.options.queue.position;
-
+
switch(position) {
case 'front':
- // move unstarted effects after this effect
+ // move unstarted effects after this effect
this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
e.startOn += effect.finishOn;
e.finishOn += effect.finishOn;
@@ -197,13 +192,13 @@
timestamp = this.effects.pluck('finishOn').max() || timestamp;
break;
}
-
+
effect.startOn += timestamp;
effect.finishOn += timestamp;
if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
this.effects.push(effect);
-
+
if (!this.interval)
this.interval = setInterval(this.loop.bind(this), 15);
},
@@ -216,7 +211,7 @@
},
loop: function() {
var timePos = new Date().getTime();
- for(var i=0, len=this.effects.length;i<len;i++)
+ for(var i=0, len=this.effects.length;i<len;i++)
this.effects[i] && this.effects[i].loop(timePos);
}
});
@@ -225,7 +220,7 @@
instances: $H(),
get: function(queueName) {
if (!Object.isString(queueName)) return queueName;
-
+
return this.instances.get(queueName) ||
this.instances.set(queueName, new Effect.ScopedQueue());
}
@@ -250,23 +245,35 @@
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.render = (function() {
+ function dispatch(effect, eventName) {
+ if (effect.options[eventName + 'Internal'])
+ effect.options[eventName + 'Internal'](effect);
+ if (effect.options[eventName])
+ effect.options[eventName](effect);
+ }
+
+ return function(pos) {
+ if (this.state === "idle") {
+ this.state = "running";
+ dispatch(this, 'beforeSetup');
+ if (this.setup) this.setup();
+ dispatch(this, 'afterSetup');
+ }
+ if (this.state === "running") {
+ pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
+ this.position = pos;
+ dispatch(this, 'beforeUpdate');
+ if (this.update) this.update(pos);
+ dispatch(this, 'afterUpdate');
+ }
+ };
+ })();
+
this.event('beforeStart');
if (!this.options.sync)
- Effect.Queues.get(Object.isString(this.options.queue) ?
+ Effect.Queues.get(Object.isString(this.options.queue) ?
'global' : this.options.queue.scope).add(this);
},
loop: function(timePos) {
@@ -275,9 +282,9 @@
this.render(1.0);
this.cancel();
this.event('beforeFinish');
- if (this.finish) this.finish();
+ if (this.finish) this.finish();
this.event('afterFinish');
- return;
+ return;
}
var pos = (timePos - this.startOn) / this.totalTime,
frame = (pos * this.totalFrames).round();
@@ -289,7 +296,7 @@
},
cancel: function() {
if (!this.options.sync)
- Effect.Queues.get(Object.isString(this.options.queue) ?
+ Effect.Queues.get(Object.isString(this.options.queue) ?
'global' : this.options.queue.scope).remove(this);
this.state = 'finished';
},
@@ -327,10 +334,10 @@
Effect.Tween = Class.create(Effect.Base, {
initialize: function(object, from, to) {
object = Object.isString(object) ? $(object) : object;
- var args = $A(arguments), method = args.last(),
+ 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) :
+ Object.isFunction(object[method]) ? object[method].bind(object) :
function(value) { object[method] = value };
this.start(Object.extend({ from: from, to: to }, options || { }));
},
@@ -394,7 +401,7 @@
// for backwards compatibility
Effect.MoveBy = function(element, toTop, toLeft) {
- return new Effect.Move(element,
+ return new Effect.Move(element,
Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
};
@@ -416,15 +423,15 @@
setup: function() {
this.restoreAfterFinish = this.options.restoreAfterFinish || false;
this.elementPositioning = this.element.getStyle('position');
-
+
this.originalStyle = { };
['top','left','width','height','fontSize'].each( function(k) {
this.originalStyle[k] = this.element.style[k];
}.bind(this));
-
+
this.originalTop = this.element.offsetTop;
this.originalLeft = this.element.offsetLeft;
-
+
var fontSize = this.element.getStyle('font-size') || '100%';
['em','px','%','pt'].each( function(fontSizeType) {
if (fontSize.indexOf(fontSizeType)>0) {
@@ -432,9 +439,9 @@
this.fontSizeType = fontSizeType;
}
}.bind(this));
-
+
this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
-
+
this.dims = null;
if (this.options.scaleMode=='box')
this.dims = [this.element.offsetHeight, this.element.offsetWidth];
@@ -509,17 +516,16 @@
Effect.ScrollTo = function(element) {
var options = arguments[1] || { },
- scrollOffsets = document.viewport.getScrollOffsets(),
- elementOffsets = $(element).cumulativeOffset(),
- max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();
+ scrollOffsets = document.viewport.getScrollOffsets(),
+ elementOffsets = $(element).cumulativeOffset();
if (options.offset) elementOffsets[1] += options.offset;
return new Effect.Tween(null,
scrollOffsets.top,
- elementOffsets[1] > max ? max : elementOffsets[1],
+ elementOffsets[1],
options,
- function(p){ scrollTo(scrollOffsets.left, p.round()) }
+ function(p){ scrollTo(scrollOffsets.left, p.round()); }
);
};
@@ -531,9 +537,9 @@
var options = Object.extend({
from: element.getOpacity() || 1.0,
to: 0.0,
- afterFinishInternal: function(effect) {
+ afterFinishInternal: function(effect) {
if (effect.options.to!=0) return;
- effect.element.hide().setStyle({opacity: oldOpacity});
+ effect.element.hide().setStyle({opacity: oldOpacity});
}
}, arguments[1] || { });
return new Effect.Opacity(element,options);
@@ -549,15 +555,15 @@
effect.element.forceRerendering();
},
beforeSetup: function(effect) {
- effect.element.setOpacity(effect.options.from).show();
+ effect.element.setOpacity(effect.options.from).show();
}}, arguments[1] || { });
return new Effect.Opacity(element,options);
};
Effect.Puff = function(element) {
element = $(element);
- var oldStyle = {
- opacity: element.getInlineOpacity(),
+ var oldStyle = {
+ opacity: element.getInlineOpacity(),
position: element.getStyle('position'),
top: element.style.top,
left: element.style.left,
@@ -565,12 +571,12 @@
height: element.style.height
};
return new Effect.Parallel(
- [ new Effect.Scale(element, 200,
- { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
- new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
- Object.extend({ duration: 1.0,
+ [ new Effect.Scale(element, 200,
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
+ Object.extend({ duration: 1.0,
beforeSetupInternal: function(effect) {
- Position.absolutize(effect.effects[0].element)
+ Position.absolutize(effect.effects[0].element);
},
afterFinishInternal: function(effect) {
effect.effects[0].element.hide().setStyle(oldStyle); }
@@ -582,12 +588,12 @@
element = $(element);
element.makeClipping();
return new Effect.Scale(element, 0,
- Object.extend({ scaleContent: false,
- scaleX: false,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
restoreAfterFinish: true,
afterFinishInternal: function(effect) {
effect.element.hide().undoClipping();
- }
+ }
}, arguments[1] || { })
);
};
@@ -595,15 +601,15 @@
Effect.BlindDown = function(element) {
element = $(element);
var elementDimensions = element.getDimensions();
- return new Effect.Scale(element, 100, Object.extend({
- scaleContent: false,
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
scaleX: false,
scaleFrom: 0,
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
restoreAfterFinish: true,
afterSetup: function(effect) {
- effect.element.makeClipping().setStyle({height: '0px'}).show();
- },
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
+ },
afterFinishInternal: function(effect) {
effect.element.undoClipping();
}
@@ -618,16 +624,16 @@
from: 0,
transition: Effect.Transitions.flicker,
afterFinishInternal: function(effect) {
- new Effect.Scale(effect.element, 1, {
+ new Effect.Scale(effect.element, 1, {
duration: 0.3, scaleFromCenter: true,
scaleX: false, scaleContent: false, restoreAfterFinish: true,
- beforeSetup: function(effect) {
+ beforeSetup: function(effect) {
effect.element.makePositioned().makeClipping();
},
afterFinishInternal: function(effect) {
effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
}
- })
+ });
}
}, arguments[1] || { }));
};
@@ -639,16 +645,16 @@
left: element.getStyle('left'),
opacity: element.getInlineOpacity() };
return new Effect.Parallel(
- [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
Object.extend(
{ duration: 0.5,
beforeSetup: function(effect) {
- effect.effects[0].element.makePositioned();
+ effect.effects[0].element.makePositioned();
},
afterFinishInternal: function(effect) {
effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
- }
+ }
}, arguments[1] || { }));
};
@@ -676,7 +682,7 @@
new Effect.Move(effect.element,
{ x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
effect.element.undoPositioned().setStyle(oldStyle);
- }}) }}) }}) }}) }}) }});
+ }}); }}); }}); }}); }}); }});
};
Effect.SlideDown = function(element) {
@@ -684,9 +690,9 @@
// SlideDown need to have the content of the element wrapped in a container element with fixed height!
var oldInnerBottom = element.down().getStyle('bottom');
var elementDimensions = element.getDimensions();
- return new Effect.Scale(element, 100, Object.extend({
- scaleContent: false,
- scaleX: false,
+ return new Effect.Scale(element, 100, Object.extend({
+ scaleContent: false,
+ scaleX: false,
scaleFrom: window.opera ? 0 : 1,
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
restoreAfterFinish: true,
@@ -694,11 +700,11 @@
effect.element.makePositioned();
effect.element.down().makePositioned();
if (window.opera) effect.element.setStyle({top: ''});
- effect.element.makeClipping().setStyle({height: '0px'}).show();
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
},
afterUpdateInternal: function(effect) {
effect.element.down().setStyle({bottom:
- (effect.dims[0] - effect.element.clientHeight) + 'px' });
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
},
afterFinishInternal: function(effect) {
effect.element.undoClipping().undoPositioned();
@@ -712,8 +718,8 @@
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,
+ Object.extend({ scaleContent: false,
+ scaleX: false,
scaleMode: 'box',
scaleFrom: 100,
scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
@@ -723,7 +729,7 @@
effect.element.down().makePositioned();
if (window.opera) effect.element.setStyle({top: ''});
effect.element.makeClipping().show();
- },
+ },
afterUpdateInternal: function(effect) {
effect.element.down().setStyle({bottom:
(effect.dims[0] - effect.element.clientHeight) + 'px' });
@@ -736,15 +742,15 @@
);
};
-// Bug in opera makes the TD containing this element expand for a instance after finish
+// Bug in opera makes the TD containing this element expand for a instance after finish
Effect.Squish = function(element) {
- return new Effect.Scale(element, window.opera ? 1 : 0, {
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
restoreAfterFinish: true,
beforeSetup: function(effect) {
- effect.element.makeClipping();
- },
+ effect.element.makeClipping();
+ },
afterFinishInternal: function(effect) {
- effect.element.hide().undoClipping();
+ effect.element.hide().undoClipping();
}
});
};
@@ -764,13 +770,13 @@
width: element.style.width,
opacity: element.getInlineOpacity() };
- var dims = element.getDimensions();
+ var dims = element.getDimensions();
var initialMoveX, initialMoveY;
var moveX, moveY;
-
+
switch (options.direction) {
case 'top-left':
- initialMoveX = initialMoveY = moveX = moveY = 0;
+ initialMoveX = initialMoveY = moveX = moveY = 0;
break;
case 'top-right':
initialMoveX = dims.width;
@@ -795,11 +801,11 @@
moveY = -dims.height / 2;
break;
}
-
+
return new Effect.Move(element, {
x: initialMoveX,
y: initialMoveY,
- duration: 0.01,
+ duration: 0.01,
beforeSetup: function(effect) {
effect.element.hide().makeClipping().makePositioned();
},
@@ -808,17 +814,17 @@
[ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
new Effect.Scale(effect.element, 100, {
- scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
], Object.extend({
beforeSetup: function(effect) {
- effect.effects[0].element.setStyle({height: '0px'}).show();
+ effect.effects[0].element.setStyle({height: '0px'}).show();
},
afterFinishInternal: function(effect) {
- effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
}
}, options)
- )
+ );
}
});
};
@@ -840,7 +846,7 @@
var dims = element.getDimensions();
var moveX, moveY;
-
+
switch (options.direction) {
case 'top-left':
moveX = moveY = 0;
@@ -857,19 +863,19 @@
moveX = dims.width;
moveY = dims.height;
break;
- case 'center':
+ case 'center':
moveX = dims.width / 2;
moveY = dims.height / 2;
break;
}
-
+
return new Effect.Parallel(
[ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
- ], Object.extend({
+ ], Object.extend({
beforeStartInternal: function(effect) {
- effect.effects[0].element.makePositioned().makeClipping();
+ effect.effects[0].element.makePositioned().makeClipping();
},
afterFinishInternal: function(effect) {
effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
@@ -879,12 +885,14 @@
Effect.Pulsate = function(element) {
element = $(element);
- 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)) };
- reverser.bind(transition);
- return new Effect.Opacity(element,
+ var options = arguments[1] || { },
+ oldOpacity = element.getInlineOpacity(),
+ transition = options.transition || Effect.Transitions.linear,
+ reverser = function(pos){
+ return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5);
+ };
+
+ return new Effect.Opacity(element,
Object.extend(Object.extend({ duration: 2.0, from: 0,
afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
}, options), {transition: reverser}));
@@ -898,12 +906,12 @@
width: element.style.width,
height: element.style.height };
element.makeClipping();
- return new Effect.Scale(element, 5, Object.extend({
+ return new Effect.Scale(element, 5, Object.extend({
scaleContent: false,
scaleX: false,
afterFinishInternal: function(effect) {
- new Effect.Scale(element, 1, {
- scaleContent: false,
+ new Effect.Scale(element, 1, {
+ scaleContent: false,
scaleY: false,
afterFinishInternal: function(effect) {
effect.element.hide().undoClipping().setStyle(oldStyle);
@@ -918,7 +926,7 @@
var options = Object.extend({
style: { }
}, arguments[1] || { });
-
+
if (!Object.isString(options.style)) this.style = $H(options.style);
else {
if (options.style.include(':'))
@@ -936,18 +944,18 @@
effect.transforms.each(function(transform) {
effect.element.style[transform.style] = '';
});
- }
+ };
}
}
this.start(options);
},
-
+
setup: function(){
function parseColor(color){
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 )
+ return parseInt( color.slice(i*2+1,i*2+3), 16 );
});
}
this.transforms = this.style.map(function(pair){
@@ -967,9 +975,9 @@
}
var originalValue = this.element.getStyle(property);
- return {
- style: property.camelize(),
- originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
+ return {
+ style: property.camelize(),
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
targetValue: unit=='color' ? parseColor(value) : value,
unit: unit
};
@@ -980,13 +988,13 @@
transform.unit != 'color' &&
(isNaN(transform.originalValue) || isNaN(transform.targetValue))
)
- )
+ );
});
},
update: function(position) {
var style = { }, transform, i = this.transforms.length;
while(i--)
- style[(transform = this.transforms[i]).style] =
+ style[(transform = this.transforms[i]).style] =
transform.unit=='color' ? '#'+
(Math.round(transform.originalValue[0]+
(transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
@@ -995,7 +1003,7 @@
(Math.round(transform.originalValue[2]+
(transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
(transform.originalValue +
- (transform.targetValue - transform.originalValue) * position).toFixed(3) +
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
(transform.unit === null ? '' : transform.unit);
this.element.setStyle(style, true);
}
@@ -1032,7 +1040,7 @@
});
Element.CSS_PROPERTIES = $w(
- 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
@@ -1041,7 +1049,7 @@
'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
'right textIndent top width wordSpacing zIndex');
-
+
Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
String.__parseStyleElement = document.createElement('div');
@@ -1053,11 +1061,11 @@
String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
style = String.__parseStyleElement.childNodes[0].style;
}
-
+
Element.CSS_PROPERTIES.each(function(property){
- if (style[property]) styleRules.set(property, style[property]);
+ if (style[property]) styleRules.set(property, style[property]);
});
-
+
if (Prototype.Browser.IE && this.include('opacity'))
styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
@@ -1083,7 +1091,7 @@
if (!styles.opacity) styles.opacity = element.getOpacity();
return styles;
};
-};
+}
Effect.Methods = {
morph: function(element, style) {
@@ -1092,7 +1100,7 @@
return element;
},
visualEffect: function(element, effect, options) {
- element = $(element)
+ element = $(element);
var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
new Effect[klass](element, options);
return element;
@@ -1106,17 +1114,17 @@
$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
'pulsate shake puff squish switchOff dropOut').each(
- function(effect) {
+ function(effect) {
Effect.Methods[effect] = function(element, options){
element = $(element);
Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
return element;
- }
+ };
}
);
-$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
function(f) { Effect.Methods[f] = Element[f]; }
);
-Element.addMethods(Effect.Methods);
+Element.addMethods(Effect.Methods);
\ No newline at end of file
Modified: branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/scriptaculous.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/scriptaculous.js 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/scriptaculous.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,7 +1,7 @@
-// script.aculo.us scriptaculous.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+// script.aculo.us scriptaculous.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
-// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-//
+// Copyright (c) 2005-2008 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
// "Software"), to deal in the Software without restriction, including
@@ -9,7 +9,7 @@
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
-//
+//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
@@ -24,35 +24,37 @@
// For details, see the script.aculo.us web site: http://script.aculo.us/
var Scriptaculous = {
- Version: '1.8.1',
+ Version: '1.8.2',
require: function(libraryName) {
// inserting via DOM fails in Safari 2.0, so brute force approach
document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
},
- REQUIRED_PROTOTYPE: '1.6.0',
+ REQUIRED_PROTOTYPE: '1.6.0.3',
load: function() {
- function convertVersionString(versionString){
- var r = versionString.split('.');
- return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+ function convertVersionString(versionString) {
+ var v = versionString.replace(/_.*|\./g, '');
+ v = parseInt(v + '0'.times(4-v.length));
+ return versionString.indexOf('_') > -1 ? v-1 : v;
}
-
- if((typeof Prototype=='undefined') ||
- (typeof Element == 'undefined') ||
+
+ if((typeof Prototype=='undefined') ||
+ (typeof Element == 'undefined') ||
(typeof Element.Methods=='undefined') ||
- (convertVersionString(Prototype.Version) <
+ (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,]*)/);
+
+ var js = /scriptaculous\.js(\?.*)?$/;
+ $$('head script[src]').findAll(function(s) {
+ return s.src.match(js);
+ }).each(function(s) {
+ var path = s.src.replace(js, ''),
+ includes = s.src.match(/\?.*load=([a-z,]*)/);
(includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
function(include) { Scriptaculous.require(path+include+'.js') });
});
}
-}
+};
Scriptaculous.load();
\ No newline at end of file
Modified: branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/slider.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/slider.js 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/slider.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,6 +1,6 @@
-// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+// script.aculo.us slider.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
-// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
+// Copyright (c) 2005-2008 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/
@@ -16,13 +16,13 @@
Control.Slider = Class.create({
initialize: function(handle, track, options) {
var slider = this;
-
+
if (Object.isArray(handle)) {
this.handles = handle.collect( function(e) { return $(e) });
} else {
this.handles = [$(handle)];
}
-
+
this.track = $(track);
this.options = options || { };
@@ -30,7 +30,7 @@
this.increment = this.options.increment || 1;
this.step = parseInt(this.options.step || '1');
this.range = this.options.range || $R(0,1);
-
+
this.value = 0; // assure backwards compat
this.values = this.handles.map( function() { return 0 });
this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
@@ -45,13 +45,13 @@
// Will be used to align the handle onto the track, if necessary
this.alignX = parseInt(this.options.alignX || '0');
this.alignY = parseInt(this.options.alignY || '0');
-
+
this.trackLength = this.maximumOffset() - this.minimumOffset();
- this.handleLength = this.isVertical() ?
- (this.handles[0].offsetHeight != 0 ?
- this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
- (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
+ this.handleLength = this.isVertical() ?
+ (this.handles[0].offsetHeight != 0 ?
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
this.handles[0].style.width.replace(/px$/,""));
this.active = false;
@@ -75,20 +75,20 @@
this.handles.each( function(h,i) {
i = slider.handles.length-1-i;
slider.setValue(parseFloat(
- (Object.isArray(slider.options.sliderValue) ?
- slider.options.sliderValue[i] : slider.options.sliderValue) ||
+ (Object.isArray(slider.options.sliderValue) ?
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
slider.range.start), i);
h.makePositioned().observe("mousedown", slider.eventMouseDown);
});
-
+
this.track.observe("mousedown", this.eventMouseDown);
document.observe("mouseup", this.eventMouseUp);
document.observe("mousemove", this.eventMouseMove);
-
+
this.initialized = true;
},
dispose: function() {
- var slider = this;
+ var slider = this;
Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
Event.stopObserving(document, "mouseup", this.eventMouseUp);
Event.stopObserving(document, "mousemove", this.eventMouseMove);
@@ -101,12 +101,12 @@
},
setEnabled: function(){
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());
-
+
var offset = Math.abs(this.allowedValues[0] - value);
var newValue = this.allowedValues[0];
this.allowedValues.each( function(v) {
@@ -114,7 +114,7 @@
if (currentOffset <= offset){
newValue = v;
offset = currentOffset;
- }
+ }
});
return newValue;
}
@@ -138,28 +138,28 @@
sliderValue = this.getNearestValue(sliderValue);
this.values[handleIdx] = sliderValue;
this.value = this.values[0]; // assure backwards compat
-
- this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
+
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
this.translateToPx(sliderValue);
-
+
this.drawSpans();
if (!this.dragging || !this.event) this.updateFinished();
},
setValueBy: function(delta, handleIdx) {
- this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
handleIdx || this.activeHandleIdx || 0);
},
translateToPx: function(value) {
return Math.round(
- ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
(value - this.range.start)) + "px";
},
translateToValue: function(offset) {
- return ((offset/(this.trackLength-this.handleLength) *
+ return ((offset/(this.trackLength-this.handleLength) *
(this.range.end-this.range.start)) + this.range.start);
},
getRange: function(range) {
- var v = this.values.sortBy(Prototype.K);
+ var v = this.values.sortBy(Prototype.K);
range = range || 0;
return $R(v[range],v[range+1]);
},
@@ -167,12 +167,12 @@
return(this.isVertical() ? this.alignY : this.alignX);
},
maximumOffset: function(){
- return(this.isVertical() ?
+ return(this.isVertical() ?
(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.height.replace(/px$/,"")) - this.alignY :
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
this.track.style.width.replace(/px$/,"")) - this.alignX);
- },
+ },
isVertical: function(){
return (this.axis == 'vertical');
},
@@ -184,7 +184,7 @@
this.setSpan(this.options.startSpan,
$R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
if (this.options.endSpan)
- this.setSpan(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) {
@@ -204,14 +204,14 @@
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) {
- var offsets = Position.cumulativeOffset(this.track);
+ var offsets = Position.cumulativeOffset(this.track);
this.event = event;
- this.setValue(this.translateToValue(
+ this.setValue(this.translateToValue(
(this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
));
var offsets = Position.cumulativeOffset(this.activeHandle);
@@ -219,14 +219,14 @@
this.offsetY = (pointer[1] - offsets[1]);
} else {
// find the handle (prevents issues with Safari)
- while((this.handles.indexOf(handle) == -1) && handle.parentNode)
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
handle = handle.parentNode;
-
+
if (this.handles.indexOf(handle)!=-1) {
this.activeHandle = handle;
this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
this.updateStyles();
-
+
var offsets = Position.cumulativeOffset(this.activeHandle);
this.offsetX = (pointer[0] - offsets[0]);
this.offsetY = (pointer[1] - offsets[1]);
@@ -261,15 +261,15 @@
}
this.active = false;
this.dragging = false;
- },
+ },
finishDrag: function(event, success) {
this.active = false;
this.dragging = false;
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/jsf2.0/framework/impl/src/main/javascript/scriptaculous/sound.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/sound.js 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/sound.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,6 +1,6 @@
-// script.aculo.us sound.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+// script.aculo.us sound.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
-// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// Based on code created by Jules Gravinese (http://www.webveteran.com/)
//
@@ -23,23 +23,23 @@
var options = Object.extend({
track: 'global', url: url, replace: false
}, arguments[1] || {});
-
+
if(options.replace && this.tracks[options.track]) {
$R(0, this.tracks[options.track].id).each(function(id){
var sound = $('sound_'+options.track+'_'+id);
sound.Stop && sound.Stop();
sound.remove();
- })
+ });
this.tracks[options.track] = null;
}
-
+
if(!this.tracks[options.track])
- this.tracks[options.track] = { id: 0 }
+ this.tracks[options.track] = { id: 0 };
else
this.tracks[options.track].id++;
-
+
options.id = this.tracks[options.track].id;
- $$('body')[0].insert(
+ $$('body')[0].insert(
Prototype.Browser.IE ? new Element('bgsound',{
id: 'sound_'+options.track+'_'+options.id,
src: options.url, loop: 1, autostart: true
@@ -49,7 +49,7 @@
if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
- Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>');
else
- Sound.play = function(){}
-}
+ Sound.play = function(){};
+}
\ No newline at end of file
Modified: branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/unittest.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/unittest.js 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/main/javascript/scriptaculous/unittest.js 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,8 +1,8 @@
-// script.aculo.us unittest.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008
+// script.aculo.us unittest.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
-// 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/)
+// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
+// (c) 2005-2008 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/
@@ -32,8 +32,8 @@
this.mark.style.left = options.pointerX + "px";
this.mark.style.width = "5px";
this.mark.style.height = "5px;";
- this.mark.style.borderTop = "1px solid red;"
- this.mark.style.borderLeft = "1px solid red;"
+ this.mark.style.borderTop = "1px solid red;";
+ this.mark.style.borderLeft = "1px solid red;";
if(this.step)
alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
@@ -67,7 +67,7 @@
}
};
-var Test = {}
+var Test = {};
Test.Unit = {};
// security exception workaround
@@ -117,7 +117,7 @@
'<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
'<tbody id="loglines"></tbody>' +
'</table>';
- this.logsummary = $('logsummary')
+ this.logsummary = $('logsummary');
this.loglines = $('loglines');
},
_toHTML: function(txt) {
@@ -125,15 +125,15 @@
},
addLinksToResults: function(){
$$("tr.failed .nameCell").each( function(td){ // todo: limit to children of this.log
- td.title = "Run only this test"
+ td.title = "Run only this test";
Event.observe(td, 'click', function(){ window.location.search = "?tests=" + td.innerHTML;});
});
$$("tr.passed .nameCell").each( function(td){ // todo: limit to children of this.log
- td.title = "Run all tests"
+ td.title = "Run all tests";
Event.observe(td, 'click', function(){ window.location.search = "";});
});
}
-}
+};
Test.Unit.Runner = Class.create();
Test.Unit.Runner.prototype = {
@@ -246,7 +246,7 @@
failures + " failures, " +
errors + " errors");
}
-}
+};
Test.Unit.Assertions = Class.create();
Test.Unit.Assertions.prototype = {
@@ -331,7 +331,7 @@
catch(e) { this.error(e); }
},
assertNull: function(obj) {
- var message = arguments[1] || 'assertNull'
+ var message = arguments[1] || 'assertNull';
try { (obj==null) ? this.pass() :
this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); }
catch(e) { this.error(e); }
@@ -461,7 +461,7 @@
iterations + ' iterations in ' + (timeTaken/1000)+'s' );
return timeTaken;
}
-}
+};
Test.Unit.Testcase = Class.create();
Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), {
@@ -526,7 +526,7 @@
};
var makeAssertion = function(assertion, args, object) {
this[assertion].apply(this,(args || []).concat([object]));
- }
+ };
Test.BDDMethods = {};
$H(METHODMAP).each(function(pair) {
@@ -539,7 +539,7 @@
[Array.prototype, String.prototype, Number.prototype, Boolean.prototype].each(
function(p){ Object.extend(p, Test.BDDMethods) }
);
-}
+};
Test.context = function(name, spec, log){
Test.setupBDDExtensionMethods();
Modified: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,5 +1,22 @@
/**
- *
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.cache;
@@ -26,7 +43,7 @@
}
};
- private static final int COUNT = 2000;
+ private static final int COUNT = 500;
private static final int PASS_COUNT = 2;
@@ -39,8 +56,13 @@
try {
for (int i = 0; i < COUNT; i++) {
+ try {
threads[i] = new LRUMapCacheTestThread(cache, new Integer(new Random().nextInt(10)));
threads[i].start();
+ } catch (OutOfMemoryError e) {
+ System.out.println("Out of memory pass:"+k+" thread: "+i);
+ throw e;
+ }
}
} catch (Exception e) {
e.printStackTrace();
Modified: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/FacesConfigTest.java
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/FacesConfigTest.java 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/FacesConfigTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,5 +1,22 @@
/**
- *
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.config;
Modified: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/MockServletContext.java
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/MockServletContext.java 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/MockServletContext.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,5 +1,22 @@
/**
- *
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.config;
Modified: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/MockXmlReader.java
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/MockXmlReader.java 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/MockXmlReader.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,5 +1,22 @@
/**
- *
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.config;
Modified: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/StateHandlerTest.java
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/StateHandlerTest.java 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/StateHandlerTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,5 +1,22 @@
/**
- *
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.config;
Modified: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/WebXMLTest.java
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/WebXMLTest.java 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/WebXMLTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,5 +1,22 @@
/**
- *
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.config;
Modified: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/WebappHandlerTest.java
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/WebappHandlerTest.java 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/config/WebappHandlerTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,5 +1,22 @@
/**
- *
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.config;
Modified: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/event/EventsQueueTest.java
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/event/EventsQueueTest.java 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/event/EventsQueueTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,5 +1,22 @@
/**
- *
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.event;
Modified: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/framework/ajax/xmlfilter/nekko/HtmlCorrectionFilterTestCase.java
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/framework/ajax/xmlfilter/nekko/HtmlCorrectionFilterTestCase.java 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/framework/ajax/xmlfilter/nekko/HtmlCorrectionFilterTestCase.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,5 +1,22 @@
/**
- *
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.framework.ajax.xmlfilter.nekko;
Copied: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/io/parser/FastBufferOutputStreamTest.java (from rev 14238, trunk/framework/impl/src/test/java/org/ajax4jsf/io/parser/FastBufferOutputStreamTest.java)
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/io/parser/FastBufferOutputStreamTest.java (rev 0)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/io/parser/FastBufferOutputStreamTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -0,0 +1,82 @@
+/**
+ * License Agreement.
+ *
+ * JBoss RichFaces - Ajax4jsf Component Library
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.ajax4jsf.io.parser;
+
+import junit.framework.TestCase;
+
+import org.ajax4jsf.io.ByteBuffer;
+import org.ajax4jsf.io.FastBufferOutputStream;
+
+/**
+ * @author Nick Belaevski
+ * @since 3.3.0
+ */
+
+public class FastBufferOutputStreamTest extends TestCase {
+
+ /**
+ * Test method for {@link org.ajax4jsf.io.FastBufferOutputStream#reset()}.
+ */
+ public void testResetOneBuffer() throws Exception {
+ FastBufferOutputStream stream = new FastBufferOutputStream(256);
+ for (int i = 0; i < 255; i++) {
+ stream.write(i);
+ }
+
+ assertEquals(255, stream.getLength());
+ ByteBuffer firstBuffer = stream.getFirstBuffer();
+ assertNull(firstBuffer.getNext());
+ assertNull(firstBuffer.getPrevious());
+
+ stream.reset();
+
+ assertEquals(0, stream.getLength());
+ firstBuffer = stream.getFirstBuffer();
+ assertEquals(0, firstBuffer.getUsedSize());
+ assertNull(firstBuffer.getNext());
+ assertNull(firstBuffer.getPrevious());
+ }
+
+ /**
+ * Test method for {@link org.ajax4jsf.io.FastBufferOutputStream#reset()}.
+ */
+ public void testResetTwoBuffers() throws Exception {
+ FastBufferOutputStream stream = new FastBufferOutputStream(256);
+ for (int i = 0; i < 257; i++) {
+ stream.write(i);
+ }
+
+ assertEquals(257, stream.getLength());
+ ByteBuffer firstBuffer = stream.getFirstBuffer();
+ assertNotNull(firstBuffer.getNext());
+ assertNull(firstBuffer.getPrevious());
+
+ stream.reset();
+
+ assertEquals(0, stream.getLength());
+ firstBuffer = stream.getFirstBuffer();
+ assertEquals(0, firstBuffer.getUsedSize());
+ assertNull(firstBuffer.getNext());
+ assertNull(firstBuffer.getPrevious());
+ }
+
+}
Copied: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/io/parser/FastBufferWriterTest.java (from rev 14238, trunk/framework/impl/src/test/java/org/ajax4jsf/io/parser/FastBufferWriterTest.java)
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/io/parser/FastBufferWriterTest.java (rev 0)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/io/parser/FastBufferWriterTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -0,0 +1,82 @@
+/**
+ * License Agreement.
+ *
+ * JBoss RichFaces - Ajax4jsf Component Library
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.ajax4jsf.io.parser;
+
+import junit.framework.TestCase;
+
+import org.ajax4jsf.io.CharBuffer;
+import org.ajax4jsf.io.FastBufferWriter;
+
+/**
+ * @author Nick Belaevski
+ * @since 3.3.0
+ */
+
+public class FastBufferWriterTest extends TestCase {
+
+ /**
+ * Test method for {@link org.ajax4jsf.io.FastBufferWriter#reset()}.
+ */
+ public void testResetOneBuffer() throws Exception {
+ FastBufferWriter stream = new FastBufferWriter(256);
+ for (int i = 0; i < 255; i++) {
+ stream.write(i);
+ }
+
+ assertEquals(255, stream.getLength());
+ CharBuffer firstBuffer = stream.getFirstBuffer();
+ assertNull(firstBuffer.getNext());
+ assertNull(firstBuffer.getPrevious());
+
+ stream.reset();
+
+ assertEquals(0, stream.getLength());
+ firstBuffer = stream.getFirstBuffer();
+ assertEquals(0, firstBuffer.getUsedSize());
+ assertNull(firstBuffer.getNext());
+ assertNull(firstBuffer.getPrevious());
+ }
+
+ /**
+ * Test method for {@link org.ajax4jsf.io.FastBufferWriter#reset()}.
+ */
+ public void testResetTwoBuffers() throws Exception {
+ FastBufferWriter stream = new FastBufferWriter(256);
+ for (int i = 0; i < 257; i++) {
+ stream.write(i);
+ }
+
+ assertEquals(257, stream.getLength());
+ CharBuffer firstBuffer = stream.getFirstBuffer();
+ assertNotNull(firstBuffer.getNext());
+ assertNull(firstBuffer.getPrevious());
+
+ stream.reset();
+
+ assertEquals(0, stream.getLength());
+ firstBuffer = stream.getFirstBuffer();
+ assertEquals(0, firstBuffer.getUsedSize());
+ assertNull(firstBuffer.getNext());
+ assertNull(firstBuffer.getPrevious());
+ }
+
+}
Modified: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/io/parser/FastParserTest.java
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/io/parser/FastParserTest.java 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/io/parser/FastParserTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -25,10 +25,13 @@
import java.io.StringReader;
import java.io.StringWriter;
+import javax.xml.parsers.DocumentBuilderFactory;
+
import junit.framework.TestCase;
-import org.ajax4jsf.context.SAXEndElementEvent;
-import org.ajax4jsf.context.SAXStartElementEvent;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
public class FastParserTest extends TestCase {
@@ -36,7 +39,7 @@
/*
* Test method for 'org.ajax4jsf.io.parser.FastHtmlParser.parse(Reader, Writer)'
*/
- public void testParse() {
+ public void testParse() throws Exception {
String toParse="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" +
@@ -58,7 +61,7 @@
assertTrue(indexOf3>indexOf2);
}
- public void testParseWithHead() {
+ public void testParseWithHead() throws Exception {
String toParse="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" +
@@ -73,7 +76,7 @@
assertTrue(resultString.indexOf("</head>")==resultString.lastIndexOf("</head>"));
}
- public void testParseWithHeadTitle() {
+ public void testParseWithHeadTitle() throws Exception {
String toParse="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" +
@@ -95,7 +98,7 @@
assertTrue(resultString.indexOf("</head>")>resultString.lastIndexOf("<link"));
}
- public void testParseWithHeadTitleMeta() {
+ public void testParseWithHeadTitleMeta() throws Exception {
String toParse="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" +
@@ -118,22 +121,27 @@
assertTrue(resultString.indexOf("<meta")>resultString.lastIndexOf("</script"));
assertTrue(resultString.indexOf("<meta")>resultString.lastIndexOf("<link"));
}
-
+
/**
* @param toParse
* @return
*/
- private String parseString(String toParse) {
+ private String parseString(String toParse) throws Exception {
FastHtmlParser parser = new FastHtmlParser();
StringReader in = new StringReader(toParse);
StringWriter out = new StringWriter();
- Object[] headEvents = new Object[] {
- new SAXStartElementEvent("script", "src=/some/script.js"),
- new SAXEndElementEvent("script"),
- new SAXStartElementEvent("link", "href=/some/script.js"),
- new SAXEndElementEvent("link")
- };
- parser.setHeadEvents(headEvents);
+ Document document = DocumentBuilderFactory.newInstance().
+ newDocumentBuilder().newDocument();
+
+ Element scriptNode = document.createElement("script");
+ scriptNode.setAttribute("src", "/some/script.js");
+
+ Element linkNode = document.createElement("link");
+ linkNode.setAttribute("href", "/some/script.css");
+
+ parser.setHeadNodes(new Node[] {
+ scriptNode, linkNode
+ });
try {
parser.parse(in,out);
} catch (IOException e) {
Modified: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/javascript/JSMinTest.java
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/javascript/JSMinTest.java 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/javascript/JSMinTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,5 +1,22 @@
/**
- *
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.javascript;
Copied: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/renderkit (from rev 14799, branches/community/3.3.X/framework/impl/src/test/java/org/ajax4jsf/renderkit)
Deleted: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/renderkit/RendererUtilsTest.java
===================================================================
--- branches/community/3.3.X/framework/impl/src/test/java/org/ajax4jsf/renderkit/RendererUtilsTest.java 2009-07-06 18:29:23 UTC (rev 14799)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/renderkit/RendererUtilsTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,166 +0,0 @@
-/**
- * License Agreement.
- *
- * Rich Faces - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-package org.ajax4jsf.renderkit;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.ajax4jsf.javascript.JSFunctionDefinition;
-import org.ajax4jsf.renderkit.RendererUtils.ScriptHashVariableWrapper;
-
-import junit.framework.TestCase;
-
-/**
- * @author Nick Belaevski
- * @since 3.3.2
- */
-public class RendererUtilsTest extends TestCase {
-
- public void testIsEmpty() throws Exception {
- RendererUtils utils = RendererUtils.getInstance();
-
- assertTrue(utils.isEmpty(null));
- assertFalse(utils.isEmpty(new Object()));
- assertFalse(utils.isEmpty(Boolean.FALSE));
- assertFalse(utils.isEmpty(Long.valueOf(0)));
- assertFalse(utils.isEmpty(Integer.valueOf(0)));
- assertFalse(utils.isEmpty(Short.valueOf((short) 0)));
- assertFalse(utils.isEmpty(Byte.valueOf((byte) 0)));
-
- assertTrue(utils.isEmpty(""));
- assertFalse(utils.isEmpty("s"));
-
- assertTrue(utils.isEmpty(new ArrayList<Object>()));
- assertTrue(utils.isEmpty(Collections.EMPTY_LIST));
-
- List<Object> testList = new ArrayList<Object>();
- testList.add("x");
- assertFalse(utils.isEmpty(testList));
-
- assertTrue(utils.isEmpty(new HashMap<String, Object>()));
- assertTrue(utils.isEmpty(Collections.EMPTY_MAP));
-
- Map<String, Object> testMap = new HashMap<String, Object>();
- testMap.put("x", "y");
- assertFalse(utils.isEmpty(testMap));
-
- assertTrue(utils.isEmpty(new Object[0]));
- assertTrue(utils.isEmpty(new int[0]));
-
- assertFalse(utils.isEmpty(new Object[1]));
- assertFalse(utils.isEmpty(new int[1]));
- }
-
- public void testScriptHashVariableWrapper() throws Exception {
- assertEquals("abc", RendererUtils.ScriptHashVariableWrapper.DEFAULT.wrap("abc"));
-
- Object eventHandler = RendererUtils.ScriptHashVariableWrapper.EVENT_HANDLER.wrap("abc");
- assertTrue(eventHandler instanceof JSFunctionDefinition);
-
- JSFunctionDefinition handlerFunction = (JSFunctionDefinition) eventHandler;
- assertEquals("function(event){abc}", handlerFunction.toScript().replaceAll("\\s", ""));
- }
-
- public void testAddToScriptHash() throws Exception {
- Map<String,Object> hash = new HashMap<String, Object>();
- RendererUtils utils = RendererUtils.getInstance();
-
- utils.addToScriptHash(hash, "x", "y", null, null);
- assertEquals("y", hash.get("x"));
-
- utils.addToScriptHash(hash, "y", "", null, null);
- assertNull(hash.get("y"));
- assertFalse(hash.containsKey("y"));
-
- utils.addToScriptHash(hash, "y1", null, null, null);
- assertNull(hash.get("y1"));
- assertFalse(hash.containsKey("y1"));
-
- utils.addToScriptHash(hash, "st", "server", "", null);
- assertEquals("server", hash.get("st"));
-
- utils.addToScriptHash(hash, "st1", "ajax", "ajax", null);
- assertNull(hash.get("st1"));
- assertFalse(hash.containsKey("st1"));
-
- utils.addToScriptHash(hash, "st2", "", "ajax", null);
- assertNull(hash.get("st2"));
- assertFalse(hash.containsKey("st2"));
-
- utils.addToScriptHash(hash, "null", null, "server", null);
- assertNull(hash.get("null"));
- assertFalse(hash.containsKey("null"));
-
- utils.addToScriptHash(hash, "b", false, null, null);
- assertNull(hash.get("b"));
- assertFalse(hash.containsKey("b"));
-
- utils.addToScriptHash(hash, "b1", true, null, null);
- assertEquals(Boolean.TRUE, hash.get("b1"));
-
- utils.addToScriptHash(hash, "b2", true, "true", null);
- assertNull(hash.get("b2"));
- assertFalse(hash.containsKey("b2"));
-
- utils.addToScriptHash(hash, "b3", false, "true", null);
- assertEquals(Boolean.FALSE, hash.get("b3"));
-
- utils.addToScriptHash(hash, "b4", true, "false", null);
- assertEquals(Boolean.TRUE, hash.get("b4"));
-
- utils.addToScriptHash(hash, "b5", false, "false", null);
- assertNull(hash.get("b5"));
- assertFalse(hash.containsKey("b5"));
-
- utils.addToScriptHash(hash, "i", Integer.valueOf(0), null, null);
- assertEquals(Integer.valueOf(0), hash.get("i"));
-
- utils.addToScriptHash(hash, "i1", Integer.valueOf(0), "0", null);
- assertNull(hash.get("i1"));
- assertFalse(hash.containsKey("i1"));
-
- utils.addToScriptHash(hash, "i2", Integer.valueOf(0), "1", null);
- assertEquals(Integer.valueOf(0), hash.get("i2"));
-
- utils.addToScriptHash(hash, "i3", Integer.MIN_VALUE, null, null);
- assertNull(hash.get("i3"));
- assertFalse(hash.containsKey("i3"));
-
- utils.addToScriptHash(hash, "i4", Integer.MIN_VALUE, "0", null);
- assertNull(hash.get("i4"));
- assertFalse(hash.containsKey("i4"));
-
- utils.addToScriptHash(hash, "plain", "test", null, ScriptHashVariableWrapper.DEFAULT);
- assertEquals("test", hash.get("plain"));
-
- utils.addToScriptHash(hash, "plain1", "newtest", "blank", ScriptHashVariableWrapper.DEFAULT);
- assertEquals("newtest", hash.get("plain1"));
-
- utils.addToScriptHash(hash, "onclick", "alert(1)", null, ScriptHashVariableWrapper.EVENT_HANDLER);
- assertTrue(hash.get("onclick") instanceof JSFunctionDefinition);
-
- utils.addToScriptHash(hash, "onclick1", "alert(1)", "no-val", ScriptHashVariableWrapper.EVENT_HANDLER);
- assertTrue(hash.get("onclick1") instanceof JSFunctionDefinition);
- }
-}
Copied: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/renderkit/RendererUtilsTest.java (from rev 14799, branches/community/3.3.X/framework/impl/src/test/java/org/ajax4jsf/renderkit/RendererUtilsTest.java)
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/renderkit/RendererUtilsTest.java (rev 0)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/renderkit/RendererUtilsTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -0,0 +1,166 @@
+/**
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package org.ajax4jsf.renderkit;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.ajax4jsf.javascript.JSFunctionDefinition;
+import org.ajax4jsf.renderkit.RendererUtils.ScriptHashVariableWrapper;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Nick Belaevski
+ * @since 3.3.2
+ */
+public class RendererUtilsTest extends TestCase {
+
+ public void testIsEmpty() throws Exception {
+ RendererUtils utils = RendererUtils.getInstance();
+
+ assertTrue(utils.isEmpty(null));
+ assertFalse(utils.isEmpty(new Object()));
+ assertFalse(utils.isEmpty(Boolean.FALSE));
+ assertFalse(utils.isEmpty(Long.valueOf(0)));
+ assertFalse(utils.isEmpty(Integer.valueOf(0)));
+ assertFalse(utils.isEmpty(Short.valueOf((short) 0)));
+ assertFalse(utils.isEmpty(Byte.valueOf((byte) 0)));
+
+ assertTrue(utils.isEmpty(""));
+ assertFalse(utils.isEmpty("s"));
+
+ assertTrue(utils.isEmpty(new ArrayList<Object>()));
+ assertTrue(utils.isEmpty(Collections.EMPTY_LIST));
+
+ List<Object> testList = new ArrayList<Object>();
+ testList.add("x");
+ assertFalse(utils.isEmpty(testList));
+
+ assertTrue(utils.isEmpty(new HashMap<String, Object>()));
+ assertTrue(utils.isEmpty(Collections.EMPTY_MAP));
+
+ Map<String, Object> testMap = new HashMap<String, Object>();
+ testMap.put("x", "y");
+ assertFalse(utils.isEmpty(testMap));
+
+ assertTrue(utils.isEmpty(new Object[0]));
+ assertTrue(utils.isEmpty(new int[0]));
+
+ assertFalse(utils.isEmpty(new Object[1]));
+ assertFalse(utils.isEmpty(new int[1]));
+ }
+
+ public void testScriptHashVariableWrapper() throws Exception {
+ assertEquals("abc", RendererUtils.ScriptHashVariableWrapper.DEFAULT.wrap("abc"));
+
+ Object eventHandler = RendererUtils.ScriptHashVariableWrapper.EVENT_HANDLER.wrap("abc");
+ assertTrue(eventHandler instanceof JSFunctionDefinition);
+
+ JSFunctionDefinition handlerFunction = (JSFunctionDefinition) eventHandler;
+ assertEquals("function(event){abc}", handlerFunction.toScript().replaceAll("\\s", ""));
+ }
+
+ public void testAddToScriptHash() throws Exception {
+ Map<String,Object> hash = new HashMap<String, Object>();
+ RendererUtils utils = RendererUtils.getInstance();
+
+ utils.addToScriptHash(hash, "x", "y", null, null);
+ assertEquals("y", hash.get("x"));
+
+ utils.addToScriptHash(hash, "y", "", null, null);
+ assertNull(hash.get("y"));
+ assertFalse(hash.containsKey("y"));
+
+ utils.addToScriptHash(hash, "y1", null, null, null);
+ assertNull(hash.get("y1"));
+ assertFalse(hash.containsKey("y1"));
+
+ utils.addToScriptHash(hash, "st", "server", "", null);
+ assertEquals("server", hash.get("st"));
+
+ utils.addToScriptHash(hash, "st1", "ajax", "ajax", null);
+ assertNull(hash.get("st1"));
+ assertFalse(hash.containsKey("st1"));
+
+ utils.addToScriptHash(hash, "st2", "", "ajax", null);
+ assertNull(hash.get("st2"));
+ assertFalse(hash.containsKey("st2"));
+
+ utils.addToScriptHash(hash, "null", null, "server", null);
+ assertNull(hash.get("null"));
+ assertFalse(hash.containsKey("null"));
+
+ utils.addToScriptHash(hash, "b", false, null, null);
+ assertNull(hash.get("b"));
+ assertFalse(hash.containsKey("b"));
+
+ utils.addToScriptHash(hash, "b1", true, null, null);
+ assertEquals(Boolean.TRUE, hash.get("b1"));
+
+ utils.addToScriptHash(hash, "b2", true, "true", null);
+ assertNull(hash.get("b2"));
+ assertFalse(hash.containsKey("b2"));
+
+ utils.addToScriptHash(hash, "b3", false, "true", null);
+ assertEquals(Boolean.FALSE, hash.get("b3"));
+
+ utils.addToScriptHash(hash, "b4", true, "false", null);
+ assertEquals(Boolean.TRUE, hash.get("b4"));
+
+ utils.addToScriptHash(hash, "b5", false, "false", null);
+ assertNull(hash.get("b5"));
+ assertFalse(hash.containsKey("b5"));
+
+ utils.addToScriptHash(hash, "i", Integer.valueOf(0), null, null);
+ assertEquals(Integer.valueOf(0), hash.get("i"));
+
+ utils.addToScriptHash(hash, "i1", Integer.valueOf(0), "0", null);
+ assertNull(hash.get("i1"));
+ assertFalse(hash.containsKey("i1"));
+
+ utils.addToScriptHash(hash, "i2", Integer.valueOf(0), "1", null);
+ assertEquals(Integer.valueOf(0), hash.get("i2"));
+
+ utils.addToScriptHash(hash, "i3", Integer.MIN_VALUE, null, null);
+ assertNull(hash.get("i3"));
+ assertFalse(hash.containsKey("i3"));
+
+ utils.addToScriptHash(hash, "i4", Integer.MIN_VALUE, "0", null);
+ assertNull(hash.get("i4"));
+ assertFalse(hash.containsKey("i4"));
+
+ utils.addToScriptHash(hash, "plain", "test", null, ScriptHashVariableWrapper.DEFAULT);
+ assertEquals("test", hash.get("plain"));
+
+ utils.addToScriptHash(hash, "plain1", "newtest", "blank", ScriptHashVariableWrapper.DEFAULT);
+ assertEquals("newtest", hash.get("plain1"));
+
+ utils.addToScriptHash(hash, "onclick", "alert(1)", null, ScriptHashVariableWrapper.EVENT_HANDLER);
+ assertTrue(hash.get("onclick") instanceof JSFunctionDefinition);
+
+ utils.addToScriptHash(hash, "onclick1", "alert(1)", "no-val", ScriptHashVariableWrapper.EVENT_HANDLER);
+ assertTrue(hash.get("onclick1") instanceof JSFunctionDefinition);
+ }
+}
Copied: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/resource (from rev 14238, trunk/framework/impl/src/test/java/org/ajax4jsf/resource)
Copied: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/resource/cached (from rev 14238, trunk/framework/impl/src/test/java/org/ajax4jsf/resource/cached)
Deleted: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/resource/cached/DualLRUMapTest.java
===================================================================
--- trunk/framework/impl/src/test/java/org/ajax4jsf/resource/cached/DualLRUMapTest.java 2009-05-18 14:55:17 UTC (rev 14238)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/resource/cached/DualLRUMapTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,78 +0,0 @@
-/**
- * License Agreement.
- *
- * JBoss RichFaces - Ajax4jsf Component Library
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.ajax4jsf.resource.cached;
-
-import junit.framework.TestCase;
-
-/**
- * @author Nick Belaevski
- * @since 3.3.0
- */
-
-public class DualLRUMapTest extends TestCase {
-
- public void testBasic() throws Exception {
- DualLRUMap<String, String> map = new DualLRUMap<String, String>(16);
-
- map.put("1", "a");
- map.put("2", "b");
- map.put("3", "c");
-
- assertEquals("a", map.get("1"));
- assertEquals("b", map.get("2"));
- assertEquals("c", map.get("3"));
-
- assertEquals("1", map.getKey("a"));
- assertEquals("2", map.getKey("b"));
- assertEquals("3", map.getKey("c"));
-
- assertTrue(map.containsKey("1"));
- assertTrue(map.containsValue("a"));
- assertTrue(map.containsKey("2"));
- assertTrue(map.containsValue("b"));
- assertTrue(map.containsKey("3"));
- assertTrue(map.containsValue("c"));
-
- map.remove("2");
- assertNull(map.get("2"));
- assertNull(map.getKey("b"));
-
- assertFalse(map.containsKey("2"));
- assertFalse(map.containsValue("b"));
- }
-
- public void testRemoveEldest() throws Exception {
- DualLRUMap<String,String> map = new DualLRUMap<String, String>(2);
-
- map.put("1", "a");
- map.put("2", "b");
-
- assertNotNull(map.get("2"));
- assertNotNull(map.get("1"));
-
- map.put("3", "c");
-
- assertNull(map.get("2"));
- assertNull(map.getKey("b"));
- }
-
-}
Copied: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/resource/cached/DualLRUMapTest.java (from rev 14238, trunk/framework/impl/src/test/java/org/ajax4jsf/resource/cached/DualLRUMapTest.java)
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/resource/cached/DualLRUMapTest.java (rev 0)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/resource/cached/DualLRUMapTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -0,0 +1,78 @@
+/**
+ * License Agreement.
+ *
+ * JBoss RichFaces - Ajax4jsf Component Library
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.ajax4jsf.resource.cached;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Nick Belaevski
+ * @since 3.3.0
+ */
+
+public class DualLRUMapTest extends TestCase {
+
+ public void testBasic() throws Exception {
+ DualLRUMap<String, String> map = new DualLRUMap<String, String>(16);
+
+ map.put("1", "a");
+ map.put("2", "b");
+ map.put("3", "c");
+
+ assertEquals("a", map.get("1"));
+ assertEquals("b", map.get("2"));
+ assertEquals("c", map.get("3"));
+
+ assertEquals("1", map.getKey("a"));
+ assertEquals("2", map.getKey("b"));
+ assertEquals("3", map.getKey("c"));
+
+ assertTrue(map.containsKey("1"));
+ assertTrue(map.containsValue("a"));
+ assertTrue(map.containsKey("2"));
+ assertTrue(map.containsValue("b"));
+ assertTrue(map.containsKey("3"));
+ assertTrue(map.containsValue("c"));
+
+ map.remove("2");
+ assertNull(map.get("2"));
+ assertNull(map.getKey("b"));
+
+ assertFalse(map.containsKey("2"));
+ assertFalse(map.containsValue("b"));
+ }
+
+ public void testRemoveEldest() throws Exception {
+ DualLRUMap<String,String> map = new DualLRUMap<String, String>(2);
+
+ map.put("1", "a");
+ map.put("2", "b");
+
+ assertNotNull(map.get("2"));
+ assertNotNull(map.get("1"));
+
+ map.put("3", "c");
+
+ assertNull(map.get("2"));
+ assertNull(map.getKey("b"));
+ }
+
+}
Modified: branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/util/LRUMapTest.java
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/util/LRUMapTest.java 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/test/java/org/ajax4jsf/util/LRUMapTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,5 +1,22 @@
/**
- *
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.util;
Modified: branches/jsf2.0/framework/impl/src/test/java/org/richfaces/component/util/ComponentUtilTest.java
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/richfaces/component/util/ComponentUtilTest.java 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/test/java/org/richfaces/component/util/ComponentUtilTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,3 +1,23 @@
+/**
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
package org.richfaces.component.util;
import java.util.ArrayList;
Copied: branches/jsf2.0/framework/impl/src/test/java/org/richfaces/json (from rev 14238, trunk/framework/impl/src/test/java/org/richfaces/json)
Deleted: branches/jsf2.0/framework/impl/src/test/java/org/richfaces/json/SerializationTest.java
===================================================================
--- trunk/framework/impl/src/test/java/org/richfaces/json/SerializationTest.java 2009-05-18 14:55:17 UTC (rev 14238)
+++ branches/jsf2.0/framework/impl/src/test/java/org/richfaces/json/SerializationTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -1,111 +0,0 @@
-/**
- * License Agreement.
- *
- * JBoss RichFaces - Ajax4jsf Component Library
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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 library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.richfaces.json;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.util.Iterator;
-
-import junit.framework.TestCase;
-
-/**
- * @author Nick Belaevski
- * @since 3.3.0
- */
-
-public class SerializationTest extends TestCase {
-
- private <T> T saveRestore(T t) throws IOException, ClassNotFoundException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(baos);
- oos.writeObject(t);
- oos.close();
-
- ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
- T restoredT = (T) t.getClass().cast(ois.readObject());
-
- return restoredT;
- }
-
- public void testJSONObject() throws Exception {
- JSONObject restoredObject = saveRestore(
- new JSONObject("{a:null, b:'abc', c: {d: 'e', f: 'g'}, h: ['i', 'j']}"));
-
- assertSame(JSONObject.NULL, restoredObject.get("a"));
- assertEquals("abc", restoredObject.get("b"));
-
- JSONObject nestedObject = (JSONObject) restoredObject.get("c");
- assertEquals("e", nestedObject.get("d"));
- assertEquals("g", nestedObject.get("f"));
-
- JSONArray array = (JSONArray) restoredObject.get("h");
- assertEquals(2, array.length());
- assertEquals("i", array.get(0));
- assertEquals("j", array.get(1));
-
- }
-
- public void testJSONCollection() throws Exception {
- JSONCollection restored = saveRestore(new JSONCollection("[1, '2', null, [3, 4], {a: 'b', c: 'd'}]"));
- Iterator iterator = restored.iterator();
-
- assertEquals(Integer.valueOf(1), iterator.next());
- assertEquals("2", iterator.next());
- assertSame(JSONObject.NULL, iterator.next());
-
- JSONCollection nestedCollection = (JSONCollection) iterator.next();
- Iterator nestedIterator = nestedCollection.iterator();
- assertEquals(Integer.valueOf(3), nestedIterator.next());
- assertEquals(Integer.valueOf(4), nestedIterator.next());
- assertFalse(nestedIterator.hasNext());
-
- JSONMap nestedMap = (JSONMap) iterator.next();
- assertEquals("b", nestedMap.get("a"));
- assertEquals("d", nestedMap.get("c"));
- assertEquals(2, nestedMap.size());
-
- assertFalse(iterator.hasNext());
- }
-
- public void testJSONMap() throws Exception {
- JSONMap restored = saveRestore(new JSONMap("{a: 'b', c: 3, d: null, e: [5, 'v'], f: {x: 'y', z: 2}}"));
- assertEquals("b", restored.get("a"));
- assertEquals(Integer.valueOf(3), restored.get("c"));
- assertSame(JSONObject.NULL, restored.get("d"));
-
- JSONCollection nestedCollection = (JSONCollection) restored.get("e");
- Iterator nestedIterator = nestedCollection.iterator();
- assertEquals(Integer.valueOf(5), nestedIterator.next());
- assertEquals("v", nestedIterator.next());
- assertFalse(nestedIterator.hasNext());
-
- JSONMap nestedObject = (JSONMap) restored.get("f");
- assertEquals("y", nestedObject.get("x"));
- assertEquals(Integer.valueOf(2), nestedObject.get("z"));
- assertEquals(2, nestedObject.size());
-
- assertEquals(5, restored.size());
- }
-}
Copied: branches/jsf2.0/framework/impl/src/test/java/org/richfaces/json/SerializationTest.java (from rev 14238, trunk/framework/impl/src/test/java/org/richfaces/json/SerializationTest.java)
===================================================================
--- branches/jsf2.0/framework/impl/src/test/java/org/richfaces/json/SerializationTest.java (rev 0)
+++ branches/jsf2.0/framework/impl/src/test/java/org/richfaces/json/SerializationTest.java 2009-07-07 18:11:35 UTC (rev 14817)
@@ -0,0 +1,111 @@
+/**
+ * License Agreement.
+ *
+ * JBoss RichFaces - Ajax4jsf Component Library
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.richfaces.json;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Iterator;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Nick Belaevski
+ * @since 3.3.0
+ */
+
+public class SerializationTest extends TestCase {
+
+ private <T> T saveRestore(T t) throws IOException, ClassNotFoundException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(t);
+ oos.close();
+
+ ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
+ T restoredT = (T) t.getClass().cast(ois.readObject());
+
+ return restoredT;
+ }
+
+ public void testJSONObject() throws Exception {
+ JSONObject restoredObject = saveRestore(
+ new JSONObject("{a:null, b:'abc', c: {d: 'e', f: 'g'}, h: ['i', 'j']}"));
+
+ assertSame(JSONObject.NULL, restoredObject.get("a"));
+ assertEquals("abc", restoredObject.get("b"));
+
+ JSONObject nestedObject = (JSONObject) restoredObject.get("c");
+ assertEquals("e", nestedObject.get("d"));
+ assertEquals("g", nestedObject.get("f"));
+
+ JSONArray array = (JSONArray) restoredObject.get("h");
+ assertEquals(2, array.length());
+ assertEquals("i", array.get(0));
+ assertEquals("j", array.get(1));
+
+ }
+
+ public void testJSONCollection() throws Exception {
+ JSONCollection restored = saveRestore(new JSONCollection("[1, '2', null, [3, 4], {a: 'b', c: 'd'}]"));
+ Iterator iterator = restored.iterator();
+
+ assertEquals(Integer.valueOf(1), iterator.next());
+ assertEquals("2", iterator.next());
+ assertSame(JSONObject.NULL, iterator.next());
+
+ JSONCollection nestedCollection = (JSONCollection) iterator.next();
+ Iterator nestedIterator = nestedCollection.iterator();
+ assertEquals(Integer.valueOf(3), nestedIterator.next());
+ assertEquals(Integer.valueOf(4), nestedIterator.next());
+ assertFalse(nestedIterator.hasNext());
+
+ JSONMap nestedMap = (JSONMap) iterator.next();
+ assertEquals("b", nestedMap.get("a"));
+ assertEquals("d", nestedMap.get("c"));
+ assertEquals(2, nestedMap.size());
+
+ assertFalse(iterator.hasNext());
+ }
+
+ public void testJSONMap() throws Exception {
+ JSONMap restored = saveRestore(new JSONMap("{a: 'b', c: 3, d: null, e: [5, 'v'], f: {x: 'y', z: 2}}"));
+ assertEquals("b", restored.get("a"));
+ assertEquals(Integer.valueOf(3), restored.get("c"));
+ assertSame(JSONObject.NULL, restored.get("d"));
+
+ JSONCollection nestedCollection = (JSONCollection) restored.get("e");
+ Iterator nestedIterator = nestedCollection.iterator();
+ assertEquals(Integer.valueOf(5), nestedIterator.next());
+ assertEquals("v", nestedIterator.next());
+ assertFalse(nestedIterator.hasNext());
+
+ JSONMap nestedObject = (JSONMap) restored.get("f");
+ assertEquals("y", nestedObject.get("x"));
+ assertEquals(Integer.valueOf(2), nestedObject.get("z"));
+ assertEquals(2, nestedObject.size());
+
+ assertEquals(5, restored.size());
+ }
+}
Modified: branches/jsf2.0/framework/impl/src/test/resources/WEB-INF/web.xml
===================================================================
--- branches/jsf2.0/framework/impl/src/test/resources/WEB-INF/web.xml 2009-07-07 17:31:52 UTC (rev 14816)
+++ branches/jsf2.0/framework/impl/src/test/resources/WEB-INF/web.xml 2009-07-07 18:11:35 UTC (rev 14817)
@@ -15,7 +15,53 @@
<filter>
<filter-name>foo</filter-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
- </filter>
+ </filter>
+ <filter>
+ <description>Convert HTML to XML</description>
+ <display-name>Filter</display-name>
+ <filter-name>A4J</filter-name>
+ <filter-class>org.ajax4jsf.Filter</filter-class>
+ <init-param>
+ <param-name>publicid</param-name>
+ <param-value>-//W3C//DTD XHTML 1.0 Transitional//EN</param-value>
+ </init-param>
+ <init-param>
+ <param-name>systemid</param-name>
+ <param-value>http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd</param-value>
+ </init-param>
+ <init-param>
+ <param-name>namespace</param-name>
+ <param-value>http://www.w3.org/1999/xhtml</param-value>
+ </init-param>
+ <init-param>
+ <param-name>forceparser</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <init-param>
+ <param-name>rewriteid</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>mime-type</param-name>
+ <param-value>text/xml</param-value>
+ </init-param>
+ <init-param>
+ <param-name>log4j-init-file</param-name>
+ <param-value>WEB-INF/log4j.xml</param-value>
+ </init-param>
+ <init-param>
+ <param-name>enable-cache</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>A4J</filter-name>
+ <url-pattern>*.jsf</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>A4J</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
<filter-mapping>
<filter-name>foo</filter-name>
<servlet-name>Faces Servlet</servlet-name>
15 years, 2 months
JBoss Rich Faces SVN: r14816 - in branches/jsf2.0/framework/impl/src/main/resources: org/ajax4jsf and 6 other directories.
by richfaces-svn-commits@lists.jboss.org
Author: nbelaevski
Date: 2009-07-07 13:31:52 -0400 (Tue, 07 Jul 2009)
New Revision: 14816
Added:
branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/jquery.utils.js
branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/ui.core.js
branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/resource/
branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/resource/TestResource2.resource-marker
Modified:
branches/jsf2.0/framework/impl/src/main/resources/META-INF/resources-config.xml
branches/jsf2.0/framework/impl/src/main/resources/org/ajax4jsf/javascript/scripts/form.js
branches/jsf2.0/framework/impl/src/main/resources/org/ajax4jsf/messages.properties
branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages.properties
branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages_de.properties
branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages_en.properties
branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages_pl.properties
branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/dnd/dnd-draggable.js
branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/events.js
branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/skinning.js
branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/utils.js
Log:
Reintegrated community/3.3.x into JSF 2.0 branch
Modified: branches/jsf2.0/framework/impl/src/main/resources/META-INF/resources-config.xml
===================================================================
--- branches/jsf2.0/framework/impl/src/main/resources/META-INF/resources-config.xml 2009-07-07 17:19:37 UTC (rev 14815)
+++ branches/jsf2.0/framework/impl/src/main/resources/META-INF/resources-config.xml 2009-07-07 17:31:52 UTC (rev 14816)
@@ -2,10 +2,10 @@
<resource-config>
<resource class="org.ajax4jsf.javascript.AjaxScript">
<name>org.ajax4jsf.javascript.AjaxScript</name>
- </resource>
- <resource class="org.ajax4jsf.javascript.SmartPositionScript">
- <name>org.ajax4jsf.javascript.SmartPositionScript</name>
</resource>
+ <resource class="org.ajax4jsf.javascript.SmartPositionScript">
+ <name>org.ajax4jsf.javascript.SmartPositionScript</name>
+ </resource>
<resource class="org.ajax4jsf.javascript.AjaxScript">
<name>ajax.js</name>
</resource>
@@ -25,24 +25,24 @@
<path>org/ajax4jsf/framework.pack.js</path>
<renderer class="org.ajax4jsf.resource.CompressedScriptRenderer"/>
</resource>
- <resource >
- <name>org/ajax4jsf/renderers/ajax/scripts/form.js</name>
- <path>/org/ajax4jsf/javascript/scripts/form.js</path>
- <renderer class="org.ajax4jsf.resource.ScriptRenderer"/>
- </resource>
- <resource class="org.richfaces.renderkit.html.GradientA">
- <name>org.richfaces.renderkit.html.GradientA</name>
- </resource>
+ <resource >
+ <name>org/ajax4jsf/renderers/ajax/scripts/form.js</name>
+ <path>/org/ajax4jsf/javascript/scripts/form.js</path>
+ <renderer class="org.ajax4jsf.resource.ScriptRenderer"/>
+ </resource>
+ <resource class="org.richfaces.renderkit.html.GradientA">
+ <name>org.richfaces.renderkit.html.GradientA</name>
+ </resource>
<resource class="org.richfaces.renderkit.html.CustomizeableGradient">
<name>org.richfaces.renderkit.html.CustomizeableGradient</name>
</resource>
- <resource class="org.richfaces.renderkit.html.images.SliderArrowImage">
- <name>org.richfaces.renderkit.html.images.SliderArrowImage</name>
- </resource>
+ <resource class="org.richfaces.renderkit.html.images.SliderArrowImage">
+ <name>org.richfaces.renderkit.html.images.SliderArrowImage</name>
+ </resource>
<resource class="org.richfaces.renderkit.html.BaseGradient">
<name>org.richfaces.renderkit.html.BaseGradient</name>
</resource>
-
+
<resource>
<name>jquery.js</name>
<path>org/richfaces/renderkit/html/scripts/jquery/jquery.js</path>
@@ -82,21 +82,27 @@
<name>scriptaculous/sound.js</name>
<path>org/richfaces/renderkit/html/scripts/scriptaculous/sound.js</path>
<renderer class="org.ajax4jsf.resource.ScriptRenderer"/>
- </resource>
-
+ </resource>
+
<resource>
<name>scriptaculous/unittest.js</name>
<path>org/richfaces/renderkit/html/scripts/scriptaculous/unittest.js</path>
<renderer class="org.ajax4jsf.resource.ScriptRenderer"/>
</resource>
-
+
<resource>
<name>org/richfaces/renderkit/html/scripts/jquery.jcarousel.js</name>
<path>org/richfaces/renderkit/html/scripts/jquery.jcarousel.js</path>
<renderer class="org.ajax4jsf.resource.ScriptRenderer"/>
</resource>
-
+
<resource>
+ <name>org/richfaces/renderkit/html/scripts/jquery.utils.js</name>
+ <path>org/richfaces/renderkit/html/scripts/jquery.utils.js</path>
+ <renderer class="org.ajax4jsf.resource.ScriptRenderer"/>
+ </resource>
+
+ <resource>
<name>org/ajax4jsf/javascript/scripts/AJAX.js</name>
<path>org/ajax4jsf/javascript/scripts/AJAX.js</path>
<renderer class="org.ajax4jsf.resource.ScriptRenderer"/>
@@ -130,5 +136,5 @@
<name>org/richfaces/renderkit/html/scripts/skinning.js</name>
<path>org/richfaces/renderkit/html/scripts/skinning.js</path>
<renderer class="org.ajax4jsf.resource.ScriptRenderer"/>
- </resource>
+ </resource>
</resource-config>
Modified: branches/jsf2.0/framework/impl/src/main/resources/org/ajax4jsf/javascript/scripts/form.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/resources/org/ajax4jsf/javascript/scripts/form.js 2009-07-07 17:19:37 UTC (rev 14815)
+++ branches/jsf2.0/framework/impl/src/main/resources/org/ajax4jsf/javascript/scripts/form.js 2009-07-07 17:31:52 UTC (rev 14816)
@@ -34,7 +34,14 @@
input.id=param;
input.name=param;
input.value=parameters[param];
- form.appendChild(input);
+
+ if (param === "javax.faces.portletbridge.STATE_ID" /* fix for fileUpload in portlets */
+ && form.firstChild) {
+
+ form.insertBefore(input, form.firstChild);
+ } else {
+ form.appendChild(input);
+ }
}
}
}
Modified: branches/jsf2.0/framework/impl/src/main/resources/org/ajax4jsf/messages.properties
===================================================================
--- branches/jsf2.0/framework/impl/src/main/resources/org/ajax4jsf/messages.properties 2009-07-07 17:19:37 UTC (rev 14815)
+++ branches/jsf2.0/framework/impl/src/main/resources/org/ajax4jsf/messages.properties 2009-07-07 17:31:52 UTC (rev 14816)
@@ -180,8 +180,9 @@
NULL_SKIN_NAME_ERROR=Name for current Skin calculated as null
CREATE_SKIN_INFO=Create new Skin instance for name {0}
DEFAULT_PROPERTIES_NOT_FOUND_ERROR=Default properties for skin not found in {0}
-SKIN_PROPERTIES_IO_ERROR=Attempt to load Skin property file caused IOError
+SKIN_PROPERTIES_IO_ERROR=Attempt to load property file caused IOError
SKIN_NOT_FOUND_ERROR=Skin with name {0} not found
+THEME_NOT_FOUND_ERROR=Theme with name {0} not found
ACESSING_SKIN_PROPERTY_AS_ARRAY_ERROR=Attempt to access to skin property as array
ACESSING_SKIN_PROPERTY_ERROR=Attempt to access to skin property not as string parameter
SKIN_PROPERTIES_READ_ONLY_ERROR=Skin properties is read-only
@@ -257,4 +258,5 @@
HIGHLIGHT_LIBRARY_NOT_FOUND="In order to use highlight attribute of the rich:insert component, add jhighlight.jar from https://jhighlight.dev.java.net/ into application."
INVALID_VALUE="Component {0} has invalid value expression {1}"
DATASCROLLER_PAGE_MISSING=Datascroller {0}: The requested page #{1} isn''t found in the model containing {2} pages. Paging is reset to page #{3}
-DATASCROLLER_PAGES_DIFFERENT=Datascroller components attached to component: {0} have different values of ''page'' attribute : {1}
\ No newline at end of file
+DATASCROLLER_PAGES_DIFFERENT=Datascroller components attached to component\: {0} have different values of ''page'' attribute \: {1}
+COMPONENT_CONVERSION_ERROR=Component {0}\: conversion error occurred for value {1}
\ No newline at end of file
Modified: branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages.properties
===================================================================
--- branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages.properties 2009-07-07 17:19:37 UTC (rev 14815)
+++ branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages.properties 2009-07-07 17:31:52 UTC (rev 14816)
@@ -1,9 +1,10 @@
# components
-org.richfaces.component.UIExtendedDataTable.Menu.Columns=Columns de
-org.richfaces.component.UIExtendedDataTable.Menu.SortAscending=Sort Ascending de
-org.richfaces.component.UIExtendedDataTable.Menu.SortDescending=Sort Descending de
-org.richfaces.component.UIExtendedDataTable.Menu.GroupByColumn=Group by this column de
-org.richfaces.component.UIExtendedDataTable.Menu.DisableGrouping=Disable Grouping de
+org.richfaces.component.UIExtendedDataTable.Menu.Columns=Columns
+org.richfaces.component.UIExtendedDataTable.Menu.SortAscending=Sort Ascending
+org.richfaces.component.UIExtendedDataTable.Menu.SortDescending=Sort Descending
+org.richfaces.component.UIExtendedDataTable.Menu.GroupByColumn=Group by this column
+org.richfaces.component.UIExtendedDataTable.Menu.DisableGrouping=Disable Grouping
+org.richfaces.component.UIExtendedDataTable.NoData=No data
# converters
Modified: branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages_de.properties
===================================================================
--- branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages_de.properties 2009-07-07 17:19:37 UTC (rev 14815)
+++ branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages_de.properties 2009-07-07 17:31:52 UTC (rev 14816)
@@ -1,9 +1,10 @@
# components
-org.richfaces.component.UIExtendedDataTable.Menu.Columns=Columns de
-org.richfaces.component.UIExtendedDataTable.Menu.SortAscending=Sort Ascending de
-org.richfaces.component.UIExtendedDataTable.Menu.SortDescending=Sort Descending de
-org.richfaces.component.UIExtendedDataTable.Menu.GroupByColumn=Group by this column de
-org.richfaces.component.UIExtendedDataTable.Menu.DisableGrouping=Disable Grouping de
+org.richfaces.component.UIExtendedDataTable.Menu.Columns=Spalten
+org.richfaces.component.UIExtendedDataTable.Menu.SortAscending=Absteigend sortieren
+org.richfaces.component.UIExtendedDataTable.Menu.SortDescending=Aufsteigend sortieren
+org.richfaces.component.UIExtendedDataTable.Menu.GroupByColumn=Gruppierung anhand der Spalte
+org.richfaces.component.UIExtendedDataTable.Menu.DisableGrouping=Gruppierung aufheben
+org.richfaces.component.UIExtendedDataTable.NoData=Keine Daten
# converters
Modified: branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages_en.properties
===================================================================
--- branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages_en.properties 2009-07-07 17:19:37 UTC (rev 14815)
+++ branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages_en.properties 2009-07-07 17:31:52 UTC (rev 14816)
@@ -4,6 +4,7 @@
org.richfaces.component.UIExtendedDataTable.Menu.SortDescending=Sort Descending
org.richfaces.component.UIExtendedDataTable.Menu.GroupByColumn=Group by this column
org.richfaces.component.UIExtendedDataTable.Menu.DisableGrouping=Disable Grouping
+org.richfaces.component.UIExtendedDataTable.NoData=No data
# converters
Modified: branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages_pl.properties
===================================================================
--- branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages_pl.properties 2009-07-07 17:19:37 UTC (rev 14815)
+++ branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/component/messages_pl.properties 2009-07-07 17:31:52 UTC (rev 14816)
@@ -4,6 +4,7 @@
org.richfaces.component.UIExtendedDataTable.Menu.SortDescending=Sortuj malej\u0105co
org.richfaces.component.UIExtendedDataTable.Menu.GroupByColumn=Grupuj po kolumnie
org.richfaces.component.UIExtendedDataTable.Menu.DisableGrouping=Wy\u0142\u0105cz grupowanie
+org.richfaces.component.UIExtendedDataTable.NoData=Brak danych
# converters
Modified: branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/dnd/dnd-draggable.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/dnd/dnd-draggable.js 2009-07-07 17:19:37 UTC (rev 14815)
+++ branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/dnd/dnd-draggable.js 2009-07-07 17:31:52 UTC (rev 14816)
@@ -19,12 +19,22 @@
this.onupBound = this.onup.bindAsEventListener(this);
},
- activate: function(event) {
+ activate: function(event) {
Event.observe(document, "mousemove", this.onmoveBound);
Event.observe(document, "mouseup", this.onupBound);
if (event.type == "mousemove") {
this.onmoveBound(event);
}
+ // prevent text selection in IE
+ this.onSelectStartHandler = document.onselectstart;
+ this.onDragStartHandler = document.ondragstart;
+
+ document.onselectstart = function () { return false; };
+ document.ondragstart = function () { DnD.ieReleaseCapture(); return false; };
+
+ if (document.releaseCapture) {
+ Event.observe(document, "mousemove", DnD.ieReleaseCapture);
+ }
},
onmove: function(event) {
@@ -58,6 +68,13 @@
deactivate: function() {
Event.stopObserving(document, "mousemove", this.onmoveBound);
Event.stopObserving(document, "mouseup", this.onupBound);
+
+ document.onselectstart = this.onSelectStartHandler;
+ document.ondragstart = this.onDragStartHandler;
+
+ if (document.releaseCapture) {
+ Event.stopObserving(document, "mousemove", DnD.ieReleaseCapture);
+ }
}
};
@@ -179,10 +196,12 @@
}
},
+ isDragEnabled: function() {
+ return !!this.getContentType();
+ },
+
startDrag : function(event) {
- var contentType = this.getContentType();
-
- if (contentType) {
+ if (this.isDragEnabled()) {
if(this.grabbingCursor) {
if(this.grabCursor && this.grabCursor.visible) {
this.grabCursor.hideCursor();
@@ -205,18 +224,7 @@
Event.observe(document, "mousemove", this.dragTrigger);
this.lastDragX = Event.pointerX(event);
- this.lastDragY = Event.pointerY(event);
-
- // prevent text selection in IE
- this.onSelectStartHandler = document.onselectstart;
- this.onDragStartHandler = document.ondragstart;
-
- document.onselectstart = function () { return false; };
- document.ondragstart = function () { DnD.ieReleaseCapture(); return false; };
-
- if (document.releaseCapture) {
- Event.observe(document, "mousemove", DnD.ieReleaseCapture);
- }
+ this.lastDragY = Event.pointerY(event);
}
},
@@ -261,13 +269,6 @@
this.lastDragX = undefined;
this.lastDragY = undefined;
- document.onselectstart = this.onSelectStartHandler;
- document.ondragstart = this.onDragStartHandler;
-
- if (document.releaseCapture) {
- Event.stopObserving(document, "mousemove", DnD.ieReleaseCapture);
- }
-
if (this.endDragListener) {
this.endDragListener.deactivate();
}
Modified: branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/events.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/events.js 2009-07-07 17:19:37 UTC (rev 14815)
+++ branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/events.js 2009-07-07 17:31:52 UTC (rev 14816)
@@ -117,12 +117,21 @@
return {
event: eventObj,
+
fire: function() {
if (component.fireEvent) {
component.fireEvent("on" + type, this.event);
} else {
component.dispatchEvent(this.event);
}
+ },
+
+ destroy: function() {
+ if (props) {
+ for (var name in props) {
+ this.event[name] = undefined;
+ }
+ }
}
};
}
Copied: branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/jquery.utils.js (from rev 14238, trunk/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/jquery.utils.js)
===================================================================
--- branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/jquery.utils.js (rev 0)
+++ branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/jquery.utils.js 2009-07-07 17:31:52 UTC (rev 14816)
@@ -0,0 +1,83 @@
+if (!window.Richfaces) {
+ window.Richfaces = {};
+}
+
+Richfaces.jQuery = {};
+
+(function(_r$, jQuery) {
+ var PX_REGEX = /^\s*[^\s]*px\s*$/;
+
+ var parseToPx = function(value) {
+ if (value) {
+ if (PX_REGEX.test(value)) {
+ try {
+ return parseInt(value.replace(PX_REGEX, ""), 10);
+ } catch (e) { }
+ }
+ }
+
+ return NaN;
+ };
+
+ _r$.position = function(rect, element) {
+ var jqe = jQuery(element);
+ var width = jqe.width();
+ var height = jqe.height();
+
+ var left = parseToPx(jqe.css('left'));
+ if (isNaN(left)) {
+ left = 0;
+ jqe.css('left', '0px');
+ }
+
+ var top = parseToPx(jqe.css('top'));
+ if (isNaN(top)) {
+ top = 0;
+ jqe.css('top', '0px');
+ }
+
+ var elementOffset = jqe.offset();
+
+ var jqw = jQuery(window);
+
+ var winWidth = jqw.width();
+ var winLeft = jqw.scrollLeft();
+
+ var winHeight = jqw.height();
+ var winTop = jqw.scrollTop();
+
+ var newLeft;
+ if (rect.left + width > winLeft + winWidth && rect.left + rect.width - width >= winLeft) {
+ newLeft = rect.left + rect.width - width;
+ } else {
+ newLeft = rect.left;
+ }
+
+ var newTop;
+ if (rect.top + rect.height + height > winTop + winHeight && rect.top - height >= winTop) {
+ newTop = rect.top - height;
+ } else {
+ newTop = rect.top + rect.height;
+ }
+
+ left += newLeft - elementOffset.left;
+ top += newTop - elementOffset.top;
+
+ jqe.css('left', (left + 'px')).css('top', (top + 'px'));
+ };
+
+ _r$.getPointerRectangle = function(event) {
+ var e = jQuery.event.fix(event);
+
+ return {width: 0, height: 0, left: e.pageX, top: e.pageY};
+ };
+
+ _r$.getElementRectangle = function(element) {
+ var jqe = jQuery(element);
+ var offset = jqe.offset();
+
+ return {width: jqe.width(), height: jqe.height(), left: offset.left, top: offset.top};
+ };
+
+}(Richfaces.jQuery, jQuery));
+
Modified: branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/skinning.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/skinning.js 2009-07-07 17:19:37 UTC (rev 14815)
+++ branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/skinning.js 2009-07-07 17:31:52 UTC (rev 14816)
@@ -1,7 +1,9 @@
{
var mediaName = "rich-extended-skinning";
- var skipNavigator = window.opera || navigator.userAgent.indexOf('AppleWebKit/') > -1;
+ var userAgent = navigator.userAgent;
+
+ var skipNavigator = window.opera || (userAgent.indexOf('AppleWebKit/') > -1 && userAgent.indexOf('Chrome/') == -1);
if (!skipNavigator) {
var resetMedia = function(elt) {
Copied: branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/ui.core.js (from rev 14238, trunk/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/ui.core.js)
===================================================================
--- branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/ui.core.js (rev 0)
+++ branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/ui.core.js 2009-07-07 17:31:52 UTC (rev 14816)
@@ -0,0 +1,519 @@
+/*
+ * jQuery UI 1.7.1
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI
+ */
+;jQuery.ui || (function($) {
+
+var _remove = $.fn.remove,
+ isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9);
+
+//Helper functions and ui object
+$.ui = {
+ version: "1.7.1",
+
+ // $.ui.plugin is deprecated. Use the proxy pattern instead.
+ plugin: {
+ add: function(module, option, set) {
+ var proto = $.ui[module].prototype;
+ for(var i in set) {
+ proto.plugins[i] = proto.plugins[i] || [];
+ proto.plugins[i].push([option, set[i]]);
+ }
+ },
+ call: function(instance, name, args) {
+ var set = instance.plugins[name];
+ if(!set || !instance.element[0].parentNode) { return; }
+
+ for (var i = 0; i < set.length; i++) {
+ if (instance.options[set[i][0]]) {
+ set[i][1].apply(instance.element, args);
+ }
+ }
+ }
+ },
+
+ contains: function(a, b) {
+ return document.compareDocumentPosition
+ ? a.compareDocumentPosition(b) & 16
+ : a !== b && a.contains(b);
+ },
+
+ hasScroll: function(el, a) {
+
+ //If overflow is hidden, the element might have extra content, but the user wants to hide it
+ if ($(el).css('overflow') == 'hidden') { return false; }
+
+ var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
+ has = false;
+
+ if (el[scroll] > 0) { return true; }
+
+ // TODO: determine which cases actually cause this to happen
+ // if the element doesn't have the scroll set, see if it's possible to
+ // set the scroll
+ el[scroll] = 1;
+ has = (el[scroll] > 0);
+ el[scroll] = 0;
+ return has;
+ },
+
+ isOverAxis: function(x, reference, size) {
+ //Determines when x coordinate is over "b" element axis
+ return (x > reference) && (x < (reference + size));
+ },
+
+ isOver: function(y, x, top, left, height, width) {
+ //Determines when x, y coordinates is over "b" element
+ return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);
+ },
+
+ keyCode: {
+ BACKSPACE: 8,
+ CAPS_LOCK: 20,
+ COMMA: 188,
+ CONTROL: 17,
+ DELETE: 46,
+ DOWN: 40,
+ END: 35,
+ ENTER: 13,
+ ESCAPE: 27,
+ HOME: 36,
+ INSERT: 45,
+ LEFT: 37,
+ NUMPAD_ADD: 107,
+ NUMPAD_DECIMAL: 110,
+ NUMPAD_DIVIDE: 111,
+ NUMPAD_ENTER: 108,
+ NUMPAD_MULTIPLY: 106,
+ NUMPAD_SUBTRACT: 109,
+ PAGE_DOWN: 34,
+ PAGE_UP: 33,
+ PERIOD: 190,
+ RIGHT: 39,
+ SHIFT: 16,
+ SPACE: 32,
+ TAB: 9,
+ UP: 38
+ }
+};
+
+// WAI-ARIA normalization
+if (isFF2) {
+ var attr = $.attr,
+ removeAttr = $.fn.removeAttr,
+ ariaNS = "http://www.w3.org/2005/07/aaa",
+ ariaState = /^aria-/,
+ ariaRole = /^wairole:/;
+
+ $.attr = function(elem, name, value) {
+ var set = value !== undefined;
+
+ return (name == 'role'
+ ? (set
+ ? attr.call(this, elem, name, "wairole:" + value)
+ : (attr.apply(this, arguments) || "").replace(ariaRole, ""))
+ : (ariaState.test(name)
+ ? (set
+ ? elem.setAttributeNS(ariaNS,
+ name.replace(ariaState, "aaa:"), value)
+ : attr.call(this, elem, name.replace(ariaState, "aaa:")))
+ : attr.apply(this, arguments)));
+ };
+
+ $.fn.removeAttr = function(name) {
+ return (ariaState.test(name)
+ ? this.each(function() {
+ this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
+ }) : removeAttr.call(this, name));
+ };
+}
+
+//jQuery plugins
+$.fn.extend({
+ remove: function() {
+ // Safari has a native remove event which actually removes DOM elements,
+ // so we have to use triggerHandler instead of trigger (#3037).
+ $("*", this).add(this).each(function() {
+ $(this).triggerHandler("remove");
+ });
+ return _remove.apply(this, arguments );
+ },
+
+ enableSelection: function() {
+ return this
+ .attr('unselectable', 'off')
+ .css('MozUserSelect', '')
+ .unbind('selectstart.ui');
+ },
+
+ disableSelection: function() {
+ return this
+ .attr('unselectable', 'on')
+ .css('MozUserSelect', 'none')
+ .bind('selectstart.ui', function() { return false; });
+ },
+
+ scrollParent: function() {
+ var scrollParent;
+ if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
+ scrollParent = this.parents().filter(function() {
+ return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
+ }).eq(0);
+ } else {
+ scrollParent = this.parents().filter(function() {
+ return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
+ }).eq(0);
+ }
+
+ return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
+ }
+});
+
+
+//Additional selectors
+$.extend($.expr[':'], {
+ data: function(elem, i, match) {
+ return !!$.data(elem, match[3]);
+ },
+
+ focusable: function(element) {
+ var nodeName = element.nodeName.toLowerCase(),
+ tabIndex = $.attr(element, 'tabindex');
+ return (/input|select|textarea|button|object/.test(nodeName)
+ ? !element.disabled
+ : 'a' == nodeName || 'area' == nodeName
+ ? element.href || !isNaN(tabIndex)
+ : !isNaN(tabIndex))
+ // the element and all of its ancestors must be visible
+ // the browser may report that the area is hidden
+ && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
+ },
+
+ tabbable: function(element) {
+ var tabIndex = $.attr(element, 'tabindex');
+ return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
+ }
+});
+
+
+// $.widget is a factory to create jQuery plugins
+// taking some boilerplate code out of the plugin code
+function getter(namespace, plugin, method, args) {
+ function getMethods(type) {
+ var methods = $[namespace][plugin][type] || [];
+ return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
+ }
+
+ var methods = getMethods('getter');
+ if (args.length == 1 && typeof args[0] == 'string') {
+ methods = methods.concat(getMethods('getterSetter'));
+ }
+ return ($.inArray(method, methods) != -1);
+}
+
+$.widget = function(name, prototype) {
+ var namespace = name.split(".")[0];
+ name = name.split(".")[1];
+
+ // create plugin method
+ $.fn[name] = function(options) {
+ var isMethodCall = (typeof options == 'string'),
+ args = Array.prototype.slice.call(arguments, 1);
+
+ // prevent calls to internal methods
+ if (isMethodCall && options.substring(0, 1) == '_') {
+ return this;
+ }
+
+ // handle getter methods
+ if (isMethodCall && getter(namespace, name, options, args)) {
+ var instance = $.data(this[0], name);
+ return (instance ? instance[options].apply(instance, args)
+ : undefined);
+ }
+
+ // handle initialization and non-getter methods
+ return this.each(function() {
+ var instance = $.data(this, name);
+
+ // constructor
+ (!instance && !isMethodCall &&
+ $.data(this, name, new $[namespace][name](this, options))._init());
+
+ // method call
+ (instance && isMethodCall && $.isFunction(instance[options]) &&
+ instance[options].apply(instance, args));
+ });
+ };
+
+ // create widget constructor
+ $[namespace] = $[namespace] || {};
+ $[namespace][name] = function(element, options) {
+ var self = this;
+
+ this.namespace = namespace;
+ this.widgetName = name;
+ this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
+ this.widgetBaseClass = namespace + '-' + name;
+
+ this.options = $.extend({},
+ $.widget.defaults,
+ $[namespace][name].defaults,
+ $.metadata && $.metadata.get(element)[name],
+ options);
+
+ this.element = $(element)
+ .bind('setData.' + name, function(event, key, value) {
+ if (event.target == element) {
+ return self._setData(key, value);
+ }
+ })
+ .bind('getData.' + name, function(event, key) {
+ if (event.target == element) {
+ return self._getData(key);
+ }
+ })
+ .bind('remove', function() {
+ return self.destroy();
+ });
+ };
+
+ // add widget prototype
+ $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);
+
+ // TODO: merge getter and getterSetter properties from widget prototype
+ // and plugin prototype
+ $[namespace][name].getterSetter = 'option';
+};
+
+$.widget.prototype = {
+ _init: function() {},
+ destroy: function() {
+ this.element.removeData(this.widgetName)
+ .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
+ .removeAttr('aria-disabled');
+ },
+
+ option: function(key, value) {
+ var options = key,
+ self = this;
+
+ if (typeof key == "string") {
+ if (value === undefined) {
+ return this._getData(key);
+ }
+ options = {};
+ options[key] = value;
+ }
+
+ $.each(options, function(key, value) {
+ self._setData(key, value);
+ });
+ },
+ _getData: function(key) {
+ return this.options[key];
+ },
+ _setData: function(key, value) {
+ this.options[key] = value;
+
+ if (key == 'disabled') {
+ this.element
+ [value ? 'addClass' : 'removeClass'](
+ this.widgetBaseClass + '-disabled' + ' ' +
+ this.namespace + '-state-disabled')
+ .attr("aria-disabled", value);
+ }
+ },
+
+ enable: function() {
+ this._setData('disabled', false);
+ },
+ disable: function() {
+ this._setData('disabled', true);
+ },
+
+ _trigger: function(type, event, data) {
+ var callback = this.options[type],
+ eventName = (type == this.widgetEventPrefix
+ ? type : this.widgetEventPrefix + type);
+
+ event = $.Event(event);
+ event.type = eventName;
+
+ // copy original event properties over to the new event
+ // this would happen if we could call $.event.fix instead of $.Event
+ // but we don't have a way to force an event to be fixed multiple times
+ if (event.originalEvent) {
+ for (var i = $.event.props.length, prop; i;) {
+ prop = $.event.props[--i];
+ event[prop] = event.originalEvent[prop];
+ }
+ }
+
+ this.element.trigger(event, data);
+
+ return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false
+ || event.isDefaultPrevented());
+ }
+};
+
+$.widget.defaults = {
+ disabled: false
+};
+
+
+/** Mouse Interaction Plugin **/
+
+$.ui.mouse = {
+ _mouseInit: function() {
+ var self = this;
+
+ this.element
+ .bind('mousedown.'+this.widgetName, function(event) {
+ return self._mouseDown(event);
+ })
+ .bind('click.'+this.widgetName, function(event) {
+ if(self._preventClickEvent) {
+ self._preventClickEvent = false;
+ event.stopImmediatePropagation();
+ return false;
+ }
+ });
+
+ // Prevent text selection in IE
+ if ($.browser.msie) {
+ this._mouseUnselectable = this.element.attr('unselectable');
+ this.element.attr('unselectable', 'on');
+ }
+
+ this.started = false;
+ },
+
+ // TODO: make sure destroying one instance of mouse doesn't mess with
+ // other instances of mouse
+ _mouseDestroy: function() {
+ this.element.unbind('.'+this.widgetName);
+
+ // Restore text selection in IE
+ ($.browser.msie
+ && this.element.attr('unselectable', this._mouseUnselectable));
+ },
+
+ _mouseDown: function(event) {
+ // don't let more than one widget handle mouseStart
+ // TODO: figure out why we have to use originalEvent
+ event.originalEvent = event.originalEvent || {};
+ if (event.originalEvent.mouseHandled) { return; }
+
+ // we may have missed mouseup (out of window)
+ (this._mouseStarted && this._mouseUp(event));
+
+ this._mouseDownEvent = event;
+
+ var self = this,
+ btnIsLeft = (event.which == 1),
+ elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
+ if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
+ return true;
+ }
+
+ this.mouseDelayMet = !this.options.delay;
+ if (!this.mouseDelayMet) {
+ this._mouseDelayTimer = setTimeout(function() {
+ self.mouseDelayMet = true;
+ }, this.options.delay);
+ }
+
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+ this._mouseStarted = (this._mouseStart(event) !== false);
+ if (!this._mouseStarted) {
+ event.preventDefault();
+ return true;
+ }
+ }
+
+ // these delegates are required to keep context
+ this._mouseMoveDelegate = function(event) {
+ return self._mouseMove(event);
+ };
+ this._mouseUpDelegate = function(event) {
+ return self._mouseUp(event);
+ };
+ $(document)
+ .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+ .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+
+ // preventDefault() is used to prevent the selection of text here -
+ // however, in Safari, this causes select boxes not to be selectable
+ // anymore, so this fix is needed
+ ($.browser.safari || event.preventDefault());
+
+ event.originalEvent.mouseHandled = true;
+ return true;
+ },
+
+ _mouseMove: function(event) {
+ // IE mouseup check - mouseup happened when mouse was out of window
+ if ($.browser.msie && !event.button) {
+ return this._mouseUp(event);
+ }
+
+ if (this._mouseStarted) {
+ this._mouseDrag(event);
+ return event.preventDefault();
+ }
+
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+ this._mouseStarted =
+ (this._mouseStart(this._mouseDownEvent, event) !== false);
+ (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
+ }
+
+ return !this._mouseStarted;
+ },
+
+ _mouseUp: function(event) {
+ $(document)
+ .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+ .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+
+ if (this._mouseStarted) {
+ this._mouseStarted = false;
+ this._preventClickEvent = (event.target == this._mouseDownEvent.target);
+ this._mouseStop(event);
+ }
+
+ return false;
+ },
+
+ _mouseDistanceMet: function(event) {
+ return (Math.max(
+ Math.abs(this._mouseDownEvent.pageX - event.pageX),
+ Math.abs(this._mouseDownEvent.pageY - event.pageY)
+ ) >= this.options.distance
+ );
+ },
+
+ _mouseDelayMet: function(event) {
+ return this.mouseDelayMet;
+ },
+
+ // These are placeholder methods, to be overriden by extending plugin
+ _mouseStart: function(event) {},
+ _mouseDrag: function(event) {},
+ _mouseStop: function(event) {},
+ _mouseCapture: function(event) { return true; }
+};
+
+$.ui.mouse.defaults = {
+ cancel: null,
+ distance: 1,
+ delay: 0
+};
+
+})(jQuery);
Modified: branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/utils.js
===================================================================
--- branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/utils.js 2009-07-07 17:19:37 UTC (rev 14815)
+++ branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/renderkit/html/scripts/utils.js 2009-07-07 17:31:52 UTC (rev 14816)
@@ -123,38 +123,38 @@
Richfaces.evalMacro = function(template, object)
{
- var value="";
+ var _value_="";
// variable evaluation
if (Richfaces.VARIABLE_NAME_PATTERN.test(template))
{
if (template.indexOf('.')==-1) {
- value = object[template];
- if (!value) value=window[template];
+ _value_ = object[template];
+ if (!_value_) _value_=window[template];
}
// object's variable evaluation
else {
- value = Richfaces.getObjectValue(template, object);
- if (!value) value=Richfaces.getObjectValue(template, window);
+ _value_ = Richfaces.getObjectValue(template, object);
+ if (!_value_) _value_=Richfaces.getObjectValue(template, window);
}
- if (value && typeof value=='function') value = value(object);
- if (!value) value="";
+ if (_value_ && typeof _value_=='function') _value_ = _value_(object);
+ if (!_value_) _value_="";
}
//js string evaluation
else {
try {
if (Richfaces.browser.isObjectEval) {
- value = object.eval(template);
+ _value_ = object.eval(template);
}
else with (object) {
- value = eval(template) ;
+ _value_ = eval(template) ;
}
- if (typeof value == 'function') {
- value = value(object);
+ if (typeof _value_ == 'function') {
+ _value_ = _value_(object);
}
} catch (e) { LOG.warn("Exception: "+e.Message + "\n[" + template + "]"); }
}
- return value;
+ return _value_;
}
Richfaces.evalSimpleMacro = function(template, object)
{
@@ -181,6 +181,7 @@
isSafari: /Safari/.test(navigator.userAgent),
isOpera: !!window.opera,
isObjectEval: (Richfaces.eval!=undefined),
+ isFF2: (!window.opera && /Firefox\s*[\/]2[\.]/.test(navigator.userAgent)),
isFF3: (!window.opera && /Firefox\s*[\/]3[\.]/.test(navigator.userAgent))
};
@@ -442,4 +443,77 @@
element.removeAttributeNode(node);
}
}
-};
\ No newline at end of file
+};
+
+Richfaces.mergeObjects = function() {
+ var target = arguments[0];
+ if (target) {
+ for (var i = 1; i < arguments.length; i++) {
+ var source = arguments[i];
+ if (source) {
+ for (var name in source) {
+ if (!target[name]) {
+ target[name] = source[name];
+ }
+ }
+ }
+ }
+ }
+};
+
+Richfaces.invokeEvent = function(eventFunc, element, eventName, memo) {
+ var result;
+ if (eventFunc) {
+ 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.rich = {component:this};
+ event.memo = memo || { };
+ try {
+ result = eventFunc.call(element,event);
+ }
+ catch (e) { LOG.warn("Exception: "+e.Message + "\n[on"+eventName + "]"); }
+ }
+ if (result!=false) result = true;
+ return result;
+};
+
+Richfaces.setupScrollEventHandlers = function(element, handler) {
+
+ var elements = []
+
+ element = element.parentNode;
+ while (element && element!=window.document.body)
+ {
+ if (element.offsetWidth!=element.scrollWidth || element.offsetHeight!=element.scrollHeight)
+ {
+ elements.push(element);
+ Event.observe(element, "scroll", handler, false);
+ }
+ element = element.parentNode;
+ }
+
+ return elements;
+};
+
+Richfaces.removeScrollEventHandlers = function(elements, handler) {
+ if (elements)
+ {
+ for (var i=0;i<elements.length;i++)
+ {
+ Event.stopObserving(elements[i], "scroll", handler, false);
+ }
+ elements = null;
+ }
+};
Added: branches/jsf2.0/framework/impl/src/main/resources/org/richfaces/resource/TestResource2.resource-marker
===================================================================
15 years, 2 months