[kune-commits] r1439 - in trunk: . src/main/java/cc/kune/core/client/errors src/main/java/cc/kune/core/client/services src/main/java/cc/kune/core/public src/main/java/cc/kune/core/server/state src/main/java/cc/kune/wave/server src/main/java/com src/main/java/com/google src/main/java/com/google/wave src/main/java/com/google/wave/splash src/main/java/com/google/wave/splash/rpc src/main/java/com/google/wave/splash/text src/main/java/com/google/wave/splash/web src/main/java/com/google/wave/splash/web/template src/main/java/org/ourproject/kune/chat/client src/main/java/org/ourproject/kune/wiki src/main/java/org/ourproject/kune/workspace/client src/main/webapp/others src/main/webapp/others/splash src/main/webapp/others/splash/images src/main/webapp/others/splash/js src/main/webapp/others/splash/style src/test/java/cc/kune/wave/server

Vicente J. Ruiz Jurado vjrj_ at ourproject.org
Fri Jul 1 13:27:51 CEST 2011


Author: vjrj_
Date: 2011-07-01 13:27:50 +0200 (Fri, 01 Jul 2011)
New Revision: 1439

Added:
   trunk/src/main/java/com/google/
   trunk/src/main/java/com/google/wave/
   trunk/src/main/java/com/google/wave/splash/
   trunk/src/main/java/com/google/wave/splash/rpc/
   trunk/src/main/java/com/google/wave/splash/rpc/ClientAction.java
   trunk/src/main/java/com/google/wave/splash/text/
   trunk/src/main/java/com/google/wave/splash/text/ContentRenderer.java
   trunk/src/main/java/com/google/wave/splash/text/ContentUnrenderer.java
   trunk/src/main/java/com/google/wave/splash/text/GadgetRenderer.java
   trunk/src/main/java/com/google/wave/splash/text/Markup.java
   trunk/src/main/java/com/google/wave/splash/web/
   trunk/src/main/java/com/google/wave/splash/web/template/
   trunk/src/main/java/com/google/wave/splash/web/template/Templates.java
   trunk/src/main/java/com/google/wave/splash/web/template/ThreadedWaveRenderer.java
   trunk/src/main/java/com/google/wave/splash/web/template/WaveRenderer.java
   trunk/src/main/webapp/others/splash/
   trunk/src/main/webapp/others/splash/blip.html.fragment
   trunk/src/main/webapp/others/splash/feed.html.fragment
   trunk/src/main/webapp/others/splash/full_client.html
   trunk/src/main/webapp/others/splash/header.html.fragment
   trunk/src/main/webapp/others/splash/images/
   trunk/src/main/webapp/others/splash/images/attachment.png
   trunk/src/main/webapp/others/splash/images/avatar1.png
   trunk/src/main/webapp/others/splash/images/avatar2.png
   trunk/src/main/webapp/others/splash/images/avatar3.png
   trunk/src/main/webapp/others/splash/images/avatar4.png
   trunk/src/main/webapp/others/splash/images/avatar5.png
   trunk/src/main/webapp/others/splash/images/avatar6.png
   trunk/src/main/webapp/others/splash/images/background_dot.png
   trunk/src/main/webapp/others/splash/images/close_window.png
   trunk/src/main/webapp/others/splash/images/comment.png
   trunk/src/main/webapp/others/splash/images/cross.png
   trunk/src/main/webapp/others/splash/images/dialog_close.gif
   trunk/src/main/webapp/others/splash/images/dialog_pointer.gif
   trunk/src/main/webapp/others/splash/images/email.png
   trunk/src/main/webapp/others/splash/images/group.png
   trunk/src/main/webapp/others/splash/images/inline_reply_arrow.gif
   trunk/src/main/webapp/others/splash/images/inline_reply_arrow_expanded.gif
   trunk/src/main/webapp/others/splash/images/inline_reply_pointer.gif
   trunk/src/main/webapp/others/splash/images/lightbox-blank.gif
   trunk/src/main/webapp/others/splash/images/lightbox-btn-close.gif
   trunk/src/main/webapp/others/splash/images/lightbox-btn-next.gif
   trunk/src/main/webapp/others/splash/images/lightbox-btn-prev.gif
   trunk/src/main/webapp/others/splash/images/lightbox-ico-loading.gif
   trunk/src/main/webapp/others/splash/images/loading.gif
   trunk/src/main/webapp/others/splash/images/loading_permalink.gif
   trunk/src/main/webapp/others/splash/images/logo.png
   trunk/src/main/webapp/others/splash/images/logo_on_black.png
   trunk/src/main/webapp/others/splash/images/logo_small.png
   trunk/src/main/webapp/others/splash/images/minimize_window.png
   trunk/src/main/webapp/others/splash/images/page_edit.png
   trunk/src/main/webapp/others/splash/images/pencil.png
   trunk/src/main/webapp/others/splash/images/reply.png
   trunk/src/main/webapp/others/splash/images/search_field_on_black.png
   trunk/src/main/webapp/others/splash/images/search_field_on_black_button.png
   trunk/src/main/webapp/others/splash/images/search_field_on_black_button_right.png
   trunk/src/main/webapp/others/splash/images/search_field_on_black_left.png
   trunk/src/main/webapp/others/splash/images/search_small_button.png
   trunk/src/main/webapp/others/splash/images/share_icon.png
   trunk/src/main/webapp/others/splash/images/user1.png
   trunk/src/main/webapp/others/splash/images/user2.png
   trunk/src/main/webapp/others/splash/images/user3.png
   trunk/src/main/webapp/others/splash/images/user4.png
   trunk/src/main/webapp/others/splash/images/user5.png
   trunk/src/main/webapp/others/splash/images/user6.png
   trunk/src/main/webapp/others/splash/images/wave-loading.gif
   trunk/src/main/webapp/others/splash/js/
   trunk/src/main/webapp/others/splash/js/common_client.js
   trunk/src/main/webapp/others/splash/js/editor.js
   trunk/src/main/webapp/others/splash/js/embed_support.js
   trunk/src/main/webapp/others/splash/js/embed_test.js
   trunk/src/main/webapp/others/splash/js/full_client.js
   trunk/src/main/webapp/others/splash/js/gadget.js
   trunk/src/main/webapp/others/splash/js/ie6sucks.js
   trunk/src/main/webapp/others/splash/js/jScrollTouch.js
   trunk/src/main/webapp/others/splash/js/jquery-1.4.2.min.js
   trunk/src/main/webapp/others/splash/js/jquery.lightbox-0.5.min.js
   trunk/src/main/webapp/others/splash/js/mobile_client.js
   trunk/src/main/webapp/others/splash/js/permalink_client.js
   trunk/src/main/webapp/others/splash/js/rpc.js
   trunk/src/main/webapp/others/splash/js/rpc_test.js
   trunk/src/main/webapp/others/splash/mobile_client.html
   trunk/src/main/webapp/others/splash/permalink_client.html
   trunk/src/main/webapp/others/splash/rpc_relay.html
   trunk/src/main/webapp/others/splash/style/
   trunk/src/main/webapp/others/splash/style/border-radius.htc
   trunk/src/main/webapp/others/splash/style/jquery.lightbox-0.5.css
   trunk/src/main/webapp/others/splash/style/main.css
   trunk/src/main/webapp/others/splash/style/mobile.css
   trunk/src/main/webapp/others/splash/style/orig-style.css
   trunk/src/main/webapp/others/splash/style/permalink.css
   trunk/src/main/webapp/others/splash/style/permalink_ie.css
   trunk/src/main/webapp/others/splash/style/stuff.css
   trunk/src/main/webapp/others/splash/wave_not_found.html.fragment
   trunk/src/test/java/cc/kune/wave/server/KuneWaveMarkupTests.java
Removed:
   trunk/src/main/java/org/ourproject/kune/chat/client/ctx/
   trunk/src/main/java/org/ourproject/kune/wiki/client/
   trunk/src/main/java/org/ourproject/kune/workspace/client/sitebar/
Modified:
   trunk/.classpath
   trunk/pom.xml
   trunk/src/main/java/cc/kune/core/client/errors/DefaultException.java
   trunk/src/main/java/cc/kune/core/client/services/FileDownloadUtils.java
   trunk/src/main/java/cc/kune/core/public/ws.html
   trunk/src/main/java/cc/kune/core/server/state/StateServiceDefault.java
   trunk/src/main/java/cc/kune/wave/server/KuneWaveManager.java
   trunk/src/main/java/cc/kune/wave/server/KuneWaveManagerDefault.java
   trunk/src/test/java/cc/kune/wave/server/KuneWaveManagerDefaultTest.java
Log:
Wave renderer

Modified: trunk/.classpath
===================================================================
--- trunk/.classpath	2011-07-01 01:37:33 UTC (rev 1438)
+++ trunk/.classpath	2011-07-01 11:27:50 UTC (rev 1439)
@@ -92,6 +92,7 @@
   <classpathentry kind="var" path="M2_REPO/org/jruby/rack/jruby-rack/0.9.4/jruby-rack-0.9.4.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/json/json/20080701/json-20080701.jar" sourcepath="M2_REPO/org/json/json/20080701/json-20080701-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/net/sf/json-lib/json-lib/2.1/json-lib-2.1-jdk15.jar" sourcepath="M2_REPO/net/sf/json-lib/json-lib/2.1/json-lib-2.1-jdk15-sources.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/jsoup/jsoup/1.2.2/jsoup-1.2.2.jar" sourcepath="M2_REPO/org/jsoup/jsoup/1.2.2/jsoup-1.2.2-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/net/sourceforge/findbugs/jsr-305/v0r47/jsr-305-v0r47.jar" sourcepath="M2_REPO/net/sourceforge/findbugs/jsr-305/v0r47/jsr-305-v0r47-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/hibernate/jtidy/r8-20060801/jtidy-r8-20060801.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/jukito/jukito/1.0/jukito-1.0.jar" sourcepath="M2_REPO/org/jukito/jukito/1.0/jukito-1.0-sources.jar"/>
@@ -111,6 +112,7 @@
   <classpathentry kind="var" path="M2_REPO/org/waveprotocol/media-src/0.3.1-SNAPSHOT/media-src-0.3.1-SNAPSHOT.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/mockito/mockito-core/1.8.5/mockito-core-1.8.5.jar" sourcepath="M2_REPO/org/mockito/mockito-core/1.8.5/mockito-core-1.8.5-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/waveprotocol/model-src/0.3.1-SNAPSHOT/model-src-0.3.1-SNAPSHOT.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/mvel/mvel2/2.0.16/mvel2-2.0.16.jar" sourcepath="M2_REPO/org/mvel/mvel2/2.0.16/mvel2-2.0.16-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/mysql/mysql-connector-java/5.1.13/mysql-connector-java-5.1.13.jar"/>
   <classpathentry kind="var" path="M2_REPO/net/sourceforge/nekohtml/nekohtml/1.9.14/nekohtml-1.9.14.jar" sourcepath="M2_REPO/net/sourceforge/nekohtml/nekohtml/1.9.14/nekohtml-1.9.14-sources.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/objenesis/objenesis/1.0/objenesis-1.0.jar" sourcepath="M2_REPO/org/objenesis/objenesis/1.0/objenesis-1.0-sources.jar"/>

Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml	2011-07-01 01:37:33 UTC (rev 1438)
+++ trunk/pom.xml	2011-07-01 11:27:50 UTC (rev 1439)
@@ -658,6 +658,17 @@
       <version>1.4</version>
       <type>jar</type>
     </dependency>
+    <!-- splash -->
+<dependency>
+    <groupId>org.jsoup</groupId>
+    <artifactId>jsoup</artifactId>
+    <version>1.2.2</version>
+</dependency>
+<dependency>
+    <groupId>org.mvel</groupId>
+    <artifactId>mvel2</artifactId>
+    <version>2.0.16</version>
+</dependency>
     <!-- gwtupload -->
     <dependency>
       <groupId>com.googlecode.gwtupload</groupId>

Modified: trunk/src/main/java/cc/kune/core/client/errors/DefaultException.java
===================================================================
--- trunk/src/main/java/cc/kune/core/client/errors/DefaultException.java	2011-07-01 01:37:33 UTC (rev 1438)
+++ trunk/src/main/java/cc/kune/core/client/errors/DefaultException.java	2011-07-01 11:27:50 UTC (rev 1439)
@@ -24,18 +24,26 @@
 
 public class DefaultException extends InvocationException implements IsSerializable {
 
-    private static final long serialVersionUID = -6111471089427505005L;
+  private static final long serialVersionUID = -6111471089427505005L;
 
-    public DefaultException() {
-        this(0, "");
-    }
+  public DefaultException() {
+    this(0, "");
+  }
 
-    public DefaultException(final int statusCode, final String message) {
-        super(statusCode + " " + message);
+  public DefaultException(final int statusCode, final String message) {
+    super(statusCode + " " + message);
 
-    }
+  }
 
-    public DefaultException(final String message) {
-        super(message);
-    }
+  public DefaultException(final String message) {
+    super(message);
+  }
+
+  public DefaultException(final String message, final Throwable cause) {
+    super(message, cause);
+  }
+
+  public DefaultException(final Throwable cause) {
+    super("", cause);
+  }
 }

