You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by sn...@apache.org on 2006/07/13 15:07:47 UTC

svn commit: r421613 [2/4] - in /incubator/roller/branches/roller_3.0: src/org/apache/roller/business/hibernate/ src/org/apache/roller/business/search/operations/ src/org/apache/roller/model/ src/org/apache/roller/pojos/ src/org/apache/roller/ui/authori...

Modified: incubator/roller/branches/roller_3.0/web/WEB-INF/velocity/weblog.vm
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/WEB-INF/velocity/weblog.vm?rev=421613&r1=421612&r2=421613&view=diff
==============================================================================
--- incubator/roller/branches/roller_3.0/web/WEB-INF/velocity/weblog.vm (original)
+++ incubator/roller/branches/roller_3.0/web/WEB-INF/velocity/weblog.vm Thu Jul 13 06:07:42 2006
@@ -1,305 +1,207 @@
 
-#** macros for use with WeblogPageModel
+#** Set of essential macros needed in Roller velocity templates.
 
-   Contents
-      #showWeblogEntryDayPager()
-      #showEntryText()
-      #showComments()
-      #showCommentForm()
+Implemented:
+      #showWeblogEntriesPager($pager)
+      #showWeblogEntryComments($entry)
+      #showWeblogEntryCommentForm($entry)
+      #showCategoryLinksList()
+      #showWeblogEntriesLinkList()
+
+To be implemented:
+      #showBookmarkList()
+      #showPageLinksList()
       #showTrackbackAutodiscoveryRDF()
       #showAutodiscoveryLinks()
+      #includePage()
       #showSearchForm()
       #showSearchAgainForm()
       #showSearchSummary()
       #showSearchPager()
-      #showBookmarkList()
-      #showPageLinksList()
-      #showCategoryLinksList()
-      #showAuthorMenu()
-      #includePage()
 *#
 