Modified: trunk/src/main/java/cc/kune/core/client/services/FileDownloadUtils.java
===================================================================
--- trunk/src/main/java/cc/kune/core/client/services/FileDownloadUtils.java	2011-07-01 01:37:33 UTC (rev 1438)
+++ trunk/src/main/java/cc/kune/core/client/services/FileDownloadUtils.java	2011-07-01 11:27:50 UTC (rev 1439)
@@ -33,7 +33,7 @@
 
 public class FileDownloadUtils {
 
-  private static final String AVATARDOWNLOADSERVLET = "servlets/UserLogoDownloadManager";
+  public static final String AVATARDOWNLOADSERVLET = "servlets/UserLogoDownloadManager";
   private static final String BACKDOWNLOADSERVLET = "servlets/EntityBackgroundDownloadManager";
   private static final String DOWNLOADSERVLET = "servlets/FileDownloadManager";
   protected static final String GROUP_NO_AVATAR_IMAGE = "images/group-def-icon.png";

Modified: trunk/src/main/java/cc/kune/core/public/ws.html
===================================================================
--- trunk/src/main/java/cc/kune/core/public/ws.html	2011-07-01 01:37:33 UTC (rev 1438)
+++ trunk/src/main/java/cc/kune/core/public/ws.html	2011-07-01 11:27:50 UTC (rev 1439)
@@ -51,7 +51,15 @@
 <link type="text/css" rel="stylesheet"
     href="fontface/ubuntufontface.css">
 <link type="text/css" rel="stylesheet" href="kune-message.css">
+<link type="text/css" rel="stylesheet" href="/others/splash/style/permalink.css">
+<link type="text/css" rel="stylesheet" href="/others/splash/style/stuff.css">
+<link type="text/css" rel="stylesheet" href="/others/splash/style/main.css">
 <link type="text/css" rel="stylesheet" href="ws.css">
+<script type="text/javascript" src="/others/splash/js/gadget.js"></script>
+<script type="text/javascript" src="/others/splash/js/rpc.js"></script>
+<script type="text/javascript" src="/others/splash/js/common_client.js"></script>
+<script type="text/javascript" src="/others/splash/js/permalink_client.js"></script>
+
 <style type="text/css">
 body {
   background-color: white;

Modified: trunk/src/main/java/cc/kune/core/server/state/StateServiceDefault.java
===================================================================
--- trunk/src/main/java/cc/kune/core/server/state/StateServiceDefault.java	2011-07-01 01:37:33 UTC (rev 1438)
+++ trunk/src/main/java/cc/kune/core/server/state/StateServiceDefault.java	2011-07-01 11:27:50 UTC (rev 1439)
@@ -109,8 +109,8 @@
         // FIXME if we remove the authors this fails...
         final Wavelet wavelet = kuneWaveManager.fetchWavelet(
             JavaWaverefEncoder.decodeWaveRefFromPath(waveId), content.getAuthors().get(0).getShortName());
-        final String currentContent = wavelet.getRootBlip().getContent();
-        state.setContent(currentContent);
+        // final String currentContent = wavelet.getRootBlip().getContent();
+        state.setContent(kuneWaveManager.render(wavelet));
         // Well we "cache" the last modified time of waves in db (w'll find
         // another way to do it better in the future with db persitence of
         // waves)

Modified: trunk/src/main/java/cc/kune/wave/server/KuneWaveManager.java
===================================================================
--- trunk/src/main/java/cc/kune/wave/server/KuneWaveManager.java	2011-07-01 01:37:33 UTC (rev 1438)
+++ trunk/src/main/java/cc/kune/wave/server/KuneWaveManager.java	2011-07-01 11:27:50 UTC (rev 1439)
@@ -43,6 +43,10 @@
 
   boolean isParticipant(Wavelet wavelet, String user);
 
+  String render(Wavelet wavelet);
+
+  String render(WaveRef waveRef, String author);
+
   void setTitle(WaveRef waveName, String title, String author);
 
 }

Modified: trunk/src/main/java/cc/kune/wave/server/KuneWaveManagerDefault.java
===================================================================
--- trunk/src/main/java/cc/kune/wave/server/KuneWaveManagerDefault.java	2011-07-01 01:37:33 UTC (rev 1438)
+++ trunk/src/main/java/cc/kune/wave/server/KuneWaveManagerDefault.java	2011-07-01 11:27:50 UTC (rev 1439)
@@ -68,6 +68,8 @@
 import com.google.wave.api.impl.DocumentModifyAction.BundledAnnotation;
 import com.google.wave.api.impl.DocumentModifyAction.ModifyHow;
 import com.google.wave.api.impl.WaveletData;
+import com.google.wave.splash.rpc.ClientAction;
+import com.google.wave.splash.web.template.WaveRenderer;
 
 public class KuneWaveManagerDefault implements KuneWaveManager {
   public static final Log LOG = LogFactory.getLog(KuneWaveManagerDefault.class);
@@ -86,17 +88,20 @@
   private final ParticipantUtils participantUtils;
   private final WaveletProvider waveletProvider;
 
+  private final WaveRenderer waveRenderer;
+
   @Inject
   public KuneWaveManagerDefault(final EventDataConverterManager converterManager,
       @Named("DataApiRegistry") final OperationServiceRegistry operationRegistry,
       final WaveletProvider waveletProvider, final ConversationUtil conversationUtil,
-      final ParticipantUtils participantUtils,
+      final ParticipantUtils participantUtils, final WaveRenderer waveRenderer,
       @Named(CoreSettings.WAVE_SERVER_DOMAIN) final String domain) {
     this.converterManager = converterManager;
     this.waveletProvider = waveletProvider;
     this.conversationUtil = conversationUtil;
     this.operationRegistry = operationRegistry;
     this.participantUtils = participantUtils;
+    this.waveRenderer = waveRenderer;
     this.domain = domain;
   }
 
@@ -158,8 +163,8 @@
     final Wavelet newWavelet = opQueue.createWavelet(domain, participants);
     opQueue.setTitleOfWavelet(newWavelet, title);
     final Blip rootBlip = newWavelet.getRootBlip();
-    rootBlip.append(new com.google.wave.api.Markup(message).getText());
-
+    // rootBlip.append(new com.google.wave.api.Markup(message).getText());
+    rootBlip.appendMarkup(message);
     if (gadgetUrl != WITHOUT_GADGET) {
       final Gadget gadget = new Gadget(gadgetUrl.toString());
       rootBlip.append(gadget);
@@ -295,6 +300,17 @@
   }
 
   @Override
+  public String render(final Wavelet wavelet) {
+    final ClientAction clientPage = waveRenderer.render(wavelet, 0);
+    return clientPage.getHtml();
+  }
+
+  @Override
+  public String render(final WaveRef waveRef, final String author) {
+    return render(fetchWavelet(waveRef, author));
+  }
+
+  @Override
   public void setTitle(final WaveRef waveName, final String title, final String author) {
     final Wavelet wavelet = fetchWavelet(waveName, author);
     final OperationQueue opQueue = new OperationQueue();

Added: trunk/src/main/java/com/google/wave/splash/rpc/ClientAction.java
===================================================================
--- trunk/src/main/java/com/google/wave/splash/rpc/ClientAction.java	                        (rev 0)
+++ trunk/src/main/java/com/google/wave/splash/rpc/ClientAction.java	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,106 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.google.wave.splash.rpc;
+
+/**
+ * A value object that is transformed into a JSON return value for the web client
+ * to process.
+ *
+ * @author dhanji at gmail.com (Dhanji R. Prasanna)
+ */
+public final class ClientAction {
+  private String waveId;
+  private String blipId;
+  private String action;
+  private String html = "";
+
+  private String parent;
+  private boolean indent;
+  private long version;
+
+  public ClientAction(String action) {
+    action(action);
+  }
+
+  public String getBlipId() {
+    return blipId;
+  }
+
+  public ClientAction blipId(String blipId) {
+    this.blipId = blipId;
+    return this;
+  }
+
+  public ClientAction waveId(String waveId) {
+    this.waveId = waveId;
+    return this;
+  }
+
+  public String getWaveId() {
+    return waveId;
+  }
+
+  public String getAction() {
+    return action;
+  }
+
+  public ClientAction action(String action) {
+    this.action = action;
+    return this;
+  }
+
+  public String getHtml() {
+    return html;
+  }
+
+  public ClientAction html(String html) {
+    this.html = html;
+    return this;
+  }
+
+  public String getParent() {
+    return parent;
+  }
+
+  public ClientAction parent(String parent) {
+    this.parent = parent;
+    return this;
+  }
+
+  public boolean isIndent() {
+    return indent;
+  }
+
+  public ClientAction indent() {
+    this.indent = true;
+    return this;
+  }
+
+  public ClientAction indent(boolean indent) {
+    this.indent = indent;
+    return this;
+  }
+
+  public ClientAction version(long version) {
+    this.version = version;
+    return this;
+  }
+
+  public long getVersion() {
+    return version;
+  }
+}


Property changes on: trunk/src/main/java/com/google/wave/splash/rpc/ClientAction.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/java/com/google/wave/splash/text/ContentRenderer.java
===================================================================
--- trunk/src/main/java/com/google/wave/splash/text/ContentRenderer.java	                        (rev 0)
+++ trunk/src/main/java/com/google/wave/splash/text/ContentRenderer.java	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,240 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.google.wave.splash.text;
+
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import com.google.inject.Inject;
+import com.google.wave.api.Annotation;
+import com.google.wave.api.Annotations;
+import com.google.wave.api.Attachment;
+import com.google.wave.api.Element;
+import com.google.wave.api.ElementType;
+import com.google.wave.api.Gadget;
+import com.google.wave.splash.web.template.WaveRenderer;
+
+/**
+ * A utility class that converts blip content into html.
+ * 
+ * @author David Byttow
+ * @author dhanji at gmail.com (Dhanji R. Prasanna)
+ */
+public class ContentRenderer {
+
+  /**
+   * Represents a marker in content that is either the start or end of an
+   * annotation or a single element.
+   */
+  static class Marker implements Comparable<Marker> {
+    static Marker fromAnnotation(final Annotation annotation, final int index, final boolean isEnd) {
+      return new Marker(annotation, index, isEnd);
+    }
+
+    static Marker fromElement(final Element element, final int index) {
+      return new Marker(element, index);
+    }
+
+    private final Annotation annotation;
+    private final Element element;
+    private final int index;
+    private boolean isEnd;
+
+    private Marker(final Annotation annotation, final int index, final boolean isEnd) {
+      this.annotation = annotation;
+      this.element = null;
+      this.index = index;
+      this.isEnd = isEnd;
+    }
+
+    private Marker(final Element element, final int index) {
+      this.element = element;
+      this.annotation = null;
+      this.index = index;
+    }
+
+    @Override
+    public int compareTo(final Marker that) {
+      final int value = Integer.signum(this.index - that.index);
+      if (value == 0) {
+        if (this.isElement() != that.isElement()) {
+          // At boundaries, annotations should wrap elements.
+          final Marker annotation = this.isAnnotation() ? this : that;
+          return annotation.isEnd ? -1 : 1;
+        }
+      }
+      return value;
+    }
+
+    boolean isAnnotation() {
+      return this.annotation != null;
+    }
+
+    boolean isElement() {
+      return this.element != null;
+    }
+  }
+
+  private final GadgetRenderer gadgetRenderer;
+  private final WaveRenderer waveRenderer;
+
+  @Inject
+  public ContentRenderer(final GadgetRenderer gadgetRenderer, final WaveRenderer waveRenderer) {
+    this.gadgetRenderer = gadgetRenderer;
+    this.waveRenderer = waveRenderer;
+  }
+
+  private void emitStyleAnnotation(final Marker marker, final StringBuilder builder) {
+    if (marker.isEnd) {
+      builder.append("</span>");
+    } else {
+      // Transform name into dash-separated css property rather than lower camel
+      // case.
+      String name = Markup.sanitize(marker.annotation.getName());
+      final String value = Markup.sanitize(marker.annotation.getValue());
+
+      // Title annotations are translated as bold.
+      name = name.substring(marker.annotation.getName().indexOf("/") + 1);
+      name = Markup.toDashedStyle(name);
+
+      builder.append("<span style='");
+      builder.append(name);
+      builder.append(':');
+      builder.append(value);
+      builder.append("'>");
+    }
+  }
+
+  private void renderElement(final Element element, final int index, final List<String> contributors,
+      final StringBuilder builder) {
+    final ElementType type = element.getType();
+    switch (type) {
+    case LINE:
+      // TODO(anthonybaxter): need to handle <line t="li"> and <line t="li"
+      // i="3">
+      // TODO(anthonybaxter): also handle H1 &c
+      // Special case: If this is the first LINE element at position 0,
+      // ignore it because we've already appended the first <p> tag.
+      if (index > 0) {
+        builder.append("</p><p>");
+      }
+      break;
+    case ATTACHMENT:
+      final Attachment attachment = (Attachment) element;
+      final String url = Markup.sanitizeAndEncode(attachment.getAttachmentUrl());
+      String caption = Markup.sanitize(element.getProperty("caption"));
+      if (caption == null) {
+        caption = "";
+      }
+      // TODO: Revisit this questionable html.
+      builder.append("<table class=\"attachment-element\"><tr><td>").append(
+          "<a class=\"lightbox\" title=\"").append(caption).append("\" href=\"").append(url).append(
+          "\"><img src=\"").append(url).append(
+          "\"/></a></td></tr></td></tr><tr><td><div class=\"caption\">").append(caption).append(
+          "</div></td></tr></table>");
+      break;
+    case IMAGE:
+      String imageUrl = element.getProperty("url");
+
+      if (Markup.isTrustedImageUrl(imageUrl)) {
+        imageUrl = Markup.sanitizeAndEncode(imageUrl);
+        builder.append("<img src=\"").append(imageUrl).append("\"/>");
+      }
+      break;
+    case GADGET:
+      gadgetRenderer.render((Gadget) element, contributors, builder);
+      break;
+    case INLINE_BLIP:
+      waveRenderer.renderInlineReply(element, index, builder);
+
+      break;
+    default:
+      // Ignore all others.
+    }
+  }
+
+  /**
+   * Takes content and applies style and formatting to it based on its
+   * annotations and elements.
+   * 
+   */
+  public String renderHtml(final String content, final Annotations annotations,
+      final SortedMap<Integer, Element> elements, final List<String> contributors) {
+    final StringBuilder builder = new StringBuilder();
+
+    // NOTE(dhanji): This step is enormously important!
+    final char[] raw = content.toCharArray();
+
+    final SortedSet<Marker> markers = new TreeSet<Marker>();
+
+    // First add annotations sorted by range.
+    for (final Annotation annotation : annotations.asList()) {
+      // Ignore anything but style or title annotations.
+      final String annotationName = annotation.getName();
+      if (annotationName.startsWith("style")) {
+        markers.add(Marker.fromAnnotation(annotation, annotation.getRange().getStart(), false));
+        markers.add(Marker.fromAnnotation(annotation, annotation.getRange().getEnd(), true));
+      } else if ("conv/title".equals(annotationName)) {
+        // Find the first newline and make sure the annotation only gets to that
+        // point.
+        final int start = annotation.getRange().getStart();
+        final int from = raw[0] == '\n' ? 1 : 0;
+        final int end = content.indexOf('\n', from);
+        if (end > start && start < end) {
+          // Commented (vjrj)
+          // final Annotation title = new Annotation(Annotation.FONT_WEIGHT,
+          // "bold", start, end);
+          // markers.add(Marker.fromAnnotation(title, start, false));
+          // markers.add(Marker.fromAnnotation(title, end, true));
+        }
+      }
+    }
+
+    // Now add elements sorted by index.
+    for (final Map.Entry<Integer, Element> entry : elements.entrySet()) {
+      markers.add(Marker.fromElement(entry.getValue(), entry.getKey()));
+    }
+
+    builder.append("<p>");
+    int cursor = 0;
+    for (final Marker marker : markers) {
+      if (marker.index > cursor) {
+        final int to = Math.min(raw.length, marker.index);
+        builder.append(Markup.sanitize(new String(raw, cursor, to - cursor)));
+      }
+
+      cursor = marker.index;
+
+      if (marker.isElement()) {
+        renderElement(marker.element, marker.index, contributors, builder);
+      } else {
+        emitStyleAnnotation(marker, builder);
+      }
+    }
+
+    // add any tail bits
+    if (cursor < raw.length - 1) {
+      builder.append(Markup.sanitize(new String(raw, cursor, raw.length - cursor)));
+    }
+
+    // Replace empty paragraphs. (TODO expensive and silly)
+    return builder.toString().replace("<p>\n</p>", "<p><br/></p>");
+  }
+}


Property changes on: trunk/src/main/java/com/google/wave/splash/text/ContentRenderer.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/java/com/google/wave/splash/text/ContentUnrenderer.java
===================================================================
--- trunk/src/main/java/com/google/wave/splash/text/ContentUnrenderer.java	                        (rev 0)
+++ trunk/src/main/java/com/google/wave/splash/text/ContentUnrenderer.java	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,90 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.google.wave.splash.text;
+
+
+import com.google.common.collect.Maps;
+import com.google.wave.api.Annotations;
+import com.google.wave.api.Line;
+
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.nodes.Node;
+import org.jsoup.nodes.TextNode;
+
+import java.util.Map;
+import java.util.logging.Logger;
+
+/**
+ * @author anthonybaxter at gmail.com (Anthony Baxter)
+ */
+public class ContentUnrenderer {
+
+  private static final Logger LOG = Logger.getLogger(ContentUnrenderer.class.getName());
+
+  /**
+   * Turns a HTML document back into a set of text, elements, annotations.
+   */
+  public static UnrenderedBlip unrender(String content) {
+    StringBuilder sb = new StringBuilder();
+    Map<Integer, com.google.wave.api.Element> elements = Maps.newHashMap();
+    Annotations annotations = new Annotations();
+    Document doc = Jsoup.parse(content);
+    unrender(doc.body(), sb, elements, annotations);
+    return new UnrenderedBlip(sb.toString(), elements, annotations);
+  }
+
+  /**
+   * Helper method to recursively parse a HTML element and construct a wave document.
+   */
+  private static void unrender(Node parent, StringBuilder output, Map<Integer,
+      com.google.wave.api.Element> elements, Annotations annotations) {
+    for (Node node : parent.childNodes()) {
+      if (node instanceof TextNode) {
+        output.append(((TextNode)node).text());
+      }
+      else if (node instanceof Element) {
+        int position = output.length();
+        Element element = (Element)node;
+        if ("p".equals(element.tag().getName())) {
+          elements.put(position, new Line());
+          // handle any attributes?
+        }
+        // Additional HTML element tags here.
+        unrender(element, output, elements, annotations);
+      }
+    }
+
+  }
+
+  /**
+   * Container for the output of the unrender method.
+   */
+  public static class UnrenderedBlip {
+    public String contents;
+    Map<Integer, com.google.wave.api.Element> elements;
+    Annotations annotations = new Annotations();
+
+    UnrenderedBlip(String contents, Map<Integer, com.google.wave.api.Element> elements,
+        Annotations annotations) {
+      this.contents = contents;
+      this.elements = elements;
+      this.annotations = annotations;
+    }
+  }
+}


Property changes on: trunk/src/main/java/com/google/wave/splash/text/ContentUnrenderer.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/java/com/google/wave/splash/text/GadgetRenderer.java
===================================================================
--- trunk/src/main/java/com/google/wave/splash/text/GadgetRenderer.java	                        (rev 0)
+++ trunk/src/main/java/com/google/wave/splash/text/GadgetRenderer.java	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,103 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.google.wave.splash.text;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.wave.api.Gadget;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.servlet.http.HttpServletRequest;
+
+
+/**
+ * Render gadget iframes from Elements.
+ *
+ * @author David Byttow
+ */
+public class GadgetRenderer {
+  private static final Set<String> NON_STATE_PROPERTIES = ImmutableSet.of("author", "url");
+  private final Provider<HttpServletRequest> requestProvider;
+  private final AtomicInteger nextId = new AtomicInteger(0);
+
+  @Inject
+  public GadgetRenderer(Provider<HttpServletRequest> requestProvider) {
+    this.requestProvider = requestProvider;
+  }
+
+  void render(Gadget gadget, List<String> contributors, StringBuilder builder) {
+    String id = "g" + nextId.incrementAndGet();
+    String parentUrl = requestProvider.get().getRequestURL().toString();
+
+    appendState(gadget, id, contributors, builder);
+    builder.append("<iframe class=\"gadget\" "
+        + "id=\"").append(id).append("\" "
+        + "name=\"").append(id).append("\" "
+        + "width=\"100%\" height=\"1px\" ")
+        .append("frameBorder=\"no\" scrolling=\"no\" src=\""
+            + "http://www.gmodules.com/gadgets/ifr?container=wave&view=default&debug=0&"
+            + "lang=en&country=ALL&nocache=0&wave=1")
+        .append("&mid=").append(id)
+        .append("&parent=").append(Markup.sanitizeAndEncode(parentUrl))
+        .append("&url=").append(Markup.sanitizeAndEncode(gadget.getUrl()))
+        .append("\"/>");
+  }
+
+  private void appendState(Gadget gadget, String id, List<String> contributors,
+      StringBuilder builder) {
+    String output = "";
+    builder.append("<div class=\"invisible\" id=\"")
+        .append(id)
+        .append("_state\">");
+    for (Map.Entry<String, String> entry : gadget.getProperties().entrySet()) {
+      if (NON_STATE_PROPERTIES.contains(entry.getKey())) {
+        continue;
+      }
+      renderStateValue("gadget-state", entry.getKey(), entry.getValue(), builder);
+    }
+
+    for (String participantId : contributors) {
+      renderStateValue("gadget-participant", null, participantId, builder);
+    }
+    renderStateValue("gadget-author", null, gadget.getProperties().get("author"), builder);
+    builder.append("</div>");
+  }
+
+  private void renderStateValue(String className, String key, String value,
+      StringBuilder builder) {
+    // TODO: Is this kosher? Should we encode this data in
+    // another way?
+    builder.append("<span class=\"")
+        .append(className)
+        .append("\"");
+    if (key != null) {
+      builder.append(" hiddenKey=\"")
+          .append(Markup.sanitize(key))
+          .append('"');
+    }
+    builder.append(">");
+    if (value != null) {
+      builder.append(Markup.sanitize(value));
+    }
+    builder.append("</span>");
+  }
+}


Property changes on: trunk/src/main/java/com/google/wave/splash/text/GadgetRenderer.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/java/com/google/wave/splash/text/Markup.java
===================================================================
--- trunk/src/main/java/com/google/wave/splash/text/Markup.java	                        (rev 0)
+++ trunk/src/main/java/com/google/wave/splash/text/Markup.java	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,262 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.google.wave.splash.text;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import cc.kune.core.client.errors.DefaultException;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+/**
+ * A utility class that converts raw wave documents into html.
+ * 
+ * @author dhanji at gmail.com (Dhanji R. Prasanna)
+ */
+ at Singleton
+public class Markup {
+  private static final DateFormat MONTH_DAY_FORMATTER = new SimpleDateFormat("MMM dd");
+  private static final DateFormat MONTH_DAY_YEAR_FORMATTER = new SimpleDateFormat("MMM dd, yyyy");
+  private static final DateFormat TIME_FORMATTER = new SimpleDateFormat("h:mm a");
+  private static final DateFormat TIME_MILLIS_FORMATTER = new SimpleDateFormat("s.SSS");
+
+  public static String embedSnippet(final String waveId) {
+    // TODO(dhanji): Move to template
+    return "&lt;script type=\"text/javascript\"&gt;" + "    function load() {"
+        + "      var targetDiv = document.getElementById('waveframe');"
+        + "      var wavePanel = new google.wave.WavePanel({"
+        + "        rootUrl: \"http://localhost:8080/\"," + "        target: targetDiv,"
+        + "        lite: true" + "      }).loadWave(\"" + waveId + "\");" + "    }"
+        + "  &lt;/script&gt;";
+  }
+
+  private static String extractScheme(final String uri) {
+    if (null == uri) {
+      return null;
+    }
+    final int colonPos = uri.indexOf(':');
+    if (colonPos < 0) {
+      return null;
+    }
+    final String scheme = uri.substring(0, colonPos);
+    if (scheme.indexOf('/') >= 0 || scheme.indexOf('#') >= 0) {
+      // The URI's prefix up to the first ':' contains other URI special
+      // chars, and won't be interpreted as a scheme.
+      return null;
+    }
+    return scheme;
+  }
+
+  /**
+   * Formats a given timestamp into a friendly date string. The output will look
+   * differently depending on the day and year. If the time given is the same
+   * day as "now", then it will only display the time (12:30 PM). If it's in the
+   * same year, then it will display the month and day (Jun 01) otherwise it
+   * will return the month, day and year (Jun 01, 2009).
+   * 
+   * @param timestamp
+   * @return the formatted date time string.
+   */
+  public static String formatDateTime(final long timestamp) {
+    final Date date = new Date(timestamp);
+    final Date now = new Date();
+    if (now.getDay() == date.getDay()) {
+      return TIME_FORMATTER.format(date);
+    } else if (now.getYear() == date.getYear()) {
+      return MONTH_DAY_FORMATTER.format(date);
+    } else {
+      return MONTH_DAY_YEAR_FORMATTER.format(date);
+    }
+  }
+
+  public static String formatMillis(final long millis) {
+    return TIME_MILLIS_FORMATTER.format(new Date(millis)) + "s";
+  }
+
+  // TODO(dhanji): Should we allow more schemes? Like im:
+  private static boolean isSafeUri(final String uri) {
+    final String scheme = extractScheme(uri);
+    return (scheme == null || "http".equalsIgnoreCase(scheme) || "https".equalsIgnoreCase(scheme)
+        || "mailto".equalsIgnoreCase(scheme) || "ftp".equalsIgnoreCase(scheme));
+  }
+
+  /**
+   * Checks if an image URL is safe (i.e. hosted on Google)
+   * 
+   * @param imageUrl
+   *          A string URL
+   * @return True if this image URL is safe to use in a google-hosted page.
+   */
+  public static boolean isTrustedImageUrl(final String imageUrl) {
+    final String scheme = extractScheme(imageUrl);
+
+    // NOTE(dhanji): the trailing slash is extremely important.
+    return (scheme != null)
+        && (imageUrl.startsWith(scheme + "://www.google.com/") || imageUrl.startsWith(scheme
+            + "://google.com/"));
+  }
+
+  /**
+   * Sanitizes untrusted text so that it does not emit HTML markup. This utility
+   * is based on a similar one in GWT's SafeHtml.java. It eliminates all
+   * predefined entities in HTML/XHTML, replacing them with escape codes:
+   * http://
+   * en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
+   * 
+   * @param text
+   *          The untrusted text to sanitize
+   * @return Escaped text that can safely be rendered in a web page.
+   */
+  public static String sanitize(final String text) {
+    final StringBuilder out = new StringBuilder(text.length());
+
+    final char[] chars = text.toCharArray();
+    for (final char c : chars) {
+      switch (c) {
+      case '&':
+        out.append("&amp;");
+        break;
+      case '\'':
+        out.append("&#39;");
+        break;
+      case '"':
+        out.append("&quot;");
+        break;
+      case '<':
+        out.append("&lt;");
+        break;
+      case '>':
+        out.append("&gt;");
+        break;
+      default:
+        // allow all other characters.
+        out.append(c);
+      }
+    }
+
+    return out.toString();
+  }
+
+  /**
+   * First sanitizes the given URI and then encodes it using the UTF-8 character
+   * set.
+   * 
+   * @param uri
+   *          An untrusted URI string
+   * @return Sanitized, URL-encoded URI for embedding in HTML
+   */
+  static String sanitizeAndEncode(final String uri) {
+    try {
+      return URLEncoder.encode(sanitizeUri(uri), "UTF-8");
+    } catch (final UnsupportedEncodingException e) {
+      throw new DefaultException(e);
+    }
+  }
+
+  /**
+   * Checks if the scheme is one of four simple types (see #isSafeUri), if not
+   * disallows the URI by reducing it to '#'
+   * 
+   * @param uri
+   *          An untrusted URI string to sanitize
+   * @return Returns a safe URI.
+   */
+  private static String sanitizeUri(final String uri) {
+    return isSafeUri(uri) ? uri : "#";
+  }
+
+  public static String toBlipId(final String id) {
+    // HACK to make blip ids work as DOM ids
+    return id.replace('-', '+');
+  }
+
+  //
+  // public static ClientAction measure(String action, long searchTime) {
+  // return new ClientAction("measure")
+  // .html(action + " completed in " + Markup.formatMillis(searchTime));
+  // }
+
+  /**
+   * Simply converts a lowerCamelCased symbol into a dashed one:
+   * 
+   * <pre>
+   *   fontWeight -> font-weight
+   * </pre>
+   * 
+   * TODO: perhaps we should intern all these strings to save memory and remove
+   * the overhead of string allocation, they could also be perfectly hashed.
+   */
+  static String toDashedStyle(final String name) {
+    final char[] nameChars = name.toCharArray();
+
+    // Pre allocate buffer, +1 for '-' (2-dashes are uncommon)
+    final StringBuilder builder = new StringBuilder(nameChars.length + 1);
+    for (final char nameChar : nameChars) {
+      if (Character.isUpperCase(nameChar)) {
+        builder.append('-');
+        builder.append(Character.toLowerCase(nameChar));
+        continue;
+      }
+
+      builder.append(nameChar);
+    }
+
+    return builder.toString();
+  }
+
+  public static String toDomId(final String id) {
+    // HACK to make blip ids work as DOM ids
+    return id.replace('+', '-');
+  }
+
+  @Inject
+  Markup() {
+  }
+
+  /**
+   * @return the participant's display name.
+   */
+  // TODO: This doesn't belong here.
+  public String getDisplayName(final String participantId) {
+    return "FIXME";
+  }
+
+  public String getImageSize() {
+    return "33px";
+  }
+
+  /**
+   * @return the participant's image url.
+   */
+  // TODO: This doesn't belong here.
+  public String getImageUrl(final String participantId) {
+    // FIXME
+    return "others/unknown.jpg";
+  }
+
+  /**
+   * Helpful utility for templates.
+   */
+  public String sanitizeHtml(final String text) {
+    return Markup.sanitize(text);
+  }
+}


Property changes on: trunk/src/main/java/com/google/wave/splash/text/Markup.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/java/com/google/wave/splash/web/template/Templates.java
===================================================================
--- trunk/src/main/java/com/google/wave/splash/web/template/Templates.java	                        (rev 0)
+++ trunk/src/main/java/com/google/wave/splash/web/template/Templates.java	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,138 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.google.wave.splash.web.template;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+import java.util.logging.Logger;
+
+import javax.annotation.Nullable;
+
+import org.mvel2.templates.CompiledTemplate;
+import org.mvel2.templates.TemplateCompiler;
+import org.mvel2.templates.TemplateRuntime;
+import org.mvel2.templates.util.TemplateTools;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.MapMaker;
+import com.google.common.collect.Maps;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.google.wave.splash.text.Markup;
+
+/**
+ * Handles all our html templates, loading, parsing and processing them.
+ * 
+ * @author dhanji at gmail.com (Dhanji R. Prasanna)
+ */
+ at Singleton
+public class Templates {
+  // Template file names go here.
+  public static final String BLIP_TEMPLATE = "blip.html.fragment";
+  public static final String CLIENT_TEMPLATE = "full_client.html";
+  public static final String FEED_TEMPLATE = "feed.html.fragment";
+  public static final String HEADER_TEMPLATE = "header.html.fragment";
+  private static final Logger LOG = Logger.getLogger(Templates.class.getName());
+  public static final String MOBILE_TEMPLATE = "mobile_client.html";
+  public static final String PERMALINK_WAVE_TEMPLATE = "permalink_client.html";
+
+  public static final String WAVE_NOT_FOUND_TEMPLATE = "wave_not_found.html.fragment";
+
+  private final Markup markup;
+
+  private final boolean productionMode = false;
+
+  /**
+   * file name of template -> compiled template lazy cache.
+   */
+  private final ConcurrentMap<String, CompiledTemplate> templates = new MapMaker().makeComputingMap(new Function<String, CompiledTemplate>() {
+    @Override
+    public CompiledTemplate apply(@Nullable final String template) {
+      return loadTemplate(template);
+    }
+  });
+
+  @Inject
+  public Templates(final Markup markup) {
+    this.markup = markup;
+  }
+
+  private CompiledTemplate loadTemplate(final String template) {
+    // Load from jar if in production mode, otherwise servlet root.
+    final InputStream input = openResource(template);
+    Preconditions.checkArgument(input != null, "Could not find template named: " + template);
+
+    try {
+      return TemplateCompiler.compileTemplate(TemplateTools.readStream(input));
+    } finally {
+      try {
+        input.close();
+      } catch (final IOException e) {
+        // Can't do much.
+        e.printStackTrace();
+        LOG.warning(e.toString());
+      }
+    }
+  }
+
+  /**
+   * Opens a packaged resource from the file system.
+   * 
+   * @param file
+   *          The name of the file/resource to open.
+   * @return An {@linkplain InputStream} to the named file, if found
+   */
+  public InputStream openResource(final String file) {
+    // final InputStream stream = productionMode ?
+    // Templates.class.getResourceAsStream(file)
+    // : servletContext.get().getResourceAsStream("/" + file);
+
+    FileInputStream stream = null;
+    try {
+      stream = new FileInputStream(new File("src/main/webapp/others/splash/" + file));
+    } catch (final FileNotFoundException e) {
+      // TODO Auto-generated catch block
+      LOG.info("Could not find resource named: " + file);
+    }
+    return stream;
+  }
+
+  /**
+   * Loads templates if necessary.
+   * 
+   * @param template
+   *          Name of the template file. example: "blip.html.fragment"
+   * @param context
+   *          an object to process against
+   * @return the processed, filled-in template.
+   */
+  public String process(final String template, final Object context) {
+    // Reload template each time for development mode.
+    final CompiledTemplate compiledTemplate = productionMode ? templates.get(template)
+        : loadTemplate(template);
+
+    final Map<String, Object> vars = Maps.newHashMap();
+    vars.put("markup", markup);
+    return TemplateRuntime.execute(compiledTemplate, context, vars).toString();
+  }
+}


Property changes on: trunk/src/main/java/com/google/wave/splash/web/template/Templates.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/java/com/google/wave/splash/web/template/ThreadedWaveRenderer.java
===================================================================
--- trunk/src/main/java/com/google/wave/splash/web/template/ThreadedWaveRenderer.java	                        (rev 0)
+++ trunk/src/main/java/com/google/wave/splash/web/template/ThreadedWaveRenderer.java	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,434 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.google.wave.splash.web.template;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.waveprotocol.box.server.CoreSettings;
+
+import cc.kune.common.client.utils.Url;
+import cc.kune.common.client.utils.UrlParam;
+import cc.kune.core.client.services.FileConstants;
+import cc.kune.core.client.services.FileDownloadUtils;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+import com.google.wave.api.Blip;
+import com.google.wave.api.BlipThread;
+import com.google.wave.api.Element;
+import com.google.wave.api.ParticipantProfile;
+import com.google.wave.api.Wavelet;
+import com.google.wave.splash.rpc.ClientAction;
+import com.google.wave.splash.text.ContentRenderer;
+import com.google.wave.splash.text.Markup;
+
+/**
+ * Does the actual conversion of a wavelet/blipdata tree into html, using the
+ * conversation-thread model, optionally falling back to the blip-hierarchy
+ * model, if so configured.
+ * 
+ * @author dhanji at gmail.com (Dhanji R. Prasanna)
+ */
+ at Singleton
+class ThreadedWaveRenderer implements WaveRenderer {
+  private class PageTracker {
+    private int counter;
+    // Whether or not we're trying to deliver the first page.
+    private final boolean firstPage;
+    private final List<Integer> markers = Lists.newArrayList();
+
+    /**
+     * This is an alternate output string which will wrap all html content that
+     * is not immediately displayed. This is useful for inline replies that need
+     * to be moved in and out of the appropriate part of the DOM.
+     */
+    private final StringBuilder purgatory = new StringBuilder();
+
+    // The wavelet we're trying to render in this page.
+    private final Wavelet wavelet;
+
+    public PageTracker(final int page, final Wavelet wavelet) {
+      this.wavelet = wavelet;
+      firstPage = (page == 0);
+
+      // Start purgatory (will be ended by #render)
+      purgatory.append("<div id=\"purgatory\">");
+    }
+
+    public boolean hasPages() {
+      return !markers.isEmpty();
+    }
+
+    public int marker(final int page) {
+      return markers.get(page);
+    }
+
+    public String purgatoryElement() {
+      return purgatory.append("</div>").toString();
+    }
+
+    /**
+     * Returns true if a page boundary was crossed.
+     */
+    public boolean track(final StringBuilder builder) {
+      final int length = builder.length();
+      if (length - counter >= charsPerPage) {
+        markers.add(length);
+        counter = length;
+
+        // If this is the first page, short circuit the rendering
+        // process so we can deliver the page faster.
+        if (firstPage) {
+          return true;
+        }
+      }
+      return false;
+    }
+  }
+
+  private static final Set<String> HIDDEN_PARTICIPANTS = ImmutableSet.of("public");
+
+  // TODO(dhanji): This is expensive, see if we can precompute branch size
+  // when constructing the thread tree.
+  private static int sizeOfThreadTree(final BlipThread inlineReplyThread) {
+    final List<Blip> blips = inlineReplyThread.getBlips();
+    int size = blips.size();
+
+    for (final Blip blip : blips) {
+      for (final BlipThread thread : blip.getReplyThreads()) {
+        size += thread.getBlipIds().size();
+      }
+    }
+
+    return size;
+  }
+  private final int charsPerPage;
+  // Ugly, but we do this to avoid polluting all the rendering methods. =(
+  private final ThreadLocal<PageTracker> currentPage = new ThreadLocal<PageTracker>();
+  private final String domain;
+
+  private final boolean isReadOnly;
+
+  private final ContentRenderer renderer;
+  private final Templates templates;
+
+  @Inject
+  public ThreadedWaveRenderer(final Templates templates, final ContentRenderer renderer,
+      @Named(CoreSettings.WAVE_SERVER_DOMAIN) final String domain) {
+    this.templates = templates;
+    this.domain = domain;
+    // vjrj: manual setted
+    this.isReadOnly = true;
+    this.charsPerPage = 100000;
+    this.renderer = renderer;
+  }
+
+  private String getAvatarUrl(final String address) {
+    String avatar = "";
+    if (address.contains(domain)) {
+      avatar = new Url("/ws/" + FileDownloadUtils.AVATARDOWNLOADSERVLET, new UrlParam(
+          FileConstants.USERNAME, address.split("@")[0])).toString();
+    } else {
+      avatar = "/others/unknown.jpg";
+    }
+    return avatar;
+  }
+
+  private Map<String, ParticipantProfile> getProfiles(final Collection<String> participants) {
+    final HashMap<String, ParticipantProfile> profiles = new HashMap<String, ParticipantProfile>();
+    for (final String address : participants) {
+      final ParticipantProfile profile = new ParticipantProfile(address, address.split("@")[0],
+          getAvatarUrl(address), "");
+      profiles.put(address, profile);
+    }
+
+    return profiles;
+  }
+
+  List<ParticipantProfile> loadProfiles(final Collection<String> participants) {
+    final ImmutableList.Builder<ParticipantProfile> result = ImmutableList.builder();
+    final Map<String, ParticipantProfile> profiles = getProfiles(participants);
+    for (final String address : participants) {
+      result.add(profiles.get(address));
+    }
+    return result.build();
+  }
+
+  /**
+   * 
+   * @param wavelet
+   *          A wavelet to render as a single html blob.
+   * @param page
+   *          The page number to send back. Use this to implement paging, if you
+   *          specify page 1, the client action will only contain the second
+   *          page as computed during the current render.
+   * @return the client action.
+   */
+  @Override
+  public ClientAction render(final Wavelet wavelet, final int page) {
+    Preconditions.checkState(null == currentPage.get(),
+        "A page render is already in progress (this is an algorithm bug)");
+    final StringBuilder builder = new StringBuilder();
+    final Blip rootBlip = wavelet.getRootBlip();
+
+    // The pagetracker tracks every page worth of HTML rendered.
+    final PageTracker pageTracker = new PageTracker(page, wavelet);
+    currentPage.set(pageTracker);
+    try {
+      return renderInternal(wavelet, page, builder, rootBlip, pageTracker);
+    } finally {
+      currentPage.remove();
+    }
+  }
+
+  private boolean renderBlip(final Blip blip, final StringBuilder builder, final String title,
+      final PageTracker pageTracker) {
+    builder.append("<div class='blip' id='");
+    builder.append(Markup.toDomId(blip.getBlipId()));
+    builder.append("'>");
+    builder.append(toHtml(blip, title));
+    builder.append("</div>");
+
+    // At the end of each blip, see if we've passed a page worth of content.
+    return pageTracker.track(builder);
+  }
+
+  String renderBlipTemplate(final Map<String, Object> blip) {
+    return templates.process(Templates.BLIP_TEMPLATE, blip);
+  }
+
+  private String renderContent(final Blip blip) {
+    return renderer.renderHtml(blip.getContent(), blip.getAnnotations(), blip.getElements(),
+        blip.getContributors());
+  }
+
+  /**
+   * Renders the header of a wavelet, including participants.
+   * 
+   * @param profiles
+   *          A list of profiles for each participant in the wave, in correct
+   *          order.
+   * @return A {@code ClientAction} that inserts the rendered participant list
+   *         in the header portion of the DOM.
+   */
+  @Override
+  public ClientAction renderHeader(final List<ParticipantProfile> profiles) {
+    final Map<String, Object> context = Maps.newHashMap();
+    final int max = Math.min(10, profiles.size());
+
+    final List<ParticipantProfile> renderedParticipants = Lists.newArrayListWithExpectedSize(max);
+    for (final ParticipantProfile p : profiles) {
+      // TODO: For some reason the address is an empty string, so
+      // we use name here instead.
+      if (HIDDEN_PARTICIPANTS.contains(p.getName())) {
+        continue;
+      }
+      if (renderedParticipants.size() >= max) {
+        break;
+      }
+      renderedParticipants.add(p);
+    }
+
+    context.put("participants", renderedParticipants);
+    return new ClientAction("update-header").html(templates.process(Templates.HEADER_TEMPLATE, context));
+  }
+
+  /**
+   * Renders an inline reply thread at the correct offset location inside a
+   * blip.
+   * 
+   * @param element
+   *          The element representing the position of the offset inline reply
+   * @param index
+   * @param builder
+   *          The current HTML content StringBuilder of the wave so far
+   */
+  @Override
+  public void renderInlineReply(final Element element, final int index, final StringBuilder builder) {
+
+    final PageTracker pageTracker = currentPage.get();
+    final BlipThread inlineReplyThread = pageTracker.wavelet.getThread(element.getProperty("id"));
+
+    // inlineReplyThread can be null if a sub-thread was completely deleted.
+    // There's still
+    // an entry left behind in the conversation that points to nothing.
+    if (inlineReplyThread != null && !inlineReplyThread.getBlipIds().isEmpty()) {
+      builder.append(" <span class=\"inline-reply\" ir-id=\"");
+      builder.append(Markup.toDomId(inlineReplyThread.getId()));
+      builder.append("\"><span class=\"count\" title=\"Click to expand inline replies\"><span class=\"count-inner\">");
+      builder.append(sizeOfThreadTree(inlineReplyThread));
+      builder.append("</span><span class=\"pointer\"></span></span> ");
+
+      // Render this thread into purgatory, it will be transferred to the
+      // appropriate
+      // spot by the JS code. This is needed to prevent the browser from trying
+      // to pre-emptively "correct" our dom structure (and thus ruin it).
+      pageTracker.purgatory.append("<div class=\"inline-reply-content\" id=\"ir-");
+      pageTracker.purgatory.append(Markup.toDomId(inlineReplyThread.getId()));
+      pageTracker.purgatory.append("\"><div class=\"inline-reply-content-inner\">");
+      renderThreads(inlineReplyThread, pageTracker.purgatory, pageTracker);
+      pageTracker.purgatory.append("</div></div>");
+
+      builder.append("</span>"); // Close inline-reply
+    }
+  }
+
+  private ClientAction renderInternal(final Wavelet wavelet, final int page,
+      final StringBuilder builder, final Blip rootBlip, final PageTracker pageTracker) {
+    final boolean stopRender = renderThreads(wavelet.getRootThread(), builder, pageTracker);
+    String html;
+    if (page != ALL_PAGES && (stopRender || pageTracker.hasPages())) {
+      if (page == 0) {
+        builder.append("<img id=\"wave-loading\" src=\"images/wave-loading.gif\">");
+        html = builder.toString();
+      } else {
+        // If this is a request for the rest of the wave, start from end of page
+        // 0 and get
+        // the rest.
+        final int start = pageTracker.marker(0);
+
+        // Append purgatory--which contains all inline reply threads
+        builder.append(pageTracker.purgatoryElement());
+
+        html = builder.substring(start);
+      }
+    } else {
+      // Append purgatory--which contains all inline reply threads
+      builder.append(pageTracker.purgatoryElement());
+
+      html = builder.toString();
+    }
+
+    return new ClientAction("update-wave").version(wavelet.getLastModifiedTime()).html(html);
+  }
+
+  @Override
+  public ClientAction renderNotFound() {
+    // TODO: This should be an alert message once that system is
+    // implemented.
+    return new ClientAction("update-wave").html(templates.process(Templates.WAVE_NOT_FOUND_TEMPLATE,
+        ImmutableMap.of()));
+  }
+
+  /**
+   * This method renders the blip thread hierarchy using the new conversation
+   * structure.
+   * 
+   * @return true if we should stop rendering because a page boundary was
+   *         reached.
+   */
+  boolean renderThreads(final BlipThread thread, final StringBuilder builder,
+      final PageTracker pageTracker) {
+    builder.append("<div class=\"thread\" id=\"");
+    builder.append(Markup.toDomId(thread.getId()));
+    builder.append("\">");
+    final List<Blip> blipsInThread = thread.getBlips();
+
+    for (final Blip blip : blipsInThread) {
+      if (renderBlip(blip, builder, "", pageTracker)) {
+        return true;
+      }
+
+      // If this blip has any reply threads, they should be rendered indented.
+      if (blip.getReplyThreads().size() > 0) {
+        builder.append("<div class=\"indent\">");
+
+        for (final BlipThread childThread : blip.getReplyThreads()) {
+          if (renderThreads(childThread, builder, pageTracker)) {
+            return true;
+          }
+        }
+
+        builder.append("</div>");
+      }
+    }
+    builder.append("</div>");
+    return false;
+  }
+
+  /**
+   * Renders the content of a blip as html. If a title is specified, renders
+   * that specially as the root blip.
+   * 
+   * @param blipData
+   *          The blip whose content you want to render
+   * @param title
+   *          The title string if this is a root blip or null
+   * @return Rendered HTML string with markup
+   */
+  @Override
+  public String toHtml(final Blip blipData, final String title) {
+    final List<String> contributors = blipData.getContributors();
+    final List<ParticipantProfile> authors = loadProfiles(contributors);
+
+    final Map<String, Object> blip = Maps.newHashMap();
+    blip.put("id", Markup.toDomId(blipData.getBlipId()));
+
+    final StringBuilder authorString = new StringBuilder();
+    final int numberOfAuthors = authors.size();
+    final int len = Math.min(3, numberOfAuthors);
+    for (int i = 0; i < len; i++) {
+      authorString.append("<div class='authorbar ");
+      if (i == 0) {
+        authorString.append("first");
+      }
+      authorString.append("'><div class=\"avatar\"><img src=\"");
+      final ParticipantProfile author = authors.get(i);
+      authorString.append(author.getImageUrl());
+      authorString.append("\" alt=\"");
+
+      final String name = author.getName();
+      authorString.append(name);
+      authorString.append("\"><span class=\"name\" title=\"");
+      authorString.append(name);
+      authorString.append("\">");
+      authorString.append(name);
+      authorString.append("</span></div></div>");
+    }
+
+    if (numberOfAuthors > 3) {
+      authorString.append("<div class=\"authorbar\">");
+      authorString.append("<div class=\"author-more\">+");
+      authorString.append(numberOfAuthors);
+      authorString.append(" others</div>");
+      authorString.append("</div>");
+
+      blip.put("authorCountClass", "author-count-many");
+    } else {
+      blip.put("authorCountClass", "author-count-" + contributors.size());
+    }
+
+    blip.put("authorString", authorString.toString());
+    blip.put("time", Markup.formatDateTime(blipData.getLastModifiedTime()));
+    blip.put("title", Markup.sanitize(title));
+    blip.put("content", renderContent(blipData));
+    blip.put("readonly", isReadOnly);
+
+    return renderBlipTemplate(blip);
+  }
+}


Property changes on: trunk/src/main/java/com/google/wave/splash/web/template/ThreadedWaveRenderer.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/java/com/google/wave/splash/web/template/WaveRenderer.java
===================================================================
--- trunk/src/main/java/com/google/wave/splash/web/template/WaveRenderer.java	                        (rev 0)
+++ trunk/src/main/java/com/google/wave/splash/web/template/WaveRenderer.java	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,78 @@
+/**
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.google.wave.splash.web.template;
+
+import com.google.inject.ImplementedBy;
+import com.google.wave.splash.rpc.ClientAction;
+import com.google.wave.api.Blip;
+import com.google.wave.api.Element;
+import com.google.wave.api.ParticipantProfile;
+import com.google.wave.api.Wavelet;
+
+import java.util.List;
+
+/**
+ * Does the actual conversion of a wavelet/blipdata tree into html. This
+ * interface is mainly to satisfy a circular dependency with ContentRenderer.
+ *
+ * @author dhanji at gmail.com (Dhanji R. Prasanna)
+ */
+ at ImplementedBy(ThreadedWaveRenderer.class) // We only have one impl.
+public interface WaveRenderer {
+  /**
+   * Page number sentinel value indicating that all pages are expected.
+   */
+  int ALL_PAGES = -1;
+
+  /**
+   * Renders an inline reply thread at the correct offset location inside a blip.
+   * @param element The element representing the position of the offset inline reply
+   * @param index The offset into the blip's text at which this element occurs
+   * @param builder The current HTML content StringBuilder of the wave so far
+   */
+  void renderInlineReply(Element element, int index, StringBuilder builder);
+
+  /**
+   *
+   * @param wavelet A wavelet to render as a single html blob.
+   * @param page The page number to send back. Use this to implement paging,
+   *     if you specify page 1, the client action will only contain the second
+   *     page as computed during the current render.
+   * @return the client action.
+   */
+  ClientAction render(Wavelet wavelet, int page);
+
+  /**
+   * Renders the header of a wavelet, including participants.
+   * @param profiles A list of profiles for each participant in the wave, in correct order.
+   * @return A {@code ClientAction} that inserts the rendered participant list in the header
+   *   portion of the DOM.
+   */
+  ClientAction renderHeader(List<ParticipantProfile> profiles);
+
+  /**
+   * Renders the content of a blip as html. If a title is specified, renders
+   * that specially as the root blip.
+   *
+   * @param blipData The blip whose content you want to render
+   * @param title    The title string if this is a root blip or null
+   * @return Rendered HTML string with markup
+   */
+  String toHtml(Blip blipData, String title);
+
+  ClientAction renderNotFound();
+}


Property changes on: trunk/src/main/java/com/google/wave/splash/web/template/WaveRenderer.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/blip.html.fragment
===================================================================
--- trunk/src/main/webapp/others/splash/blip.html.fragment	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/blip.html.fragment	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,16 @@
+<div class="left @{authorCountClass}">
+  @{authorString}
+  @if{!readonly}
+  <div class="toolbar">
+    <img src="images/cross.png" alt="delete">
+    <img class="edit-button" src="images/pencil.png" alt="edit">
+    <img class="reply-button" src="images/reply.png" alt="reply">
+  </div>
+  @end{}
+</div>
+<div class="right @{authorCountClass}">
+  <div class="right-inner">
+    <div class="time">@{time}</div>
+    <div class="content styleable">@{content}</div>
+  </div>
+</div>

Added: trunk/src/main/webapp/others/splash/feed.html.fragment
===================================================================
--- trunk/src/main/webapp/others/splash/feed.html.fragment	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/feed.html.fragment	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,19 @@
+<div style="display:none">
+ at foreach{item : feed}
+<div class="item @if{item.unreadCount == 0}read at end{}" wave_id="@{item.waveId}">
+  <div class="time">
+    <p>@{markup.formatDateTime(item.lastModified)}</p>
+    <!-- TODO: i18n -->
+    <p class="messages">@{item.blipCount} msgs</p>
+  </div>
+  <div class="avatar">
+    <!-- TODO: Kinda hacky. -->
+    <img width="@{markup.getImageSize()}" height="@{markup.getImageSize()}" src="@{markup.getImageUrl(item.participants[0])}"
+        alt="@{markup.getDisplayName(item.participants[0])}"
+        title="@{markup.getDisplayName(item.participants[0])}"/>
+  </div>
+  <div class="title">@{markup.sanitizeHtml(item.title)}</div>
+  <div class="snippet">@{markup.sanitizeHtml(item.snippet)}</div>
+</div>
+ at end{}
+</div>

Added: trunk/src/main/webapp/others/splash/full_client.html
===================================================================
--- trunk/src/main/webapp/others/splash/full_client.html	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/full_client.html	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,104 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+    "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+  <meta name="viewport" content="width=device-width" /> <!-- for ipad: prevents pinch zoom -->
+  <title>Google Wave Splash</title>
+  <link rel="stylesheet" href="style/stuff.css">
+  <link rel="stylesheet" href="style/main.css">
+  <link rel="stylesheet" type="text/css" href="style/jquery.lightbox-0.5.css" media="screen">
+
+  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
+  <script type="text/javascript" src="http://wave.google.com/gadgets/js/core:rpc.js?debug=1&c=1"></script>
+
+  <!-- [MINIFY] -->
+  <script type="text/javascript" src="js/jquery.lightbox-0.5.min.js"></script>
+  <script type="text/javascript" src="js/jScrollTouch.js"></script>
+  <script type="text/javascript" src="js/editor.js"></script>
+  <script type="text/javascript" src="js/gadget.js"></script>
+  <script type="text/javascript" src="js/rpc.js"></script>
+  <script type="text/javascript" src="js/common_client.js"></script>
+  <script type="text/javascript" src="js/full_client.js"></script>
+  <!-- [END_MINIFY] -->
+  <script type="text/javascript">
+    var BOOTSTRAP = {
+      'email': '@{email}',
+      'displayName': '@{displayName}'
+    };
+  </script>
+  <!--[if IE 6]>
+  <script type="text/javascript" src="js/ie6sucks.js"></script>
+  <![endif]-->
+</head>
+<body>
+
+<div id="header">
+  <div id="headerInner">
+    <table id="headerLayout" cellspacing="0" summary="">
+      <tr>
+        <td id="logo">
+          <h1>
+            <a href="#">Google Wave Splash</a>
+          </h1>
+        </td>
+        @if{enableHeaderButtons}
+        <td class="button">
+          <a href="#"><span>New wave</span></a>
+        </td>
+        <td class="button">
+          <a href="#"><span>Mark all read</span></a>
+        </td>
+        @end{}
+
+        <td class="control-bar">
+          <a href="/speedz">Speedz</a> | <a href="/logout">Sign out</a> 
+          <div id="measure">Search completed in X.XXs</div>
+        </td>
+        <!--
+        TODO(dhanji): This is cool, bring it back in the right place
+        <td class="headerAlert">
+          <div id="alertbar" class="highlight"><div id="alert">You have a happy hippgray app now!</div></div>
+        </td>
+        -->
+      </tr>
+      <tr>
+        <td colspan="5">
+          <div id="alertbar" class="highlight"><div id="alert">You have a happy hippgray app now!</div></div>
+        </td>
+      </tr>      
+    </table>
+  </div>
+  <!-- /#headerInner" -->
+</div>
+<!-- /#header -->
+
+<div id="content">
+  <div id="wave" class="wave-window">
+    <div id="wave-header" class="header" style="display:none"></div>
+    <div id="conversation"></div>
+  </div>
+  <div id="feed-container" class="feed-container">
+
+    <div id="headerSearch">
+      <table id="search" cellspacing="0" summary="">
+        <tr>
+          <td>
+            <input id="searchField" name="searchField" value="Search your waves"/>
+          </td>
+          <td id="searchButton">
+            <span><span>Go</span></span>
+          </td>
+        </tr>
+      </table>
+      <!-- /#search -->
+    </div>
+
+    <div id="feed" class="feed">
+      <img id="feed-loading" src="images/loading.gif" alt="Loading feed contents...">
+      <div id="more-feed" class="more-button">Show More...</div>
+    </div>
+  </div>
+</div>
+
+</body>
+</html>


Property changes on: trunk/src/main/webapp/others/splash/full_client.html
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/header.html.fragment
===================================================================
--- trunk/src/main/webapp/others/splash/header.html.fragment	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/header.html.fragment	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,15 @@
+<table cellspacing="0" cellpadding="0"><tr>
+  <td width="100%">
+    <div class="participants">
+      @foreach{participant : participants}
+      <span class="avatar">
+        <img src="@{participant.imageUrl}" alt="@{participant.name}">
+        <span class="name">@{participant.name}</span>
+      </span>
+      @end{'<span class="punctuation">,</span>'}
+    </div>
+  </td>
+  <td valign="top">
+    <a class="detail" style="display:none" href="#">Show</a>
+  </td>
+</tr></table>

Added: trunk/src/main/webapp/others/splash/images/attachment.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/attachment.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/avatar1.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/avatar1.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/avatar2.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/avatar2.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/avatar3.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/avatar3.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/avatar4.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/avatar4.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/avatar5.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/avatar5.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/avatar6.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/avatar6.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/background_dot.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/background_dot.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/close_window.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/close_window.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/comment.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/comment.png
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/cross.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/cross.png
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/dialog_close.gif
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/dialog_close.gif
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/dialog_pointer.gif
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/dialog_pointer.gif
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/email.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/email.png
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/group.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/group.png
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/inline_reply_arrow.gif
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/inline_reply_arrow.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/inline_reply_arrow_expanded.gif
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/inline_reply_arrow_expanded.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/inline_reply_pointer.gif
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/inline_reply_pointer.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/lightbox-blank.gif
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/lightbox-blank.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/lightbox-btn-close.gif
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/lightbox-btn-close.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/lightbox-btn-next.gif
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/lightbox-btn-next.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/lightbox-btn-prev.gif
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/lightbox-btn-prev.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/lightbox-ico-loading.gif
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/lightbox-ico-loading.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/loading.gif
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/loading.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/loading_permalink.gif
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/loading_permalink.gif
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/logo.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/logo.png
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/logo_on_black.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/logo_on_black.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/logo_small.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/logo_small.png
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/minimize_window.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/minimize_window.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/page_edit.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/page_edit.png
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/pencil.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/pencil.png
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/reply.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/reply.png
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/search_field_on_black.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/search_field_on_black.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/search_field_on_black_button.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/search_field_on_black_button.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/search_field_on_black_button_right.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/search_field_on_black_button_right.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/search_field_on_black_left.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/search_field_on_black_left.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/search_small_button.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/search_small_button.png
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/share_icon.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/share_icon.png
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/user1.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/user1.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/user2.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/user2.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/user3.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/user3.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/user4.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/user4.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/user5.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/user5.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/user6.png
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/user6.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/images/wave-loading.gif
===================================================================
(Binary files differ)


Property changes on: trunk/src/main/webapp/others/splash/images/wave-loading.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/src/main/webapp/others/splash/js/common_client.js
===================================================================
--- trunk/src/main/webapp/others/splash/js/common_client.js	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/js/common_client.js	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,130 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+function log(msg) {
+  if (window.console && window.console.log) {
+    console.log(msg);
+  }
+}
+
+function warn(msg) {
+  if (window.console && window.console.warn) {
+    console.warn(msg);
+  }
+}
+
+function showToolbar(blip) {
+  var toolbar = $('.toolbar', blip);
+  // stop currently running fade
+  toolbar.stop(true, true);
+  toolbar.delay(200).fadeIn('fast'); // delay to prevent spurious hovers
+}
+
+function hideToolbar(blip) {
+  var toolbar = $('.toolbar', blip);
+  toolbar.stop(true, true);
+  toolbar.delay(200).fadeOut('fast');
+}
+
+function expandHeader() {
+  var participantsRef = $('.participants');
+  participantsRef.addClass('expanded');
+  participantsRef.css('height', 'auto');
+  var height = participantsRef.height();
+  participantsRef.css('height', null);
+  participantsRef.animate({height: height});
+  $('.header .detail').text("Hide");
+}
+
+function collapseHeader() {
+  var participantsRef = $('.participants');
+  participantsRef.removeClass('expanded');
+  participantsRef.animate({height: 18});
+  $('.header .detail').text("Show");
+}
+
+function toggleHeader() {
+  if ($('.participants').hasClass('expanded')) {
+    collapseHeader();
+  } else {
+    expandHeader();
+  }
+}
+
+/**
+ * Application entry point.
+ */
+function initCommon() {
+  // Global client state, tells server what we desire each poll.
+  // Add a key to this object to create an open state.
+  // Manages open searches, waves, etc.
+  var waveOptions = {};
+  waveOptions.query = "";
+  waveOptions.startAt = 0;
+  waveOptions.numResults = 10;
+  waveOptions.currentFeedTime = 0;
+  waveOptions.page = 0;
+
+  window.waveOptions_ = waveOptions;
+
+  $('.header .detail').live('click', function() {
+    toggleHeader();
+  });
+
+  // Search box actions.
+  var searchBox = $('#searchField');
+
+  // Execute search.
+  searchBox.keydown(function(event) {
+    if (event.keyCode == 13) { /*Enter hit*/
+      onSearch()
+    }
+  });
+  $('#searchButton').click(onSearch);
+
+  // Page in more feed items.
+  $('#more-feed').live('click', function() {
+    // Advance the page and call rpcSearch again.
+    window.waveOptions_.startAt += window.waveOptions_.numResults;
+
+    wave.Rpc.getInstance().rpcSearch();
+  });
+
+  // Page in more of the wave if applicable.
+  // TODO(dhanji): get rid of this or hide behind flag?
+  $('#more-wave').live('click', function() {
+    // Advance the page and call wave open again.
+    window.waveOptions_.page += 1;
+
+    $(this).remove(); // it gets re-rendered.
+    wave.Rpc.getInstance().rpcOpenWave();
+  });
+
+  // Listen for expansion of collapsed inline replies.
+  // TODO(dhanji): Left factor with same impl in permalink_client.js
+  $('.inline-reply .count').live('click', function() {
+    var replyThreadRef = $('.content', $(this).parent());
+
+    if (replyThreadRef.is(":visible")) {
+      replyThreadRef.slideUp();
+    } else {
+      replyThreadRef.slideDown();
+    }
+  });
+
+  initEditor();
+  initGadgetSystem();
+}


Property changes on: trunk/src/main/webapp/others/splash/js/common_client.js
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/js/editor.js
===================================================================
--- trunk/src/main/webapp/others/splash/js/editor.js	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/js/editor.js	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,78 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+function isEditing() {
+  return $('#editor').length > 0
+}
+
+function startEditMode(obj) {
+  stopEditMode();
+  var blipId = obj.closest('.blip').attr('id');
+  var contentRef = $('#' + blipId + ' .content');
+  contentRef.addClass('editor')
+      .attr('id', 'editor')
+      .attr('contentEditable', 'true')
+      .attr('blip_id', blipId)
+      .focus();
+  hideToolbar($('#' + blipId));
+}
+
+function stopEditMode() {
+  if (!isEditing()) {
+    // Not editing.
+    return;
+  }
+  var editorRef = $('#editor');
+  // Note: You cannot "removeAttr('contentEditable')" once its been added in
+  // FF
+  editorRef.removeClass('editor')
+      .attr('contentEditable', 'false')
+      .addClass('content-dirty')
+      .removeAttr('id');
+}
+
+function startReply(ref) {
+  var parentId = ref.closest('.blip').attr('id');
+  var parentRef = $('#' + parentId);
+  var newBlipRef = insertNewBlip('TBD_' + parentId, parentRef, null,
+      parentRef.html());
+  newBlipRef.find('.author').text(user.getDisplayName());
+  newBlipRef.find('.content').html('');
+  newBlipRef.data('parentId', parentId);
+  // TODO: Calling slideDown followed by focus does not seem
+  // to work well on FF, even when using a callback on slideDown.
+  newBlipRef.show();
+  startEditMode(newBlipRef);
+}
+
+function initEditor() {
+  $('.edit-button').live('click', function() {
+    startEditMode($(this));
+  });
+  $('.reply-button').live('click', function() {
+    startReply($(this));
+  });
+
+  // TODO: Add other ways to get into edit mode.
+
+  $('.editor').live('keypress', function(event) {
+    if (event.shiftKey && event.keyCode == '13') {
+      // Shift+enter!
+      stopEditMode();
+      event.preventDefault();
+    }
+  });
+}


Property changes on: trunk/src/main/webapp/others/splash/js/editor.js
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/js/embed_support.js
===================================================================
--- trunk/src/main/webapp/others/splash/js/embed_support.js	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/js/embed_support.js	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,148 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+* /**
+ * @fileoverview Gadgets-RPC relay and embed client x-iframe support.
+ *
+ * @author dhanji at gmail.com (Dhanji R. Prasanna)
+ */
+
+window.wave = window.wave || {};
+var wave = window.wave;
+
+/**
+ * Service name for loading a new wave in the current view.
+ */
+var LOAD_WAVE = "load_wave";
+
+/**
+ * Service name for loading a new wave in the current view,
+ * specific to a given user (without an explicit wave id).
+ */
+var LOAD_USER_WAVE = "load_user_wave";
+
+/**
+ * Event that is fired when wave load completes.
+ */
+var LOAD_DONE = "load_done";
+
+/**
+ * Api to communicate with the parent of this iframe.
+ * @constructor
+ * @export
+ */
+wave.EmbedApi = function() {
+  // Tests if gadgets library is loaded.
+  if (window.gadgets && window.gadgets.rpc && window.gadgets.config) {
+    this.configParentRelay_();
+    this.registerService(LOAD_WAVE);
+    this.registerService(LOAD_USER_WAVE);
+  } else {
+    throw "Error: gadget library has not loaded yet.";
+  }
+};
+
+/**
+ * Default configuration for the gadget relay.
+ */
+wave.EmbedApi.GADGET_CONFIG = {
+  rpc : {
+    useLegacyProtocol : false,
+    parentRelayUrl :
+        "http://wave.google.com/gadgets/files/container/rpc_relay.html"
+  },
+  "core.io" : {
+    jsonProxyUrl : "http://%host%/gadgets/makeRequest",
+    proxyUrl : "http://%host%/gadgets/proxy?refresh=%refresh%&url=%url%"
+  }
+};
+
+/**
+ * Registers an inter-iframe callback service provided by the embedded client.
+ *
+ * @param service {string} the name of the service.
+ */
+wave.EmbedApi.prototype.registerService = function(service) {
+  var hub = window.gadgets.rpc;
+  if (hub) {
+    hub.register(service, function() {
+      var service = this['s'];
+      var gadgetId = this['f'];
+      var args = this['a'];
+      this.callback(service, gadgetId, args);
+    });
+  }
+};
+
+/**
+ * Configures parent relay to send RPCs to wave-embedding container.
+ * @private
+ */
+wave.EmbedApi.prototype.configParentRelay_ = function() {
+  window.gadgets.config.init(wave.EmbedApi.GADGET_CONFIG);
+};
+
+/**
+ * Fires an event to the outer page via a callback.
+ *
+ * @private
+ * @param event {string} indicating the name of the event to fire.
+ * @param opt_args {Array.<Object>=} a list of parameters that the other side
+ *     needs specific to the event (optional).
+ */
+wave.EmbedApi.prototype.fireEvent = function(event, opt_args) {
+  if (window.gadgets && window.gadgets.rpc) {
+    var base = [null, event, null];
+    var args = base.concat(opt_args);
+    window.gadgets.rpc.call.apply(null, args);
+  }
+};
+
+/**
+ * Receives events from the outer page (complement to
+ *     <code>wave.EmbedApi.fireEvent()</code>).
+ * @export
+ * @param service {string} The name of the service that the gadget wants to
+ *     call.
+ * @param gadgetId {string} The id of the gadget that initiated the RPC.
+ * @param args {Array<Object>} Generic RPC call argument array.
+ */
+wave.EmbedApi.prototype.callback = function(service, gadgetId, args) {
+  if (LOAD_WAVE == service) {
+    // load a new wave with wave id
+    window.wave.Rpc.getInstance().rpcOpenWave(args[0]);
+  } else if (LOAD_USER_WAVE == service) {
+    // load a "myembed" wave
+    // TODO(dhanji): Call the appropriate rpc when it is available.
+  }
+};
+
+/**
+ * Sends a notification to the containing page that wave load has completed.
+ *
+ * @export
+ */
+wave.EmbedApi.prototype.loaded = function() {
+  this.fireEvent(LOAD_DONE);
+};
+
+/**
+ * Register the singleton instance of <code>EmbedApi</code> as soon as possible.
+ */
+(wave.EmbedApi.initialize_ = function() {
+  window.wave.embedApi = window.wave.embedApi || new wave.EmbedApi();
+})();
+


Property changes on: trunk/src/main/webapp/others/splash/js/embed_support.js
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/js/embed_test.js
===================================================================
--- trunk/src/main/webapp/others/splash/js/embed_test.js	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/js/embed_test.js	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,112 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @fileoverview Tests basic functionality of the Embed API
+ *
+ * @author dhanji at gmail.com (Dhanji R. Prasanna)
+ */
+
+/**
+ * Stubs.
+ */
+var window = {};
+var gadgets = {};
+window.gadgets = gadgets;
+gadgets.util = {};
+gadgets.rpc = {};
+gadgets.config = {};
+
+/**
+ * Setup a light fake implementation of gadget.rpc:
+ */
+var callbacks = {};
+
+gadgets.rpc.call = function(frameid, method, c, param1, param2) {
+  method += "_done";
+  for (var name in callbacks){
+    if (method == name) {
+      tocall = callbacks[method];
+      tocall['a'] = new Array(param1, param2);
+      tocall['s'] = method;
+      tocall['f'] = frameid;
+      tocall['c'] = null;
+      tocall.call(tocall);
+      return;
+    }
+  }
+}
+
+gadgets.rpc.register = function(name, callback) {
+  callbacks[name] = callback;
+}
+
+gadgets.rpc.registerDefault = function(method) {
+}
+
+gadgets.rpc.setRelayUrl = function(url) {
+}
+
+/**
+ * Tests that we register available services on the gadget api,
+ * and perform the appropriate initialization steps.
+ */
+function testServicesInitialized() {
+  var initCalled = false;
+  gadgets.config.init = function() {
+    initCalled = true;
+  };
+  var embedApi = new EmbedApi();
+  assertTrue(callbacks['load_wave']);
+  assertTrue(callbacks['load_user_wave']);
+  assertTrue(initCalled);
+}
+
+/**
+ * Tests the event propagation system by simulating the
+ * firing of the 'loaded' event.
+ */
+function testLoadedEventFired() {
+  var embedApi = new EmbedApi();
+
+  var loadCalled = false;
+  gadgets.rpc.register('load_done', function() {
+    loadCalled = true;
+  });
+
+  // Trigger the load event and make sure it propagates
+  embedApi.loaded();
+  assertTrue(loadCalled);
+}
+
+/**
+ * Tests the event propagation system by simulating the
+ * firing of the 'loaded' event.
+ */
+function testLoadWave() {
+  var waveOpenId = '';
+  window.rpcOpenWave = function(waveId) {
+    waveOpenId = waveId;
+  };
+
+  var embedApi = new EmbedApi();
+  var expectedWaveId = 'google.com!w+somewaveid';
+  gadgets.rpc.call('frameId_1', 'load_wave', null, 'gadgetId', expectedWaveId);
+
+  // Make sure the correct wave id was passed thru.
+  assertEquals(expectedWaveId, waveOpenId);
+}


Property changes on: trunk/src/main/webapp/others/splash/js/embed_test.js
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/js/full_client.js
===================================================================
--- trunk/src/main/webapp/others/splash/js/full_client.js	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/js/full_client.js	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,98 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+var RPC_UPDATE_INTERVAL_MS = 3000;
+
+/**
+ * Application entry point.
+ */
+$(document).ready(function() {
+  initCommon();
+
+  // Set up the wave panel.
+  var wave = $('#wave');
+
+  // toolbar on hover
+  $('.blip').live('mouseenter', function() {
+    if (!isEditing()) {
+      showToolbar($(this));
+    }
+  }).live('mouseleave', function() {
+    hideToolbar($(this));
+  });
+
+  // Dismiss yellow alert.
+  $('#alertbar').click(function() {
+    $(this).fadeOut();
+  });
+
+  // Clicking on a feed triggers an animation to open it.
+  $('.item').live('click', function() {
+    // First close the wave window if it's open (and erase current conversation)
+    $('#conversation').html('<img id="wave-loading" src="images/wave-loading.gif">');
+    $('#wave-header').hide();
+
+    var item = $(this);
+
+    // Send RPC to open wave at this point.
+    // TODO(dhanji): Make it possible to have many waves open
+    window.waveOptions_.waveId = item.attr('wave_id');
+    window.waveOptions_.waveVersion = -1;
+    window.waveOptions_.page = 0;
+    window.wave.Rpc.getInstance().rpcOpenWave();
+  });
+
+  // Search box actions.
+  var searchBox = $('#searchField');
+
+  // Watermark on/off
+  $('#searchField').focus(function() {
+    searchBox.text('');
+  });
+
+  $('#searchField').blur(function() {
+    if (searchBox.text() == '') {
+      searchBox.text('Search your waves');
+    }
+  });
+
+  initEditor();
+  initGadgetSystem();
+
+  // Enable touch scrolling for both our panels.
+  $('#feed').jScrollTouch();
+  // TODO(dhanji): Do this for the conversation too.
+
+  var rpc = window.wave.Rpc.getInstance();
+
+  // Run search immediately for our inbox.    
+  rpc.rpcSearch();
+  setInterval(function() {
+    // This is needed to specify the scope of the function.
+    rpc.rpcAsyncUpdate.call(rpc);
+  }, RPC_UPDATE_INTERVAL_MS);
+});
+
+function onSearch() {
+  // Clear feed.
+  $('#feed')
+      .html('<img id="feed-loading" src="images/loading.gif" alt="Loading feed contents...">'
+      + '<div id="more-feed" class="more-button">Show More...</div>');
+
+  // Search for new query content
+  window.waveOptions_.query = $('#searchField').attr('value');
+  window.wave.Rpc.getInstance().rpcSearch();
+}


Property changes on: trunk/src/main/webapp/others/splash/js/full_client.js
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/js/gadget.js
===================================================================
--- trunk/src/main/webapp/others/splash/js/gadget.js	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/js/gadget.js	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,119 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @fileoverview Gadget support.
+ *
+ * @author David Byttow
+ */
+
+// TODO(dhanji): we should eventually extract the relay host from
+//  the iframe source rather than hardcoding it.
+var REMOTE_RPC_RELAY_URL =
+    "http://www.gmodules.com/gadgets/files/container/rpc_relay.html";
+
+var DEFAULT_GADGET_MODE = {'${playback}': '1', '${edit}': '0'};
+
+/**
+ * Registers an rpc handler.
+ *
+ * @param service the name of the service.
+ * @param handler the handler, which is of type
+ *     Function(string, string, array.<string>)
+ */
+function registerRpc(service, handler) {
+  gadgets.rpc.register(service, function() {
+    var service = this['s'];
+    var gadgetId = this['f'];
+    var args = this['a'];
+    handler(service, gadgetId, args);
+  });
+}
+
+/**
+ * Extracts gadget state out of the DOM and pushes it down via gadgets.rpc and
+ * clear the DOM of the unnecessary state after.
+ *
+ * @param gadgetId the gadget id to extract.
+ */
+function extractGadgetState(gadgetId) {
+  // TODO: Use global objects or pool?
+  var state = {};
+  var participants = {
+      // TODO: Should be proper ID.
+      myId: "anonymous at a.gwave.com",
+      authorId: "",
+      participants: {}
+  };
+
+  // Fill in state and participants.
+  var id = '#' + gadgetId + '_state';
+  // Single loop and then if-else switch, rather than multiple loops.
+  $(id).find('span').each(function() {
+    var className = $(this).attr('class');
+    var key = $(this).attr('hiddenKey');
+    var value = $(this).text()
+    if ($(this).hasClass('gadget-state')) {
+      state[key] = value;
+    } else if ($(this).hasClass('gadget-participant')) {
+      // TODO: Profile thumbnail and displayName.
+      var p = {
+          'id': value,
+          'displayName': value,
+          'thumbnailUrl': ''
+      };
+      participants['participants'][value] = p;
+    } else if ($(this).hasClass('gadget-author')) {
+      participants['authorId'] = value;
+    }
+    if (key) {
+      state[key] = value;
+    }
+  });
+
+  // TODO: Enable gadget updates.
+  gadgets.rpc.call(gadgetId, "wave_gadget_mode", null, DEFAULT_GADGET_MODE);
+  gadgets.rpc.call(gadgetId, "wave_participants", null, participants);
+  gadgets.rpc.call(gadgetId, "wave_gadget_state", null, state);
+  // TODO: Deliver the real private state to the gadgets.
+  gadgets.rpc.call(gadgetId, "wave_private_gadget_state", null, {});
+
+  // Clear state out of DOM.
+  $(id).remove();
+}
+
+/**
+ * Initializes the gadget system, call this once at startup.
+ */
+function initGadgetSystem() {
+  // Once a gadget has called us back, we can inject the state/participants.
+  registerRpc("wave_enable", function(service, gadgetId, args) {
+    gadgets.rpc.setRelayUrl(gadgetId, REMOTE_RPC_RELAY_URL);
+    extractGadgetState(gadgetId);
+  });
+
+  registerRpc("resize_iframe", function(service, gadgetId, args) {
+    $('#' + gadgetId).attr('height', args[0]);
+  });
+
+  gadgets.rpc.registerDefault(function() {
+    var eventType = this['s'];
+    var eventObj = this['a'][0];
+    //log(eventType + ": " + eventObj);
+  });
+}
+


Property changes on: trunk/src/main/webapp/others/splash/js/gadget.js
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/js/ie6sucks.js
===================================================================
--- trunk/src/main/webapp/others/splash/js/ie6sucks.js	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/js/ie6sucks.js	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,76 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+function fixLayout() {
+  var targetHeight = $(window).height() - 70;
+  $('#feed').css("height", targetHeight);
+  $('#wave').css("height", targetHeight);
+
+  var targetWidth = 0.7 * $(window).width();
+  $('#wave').css("width", targetWidth + 'px');
+}
+
+/**
+ * Init, separate from the main init.
+ */
+$(document).ready(function() {
+  $('#feed').css("top", 0);
+  $('#content').css("position", "relative");
+  $('#content').css("top", 0);
+
+  fixLayout();
+
+  $(window).resize(fixLayout);
+
+  // Do this everytime a wave is opened
+  window.wave.uiCallbacks_.waveOpened = function() {
+    var waveRef = $('#wave');
+
+    $('.blip', waveRef).each(function() {
+      var leftRef = $('.left', $(this));
+      var rightRef = $('.right', $(this));
+      var leftHeight = leftRef.height();
+      var rightHeight = rightRef.height();
+
+      // Normalize heights
+      if (rightHeight < leftHeight) {
+        rightRef.css('height', leftHeight);
+      }
+
+      // The right half needs to be explicitly floated right or
+      // it just flows to the next line on the left.
+      rightRef.css('float', 'right');
+      rightRef.css('behavior', 'url(border-radius.htc)');
+
+      // The left half needs to be position absolute. Otherwise,
+      // it does not layout inside the correct blip.
+      leftRef.css({
+        'position': 'absolute',
+        'margin-top': '-12px'
+      });
+      
+      // Set the height of a blip to the max of the
+      // left, right divs inside the blip. We add 10px for spacing.
+      $(this).css('height', Math.max(leftHeight, rightHeight) + 60);
+    });
+  };
+
+  // Do this everytime a search is rendered
+  window.wave.uiCallbacks_.feedOpened = function() {
+    $('.item', $('#feed')).css('overflow', 'hidden');
+    $('.snippet', $('#feed')).css('overflow', 'hidden');
+  };
+});


Property changes on: trunk/src/main/webapp/others/splash/js/ie6sucks.js
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/js/jScrollTouch.js
===================================================================
--- trunk/src/main/webapp/others/splash/js/jScrollTouch.js	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/js/jScrollTouch.js	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,104 @@
+/*
+ * jQuery jScrollTouch plugin 1.1
+ *
+ * Copyright (c) 2010 Damien Rottemberg damien at dealinium.com
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ *
+ */
+
+
+(function($){
+  $.fn.jScrollTouch = function () {
+	if((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) || (navigator.userAgent.match(/iPad/i))) {
+ 		var isTouchScreen = 1;
+ 	}else{
+ 		var isTouchScreen = 0;
+ 	}
+ 	$(this).css({'overflow': 'auto','position':'relative'});
+	return this.each(function() {
+		var cont = $(this);
+		
+		var height = 0;
+		var cpos = cont.scrollTop()
+		cont.scrollTop(100000);
+		height = cont.scrollTop();
+		cont.scrollTop(cpos);
+		var fullheight = height + cont.outerHeight();
+		var scrollbarV_length = cont.innerHeight()*(cont.innerHeight()/fullheight)+2;
+		
+		var width = 0;
+		var lpos = cont.scrollLeft();
+		cont.scrollLeft(100000);
+		width = cont.scrollLeft();
+		cont.scrollLeft(lpos);
+		var fullwidth = width + cont.outerWidth();
+		var scrollbarH_length = cont.innerWidth()*(cont.innerWidth()/fullwidth)+2;
+		
+		
+		if(isTouchScreen){
+			var scrollbarV = $('<div></div>');
+			scrollbarV.css({'display':'none','position':'absolute','width':'5px','height':scrollbarV_length+'px','left':cont.innerWidth()-7+'px','top':0,'background':'black','border':'1px white solid','-webkit-border-radius':'5px','opacity':'0.9'});
+			
+			var scrollbarH = $('<div></div>');
+			scrollbarH.css({'display':'none','position':'absolute','height':'5px','width':scrollbarH_length+'px','top':cont.innerHeight()-7+'px','left':0,'background':'black','border':'1px white solid','-webkit-border-radius':'5px','opacity':'0.9'});
+			
+			
+			if(height) cont.append(scrollbarV);
+			if(width) cont.append(scrollbarH);
+		}
+		
+	
+		cont.bind('mousedown touchstart',function(e){
+			cpos = cont.scrollTop();
+					
+			if(isTouchScreen){
+				e = e.originalEvent.touches[0];
+			}
+			
+			if(isTouchScreen){
+				scrollbarV.show();
+				scrollbarH.show();
+			}
+			
+			var sY = e.pageY;
+			var sX = e.pageX;
+			
+			cont.bind('mousemove touchmove ',function(ev){
+				if(isTouchScreen){
+					ev.preventDefault();
+					ev = ev.originalEvent.touches[0];
+					
+				}	
+				
+				var top = cpos-(ev.pageY-sY);
+				var left =  lpos-(ev.pageX-sX);
+				
+				cont.scrollTop(top);
+				cpos = cont.scrollTop();
+				sY = ev.pageY;
+				
+				cont.scrollLeft(left);
+				lpos = cont.scrollLeft();
+				sX = ev.pageX;
+				if(isTouchScreen){
+					scrollbarV.css({'left':Math.min(cont.innerWidth()-7+lpos,fullwidth)+'px','top':Math.min(cpos+cpos*cont.innerHeight()/fullheight,fullheight-scrollbarV_length)+'px'});
+					scrollbarH.css({'top':Math.min(cont.innerHeight()-7+cpos,fullheight)+'px','left':Math.min(lpos+lpos*cont.innerWidth()/fullwidth,fullwidth-scrollbarH_length)+'px'});
+					
+				}	
+			});
+			cont.bind('mouseup touchend',function(ev){	
+				cont.unbind('mousemove touchmove mouseup touchend');
+				if(isTouchScreen){
+					scrollbarV.fadeOut();
+					scrollbarH.fadeOut();
+				}
+				
+			});
+		});
+	});
+}
+})(jQuery);   
\ No newline at end of file


Property changes on: trunk/src/main/webapp/others/splash/js/jScrollTouch.js
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/js/jquery-1.4.2.min.js
===================================================================
--- trunk/src/main/webapp/others/splash/js/jquery-1.4.2.min.js	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/js/jquery-1.4.2.min.js	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,154 @@
+/*!
+ * jQuery JavaScript Library v1.4.2
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Sat Feb 13 22:33:48 2010 -0500
+ */
+(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
+e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
+j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
+"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
+true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
+Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
+(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
+a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
+"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
+function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
+c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
+L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
+"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
+a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
+d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
+a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
+!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
+true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
+parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
+false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
+s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
+applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
+else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
+a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
+w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
+cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
+i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
+" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
+this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
+e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
+c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
+a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
+function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
+k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
+C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
+null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
+e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
+f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
+if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
+d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
+"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
+a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
+isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
+{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
+if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
+e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
+"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
+d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
+!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
+toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
+u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
+function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
+if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
+t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
+g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
+for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
+1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.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\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
+relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
+l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
+h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
+CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
+g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
+text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
+setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
+h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
+m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
+"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
+h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
+!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
+h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
+q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
+if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
+(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
+function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
+gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
+c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
+{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
+"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
+d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
+a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
+1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
+a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
+c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
+wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
+prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
+this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
+return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
+""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
+this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
+u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
+1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
+return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
+""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
+c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
+c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
+function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
+Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
+"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
+a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
+a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
+"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
+serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
+function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
+global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
+e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
+"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
+false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
+false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
+c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
+d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
+g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
+1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
+"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
+if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
+this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
+"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
+animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
+j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
+this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
+"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
+c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
+this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
+this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
+e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
+c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
+function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
+this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
+k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
+f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<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>";
+a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
+c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
+d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
+f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
+"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
+e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);


Property changes on: trunk/src/main/webapp/others/splash/js/jquery-1.4.2.min.js
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/js/jquery.lightbox-0.5.min.js
===================================================================
--- trunk/src/main/webapp/others/splash/js/jquery.lightbox-0.5.min.js	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/js/jquery.lightbox-0.5.min.js	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,42 @@
+/**
+ * jQuery lightBox plugin
+ * This jQuery plugin was inspired and based on Lightbox 2 by Lokesh Dhakar (http://www.huddletogether.com/projects/lightbox2/)
+ * and adapted to me for use like a plugin from jQuery.
+ * @name jquery-lightbox-0.5.js
+ * @author Leandro Vieira Pinho - http://leandrovieira.com
+ * @version 0.5
+ * @date April 11, 2008
+ * @category jQuery plugin
+ * @copyright (c) 2008 Leandro Vieira Pinho (leandrovieira.com)
+ * @license CC Attribution-No Derivative Works 2.5 Brazil - http://creativecommons.org/licenses/by-nd/2.5/br/deed.en_US
+ * @example Visit http://leandrovieira.com/projects/jquery/lightbox/ for more informations about this jQuery plugin
+ */
+(function($){$.fn.lightBox=function(settings){settings=jQuery.extend({overlayBgColor:'#000',overlayOpacity:0.8,fixedNavigation:false,imageLoading:'images/lightbox-ico-loading.gif',imageBtnPrev:'images/lightbox-btn-prev.gif',imageBtnNext:'images/lightbox-btn-next.gif',imageBtnClose:'images/lightbox-btn-close.gif',imageBlank:'images/lightbox-blank.gif',containerBorderSize:10,containerResizeSpeed:400,txtImage:'Image',txtOf:'of',keyToClose:'c',keyToPrev:'p',keyToNext:'n',imageArray:[],activeImage:0},settings);var jQueryMatchedObj=this;function _initialize(){_start(this,jQueryMatchedObj);return false;}
+function _start(objClicked,jQueryMatchedObj){$('embed, object, select').css({'visibility':'hidden'});_set_interface();settings.imageArray.length=0;settings.activeImage=0;if(jQueryMatchedObj.length==1){settings.imageArray.push(new Array(objClicked.getAttribute('href'),objClicked.getAttribute('title')));}else{for(var i=0;i<jQueryMatchedObj.length;i++){settings.imageArray.push(new Array(jQueryMatchedObj[i].getAttribute('href'),jQueryMatchedObj[i].getAttribute('title')));}}
+while(settings.imageArray[settings.activeImage][0]!=objClicked.getAttribute('href')){settings.activeImage++;}
+_set_image_to_view();}
+function _set_interface(){$('body').append('<div id="jquery-overlay"></div><div id="jquery-lightbox"><div id="lightbox-container-image-box"><div id="lightbox-container-image"><img id="lightbox-image"><div style="" id="lightbox-nav"><a href="#" id="lightbox-nav-btnPrev"></a><a href="#" id="lightbox-nav-btnNext"></a></div><div id="lightbox-loading"><a href="#" id="lightbox-loading-link"><img src="'+settings.imageLoading+'"></a></div></div></div><div id="lightbox-container-image-data-box"><div id="lightbox-container-image-data"><div id="lightbox-image-details"><span id="lightbox-image-details-caption"></span><span id="lightbox-image-details-currentNumber"></span></div><div id="lightbox-secNav"><a href="#" id="lightbox-secNav-btnClose"><img src="'+settings.imageBtnClose+'"></a></div></div></div></div>');var arrPageSizes=___getPageSize();$('#jquery-overlay').css({backgroundColor:settings.overlayBgColor,opacity:settings.overlayOpacity,width:arrPageSizes[0],height:arrPageSizes[1]}).fadeIn();var arrPageScroll=___getPageScroll();$('#jquery-lightbox').css({top:arrPageScroll[1]+(arrPageSizes[3]/10),left:arrPageScroll[0]}).show();$('#jquery-overlay,#jquery-lightbox').click(function(){_finish();});$('#lightbox-loading-link,#lightbox-secNav-btnClose').click(function(){_finish();return false;});$(window).resize(function(){var arrPageSizes=___getPageSize();$('#jquery-overlay').css({width:arrPageSizes[0],height:arrPageSizes[1]});var arrPageScroll=___getPageScroll();$('#jquery-lightbox').css({top:arrPageScroll[1]+(arrPageSizes[3]/10),left:arrPageScroll[0]});});}
+function _set_image_to_view(){$('#lightbox-loading').show();if(settings.fixedNavigation){$('#lightbox-image,#lightbox-container-image-data-box,#lightbox-image-details-currentNumber').hide();}else{$('#lightbox-image,#lightbox-nav,#lightbox-nav-btnPrev,#lightbox-nav-btnNext,#lightbox-container-image-data-box,#lightbox-image-details-currentNumber').hide();}
+var objImagePreloader=new Image();objImagePreloader.onload=function(){$('#lightbox-image').attr('src',settings.imageArray[settings.activeImage][0]);_resize_container_image_box(objImagePreloader.width,objImagePreloader.height);objImagePreloader.onload=function(){};};objImagePreloader.src=settings.imageArray[settings.activeImage][0];};function _resize_container_image_box(intImageWidth,intImageHeight){var intCurrentWidth=$('#lightbox-container-image-box').width();var intCurrentHeight=$('#lightbox-container-image-box').height();var intWidth=(intImageWidth+(settings.containerBorderSize*2));var intHeight=(intImageHeight+(settings.containerBorderSize*2));var intDiffW=intCurrentWidth-intWidth;var intDiffH=intCurrentHeight-intHeight;$('#lightbox-container-image-box').animate({width:intWidth,height:intHeight},settings.containerResizeSpeed,function(){_show_image();});if((intDiffW==0)&&(intDiffH==0)){if($.browser.msie){___pause(250);}else{___pause(100);}}
+$('#lightbox-container-image-data-box').css({width:intImageWidth});$('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css({height:intImageHeight+(settings.containerBorderSize*2)});};function _show_image(){$('#lightbox-loading').hide();$('#lightbox-image').fadeIn(function(){_show_image_data();_set_navigation();});_preload_neighbor_images();};function _show_image_data(){$('#lightbox-container-image-data-box').slideDown('fast');$('#lightbox-image-details-caption').hide();if(settings.imageArray[settings.activeImage][1]){$('#lightbox-image-details-caption').html(settings.imageArray[settings.activeImage][1]).show();}
+if(settings.imageArray.length>1){$('#lightbox-image-details-currentNumber').html(settings.txtImage+' '+(settings.activeImage+1)+' '+settings.txtOf+' '+settings.imageArray.length).show();}}
+function _set_navigation(){$('#lightbox-nav').show();$('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css({'background':'transparent url('+settings.imageBlank+') no-repeat'});if(settings.activeImage!=0){if(settings.fixedNavigation){$('#lightbox-nav-btnPrev').css({'background':'url('+settings.imageBtnPrev+') left 15% no-repeat'}).unbind().bind('click',function(){settings.activeImage=settings.activeImage-1;_set_image_to_view();return false;});}else{$('#lightbox-nav-btnPrev').unbind().hover(function(){$(this).css({'background':'url('+settings.imageBtnPrev+') left 15% no-repeat'});},function(){$(this).css({'background':'transparent url('+settings.imageBlank+') no-repeat'});}).show().bind('click',function(){settings.activeImage=settings.activeImage-1;_set_image_to_view();return false;});}}
+if(settings.activeImage!=(settings.imageArray.length-1)){if(settings.fixedNavigation){$('#lightbox-nav-btnNext').css({'background':'url('+settings.imageBtnNext+') right 15% no-repeat'}).unbind().bind('click',function(){settings.activeImage=settings.activeImage+1;_set_image_to_view();return false;});}else{$('#lightbox-nav-btnNext').unbind().hover(function(){$(this).css({'background':'url('+settings.imageBtnNext+') right 15% no-repeat'});},function(){$(this).css({'background':'transparent url('+settings.imageBlank+') no-repeat'});}).show().bind('click',function(){settings.activeImage=settings.activeImage+1;_set_image_to_view();return false;});}}
+_enable_keyboard_navigation();}
+function _enable_keyboard_navigation(){$(document).keydown(function(objEvent){_keyboard_action(objEvent);});}
+function _disable_keyboard_navigation(){$(document).unbind();}
+function _keyboard_action(objEvent){if(objEvent==null){keycode=event.keyCode;escapeKey=27;}else{keycode=objEvent.keyCode;escapeKey=objEvent.DOM_VK_ESCAPE;}
+key=String.fromCharCode(keycode).toLowerCase();if((key==settings.keyToClose)||(key=='x')||(keycode==escapeKey)){_finish();}
+if((key==settings.keyToPrev)||(keycode==37)){if(settings.activeImage!=0){settings.activeImage=settings.activeImage-1;_set_image_to_view();_disable_keyboard_navigation();}}
+if((key==settings.keyToNext)||(keycode==39)){if(settings.activeImage!=(settings.imageArray.length-1)){settings.activeImage=settings.activeImage+1;_set_image_to_view();_disable_keyboard_navigation();}}}
+function _preload_neighbor_images(){if((settings.imageArray.length-1)>settings.activeImage){objNext=new Image();objNext.src=settings.imageArray[settings.activeImage+1][0];}
+if(settings.activeImage>0){objPrev=new Image();objPrev.src=settings.imageArray[settings.activeImage-1][0];}}
+function _finish(){$('#jquery-lightbox').remove();$('#jquery-overlay').fadeOut(function(){$('#jquery-overlay').remove();});$('embed, object, select').css({'visibility':'visible'});}
+function ___getPageSize(){var xScroll,yScroll;if(window.innerHeight&&window.scrollMaxY){xScroll=window.innerWidth+window.scrollMaxX;yScroll=window.innerHeight+window.scrollMaxY;}else if(document.body.scrollHeight>document.body.offsetHeight){xScroll=document.body.scrollWidth;yScroll=document.body.scrollHeight;}else{xScroll=document.body.offsetWidth;yScroll=document.body.offsetHeight;}
+var windowWidth,windowHeight;if(self.innerHeight){if(document.documentElement.clientWidth){windowWidth=document.documentElement.clientWidth;}else{windowWidth=self.innerWidth;}
+windowHeight=self.innerHeight;}else if(document.documentElement&&document.documentElement.clientHeight){windowWidth=document.documentElement.clientWidth;windowHeight=document.documentElement.clientHeight;}else if(document.body){windowWidth=document.body.clientWidth;windowHeight=document.body.clientHeight;}
+if(yScroll<windowHeight){pageHeight=windowHeight;}else{pageHeight=yScroll;}
+if(xScroll<windowWidth){pageWidth=xScroll;}else{pageWidth=windowWidth;}
+arrayPageSize=new Array(pageWidth,pageHeight,windowWidth,windowHeight);return arrayPageSize;};function ___getPageScroll(){var xScroll,yScroll;if(self.pageYOffset){yScroll=self.pageYOffset;xScroll=self.pageXOffset;}else if(document.documentElement&&document.documentElement.scrollTop){yScroll=document.documentElement.scrollTop;xScroll=document.documentElement.scrollLeft;}else if(document.body){yScroll=document.body.scrollTop;xScroll=document.body.scrollLeft;}
+arrayPageScroll=new Array(xScroll,yScroll);return arrayPageScroll;};function ___pause(ms){var date=new Date();curDate=null;do{var curDate=new Date();}
+while(curDate-date<ms);};return this.unbind('click').click(_initialize);};})(jQuery);
\ No newline at end of file


Property changes on: trunk/src/main/webapp/others/splash/js/jquery.lightbox-0.5.min.js
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/js/mobile_client.js
===================================================================
--- trunk/src/main/webapp/others/splash/js/mobile_client.js	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/js/mobile_client.js	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,127 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+var RPC_UPDATE_INTERVAL_MS = 3000;
+
+function log(msg) {
+  if (window.console && window.console.log) {
+    console.log(msg);
+  }
+}
+
+function warn(msg) {
+  if (window.console && window.console.warn) {
+    console.warn(msg);
+  }
+}
+
+/**
+ * Application entry point.
+ */
+$(document).ready(function() {
+  initCommon();
+
+  // Set up the wave panel.
+  var wave = $('#wave');
+
+  // toolbar on hover
+  $('.blip').live('mouseenter', function() {
+    if (!isEditing()) {
+      showToolbar($(this));
+    }
+  }).live('mouseleave', function() {
+    hideToolbar($(this));
+  });
+
+  // Dismiss yellow alert.
+  $('#alertbar').click(function() {
+    $(this).fadeOut();
+  });
+
+  // Clicking on a feed triggers an animation to open it.
+  $('.item').live('click', function() {
+    // In the mobile client, we swap the wave and feed when a digest is clicked.
+    $('#feed').hide();
+
+    wave.show();
+    $('#conversation').html('<img id="wave-loading" src="images/wave-loading.gif">');
+    $('#main-button').text('Back to Waves');
+
+    var item = $(this);
+
+    // Send RPC to open wave at this point.
+    // TODO(dhanji): Make it possible to have many waves open
+    window.waveOptions_.waveId = item.attr('wave_id');
+    window.waveOptions_.waveVersion = -1;
+    window.waveOptions_.page = 0;
+    window.wave.Rpc.getInstance().rpcOpenWave();
+  });
+
+  // Search box actions.
+  var searchBox = $('#searchField');
+
+  $('#main-button').click(function() {
+    // If we're in wave mode, go back.
+    if (window.waveOptions_.waveId) {
+      wave.hide();
+      $('#feed').show();
+      $('#main-button').text('New Wave');
+    } else {
+      // TODO(dhanji): Implement.
+    }
+  });
+  
+  $('#searchField').click(function() {
+    $('#searchField').val('');
+  });
+
+  $('#searchToggle').click(function() {
+    toggleSearch();
+  });
+
+  initEditor();
+  initGadgetSystem();
+
+  var rpc = window.wave.Rpc.getInstance();
+
+  // Run search immediately for our inbox.
+  rpc.rpcSearch();
+  setInterval(function() {
+    // This is needed to specify the scope of the function.
+    rpc.rpcAsyncUpdate.call(rpc);
+  }, RPC_UPDATE_INTERVAL_MS);
+});
+
+function onSearch() {
+  // Clear feed.
+  $('.feed')
+      .html('<img id="feed-loading" src="images/loading.gif" alt="Loading feed contents...">'
+      + '<div id="more-feed" class="more-button">Show More...</div>');
+
+  // Search for new query content
+  window.waveOptions_.query = $('#searchField').attr('value');
+  window.wave.Rpc.getInstance().rpcSearch();
+}
+
+function toggleSearch() {
+  var headerSearchRef = $('#headerSearch')
+  if (headerSearchRef.is(':visible')) {
+    headerSearchRef.fadeOut();
+  }
+  else {
+    headerSearchRef.fadeIn();
+  }
+}


Property changes on: trunk/src/main/webapp/others/splash/js/mobile_client.js
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/js/permalink_client.js
===================================================================
--- trunk/src/main/webapp/others/splash/js/permalink_client.js	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/js/permalink_client.js	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,106 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @fileoverview JS for the standalone (permalink) version of the client.
+ * @author dhanji at gmail.com (Dhanji R. Prasanna)
+ */
+
+
+var RPC_UPDATE_INTERVAL_MS = 3000;
+
+window.waveOptions_ = {};
+
+/**
+ * Application entry point.
+ */
+$(document).ready(function() {
+  var path = window.location.pathname;
+  
+  // adjust the height of the content frame to fill the iframe height
+  $("#contentInner3")
+    .css("height", 0)
+    .css("height",
+      $(window).height() - $("#header").outerHeight()
+          - $("#content").outerHeight());
+
+  // extract wave id.
+  var waveId = $('#wave').attr('wave_id');
+
+  // run rpc right away to open the wave.
+  window.waveOptions_.waveId = waveId;
+  window.waveOptions_.page = 0;
+  window.waveOptions_.waveVersion = -1;
+
+  // Options for rendering the wave. Maybe we need a more robust solution.
+  window.waveOptions_.showHeader = $('#wave').attr('show_header');
+
+  // Override async update options, coz we don't need search and stuff.
+  // TODO(dhanji): this is broken, fix.
+  RPC_UPDATE_OPTIONS = "update_wave";
+
+  $('#share-link').click(function() {
+    var shareRef = $('#share-popup');
+    shareRef.fadeIn();
+    return false;
+  });
+
+  $(".dialog-close").mousedown(function() {
+    $(this).addClass("down");
+  });
+
+  $(".dialog-close").mouseout(function() {
+    $(this).removeClass("down");
+  });
+
+  $(document).click(function(event) {
+    if ($(event.target).is("#share-popup, #share-popup *")
+        && !$(event.target).is(".dialog-close, .dialog-close *"))
+    {
+      return false;
+    }
+
+    $('#share-popup').fadeOut();
+  });
+
+  // Listen for expansion of collapsed inline replies.
+  // TODO(dhanji): Merge into a common.js (NOT common_client.js)
+  $('.inline-reply .count').live('click', function() {
+    var inlineReplyId = '#ir-' + $(this).parent().attr('ir-id');
+    var countRef = $(this);
+
+    if (countRef.hasClass('expanded')) {
+      // Move this back to purgatory!
+      $(inlineReplyId).appendTo('#purgatory');
+      countRef.removeClass('expanded');
+    } else {
+      $(inlineReplyId).insertAfter(countRef);
+      countRef.addClass('expanded');
+    }
+  });
+
+  var rpc = window.wave.Rpc.getInstance();
+
+  initGadgetSystem();
+  rpc.rpcOpenWave();
+
+  setInterval(function() {
+    // This is needed to specify the scope of the function.
+    window.wave.Rpc.getInstance().rpcAsyncUpdate();
+  }, RPC_UPDATE_INTERVAL_MS);
+});
+


Property changes on: trunk/src/main/webapp/others/splash/js/permalink_client.js
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/js/rpc.js
===================================================================
--- trunk/src/main/webapp/others/splash/js/rpc.js	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/js/rpc.js	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,708 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @fileoverview Client/Server RPC abstraction and UI update callback layer.
+ * The current user is provided to us by means for the global
+ * <code>BOOTSTRAP</code> constant, in the containing HTML template. This
+ * file also relies on the presence of the jQuery 1.4.2 library
+ * (http://code.jquery.com/jquery-1.4.2.js) and the jQuery lightbox 0.5.0
+ * plugin (http://leandrovieira.com/projects/jquery/lightbox/).
+ * We also require <code>window.waveOptions_</code> to be an object that is
+ * set to the current client state (essentially the open wave + version).
+ * Classes:
+ *   wave.DataView
+ *   wave.Rpc
+ * @author dhanji at google.com (Dhanji R. Prasanna)
+ */
+
+
+var wave = wave || {};
+
+/**
+ * Global user info.
+ *
+ * @type {!Object}
+ */
+wave.user = wave.user || {};
+
+/**
+ * A registry of UI callbacks.
+ *
+ * @type {!Object.<string,function()>}
+ * @private
+ */
+wave.uiCallbacks_ = wave.uiCallbacks_ || {};
+
+/**
+ * @return {string} Email address of the current user.
+ */
+wave.user.getEmail = function() {
+  // BOOTSTRAP is current user info provided by the HTML template.
+  return BOOTSTRAP.email;
+};
+
+/**
+ * @return {string} Full name of the current user.
+ */
+wave.user.getDisplayName = function() {
+  // BOOTSTRAP is current user info provided by the HTML template.
+  return BOOTSTRAP.displayName;
+};
+
+
+/**
+ * Represents all UI access to the data controls of the current client.
+ * Data from/to the server should be read and written to the UI using
+ * this class.
+ *
+ * @constructor
+ * @export
+ */
+wave.DataView = function() {
+  /**
+   * List of dirty blips that represent pending edits to the wave.
+   *
+   * @type {!Array<Element>}
+   * @private
+   */
+  this.pendingEdits_ = [];
+
+  /**
+   * A reference to the conversation element of the wave.
+   *
+   * @type {Element}
+   * @private
+   */
+  this.conversation_ = $('#conversation');
+};
+
+/**
+ * The nominal height of the wave header in pixels.
+ *
+ * @type {number}
+ * @private
+ */
+wave.DataView.WAVE_HEADER_HEIGHT_PX_ = 18;
+
+/**
+ * Gathers all the edited blips from the DOM (marked by class content-dirty)
+ * and adds them to the current client state as new or edited blips.
+ */
+wave.DataView.prototype.addPendingEdits = function() {
+  var requestId = 0;
+  $('.content-dirty').each(function() {
+    var dirtyRef = $(this);
+    var blipId = dirtyRef.attr('blip_id');
+    var blipRef = $('#' + blipId);
+    var parentId = blipRef.data('parentId');
+    var threadId = blipRef.parent('div.thread').attr('id');
+    var content = dirtyRef.html();
+    if (parentId) {
+      // If the parent id exists, we assume this is a new reply.
+      window.waveOptions_['newblip_' + requestId + '_previousBlip'] = parentId;
+      window.waveOptions_['newblip_' + requestId + '_text'] = content;
+      window.waveOptions_['newblip_' + requestId + '_threadId'] = threadId;
+    } else {
+      window.waveOptions_['editblip_' + blipId] = content;
+    }
+    requestId++;
+    this.pendingEdits_.push(dirtyRef);
+  });
+};
+
+/**
+ * Clears all the edited blips state stored in the client state, typically
+ * called after this state has been synchronized with the server. Acts as
+ * as complement to <code>addPendingEdits</code>.
+ */
+wave.DataView.prototype.clearPendingEdits = function() {
+  var requestId = 0;
+  for (var i = 0; i < this.pendingEdits_.length; i++) {
+    var dirtyRef = this.pendingEdits[i];
+    var blipId = dirtyRef.attr('blip_id');
+    var blipRef = $('#' + blipId);
+    var parentId = blipRef.data('parentId');
+
+    delete window.waveOptions_['newblip_' + requestId + '_previousBlip'];
+    delete window.waveOptions_['newblip_' + requestId + '_text'];
+    delete window.waveOptions_['newblip_' + requestId + '_threadId'];
+    delete window.waveOptions_['editblip_' + blipId];
+    dirtyRef.removeClass('content-dirty');
+    requestId++;
+  }
+  
+  // Finally, clear all pending edits.
+  this.pendingEdits_.length = 0;
+};
+
+/**
+ * Updates the the time-measure field with the value from the last
+ * action. For example, "Search completed in XX.Xs"
+ *
+ * @param {string} html A String of processed html representing the
+ *     measurement to be displayed.
+ */
+wave.DataView.prototype.measure = function(html) {
+  $('#measure').html(html);
+};
+
+/**
+ * Appends a conversation fragment to the existing wave conversation.
+ *
+ * @param {string} html A String of processed html representing the
+ *     fragment of conversation to be appended.
+ */
+wave.DataView.prototype.appendConversation = function(html) {
+  this.conversation_.append($(html));
+  $('#wave-loading').remove();
+  $('#wave-header').show();
+
+  // Set up the lightbox for any slideshows in the wave (using the jQuery
+  // lightbox plugin).
+  $('a.lightbox').lightBox();
+};
+
+/**
+ * Replaces the existing wave conversation with a newly rendered html
+ * conversation.
+ *
+ * @param {string} html A string of processed html representing the
+ *     fragment of conversation to place.
+ * @return {boolean} True if there is more conversation to be loaded for
+ *     this wave.
+ */
+wave.DataView.prototype.insertConversation = function(html) {
+  this.conversation_.html($(html));
+
+  // Set up the lightbox for any slideshows in the wave.
+  $('a.lightbox').lightBox();
+
+  return $('#wave-loading').length > 0;
+};
+
+/**
+ * Replaces the existing wave header with a newly rendered html
+ * list of participants.
+ *
+ * @param {string} html A string of processed html representing the
+ *     header of the wave.
+ */
+wave.DataView.prototype.insertHeader = function(html) {
+  var headerRef = $('#wave-header');
+  headerRef.removeClass('expanded');
+  headerRef.html($(html));
+  headerRef.show();
+
+  // Determine the actual height with all participants.
+  var participantsRef = $('.participants');
+  participantsRef.css('height', 'auto');
+  var height = participantsRef.height();
+  participantsRef.css('height', null);
+
+  // Display a "show more" option if the content height is greater than
+  // the default height of the wave header.
+  if (height > wave.DataView.WAVE_HEADER_HEIGHT_PX_) {
+    $('.header .detail').show();
+  }
+};
+
+/**
+ * Deletes the specified blip from view with an animation.
+ *
+ * @param {string} blipId A DOM selector for the blip to delete.
+ */
+wave.DataView.prototype.deleteBlip = function(blipId) {
+  // Animate by sliding it up out of view.
+  $(blipId).slideUp(function() {
+    $(this).remove();
+  });
+};
+
+/**
+ * Inserts a new blip into the wave conversation at the appropriate spot in the
+ * DOM.
+ *
+ * @param {string} blipId Id of the blip to be inserted into the DOM.
+ * @param {string=} opt_parent DOM selector of the parent blip to insert under
+ *     (optional).
+ * @param {boolean=} opt_indent True if this blip should be rendered inside a
+ *     new indent level under the parent. Default is false (optional).
+ * @param {string=} opt_html Processed html containing the content of the blip
+ *     itself to be inserted directly into the DOM (optional).
+ * @param {number=} opt_version Version number of the of the new blip
+ *     (optional).
+ * @return {Element} A reference to the blip DOM element that was just inserted.
+ */
+wave.DataView.prototype.insertBlip = function(blipId, opt_parent, opt_indent,
+    opt_html, opt_version) {
+  var indent = opt_indent || false;
+  var html = opt_html || 'TEST';
+  var version = opt_version || '0';
+
+  // Construct a blip html fragment and slide it in.
+  var htmlBuilder = [
+    '<div id="',
+    blipId,
+    '" class="blip" style="display:none">',
+    html,
+    '</div>'
+  ];
+  blipRef = $(htmlBuilder.join(''));
+
+  // Handle the indented reply case.
+  if (!opt_parent) {
+    // If this is the root blip. Add to container.
+    this.conversation_.prepend(blip);
+  } else if (indent) {
+    // See if the parent blip already has an inline child.
+    var parentRef = $(opt_parent);
+    var indentRef = parentRef.children('.indent');
+    if (indentRef.length) {
+      // If it does, insert into it.
+      indentRef.append(blipRef);
+    } else {
+      // Insert an indent wrapper.
+      indentRef = $('<div class="indent"></div>');
+      parentRef.after(indentRef);
+      indentRef.append(blipRef);
+    }
+  } else {
+    $(opt_parent).after(blipRef);
+  }
+  return blipRef;
+};
+
+/**
+ * Updates an existing blip in the wave conversation in place.
+ *
+ * @param {string} blipId A DOM selector of the blip id to update in place.
+ * @param {string} html Processed HTML of the new content of the blip.
+ */
+wave.DataView.prototype.replaceBlip = function(blipId, html) {
+  var blip = $(blipId);
+
+  // Animated transition from the old to the new content.
+  blip.fadeTo('slow', 0, function() {
+    blip.html(html);
+    blip.fadeTo('slow', 1);
+  });
+};
+
+/**
+ * Inserts the incoming HTML into the feed before the more feed button, and
+ * removes the feed loading indicator.
+ *
+ * @param {string} html Processed HTML of the new content of the feed.
+ */
+wave.DataView.prototype.insertFeed = function(html) {
+  var newFeed = $(html);
+
+  // Insert fragment into feed invisible, then slide in.
+  $('#feed-loading').remove();
+
+  // Insert it before the more button.
+  $('#more-feed').before(newFeed);
+  newFeed.show();
+};
+
+/**
+ * Tests if an element(s) exists in the DOM by its selector.
+ *
+ * @param {string} selector A DOM selector in CSS fashion.
+ * @return {boolean} True if this CSS selector exists in the DOM.
+ */
+wave.DataView.prototype.exists = function(selector) {
+  return $(selector).length > 0;
+};
+
+/**
+ * Determines if the given client action data is newer than the version of the
+ * existing blip.
+ *
+ * @param {!Object} data A client action that may or may not contain a version.
+ * @param {Element} blip A blip element on the page.
+ * @return {boolean} True if the data is newer than the blip on page.
+ */
+wave.DataView.prototype.hasNewer = function(data, blip) {
+  return data.version && blip.data('version') >= data.version;
+};
+
+/**
+ * Handles all high-level RPC communication with the web server.
+ *
+ * @param {!wave.DataView} dataView A handle to the underlying data view.
+ * @export
+ * @constructor
+ */
+wave.Rpc = function(dataView) {
+  /**
+   * The singleton data view to modify the UI.
+   *
+   * @type {wave.DataView}
+   * @private
+   */
+  this.dataView_ = dataView;
+  // Register global RPC server callbacks.
+  this.callbacks_ = {
+    'add-blip': this.addBlipCallback_,
+    'update-blip': this.updateBlipCallback_,
+    'delete-blip': this.deleteBlipCallback_,
+    'update-feed': this.updateFeedCallback_,
+    'update-wave-version': this.updateWaveVersionCallback_,
+    'update-wave': this.updateWaveCallback_,
+    'update-header': this.updateHeaderCallback_,
+    'measure': this.measureCallback_
+  };
+};
+
+/**
+ * Global instance.
+ *
+ * @type {wave.Rpc}
+ * @private
+ */
+wave.Rpc.instance_ = null;
+
+/**
+ * Singleton factory method.
+ *
+ * @return {wave.Rpc} Singleton instance of <code>wave.Rpc</code> class.
+ * @export
+ */
+wave.Rpc.getInstance = function() {
+  if (!wave.Rpc.instance_) {
+    wave.Rpc.instance_ = new wave.Rpc(new wave.DataView());
+  }
+
+  return wave.Rpc.instance_;
+};
+
+/**
+ * Default RPC endpoints requested by this edition of the client.
+ * A comma-separated list of rpc names that will be executed each
+ * time a short-poll request is made in the background.
+ *
+ * @type {string}
+ * @private
+ */
+wave.Rpc.RPC_UPDATE_OPTIONS_ = 'update_wave,edit_wave';
+
+/**
+ * The Ajax URL where RPCs should be sent for background batch
+ * execution. This URL accepts only POST messages.
+ *
+ * @type {string}
+ * @private
+ */
+wave.Rpc.ASYNC_UPDATE_URL_ = '/async/update?rpc=' +
+    wave.Rpc.RPC_UPDATE_OPTIONS_;
+
+/**
+ * The Ajax URL for executing searches immediately.
+ *
+ * @type {string}
+ * @private
+ */
+wave.Rpc.SYNC_SEARCH_URL_ = '/async/search?rpc=search';
+
+/**
+ * The Ajax URL for executing wave-open requests immediately.
+ *
+ * @type {string}
+ * @private
+ */
+wave.Rpc.SYNC_WAVE_URL_ = '/async/wave?rpc=open_wave';
+
+/**
+ * An internal map of RPC names to callbacks.
+ *
+ * @type {Object.<string,function(Object)>}
+ * @private
+ */
+wave.Rpc.prototype.callbacks_;
+
+/**
+ * Executes a search RPC immediately. Responses are handled
+ * via <code>updateFeedCallback</code>.
+ *
+ * @export
+ */
+wave.Rpc.prototype.rpcSearch = function() {
+  this.rpc_(wave.Rpc.SYNC_SEARCH_URL_);
+};
+
+/**
+ * Executes an open wave RPC immediately. Responses are handled
+ * via <code>updateWaveCallback</code>.
+ *
+ * @export
+ */
+wave.Rpc.prototype.rpcOpenWave = function() {
+  this.rpc_(wave.Rpc.SYNC_WAVE_URL_);
+};
+
+/**
+ * Synchronizes the client state with the server via a periodic
+ * short poll. This function is typically called by a timer and
+ * sends a batch of RPCs including edits, new blip additions, etc.
+ *
+ * @export
+ */
+wave.Rpc.prototype.rpcAsyncUpdate = function() {
+  this.dataView_.addPendingEdits();
+  this.rpc_(wave.Rpc.ASYNC_UPDATE_URL_);
+  this.dataView_.clearPendingEdits();
+};
+
+/**
+ * Tests if the given wave id is currently open in the client.
+ *
+ * @param {string} waveId A wave id of the form "[domain.com]![id]"
+ *     as described in the wave protocol specification.
+ * @return {boolean} True if the given wave id is currently open.
+ * @private
+ */
+wave.Rpc.prototype.isCurrentWave_ = function(waveId) {
+  return window.waveOptions_.waveId == waveId;
+};
+
+/**
+ * A callback for handling network communication failure in the background.
+ * Displays a useful message to the user.
+ * TODO(dhanji): Revisit for i18n.
+ *
+ * @private
+ */
+wave.Rpc.prototype.onAjaxFailure_ = function() {
+  alert('Oops, there was a network failure. Please give it a few seconds' +
+      ' and try again.');
+};
+
+/**
+ * The central RPC invoker, takes the entire state of the client and posts it
+ * as name/value pairs to a given RPC endpoint. Asynchronous responses are
+ * processed in <code>handleRpcResponse_</code>.
+ *
+ * @param {string} url  The relative URL representing an RPC endpoint.
+ * @private
+ */
+wave.Rpc.prototype.rpc_ = function(url) {
+  var self = this;
+  var success = function(data) {
+    self.handleRpcResponse_.call(self, data);
+  };
+  $.ajax({
+    type: 'POST',
+    url: url,
+    dataType: 'json',
+    data: window.waveOptions_,
+    success: success,
+    failure: self.onAjaxFailure_
+  });
+};
+
+/**
+ * Callback dispatcher, invoked when the server responds with
+ * any data at all, dispatches to the various *Callback() functions.
+ *
+ * @param {Array.<Object>} data The server response in the form of a
+ *     list of <code>ClientAction</code> objects.
+ * @private
+ */
+wave.Rpc.prototype.handleRpcResponse_ = function(data) {
+  // Data is a list of client actions to perform.
+  if (data == null) {
+    warn('handleRpcResponse_ called with null data');
+    return;
+  }
+  for (var i = 0; i < data.length; i++) {
+    var clientAction = data[i];
+
+    // Dispatch result based on action name.
+    this.callbacks_[clientAction.action].call(this, clientAction);
+  }
+};
+
+/**
+ * Updates the the time-measure field with the value from the last
+ * action. For example, "Search completed in XX.Xs"
+ *
+ * @param {!Object} data A client action containing processed html
+ *     representing the measurement to be displayed.
+ * @private
+ */
+wave.Rpc.prototype.measureCallback_ = function(data) {
+  this.dataView_.measure(data.html);
+};
+
+/**
+ * Updates the wave version that the client thinks it has. This is generally
+ * done when we have the streaming blip updates set, so we know to request a
+ * diff from the known version next time.
+ *
+ * @param {!Object} data A client action containing the current version of the
+ *     wave being displayed.
+ * @private
+ */
+wave.Rpc.prototype.updateWaveVersionCallback_ = function(data) {
+  if (!this.isCurrentWave_(data.waveId)) {
+    return;
+  }
+
+  // Store the wave version as the current wave version.
+  window.waveOptions_.waveVersion = data.version;
+};
+
+/**
+ * Updates the wave window with an entire pre-rendered wave. Used for
+ * entire wave open, rather than incremental updates/adds of blips.
+ * This function actually pages in the wave, by loading an initial fragment
+ * and then if necessary issuing an immediate background request for the rest
+ * of the conversation.
+ *
+ * @param {!Object} data A client action containing the rendered html
+ *    of the currently open wave conversation.
+ * @private
+ */
+wave.Rpc.prototype.updateWaveCallback_ = function(data) {
+  if (!this.isCurrentWave_(data.waveId)) {
+    return;
+  }
+
+  // Store the version we just fetched.
+  window.waveOptions_.waveVersion = data.version;
+
+  if (window.waveOptions_.page > 0) {
+    this.dataView_.appendConversation(data.html);
+  } else {
+    var hasMore = this.dataView_.insertConversation(data.html);
+    if (hasMore) {
+      // Advance the page and call wave open again (any page > 0 is the
+      // rest of the conversation).
+      window.waveOptions_.page = 1;
+      this.rpcOpenWave();
+    }
+  }
+
+  // Callback various event handlers to say the wave is ready.
+  if (window.embedApi) {
+    window.embedApi.loaded();
+  }
+  if (wave.uiCallbacks_.waveOpened) {
+    wave.uiCallbacks_.waveOpened();
+  }
+};
+
+/**
+ * Updates the wave window header with participant information and avatars.
+ * Replaces any existing content in the header.
+ *
+ * @param {!Object} data A client action object containing the processed html
+ *     with participants and avatars.
+ * @private
+ */
+wave.Rpc.prototype.updateHeaderCallback_ = function(data) {
+  if (!this.isCurrentWave_(data.waveId)) {
+    return;
+  }
+
+  this.dataView_.insertHeader(data.html);
+};
+
+/**
+ * Updates the feed column with newer digest items, inserts
+ * them directly into the feed. Appends these items to the feed
+ * rather than replacing them directly.
+ *
+ * @param {!Object} data A client action containing processed html
+ *     of the entire list of feed items.
+ * @private
+ */
+wave.Rpc.prototype.updateFeedCallback_ = function(data) {
+  this.dataView_.insertFeed(data.html);
+
+  if (wave.uiCallbacks_.feedOpened) {
+    wave.uiCallbacks_.feedOpened();
+  }
+};
+
+/**
+ * Deletes an existing blip from the wave conversation.
+ *
+ * @param {!Object} data A client action object containing a DOM selector
+ *     of the blip id to be deleted.
+ * @private
+ */
+wave.Rpc.prototype.deleteBlipCallback_ = function(data) {
+  // We already have this version.
+  if (this.dataView_.hasNewer(data, $(data.blipId))) {
+    return;
+  }
+
+  this.dataView_.deleteBlip(data.blipId);
+};
+
+/**
+ * Append blip to the current wave conversation. If this blip already
+ * exists in the DOM, perform an update-in-place with the new content
+ * instead.
+ *
+ * @param {!Object} data A client action object containing the blip id
+ *      of the the new blip and processed HTML of its content.
+ * @private
+ */
+wave.Rpc.prototype.addBlipCallback_ = function(data) {
+  // Kill the loading indicator if it's on.
+  if ($('#loading').length > 0) {
+    $('#loading').hide();
+  }
+
+  // If this element already exists, update it in place instead.
+  var selector = '#' + data.blipId;
+  if (this.dataView_.exists(selector)) {
+    data.blipId = selector;
+    this.updateBlipCallback_(data);
+    return;
+  }
+
+  this.dataView_.insertBlip(data.blipId, data.parent, data.indent, data.html,
+      data.version).slideDown();
+};
+
+/**
+ * Update blip in place, with new version. Fades out old content, replace, and
+ * fades in new content.
+ *
+ * @param {!Object} data A client action object containing DOM selector of the
+ *     blip to update, its version for comparison and html content of the new
+ *     state of the blip.
+ * @private
+ */
+wave.Rpc.prototype.updateBlipCallback_ = function(data) {
+  var blip = $(data.blipId);
+
+  // We already have this version.
+  if (this.dataView_.hasNewer(data, $(data.blipId))) {
+    return;
+  }
+
+  this.dataView_.replaceBlip(data.blipId, data.html);
+
+  // Remember this version so we ignore redundant updates.
+  blip.data('version', data.version);
+};


Property changes on: trunk/src/main/webapp/others/splash/js/rpc.js
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/js/rpc_test.js
===================================================================
--- trunk/src/main/webapp/others/splash/js/rpc_test.js	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/js/rpc_test.js	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,310 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * NOTE(dhanji): Edited for readability (temporary).
+ * @fileoverview Unit tests for rpc.js.
+ * @author dhanji at gmail.com (Dhanji R. Prasanna)
+ */
+
+function testMeasureCallback() {
+  var result;
+  var rpc = new wave.Rpc({
+    measure: function(html) {
+      result = html;
+    }
+  });
+
+  // Simulate data coming back from the server.
+  var expected = '<some_html>';
+  rpc.handleRpcResponse_([{
+    action: 'measure',
+    html: expected
+  }]);
+
+  assertEquals(expected, result);
+}
+
+
+function testUpdateWaveVersion() {
+  window = {};
+  window.waveOptions_ = {};
+  window.waveOptions_.waveId = 'aWaveId';
+
+  var rpc = new wave.Rpc({});
+
+  // Simulate data coming back from the server.
+  var expectedVersion = 1234567;
+  rpc.handleRpcResponse_([{
+    action: 'update-wave-version',
+    waveId: 'aWaveId',
+    version: expectedVersion
+  }]);
+
+  assertEquals(expectedVersion, window.waveOptions_.waveVersion);
+}
+
+
+function testUpdateWaveAppendsToConversation() {
+  window = {};
+  window.waveOptions_ = {};
+  window.waveOptions_.waveId = 'aWaveId';
+  window.waveOptions_.page = 1; // Forces append rather than replace.
+
+  var result;
+  var rpc = new wave.Rpc({
+    appendConversation: function(html) {
+      result = html;
+    }
+  });
+
+  // Simulate data coming back from the server.
+  var expectedVersion = 12345678;
+  var expectedHtml = '<some_html>';
+  rpc.handleRpcResponse_([{
+    action: 'update-wave',
+    waveId: 'aWaveId',
+    version: expectedVersion,
+    html: expectedHtml
+  }]);
+
+  // Ensure version was updated too.
+  assertEquals(expectedVersion, window.waveOptions_.waveVersion);
+  assertEquals(expectedHtml, result);
+}
+
+
+function testUpdateWaveInsertsConversationOnePage() {
+  window = {};
+  window.waveOptions_ = {};
+  window.waveOptions_.waveId = 'aWaveId';
+  window.waveOptions_.page = 0; // Forces replace conversation.
+
+  // Test on-wave opened callbacks too.
+  var embedApiSignaled = false, waveOpenCalled = false;
+  window.embedApi = {};
+  window.embedApi.loaded = function() {
+    embedApiSignaled = true;
+  };
+  window.wave.uiCallbacks_ = {};
+  window.wave.uiCallbacks_.waveOpened = function() {
+    waveOpenCalled = true;
+  };
+
+  var result;
+  var rpc = new wave.Rpc({
+    insertConversation: function(html) {
+      result = html;
+      return false; // Only one page exists.
+    }
+  });
+
+  // Simulate data coming back from the server.
+  var expectedVersion = 125678;
+  var expectedHtml = '<some_other_html_1>';
+  rpc.handleRpcResponse_([{
+    action: 'update-wave',
+    waveId: 'aWaveId',
+    version: expectedVersion,
+    html: expectedHtml
+  }]);
+
+  // Ensure version was updated too.
+  assertEquals(expectedVersion, window.waveOptions_.waveVersion);
+  assertEquals(expectedHtml, result);
+
+  // Page should not have advanced.
+  assertEquals(0, window.waveOptions_.page);
+
+  // Callbacks should fire.
+  assertTrue(embedApiSignaled);
+  assertTrue(waveOpenCalled);
+}
+
+
+function testUpdateWaveInsertsConversationManyPages() {
+  window = {};
+  window.waveOptions_ = {};
+  window.waveOptions_.waveId = 'aWaveId';
+  window.waveOptions_.page = 0; // Forces replace conversation.
+
+  // Mock Jquery ajax function
+  var ajaxPostData;
+  window.$ = {};
+  window.$.ajax = function(data) {
+    ajaxPostData = data;
+  };
+
+  var result;
+  var rpc = new wave.Rpc({
+    insertConversation: function(html) {
+      result = html;
+      return true; // Triggers load of additional page
+    }
+  });
+
+  // Simulate data coming back from the server.
+  var expectedVersion = 125678;
+  var expectedHtml = '<some_other_html>';
+  rpc.handleRpcResponse_([{
+    action: 'update-wave',
+    waveId: 'aWaveId',
+    version: expectedVersion,
+    html: expectedHtml
+  }]);
+
+  // Ensure version was updated too.
+  assertEquals(expectedVersion, window.waveOptions_.waveVersion);
+  assertEquals(expectedHtml, result);
+
+  // Page should have advanced
+  assertEquals(1, window.waveOptions_.page);
+
+  // Assert the right RPC was called for the second page
+  assertEquals(window.waveOptions_, ajaxPostData.data);
+  assertEquals('POST', ajaxPostData.type);
+}
+
+
+function testUpdateWaveHeader() {
+  window = {};
+  window.waveOptions_ = {};
+  window.waveOptions_.waveId = 'aWaveId';
+
+  var result;
+  var rpc = new wave.Rpc({
+    insertHeader: function(html) {
+      result = html;
+    }
+  });
+
+  // Simulate data coming back from the server.
+  var expected = '<some_header_html>';
+  rpc.handleRpcResponse_([{
+    action: 'update-header',
+    waveId: 'aWaveId',
+    html: expected
+  }]);
+
+  assertEquals(expected, result);
+}
+
+
+function testUpdateFeed() {
+  window = {};
+  window.wave.uiCallbacks_ = {};
+  var feedOpenCalled = false;
+  window.wave.uiCallbacks_.feedOpened = function() {
+    feedOpenCalled = true;
+  };
+
+  var result;
+  var rpc = new wave.Rpc({
+    insertFeed: function(html) {
+      result = html;
+    }
+  });
+
+  // Simulate data coming back from the server.
+  var expected = '<some_feed_html>';
+  rpc.handleRpcResponse_([{
+    action: 'update-feed',
+    html: expected
+  }]);
+
+  assertEquals(expected, result);
+  assertTrue(feedOpenCalled);
+}
+
+
+function testDeleteBlipOnNewerVersion() {
+  // Mock the jquery version discovery logic.
+  var expectedBlipId = 'aBlipId';
+  var expectedVersion = 7658;
+  $ = function(blipId) {
+    if (expectedBlipId = blipId) {
+      return {
+        data: function(arg) {
+          if ('version' == arg) {
+            expectedVersion - 1; /* -1 version should trigger a delete */
+          }
+        }
+      };
+    }
+  };
+
+  var toDelete;
+  var rpc = new wave.Rpc({
+    deleteBlip: function(blipId) {
+      toDelete = blipId;
+    },
+    hasNewer: function(data, blip) {
+      return false;
+    }
+  });
+
+  // Simulate data coming back from the server.
+  rpc.handleRpcResponse_([{
+    action: 'delete-blip',
+    blipId: 'aBlipId',
+    version: expectedVersion
+  }]);
+
+  assertEquals(expectedBlipId, toDelete);
+}
+
+
+function testUpdateBlip() {
+  var expectedBlipId = 'aBlipId';
+  var expectedHtml = '<a_replaced_blip>';
+  var expectedVersion = 128973;
+
+  var updatedVersion;
+  $ = function() {
+    return {
+      data: function(arg, version) {
+        if ('version' == arg) {
+          updatedVersion = version;
+        }
+      }
+    };
+  };
+
+  var replacedBlipId;
+  var replacedHtml;
+  var rpc = new wave.Rpc({
+    replaceBlip: function(blipId, html) {
+      replacedBlipId = blipId;
+      replacedHtml = html;
+    },
+    hasNewer: function(data, blip) {
+      return false;
+    }
+  });
+
+  // Simulate data coming back from the server.
+  rpc.handleRpcResponse_([{
+    action: 'update-blip',
+    blipId: 'aBlipId',
+    html: expectedHtml,
+    version: expectedVersion
+  }]);
+
+  assertEquals(expectedVersion, updatedVersion);
+  assertEquals(expectedBlipId, replacedBlipId);
+  assertEquals(expectedHtml, replacedHtml);
+}


Property changes on: trunk/src/main/webapp/others/splash/js/rpc_test.js
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/mobile_client.html
===================================================================
--- trunk/src/main/webapp/others/splash/mobile_client.html	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/mobile_client.html	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+    "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+  <title>Google Wave Splash v1.1</title>
+  <link rel="stylesheet" href="style/main.css">
+  <link rel="stylesheet" href="style/mobile.css">
+  <link rel="stylesheet" type="text/css" href="style/jquery.lightbox-0.5.css" media="screen">
+
+  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
+  <script type="text/javascript" src="js/jquery.lightbox-0.5.min.js"></script>
+  <script type="text/javascript"
+          src="http://wave.google.com/gadgets/js/core:rpc.js?debug=1&c=1"></script>
+
+  <!-- [MINIFY] -->
+  <script type="text/javascript" src="js/editor.js"></script>
+  <script type="text/javascript" src="js/gadget.js"></script>
+  <script type="text/javascript" src="js/rpc.js"></script>
+  <script type="text/javascript" src="js/common_client.js"></script>
+  <script type="text/javascript" src="js/mobile_client.js"></script>
+  <!-- [END_MINIFY] -->
+  <script type="text/javascript">
+    var BOOTSTRAP = {
+      'email': '@{email}',
+      'displayName': '@{displayName}'
+    };
+  </script>
+  <meta name="viewport" content="user-scalable=no" width="device-width" />
+</head>
+<body>
+
+<div id="header">
+  <div id="headerInner">
+    <table id="headerLayout" cellspacing="0" summary="">
+      <tr>
+        <td id="tdLogo">
+          <div id="logo"></div>
+        </td>
+        <td>
+          <div class="mobile-button">
+            <a href="#"><span id="main-button">New Wave</span></a>
+          </div>
+        </td>
+
+        <td id="tdSearchToggle" style="vertical-align:bottom;">
+          <img id="searchToggle" src="images/search_small_button.png" />
+        </td>
+        <td id="td-logout">
+          <div class="mobile-button">
+            <a id="logout" href="/logout">
+              <span>Sign out</span>
+            </a>
+          </div>
+        </td></tr>
+    </table>
+  </div>
+  <!-- /#headerInner" -->
+
+  <div id="headerSearch">
+    <table id="search" cellspacing="0" summary="">
+      <tr>
+        <td>
+          <input id="searchField" name="searchField" value="Search your waves"/>
+        </td>
+        <td id="searchButton">
+          <span><span>Go</span></span>
+        </td>
+      </tr>
+    </table>
+  </div>
+  <!-- /#headerSearch" -->
+
+<!-- /#header -->
+
+</div>
+
+<div id="content">
+  <div id="wave" class="wave-window">
+    <div class="header" style="display:none"></div>
+    <div id="conversation"></div>
+  </div>
+
+  <div id="feed" class="feed">
+
+    <div id="loading-wrapper">
+      <img id="feed-loading" src="images/loading.gif" alt="Loading feed contents...">
+    </div>
+
+    <div id="more-feed" class="more-button">Show More...</div>
+  </div>
+</div>
+
+</body>
+</html>


Property changes on: trunk/src/main/webapp/others/splash/mobile_client.html
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/permalink_client.html
===================================================================
--- trunk/src/main/webapp/others/splash/permalink_client.html	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/permalink_client.html	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,92 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+    "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+  <title>Google Wave Splash</title>
+  <!-- TODO: FIX THE PATHS BEFORE CHECKING IN -->
+  <link rel="stylesheet" type="text/css" href="@{pathToRoot}style/permalink.css">
+
+  <!--[if lte IE 7]>
+  <link rel="stylesheet" type="text/css" href="@{pathToRoot}style/permalink_ie.css">
+  <![endif]-->
+
+  <style type="text/css" media="screen">@{style}</style>
+  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
+  <script type="text/javascript" src="@{pathToRoot}js/jquery.lightbox-0.5.min.js"></script>
+
+  <!-- [MINIFY] -->
+  <!-- please preserve this order: gadgets, rpc, permalink_client -->
+  <script type="text/javascript" src="@{pathToRoot}js/gadget.js"></script>
+  <script type="text/javascript" src="@{pathToRoot}js/rpc.js"></script>
+  <script type="text/javascript" src="@{pathToRoot}js/common_client.js"></script>
+  <script type="text/javascript" src="@{pathToRoot}js/permalink_client.js"></script>
+  <!-- [END_MINIFY] -->
+
+  <script type="text/javascript" src="http://wave.google.com/gadgets/js/core:rpc.js?c=1"></script>
+
+  @if{embedded}
+  <script type="text/javascript" src="@{pathToRoot}js/embed_support.js"></script>
+  @end{}
+
+  <!--[if IE 6]>
+  <script type="text/javascript" src="@{pathToRoot}/js/ie6sucks.js"></script>
+  <![endif]-->
+</head>
+<body at if{embedded} class="embedded"@end{}>
+<div id="wave" class="wave-window" wave_id="@{waveId}"
+    show_header="@{showHeader}">
+ at if{embedded}
+  <div id="share-popup" class="popup">
+    <div class="popup-pointer"></div>
+    <a class="dialog-close" href="#"><span>Close</span></a>
+    <label for="share-popup-link">Copy this link:</label><div class="input-wrapper"><input id="share-popup-link" type="text" value="@{waveLink}"></div>
+    <div class="separator"><em>OR</em></div>
+    <label for="share-popup-embed">Paste this HTML to embed:</label><div class="input-wrapper"><input id="share-popup-embed" type="text" value="@{waveEmbed}"></div>
+    <div id="share-popup-wave-id">ID: @{waveId}</div>
+  </div>
+  <div id="frame">
+    <div id="header">
+      <div id="headerInner">
+        <div id="logo">
+          Google Wave
+        </div>
+        <ul id="menu">
+          <li class="first">
+            Anonymous
+          </li>
+          @if{showLoginLink}
+          <li>
+            <a href="@{waveLink}" target="_blank">View in Google Wave</a>
+          </li>
+          @end{}
+          <li id="shareLink">
+            <a id="share-link" href="#">Share this wave</a>
+          </li>
+        </ul>
+        <div id="participants">
+          <h3>Participants:</h3>
+          <div id="wave-header"><span style="font-weight:normal;">Loading...</span></div>
+        </div>
+      </div> <!-- /#headerInner -->
+    </div> <!-- /#header -->
+    <div id="content">
+      <div id="contentInner">
+        <div id="contentInner2">
+          <div id="contentInner3" class="styleable">
+ at end{}
+  <div id="conversation">
+    @if{content == ''}
+    <img id="wave-loading" src="@{pathToRoot}images/loading_permalink.gif" alt="Loading...">
+    @end{}
+    @{content}
+  </div>
+ at if{embedded}
+          </div> <!-- /#contentInner3 -->
+        </div> <!-- /#contentInner2 -->
+      </div> <!-- /#contentInner -->
+    </div> <!-- /#content -->
+  </div> <!-- /#frame -->
+ at end{}
+</div>
+</body>
+</html>


Property changes on: trunk/src/main/webapp/others/splash/permalink_client.html
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/rpc_relay.html
===================================================================
--- trunk/src/main/webapp/others/splash/rpc_relay.html	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/rpc_relay.html	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,3 @@
+<script>
+var u = location.href, h = u.substr(u.indexOf('#') + 1).split('&'), t, r;try {t = h[0] === '..' ? parent.parent : parent.frames[h[0]];r = t.gadgets.rpc.receive;} catch (e) {}r && r(h);
+</script>


Property changes on: trunk/src/main/webapp/others/splash/rpc_relay.html
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/style/border-radius.htc
===================================================================
--- trunk/src/main/webapp/others/splash/style/border-radius.htc	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/style/border-radius.htc	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,143 @@
+--Do not remove this if you are using--
+Original Author: Remiz Rahnas
+Original Author URL: http://www.htmlremix.com
+Published date: 2008/09/24
+
+Changes by Nick Fetchak:
+- IE8 standards mode compatibility
+- VML elements now positioned behind original box rather than inside of it - should be less prone to breakage
+Published date : 2009/11/18
+
+
+<public:attach event="oncontentready" onevent="oncontentready('v08vnSVo78t4JfjH')" />
+<script type="text/javascript">
+
+// findPos() borrowed from http://www.quirksmode.org/js/findpos.html
+function findPos(obj) {
+	var curleft = curtop = 0;
+
+	if (obj.offsetParent) {
+		do {
+			curleft += obj.offsetLeft;
+			curtop += obj.offsetTop;
+		} while (obj = obj.offsetParent);
+	}
+
+	return({
+		'x': curleft,
+		'y': curtop
+	});
+}
+
+function oncontentready(classID) {
+  if (this.className.match(classID)) { return(false); }
+
+	if (!document.namespaces.v) { document.namespaces.add("v", "urn:schemas-microsoft-com:vml"); }
+
+	this.className = this.className.concat(' ', classID);
+	var arcSize = Math.min(parseInt(this.currentStyle['-moz-border-radius'] ||
+	                                this.currentStyle['-webkit-border-radius'] ||
+	                                this.currentStyle['border-radius'] ||
+	                                this.currentStyle['-khtml-border-radius']) /
+	                       Math.min(this.offsetWidth, this.offsetHeight), 1);
+	var fillColor = this.currentStyle.backgroundColor;
+	var fillSrc = this.currentStyle.backgroundImage.replace(/^url\("(.+)"\)$/, '$1');
+	var strokeColor = this.currentStyle.borderColor;
+	var strokeWeight = parseInt(this.currentStyle.borderWidth);
+	var stroked = 'true';
+	if (isNaN(strokeWeight)) {
+		strokeWeight = 0;
+		strokeColor = fillColor;
+		stroked = 'false';
+	}
+
+	this.style.background = 'transparent';
+	this.style.borderColor = 'transparent';
+
+	// Find which element provides position:relative for the target element (default to BODY)
+	var el = this;
+	var limit = 100, i = 0;
+	while ((typeof(el) != 'unknown') && (el.currentStyle.position != 'relative') && (el.tagName != 'BODY')) {
+		el = el.parentElement;
+		i++;
+		if (i >= limit) { return(false); }
+	}
+	var el_zindex = parseInt(el.currentStyle.zIndex);
+	if (isNaN(el_zindex)) { el_zindex = 0; }
+	//alert('got tag '+ el.tagName +' with pos '+ el.currentStyle.position);
+
+	var rect_size = {
+		'width': this.offsetWidth - strokeWeight,
+		'height': this.offsetHeight - strokeWeight
+	};
+	var el_pos = findPos(el);
+	var this_pos = findPos(this);
+	this_pos.y = this_pos.y + (0.5 * strokeWeight) - el_pos.y;
+	this_pos.x = this_pos.x + (0.5 * strokeWeight) - el_pos.x;
+
+	var rect = document.createElement('v:roundrect');
+	rect.arcsize = arcSize +'px';
+	rect.strokecolor = strokeColor;
+	rect.strokeWeight = strokeWeight +'px';
+	rect.stroked = stroked;
+	rect.style.display = 'block';
+	rect.style.position = 'absolute';
+	rect.style.top = this_pos.y +'px';
+	rect.style.left = this_pos.x +'px';
+	rect.style.width = rect_size.width +'px';
+	rect.style.height = rect_size.height +'px';
+	rect.style.antialias = true;
+	rect.style.zIndex = el_zindex - 1;
+
+	var fill = document.createElement('v:fill');
+	fill.color = fillColor;
+	fill.src = fillSrc;
+	fill.type = 'tile';
+
+	rect.appendChild(fill);
+	el.appendChild(rect);
+
+	var css = el.document.createStyleSheet();
+	css.addRule("v\\:roundrect", "behavior: url(#default#VML)");
+	css.addRule("v\\:fill", "behavior: url(#default#VML)");
+
+	isIE6 = /msie|MSIE 6/.test(navigator.userAgent);
+	// IE6 doesn't support transparent borders, use padding to offset original element
+	if (isIE6 && (strokeWeight > 0)) {
+		this.style.borderStyle = 'none';
+		this.style.paddingTop = parseInt(this.currentStyle.paddingTop || 0) + strokeWeight;
+		this.style.paddingBottom = parseInt(this.currentStyle.paddingBottom || 0) + strokeWeight;
+	}
+
+	if (typeof(window.rounded_elements) == 'undefined') {
+		window.rounded_elements = new Array();
+
+		if (typeof(window.onresize) == 'function') { window.previous_onresize = window.onresize; }
+		window.onresize = window_resize;
+	}
+	this.element.vml = rect;
+	window.rounded_elements.push(this.element);
+}
+
+function window_resize() {
+	if (typeof(window.rounded_elements) == 'undefined') { return(false); }
+
+	for (var i in window.rounded_elements) {
+		var el = window.rounded_elements[i];
+
+		var strokeWeight = parseInt(el.currentStyle.borderWidth);
+		if (isNaN(strokeWeight)) { strokeWeight = 0; }
+
+		var parent_pos = findPos(el.vml.parentNode);
+		var pos = findPos(el);
+		pos.y = pos.y + (0.5 * strokeWeight) - parent_pos.y;
+		pos.x = pos.x + (0.5 * strokeWeight) - parent_pos.x;
+
+		el.vml.style.top = pos.y +'px';
+		el.vml.style.left = pos.x +'px';
+	}
+
+	if (typeof(window.previous_onresize) == 'function') { window.previous_onresize(); }
+}
+</script>
+


Property changes on: trunk/src/main/webapp/others/splash/style/border-radius.htc
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/src/main/webapp/others/splash/style/jquery.lightbox-0.5.css
===================================================================
--- trunk/src/main/webapp/others/splash/style/jquery.lightbox-0.5.css	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/style/jquery.lightbox-0.5.css	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,112 @@
+/**
+ * jQuery lightBox plugin
+ * This jQuery plugin was inspired and based on Lightbox 2 by Lokesh Dhakar (http://www.huddletogether.com/projects/lightbox2/)
+ * and adapted to me for use like a plugin from jQuery.
+ * @name jquery-lightbox-0.5.css
+ * @author Leandro Vieira Pinho - http://leandrovieira.com
+ * @version 0.5
+ * @date April 11, 2008
+ * @category jQuery plugin
+ * @copyright (c) 2008 Leandro Vieira Pinho (leandrovieira.com)
+ * @license CC Attribution-No Derivative Works 2.5 Brazil - http://creativecommons.org/licenses/by-nd/2.5/br/deed.en_US
+ * @example Visit http://leandrovieira.com/projects/jquery/lightbox/ for more informations about this jQuery plugin
+ */
+#jquery-overlay {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 90;
+  width: 100%;
+  height: 500px;
+}
+#jquery-lightbox {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  z-index: 100;
+  text-align: center;
+  line-height: 0;
+}
+#jquery-lightbox a img {
+  border: none;
+}
+#lightbox-container-image-box {
+  position: relative;
+  background-color: #fff;
+  width: 250px;
+  height: 250px;
+  margin: 0 auto;
+}
+
+#lightbox-container-image {
+  padding: 10px;
+}
+#lightbox-loading {
+  position: absolute;
+  top: 40%;
+  left: 0%;
+  height: 25%;
+  width: 100%;
+  text-align: center;
+  line-height: 0;
+}
+#lightbox-nav {
+  position: absolute;
+  top: 0;
+  left: 0;
+  height: 100%;
+  width: 100%;
+  z-index: 10;
+}
+#lightbox-container-image-box>#lightbox-nav {
+  left: 0;
+}
+#lightbox-nav a {
+  outline: none;
+}
+#lightbox-nav-btnPrev,#lightbox-nav-btnNext {
+  width: 49%;
+  height: 100%;
+  zoom: 1;
+  display: block;
+}
+#lightbox-nav-btnPrev {
+  left: 0;
+  float: left;
+}
+#lightbox-nav-btnNext {
+  right: 0;
+  float: right;
+}
+#lightbox-container-image-data-box {
+  font: 10px Verdana, Helvetica, sans-serif;
+  background-color: #fff;
+  margin: 0 auto;
+  line-height: 1.4em;
+  overflow: auto;
+  width: 100%;
+  padding: 0 10px 0;
+}
+#lightbox-container-image-data {
+  padding: 0 10px;
+  color: #666;
+}
+#lightbox-container-image-data #lightbox-image-details {
+  width: 70%;
+  float: left;
+  text-align: left;
+}
+#lightbox-image-details-caption {
+  font-weight: bold;
+}
+#lightbox-image-details-currentNumber {
+  display: block;
+  clear: left;
+  padding-bottom: 1.0em;
+}
+#lightbox-secNav-btnClose {
+  width: 66px;
+  float: right;
+  padding-bottom: 0.7em;
+}
\ No newline at end of file


Property changes on: trunk/src/main/webapp/others/splash/style/jquery.lightbox-0.5.css
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/style/main.css
===================================================================
--- trunk/src/main/webapp/others/splash/style/main.css	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/style/main.css	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,236 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/* GENERAL ------------------------------------------------------------------ */
+
+/* Zero default margin & padding around common elements */
+body, dd, dl, dt, fieldset, form, h1, h2, h3, h4, h5, h6, li, ol, p, ul {
+  margin: 0;
+  border: 0 none #FFFFFF;
+  padding: 0;
+}
+
+body {
+  overflow: hidden; /** HACK(dhanji): HEEEEELP! Horiz Scrollbar of doom **/
+  background-color: #ffffff;
+  color: #000000;
+  line-height: 1.4;
+  font-family: Helvetica, Arial, sans-serif;
+  font-size: 12px;
+}
+
+a {
+  color: #0066CC;
+  text-decoration: underline;
+}
+
+a:visited {
+  color: #0066CC;
+}
+
+a:hover {
+  text-decoration: none;
+}
+
+img {
+  border: 0 none transparent;
+}
+
+input, select, table, textarea {
+  font-size: 100%;
+  font-family: Arial, Helvetica, sans-serif;
+}
+
+/* MAIN --------------------------------------------------------------------- */
+
+#header {
+  position: relative;
+  z-index: 2;
+  background-color: #202020;
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#4c4c4c), to(#191919));
+  background-image: -moz-linear-gradient(top, #4c4c4c, #191919);
+  -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, 0.35);
+  -moz-box-shadow: 0 4px 5px rgba(0, 0, 0, 0.35);
+}
+
+#headerInner {
+  height: 70px;
+  border-right: 0 none #ffffff;
+}
+
+#headerLayout {
+  width: 100%;
+}
+
+#headerLayout td {
+  padding: 0;
+  vertical-align: top;
+}
+
+#headerSearch {
+  width: 100%;
+  padding: 0 10px 0 0 !important;
+}
+
+h1 {
+  float: left;
+  width: 180px;
+  height: 43px;
+  margin: 6px 10px 0 10px;
+  background-image: url(../images/logo_on_black.png);
+  background-repeat: no-repeat;
+}
+
+h1 a {
+  display: block;
+  text-indent: -9999px;
+  text-decoration: none;
+}
+
+#td-logo {
+  width: 77px;
+}
+
+.button a {
+  display: block;
+  margin: 22px 7px 0 0;
+  border: 1px solid #191919;
+  border-radius: 3px;
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  color: #ffffff;
+  white-space: nowrap;
+  text-decoration: none;
+}
+
+.button a span {
+  display: block;
+  height: 23px;
+  border-top: 1px solid #7f7f7f;
+  border-left: 1px solid #7f7f7f;
+  border-radius: 3px;
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  padding: 0 7px 0 7px;
+  background-color: #333333;
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#666666), to(#333333));
+  background-image: -moz-linear-gradient(top, #666666, #333333);
+  line-height: 24px;
+  text-align: center;
+}
+
+#search {
+  width: 100%;
+  height: 25px;
+  margin: 2px 0 0 0px;
+  background-image: url(../images/search_field_on_black_left.png);
+  background-repeat: no-repeat;
+}
+
+td.headerAlert {
+  width: 100%;
+}
+
+/** Alert bar **/
+div.highlight {
+  float: right;
+  overflow: hidden;
+  margin: 20px 36px 0 0;
+
+  -webkit-border-radius: 6px;
+  -moz-border-radius: 6px;
+  border-top: 1px solid #000;
+  border-bottom: 1px solid #cecece;
+}
+
+#alert {
+  float: left;
+  font-size: 1.1em;
+  display: none;
+
+  padding: 3px 16px 2px 16px; /*border: 1px solid #000;*/
+  cursor: pointer;
+
+  -webkit-border-radius: 6px;
+  -moz-border-radius: 6px;
+
+  background-color: #eede54;
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0.0, #f5eca1), color-stop(1.0, #eede54));
+}
+
+#measure {
+  position: absolute;
+  color: #aaa;
+  right: 10px;
+  bottom: 2px;
+}
+
+#search td {
+  width: 100%;
+  padding: 0 0 0 20px;
+}
+
+#search input {
+  display: block;
+  height: 25px;
+  width: 100%;
+  margin: 0;
+  border: 0 none #ffffff;
+  padding: 0 0 0 4px;
+  outline: 0 none #ffffff;
+  background-color: #ffffff;
+  background-image: url(../images/search_field_on_black.png);
+  color: #999999;
+  line-height: 26px;
+}
+
+#search input.clicked {
+  color: #000000;
+}
+
+#search #searchButton {
+  width: auto;
+  padding: 0 0 0 2px;
+  background-repeat: no-repeat;
+  color: #ffffff;
+  cursor: pointer;
+}
+
+#searchButton span {
+  display: block;
+  height: 25px;
+  padding: 0 12px 0 0;
+  background-image: url(../images/search_field_on_black_button_right.png);
+  background-repeat: no-repeat;
+  background-position: 100% 0;
+  line-height: 26px;
+}
+
+#searchButton span span {
+  padding: 0 4px 0 11px;
+  background-image: url(../images/search_field_on_black_button.png);
+  background-repeat: repeat-x;
+}
+
+#content {
+  z-index: 1;
+  left: 0;
+  right: 0;
+  top: 70px;
+  bottom: 0;
+  overflow: auto;
+}