-##-----------------------------------------------------------------------------
-#**
- * Shows weblog entries from specified category using specified page as a "day 
- * template" for the display of each day. The maxEntries argument is ignored
- * because now the number of entries to display is controlled by the 
- * entryDisplayCount property on the Preferences:Settings page.
- * <p>
- * This macro allows Roller to support five different types of blog displays:
- * <p>
- * Current day page<br />
- *     /page/&lt;handle&gt;/<br>
- * On the current day page, Roller will show the most recent N blog  
- * entries (not just those for the day).
- * At the end of the page, a previous link points to day page of entries  
- * before the ones shown (and the link is displayed as the day's date).  
- * This works exactly as before.
- * <p>
- * Day page<br>
- *     /page/&lt;handle&gt;/YYYYMMDD<br>
- * <p>On a day page, Roller will show all of the entries for a specific  
- * day. At the end of the page, a next/previous link allows navigation  
- * to next and previous day of entries (and the links are displayed as  
- * the day's dates). Before, day pages always showed N entries (where  
- * usually N=15), but now they'll show only a day's worth (e.g. 1-3  
- * entries).
- * <p>
- * Month page<br>
- *     /page/&lt;handle&gt;/YYYYMM<br>
- * <p>On a month page, Roller will show the most recent N blog entries in  
- * the month. At the end of the page, a previous link points to day page  
- * of entries before the ones shown. This is new; we didn't have month  
- * pages before.
- * <p>
- * Entry page<br>
- *     /page/&lt;handle&gt;?entry=&lt;anchor&gt;<br>
- * <p>On an entry page, one entry is shown. The next/prev links link to the  
- * next and previous entries (and the links are displayed as the entry  
- * titles, nicely truncated). This one also works exactly as before.
- * <p>
- * Search page<br>
- *     /page/<handle>?q=<search terms><br>
- * <p>If there are search results, then this macro will show them using the 
- * current weblog's day template.
- * <br>
- *
- * @param pageName   Page name of page to serve as day template.
- * @param maxEntries (ignored)
- * @param category   Only display weblog entries from this category.
- *#
-#macro( showWeblogEntryDayPager $weblog $pageName $maxEntries $category)
-    #set($maxEntries = $website.entryDisplayCount)
-    #set($dayTemplateId = $pageModel.getPageIdByName($pageName))
-    #if(!$dayTemplateId ) ## if no page name, try Preview space
-        #set($dayTemplateId = $pageName)
-    #end
-    #if ($pageModel.weblogEntry)
-        <div class="top-next-prev">#showNextPreviousControl()</div>
-        #set($day = $entry.pubTime)
-        #set($entries = [$pageModel.weblogEntry])
-        #parse($dayTemplateId )
-        #if($trackbacksEnabled && $website.allowComments && $entry.commentsStillAllowed)
-           <div class="trackbackUrl">
-           $text.get("macro.weblog.trackback") #showTrackbackURL($entry)
-           </div>
-        #end
-        <div class="bottom-next-prev">#showNextPreviousControl()</div>
-        #showEntryLinkbacks($entry)
-        #showComments($entry)
-        #if($commentsEnabled && $website.allowComments && $entry.commentsStillAllowed)
-            #showCommentForm($entry)
-        #else
-            $text.get("comments.disabled")
-        #end
-    #else
-        #if($searchResults)
-            #set($map = $searchResults.results )
-            #showSearchAgainForm()
-            #showSearchSummary()
-            #foreach($day in $searchResults.results.keySet())
-                #set($entries = $searchResults.results.get($day))
-                #parse($dayTemplateId)
-            #end
-            #showSearchPager()
-        #else
-            #set($map = $pageModel.getRecentWeblogEntries($maxEntries, $category))
-            #if($map.size() == 0)
-               $text.get("macro.weblog.noEntriesForDate")
-            #else               
-               #foreach($day in $map.keySet())
-                   #set($entries = $map.get($day))
-                   #parse($dayTemplateId)
-               #end
-            #end
-            <div class="bottom-next-prev">#showNextPreviousControl()</div>
-        #end
+
+#** 
+Shows weblog entries pager via default day template 
+*#
+#macro(showWeblogEntriesPager $pager)
+    #set($dayPage = $model.weblog.findPageIdByName("_day"))
+    #set($map = $pager.getEntries())
+    #foreach($day in $map.keySet())
+        #set($entries = $map.get($day))   
+        #parse($dayPage)
     #end
 #end
 
-##-----------------------------------------------------------------------------
-#**
- * Use this to show entry summary or text as appropriate on your blog pages.
- * On single-entry pages, text is prefered. Everywhere else, summary is 
- * preferred. Also, applies all plugins configured by entry.
- *#
-#macro( showWeblogEntryText $entry )
-   #if( $entryPage )
-      #parse($entryPage.id)
-   #else
-      #if( $pageModel.weblogEntry) 
-          ## on single-entry pages, we prefer text
-          #if( $utilities.isNotEmpty($entry.text) )
-              #set( $sourceText = $entry.text )
-          #else 
-              #set( $sourceText = $entry.summary )
-          #end
-      #else
-          ## on multi-entry pages, we prefer summary
-          #if( $utilities.isNotEmpty($entry.summary) )
-              #set( $sourceText = $entry.summary )
-              #if( $utilities.isNotEmpty($entry.text) )
-                 #set( $readMore = "<a class='readmore' href='$entry.permaLink'> ...</a>" )
-                 #set( $sourceText = "$sourceText$readMore")
-              #end
-          #else 
-              #set( $sourceText = $entry.text )
-          #end
-      #end
-      #if( $entry.plugins )
-         #set( $displayText = $pageHelper.renderPlugins($entry, $sourceText) )
-      #else
-         #set( $displayText = $sourceText )
-      #end
-      $utilities.textToCDATA($displayText)
-   #end
+
+#** Show next/prev control for specified pager *#
+#macro(showNextPrevControl $pager)
+    #if ($pager.prevLink)
+        &laquo; <a href="$pager.prevLink">$pager.prevName</a> |  
+    #end
+    #if ($pager.prevLink || $pager.nextLink)
+        <a href="$model.weblog.URL/page/$model.weblogPage.link">$model.weblogPage.name</a>
+    #end
+    #if ($pager.nextLink)
+        | <a href="$pager.nextLink">$pager.nextName</a> &raquo;
+    #end
 #end
 
-##-----------------------------------------------------------------------------
-#**
- * Display all comments comments for an entry.
- * @param entry WeblogEntryData object for which comments are to be displayed.
- *#
-#macro( showComments $entry )
-    <div class="comments" id="comments">
-    #if( $previewComments )
-        #set( $comments = $previewComments )
+
+#** 
+Show comments for weblog entry according to Roller configuration 
+*#
+#macro(showWeblogEntryComments $entry)
+    #set($commentPreview = $model.getCommentPreview())
+    <a name="comments"></a>
+    <div class="comments">
+
+    #if($commentPreview)
+        #set($comments = [$commentPreview])
         <div class="comments-head">$text.get( "macro.weblog.preview" ):</div>
     #else
         <div class="comments-head">$text.get( "macro.weblog.comments" ):</div>
-        #set($comments = $pageModel.getComments($entry))
+        #set($entry = $map.getValues().get(0))
+        #set($comments = $entry.getComments(true, true))
     #end
+
     <br/>
     #foreach( $comment in $comments )
         <!-- comment: $comment.id -->
-        #if($comment.approved || $previewComments)
-            #set($content = $utilities.encodeEmail($comment.content))
+        #if($comment.approved || $commentPreview)
+            #set($content = $utils.encodeEmail($comment.content))
             #if($config.getBooleanProperty("users.comments.escapehtml"))
-                #set($content = $utilities.escapeHTML($content))
+                #set($content = $utils.escapeHTML($content))
             #else 
-                #set($content = $utilities.transformToHTMLSubset($utilities.escapeHTML($content)))
+                #set($content = $utils.transformToHTMLSubset($utils.escapeHTML($content)))
             #end
             #if($config.getBooleanProperty("users.comments.autoformat"))
-                #set($content = $utilities.autoformat($content))
+                #set($content = $utils.autoformat($content))
             #end
-            #set($content = $utilities.addNofollow($content))
-            <div class="comment" id="comment${velocityCount}">
-                ${content}
-                #showCommentDetails($comment true)
+            #set($content = $utils.addNofollow($content))
+
+            <div class="comment#if($velocityCount % 2 == 0) even#else odd#end" id="comment${velocityCount}">
+                #if ($content.startsWith("<p>")) #set ($content = $content.substring(3)) #end
+                <strong>${velocityCount}.</strong> ${content}
+
+                $dateFormatter.applyPattern($text.get( "macro.weblog.datepattern" ))
+                <p class="comment-details">
+                $text.get("macro.weblog.postedby")
+                #if (!$utils.isEmpty($comment.name) && !$utils.isEmpty($comment.remoteHost))
+                    <b>$comment.name</b> ($comment.remoteHost)
+                #elseif (!$utils.isEmpty($comment.name))
+                    <b>$comment.name</b>
+                #elseif (!$utils.isEmpty($comment.remoteHost))
+                    <b>$comment.remoteHost</b>
+                #end
+                $text.get("macro.weblog.on") $dateFormatter.format($comment.postTime)
+                #if( $utils.isNotEmpty($comment.url) )
+                    $text.get( "macro.weblog.postedbywebsite", [$comment.url, $comment.url] )
+                #end
+                <a href="${ctxPath}${entry.permaLink}#comment${velocityCount}"
+                   class="entrypermalink"
+                   title="$text.get( "macro.weblog.commentpermalink.title" )">#</a>
+                </p>
             </div>
+
         #end
     #end
     </div>
 #end
 
-##-----------------------------------------------------------------------------
-#**
- * Display comment form for a weblog entry.
- * @param entry WeblogEntry object for which form is to be shown.
- *#
-#macro( showWeblogCommentForm $entry )
-    <div class="comments-form">
-    <div class="comments-head">$text.get("macro.weblog.postcommentHeader")</div><br/>
 
-    #showStatusMessage()
+#** 
+Show comments form for weblog entry 
+*#
+#macro(showWeblogEntryCommentForm $entry)
+    #set($cform = $model.getCommentForm())
 
-    <form method="post" action="$ctxPath/comment" focus="name"
-        name="form" onsubmit="fixURL(this); return validateComments(this)">
-        
-        #if($requestParameters.popup)
-        <input type="hidden" name="popup" value="true" />
-        #end
+    <div class="comments-form">
+    <div class="comments-head">$text.get("macro.weblog.postcommentHeader")</div>
+
+    #if( $model.errorMessage )
+        <span class="error">$model.errorMessage</span>
+    #end
+    #if( $model.statusMessage )
+        <span class="status">$model.statusMessage</span>
+    #end
 
-        <!-- is this a post or a preview -->
+    <form method="post" action="$config.getContextURL()/roller-ui/rendering/comment/$entry.website.handle/entry/$entry.anchor" 
+        focus="name" name="form" onsubmit="fixURL(this); return validateComments(this)">    
         <input type="hidden" name="method" value="post" />
         <input type="hidden" name="entryid" value="$entry.id" />
 
-        <table cellspacing="0" cellpadding="1" border="0" width="95%">
-        <tr><th>$text.get( "macro.weblog.name" )</th>
-            <td><input type="text" name="name" value="$commentForm.name" size="50" maxlength="255" /></td>
-        </tr>
-
-        <tr><th>$text.get( "macro.weblog.email" )</th>
-            <td><input type="text" name="email" value="$commentForm.email" size="50" maxlength="255" /></td>
-        </tr>
-
-        <tr><th>$text.get( "macro.weblog.url" )</th>
-            <td><input type="text" name="url" value="$commentForm.url" size="50" maxlength="255" /></td>
-        </tr>
-        #if ($pageModel.emailComments)
-        <tr>
-            <td></td>
-            <td>
-                <input type="checkbox" id="notify" name="notify" />
-                <label for="notify">$text.get( "macro.weblog.notifyMeOfComments" )</label>
-            </td>
-        </tr>
+        <ul>
+            <li>
+                <label class="desc">$text.get( "macro.weblog.name" )</label>
+                <input type="text" name="name" class="text large" value="$cform.name" size="50" maxlength="255" />
+            </li>
+
+
+            <li><label class="desc">$text.get( "macro.weblog.email" )</label>
+                <input type="text" name="email" class="text large" value="$cform.email" size="50" maxlength="255" />
+            </li>
+
+            <li><label class="desc">$text.get( "macro.weblog.url" )</label>
+                <input type="text" name="url" class="text large" value="$cform.url" size="50" maxlength="255" />
+            </li>
+
+        #if ($config.getBooleanProperty("users.comments.emailnotify"))
+            <li><input type="checkbox" class="checkbox" id="notify" name="notify" />
+                <label for="notify" class="choice">$text.get( "macro.weblog.notifyMeOfComments" )</label>
+            </li>
         #end
-        <tr>
-            <td></td>
-            <td>
-                <input type="checkbox" id="rememberInfo" name="rememberInfo" />
-                <label for="rememberInfo">$text.get( "macro.weblog.rememberinfo" )</label>
-            </td>
-        </tr>
-        </table>
-        <br/>
-
-        <table>
-        <tr><th style="text-align: left">$text.get( "macro.weblog.yourcomment" )</th></tr>
-        <tr>
-            <td>
-            <textarea name="content" cols="50" rows="10">$commentForm.content</textarea><br />
-            <span class="comments-syntax-indicator">
-            $text.get( "macro.weblog.htmlsyntax" )
-            #if( $escapeHtml )
-                <span class="disabled">$text.get( "macro.weblog.htmldisabled" )</span>
-            #else
-                <span class="enabled">$text.get( "macro.weblog.htmlenabled" )</span>
-            #end
-            </span>
-            </td>
-        </tr>
-        </table>
-        
-        <script type="text/javascript" src="$ctxPath/theme/scripts/clientSideInclude.js"></script>
-        <div id="commentAuthenticator"></div>
- 
-        <table cellspacing="0" cellpadding="1" border="0" width="95%">
-        <tr>
-            <td align="left" nowrap="nowrap">
-               <input type="button" name="post" value="&nbsp;$text.get( "macro.weblog.preview" )&nbsp;"
-                  onClick="this.form.method.value='preview';this.form.submit()" />
-               <input type="submit" name="post" value="&nbsp;$text.get( "macro.weblog.post" )&nbsp;" />
-            </td>
-            <td align="right">
-               <!-- <input type="button" value="&nbsp;$text.get( "macro.weblog.clear" )&nbsp;" /> -->
-            </td>
-        </tr>
-        </table>
+            <li>
+                <input type="checkbox" class="checkbox" id="rememberInfo" name="rememberInfo" />
+                <label for="rememberInfo" class="choice">$text.get( "macro.weblog.rememberinfo" )</label>
+            </li>
+            <li>
+                <label class="desc">$text.get( "macro.weblog.yourcomment" )</label>
+                <textarea name="content" class="textarea large" cols="" rows="">$cform.content</textarea>
+            </li>
+            <li class="info">
+                <span class="comments-syntax-indicator">
+                $text.get( "macro.weblog.htmlsyntax" )
+                #if($config.getBooleanProperty("users.comments.escapehtml"))
+                    <span class="disabled">$text.get( "macro.weblog.htmldisabled" )</span>
+                #else
+                    <span class="enabled">$text.get( "macro.weblog.htmlenabled" )</span>
+                #end
+                </span>
+            </li>
+            <li class="info">
+               <script type="text/javascript" src="$config.getContextURL()/theme/scripts/clientSideInclude.js"></script>
+               <div id="commentAuthenticator"></div>
+            </li>
+            <li>
+               <input type="button" class="button" name="post" value="&nbsp;$text.get( "macro.weblog.preview" )&nbsp;"
+                  onclick="this.form.method.value='preview';this.form.submit()" />
+               <input type="submit" class="button" name="post" value="&nbsp;$text.get( "macro.weblog.post" )&nbsp;" />
+            </li>
+        </ul>
 
     </form>
 
-    <script type="text/javascript" src="$ctxPath/theme/scripts/roller.js"></script>
+    <script type="text/javascript" src="$config.getContextURL()/theme/scripts/roller.js"></script>
     <script type="text/javascript">
-    clientSideInclude('commentAuthenticator', '$ctxPath/CommentAuthenticatorServlet');
+    clientSideInclude('commentAuthenticator', '$config.getContextURL()/CommentAuthenticatorServlet');
 
     var author = getCookie("commentAuthor");
     var email = getCookie("commentEmail");
     var url = getCookie("commentUrl");
     // check each field - IE will render "null"
     if (author) {
-        document.form.name.value = author;
+        document.forms['commentForm'].name.value = author;
     }
     if (email) {
-        document.form.email.value = email;
+        document.forms['commentForm'].email.value = email;
     }
     if (url) {
-        document.form.url.value = url;
+        document.forms['commentForm'].url.value = url;
     }
 
     if (author || email || url) {
-        document.form.rememberInfo.checked = true;
+        document.forms['commentForm'].rememberInfo.checked = true;
     }
 
     function fixURL(theForm) {
@@ -329,193 +231,44 @@
     </div>
 #end
 
+#** Show weblog's categories in specified parent category *#
+#macro(showCategoryLinkList $weblog $categoryPath)
+    #set($rawUrl = "$config.contextURL/$weblog.handle")
+    <ul class="clearfix">
+        #set($weblogUrl = $rawUrl)
+        #set($selectedCat = "")
+
+        #if($model.weblogCategory)
+           #set($selectedCat = $model.weblogCategory)
+           <li><a href="$weblogUrl">$text.get("macro.weblog.allcategories")</a></li>
+        #else
+           <li class="selected"><a href="$weblogUrl">$text.get("macro.weblog.allcategories")</a></li>
+        #end
 
-##-----------------------------------------------------------------------------
-#**
- * Display a trackback auto-discovery comment for a WeblogEntry.
- **#
-#macro( showTrackbackAutodiscovery $entry )
-<!--
-<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-         xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"
-         xmlns:dc="http://purl.org/dc/elements/1.1/">
-<rdf:Description
-    rdf:about="$entry.permaLink"
-    trackback:ping="#showTrackbackURL($entry)"
-    dc:title="$entry.title"
-    dc:identifier="$entry.permaLink"
-    dc:subject="$entry.category.name"
-    dc:description="$entry.title"
-    dc:creator="$entry.creator.userName"
-    dc:date="$entry.pubTime" />
-</rdf:RDF>
--->
-#end
-
-##-----------------------------------------------------------------------------
-#**
- * Show autodiscovery links for feeds and publishing end-points.
- *#
-#macro( showAutodiscoveryLinks $weblog )
-    <link rel="alternate" type="application/rss+xml"
-        title="RSS" href="$absBaseURL/rss/${website.handle}" />
-#end
-
-##-----------------------------------------------------------------------------
-#**
- * Display search form for searching a weblog.  This is only a form, no div
- * or anything around it.
- *#
-#macro( showSearchForm )
-    <form id="searchForm" method="get" action="${ctxPath}/search/${website.handle}"
-        style="margin: 0; padding: 0" onsubmit="return validateSearch(this)">
-        <p>
-          <input type="text" id="q" name="q" size="20"
-              maxlength="255" value="#if($term)$term#end" />
-          #set( $cats = $pageModel.getWeblogCategories("nil") )
-          <select name="c">
-          <option value="">- In Category -</option>
-          #foreach( $cat in $cats )
-              <option #if($cat.name == $req.getParameter('c'))selected="selected"#end>$cat.name</option>
-          #end
-          </select>
-          <input type="submit" value="$text.get( "macro.weblog.searchbutton" )" />
-        </p>
-    </form>
-    <script type="text/javascript">
-        function validateSearch(form) {
-            if (form.q.value == "") {
-                alert("$text.get( "macro.weblog.searchalert" )");
-                form.q.focus();
-                return false;
-            }
-            return true;
-        }
-    </script>
-#end
-
-##-----------------------------------------------------------------------------
-#**
- * Display search form for searching a weblog.  This is only a form, no div
- * or anything around it.
- *#
-#macro( showSearchForm )
-    <form id="searchForm" method="get" action="${ctxPath}/search/${website.handle}"
-        style="margin: 0; padding: 0" onsubmit="return validateSearch(this)">
-        <p>
-          <input type="text" id="q" name="q" size="20"
-              maxlength="255" value="#if($term)$term#end" />
-          #set( $cats = $pageModel.getWeblogCategories("nil") )
-          <select name="c">
-          <option value="">- In Category -</option>
-          #foreach( $cat in $cats )
-              <option #if($cat.name == $req.getParameter('c'))selected="selected"#end>$cat.name</option>
-          #end
-          </select>
-          <input type="submit" value="$text.get( "macro.weblog.searchbutton" )" />
-        </p>
-    </form>
-    <script type="text/javascript">
-        function validateSearch(form) {
-            if (form.q.value == "") {
-                alert("$text.get( "macro.weblog.searchalert" )");
-                form.q.focus();
-                return false;
-            }
-            return true;
-        }
-    </script>
-#end
+        #if($req.getParameter($PAGEID_KEY) )
+            #set($pageParam = "&$PAGEID_KEY=$req.getParameter($PAGEID_KEY)")
+        #end
 
-##-----------------------------------------------------------------------------
-#**
- * Display search again form
- *#
-#macro( showSearchAgainForm )
-    <div id="searchAgain">
-        $text.get( "macro.weblog.searchdictionary", [$searchResults.term, $searchResults.term, $searchResults.term] )
-
-        $text.get( "macro.weblog.searchhits", [$searchResults.hits])
-
-        <form method="get" action="${ctxPath}/search/${website.handle}"
-            style="margin: 5px">
-            <input type="text" id="q" name="q" size="31"
-                maxlength="255" value="$searchResults.term"
-                style="padding-left: 1px" /><br />
-            #set( $cats = $pageModel.getWeblogCategories("nil") )
-            <select name="c">
-            <option value="">- Restrict By Category -</option>
-            #foreach( $cat in $cats )
-              <option #if($cat.name == $req.getParameter('c'))selected="selected"#end>$cat.name</option>
+        #set($cats = $weblog.getWeblogCategories($categoryPath))
+        #foreach($cat in $cats)
+            #set($catParam = "?cat=$utilities.encode($cat.path)")
+            #set($weblogUrl = "$rawUrl$catParam$!pageParam")
+            #if($selectedCat == $cat.path)
+                <li class="selected"><a href="$weblogUrl">$cat.name</a></li>
+            #else
+                <li><a href="$weblogUrl">$cat.name</a></li>
             #end
-            </select>
-            <input type="submit" value="$text.get( "macro.weblog.searchagain" )" />
-        </form>
-
-        $text.get( "macro.weblog.searchgoogle", [$searchResults.term, $absBaseURL, $ctxPath, ${website.handle}] )
-    </div>
-    <!-- searchhi script hangs firefox, commenting it out for now -->
-    <!-- script type="text/javascript" src="$ctxPath/theme/scripts/searchhi.js"></script -->
-#end
-
-##-----------------------------------------------------------------------------
-#**
- * Displays header like "1 - 10 of 20 found.".
-**#
-#macro( showSearchSummary )
-    #set( $min = $searchResults.offset + 1 )
-    #set( $max = $searchResults.offset + $searchResults.limit )
-    #if( $max > $searchResults.hits )#set( $max = $searchResults.hits )#end
-    <h3>
-        $min - $max of $searchResults.hits found.
-    </h3>
-#end
-
-##-----------------------------------------------------------------------------
-#**
- * Display list of search result pages (for pagination).
-**#
-#macro( showSearchPager )
-    <h3 style="text-align:center;">
-    #set( $numPages = $searchResults.hits / $searchResults.limit )
-    #set( $remainder = $searchResults.hits % $searchResults.limit )
-    #if( $remainder > 0 )#set( $numPages = $numPages + 1 )#end
-    #if( $numPages > 1 )
-        #foreach( $pageNum in [1..$numPages] )
-            #set( $i = $pageNum - 1 )
-            #set( $start = $searchResults.limit * $i )
-            <a href="?q=${utilities.encode($searchResults.term)}&${USERNAME_KEY}=$!{username}&n=${searchResults.limit}&o=${start}"
-               >$pageNum</a>#if( $pageNum != $numPages) | #end
         #end
-    #end
-    </h3>
-#end
-
-##-----------------------------------------------------------------------------
-
-#macro( showBookmarkList $weblog )
-#end
-
-##-----------------------------------------------------------------------------
-
-#macro( showPageLinksList $weblog )
-#end
-
-##-----------------------------------------------------------------------------
-
-#macro( showCategoryLinksList $weblog )
-#end
-
-##-----------------------------------------------------------------------------
-
-#macro( showAuthorMenu $weblog )
+    </ul>
 #end
 
-##-----------------------------------------------------------------------------
-
-#macro( includePage $pageName )
+#** Show recent weblog entries in specified category *#
+#macro(showWeblogEntriesLinkList $categoryPath $max)
+   #set($recentEntries = $model.getRecentWeblogEntries($categoryPath, $max))
+   <ul class="recentposts">
+   #foreach ($var in $recentEntries)
+       <li class="recentposts"><a href="$var.permalink">$var.title</a></li>
+   #end
+   </ul>
 #end
-
-
-
 

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/Weblog.vm
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/Weblog.vm?rev=421613&view=auto
==============================================================================
--- incubator/roller/branches/roller_3.0/web/themes/andreas08/Weblog.vm (added)
+++ incubator/roller/branches/roller_3.0/web/themes/andreas08/Weblog.vm Thu Jul 13 06:07:42 2006
@@ -0,0 +1,13 @@
+#set($pager = $model.getWeblogEntriesPager()) 
+<div class="next-previous">
+#showNextPrevControl($pager)
+</div>
+
+<div class="entries">
+#showWeblogEntriesPager($pager)
+</div>
+
+#if ($model.permalink)
+   #showWeblogEntryComments($entry)
+   #showWeblogEntryCommentForm($entry)
+#end

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/Weblog.vm
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/_css.vm
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/_css.vm?rev=421613&view=auto
==============================================================================
--- incubator/roller/branches/roller_3.0/web/themes/andreas08/_css.vm (added)
+++ incubator/roller/branches/roller_3.0/web/themes/andreas08/_css.vm Thu Jul 13 06:07:42 2006
@@ -0,0 +1,9 @@
+<link rel="stylesheet" type="text/css" href="$config.contextURL/themes/base.css" />
+<style type="text/css">
+@import url($config.contextURL/themes/andreas08/styles/tools.css);
+@import url($config.contextURL/themes/andreas08/styles/typo.css);
+@import url($config.contextURL/themes/andreas08/styles/forms.css);
+@import url($config.contextURL/themes/andreas08/styles/layout-navtop-subright.css);
+@import url($config.contextURL/themes/andreas08/styles/layout.css);
+@import url($config.contextURL/themes/andreas08/styles/andreas08.css);
+</style>

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/_css.vm
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/_day.vm
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/_day.vm?rev=421613&view=auto
==============================================================================
--- incubator/roller/branches/roller_3.0/web/themes/andreas08/_day.vm (added)
+++ incubator/roller/branches/roller_3.0/web/themes/andreas08/_day.vm Thu Jul 13 06:07:42 2006
@@ -0,0 +1,59 @@
+<div class="day">
+
+<div class="entry">
+    <a href="$config.contextURL/$model.weblog.handle/$utils.formatDate($day, "yyyyMMdd")">
+        <img class="daypermalink"
+            src="$config.contextURL/themes/andreas08/images/calendar.png"
+            title="$text.get("macro.weblog.daypermalink.title")"
+            alt='$utils.formatDate($day, "yyyyMMdd")' /></a>
+
+   #set($format = $text.get("macro.weblog.date.toStringFormat"))
+   $utils.formatDate($day, $format)
+</div>
+
+#foreach( $entry in $entries )
+<p>
+    <a name="$utils.encode($entry.anchor)"></a>
+    <span class="entryTitle"><a href="$entry.permalink">$entry.title</a>
+        #if ($utils.isUserAuthorizedToAuthor($entry.website))
+            [<a href="$config.getWeblogEntryEditURL($entry)">$text.get("macro.weblog.entrypermalink.edit")</a>]
+        #end
+    </span>
+
+    #if($model.permalink) 
+        #if($utils.isNotEmpty($entry.text))
+            #set($sourceText = $entry.transformedText)
+        #else 
+            #set($sourceText = $entry.transformedSummary)
+        #end
+    #else
+        #if($utils.isNotEmpty($entry.summary))
+            #set($sourceText = $entry.transformedSummary)
+            #if($utils.isNotEmpty($entry.text))
+               #set($readMore = "[<a class='readmore' href='$entry.permalink'>$text.get('macro.weblog.readMore')</a>]" )
+               #set($sourceText = "$sourceText$readMore")
+            #end
+        #else 
+            #set($sourceText = $entry.transformedText)
+        #end
+    #end
+    $sourceText
+
+    <span class="info">
+        #if ($utils.isUserAuthorizedToAuthor($entry.website))
+            [<a href="$config.getWeblogEntryEditURL($entry)">$text.get("macro.weblog.entrypermalink.edit")</a>]
+        #end $entry.commentCount
+        Posted by $entry.creator.fullName in <span class="category">$entry.category.name</span>
+        <span class="dateStamp">at <a href="$entry.permalink">$utils.formatDate($entry.pubTime, "yyyyMMdd")</a></span>
+        #set($commentCount = $entry.commentCount)
+        #if($entry.commentsStillAllowed || $commentCount > 0)  
+            #set($link = "$entry.permalink#comments" )
+            <a href="$link" class="commentsLink">$text.get("macro.weblog.comments")[$commentCount]</a>
+        #end
+    </span>
+
+</p>
+#end
+
+</div>
+

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/_day.vm
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/_decorator.vm
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/_decorator.vm?rev=421613&view=auto
==============================================================================
--- incubator/roller/branches/roller_3.0/web/themes/andreas08/_decorator.vm (added)
+++ incubator/roller/branches/roller_3.0/web/themes/andreas08/_decorator.vm Thu Jul 13 06:07:42 2006
@@ -0,0 +1,90 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
+<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <title>$model.weblog.name | #if (!$model.weblogCategory && $model.weblogPage.name == "Weblog") $model.weblogPage.name #elseif ($model.weblogCategory && $page.Name == "Weblog") $model.weblogCategory.name Category #elseif ($model.weblogPage.name == "Weblog") $title #else $model.weblogPage.name #end</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <meta http-equiv="Content-Language" content="en" />
+    <base href="$config.absoluteContextURL/$model.weblog.handle">
+    #includePage("_css")
+    #showRSSAutodiscoveryLink()
+    #showRSDLink()
+    <script type="text/javascript" src="$config.contextURL/themes/scripts/roller.js"></script>
+    <script type="text/javascript" src="$config.contextURL/themes/andreas08/scripts/prototype.js"></script>
+    <script type="text/javascript" 
+        src="$config.contextURL/themes/andreas08/scripts/scriptaculous.js?load=effects"></script>
+    <script type="text/javascript" src="$config.contextURL/themes/andreas08/scripts/lightbox.js"></script>
+    <link rel="stylesheet" type="text/css" href="$config.contextURL/themes/andreas08/styles/lightbox.css" />
+</head>
+
+#if( $model.weblogCategory )
+    #set( $chosenCat = $model.weblogCategory.name )
+    #set( $chosenCat = $stringUtils.replace($chosenCat, " ", "").toLowerCase() )
+    #set( $chosenCat = $stringUtils.replace($chosenCat, "/", "") )
+#end
+
+<body id="page-$model.weblogPage.name"#if($chosenCat) class="$chosenCat"#end>
+    
+<div id="page">  
+
+    <div id="header" class="clearfix">
+        <h1><a href="$config.contextURL/$model.weblog.handle">$model.weblog.name</a></h1>
+
+        <h2><!-- Short tagline goes here --></h2>
+        <div id="branding"></div>
+    </div>
+
+
+    <div id="content" class="clearfix">
+        <div id="main">
+
+        $decorator_body
+
+        </div><!-- end main -->
+
+        <div id="sub">
+            #showCssNavBar()
+            <div class="editorMenu">$menuModel.showEditorNavBar(true)</div>
+            <div class="small box" id="description">
+                <div id="feed">
+                    <a href="$config.contextURL/rss/${website.handle}"><img class="rssbadge"
+                        src="$config.contextURL/themes/$theme/images/feed-icon-16x16.jpg" alt="Click me to subscribe" /></a>
+                </div>
+                $model.weblog.description
+            </div>
+            <div class="small" id="calendar">$calendarModel.showWeblogCalendar($model.weblog, "nil")</div>
+            <div id="searchbar">
+                <h2>Search This Site</h2>
+
+                <form id="search" method="get" 
+                    action="$config.contextURL/search/$model.weblog.handle" style="margin: 0; padding: 0">
+                    <fieldset>
+                        <input type="text" id="q" name="q" size="15" class="text small"
+                            maxlength="255" value="" 
+                            onfocus="this.style.backgroundColor='#ffd'" 
+                            onblur="this.style.backgroundColor='#fff'" />
+                        <input type="submit" value="Go!" id="searchbutton" />
+                    </fieldset>
+                </form>
+            </div>
+
+            <h2>Recent Entries</h2>
+            #showWeblogEntryLinkList(20)
+
+        </div>
+
+        <div id="nav">
+            <div class="wrapper">
+                <h2 class="hide">Navigation</h2>
+                #showCategoryLinkList($model.weblog "nil")
+            </div>
+        </div>
+    </div><!-- end content -->
+
+    <div id="footer" class="clearfix">
+        <p>&copy; $model.weblog.creator.fullName | Design by <a href="http://andreasviklund.com">Andreas Viklund</a></p>
+    </div>
+
+</div><!-- end page -->
+</body>
+</html>

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/_decorator.vm
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/aquadot.jpg
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/aquadot.jpg?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/aquadot.jpg
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/aquadot.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/calendar.png
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/calendar.png?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/calendar.png
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/calendar.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/close.gif
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/close.gif?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/close.gif
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/close.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/closelabel.gif
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/closelabel.gif?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/closelabel.gif
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/closelabel.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/feed-icon-16x16.jpg
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/feed-icon-16x16.jpg?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/feed-icon-16x16.jpg
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/feed-icon-16x16.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/fieldbg.gif
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/fieldbg.gif?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/fieldbg.gif
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/fieldbg.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_blue.jpg
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_blue.jpg?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_blue.jpg
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_blue.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_bluepurple.jpg
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_bluepurple.jpg?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_bluepurple.jpg
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_bluepurple.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_greenblue.jpg
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_greenblue.jpg?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_greenblue.jpg
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_greenblue.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_purple.jpg
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_purple.jpg?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_purple.jpg
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/header_purple.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/loading.gif
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/loading.gif?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/loading.gif
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/loading.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/next.gif
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/next.gif?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/next.gif
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/next.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/nextlabel.gif
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/nextlabel.gif?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/nextlabel.gif
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/nextlabel.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/prev.gif
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/prev.gif?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/prev.gif
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/prev.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/prevlabel.gif
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/prevlabel.gif?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/prevlabel.gif
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/prevlabel.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/squares.jpg
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/images/squares.jpg?rev=421613&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/squares.jpg
------------------------------------------------------------------------------
    svn:executable = *

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/images/squares.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/roller/branches/roller_3.0/web/themes/andreas08/scripts/effects.js
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/web/themes/andreas08/scripts/effects.js?rev=421613&view=auto
==============================================================================
--- incubator/roller/branches/roller_3.0/web/themes/andreas08/scripts/effects.js (added)
+++ incubator/roller/branches/roller_3.0/web/themes/andreas08/scripts/effects.js Thu Jul 13 06:07:42 2006
@@ -0,0 +1,903 @@
+// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+//  Justin Palmer (http://encytemedia.com/)
+//  Mark Pilgrim (http://diveintomark.org/)
+//  Martin Bialasinki
+// 
+// See scriptaculous.js for full license.  
+
+/* ------------- element ext -------------- */  
+ 
+// converts rgb() and #xxx to #xxxxxx format,  
+// returns self (or first argument) if not convertable  
+String.prototype.parseColor = function() {  
+  var color = '#';  
+  if(this.slice(0,4) == 'rgb(') {  
+    var cols = this.slice(4,this.length-1).split(',');  
+    var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);  
+  } else {  
+    if(this.slice(0,1) == '#') {  
+      if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();  
+      if(this.length==7) color = this.toLowerCase();  
+    }  
+  }  
+  return(color.length==7 ? color : (arguments[0] || this));  
+}
+
+Element.collectTextNodes = function(element) {  
+  return $A($(element).childNodes).collect( function(node) {
+    return (node.nodeType==3 ? node.nodeValue : 
+      (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+  }).flatten().join('');
+}
+
+Element.collectTextNodesIgnoreClass = function(element, className) {  
+  return $A($(element).childNodes).collect( function(node) {
+    return (node.nodeType==3 ? node.nodeValue : 
+      ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? 
+        Element.collectTextNodes(node) : ''));
+  }).flatten().join('');
+}
+
+Element.setStyle = function(element, style) {
+  element = $(element);
+  for(k in style) element.style[k.camelize()] = style[k];
+}
+
+Element.setContentZoom = function(element, percent) {  
+  Element.setStyle(element, {fontSize: (percent/100) + 'em'});   
+  if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);  
+}
+
+Element.getOpacity = function(element){  
+  var opacity;
+  if (opacity = Element.getStyle(element, 'opacity'))  
+    return parseFloat(opacity);  
+  if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/))  
+    if(opacity[1]) return parseFloat(opacity[1]) / 100;  
+  return 1.0;  
+}
+
+Element.setOpacity = function(element, value){  
+  element= $(element);  
+  if (value == 1){
+    Element.setStyle(element, { opacity: 
+      (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 
+      0.999999 : null });
+    if(/MSIE/.test(navigator.userAgent))  
+      Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')});  
+  } else {  
+    if(value < 0.00001) value = 0;  
+    Element.setStyle(element, {opacity: value});
+    if(/MSIE/.test(navigator.userAgent))  
+     Element.setStyle(element, 
+       { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') +
+                 'alpha(opacity='+value*100+')' });  
+  }   
+}  
+ 
+Element.getInlineOpacity = function(element){  
+  return $(element).style.opacity || '';
+}  
+
+Element.childrenWithClassName = function(element, className) {  
+  return $A($(element).getElementsByTagName('*')).select(
+    function(c) { return Element.hasClassName(c, className) });
+}
+
+Array.prototype.call = function() {
+  var args = arguments;
+  this.each(function(f){ f.apply(this, args) });
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+  tagifyText: function(element) {
+    var tagifyStyle = 'position:relative';
+    if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1';
+    element = $(element);
+    $A(element.childNodes).each( function(child) {
+      if(child.nodeType==3) {
+        child.nodeValue.toArray().each( function(character) {
+          element.insertBefore(
+            Builder.node('span',{style: tagifyStyle},
+              character == ' ' ? String.fromCharCode(160) : character), 
+              child);
+        });
+        Element.remove(child);
+      }
+    });
+  },
+  multiple: function(element, effect) {
+    var elements;
+    if(((typeof element == 'object') || 
+        (typeof element == 'function')) && 
+       (element.length))
+      elements = element;
+    else
+      elements = $(element).childNodes;
+      
+    var options = Object.extend({
+      speed: 0.1,
+      delay: 0.0
+    }, arguments[2] || {});
+    var masterDelay = options.delay;
+
+    $A(elements).each( function(element, index) {
+      new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+    });
+  },
+  PAIRS: {
+    'slide':  ['SlideDown','SlideUp'],
+    'blind':  ['BlindDown','BlindUp'],
+    'appear': ['Appear','Fade']
+  },
+  toggle: function(element, effect) {
+    element = $(element);
+    effect = (effect || 'appear').toLowerCase();
+    var options = Object.extend({
+      queue: { position:'end', scope:(element.id || 'global') }
+    }, arguments[2] || {});
+    Effect[Element.visible(element) ? 
+      Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+  }
+};
+
+var Effect2 = Effect; // deprecated
+
+/* ------------- transitions ------------- */
+
+Effect.Transitions = {}
+
+Effect.Transitions.linear = function(pos) {
+  return pos;
+}
+Effect.Transitions.sinoidal = function(pos) {
+  return (-Math.cos(pos*Math.PI)/2) + 0.5;
+}
+Effect.Transitions.reverse  = function(pos) {
+  return 1-pos;
+}
+Effect.Transitions.flicker = function(pos) {
+  return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+}
+Effect.Transitions.wobble = function(pos) {
+  return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+}
+Effect.Transitions.pulse = function(pos) {
+  return (Math.floor(pos*10) % 2 == 0 ? 
+    (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10)));
+}
+Effect.Transitions.none = function(pos) {
+  return 0;
+}
+Effect.Transitions.full = function(pos) {
+  return 1;
+}
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create();
+Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
+  initialize: function() {
+    this.effects  = [];
+    this.interval = null;
+  },
+  _each: function(iterator) {
+    this.effects._each(iterator);
+  },
+  add: function(effect) {
+    var timestamp = new Date().getTime();
+    
+    var position = (typeof effect.options.queue == 'string') ? 
+      effect.options.queue : effect.options.queue.position;
+    
+    switch(position) {
+      case 'front':
+        // move unstarted effects after this effect  
+        this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+            e.startOn  += effect.finishOn;
+            e.finishOn += effect.finishOn;
+          });
+        break;
+      case 'end':
+        // start effect after last queued effect has finished
+        timestamp = this.effects.pluck('finishOn').max() || timestamp;
+        break;
+    }
+    
+    effect.startOn  += timestamp;
+    effect.finishOn += timestamp;
+    this.effects.push(effect);
+    if(!this.interval) 
+      this.interval = setInterval(this.loop.bind(this), 40);
+  },
+  remove: function(effect) {
+    this.effects = this.effects.reject(function(e) { return e==effect });
+    if(this.effects.length == 0) {
+      clearInterval(this.interval);
+      this.interval = null;
+    }
+  },
+  loop: function() {
+    var timePos = new Date().getTime();
+    this.effects.invoke('loop', timePos);
+  }
+});
+
+Effect.Queues = {
+  instances: $H(),
+  get: function(queueName) {
+    if(typeof queueName != 'string') return queueName;
+    
+    if(!this.instances[queueName])
+      this.instances[queueName] = new Effect.ScopedQueue();
+      
+    return this.instances[queueName];
+  }
+}
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.DefaultOptions = {
+  transition: Effect.Transitions.sinoidal,
+  duration:   1.0,   // seconds
+  fps:        25.0,  // max. 25fps due to Effect.Queue implementation
+  sync:       false, // true for combining
+  from:       0.0,
+  to:         1.0,
+  delay:      0.0,
+  queue:      'parallel'
+}
+
+Effect.Base = function() {};
+Effect.Base.prototype = {
+  position: null,
+  start: function(options) {
+    this.options      = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
+    this.currentFrame = 0;
+    this.state        = 'idle';
+    this.startOn      = this.options.delay*1000;
+    this.finishOn     = this.startOn + (this.options.duration*1000);
+    this.event('beforeStart');
+    if(!this.options.sync)
+      Effect.Queues.get(typeof this.options.queue == 'string' ? 
+        'global' : this.options.queue.scope).add(this);
+  },
+  loop: function(timePos) {
+    if(timePos >= this.startOn) {
+      if(timePos >= this.finishOn) {
+        this.render(1.0);
+        this.cancel();
+        this.event('beforeFinish');
+        if(this.finish) this.finish(); 
+        this.event('afterFinish');
+        return;  
+      }
+      var pos   = (timePos - this.startOn) / (this.finishOn - this.startOn);
+      var frame = Math.round(pos * this.options.fps * this.options.duration);
+      if(frame > this.currentFrame) {
+        this.render(pos);
+        this.currentFrame = frame;
+      }
+    }
+  },
+  render: function(pos) {
+    if(this.state == 'idle') {
+      this.state = 'running';
+      this.event('beforeSetup');
+      if(this.setup) this.setup();
+      this.event('afterSetup');
+    }
+    if(this.state == 'running') {
+      if(this.options.transition) pos = this.options.transition(pos);
+      pos *= (this.options.to-this.options.from);
+      pos += this.options.from;
+      this.position = pos;
+      this.event('beforeUpdate');
+      if(this.update) this.update(pos);
+      this.event('afterUpdate');
+    }
+  },
+  cancel: function() {
+    if(!this.options.sync)
+      Effect.Queues.get(typeof this.options.queue == 'string' ? 
+        'global' : this.options.queue.scope).remove(this);
+    this.state = 'finished';
+  },
+  event: function(eventName) {
+    if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+    if(this.options[eventName]) this.options[eventName](this);
+  },
+  inspect: function() {
+    return '#<Effect:' + $H(this).inspect() + ',options:' + $H(this.options).inspect() + '>';
+  }
+}
+
+Effect.Parallel = Class.create();
+Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
+  initialize: function(effects) {
+    this.effects = effects || [];
+    this.start(arguments[1]);
+  },
+  update: function(position) {
+    this.effects.invoke('render', position);
+  },
+  finish: function(position) {
+    this.effects.each( function(effect) {
+      effect.render(1.0);
+      effect.cancel();
+      effect.event('beforeFinish');
+      if(effect.finish) effect.finish(position);
+      effect.event('afterFinish');
+    });
+  }
+});
+
+Effect.Opacity = Class.create();
+Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
+  initialize: function(element) {
+    this.element = $(element);
+    // make this work on IE on elements without 'layout'
+    if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout))
+      Element.setStyle(this.element, {zoom: 1});
+    var options = Object.extend({
+      from: Element.getOpacity(this.element) || 0.0,
+      to:   1.0
+    }, arguments[1] || {});
+    this.start(options);
+  },
+  update: function(position) {
+    Element.setOpacity(this.element, position);
+  }
+});
+
+Effect.Move = Class.create();
+Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
+  initialize: function(element) {
+    this.element = $(element);
+    var options = Object.extend({
+      x:    0,
+      y:    0,
+      mode: 'relative'
+    }, arguments[1] || {});
+    this.start(options);
+  },
+  setup: function() {
+    // Bug in Opera: Opera returns the "real" position of a static element or
+    // relative element that does not have top/left explicitly set.
+    // ==> Always set top and left for position relative elements in your stylesheets 
+    // (to 0 if you do not need them) 
+    Element.makePositioned(this.element);
+    this.originalLeft = parseFloat(Element.getStyle(this.element,'left') || '0');
+    this.originalTop  = parseFloat(Element.getStyle(this.element,'top')  || '0');
+    if(this.options.mode == 'absolute') {
+      // absolute movement, so we need to calc deltaX and deltaY
+      this.options.x = this.options.x - this.originalLeft;
+      this.options.y = this.options.y - this.originalTop;
+    }
+  },
+  update: function(position) {
+    Element.setStyle(this.element, {
+      left: this.options.x  * position + this.originalLeft + 'px',
+      top:  this.options.y  * position + this.originalTop  + 'px'
+    });
+  }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+  return new Effect.Move(element, 
+    Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
+};
+
+Effect.Scale = Class.create();
+Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
+  initialize: function(element, percent) {
+    this.element = $(element)
+    var options = Object.extend({
+      scaleX: true,
+      scaleY: true,
+      scaleContent: true,
+      scaleFromCenter: false,
+      scaleMode: 'box',        // 'box' or 'contents' or {} with provided values
+      scaleFrom: 100.0,
+      scaleTo:   percent
+    }, arguments[2] || {});
+    this.start(options);
+  },
+  setup: function() {
+    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+    this.elementPositioning = Element.getStyle(this.element,'position');
+    
+    this.originalStyle = {};
+    ['top','left','width','height','fontSize'].each( function(k) {
+      this.originalStyle[k] = this.element.style[k];
+    }.bind(this));
+      
+    this.originalTop  = this.element.offsetTop;
+    this.originalLeft = this.element.offsetLeft;
+    
+    var fontSize = Element.getStyle(this.element,'font-size') || '100%';
+    ['em','px','%'].each( function(fontSizeType) {
+      if(fontSize.indexOf(fontSizeType)>0) {
+        this.fontSize     = parseFloat(fontSize);
+        this.fontSizeType = fontSizeType;
+      }
+    }.bind(this));
+    
+    this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+    
+    this.dims = null;
+    if(this.options.scaleMode=='box')
+      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+    if(/^content/.test(this.options.scaleMode))
+      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+    if(!this.dims)
+      this.dims = [this.options.scaleMode.originalHeight,
+                   this.options.scaleMode.originalWidth];
+  },
+  update: function(position) {
+    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+    if(this.options.scaleContent && this.fontSize)
+      Element.setStyle(this.element, {fontSize: this.fontSize * currentScale + this.fontSizeType });
+    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+  },
+  finish: function(position) {
+    if (this.restoreAfterFinish) Element.setStyle(this.element, this.originalStyle);
+  },
+  setDimensions: function(height, width) {
+    var d = {};
+    if(this.options.scaleX) d.width = width + 'px';
+    if(this.options.scaleY) d.height = height + 'px';
+    if(this.options.scaleFromCenter) {
+      var topd  = (height - this.dims[0])/2;
+      var leftd = (width  - this.dims[1])/2;
+      if(this.elementPositioning == 'absolute') {
+        if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
+        if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+      } else {
+        if(this.options.scaleY) d.top = -topd + 'px';
+        if(this.options.scaleX) d.left = -leftd + 'px';
+      }
+    }
+    Element.setStyle(this.element, d);
+  }
+});
+
+Effect.Highlight = Class.create();
+Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
+  initialize: function(element) {
+    this.element = $(element);
+    var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
+    this.start(options);
+  },
+  setup: function() {
+    // Prevent executing on elements not in the layout flow
+    if(Element.getStyle(this.element, 'display')=='none') { this.cancel(); return; }
+    // Disable background image during the effect
+    this.oldStyle = {
+      backgroundImage: Element.getStyle(this.element, 'background-image') };
+    Element.setStyle(this.element, {backgroundImage: 'none'});
+    if(!this.options.endcolor)
+      this.options.endcolor = Element.getStyle(this.element, 'background-color').parseColor('#ffffff');
+    if(!this.options.restorecolor)
+      this.options.restorecolor = Element.getStyle(this.element, 'background-color');
+    // init color calculations
+    this._base  = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+    this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+  },
+  update: function(position) {
+    Element.setStyle(this.element,{backgroundColor: $R(0,2).inject('#',function(m,v,i){
+      return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
+  },
+  finish: function() {
+    Element.setStyle(this.element, Object.extend(this.oldStyle, {
+      backgroundColor: this.options.restorecolor
+    }));
+  }
+});
+
+Effect.ScrollTo = Class.create();
+Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
+  initialize: function(element) {
+    this.element = $(element);
+    this.start(arguments[1] || {});
+  },
+  setup: function() {
+    Position.prepare();
+    var offsets = Position.cumulativeOffset(this.element);
+    if(this.options.offset) offsets[1] += this.options.offset;
+    var max = window.innerHeight ? 
+      window.height - window.innerHeight :
+      document.body.scrollHeight - 
+        (document.documentElement.clientHeight ? 
+          document.documentElement.clientHeight : document.body.clientHeight);
+    this.scrollStart = Position.deltaY;
+    this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
+  },
+  update: function(position) {
+    Position.prepare();
+    window.scrollTo(Position.deltaX, 
+      this.scrollStart + (position*this.delta));
+  }
+});
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+  var oldOpacity = Element.getInlineOpacity(element);
+  var options = Object.extend({
+  from: Element.getOpacity(element) || 1.0,
+  to:   0.0,
+  afterFinishInternal: function(effect) { with(Element) { 
+    if(effect.options.to!=0) return;
+    hide(effect.element);
+    setStyle(effect.element, {opacity: oldOpacity}); }}
+  }, arguments[1] || {});
+  return new Effect.Opacity(element,options);
+}
+
+Effect.Appear = function(element) {
+  var options = Object.extend({
+  from: (Element.getStyle(element, 'display') == 'none' ? 0.0 : Element.getOpacity(element) || 0.0),
+  to:   1.0,
+  beforeSetup: function(effect) { with(Element) {
+    setOpacity(effect.element, effect.options.from);
+    show(effect.element); }}
+  }, arguments[1] || {});
+  return new Effect.Opacity(element,options);
+}
+
+Effect.Puff = function(element) {
+  element = $(element);
+  var oldStyle = { opacity: Element.getInlineOpacity(element), position: Element.getStyle(element, 'position') };
+  return new Effect.Parallel(
+   [ new Effect.Scale(element, 200, 
+      { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), 
+     new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], 
+     Object.extend({ duration: 1.0, 
+      beforeSetupInternal: function(effect) { with(Element) {
+        setStyle(effect.effects[0].element, {position: 'absolute'}); }},
+      afterFinishInternal: function(effect) { with(Element) {
+         hide(effect.effects[0].element);
+         setStyle(effect.effects[0].element, oldStyle); }}
+     }, arguments[1] || {})
+   );
+}
+
+Effect.BlindUp = function(element) {
+  element = $(element);
+  Element.makeClipping(element);
+  return new Effect.Scale(element, 0, 
+    Object.extend({ scaleContent: false, 
+      scaleX: false, 
+      restoreAfterFinish: true,
+      afterFinishInternal: function(effect) { with(Element) {
+        [hide, undoClipping].call(effect.element); }} 
+    }, arguments[1] || {})
+  );
+}
+
+Effect.BlindDown = function(element) {
+  element = $(element);
+  var oldHeight = Element.getStyle(element, 'height');
+  var elementDimensions = Element.getDimensions(element);
+  return new Effect.Scale(element, 100, 
+    Object.extend({ scaleContent: false, 
+      scaleX: false,
+      scaleFrom: 0,
+      scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+      restoreAfterFinish: true,
+      afterSetup: function(effect) { with(Element) {
+        makeClipping(effect.element);
+        setStyle(effect.element, {height: '0px'});
+        show(effect.element); 
+      }},  
+      afterFinishInternal: function(effect) { with(Element) {
+        undoClipping(effect.element);
+        setStyle(effect.element, {height: oldHeight});
+      }}
+    }, arguments[1] || {})
+  );
+}
+
+Effect.SwitchOff = function(element) {
+  element = $(element);
+  var oldOpacity = Element.getInlineOpacity(element);
+  return new Effect.Appear(element, { 
+    duration: 0.4,
+    from: 0,
+    transition: Effect.Transitions.flicker,
+    afterFinishInternal: function(effect) {
+      new Effect.Scale(effect.element, 1, { 
+        duration: 0.3, scaleFromCenter: true,
+        scaleX: false, scaleContent: false, restoreAfterFinish: true,
+        beforeSetup: function(effect) { with(Element) {
+          [makePositioned,makeClipping].call(effect.element);
+        }},
+        afterFinishInternal: function(effect) { with(Element) {
+          [hide,undoClipping,undoPositioned].call(effect.element);
+          setStyle(effect.element, {opacity: oldOpacity});
+        }}
+      })
+    }
+  });
+}
+
+Effect.DropOut = function(element) {
+  element = $(element);
+  var oldStyle = {
+    top: Element.getStyle(element, 'top'),
+    left: Element.getStyle(element, 'left'),
+    opacity: Element.getInlineOpacity(element) };
+  return new Effect.Parallel(
+    [ new Effect.Move(element, {x: 0, y: 100, sync: true }), 
+      new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+    Object.extend(
+      { duration: 0.5,
+        beforeSetup: function(effect) { with(Element) {
+          makePositioned(effect.effects[0].element); }},
+        afterFinishInternal: function(effect) { with(Element) {
+          [hide, undoPositioned].call(effect.effects[0].element);
+          setStyle(effect.effects[0].element, oldStyle); }} 
+      }, arguments[1] || {}));
+}
+
+Effect.Shake = function(element) {
+  element = $(element);
+  var oldStyle = {
+    top: Element.getStyle(element, 'top'),
+    left: Element.getStyle(element, 'left') };
+	  return new Effect.Move(element, 
+	    { x:  20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
+	  new Effect.Move(effect.element,
+	    { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
+	  new Effect.Move(effect.element,
+	    { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
+	  new Effect.Move(effect.element,
+	    { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
+	  new Effect.Move(effect.element,
+	    { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
+	  new Effect.Move(effect.element,
+	    { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { with(Element) {
+        undoPositioned(effect.element);
+        setStyle(effect.element, oldStyle);
+  }}}) }}) }}) }}) }}) }});
+}
+
+Effect.SlideDown = function(element) {
+  element = $(element);
+  Element.cleanWhitespace(element);
+  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+  var oldInnerBottom = Element.getStyle(element.firstChild, 'bottom');
+  var elementDimensions = Element.getDimensions(element);
+  return new Effect.Scale(element, 100, Object.extend({ 
+    scaleContent: false, 
+    scaleX: false, 
+    scaleFrom: 0,
+    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+    restoreAfterFinish: true,
+    afterSetup: function(effect) { with(Element) {
+      makePositioned(effect.element);
+      makePositioned(effect.element.firstChild);
+      if(window.opera) setStyle(effect.element, {top: ''});
+      makeClipping(effect.element);
+      setStyle(effect.element, {height: '0px'});
+      show(element); }},
+    afterUpdateInternal: function(effect) { with(Element) {
+      setStyle(effect.element.firstChild, {bottom:
+        (effect.dims[0] - effect.element.clientHeight) + 'px' }); }},
+    afterFinishInternal: function(effect) { with(Element) {
+      undoClipping(effect.element); 
+      undoPositioned(effect.element.firstChild);
+      undoPositioned(effect.element);
+      setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); }}
+    }, arguments[1] || {})
+  );
+}
+  
+Effect.SlideUp = function(element) {
+  element = $(element);
+  Element.cleanWhitespace(element);
+  var oldInnerBottom = Element.getStyle(element.firstChild, 'bottom');
+  return new Effect.Scale(element, 0, 
+   Object.extend({ scaleContent: false, 
+    scaleX: false, 
+    scaleMode: 'box',
+    scaleFrom: 100,
+    restoreAfterFinish: true,
+    beforeStartInternal: function(effect) { with(Element) {
+      makePositioned(effect.element);
+      makePositioned(effect.element.firstChild);
+      if(window.opera) setStyle(effect.element, {top: ''});
+      makeClipping(effect.element);
+      show(element); }},  
+    afterUpdateInternal: function(effect) { with(Element) {
+      setStyle(effect.element.firstChild, {bottom:
+        (effect.dims[0] - effect.element.clientHeight) + 'px' }); }},
+    afterFinishInternal: function(effect) { with(Element) {
+        [hide, undoClipping].call(effect.element); 
+        undoPositioned(effect.element.firstChild);
+        undoPositioned(effect.element);
+        setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); }}
+   }, arguments[1] || {})
+  );
+}
+
+// Bug in opera makes the TD containing this element expand for a instance after finish 
+Effect.Squish = function(element) {
+  return new Effect.Scale(element, window.opera ? 1 : 0, 
+    { restoreAfterFinish: true,
+      beforeSetup: function(effect) { with(Element) {
+        makeClipping(effect.element); }},  
+      afterFinishInternal: function(effect) { with(Element) {
+        hide(effect.element); 
+        undoClipping(effect.element); }}
+  });
+}
+
+Effect.Grow = function(element) {
+  element = $(element);
+  var options = Object.extend({
+    direction: 'center',
+    moveTransistion: Effect.Transitions.sinoidal,
+    scaleTransition: Effect.Transitions.sinoidal,
+    opacityTransition: Effect.Transitions.full
+  }, arguments[1] || {});
+  var oldStyle = {
+    top: element.style.top,
+    left: element.style.left,
+    height: element.style.height,
+    width: element.style.width,
+    opacity: Element.getInlineOpacity(element) };
+
+  var dims = Element.getDimensions(element);    
+  var initialMoveX, initialMoveY;
+  var moveX, moveY;
+  
+  switch (options.direction) {
+    case 'top-left':
+      initialMoveX = initialMoveY = moveX = moveY = 0; 
+      break;
+    case 'top-right':
+      initialMoveX = dims.width;
+      initialMoveY = moveY = 0;
+      moveX = -dims.width;
+      break;
+    case 'bottom-left':
+      initialMoveX = moveX = 0;
+      initialMoveY = dims.height;
+      moveY = -dims.height;
+      break;
+    case 'bottom-right':
+      initialMoveX = dims.width;
+      initialMoveY = dims.height;
+      moveX = -dims.width;
+      moveY = -dims.height;
+      break;
+    case 'center':
+      initialMoveX = dims.width / 2;
+      initialMoveY = dims.height / 2;
+      moveX = -dims.width / 2;
+      moveY = -dims.height / 2;
+      break;
+  }
+  
+  return new Effect.Move(element, {
+    x: initialMoveX,
+    y: initialMoveY,
+    duration: 0.01, 
+    beforeSetup: function(effect) { with(Element) {
+      hide(effect.element);
+      makeClipping(effect.element);
+      makePositioned(effect.element);
+    }},
+    afterFinishInternal: function(effect) {
+      new Effect.Parallel(
+        [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+          new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+          new Effect.Scale(effect.element, 100, {
+            scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, 
+            sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+        ], Object.extend({
+             beforeSetup: function(effect) { with(Element) {
+               setStyle(effect.effects[0].element, {height: '0px'});
+               show(effect.effects[0].element); }},
+             afterFinishInternal: function(effect) { with(Element) {
+               [undoClipping, undoPositioned].call(effect.effects[0].element); 
+               setStyle(effect.effects[0].element, oldStyle); }}
+           }, options)
+      )
+    }
+  });
+}
+
+Effect.Shrink = function(element) {
+  element = $(element);
+  var options = Object.extend({
+    direction: 'center',
+    moveTransistion: Effect.Transitions.sinoidal,
+    scaleTransition: Effect.Transitions.sinoidal,
+    opacityTransition: Effect.Transitions.none
+  }, arguments[1] || {});
+  var oldStyle = {
+    top: element.style.top,
+    left: element.style.left,
+    height: element.style.height,
+    width: element.style.width,
+    opacity: Element.getInlineOpacity(element) };
+
+  var dims = Element.getDimensions(element);
+  var moveX, moveY;
+  
+  switch (options.direction) {
+    case 'top-left':
+      moveX = moveY = 0;
+      break;
+    case 'top-right':
+      moveX = dims.width;
+      moveY = 0;
+      break;
+    case 'bottom-left':
+      moveX = 0;
+      moveY = dims.height;
+      break;
+    case 'bottom-right':
+      moveX = dims.width;
+      moveY = dims.height;
+      break;
+    case 'center':  
+      moveX = dims.width / 2;
+      moveY = dims.height / 2;
+      break;
+  }
+  
+  return new Effect.Parallel(
+    [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+      new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+      new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+    ], Object.extend({            
+         beforeStartInternal: function(effect) { with(Element) {
+           [makePositioned, makeClipping].call(effect.effects[0].element) }},
+         afterFinishInternal: function(effect) { with(Element) {
+           [hide, undoClipping, undoPositioned].call(effect.effects[0].element);
+           setStyle(effect.effects[0].element, oldStyle); }}
+       }, options)
+  );
+}
+
+Effect.Pulsate = function(element) {
+  element = $(element);
+  var options    = arguments[1] || {};
+  var oldOpacity = Element.getInlineOpacity(element);
+  var transition = options.transition || Effect.Transitions.sinoidal;
+  var reverser   = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) };
+  reverser.bind(transition);
+  return new Effect.Opacity(element, 
+    Object.extend(Object.extend({  duration: 3.0, from: 0,
+      afterFinishInternal: function(effect) { Element.setStyle(effect.element, {opacity: oldOpacity}); }
+    }, options), {transition: reverser}));
+}
+
+Effect.Fold = function(element) {
+  element = $(element);
+  var oldStyle = {
+    top: element.style.top,
+    left: element.style.left,
+    width: element.style.width,
+    height: element.style.height };
+  Element.makeClipping(element);
+  return new Effect.Scale(element, 5, Object.extend({   
+    scaleContent: false,
+    scaleX: false,
+    afterFinishInternal: function(effect) {
+    new Effect.Scale(element, 1, { 
+      scaleContent: false, 
+      scaleY: false,
+      afterFinishInternal: function(effect) { with(Element) {
+        [hide, undoClipping].call(effect.element); 
+        setStyle(effect.element, oldStyle);
+      }} });
+  }}, arguments[1] || {}));
+}

Propchange: incubator/roller/branches/roller_3.0/web/themes/andreas08/scripts/effects.js
------------------------------------------------------------------------------
    svn:executable = *