Property changes on: trunk/src/main/webapp/others/splash/style/main.css
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/style/mobile.css
===================================================================
--- trunk/src/main/webapp/others/splash/style/mobile.css	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/style/mobile.css	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,361 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/** Alternate stylesheet for android, iphone + mobile browsers **/
+
+body {
+  font-family: Arial, sans-serif;
+  font-size: 10pt;
+}
+
+a img input {
+  -webkit-tap-highlight-color: rgba(0,0,0,0);
+}
+
+#logo {
+  background-image: url(../images/logo_small.png);
+  float: left;
+  height: 43px;
+  margin: 6px 10px;
+  width: 77px;
+}
+
+.feed {
+  position: absolute;
+  background: #b5b9c2;
+  margin: 0;
+  width: 100%;
+  overflow: auto;
+}
+
+.feed .item {
+  overflow: hidden;
+  padding: 7px 7px 10px 7px;
+  border-bottom: 1px solid #999;
+  background: white;
+  position: relative;
+  cursor: pointer;
+}
+
+.feed .read {
+  background: #eaeaea !important;
+}
+
+.feed .item img.icon {
+  float: left;
+  padding-right: 6px;
+  padding-left: 6px;
+}
+
+.feed .item .title {
+  -moz-border-radius: 5px;
+  border-radius: 5px;
+  background: #C9E2FC;
+  font-weight: bold;
+  padding: 2px 6px;
+}
+
+.feed .item .time {
+  color: #9a9a9a;
+  float: right;
+  text-align: right;
+  font-weight: bold;
+  font-size: 75%;
+  padding: 4px 6px 0px 0px;
+}
+
+.read > .time {
+  color: #999;
+}
+
+.feed .item .avatar {
+  border: 3px solid #ccc;
+  border-radius: 3px 3px;
+  -moz-border-radius: 3px 3px;
+  float: left;
+  margin: 0 5px 2px 0;
+}
+
+.avatar img {
+  width: 32px;
+  height: 32px;
+  border: 1px solid #fff;
+}
+
+.messages {
+  border-radius: 3px 3px;
+  -moz-border-radius: 3px 3px;
+  background: #bdbdbd;
+  color: #fff;
+  font-size: 70%;
+  font-weight: bold;
+  margin: 3px 3px 3px 0px;
+  padding: 2px 4px 0px 4px;
+  float:right;
+}
+
+/** wave **/
+
+#conversation {
+  padding: 24px 6px06px 6px;
+}
+
+#conversation .blip {
+  position: relative;
+  right: 0;
+  overflow: hidden;
+  padding: 8px 0;
+  margin-top: -8px;
+}
+
+#conversation .blip:first-child {
+  border: none;
+}
+
+#conversation .blip div.left {
+  width: 95%;
+}
+
+#conversation .blip .authorbar {
+  float: left;
+  margin: 10px 5px 0px 3px;
+
+  background: #e5e5e5;
+
+  padding: 3px 4px;
+  -webkit-border-top-right-radius: 4px;
+  -webkit-border-top-left-radius: 4px;
+  -moz-border-radius-bottomleft: 4px;
+  -moz-border-radius-topleft: 4px;
+}
+
+#conversation .blip .author {
+  float: right;
+  padding: 2px 6px;
+
+  font-weight: bold;
+  text-shadow: -1px -1px 1px #555;
+  color: white;
+}
+
+#conversation .blip .author {
+  width: 100%;
+}
+
+#conversation .blip .author img {
+  float: left;
+  height: 32px;
+  width: 32px;
+}
+
+#conversation .blip .author .name {
+  float: right;
+}
+
+.author-more {
+  float: right;
+  clear: both;
+}
+
+.author-count-1 {
+  min-height: 24px;
+}
+
+.author-count-2 {
+  min-height: 45px;
+}
+
+.author-count-3 {
+  min-height: 136px;
+}
+
+.author-count-many {
+  min-height: 55px;
+}
+
+#conversation .blip div.left .toolbar {
+  display: none;
+  position: absolute;
+  margin: 16px 12px 0 0;
+  padding: 2px 4px 0 4px;
+  right: 0;
+
+  background: #fff;
+  -webkit-border-radius: 4px;
+  -webkit-box-shadow: 2px 2px 4px #111;
+  -moz-border-radius: 4px;
+  -moz-box-shadow: 2px 2px 4px #111;
+}
+
+.indent {
+  padding-left: 40px;
+}
+
+.unread {
+  background: #7aa2f2 !important;
+  color: #eee !important;
+}
+
+#conversation .blip div.right {
+  float: left;
+  width: 95%;
+  padding: 12px 12px 24px 12px;
+  margin: 0 auto;
+
+  -webkit-border-radius: 6px;
+  -moz-border-radius: 6px;
+  border-radius: 6px;
+
+  -webkit-box-shadow: 2px 2px 8px #000;
+  -moz-box-shadow: 2px 2px 8px #000;
+  background: white;
+}
+
+#conversation .blip div.right .time {
+  float: right;
+  font-size: 94%;
+  color: #999;
+}
+
+div.wave-window {
+  right: 0;
+  overflow: auto;
+  width: 100%;
+  height: 100%;
+  /*margin: 2px 0; *//** TODO:gradient for moz/IE **/
+  background-image: url('../images/background_dot.png');
+}
+
+.header {
+  background-color: #dfe3eb;
+
+  padding: 16px 12px 16px 24px;
+  margin: 0 auto;
+
+  -webkit-box-shadow: 2px 2px 8px #000;
+  -moz-box-shadow: 2px 2px 8px #000;
+}
+
+/** markup in text**/
+span.title {
+  font-weight: bold;
+}
+
+.avatar img {
+  width: 32px;
+  height: 32px;
+}
+
+.avatar .name {
+  margin: 0 5px;
+}
+
+.mobile-button a {
+  float: left;
+  margin: 22px 7px 0 0;
+  border: 1px solid #191919;
+  border-radius: 3px;
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  color: #ffffff;
+  white-space: nowrap;
+  text-decoration: none;
+}
+
+.mobile-button a span {
+  display: block;
+  height: 23px;
+  border-top: 1px solid #7f7f7f;
+  border-left: 1px solid #7f7f7f;
+  border-radius: 3px;
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  padding: 0 7px 0 7px;
+  background-color: #333333;
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#666666), to(#333333));
+  background-image: -moz-linear-gradient(top, #666666, #333333);
+  line-height: 24px;
+}
+
+.more-button {
+  margin: 8px auto;
+  width: 100px;
+
+  color: #333;
+  padding: 4px 14px;
+  -webkit-border-radius: 4px;
+  -moz-border-radius: 4px;
+
+  background: #EDEDED;
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0.0, #FFF),
+  color-stop(0.7, #FEFEFE), color-stop(1.0, #EDEDED));
+}
+
+/** TODO(dhanji): Clean this up later when we reconcile stuff and main.css for all clients **/
+#search-container {
+  background-color: #202020;
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#4c4c4c), to(#191919));
+  background-image: -moz-linear-gradient(top, #4c4c4c, #191919);
+  -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, 0.35);
+  -moz-box-shadow: 0 4px 5px rgba(0, 0, 0, 0.35);
+}
+
+#search {
+  width: 200px;
+}
+
+#headerSearch {
+  display: none;
+  margin: -15px auto 0px;
+  padding: 10px 0px !important;
+  width: 200px;
+}
+
+#tdSearchToggle {
+  text-align: center;
+}
+
+#td-logout {
+  padding: 10px 0px 0px 0px;
+  text-align: right;
+}
+
+#td-logout .mobile-button {
+float:right;
+}
+
+#logout {
+  color: #fff;
+  text-decoration: none;
+}
+
+#logout span {
+  background-color: #111111;
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#333333), to(#111111));
+  background-image: -moz-linear-gradient(top, #333333, #111111);
+}
+
+
+#loading-wrapper {
+  position: relative;
+  text-align: center;
+}
+
+#feed-loading, #wave-loading {
+  margin: 30px auto 0px auto;
+  text-align: center;
+}


Property changes on: trunk/src/main/webapp/others/splash/style/mobile.css
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/style/orig-style.css
===================================================================
--- trunk/src/main/webapp/others/splash/style/orig-style.css	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/style/orig-style.css	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,417 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+.header .title {
+  float: left;
+}
+
+.control-icon {
+  float: right;
+  width: 14px;
+  margin-left: 6px;
+  cursor: pointer;
+  cursor: hand;
+}
+
+.wnd-min {
+  background-image: url('../images/minimize_window.png')
+}
+
+.wnd-close {
+  background-image: url('../images/close_window.png')
+}
+
+.conversation {
+  padding: 24px 6px 206px 6px;
+}
+
+.conversation .blip {
+  position: relative;
+  right: 0;
+  overflow: hidden;
+  padding: 8px 0;
+  margin-top: -8px;
+}
+
+.conversation .blip:first-child {
+  border: none;
+}
+
+.conversation .blip div.left {
+  float: left;
+  width: 20%;
+}
+
+.conversation .blip .authorbar {
+  float: right;
+  margin: 12px 0 0 0;
+
+  background: #333;
+
+  padding: 3px 4px;
+  -webkit-border-bottom-left-radius: 4px;
+  -webkit-border-top-left-radius: 4px;
+  -moz-border-radius-bottomleft: 4px;
+  -moz-border-radius-topleft: 4px;
+}
+
+.conversation .blip .author {
+  float: right;
+  padding: 2px 6px;
+
+  font-weight: bold;
+  text-shadow: -1px -1px 1px #555;
+  color: white;
+}
+
+.conversation .blip .author {
+  width: 100%;
+}
+
+.conversation .blip .author img {
+  float: left;
+  height: 32px;
+  width: 32px;
+}
+
+.conversation .blip .author .name {
+  float: right;
+}
+
+.author-more {
+  float: right;
+  clear: both;
+}
+
+.author-count-1 {
+  min-height: 24px;
+}
+
+.author-count-2 {
+  min-height: 84px;
+}
+
+.author-count-3 {
+  min-height: 136px;
+}
+
+.author-count-many {
+  min-height: 136px;
+}
+
+.conversation .blip div.left .toolbar {
+  display: none;
+  position: absolute;
+  margin: 16px 12px 0 0;
+  padding: 2px 4px 0 4px;
+  right: 0;
+
+  background: #fff;
+  -webkit-border-radius: 4px;
+  -webkit-box-shadow: 2px 2px 4px #111;
+  -moz-border-radius: 4px;
+  -moz-box-shadow: 2px 2px 4px #111;
+}
+
+.indent {
+  padding-left: 40px;
+}
+
+.unread {
+  background: #7aa2f2 !important;
+  color: #eee !important;
+}
+
+.conversation .blip div.right {
+  float: left;
+  width: 74%;
+
+  padding: 12px 12px 24px 12px;
+  margin: 0 auto;
+
+  -webkit-border-radius: 6px;
+  -moz-border-radius: 6px;
+
+  -webkit-box-shadow: 2px 2px 8px #000;
+  -moz-box-shadow: 2px 2px 8px #000;
+
+  background: white;
+}
+
+.conversation .blip div.right .time {
+  float: right;
+  font-size: 94%;
+  color: #999;
+}
+/** markup in text**/
+span.title {
+  font-weight: bold;
+}
+
+/** an unused button **/
+.more-button {
+  margin: 4px auto;
+
+  width: 120px;
+
+  cursor: pointer;
+  cursor: hand;
+
+  font-size: 11px;
+  color: #777;
+  padding: 4px 14px;
+  -webkit-border-radius: 4px;
+  -moz-border-radius: 4px;
+
+  background: #EDEDED;
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0.0, #FFF),
+  color-stop(0.7, #FEFEFE), color-stop(1.0, #EDEDED));
+}
+
+.more-button:hover {
+  background: #DEDEDE;
+}
+
+/*** Picture thumbnail embedded in blip **/
+.picture {
+  display: block;
+  width: 260px;
+  height: 180px;
+  border: 1px solid #999;
+  padding: 2px;
+  -webkit-border-radius: 2px;
+}
+
+/** offset the text a bit from the checkbox **/
+div.todo span {
+  padding-left: 6px;
+}
+
+div.todo div.due {
+  padding: 8px 18px;
+  float: right;
+  border-left: 1px solid #DDD;
+  margin: -4px 0;
+
+  color: #AAA;
+  font-size: 9px;
+}
+
+/*** search related stuff **/
+
+.blue {
+  color: white; /**background: rgb(142, 193, 255); **/
+  -webkit-box-shadow: none !important;
+
+}
+
+.orange {
+  color: white; /**background: rgb(142, 193, 255); **/
+  -webkit-box-shadow: none !important;
+
+  background: -webkit-gradient(linear, left top, left bottom,
+  from(rgb(255, 187, 83)), to(rgb(255, 167, 63)));
+}
+
+
+#zoomframe {
+  display: none;
+  position: absolute;
+  z-index: 2;
+
+  border: 1px solid #fff;
+}
+
+/** separate from zoomframe so we can assign different opacity **/
+#zoomframe div {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  background: #000;
+  opacity: 0.2;
+}
+
+.feed .item {
+  overflow: hidden;
+  padding: 14px 10px 18px 10px;
+  border-bottom: 1px solid #999;
+  background: white;
+
+  cursor: pointer;
+}
+
+.feed .item:hover {
+  background: #cacaca !important;
+}
+
+.feed .read {
+  background: #eaeaea !important;
+}
+
+.feed .item img.icon {
+  float: left;
+  padding-right: 6px;
+  padding-left: 6px;
+}
+
+.feed .item .title {
+  font-weight: bold;
+  margin-left: 45px;
+  padding-bottom: 2px;
+}
+
+.read > .title {
+  color: #777;
+}
+
+.feed .item .snippet {
+  margin-left: 45px;
+}
+
+.read > .snippet {
+  color: #999;
+}
+
+.feed .item .snippet .tid {
+  font-style: italic;
+  padding-right: 4px;
+}
+
+.feed .item .time {
+  float: right;
+  text-align: right;
+  font-weight: bold;
+}
+
+.read > .time {
+  color: #999;
+}
+
+.messages {
+  font-weight: normal;
+}
+
+.feed .item .avatar {
+  border: 3px solid #ccc;
+  border-radius: 3px 3px;
+  -moz-border-radius: 3px 3px;
+  float: left;
+  margin: 0 5px 2px 0;
+}
+
+.avatar > img {
+  width: 32px;
+  height: 32px;
+  border: 1px solid #fff;
+}
+
+/** a pulse animation **/
+ at -webkit-keyframes pulse {
+  from {
+    -webkit-transform: scale(1.0);
+  }
+  35% {
+    -webkit-transform: scale(1.10);
+  }
+  65% {
+    -webkit-transform: scale(1.00);
+  }
+  90% {
+    -webkit-transform: scale(1.02);
+  }
+  to {
+    -webkit-transform: scale(1.0);
+  }
+}
+
+/** this is how you add the pulse anim */
+.anim-pulse {
+  -webkit-animation-name: pulse;
+  -webkit-animation-duration: 0.4s;
+  -webkit-animation-iteration-count: 1;
+}
+
+.editor {
+  border: 1px solid green;
+  min-height: 40px;
+}
+
+.header {
+  background-color: #dfe3eb;
+
+  padding: 16px 12px 16px 24px;
+  margin: 0 auto;
+
+  -webkit-box-shadow: 2px 2px 8px #000;
+  -moz-box-shadow: 2px 2px 8px #000;
+}
+
+#headerLayout td.control-bar {
+  vertical-align: middle;
+  color: #ccc
+}
+
+.control-bar a {
+  color: #ccc;
+}
+
+.control-bar a:hover {
+  color: #ccc;
+  text-decoration: underline;
+}
+
+.participants {
+  overflow: hidden;
+  height: 18px;
+}
+
+.participants > .avatar > img {
+  width: 16px;
+  height: 16px;
+  margin-bottom: -4px;
+}
+
+.participants > .avatar > .name {
+  margin: 0 5px;
+}
+
+.unknown-element {
+  color: #999;
+  font-weight: bold;
+  border: 1px solid #C9E2FC;
+  padding-left: 2px;
+  padding-right: 2px;
+}
+
+.attachment-element {
+  border: 1px solid #C9E2FC;
+  width: auto;
+  font-weight: normal;
+  text-align: center;
+  margin: 2px;
+  display: inline-block;
+}
+
+.attachment-element img {
+  max-width: 128px;
+  max-height: 128px;
+}
+
+.caption {
+  text-align: center;
+}


Property changes on: trunk/src/main/webapp/others/splash/style/orig-style.css
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/style/permalink.css
===================================================================
--- trunk/src/main/webapp/others/splash/style/permalink.css	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/style/permalink.css	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,582 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+/** Alternate stylesheet for permalink, embed and gmail integration waves **/
+
+/* Zero default margin & padding around common elements */
+blockquote, body, dd, dl, dt, fieldset, form, h1, h2, h3, h4, h5, h6, li, ol, p, ul
+{
+  margin: 0;
+  border: 0 none #FFFFFF;
+  padding: 0;
+}
+
+body {
+  background-color: #e5e5e5;
+  font-family: Arial, sans-serif;
+  font-size: 85%;
+  line-height: 1.3;
+}
+
+body.embedded {
+  background-color: transparent;
+}
+
+.wave-window {
+  width: 100%;
+  overflow: hidden;
+}
+
+a {
+  color: #003ea8;
+}
+
+
+
+
+/* HEADER ========================================= */
+
+#header
+{
+  border: 1px solid #C9E2FC;
+  border-right: 1px solid #AEC6DF;
+  -webkit-border-top-left-radius: 7px;
+  -webkit-border-top-right-radius: 7px;
+  -moz-border-radius-topleft: 7px;
+  -moz-border-radius-topright: 7px;
+  border-top-left-radius: 7px;
+  border-top-right-radius: 7px;
+  background-color: #C9E2FC;
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#E6F0FB), to(#C9E2FC));
+  background-image: -moz-linear-gradient(top, #E6F0FB, #C9E2FC);
+  text-align: left;
+}
+
+#headerInner
+{
+  overflow: hidden;
+  border-top: 1px solid #ECF5FE;
+  border-left: 1px solid #ECF5FE;
+  -webkit-border-top-left-radius: 7px;
+  -webkit-border-top-right-radius: 7px;
+  -moz-border-radius-topleft: 7px;
+  -moz-border-radius-topright: 7px;
+  border-top-left-radius: 7px;
+  border-top-right-radius: 7px;
+  padding: 8px 10px 4px 5px;
+  line-height: 18px;
+}
+
+* html #headerInner
+{
+  overflow: visible;
+  height: 1px;
+}
+
+#logo
+{
+  float: left;
+  width: 98px;
+  height: 23px;
+  overflow: hidden;
+  background-image: url(../images/logo.png);
+  background-repeat: no-repeat;
+  text-indent: -9999px;
+}
+
+* html #logo
+{
+  background-image: none;
+  filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../images/logo.png", sizingMethod="crop");
+}
+
+#menu
+{
+  float: right;
+  white-space: nowrap;
+}
+
+#menu li
+{
+  display: inline;
+  float: left;
+  margin-left: 7px;
+  border-left: 1px solid #93ABC3;
+  padding-left: 7px;
+  font-weight: bold;
+  text-shadow: 1px 1px 0 rgba(255,255,255,0.75);
+}
+
+#menu li.first
+{
+  margin-left: 0;
+  border-left: 0 none #ffffff;
+  padding-left: 0;
+}
+
+#menu li a
+{
+  font-weight: normal;
+}
+
+#shareLink {
+  padding-left: 25px !important;
+  background-image: url(../images/share_icon.png);
+  background-repeat: no-repeat;
+  background-position: 5px 50%;
+  color: #003ea8;
+}
+
+* html #shareLink {
+  padding-left: 7px !important;
+  background-image: none;
+}
+
+#shareLink:visited {
+  color: #003ea8;
+}
+
+#participants
+{
+  clear: both;
+  padding: 0.4em 0 0 0;
+  font-weight: bold;
+  text-shadow: 1px 1px 0 rgba(255,255,255,0.75);
+}
+
+* html #participants
+{
+  height: 1px;
+}
+
+#participants h3
+{
+  float: left;
+  padding-right: 0.5em;
+  font-size: 100%;
+}
+
+#participants .avatar {
+  margin: 0;
+}
+
+#participants .avatar img {
+  display: none;
+}
+
+#participants .avatar .name {
+  display: inline;
+  height: auto;
+  padding: 0;
+  line-height: 1;
+  text-shadow: 1px 1px 0 rgba(255,255,255,0.75);
+  font-weight: normal;
+}
+
+#participants .punctuation {
+  margin-left: -0.2em;
+  margin-right: 0.1em;
+}
+
+.popup {
+  display: none;
+  position: absolute;
+  z-index: 999;
+  border: 1px solid #aec6df;
+  -webkit-border-radius: 7px;
+  -moz-border-radius: 7px;
+  border-radius: 7px;
+  padding: 12px;
+  background: #ffffff;
+  color: #b2b2b2;
+  -webkit-box-shadow: 5px 5px 10px rgba(0,0,0,0.2);
+  -moz-box-shadow: 5px 5px 10px rgba(0,0,0,0.2);
+  box-shadow: 5px 5px 10px rgba(0,0,0,0.2);
+}
+
+#share-popup {
+  right: 1.2em;
+  top: 2.8em;
+  width: 290px;
+}
+
+#inline-reply-popup {
+  width: 490px;
+  height: 50%;
+  overflow: auto;
+}
+
+.popup-pointer {
+  position: absolute;
+  right: 3em;
+  top: -10px;
+  width: 19px;
+  height: 10px;
+  background-image: url(../images/dialog_pointer.gif);
+  background-repeat: no-repeat;
+}
+
+.dialog-close {
+  position: absolute;
+  right: 8px;
+  top: 8px;
+  z-index: 100;
+  border: 1px solid #aec6df;
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  border-radius: 3px;
+}
+
+.dialog-close:hover {
+  border-color: #9fb5cc;
+  background-color: #c9d9ea;
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#c9d9ea));
+  background-image: -moz-linear-gradient(top, #ffffff, #c9d9ea);
+}
+
+.dialog-close.down {
+  background-color: #aec6df;
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#c9d9ea), to(#ffffff));
+  background-image: -moz-linear-gradient(top, #c9d9ea, #ffffff);
+}
+
+.dialog-close span {
+  display: block;
+  width: 9px;
+  height: 9px;
+  padding: 3px;
+  overflow: hidden;
+  background-image: url(../images/dialog_close.gif);
+  background-repeat: no-repeat;
+  background-position: 3px 3px;
+  text-indent: -9999px;
+}
+
+#share-popup h3 {
+  color: #738699;
+  font-weight: normal;
+  font-size: 135%;
+}
+
+#share-popup .separator {
+  margin: 1.7em 0 0.5em 0;
+  text-align: center;
+  border-top: 1px solid #dddddd;
+}
+
+#share-popup .separator em {
+  position: relative;
+  top: -0.7em;
+  padding: 0 0.5em;
+  background-color: #ffffff;
+  font-style: normal;
+}
+
+#share-popup label {
+  display: block;
+  margin: 0 0 0.3em 0;
+  color: #000000;
+}
+
+.input-wrapper {
+  margin-right: 10px;
+  overflow: visible;
+}
+
+#share-popup input {
+  border: 1px solid #666666;
+  background: #eee;
+  padding: 3px 4px;
+  width: 100%;
+  font-size: 100%;
+}
+
+#share-popup-wave-id {
+  margin-top: 1.4em;
+}
+
+
+
+
+/* CONTENT ========================================= */
+
+#content
+{
+  border-left: 1px solid #C9E2FC;
+  border-right: 1px solid #AEC6DF;
+  border-bottom: 1px solid #AEC6DF;
+  -webkit-border-bottom-left-radius: 7px;
+  -webkit-border-bottom-right-radius: 7px;
+  -moz-border-radius-bottomleft: 7px;
+  -moz-border-radius-bottomright: 7px;
+  border-bottom-left-radius: 7px;
+  border-bottom-right-radius: 7px;
+}
+
+#contentInner
+{
+  border-left: 1px solid #ECF5FE;
+  border-right: 3px solid #C9E2FC;
+  border-bottom: 3px solid #C9E2FC;
+  -webkit-border-bottom-left-radius: 5px;
+  -webkit-border-bottom-right-radius: 5px;
+  -moz-border-radius-bottomleft: 5px;
+  -moz-border-radius-bottomright: 5px;
+  border-bottom-left-radius: 5px;
+  border-bottom-right-radius: 5px;
+}
+
+#contentInner2
+{
+  border-left: 3px solid #C9E2FC;
+  border-right: 1px solid #ECF5FE;
+  border-bottom: 1px solid #ECF5FE;
+}
+
+#contentInner3
+{
+  position: relative; /* Required for IE weirdness because of relatively positioned avatar imgs */
+  height: 200px;
+  overflow: auto;
+  border-top: 1px solid #AEC6DF;
+  border-right: 1px solid #C9E2FC;
+  border-bottom: 1px solid #C9E2FC;
+  border-left: 1px solid #AEC6DF;
+}
+
+#conversation {
+  max-width: 60em;
+  overflow: hidden;
+  margin: 0 auto;
+  padding: 12px 24px 12px 24px;
+  background-color: #ffffff;
+  -webkit-box-shadow: 0 0 24px rgba(0,0,0,0.15);
+  -moz-box-shadow: 0 0 24px rgba(0,0,0,0.15);
+  box-shadow: 0 0 24px rgba(0,0,0,0.15);
+}
+
+#frame #conversation {
+  max-width: none;
+  padding: 12px;
+  background-color: transparent;
+  -webkit-box-shadow: none;
+  -moz-box-shadow: none;
+  box-shadow: none;
+}
+
+.blip {
+  clear: both;
+  overflow: hidden;
+  border-top: 1px dashed #cccccc;
+  padding: 0.8em 0 1em 0;
+}
+
+* html .blip {
+  position: relative;
+  overflow: visible;
+  height: 1px;
+}
+
+.blip:first-child {
+  border-top: 0 none #ffffff;
+  padding-top: 0;
+}
+
+.indent .blip:first-child {
+  border-top: 1px dashed #cccccc;
+  padding-top: 0.8em;
+}
+
+.blip .left {
+  float: left;
+  width: 10em;
+}
+
+.blip .avatar {
+  margin: 0 0 4px 28px;
+  -webkit-border-top-right-radius: 4px;
+  -webkit-border-bottom-right-radius: 4px;
+  -moz-border-radius-topright: 4px;
+  -moz-border-radius-bottomright: 4px;
+  border-top-right-radius: 4px;
+  border-bottom-right-radius: 4px;
+  padding: 0 0.5em 0 0;
+/*
+  background-color: #e5e5e5;
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#eeeeee), to(#cccccc));
+  background-image: -moz-linear-gradient(top, #eeeeee, #cccccc);
+*/
+  color: #738699;
+  font-weight: bold;
+}
+
+.avatar img {
+  position: relative;
+  left: -28px;
+  float: left;
+  width: 20px;
+  height: 20px;
+  border: 1px solid #cccccc;
+  margin-right: -22px;
+}
+
+.avatar .name {
+  display: block;
+  width: 100%;
+  height: 22px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  line-height: 22px;
+  text-shadow: 1px 1px 0 #ffffff;
+}
+
+#conversation .blip .left .toolbar {
+  display: none;
+  position: absolute;
+  margin: 16px 12px 0 0;
+  padding: 2px 4px 0 4px;
+  right: 0;
+
+  background: #fff;
+  -webkit-border-radius: 4px;
+  -webkit-box-shadow: 2px 2px 4px #999;
+  -moz-border-radius: 4px;
+  -moz-box-shadow: 2px 2px 4px #999;
+}
+
+.indent {
+  margin: 0 0 1.3em 6em;
+  overflow: hidden;
+  padding-left: 1em;
+  border-left: 1px solid #cccccc;
+  border-bottom: 1px solid #cccccc;
+  -webkit-border-bottom-left-radius: 8px;
+  -moz-border-radius-bottomleft: 8px;
+  border-bottom-left-radius: 8px;
+  -webkit-box-shadow: -4px 4px 8px rgba(0,0,0,0.13);
+  -moz-box-shadow: -4px 4px 8px rgba(0,0,0,0.13);
+  box-shadow: -4px 4px 8px rgba(0,0,0,0.13);
+}
+
+.unread {
+  background: #7aa2f2 !important;
+  color: #eee !important;
+}
+
+#conversation .blip .right {
+  margin-left: 11em;
+}
+
+* html #conversation .blip .right {
+  height: 1px; /* Fixes 3px jog bug in IE6 */
+}
+
+#conversation .blip .right-inner {
+  width: 100%;
+  overflow: hidden;
+}
+
+#conversation .blip .right .time {
+  float: right;
+  margin: 0 0 0 1em;
+  color: #7f7f7f;
+}
+
+#conversation .content {
+  margin: 0.15em 0 0 0;
+}
+
+/** markup in text**/
+span.title {
+  font-weight: bold;
+}
+
+.content img {
+  max-width: 100%;
+}
+
+/** Inline replies styling **/
+.inline-reply {
+  display: inline;
+}
+
+.inline-reply .count {
+  position: relative;
+  top: -2px;
+  padding-left: 10px;
+  background-image: url(../images/inline_reply_arrow.gif);
+  background-repeat: no-repeat;
+  background-position: 2px 5px;
+}
+
+.inline-reply .expanded {
+  background-image: url(../images/inline_reply_arrow_expanded.gif);
+  background-position: 0 6px;
+}
+
+.inline-reply .count-inner {
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  border-radius: 3px;
+  border: 1px solid #5C8B09;
+  background: #99bb00;
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#99bb00), to(#5C8B09));
+  background-image: -moz-linear-gradient(top, #99bb00, #5C8B09);
+  padding: 1px 7px;
+  color: #ffffff;
+  font-weight: bold;
+  font-size: 85%;
+  cursor: pointer;
+  cursor: hand;
+}
+
+.inline-reply .pointer {
+  display: none;
+  position: absolute;
+  width: 19px;
+  height: 10px;
+  right: 3px;
+  bottom: -15px;
+  background-image: url(../images/inline_reply_pointer.gif);
+  background-repeat: no-repeat;
+}
+
+.inline-reply .expanded .pointer {
+  display: inline;
+}
+
+.inline-reply-content {
+  display: inline;
+}
+
+#purgatory .inline-reply-content {
+  display: none;
+}
+
+.inline-reply-content-inner {
+  margin: 11px 5px 1.4em 5px;
+  border: 1px solid #cccccc;
+  -webkit-border-radius: 7px;
+  -moz-border-radius: 7px;
+  border-radius: 7px;
+  padding: 12px;
+  -webkit-box-shadow: 0 0 5px rgba(0,0,0,0.2);
+  -moz-box-shadow: 0 0 5px rgba(0,0,0,0.2);
+  box-shadow: 0 0 5px rgba(0,0,0,0.2);
+  font-weight: normal;
+}
+


Property changes on: trunk/src/main/webapp/others/splash/style/permalink.css
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/style/permalink_ie.css
===================================================================
--- trunk/src/main/webapp/others/splash/style/permalink_ie.css	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/style/permalink_ie.css	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,23 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+/* HEADER ========================================= */
+
+
+
+
+/* CONTENT ========================================= */
+


Property changes on: trunk/src/main/webapp/others/splash/style/permalink_ie.css
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/style/stuff.css
===================================================================
--- trunk/src/main/webapp/others/splash/style/stuff.css	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/style/stuff.css	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,448 @@
+/**
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+body {
+  font-family: Arial, sans-serif;
+  font-size: 10pt;
+  background-color: #CCC;
+}
+
+.invisible {
+  display: none;
+}
+
+#content {
+  overflow: hidden;
+}
+
+#feed-loading {
+  display: block;
+  background: transparent;
+  margin: 0 auto 0 auto;
+  padding-top: 30px;
+}
+
+#wave-loading {
+  display: block;
+  background: transparent;
+  margin: 0 auto 0 auto;
+  padding-top: 20px;
+}
+
+.header .title {
+  float: left;
+}
+
+#conversation {
+  padding: 24px 24px 206px 12px;
+}
+
+#conversation .blip {
+  position: relative;
+  right: 0;
+  overflow: hidden;
+  padding: 8px 0;
+  margin-top: -8px;
+}
+
+#conversation .blip:first-child {
+  border: none;
+}
+
+#conversation .blip div.left {
+  float: left;
+  width: 18%;
+  margin-top: 7px;
+}
+
+#conversation .blip .authorbar {
+  margin: 2px 0 0 0;
+
+  background: #333;
+
+  padding: 3px 4px;
+  -webkit-border-bottom-left-radius: 4px;
+  -webkit-border-top-left-radius: 4px;
+  -moz-border-radius-bottomleft: 4px;
+  -moz-border-radius-topleft: 4px;
+}
+
+#wave-not-found {
+  text-align: center;
+  margin: 0 auto;
+  padding: 12px 12px 12px 12px;
+  width: 80%;
+  background: #fff;
+  -webkit-border-radius: 4px;
+  -webkit-box-shadow: 2px 2px 4px #111;
+  -moz-border-radius: 4px;
+  -moz-box-shadow: 2px 2px 4px #111;
+}
+
+.blip .content {
+  padding: 0px 12px 24px 42px;
+  clear: both;
+}
+
+.blip .time {
+  padding: 12px 12px 0 12px;
+  float: right;
+  font-size: 16px;
+  font-style: italic;
+}
+
+.author-more {
+}
+
+.author-count-1 {
+  min-height: 24px;
+}
+
+.author-count-2 {
+  min-height: 84px;
+}
+
+.author-count-3 {
+  min-height: 136px;
+}
+
+.author-count-many {
+  min-height: 136px;
+}
+
+#conversation .blip div.left .toolbar {
+  display: none;
+  position: absolute;
+  margin: 2px 12px 0 0;
+  padding: 2px 4px 0 4px;
+  right: 0;
+
+  background: #fff;
+  -webkit-border-radius: 4px;
+  -webkit-box-shadow: 2px 2px 4px #111;
+  -moz-border-radius: 4px;
+  -moz-box-shadow: 2px 2px 4px #111;
+}
+
+.indent {
+  padding-left: 40px;
+}
+
+.unread {
+  background: #7aa2f2 !important;
+  color: #eee !important;
+}
+
+#conversation .blip div.right {
+  float: left;
+  width: 82%;
+
+  -webkit-border-radius: 6px;
+  -moz-border-radius: 6px;
+  border-radius: 6px;
+
+  -webkit-box-shadow: 2px 2px 8px #000;
+  -moz-box-shadow: 2px 2px 8px #000;
+  background: white;
+}
+
+#conversation .blip div.right .time {
+  float: right;
+  font-size: 94%;
+  color: #999;
+}
+
+div.wave-window {
+  position: absolute;
+  right: 0;
+  overflow: auto;
+  width: 70%;
+  height: 100%;
+
+  /*margin: 2px 0; *//** TODO:gradient for moz/IE **/
+  background-image: url('../images/background_dot.png');
+}
+
+/** markup in text**/
+span.title {
+  font-weight: bold;
+}
+
+/** an unused button **/
+.more-button {
+  margin: 4px auto;
+
+  width: 120px;
+
+  cursor: pointer;
+  cursor: hand;
+
+  font-size: 11px;
+  color: #777;
+  padding: 4px 14px;
+  -webkit-border-radius: 4px;
+  -moz-border-radius: 4px;
+
+  background: #EDEDED;
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0.0, #FFF),
+  color-stop(0.7, #FEFEFE), color-stop(1.0, #EDEDED));
+}
+
+.more-button:hover {
+  background: #DEDEDE;
+}
+
+/*** Picture thumbnail embedded in blip **/
+.picture {
+  display: block;
+  width: 260px;
+  height: 180px;
+  border: 1px solid #999;
+  padding: 2px;
+  -webkit-border-radius: 2px;
+}
+
+/** offset the text a bit from the checkbox **/
+div.todo span {
+  padding-left: 6px;
+}
+
+div.todo div.due {
+  padding: 8px 18px;
+  float: right;
+  border-left: 1px solid #DDD;
+  margin: -4px 0;
+
+  color: #AAA;
+  font-size: 9px;
+}
+
+/*** search related stuff **/
+
+.blue {
+  color: white; /**background: rgb(142, 193, 255); **/
+  -webkit-box-shadow: none !important;
+
+}
+
+.orange {
+  color: white; /**background: rgb(142, 193, 255); **/
+  -webkit-box-shadow: none !important;
+
+  background: -webkit-gradient(linear, left top, left bottom,
+  from(rgb(255, 187, 83)), to(rgb(255, 167, 63)));
+}
+
+.feed-container {
+  position: absolute;
+  background: #b5b9c2;
+  margin: 0;
+  width: 30%;
+  height: 100%;
+}
+
+.feed {
+  background: #b5b9c2;
+
+  margin: 0;
+  width: 100%;
+  height: 97%;
+  overflow: auto;
+}
+
+.feed .item {
+  overflow: hidden;
+  padding: 14px 10px 18px 10px;
+  border-bottom: 1px solid #999;
+  background: white;
+
+  cursor: pointer;
+}
+
+.feed .item:hover {
+  background: #cacaca !important;
+}
+
+.feed .read {
+  background: #eaeaea !important;
+}
+
+.feed .item img.icon {
+  float: left;
+  padding-right: 6px;
+  padding-left: 6px;
+}
+
+.feed .item .title {
+  font-weight: bold;
+  margin-left: 45px;
+  padding-bottom: 2px;
+}
+
+.read > .title {
+  color: #777;
+}
+
+.feed .item .snippet {
+  margin-left: 45px;
+}
+
+.read > .snippet {
+  color: #999;
+}
+
+.feed .item .snippet .tid {
+  font-style: italic;
+  padding-right: 4px;
+}
+
+.feed .item .time {
+  float: right;
+  text-align: right;
+  font-weight: bold;
+}
+
+.read .time {
+  color: #999;
+}
+
+.messages {
+  font-weight: normal;
+}
+
+.feed .item .avatar {
+  border: 3px solid #ccc;
+  border-radius: 3px 3px;
+  -moz-border-radius: 3px 3px;
+  float: left;
+  margin: 0 5px 2px 0;
+}
+
+.feed .avatar img {
+  width: 32px;
+  height: 32px;
+  border: 1px solid #fff;
+}
+
+/** a pulse animation **/
+ at -webkit-keyframes pulse {
+  from {
+    -webkit-transform: scale(1.0);
+  }
+  35% {
+    -webkit-transform: scale(1.10);
+  }
+  65% {
+    -webkit-transform: scale(1.00);
+  }
+  90% {
+    -webkit-transform: scale(1.02);
+  }
+  to {
+    -webkit-transform: scale(1.0);
+  }
+}
+
+/** this is how you add the pulse anim */
+.anim-pulse {
+  -webkit-animation-name: pulse;
+  -webkit-animation-duration: 0.4s;
+  -webkit-animation-iteration-count: 1;
+}
+
+.editor {
+  border: 1px solid green;
+  min-height: 40px;
+}
+
+.header {
+  background-color: #dfe3eb;
+  padding: 8px 12px 8px 12px;
+  margin: 0 auto;
+  -webkit-box-shadow: 2px 2px 8px #000;
+  -moz-box-shadow: 2px 2px 8px #000;
+}
+
+#headerLayout td.control-bar {
+  vertical-align: middle;
+  color: #ccc
+}
+
+.control-bar a {
+  color: #ccc;
+}
+
+.control-bar a:hover {
+  color: #ccc;
+  text-decoration: underline;
+}
+
+.participants {
+  overflow: hidden;
+  height: 18px;
+  vertical-align: middle;
+}
+
+.participants .avatar {
+  float: left;
+  margin-bottom: 4px;
+}
+
+.blip .authorbar {
+  color: white;
+}
+
+.avatar {
+  white-space: nowrap;
+}
+
+.avatar img {
+  width: 33px;
+  height: 33px;
+  border: 1px solid #ccc;
+}
+
+.avatar .name {
+  margin: 0 5px;
+  vertical-align: top;
+}
+
+.unknown-element {
+  color: #999;
+  font-weight: bold;
+  border: 1px solid #C9E2FC;
+  padding-left: 2px;
+  padding-right: 2px;
+}
+
+.attachment-element {
+  border: 1px solid #C9E2FC;
+  width: auto;
+  font-weight: normal;
+  text-align: center;
+  margin: 2px;
+  display: inline-block;
+}
+
+.attachment-element img {
+  max-width: 128px;
+  max-height: 128px;
+}
+
+.caption {
+  text-align: center;
+}


Property changes on: trunk/src/main/webapp/others/splash/style/stuff.css
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + text/plain

Added: trunk/src/main/webapp/others/splash/wave_not_found.html.fragment
===================================================================
--- trunk/src/main/webapp/others/splash/wave_not_found.html.fragment	                        (rev 0)
+++ trunk/src/main/webapp/others/splash/wave_not_found.html.fragment	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,3 @@
+<div id="wave-not-found">
+  Sorry! There was a problem loading this wave.
+</div>

Modified: trunk/src/test/java/cc/kune/wave/server/KuneWaveManagerDefaultTest.java
===================================================================
--- trunk/src/test/java/cc/kune/wave/server/KuneWaveManagerDefaultTest.java	2011-07-01 01:37:33 UTC (rev 1438)
+++ trunk/src/test/java/cc/kune/wave/server/KuneWaveManagerDefaultTest.java	2011-07-01 11:27:50 UTC (rev 1439)
@@ -52,16 +52,14 @@
   @Test
   public void addGadget() throws DefaultException, IOException {
     doLogin();
-    final WaveRef waveletName = manager.createWave(TITLE, MESSAGE,
-        participantUtils.of(getSiteAdminShortName()));
+    final WaveRef waveletName = createTestWave();
     assertNotNull(waveletName);
     manager.addGadget(waveletName, getSiteAdminShortName(), TEST_GADGET);
   }
 
   private void addParticipant(final String whoAdds) throws IOException {
     doLogin();
-    final WaveRef waveletName = manager.createWave(TITLE, MESSAGE,
-        participantUtils.of(getSiteAdminShortName()));
+    final WaveRef waveletName = createTestWave();
     assertNotNull(waveletName);
     manager.addParticipant(waveletName, getSiteAdminShortName(), whoAdds, NEW_PARTICIPANT);
     final Wavelet fetchWavelet = manager.fetchWavelet(waveletName, getSiteAdminShortName());
@@ -83,6 +81,10 @@
 
   }
 
+  private WaveRef createTestWave() {
+    return manager.createWave(TITLE, MESSAGE, participantUtils.of(getSiteAdminShortName()));
+  }
+
   @Test
   public void createWave() throws DefaultException, IOException {
     doLogin();
@@ -107,8 +109,7 @@
   @Test
   public void createWaveWithTitle() throws DefaultException, IOException {
     doLogin();
-    final WaveRef waveletName = manager.createWave(TITLE, MESSAGE,
-        participantUtils.of(getSiteAdminShortName()));
+    final WaveRef waveletName = createTestWave();
     assertNotNull(waveletName);
     final Wavelet fetchWavelet = manager.fetchWavelet(waveletName, getSiteAdminShortName());
     assertNotNull(fetchWavelet);
@@ -123,10 +124,16 @@
   }
 
   @Test
+  public void renderWave() throws DefaultException, IOException {
+    doLogin();
+    final WaveRef waveletName = createTestWave();
+    assertNotNull(manager.render(waveletName, getSiteAdminShortName()));
+  }
+
+  @Test
   public void setTitle() throws DefaultException, IOException {
     doLogin();
-    final WaveRef waveletName = manager.createWave(TITLE, MESSAGE,
-        participantUtils.of(getSiteAdminShortName()));
+    final WaveRef waveletName = createTestWave();
     assertNotNull(waveletName);
     manager.setTitle(waveletName, TITLENEW, getSiteAdminShortName());
     final Wavelet fetchWavelet = manager.fetchWavelet(waveletName, getSiteAdminShortName());

Added: trunk/src/test/java/cc/kune/wave/server/KuneWaveMarkupTests.java
===================================================================
--- trunk/src/test/java/cc/kune/wave/server/KuneWaveMarkupTests.java	                        (rev 0)
+++ trunk/src/test/java/cc/kune/wave/server/KuneWaveMarkupTests.java	2011-07-01 11:27:50 UTC (rev 1439)
@@ -0,0 +1,34 @@
+package cc.kune.wave.server;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.waveprotocol.wave.model.document.util.XmlStringBuilder;
+
+import cc.kune.core.server.manager.impl.ContentConstants;
+
+import com.google.wave.api.Markup;
+
+public class KuneWaveMarkupTests {
+
+  private static final String FOO_MARKUP = "<b>Foo</b><br/>";
+
+  @Test
+  public void testMarkup() {
+    final Markup markup = Markup.of(FOO_MARKUP);
+    assertNotNull(markup.getMarkup());
+    assertNotNull(markup.getText());
+    assertNotNull(markup.getText().contains("\n"));
+  }
+
+  @Test
+  public void testXmlStringBuilderOfMarkup() {
+    XmlStringBuilder builder = XmlStringBuilder.createFromXmlString(FOO_MARKUP);
+    assertTrue(builder.getLength() > 0);
+    builder = XmlStringBuilder.createFromXmlString(ContentConstants.INITIAL_CONTENT);
+    assertTrue(builder.getLength() > 0);
+    builder = XmlStringBuilder.createFromXmlString(ContentConstants.WELCOME_WAVE_CONTENT);
+    assertTrue(builder.getLength() > 0);
+  }
+}


Property changes on: trunk/src/test/java/cc/kune/wave/server/KuneWaveMarkupTests.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain




More information about the kune-commits mailing list