roller-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From snoopd...@apache.org
Subject svn commit: r1201435 [2/3] - in /roller/trunk: weblogger-web/src/main/java/org/apache/roller/weblogger/ui/rendering/ weblogger-web/src/main/java/org/apache/roller/weblogger/ui/rendering/mobile/ weblogger-web/src/main/java/org/apache/roller/weblogger/ui...
Date Sun, 13 Nov 2011 15:01:38 GMT
Modified: roller/trunk/weblogger-webapp/src/main/webapp/WEB-INF/jsps/editor/TemplateEdit.jsp
URL: http://svn.apache.org/viewvc/roller/trunk/weblogger-webapp/src/main/webapp/WEB-INF/jsps/editor/TemplateEdit.jsp?rev=1201435&r1=1201434&r2=1201435&view=diff
==============================================================================
--- roller/trunk/weblogger-webapp/src/main/webapp/WEB-INF/jsps/editor/TemplateEdit.jsp (original)
+++ roller/trunk/weblogger-webapp/src/main/webapp/WEB-INF/jsps/editor/TemplateEdit.jsp Sun Nov 13 15:01:36 2011
@@ -16,6 +16,12 @@
   directory of this distribution.
 --%>
 <%@ include file="/WEB-INF/jsps/taglibs-struts2.jsp" %>
+<script type="text/javascript" 
+    src="<s:url value='/roller-ui/yui/yahoo-dom-event/yahoo-dom-event.js'></s:url>"></script>
+<script type="text/javascript" 
+    src="<s:url value='/roller-ui/yui/element/element-min.js'></s:url>"></script>
+<script type="text/javascript" 
+    src="<s:url value='/roller-ui/yui/tabview/tabview-min.js'></s:url>"></script>
 
 <p class="subtitle">
    <s:text name="pageForm.subtitle" >
@@ -61,51 +67,27 @@
             <td class="description"></td>
         </tr>
         
-        <script type="text/javascript">
-        <!--
-        var weblogURL = '<s:property value="actionWeblog.absoluteURL" />';
-        var originalLink = '<s:property value="bean.link" />';
-        var type = '<s:property value="bean.type" /> ' ;
-        
-        // Update page URL when user changes link
-        function updatePageURLDisplay() {
-            var previewSpan = document.getElementById('linkPreview');
-            var n1 = previewSpan.firstChild;
-            var n2 = document.createTextNode(document.getElementById('template_bean_link').value);
-            if (n1 == null) {
-                previewSpan.appendChild(n2);
-            } else {
-                previewSpan.replaceChild(n2, n1);
-            }           
-        }
-        // Don't launch page if user has changed link, it'll be a 404
-        function launchPage() {
-            if (originalLink != document.getElementById('template_bean_link').value) {
-                window.alert("Link changed, not launching page");
-            } else {
-                window.open(weblogURL + 'page/' + originalLink+'?type='+type, '_blank');
-            }
-        }
-        -->
-        </script>
-        
-        <s:if test="!template.required && template.custom">
+       <s:if test="!template.required && template.custom">
             <tr>
                 <td class="label" valign="top"><s:text name="pageForm.link" />&nbsp;</td>
                 <td class="field">
                     <s:textfield name="bean.link" size="50" onkeyup="updatePageURLDisplay()" />
                     <br />
-                    <s:property value="actionWeblog.absoluteURL" />page/<span id="linkPreview" style="color:red"><s:property value="bean.link" /></span>
-                    <s:if test="template.link != null">[<a id="launchLink" onClick="launchPage()"><s:text name="pageForm.launch" /></a>]</s:if>
+                    <s:property value="actionWeblog.absoluteURL" />page/<span id="linkPreview" style="color:red">
+                        <s:property value="bean.link" /></span>
+                    <s:if test="template.link != null">[<a id="launchLink" onClick="launchPage()">
+                        <s:text name="pageForm.launch" /></a>]</s:if>
                 </td>
                 <td class="description"></td>
             </tr>
         </s:if>
         <tr>
-            <td class="label" valign="top" style="padding-top: 4px"><s:text name="pageForm.description" />&nbsp;</td>
+            <td class="label" valign="top" style="padding-top: 4px">
+                <s:text name="pageForm.description" />&nbsp;</td>
             <td class="field">
                 <s:if test="template.required">
-                    <s:textarea name="bean.description" cols="50" rows="2" readonly="true" cssStyle="background: #e5e5e5" />
+                    <s:textarea name="bean.description" cols="50" rows="2" 
+                        readonly="true" cssStyle="background: #e5e5e5" />
                 </s:if>
                 <s:else>
                     <s:textarea name="bean.description" cols="50" rows="2" />
@@ -116,89 +98,56 @@
         
     </table>
 
-     <s:set name="tabMenu" value="menu"/>
-     <s:set name="type" value="bean.type"/>
+    <%-- ================================================================== --%>
+    <%-- Tabs for each of the two content areas: Standard and Mobile --%>
 
-    <table class="menuTabTable" cellspacing="0" >
-     <tr>
-          <s:if test="%{#type=='standard'}">
-        <td class="menuTabSelected">
-    </s:if>
-    <s:else>
-        <td class="menuTabUnselected">
-    </s:else>
-
-          <div class="menu-tr">
-           <s:url id="edit" action="templateEdit">
-               <s:param name="weblog" value="actionWeblog.handle" />
-               <s:param name="bean.id" value="template.id" />
-               <s:param name="bean.type">standard</s:param>
-           </s:url>
-	       <div class="menu-tl">&nbsp;&nbsp;<s:a href="%{edit}">Standard</s:a>&nbsp;&nbsp; </div>
-	    </div></td>
-
-
-          <td class="menuTabSeparator"></td>
-        <s:if test="%{#type == 'mobile'}">
-        <td class="menuTabSelected">
-    </s:if>
-    <s:else>
-        <td class="menuTabUnselected">
-    </s:else>
-        <div class="menu-tr">
-
-           <s:url id="edit" action="templateEdit">
-               <s:param name="weblog" value="actionWeblog.handle" />
-               <s:param name="bean.id" value="template.id" />
-                 <s:param name="bean.type">mobile</s:param>
-           </s:url>
-	       <div class="menu-tl">&nbsp;&nbsp;<s:a href="%{edit}">Mobile</s:a>&nbsp;&nbsp; </div>
-	    </div></td>
+    <div id="template-code-tabs" class="yui-navset">
+    <ul class="yui-nav">
+        <li class="selected"><a href="#tabStandard"><em>Standard</em></a></li>
+        <li><a href="#tabMobile"><em>Mobile</em></a></li>
+    </ul>            
+    <div class="yui-content">
+        <div id="tabStandard">
+            <%-- Standard Tab --%> 
+            <s:textarea name="bean.contentsStandard" cols="80" rows="30" cssStyle="width:100%" />
 
-     </tr>
-        </table>
-    <%-- ================================================================== --%>
-    <%-- Template editing area w/resize buttons --%>
+        </div>
+        <div id="tabMobile">
+            <%-- Standard Tab --%> 
+            <s:textarea name="bean.contentsMobile" cols="80" rows="30" cssStyle="width:100%" />
+        </div>
+    </div>
+    </div>
 
+    <%-- ================================================================== --%>
+    <%-- Save, Close and Resize text area buttons--%>
 
-    <s:textarea name="bean.contents" cols="80" rows="30" cssStyle="width:100%" />
-    
     <script type="text/javascript"><!--
-        if (getCookie("editorSize1") != null) {
-            document.getElementById('template_bean_contents').rows = getCookie("editorSize1");
-        }
-        function changeSize(e, num) {
-            a = e.rows + num;
-            if (a > 0) e.rows = a;
-            var expires = new Date();
-            expires.setTime(expires.getTime() + 24 * 90 * 60 * 60 * 1000); // sets it for approx 90 days.
-            setCookie("editorSize",e.rows,expires);
-        }
-        function changeSize1(e, num) {
-            a = e.rows + num;
-            if (a > 0) e.rows = a;
-            var expires = new Date();
-            expires.setTime(expires.getTime() + 24 * 90 * 60 * 60 * 1000); // sets it for approx 90 days.
-            setCookie("editorSize1",e.rows,expires);
+        if (getCookie("templateEditorRows") != null) {
+            document.getElementById('template_bean_contentsMobile').rows = getCookie("templateEditorRows");
+            document.getElementById('template_bean_contentsStandard').rows = getCookie("templateEditorRows");
+        } else {
+            document.getElementById('template_bean_contentsMobile').rows = 20;
+            document.getElementById('template_bean_contentsStandard').rows = 20;
         }
+
     // --></script>
     <table style="width:100%">
         <tr>
             <td>
                 <s:submit value="%{getText('pageForm.save')}" />
-                <input type="button" value="<s:text name="application.done"/>" onclick="window.location='<s:url action="templates"><s:param name="weblog" value="%{weblog}"/></s:url>'" />
+                <input type="button" value='<s:text name="application.done"/>' 
+                    onclick='window.location=<s:url action="templates"><s:param name="weblog" value="%{weblog}"/></s:url>' />
             </td>
             <td align="right">
                 <!-- Add buttons to make this textarea taller or shorter -->
-                <input type="button" name="taller" value=" &darr; " 
-                       onclick="changeSize1(document.getElementById('template_bean_contents'), 5)" />
-                <input type="button" name="shorter" value=" &uarr; " 
-                       onclick="changeSize1(document.getElementById('template_bean_contents'), -5)" />
+                <input type="button" name="taller" value=" &darr; " onclick="changeSize1(5)" />
+                <input type="button" name="shorter" value=" &uarr; " onclick="changeSize1(-5)" />
             </td>
         </tr>
     </table>
-   
-    
+
+  
     <%-- ================================================================== --%>
     <%-- Advanced settings inside a control toggle --%>
     
@@ -228,18 +177,31 @@
                         }
                         // --></script>
                         <s:if test="bean.autoContentType">
-                            <input type="radio" name="bean.autoContentType" value="true" checked="true" onchange="showContentTypeField()" id="template_bean_autoContentType1"/> 
+                            <input type="radio" name="bean.autoContentType" 
+                                   value="true" checked="true" 
+                                   onchange="showContentTypeField()" 
+                                   id="template_bean_autoContentType1"/> 
                             <s:text name="pageForm.useAutoContentType" /><br />
                             
-                            <input type="radio" name="bean.autoContentType" value="false" onchange="showContentTypeField()" id="template_bean_autoContentType2"/>
+                            <input type="radio" name="bean.autoContentType" 
+                                   value="false" 
+                                   onchange="showContentTypeField()" 
+                                   id="template_bean_autoContentType2"/>
                             <s:text name="pageForm.useManualContentType" />
                             <s:textfield name="bean.manualContentType" />
                         </s:if>
                         <s:else>
-                            <input type="radio" name="bean.autoContentType" value="true" onchange="showContentTypeField()" id="template_bean_autoContentType1"/> 
+                            <input type="radio" name="bean.autoContentType" 
+                                   value="true" 
+                                   onchange="showContentTypeField()" 
+                                   id="template_bean_autoContentType1"/> 
                             <s:text name="pageForm.useAutoContentType" /><br />
                             
-                            <input type="radio" name="bean.autoContentType" value="false" checked="true" onchange="showContentTypeField()" id="template_bean_autoContentType2"/>
+                            <input type="radio" name="bean.autoContentType" 
+                                   value="false" 
+                                   checked="true" 
+                                   onchange="showContentTypeField()" 
+                                   id="template_bean_autoContentType2"/>
                             <s:text name="pageForm.useManualContentType" />
                             <s:textfield name="bean.manualContentType" />
                         </s:else>
@@ -285,3 +247,46 @@
     </s:if>
     
 </s:form>
+
+
+<script>
+var tabView = new YAHOO.widget.TabView('template-code-tabs');
+
+var weblogURL = '<s:property value="actionWeblog.absoluteURL" />';
+var originalLink = '<s:property value="bean.link" />';
+var type = '<s:property value="bean.type" /> ' ;
+
+// Update page URL when user changes link
+function updatePageURLDisplay() {
+    var previewSpan = document.getElementById('linkPreview');
+    var n1 = previewSpan.firstChild;
+    var n2 = document.createTextNode(document.getElementById('template_bean_link').value);
+    if (n1 == null) {
+        previewSpan.appendChild(n2);
+    } else {
+        previewSpan.replaceChild(n2, n1);
+    }           
+}
+// Don't launch page if user has changed link, it'll be a 404
+function launchPage() {
+    if (originalLink != document.getElementById('template_bean_link').value) {
+        window.alert("Link changed, not launching page");
+    } else {
+        window.open(weblogURL + 'page/' + originalLink+'?type='+type, '_blank');
+    }
+}
+function changeSize1(num) {
+    var standardElem = document.getElementById('template_bean_contentsStandard');
+    var mobileElem = document.getElementById('template_bean_contentsMobile');
+    a = standardElem.rows + num;
+    if (a > 0) {
+        standardElem.rows = a;
+        mobileElem.rows = a;
+    }
+    var expires = new Date();
+    expires.setTime(expires.getTime() + 24 * 90 * 60 * 60 * 1000); // sets it for approx 90 days.
+    setCookie("templateEditorRows", standardElem.rows, expires);
+}
+</script>
+        
+ 
\ No newline at end of file

Modified: roller/trunk/weblogger-webapp/src/main/webapp/WEB-INF/jsps/taglibs-struts2.jsp
URL: http://svn.apache.org/viewvc/roller/trunk/weblogger-webapp/src/main/webapp/WEB-INF/jsps/taglibs-struts2.jsp?rev=1201435&r1=1201434&r2=1201435&view=diff
==============================================================================
--- roller/trunk/weblogger-webapp/src/main/webapp/WEB-INF/jsps/taglibs-struts2.jsp (original)
+++ roller/trunk/weblogger-webapp/src/main/webapp/WEB-INF/jsps/taglibs-struts2.jsp Sun Nov 13 15:01:36 2011
@@ -17,11 +17,11 @@
 --%>
 <% response.setContentType("text/html; charset=UTF-8"); %>
 <%@ page language="java" contentType="text/html; charset=UTF-8" %>
-
 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"  prefix="fmt" %>
 <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
 <%@ taglib uri="/struts-tags" prefix="s" %>
 <%@ taglib uri="http://jakarta.apache.org/taglibs/string-1.1" prefix="str" %>
 
-
+<link rel="stylesheet" type="text/css" 
+   href='<s:url value="/roller-ui/yui/tabview/assets/skins/sam/tabview.css"></s:url>'</link>

Added: roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/border_tabs.css
URL: http://svn.apache.org/viewvc/roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/border_tabs.css?rev=1201435&view=auto
==============================================================================
--- roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/border_tabs.css (added)
+++ roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/border_tabs.css Sun Nov 13 15:01:36 2011
@@ -0,0 +1,54 @@
+/*
+Copyright (c) 2009, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.8.0r4
+*/
+.yui-navset .yui-nav li a, .yui-navset .yui-content {
+    border:1px solid #000;  /* label and content borders */
+}
+
+.yui-navset .yui-nav .selected a, .yui-navset .yui-nav a:hover, .yui-navset .yui-content {
+    background-color:#f6f7ee; /* active tab, tab hover, and content bgcolor */
+}
+
+.yui-navset .yui-nav li em { padding:.5em; } /* tab padding */
+
+/* defaults to orientation "top" */
+.yui-navset .yui-nav .selected a {
+    border-bottom-width:0; /* no bottom border for active tab */
+    padding-bottom:1px; /* to match height of other tabs */
+}
+
+.yui-navset .yui-content {
+    margin-top:-1px; /* for active tab overlap */
+}
+
+/* overrides for other orientations */
+
+.yui-navset-bottom .yui-nav .selected a {
+    border-width:0 1px 1px; /* no top border for active tab */
+    padding:1px 0 0; /* to match height of other tabs */
+}
+
+.yui-navset-bottom .yui-content {
+    margin:0 0 -1px; /* for active tab overlap */
+}
+
+.yui-navset-left .yui-nav li.selected a {
+    border-width:1px 0 1px 1px; /* no right border for active tab */
+    padding:0 1px 0 0; /* to match width of other tabs */
+}
+
+.yui-navset-left .yui-content {
+    margin:0 0 0 -1px; /* for active tab overlap */
+}
+
+.yui-navset-right .yui-nav li.selected a {
+    border-width:1px 1px 1px 0; /* no left border for active tab */
+    padding:0 0 0 1px; /* to match width of other tabs */
+}
+
+.yui-navset-right .yui-content {
+    margin:0 -1px 0 0; /* for active tab overlap */
+}
\ No newline at end of file

Added: roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/loading.gif
URL: http://svn.apache.org/viewvc/roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/loading.gif?rev=1201435&view=auto
==============================================================================
Binary file - no diff available.

Propchange: roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/loading.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/skin-sam.css
URL: http://svn.apache.org/viewvc/roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/skin-sam.css?rev=1201435&view=auto
==============================================================================
--- roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/skin-sam.css (added)
+++ roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/skin-sam.css Sun Nov 13 15:01:36 2011
@@ -0,0 +1,77 @@
+/*
+Copyright (c) 2009, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.8.0r4
+*/
+.yui-navset .yui-nav li {
+    margin-right:0.16em; /* space between tabs */
+    padding-top:1px; /* gecko: make room for overflow */
+    zoom:1;
+}
+
+.yui-navset .yui-nav .selected { 
+    margin-bottom:-1px; /* for overlap */
+}
+
+.yui-navset .yui-nav a {
+    background:#dadbdb url(../../assets/skins/sam/sprite.png) repeat-x; /* sprite position for normal gradient */
+    border:solid #a3a3a3;
+    border-width:0 1px;
+    color:#000;
+    text-decoration:none;
+}
+
+.yui-navset .yui-nav li a em {
+    border-top:solid 1px #a3a3a3;
+    border-bottom:0;
+    cursor:hand;
+    padding:0.2em 0.5em;
+    top:-1px; /* for 1px rounded corners */
+    position:relative;
+}
+
+.yui-navset .yui-nav .selected a,
+.yui-navset .yui-nav a:focus,
+.yui-navset .yui-nav a:hover {
+    background:#214197 url(../../assets/skins/sam/sprite.png) repeat-x left -1400px;
+    color:#fff;
+}
+
+.yui-navset .yui-nav .selected a em {
+    padding:0.3em 0.5em; /* raise selected tab */
+}
+
+.yui-navset .yui-nav .selected a,
+.yui-navset .yui-nav a:hover,
+.yui-navset .yui-nav a:focus {
+    border-color:#243356;
+}
+
+.yui-navset .yui-nav a:hover em,
+.yui-navset .yui-nav a:focus em,
+.yui-navset .yui-nav .selected a em {
+    border-color:#233356 #406ed9;
+}
+
+.yui-navset .yui-nav {
+    border-bottom:1px solid #243356;
+    position:relative;
+    zoom:1;
+}
+
+.yui-navset .yui-content {
+    background:#abceff;
+    border-top:5px solid #214095;
+}
+
+.yui-navset .yui-content div {
+    border:1px solid #808080;
+    border-top-color:#243356;
+    padding:0.25em 0.5em;
+}
+
+.yui-navset .yui-content div div { /* kill inheritance */
+    border:0; 
+    padding:0;
+}

Added: roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/skins/sam/tabview-skin.css
URL: http://svn.apache.org/viewvc/roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/skins/sam/tabview-skin.css?rev=1201435&view=auto
==============================================================================
--- roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/skins/sam/tabview-skin.css (added)
+++ roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/skins/sam/tabview-skin.css Sun Nov 13 15:01:36 2011
@@ -0,0 +1,186 @@
+/*
+Copyright (c) 2009, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.8.0r4
+*/
+/* .yui-navset defaults to .yui-navset-top */
+.yui-skin-sam .yui-navset .yui-nav,
+.yui-skin-sam .yui-navset .yui-navset-top .yui-nav { /* protect nested tabviews from other orientations */
+    border:solid #2647a0; /* color between tab list and content */
+    border-width:0 0 5px;
+    zoom:1;
+}
+
+.yui-skin-sam .yui-navset .yui-nav li,
+.yui-skin-sam .yui-navset .yui-navset-top .yui-nav li {
+    margin:0 0.16em 0 0; /* space between tabs */
+    padding:1px 0 0; /* gecko: make room for overflow */
+    zoom:1;
+}
+
+.yui-skin-sam .yui-navset .yui-nav .selected,
+.yui-skin-sam .yui-navset .yui-navset-top .yui-nav .selected { 
+    margin:0 0.16em -1px 0; /* for overlap */
+}
+
+.yui-skin-sam .yui-navset .yui-nav a,
+.yui-skin-sam .yui-navset .yui-navset-top .yui-nav a {
+    background:#d8d8d8 url(../../../../assets/skins/sam/sprite.png) repeat-x; /* tab background */
+    border:solid #a3a3a3;
+    border-width:0 1px;
+    color:#000;
+    position:relative;
+    text-decoration:none;
+}
+
+.yui-skin-sam .yui-navset .yui-nav a em,
+.yui-skin-sam .yui-navset .yui-navset-top .yui-nav a em {
+    border:solid #a3a3a3;
+    border-width:1px 0 0;
+    cursor:hand;
+    padding:0.25em .75em;
+    left:0; right: 0; bottom: 0; /* protect from other orientations */
+    top:-1px; /* for 1px rounded corners */
+    position:relative;
+}
+
+.yui-skin-sam .yui-navset .yui-nav .selected a,
+.yui-skin-sam .yui-navset .yui-nav .selected a:focus, /* no focus effect for selected */
+.yui-skin-sam .yui-navset .yui-nav .selected a:hover { /* no hover effect for selected */
+    background:#2647a0 url(../../../../assets/skins/sam/sprite.png) repeat-x left -1400px; /* selected tab background */
+    color:#fff;
+}
+
+.yui-skin-sam .yui-navset .yui-nav a:hover,
+.yui-skin-sam .yui-navset .yui-nav a:focus {
+    background:#bfdaff url(../../../../assets/skins/sam/sprite.png) repeat-x left -1300px; /* selected tab background */
+    outline:0;
+}
+
+.yui-skin-sam .yui-navset .yui-nav .selected a em {
+    padding:0.35em 0.75em; /* raise selected tab */
+}
+
+.yui-skin-sam .yui-navset .yui-nav .selected a,
+.yui-skin-sam .yui-navset .yui-nav .selected a em {
+    border-color:#243356; /* selected tab border color */
+}
+
+.yui-skin-sam .yui-navset .yui-content {
+    background:#edf5ff; /* content background color */
+}
+
+.yui-skin-sam .yui-navset .yui-content,
+.yui-skin-sam .yui-navset .yui-navset-top .yui-content {
+    border:1px solid #808080; /* content border */
+    border-top-color:#243356; /* different border color */
+    padding:0.25em 0.5em; /* content padding */
+}
+
+/* left and right orientations */
+.yui-skin-sam .yui-navset-left .yui-nav,
+.yui-skin-sam .yui-navset .yui-navset-left .yui-nav,
+.yui-skin-sam .yui-navset .yui-navset-right .yui-nav,
+.yui-skin-sam .yui-navset-right .yui-nav {
+    border-width:0 5px 0 0;
+    Xposition:absolute; /* from tabview-core; have to reiterate for skin-sam due to pos:rel on skin-sam yui-nav */
+    top:0; bottom:0; /* stretch to fill content height */
+}
+
+.yui-skin-sam .yui-navset .yui-navset-right .yui-nav,
+.yui-skin-sam .yui-navset-right .yui-nav {
+    border-width:0 0 0 5px;
+}
+
+.yui-skin-sam .yui-navset-left .yui-nav li,
+.yui-skin-sam .yui-navset .yui-navset-left .yui-nav li,
+.yui-skin-sam .yui-navset-right .yui-nav li {
+    margin:0 0 0.16em; /* space between tabs */
+    padding:0 0 0 1px; /* gecko: make room for overflow */
+}
+
+.yui-skin-sam .yui-navset-right .yui-nav li {
+    padding:0 1px 0 0; /* gecko: make room for overflow */
+}
+
+.yui-skin-sam .yui-navset-left .yui-nav .selected,
+.yui-skin-sam .yui-navset .yui-navset-left .yui-nav .selected { 
+    margin:0 -1px 0.16em 0;
+}
+
+.yui-skin-sam .yui-navset-right .yui-nav .selected { 
+    margin:0 0 0.16em -1px;
+}
+
+.yui-skin-sam .yui-navset-left .yui-nav a,
+.yui-skin-sam .yui-navset-right .yui-nav a {
+    border-width:1px 0;
+}
+
+.yui-skin-sam .yui-navset-left .yui-nav a em,
+.yui-skin-sam .yui-navset .yui-navset-left .yui-nav a em,
+.yui-skin-sam .yui-navset-right .yui-nav a em {
+    border-width:0 0 0 1px;
+    padding:0.2em .75em;
+    top:auto;
+    left:-1px; /* for 1px rounded corners */
+}
+
+.yui-skin-sam .yui-navset-right .yui-nav a em {
+    border-width:0 1px 0 0;
+    left:auto;
+    right:-1px; /* for 1px rounded corners */
+}
+
+.yui-skin-sam .yui-navset-left .yui-nav a,
+.yui-skin-sam .yui-navset-left .yui-nav .selected a,
+.yui-skin-sam .yui-navset-left .yui-nav a:hover,
+.yui-skin-sam .yui-navset-right .yui-nav a,
+.yui-skin-sam .yui-navset-right .yui-nav .selected a,
+.yui-skin-sam .yui-navset-right .yui-nav a:hover,
+.yui-skin-sam .yui-navset-bottom .yui-nav a,
+.yui-skin-sam .yui-navset-bottom .yui-nav .selected a,
+.yui-skin-sam .yui-navset-bottom .yui-nav a:hover {
+    background-image:none; /* no left-right or bottom-top gradient */
+}
+
+.yui-skin-sam .yui-navset-left .yui-content {
+    border:1px solid #808080; /* content border */
+    border-left-color:#243356; /* different border color */
+}
+
+/* bottom orientation */
+.yui-skin-sam .yui-navset-bottom .yui-nav,
+.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav {
+    border-width:5px 0 0; /* color between tab list and content */
+}
+
+.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav .selected,
+.yui-skin-sam .yui-navset-bottom .yui-nav .selected { 
+    margin:-1px 0.16em 0 0; /* for overlap */
+}
+
+.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav li,
+.yui-skin-sam .yui-navset-bottom .yui-nav li { 
+    padding:0 0 1px 0; /* gecko: make room for overflow */
+    vertical-align:top;
+}
+
+.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav li a,
+.yui-skin-sam .yui-navset-bottom .yui-nav li a { 
+}
+
+.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav a em,
+.yui-skin-sam .yui-navset-bottom .yui-nav a em {
+    border-width:0 0 1px;
+    top:auto;
+    bottom:-1px; /* for 1px rounded corners */
+}
+
+.yui-skin-sam .yui-navset-bottom .yui-content,
+.yui-skin-sam .yui-navset .yui-navset-bottom .yui-content {
+    border:1px solid #808080; /* content border */
+    border-bottom-color:#243356; /* different border color */
+}
+

Added: roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/skins/sam/tabview.css
URL: http://svn.apache.org/viewvc/roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/skins/sam/tabview.css?rev=1201435&view=auto
==============================================================================
--- roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/skins/sam/tabview.css (added)
+++ roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/skins/sam/tabview.css Sun Nov 13 15:01:36 2011
@@ -0,0 +1,8 @@
+/*
+Copyright (c) 2009, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.8.0r4
+*/
+.yui-navset .yui-nav li,.yui-navset .yui-navset-top .yui-nav li,.yui-navset .yui-navset-bottom .yui-nav li{margin:0 .5em 0 0;}.yui-navset-left .yui-nav li,.yui-navset-right .yui-nav li{margin:0 0 .5em;}.yui-navset .yui-content .yui-hidden{border:0;height:0;width:0;padding:0;position:absolute;left:-999999px;overflow:hidden;visibility:hidden;}.yui-navset .yui-navset-left .yui-nav,.yui-navset .yui-navset-right .yui-nav,.yui-navset-left .yui-nav,.yui-navset-right .yui-nav{width:6em;}.yui-navset-top .yui-nav,.yui-navset-bottom .yui-nav{width:auto;}.yui-navset .yui-navset-left,.yui-navset-left{padding:0 0 0 6em;}.yui-navset-right{padding:0 6em 0 0;}.yui-navset-top,.yui-navset-bottom{padding:auto;}.yui-nav,.yui-nav li{margin:0;padding:0;list-style:none;}.yui-navset li em{font-style:normal;}.yui-navset{position:relative;zoom:1;}.yui-navset .yui-content,.yui-navset .yui-content div{zoom:1;}.yui-navset .yui-content:after{content:'';display:block;clear:both;}.yui-navset .yui-nav li,.yu
 i-navset .yui-navset-top .yui-nav li,.yui-navset .yui-navset-bottom .yui-nav li{display:inline-block;display:-moz-inline-stack;*display:inline;vertical-align:bottom;cursor:pointer;zoom:1;}.yui-navset-left .yui-nav li,.yui-navset-right .yui-nav li{display:block;}.yui-navset .yui-nav a{position:relative;}.yui-navset .yui-nav li a,.yui-navset-top .yui-nav li a,.yui-navset-bottom .yui-nav li a{display:block;display:inline-block;vertical-align:bottom;zoom:1;}.yui-navset-left .yui-nav li a,.yui-navset-right .yui-nav li a{display:block;}.yui-navset-bottom .yui-nav li a{vertical-align:text-top;}.yui-navset .yui-nav li a em,.yui-navset-top .yui-nav li a em,.yui-navset-bottom .yui-nav li a em{display:block;}.yui-navset .yui-navset-left .yui-nav,.yui-navset .yui-navset-right .yui-nav,.yui-navset-left .yui-nav,.yui-navset-right .yui-nav{position:absolute;z-index:1;}.yui-navset-top .yui-nav,.yui-navset-bottom .yui-nav{position:static;}.yui-navset .yui-navset-left .yui-nav,.yui-navset-lef
 t .yui-nav{left:0;right:auto;}.yui-navset .yui-navset-right .yui-nav,.yui-navset-right .yui-nav{right:0;left:auto;}.yui-skin-sam .yui-navset .yui-nav,.yui-skin-sam .yui-navset .yui-navset-top .yui-nav{border:solid #2647a0;border-width:0 0 5px;zoom:1;}.yui-skin-sam .yui-navset .yui-nav li,.yui-skin-sam .yui-navset .yui-navset-top .yui-nav li{margin:0 .16em 0 0;padding:1px 0 0;zoom:1;}.yui-skin-sam .yui-navset .yui-nav .selected,.yui-skin-sam .yui-navset .yui-navset-top .yui-nav .selected{margin:0 .16em -1px 0;}.yui-skin-sam .yui-navset .yui-nav a,.yui-skin-sam .yui-navset .yui-navset-top .yui-nav a{background:#d8d8d8 url(../../../../assets/skins/sam/sprite.png) repeat-x;border:solid #a3a3a3;border-width:0 1px;color:#000;position:relative;text-decoration:none;}.yui-skin-sam .yui-navset .yui-nav a em,.yui-skin-sam .yui-navset .yui-navset-top .yui-nav a em{border:solid #a3a3a3;border-width:1px 0 0;cursor:hand;padding:.25em .75em;left:0;right:0;bottom:0;top:-1px;position:relative
 ;}.yui-skin-sam .yui-navset .yui-nav .selected a,.yui-skin-sam .yui-navset .yui-nav .selected a:focus,.yui-skin-sam .yui-navset .yui-nav .selected a:hover{background:#2647a0 url(../../../../assets/skins/sam/sprite.png) repeat-x left -1400px;color:#fff;}.yui-skin-sam .yui-navset .yui-nav a:hover,.yui-skin-sam .yui-navset .yui-nav a:focus{background:#bfdaff url(../../../../assets/skins/sam/sprite.png) repeat-x left -1300px;outline:0;}.yui-skin-sam .yui-navset .yui-nav .selected a em{padding:.35em .75em;}.yui-skin-sam .yui-navset .yui-nav .selected a,.yui-skin-sam .yui-navset .yui-nav .selected a em{border-color:#243356;}.yui-skin-sam .yui-navset .yui-content{background:#edf5ff;}.yui-skin-sam .yui-navset .yui-content,.yui-skin-sam .yui-navset .yui-navset-top .yui-content{border:1px solid #808080;border-top-color:#243356;padding:.25em .5em;}.yui-skin-sam .yui-navset-left .yui-nav,.yui-skin-sam .yui-navset .yui-navset-left .yui-nav,.yui-skin-sam .yui-navset .yui-navset-right .yui
 -nav,.yui-skin-sam .yui-navset-right .yui-nav{border-width:0 5px 0 0;Xposition:absolute;top:0;bottom:0;}.yui-skin-sam .yui-navset .yui-navset-right .yui-nav,.yui-skin-sam .yui-navset-right .yui-nav{border-width:0 0 0 5px;}.yui-skin-sam .yui-navset-left .yui-nav li,.yui-skin-sam .yui-navset .yui-navset-left .yui-nav li,.yui-skin-sam .yui-navset-right .yui-nav li{margin:0 0 .16em;padding:0 0 0 1px;}.yui-skin-sam .yui-navset-right .yui-nav li{padding:0 1px 0 0;}.yui-skin-sam .yui-navset-left .yui-nav .selected,.yui-skin-sam .yui-navset .yui-navset-left .yui-nav .selected{margin:0 -1px .16em 0;}.yui-skin-sam .yui-navset-right .yui-nav .selected{margin:0 0 .16em -1px;}.yui-skin-sam .yui-navset-left .yui-nav a,.yui-skin-sam .yui-navset-right .yui-nav a{border-width:1px 0;}.yui-skin-sam .yui-navset-left .yui-nav a em,.yui-skin-sam .yui-navset .yui-navset-left .yui-nav a em,.yui-skin-sam .yui-navset-right .yui-nav a em{border-width:0 0 0 1px;padding:.2em .75em;top:auto;left:-1px;}.y
 ui-skin-sam .yui-navset-right .yui-nav a em{border-width:0 1px 0 0;left:auto;right:-1px;}.yui-skin-sam .yui-navset-left .yui-nav a,.yui-skin-sam .yui-navset-left .yui-nav .selected a,.yui-skin-sam .yui-navset-left .yui-nav a:hover,.yui-skin-sam .yui-navset-right .yui-nav a,.yui-skin-sam .yui-navset-right .yui-nav .selected a,.yui-skin-sam .yui-navset-right .yui-nav a:hover,.yui-skin-sam .yui-navset-bottom .yui-nav a,.yui-skin-sam .yui-navset-bottom .yui-nav .selected a,.yui-skin-sam .yui-navset-bottom .yui-nav a:hover{background-image:none;}.yui-skin-sam .yui-navset-left .yui-content{border:1px solid #808080;border-left-color:#243356;}.yui-skin-sam .yui-navset-bottom .yui-nav,.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav{border-width:5px 0 0;}.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav .selected,.yui-skin-sam .yui-navset-bottom .yui-nav .selected{margin:-1px .16em 0 0;}.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav li,.yui-skin-sam .yui-navset-bottom
  .yui-nav li{padding:0 0 1px 0;vertical-align:top;}.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav a em,.yui-skin-sam .yui-navset-bottom .yui-nav a em{border-width:0 0 1px;top:auto;bottom:-1px;}
+.yui-skin-sam .yui-navset-bottom .yui-content,.yui-skin-sam .yui-navset .yui-navset-bottom .yui-content{border:1px solid #808080;border-bottom-color:#243356;}

Added: roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/tabview-core.css
URL: http://svn.apache.org/viewvc/roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/tabview-core.css?rev=1201435&view=auto
==============================================================================
--- roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/tabview-core.css (added)
+++ roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/tabview-core.css Sun Nov 13 15:01:36 2011
@@ -0,0 +1,133 @@
+/*
+Copyright (c) 2009, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.8.0r4
+*/
+/* default space between tabs */
+.yui-navset .yui-nav li,
+.yui-navset .yui-navset-top .yui-nav li,
+.yui-navset .yui-navset-bottom .yui-nav li {
+    margin:0 0.5em 0 0; /* horizontal tabs */
+}
+.yui-navset-left .yui-nav li,
+.yui-navset-right .yui-nav li {
+    margin:0 0 0.5em; /* vertical tabs */
+}
+
+.yui-navset .yui-content .yui-hidden {
+    /* absolute position off-screen and box collapsing used to
+       avoid display:none, which causes issues for some content (firefox
+       restarts flash movies) */
+    border:0;
+    height:0;
+    width:0;
+    padding:0;
+    position:absolute;
+    left:-999999px;
+    overflow:hidden;
+    visibility:hidden;
+}
+
+/* default width for side tabs */
+.yui-navset .yui-navset-left .yui-nav,
+.yui-navset .yui-navset-right .yui-nav,
+.yui-navset-left .yui-nav,
+.yui-navset-right .yui-nav { width:6em; }
+
+.yui-navset-top .yui-nav,
+.yui-navset-bottom .yui-nav {
+    width:auto;
+}
+.yui-navset .yui-navset-left,
+.yui-navset-left { padding:0 0 0 6em; } /* map to nav width */
+.yui-navset-right { padding:0 6em 0 0; } /* ditto */
+
+.yui-navset-top,
+.yui-navset-bottom {
+    padding:auto;
+}
+/* core */
+
+.yui-nav,
+.yui-nav li {
+    margin:0;
+    padding:0;
+    list-style:none;
+}
+.yui-navset li em { font-style:normal; }
+
+.yui-navset {
+    position:relative; /* contain absolute positioned tabs (left/right) */
+    zoom:1;
+}
+
+.yui-navset .yui-content,
+.yui-navset .yui-content div {
+    zoom:1;
+}
+
+.yui-navset .yui-content:after {
+    content:'';
+    display:block;
+    clear:both;
+}
+
+.yui-navset .yui-nav li,
+.yui-navset .yui-navset-top .yui-nav li, /* in case nested */
+.yui-navset .yui-navset-bottom .yui-nav li {
+    display:inline-block;
+    display:-moz-inline-stack;
+    *display:inline; /* IE */
+    vertical-align:bottom; /* safari: for overlap */
+    cursor:pointer; /* gecko: due to -moz-inline-stack on anchor */
+    zoom:1; /* IE: kill space between horizontal tabs */
+}
+
+.yui-navset-left .yui-nav li,
+.yui-navset-right .yui-nav li {
+    display:block;
+}
+
+.yui-navset .yui-nav a { position:relative; } /* IE: to allow overlap */
+
+.yui-navset .yui-nav li a,
+.yui-navset-top .yui-nav li a,
+.yui-navset-bottom .yui-nav li a {
+    display:block;
+    display:inline-block;
+    vertical-align:bottom; /* safari: for overlap */
+    zoom:1;
+}
+
+.yui-navset-left .yui-nav li a,
+.yui-navset-right .yui-nav li a {
+    display:block;
+}
+
+.yui-navset-bottom .yui-nav li a {
+    vertical-align:text-top; /* for inline overlap (reverse for Opera border bug) */
+}
+
+.yui-navset .yui-nav li a em,
+.yui-navset-top .yui-nav li a em,
+.yui-navset-bottom .yui-nav li a em { display:block; }
+
+/* position left and right oriented tabs */
+.yui-navset .yui-navset-left .yui-nav,
+.yui-navset .yui-navset-right .yui-nav,
+.yui-navset-left .yui-nav,
+.yui-navset-right .yui-nav {
+   position:absolute;
+   z-index:1; 
+}
+
+.yui-navset-top .yui-nav,
+.yui-navset-bottom .yui-nav {
+    position:static;
+}
+.yui-navset .yui-navset-left .yui-nav,
+.yui-navset-left .yui-nav { left:0; right:auto; }
+
+.yui-navset .yui-navset-right .yui-nav,
+.yui-navset-right .yui-nav { right:0; left:auto; }

Added: roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/tabview.css
URL: http://svn.apache.org/viewvc/roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/tabview.css?rev=1201435&view=auto
==============================================================================
--- roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/tabview.css (added)
+++ roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/assets/tabview.css Sun Nov 13 15:01:36 2011
@@ -0,0 +1,77 @@
+/*
+Copyright (c) 2009, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.8.0r4
+*/
+/* default space between tabs */
+.yui-navset .yui-nav li {
+    margin-right:0.5em; /* horizontal tabs */
+}
+.yui-navset-left .yui-nav li, .yui-navset-right .yui-nav li {
+    margin:0 0 0.5em; /* vertical tabs */
+}
+
+/* default width for side tabs */
+.yui-navset-left .yui-nav, .yui-navset-right .yui-nav { width:6em; }
+.yui-navset-left { padding-left:6em; } /* map to nav width */
+.yui-navset-right { padding-right:6em; } /* ditto */
+
+/* core */
+
+.yui-nav, .yui-nav li {
+    margin:0;
+    padding:0;
+    list-style:none;
+}
+.yui-navset li em { font-style:normal; }
+
+.yui-navset {
+    position:relative; /* contain absolute positioned tabs (left/right) */
+    zoom:1;
+}
+
+.yui-navset .yui-content { zoom:1; }
+
+.yui-navset .yui-hidden { display:none; }
+
+.yui-navset .yui-nav li {
+    display:inline-block;
+    display:-moz-inline-stack;
+    *display:inline; /* IE */
+    vertical-align:bottom; /* safari: for overlap */
+    cursor:pointer; /* gecko: due to -moz-inline-stack on anchor */
+    zoom:1; /* IE: kill space between horizontal tabs */
+}
+
+.yui-navset-left .yui-nav li, .yui-navset-right .yui-nav li {
+    display:block;
+}
+
+.yui-navset .yui-nav a {
+    outline:0; /* gecko: keep from shifting */
+}
+
+.yui-navset .yui-nav a { position:relative; } /* IE: to allow overlap */
+
+.yui-navset .yui-nav li a {
+    display:block;
+    display:inline-block;
+    vertical-align:bottom; /* safari: for overlap */
+    zoom:1;
+}
+
+.yui-navset-left .yui-nav li a, .yui-navset-right .yui-nav li a {
+    display:block;
+}
+
+.yui-navset-bottom .yui-nav li a {
+    vertical-align:text-top; /* for inline overlap (reverse for Op border bug) */
+}
+
+.yui-navset .yui-nav li a em { display:block; }
+
+/* position left and right oriented tabs */
+.yui-navset-left .yui-nav, .yui-navset-right .yui-nav { position:absolute; z-index:1; }
+.yui-navset-left .yui-nav { left:0; }
+.yui-navset-right .yui-nav { right:0; }

Added: roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/tabview-debug.js
URL: http://svn.apache.org/viewvc/roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/tabview-debug.js?rev=1201435&view=auto
==============================================================================
--- roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/tabview-debug.js (added)
+++ roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/tabview-debug.js Sun Nov 13 15:01:36 2011
@@ -0,0 +1,995 @@
+/*
+Copyright (c) 2009, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.8.0r4
+*/
+(function() {
+
+    /**
+     * The tabview module provides a widget for managing content bound to tabs.
+     * @module tabview
+     * @requires yahoo, dom, event, element
+     *
+     */
+
+    var Y = YAHOO.util,
+        Dom = Y.Dom,
+        Event = Y.Event,
+        document = window.document,
+    
+        // STRING CONSTANTS
+        ACTIVE = 'active',
+        ACTIVE_INDEX = 'activeIndex',
+        ACTIVE_TAB = 'activeTab',
+        CONTENT_EL = 'contentEl',
+        ELEMENT = 'element',
+    
+    /**
+     * A widget to control tabbed views.
+     * @namespace YAHOO.widget
+     * @class TabView
+     * @extends YAHOO.util.Element
+     * @constructor
+     * @param {HTMLElement | String | Object} el(optional) The html 
+     * element that represents the TabView, or the attribute object to use. 
+     * An element will be created if none provided.
+     * @param {Object} attr (optional) A key map of the tabView's 
+     * initial attributes.  Ignored if first arg is attributes object.
+     */
+    TabView = function(el, attr) {
+        attr = attr || {};
+        if (arguments.length == 1 && !YAHOO.lang.isString(el) && !el.nodeName) {
+            attr = el; // treat first arg as attr object
+            el = attr.element || null;
+        }
+        
+        if (!el && !attr.element) { // create if we dont have one
+            el = this._createTabViewElement(attr);
+        }
+        TabView.superclass.constructor.call(this, el, attr); 
+    };
+
+    YAHOO.extend(TabView, Y.Element, {
+        /**
+         * The className to add when building from scratch. 
+         * @property CLASSNAME
+         * @default "navset"
+         */
+        CLASSNAME: 'yui-navset',
+        
+        /**
+         * The className of the HTMLElement containing the TabView's tab elements
+         * to look for when building from existing markup, or to add when building
+         * from scratch. 
+         * All childNodes of the tab container are treated as Tabs when building
+         * from existing markup.
+         * @property TAB_PARENT_CLASSNAME
+         * @default "nav"
+         */
+        TAB_PARENT_CLASSNAME: 'yui-nav',
+        
+        /**
+         * The className of the HTMLElement containing the TabView's label elements
+         * to look for when building from existing markup, or to add when building
+         * from scratch. 
+         * All childNodes of the content container are treated as content elements when
+         * building from existing markup.
+         * @property CONTENT_PARENT_CLASSNAME
+         * @default "nav-content"
+         */
+        CONTENT_PARENT_CLASSNAME: 'yui-content',
+        
+        _tabParent: null,
+        _contentParent: null,
+        
+        /**
+         * Adds a Tab to the TabView instance.  
+         * If no index is specified, the tab is added to the end of the tab list.
+         * @method addTab
+         * @param {YAHOO.widget.Tab} tab A Tab instance to add.
+         * @param {Integer} index The position to add the tab. 
+         * @return void
+         */
+        addTab: function(tab, index) {
+            var tabs = this.get('tabs'),
+                before = this.getTab(index),
+                tabParent = this._tabParent,
+                contentParent = this._contentParent,
+                tabElement = tab.get(ELEMENT),
+                contentEl = tab.get(CONTENT_EL);
+
+            if (!tabs) { // not ready yet
+                this._queue[this._queue.length] = ['addTab', arguments];
+                return false;
+            }
+            
+            index = (index === undefined) ? tabs.length : index;
+            
+            tabs.splice(index, 0, tab);
+
+            if ( before ) {
+                tabParent.insertBefore(tabElement, before.get(ELEMENT));
+            } else {
+                tabParent.appendChild(tabElement);
+            }
+
+            if ( contentEl && !Dom.isAncestor(contentParent, contentEl) ) {
+                contentParent.appendChild(contentEl);
+            }
+            
+            if ( !tab.get(ACTIVE) ) {
+                tab.set('contentVisible', false, true); /* hide if not active */
+            } else {
+                this.set(ACTIVE_TAB, tab, true);
+                this.set('activeIndex', index, true);
+            }
+
+            this._initTabEvents(tab);
+        },
+
+        _initTabEvents: function(tab) {
+            tab.addListener( tab.get('activationEvent'), tab._onActivate, this, tab);
+            tab.addListener( tab.get('activationEventChange'), tab._onActivationEventChange, this, tab);
+        },
+
+        _removeTabEvents: function(tab) {
+            tab.removeListener(tab.get('activationEvent'), tab._onActivate, this, tab);
+            tab.removeListener('activationEventChange', tab._onActivationEventChange, this, tab);
+        },
+
+        /**
+         * Routes childNode events.
+         * @method DOMEventHandler
+         * @param {event} e The Dom event that is being handled.
+         * @return void
+         */
+        DOMEventHandler: function(e) {
+            var target = Event.getTarget(e),
+                tabParent = this._tabParent,
+                tabs = this.get('tabs'),
+                tab,
+                tabEl,
+                contentEl;
+
+            
+            if (Dom.isAncestor(tabParent, target) ) {
+                for (var i = 0, len = tabs.length; i < len; i++) {
+                    tabEl = tabs[i].get(ELEMENT);
+                    contentEl = tabs[i].get(CONTENT_EL);
+
+                    if ( target == tabEl || Dom.isAncestor(tabEl, target) ) {
+                        tab = tabs[i];
+                        break; // note break
+                    }
+                } 
+                
+                if (tab) {
+                    tab.fireEvent(e.type, e);
+                }
+            }
+        },
+        
+        /**
+         * Returns the Tab instance at the specified index.
+         * @method getTab
+         * @param {Integer} index The position of the Tab.
+         * @return YAHOO.widget.Tab
+         */
+        getTab: function(index) {
+            return this.get('tabs')[index];
+        },
+        
+        /**
+         * Returns the index of given tab.
+         * @method getTabIndex
+         * @param {YAHOO.widget.Tab} tab The tab whose index will be returned.
+         * @return int
+         */
+        getTabIndex: function(tab) {
+            var index = null,
+                tabs = this.get('tabs');
+            for (var i = 0, len = tabs.length; i < len; ++i) {
+                if (tab == tabs[i]) {
+                    index = i;
+                    break;
+                }
+            }
+            
+            return index;
+        },
+        
+        /**
+         * Removes the specified Tab from the TabView.
+         * @method removeTab
+         * @param {YAHOO.widget.Tab} item The Tab instance to be removed.
+         * @return void
+         */
+        removeTab: function(tab) {
+            var tabCount = this.get('tabs').length,
+                index = this.getTabIndex(tab);
+
+            if ( tab === this.get(ACTIVE_TAB) ) { 
+                if (tabCount > 1) { // select another tab
+                    if (index + 1 === tabCount) { // if last, activate previous
+                        this.set(ACTIVE_INDEX, index - 1);
+                    } else { // activate next tab
+                        this.set(ACTIVE_INDEX, index + 1);
+                    }
+                } else { // no more tabs
+                    this.set(ACTIVE_TAB, null);
+                }
+            }
+            
+            this._removeTabEvents(tab);
+            this._tabParent.removeChild( tab.get(ELEMENT) );
+            this._contentParent.removeChild( tab.get(CONTENT_EL) );
+            this._configs.tabs.value.splice(index, 1);
+
+            tab.fireEvent('remove', { type: 'remove', tabview: this });
+        },
+        
+        /**
+         * Provides a readable name for the TabView instance.
+         * @method toString
+         * @return String
+         */
+        toString: function() {
+            var name = this.get('id') || this.get('tagName');
+            return "TabView " + name; 
+        },
+        
+        /**
+         * The transiton to use when switching between tabs.
+         * @method contentTransition
+         */
+        contentTransition: function(newTab, oldTab) {
+            if (newTab) {
+                newTab.set('contentVisible', true);
+            }
+            if (oldTab) {
+                oldTab.set('contentVisible', false);
+            }
+        },
+        
+        /**
+         * setAttributeConfigs TabView specific properties.
+         * @method initAttributes
+         * @param {Object} attr Hash of initial attributes
+         */
+        initAttributes: function(attr) {
+            TabView.superclass.initAttributes.call(this, attr);
+            
+            if (!attr.orientation) {
+                attr.orientation = 'top';
+            }
+            
+            var el = this.get(ELEMENT);
+
+            if (!Dom.hasClass(el, this.CLASSNAME)) {
+                Dom.addClass(el, this.CLASSNAME);        
+            }
+            
+            /**
+             * The Tabs belonging to the TabView instance.
+             * @attribute tabs
+             * @type Array
+             */
+            this.setAttributeConfig('tabs', {
+                value: [],
+                readOnly: true
+            });
+
+            /**
+             * The container of the tabView's label elements.
+             * @property _tabParent
+             * @private
+             * @type HTMLElement
+             */
+            this._tabParent = 
+                    this.getElementsByClassName(this.TAB_PARENT_CLASSNAME,
+                            'ul' )[0] || this._createTabParent();
+                
+            /**
+             * The container of the tabView's content elements.
+             * @property _contentParent
+             * @type HTMLElement
+             * @private
+             */
+            this._contentParent = 
+                    this.getElementsByClassName(this.CONTENT_PARENT_CLASSNAME,
+                            'div')[0] ||  this._createContentParent();
+            
+            /**
+             * How the Tabs should be oriented relative to the TabView.
+             * @attribute orientation
+             * @type String
+             * @default "top"
+             */
+            this.setAttributeConfig('orientation', {
+                value: attr.orientation,
+                method: function(value) {
+                    var current = this.get('orientation');
+                    this.addClass('yui-navset-' + value);
+                    
+                    if (current != value) {
+                        this.removeClass('yui-navset-' + current);
+                    }
+                    
+                    if (value === 'bottom') {
+                        this.appendChild(this._tabParent);
+                    }
+                }
+            });
+            
+            /**
+             * The index of the tab currently active.
+             * @attribute activeIndex
+             * @type Int
+             */
+            this.setAttributeConfig(ACTIVE_INDEX, {
+                value: attr.activeIndex,
+                validator: function(value) {
+                    var ret = true;
+                    if (value && this.getTab(value).get('disabled')) { // cannot activate if disabled
+                        ret = false;
+                    }
+                    return ret;
+                }
+            });
+            
+            /**
+             * The tab currently active.
+             * @attribute activeTab
+             * @type YAHOO.widget.Tab
+             */
+            this.setAttributeConfig(ACTIVE_TAB, {
+                value: attr.activeTab,
+                method: function(tab) {
+                    var activeTab = this.get(ACTIVE_TAB);
+                    
+                    if (tab) {
+                        tab.set(ACTIVE, true);
+                    }
+                    
+                    if (activeTab && activeTab !== tab) {
+                        activeTab.set(ACTIVE, false);
+                    }
+                    
+                    if (activeTab && tab !== activeTab) { // no transition if only 1
+                        this.contentTransition(tab, activeTab);
+                    } else if (tab) {
+                        tab.set('contentVisible', true);
+                    }
+                },
+                validator: function(value) {
+                    var ret = true;
+                    if (value && value.get('disabled')) { // cannot activate if disabled
+                        ret = false;
+                    }
+                    return ret;
+                }
+            });
+
+            this.on('activeTabChange', this._onActiveTabChange);
+            this.on('activeIndexChange', this._onActiveIndexChange);
+
+            YAHOO.log('attributes initialized', 'info', 'TabView');
+            if ( this._tabParent ) {
+                this._initTabs();
+            }
+            
+            // Due to delegation we add all DOM_EVENTS to the TabView container
+            // but IE will leak when unsupported events are added, so remove these
+            this.DOM_EVENTS.submit = false;
+            this.DOM_EVENTS.focus = false;
+            this.DOM_EVENTS.blur = false;
+
+            for (var type in this.DOM_EVENTS) {
+                if ( YAHOO.lang.hasOwnProperty(this.DOM_EVENTS, type) ) {
+                    this.addListener.call(this, type, this.DOMEventHandler);
+                }
+            }
+        },
+
+        /**
+         * Removes selected state from the given tab if it is the activeTab
+         * @method deselectTab
+         * @param {Int} index The tab index to deselect 
+         */
+        deselectTab: function(index) {
+            if (this.getTab(index) === this.get('activeTab')) {
+                this.set('activeTab', null);
+            }
+        },
+
+        /**
+         * Makes the tab at the given index the active tab
+         * @method selectTab
+         * @param {Int} index The tab index to be made active
+         */
+        selectTab: function(index) {
+            this.set('activeTab', this.getTab(index));
+        },
+
+        _onActiveTabChange: function(e) {
+            var activeIndex = this.get(ACTIVE_INDEX),
+                newIndex = this.getTabIndex(e.newValue);
+
+            if (activeIndex !== newIndex) {
+                if (!(this.set(ACTIVE_INDEX, newIndex)) ) { // NOTE: setting
+                     // revert if activeIndex update fails (cancelled via beforeChange) 
+                    this.set(ACTIVE_TAB, e.prevValue);
+                }
+            }
+        },
+        
+        _onActiveIndexChange: function(e) {
+            // no set if called from ActiveTabChange event
+            if (e.newValue !== this.getTabIndex(this.get(ACTIVE_TAB))) {
+                if (!(this.set(ACTIVE_TAB, this.getTab(e.newValue))) ) { // NOTE: setting
+                     // revert if activeTab update fails (cancelled via beforeChange) 
+                    this.set(ACTIVE_INDEX, e.prevValue);
+                }
+            }
+        },
+
+        /**
+         * Creates Tab instances from a collection of HTMLElements.
+         * @method _initTabs
+         * @private
+         * @return void
+         */
+        _initTabs: function() {
+            var tabs = Dom.getChildren(this._tabParent),
+                contentElements = Dom.getChildren(this._contentParent),
+                activeIndex = this.get(ACTIVE_INDEX),
+                tab,
+                attr,
+                active;
+
+            for (var i = 0, len = tabs.length; i < len; ++i) {
+                attr = {};
+                
+                if (contentElements[i]) {
+                    attr.contentEl = contentElements[i];
+                }
+
+                tab = new YAHOO.widget.Tab(tabs[i], attr);
+                this.addTab(tab);
+                
+                if (tab.hasClass(tab.ACTIVE_CLASSNAME) ) {
+                    active = tab;
+                }
+            }
+            if (activeIndex) {
+                this.set(ACTIVE_TAB, this.getTab(activeIndex));
+            } else {
+                this._configs.activeTab.value = active; // dont invoke method
+                this._configs.activeIndex.value = this.getTabIndex(active);
+            }
+        },
+
+        _createTabViewElement: function(attr) {
+            var el = document.createElement('div');
+
+            if ( this.CLASSNAME ) {
+                el.className = this.CLASSNAME;
+            }
+            
+            YAHOO.log('TabView Dom created', 'info', 'TabView');
+            return el;
+        },
+
+        _createTabParent: function(attr) {
+            var el = document.createElement('ul');
+
+            if ( this.TAB_PARENT_CLASSNAME ) {
+                el.className = this.TAB_PARENT_CLASSNAME;
+            }
+            
+            this.get(ELEMENT).appendChild(el);
+            
+            return el;
+        },
+        
+        _createContentParent: function(attr) {
+            var el = document.createElement('div');
+
+            if ( this.CONTENT_PARENT_CLASSNAME ) {
+                el.className = this.CONTENT_PARENT_CLASSNAME;
+            }
+            
+            this.get(ELEMENT).appendChild(el);
+            
+            return el;
+        }
+    });
+    
+    
+    YAHOO.widget.TabView = TabView;
+})();
+
+(function() {
+    var Y = YAHOO.util, 
+        Dom = Y.Dom,
+        Lang = YAHOO.lang,
+    
+
+    // STRING CONSTANTS
+        ACTIVE_TAB = 'activeTab',
+        LABEL = 'label',
+        LABEL_EL = 'labelEl',
+        CONTENT = 'content',
+        CONTENT_EL = 'contentEl',
+        ELEMENT = 'element',
+        CACHE_DATA = 'cacheData',
+        DATA_SRC = 'dataSrc',
+        DATA_LOADED = 'dataLoaded',
+        DATA_TIMEOUT = 'dataTimeout',
+        LOAD_METHOD = 'loadMethod',
+        POST_DATA = 'postData',
+        DISABLED = 'disabled',
+    
+    /**
+     * A representation of a Tab's label and content.
+     * @namespace YAHOO.widget
+     * @class Tab
+     * @extends YAHOO.util.Element
+     * @constructor
+     * @param element {HTMLElement | String} (optional) The html element that 
+     * represents the Tab. An element will be created if none provided.
+     * @param {Object} properties A key map of initial properties
+     */
+    Tab = function(el, attr) {
+        attr = attr || {};
+        if (arguments.length == 1 && !Lang.isString(el) && !el.nodeName) {
+            attr = el;
+            el = attr.element;
+        }
+
+        if (!el && !attr.element) {
+            el = this._createTabElement(attr);
+        }
+
+        this.loadHandler =  {
+            success: function(o) {
+                this.set(CONTENT, o.responseText);
+            },
+            failure: function(o) {
+            }
+        };
+        
+        Tab.superclass.constructor.call(this, el, attr);
+        
+        this.DOM_EVENTS = {}; // delegating to tabView
+    };
+
+    YAHOO.extend(Tab, YAHOO.util.Element, {
+        /**
+         * The default tag name for a Tab's inner element.
+         * @property LABEL_INNER_TAGNAME
+         * @type String
+         * @default "em"
+         */
+        LABEL_TAGNAME: 'em',
+        
+        /**
+         * The class name applied to active tabs.
+         * @property ACTIVE_CLASSNAME
+         * @type String
+         * @default "selected"
+         */
+        ACTIVE_CLASSNAME: 'selected',
+        
+        /**
+         * The class name applied to active tabs.
+         * @property HIDDEN_CLASSNAME
+         * @type String
+         * @default "yui-hidden"
+         */
+        HIDDEN_CLASSNAME: 'yui-hidden',
+        
+        /**
+         * The title applied to active tabs.
+         * @property ACTIVE_TITLE
+         * @type String
+         * @default "active"
+         */
+        ACTIVE_TITLE: 'active',
+
+        /**
+         * The class name applied to disabled tabs.
+         * @property DISABLED_CLASSNAME
+         * @type String
+         * @default "disabled"
+         */
+        DISABLED_CLASSNAME: DISABLED,
+        
+        /**
+         * The class name applied to dynamic tabs while loading.
+         * @property LOADING_CLASSNAME
+         * @type String
+         * @default "disabled"
+         */
+        LOADING_CLASSNAME: 'loading',
+
+        /**
+         * Provides a reference to the connection request object when data is
+         * loaded dynamically.
+         * @property dataConnection
+         * @type Object
+         */
+        dataConnection: null,
+        
+        /**
+         * Object containing success and failure callbacks for loading data.
+         * @property loadHandler
+         * @type object
+         */
+        loadHandler: null,
+
+        _loading: false,
+        
+        /**
+         * Provides a readable name for the tab.
+         * @method toString
+         * @return String
+         */
+        toString: function() {
+            var el = this.get(ELEMENT),
+                id = el.id || el.tagName;
+            return "Tab " + id; 
+        },
+        
+        /**
+         * setAttributeConfigs Tab specific properties.
+         * @method initAttributes
+         * @param {Object} attr Hash of initial attributes
+         */
+        initAttributes: function(attr) {
+            attr = attr || {};
+            Tab.superclass.initAttributes.call(this, attr);
+            
+            /**
+             * The event that triggers the tab's activation.
+             * @attribute activationEvent
+             * @type String
+             */
+            this.setAttributeConfig('activationEvent', {
+                value: attr.activationEvent || 'click'
+            });        
+
+            /**
+             * The element that contains the tab's label.
+             * @attribute labelEl
+             * @type HTMLElement
+             */
+            this.setAttributeConfig(LABEL_EL, {
+                value: attr[LABEL_EL] || this._getLabelEl(),
+                method: function(value) {
+                    value = Dom.get(value);
+                    var current = this.get(LABEL_EL);
+
+                    if (current) {
+                        if (current == value) {
+                            return false; // already set
+                        }
+                        
+                        current.parentNode.replaceChild(value, current);
+                        this.set(LABEL, value.innerHTML);
+                    }
+                } 
+            });
+
+            /**
+             * The tab's label text (or innerHTML).
+             * @attribute label
+             * @type String
+             */
+            this.setAttributeConfig(LABEL, {
+                value: attr.label || this._getLabel(),
+                method: function(value) {
+                    var labelEl = this.get(LABEL_EL);
+                    if (!labelEl) { // create if needed
+                        this.set(LABEL_EL, this._createLabelEl());
+                    }
+                    
+                    labelEl.innerHTML = value;
+                }
+            });
+            
+            /**
+             * The HTMLElement that contains the tab's content.
+             * @attribute contentEl
+             * @type HTMLElement
+             */
+            this.setAttributeConfig(CONTENT_EL, {
+                value: attr[CONTENT_EL] || document.createElement('div'),
+                method: function(value) {
+                    value = Dom.get(value);
+                    var current = this.get(CONTENT_EL);
+
+                    if (current) {
+                        if (current === value) {
+                            return false; // already set
+                        }
+                        if (!this.get('selected')) {
+                            Dom.addClass(value, this.HIDDEN_CLASSNAME);
+                        }
+                        current.parentNode.replaceChild(value, current);
+                        this.set(CONTENT, value.innerHTML);
+                    }
+                }
+            });
+            
+            /**
+             * The tab's content.
+             * @attribute content
+             * @type String
+             */
+            this.setAttributeConfig(CONTENT, {
+                value: attr[CONTENT],
+                method: function(value) {
+                    this.get(CONTENT_EL).innerHTML = value;
+                }
+            });
+
+            /**
+             * The tab's data source, used for loading content dynamically.
+             * @attribute dataSrc
+             * @type String
+             */
+            this.setAttributeConfig(DATA_SRC, {
+                value: attr.dataSrc
+            });
+            
+            /**
+             * Whether or not content should be reloaded for every view.
+             * @attribute cacheData
+             * @type Boolean
+             * @default false
+             */
+            this.setAttributeConfig(CACHE_DATA, {
+                value: attr.cacheData || false,
+                validator: Lang.isBoolean
+            });
+            
+            /**
+             * The method to use for the data request.
+             * @attribute loadMethod
+             * @type String
+             * @default "GET"
+             */
+            this.setAttributeConfig(LOAD_METHOD, {
+                value: attr.loadMethod || 'GET',
+                validator: Lang.isString
+            });
+
+            /**
+             * Whether or not any data has been loaded from the server.
+             * @attribute dataLoaded
+             * @type Boolean
+             */        
+            this.setAttributeConfig(DATA_LOADED, {
+                value: false,
+                validator: Lang.isBoolean,
+                writeOnce: true
+            });
+            
+            /**
+             * Number if milliseconds before aborting and calling failure handler.
+             * @attribute dataTimeout
+             * @type Number
+             * @default null
+             */
+            this.setAttributeConfig(DATA_TIMEOUT, {
+                value: attr.dataTimeout || null,
+                validator: Lang.isNumber
+            });
+            
+            /**
+             * Arguments to pass when POST method is used 
+             * @attribute postData
+             * @default null
+             */
+            this.setAttributeConfig(POST_DATA, {
+                value: attr.postData || null
+            });
+
+            /**
+             * Whether or not the tab is currently active.
+             * If a dataSrc is set for the tab, the content will be loaded from
+             * the given source.
+             * @attribute active
+             * @type Boolean
+             */
+            this.setAttributeConfig('active', {
+                value: attr.active || this.hasClass(this.ACTIVE_CLASSNAME),
+                method: function(value) {
+                    if (value === true) {
+                        this.addClass(this.ACTIVE_CLASSNAME);
+                        this.set('title', this.ACTIVE_TITLE);
+                    } else {
+                        this.removeClass(this.ACTIVE_CLASSNAME);
+                        this.set('title', '');
+                    }
+                },
+                validator: function(value) {
+                    return Lang.isBoolean(value) && !this.get(DISABLED) ;
+                }
+            });
+            
+            /**
+             * Whether or not the tab is disabled.
+             * @attribute disabled
+             * @type Boolean
+             */
+            this.setAttributeConfig(DISABLED, {
+                value: attr.disabled || this.hasClass(this.DISABLED_CLASSNAME),
+                method: function(value) {
+                    if (value === true) {
+                        Dom.addClass(this.get(ELEMENT), this.DISABLED_CLASSNAME);
+                    } else {
+                        Dom.removeClass(this.get(ELEMENT), this.DISABLED_CLASSNAME);
+                    }
+                },
+                validator: Lang.isBoolean
+            });
+            
+            /**
+             * The href of the tab's anchor element.
+             * @attribute href
+             * @type String
+             * @default '#'
+             */
+            this.setAttributeConfig('href', {
+                value: attr.href ||
+                        this.getElementsByTagName('a')[0].getAttribute('href', 2) || '#',
+                method: function(value) {
+                    this.getElementsByTagName('a')[0].href = value;
+                },
+                validator: Lang.isString
+            });
+            
+            /**
+             * The Whether or not the tab's content is visible.
+             * @attribute contentVisible
+             * @type Boolean
+             * @default false
+             */
+            this.setAttributeConfig('contentVisible', {
+                value: attr.contentVisible,
+                method: function(value) {
+                    if (value) {
+                        Dom.removeClass(this.get(CONTENT_EL), this.HIDDEN_CLASSNAME);
+                        
+                        if ( this.get(DATA_SRC) ) {
+                         // load dynamic content unless already loading or loaded and caching
+                            if ( !this._loading && !(this.get(DATA_LOADED) && this.get(CACHE_DATA)) ) {
+                                this._dataConnect();
+                            }
+                        }
+                    } else {
+                        Dom.addClass(this.get(CONTENT_EL), this.HIDDEN_CLASSNAME);
+                    }
+                },
+                validator: Lang.isBoolean
+            });
+            YAHOO.log('attributes initialized', 'info', 'Tab');
+        },
+        
+        _dataConnect: function() {
+            if (!Y.Connect) {
+                YAHOO.log('YAHOO.util.Connect dependency not met',
+                        'error', 'Tab');
+                return false;
+            }
+
+            Dom.addClass(this.get(CONTENT_EL).parentNode, this.LOADING_CLASSNAME);
+            this._loading = true; 
+            this.dataConnection = Y.Connect.asyncRequest(
+                this.get(LOAD_METHOD),
+                this.get(DATA_SRC), 
+                {
+                    success: function(o) {
+                        YAHOO.log('content loaded successfully', 'info', 'Tab');
+                        this.loadHandler.success.call(this, o);
+                        this.set(DATA_LOADED, true);
+                        this.dataConnection = null;
+                        Dom.removeClass(this.get(CONTENT_EL).parentNode,
+                                this.LOADING_CLASSNAME);
+                        this._loading = false;
+                    },
+                    failure: function(o) {
+                        YAHOO.log('loading failed: ' + o.statusText, 'error', 'Tab');
+                        this.loadHandler.failure.call(this, o);
+                        this.dataConnection = null;
+                        Dom.removeClass(this.get(CONTENT_EL).parentNode,
+                                this.LOADING_CLASSNAME);
+                        this._loading = false;
+                    },
+                    scope: this,
+                    timeout: this.get(DATA_TIMEOUT)
+                },
+
+                this.get(POST_DATA)
+            );
+        },
+        _createTabElement: function(attr) {
+            var el = document.createElement('li'),
+                a = document.createElement('a'),
+                label = attr.label || null,
+                labelEl = attr.labelEl || null;
+            
+            a.href = attr.href || '#'; // TODO: Use Dom.setAttribute?
+            el.appendChild(a);
+            
+            if (labelEl) { // user supplied labelEl
+                if (!label) { // user supplied label
+                    label = this._getLabel();
+                }
+            } else {
+                labelEl = this._createLabelEl();
+            }
+            
+            a.appendChild(labelEl);
+            
+            YAHOO.log('creating Tab Dom', 'info', 'Tab');
+            return el;
+        },
+
+        _getLabelEl: function() {
+            return this.getElementsByTagName(this.LABEL_TAGNAME)[0];
+        },
+
+        _createLabelEl: function() {
+            var el = document.createElement(this.LABEL_TAGNAME);
+            return el;
+        },
+    
+        
+        _getLabel: function() {
+            var el = this.get(LABEL_EL);
+                
+                if (!el) {
+                    return undefined;
+                }
+            
+            return el.innerHTML;
+        },
+
+        _onActivate: function(e, tabview) {
+            var tab = this,
+                silent = false;
+
+            Y.Event.preventDefault(e);
+            if (tab === tabview.get(ACTIVE_TAB)) {
+                silent = true; // dont fire activeTabChange if already active
+            }
+            tabview.set(ACTIVE_TAB, tab, silent);
+        },
+
+        _onActivationEventChange: function(e) {
+            var tab = this;
+
+            if (e.prevValue != e.newValue) {
+                tab.removeListener(e.prevValue, tab._onActivate);
+                tab.addListener(e.newValue, tab._onActivate, this, tab);
+            }
+        }
+    });
+    
+    
+    /**
+     * Fires when a tab is removed from the tabview
+     * @event remove
+     * @type CustomEvent
+     * @param {Event} An event object with fields for "type" ("remove")
+     * and "tabview" (the tabview instance it was removed from) 
+     */
+    
+    YAHOO.widget.Tab = Tab;
+})();
+
+YAHOO.register("tabview", YAHOO.widget.TabView, {version: "2.8.0r4", build: "2449"});

Added: roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/tabview-min.js
URL: http://svn.apache.org/viewvc/roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/tabview-min.js?rev=1201435&view=auto
==============================================================================
--- roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/tabview-min.js (added)
+++ roller/trunk/weblogger-webapp/src/main/webapp/roller-ui/yui/tabview/tabview-min.js Sun Nov 13 15:01:36 2011
@@ -0,0 +1,8 @@
+/*
+Copyright (c) 2009, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.8.0r4
+*/
+(function(){var B=YAHOO.util,C=B.Dom,H=B.Event,F=window.document,J="active",D="activeIndex",E="activeTab",A="contentEl",G="element",I=function(L,K){K=K||{};if(arguments.length==1&&!YAHOO.lang.isString(L)&&!L.nodeName){K=L;L=K.element||null;}if(!L&&!K.element){L=this._createTabViewElement(K);}I.superclass.constructor.call(this,L,K);};YAHOO.extend(I,B.Element,{CLASSNAME:"yui-navset",TAB_PARENT_CLASSNAME:"yui-nav",CONTENT_PARENT_CLASSNAME:"yui-content",_tabParent:null,_contentParent:null,addTab:function(P,L){var N=this.get("tabs"),Q=this.getTab(L),R=this._tabParent,K=this._contentParent,M=P.get(G),O=P.get(A);if(!N){this._queue[this._queue.length]=["addTab",arguments];return false;}L=(L===undefined)?N.length:L;N.splice(L,0,P);if(Q){R.insertBefore(M,Q.get(G));}else{R.appendChild(M);}if(O&&!C.isAncestor(K,O)){K.appendChild(O);}if(!P.get(J)){P.set("contentVisible",false,true);}else{this.set(E,P,true);this.set("activeIndex",L,true);}this._initTabEvents(P);},_initTabEvents:function(K
 ){K.addListener(K.get("activationEvent"),K._onActivate,this,K);K.addListener(K.get("activationEventChange"),K._onActivationEventChange,this,K);},_removeTabEvents:function(K){K.removeListener(K.get("activationEvent"),K._onActivate,this,K);K.removeListener("activationEventChange",K._onActivationEventChange,this,K);},DOMEventHandler:function(P){var Q=H.getTarget(P),S=this._tabParent,R=this.get("tabs"),M,L,K;if(C.isAncestor(S,Q)){for(var N=0,O=R.length;N<O;N++){L=R[N].get(G);K=R[N].get(A);if(Q==L||C.isAncestor(L,Q)){M=R[N];break;}}if(M){M.fireEvent(P.type,P);}}},getTab:function(K){return this.get("tabs")[K];},getTabIndex:function(O){var L=null,N=this.get("tabs");for(var M=0,K=N.length;M<K;++M){if(O==N[M]){L=M;break;}}return L;},removeTab:function(M){var L=this.get("tabs").length,K=this.getTabIndex(M);if(M===this.get(E)){if(L>1){if(K+1===L){this.set(D,K-1);}else{this.set(D,K+1);}}else{this.set(E,null);}}this._removeTabEvents(M);this._tabParent.removeChild(M.get(G));this._contentP
 arent.removeChild(M.get(A));this._configs.tabs.value.splice(K,1);M.fireEvent("remove",{type:"remove",tabview:this});},toString:function(){var K=this.get("id")||this.get("tagName");return"TabView "+K;},contentTransition:function(L,K){if(L){L.set("contentVisible",true);}if(K){K.set("contentVisible",false);}},initAttributes:function(K){I.superclass.initAttributes.call(this,K);if(!K.orientation){K.orientation="top";}var M=this.get(G);if(!C.hasClass(M,this.CLASSNAME)){C.addClass(M,this.CLASSNAME);}this.setAttributeConfig("tabs",{value:[],readOnly:true});this._tabParent=this.getElementsByClassName(this.TAB_PARENT_CLASSNAME,"ul")[0]||this._createTabParent();this._contentParent=this.getElementsByClassName(this.CONTENT_PARENT_CLASSNAME,"div")[0]||this._createContentParent();this.setAttributeConfig("orientation",{value:K.orientation,method:function(N){var O=this.get("orientation");this.addClass("yui-navset-"+N);if(O!=N){this.removeClass("yui-navset-"+O);}if(N==="bottom"){this.appendCh
 ild(this._tabParent);}}});this.setAttributeConfig(D,{value:K.activeIndex,validator:function(O){var N=true;if(O&&this.getTab(O).get("disabled")){N=false;}return N;}});this.setAttributeConfig(E,{value:K.activeTab,method:function(O){var N=this.get(E);if(O){O.set(J,true);}if(N&&N!==O){N.set(J,false);}if(N&&O!==N){this.contentTransition(O,N);}else{if(O){O.set("contentVisible",true);}}},validator:function(O){var N=true;if(O&&O.get("disabled")){N=false;}return N;}});this.on("activeTabChange",this._onActiveTabChange);this.on("activeIndexChange",this._onActiveIndexChange);if(this._tabParent){this._initTabs();}this.DOM_EVENTS.submit=false;this.DOM_EVENTS.focus=false;this.DOM_EVENTS.blur=false;for(var L in this.DOM_EVENTS){if(YAHOO.lang.hasOwnProperty(this.DOM_EVENTS,L)){this.addListener.call(this,L,this.DOMEventHandler);}}},deselectTab:function(K){if(this.getTab(K)===this.get("activeTab")){this.set("activeTab",null);}},selectTab:function(K){this.set("activeTab",this.getTab(K));},_onAc
 tiveTabChange:function(M){var K=this.get(D),L=this.getTabIndex(M.newValue);if(K!==L){if(!(this.set(D,L))){this.set(E,M.prevValue);}}},_onActiveIndexChange:function(K){if(K.newValue!==this.getTabIndex(this.get(E))){if(!(this.set(E,this.getTab(K.newValue)))){this.set(D,K.prevValue);}}},_initTabs:function(){var P=C.getChildren(this._tabParent),N=C.getChildren(this._contentParent),M=this.get(D),Q,L,R;for(var O=0,K=P.length;O<K;++O){L={};if(N[O]){L.contentEl=N[O];}Q=new YAHOO.widget.Tab(P[O],L);this.addTab(Q);if(Q.hasClass(Q.ACTIVE_CLASSNAME)){R=Q;}}if(M){this.set(E,this.getTab(M));}else{this._configs.activeTab.value=R;this._configs.activeIndex.value=this.getTabIndex(R);}},_createTabViewElement:function(K){var L=F.createElement("div");if(this.CLASSNAME){L.className=this.CLASSNAME;}return L;},_createTabParent:function(K){var L=F.createElement("ul");if(this.TAB_PARENT_CLASSNAME){L.className=this.TAB_PARENT_CLASSNAME;}this.get(G).appendChild(L);return L;},_createContentParent:functi
 on(K){var L=F.createElement("div");if(this.CONTENT_PARENT_CLASSNAME){L.className=this.CONTENT_PARENT_CLASSNAME;}this.get(G).appendChild(L);return L;}});YAHOO.widget.TabView=I;})();(function(){var D=YAHOO.util,I=D.Dom,L=YAHOO.lang,M="activeTab",J="label",G="labelEl",Q="content",C="contentEl",O="element",P="cacheData",B="dataSrc",H="dataLoaded",A="dataTimeout",N="loadMethod",F="postData",K="disabled",E=function(S,R){R=R||{};if(arguments.length==1&&!L.isString(S)&&!S.nodeName){R=S;S=R.element;}if(!S&&!R.element){S=this._createTabElement(R);}this.loadHandler={success:function(T){this.set(Q,T.responseText);},failure:function(T){}};E.superclass.constructor.call(this,S,R);this.DOM_EVENTS={};};YAHOO.extend(E,YAHOO.util.Element,{LABEL_TAGNAME:"em",ACTIVE_CLASSNAME:"selected",HIDDEN_CLASSNAME:"yui-hidden",ACTIVE_TITLE:"active",DISABLED_CLASSNAME:K,LOADING_CLASSNAME:"loading",dataConnection:null,loadHandler:null,_loading:false,toString:function(){var R=this.get(O),S=R.id||R.tagName;ret
 urn"Tab "+S;},initAttributes:function(R){R=R||{};E.superclass.initAttributes.call(this,R);
+this.setAttributeConfig("activationEvent",{value:R.activationEvent||"click"});this.setAttributeConfig(G,{value:R[G]||this._getLabelEl(),method:function(S){S=I.get(S);var T=this.get(G);if(T){if(T==S){return false;}T.parentNode.replaceChild(S,T);this.set(J,S.innerHTML);}}});this.setAttributeConfig(J,{value:R.label||this._getLabel(),method:function(T){var S=this.get(G);if(!S){this.set(G,this._createLabelEl());}S.innerHTML=T;}});this.setAttributeConfig(C,{value:R[C]||document.createElement("div"),method:function(S){S=I.get(S);var T=this.get(C);if(T){if(T===S){return false;}if(!this.get("selected")){I.addClass(S,this.HIDDEN_CLASSNAME);}T.parentNode.replaceChild(S,T);this.set(Q,S.innerHTML);}}});this.setAttributeConfig(Q,{value:R[Q],method:function(S){this.get(C).innerHTML=S;}});this.setAttributeConfig(B,{value:R.dataSrc});this.setAttributeConfig(P,{value:R.cacheData||false,validator:L.isBoolean});this.setAttributeConfig(N,{value:R.loadMethod||"GET",validator:L.isString});this.set
 AttributeConfig(H,{value:false,validator:L.isBoolean,writeOnce:true});this.setAttributeConfig(A,{value:R.dataTimeout||null,validator:L.isNumber});this.setAttributeConfig(F,{value:R.postData||null});this.setAttributeConfig("active",{value:R.active||this.hasClass(this.ACTIVE_CLASSNAME),method:function(S){if(S===true){this.addClass(this.ACTIVE_CLASSNAME);this.set("title",this.ACTIVE_TITLE);}else{this.removeClass(this.ACTIVE_CLASSNAME);this.set("title","");}},validator:function(S){return L.isBoolean(S)&&!this.get(K);}});this.setAttributeConfig(K,{value:R.disabled||this.hasClass(this.DISABLED_CLASSNAME),method:function(S){if(S===true){I.addClass(this.get(O),this.DISABLED_CLASSNAME);}else{I.removeClass(this.get(O),this.DISABLED_CLASSNAME);}},validator:L.isBoolean});this.setAttributeConfig("href",{value:R.href||this.getElementsByTagName("a")[0].getAttribute("href",2)||"#",method:function(S){this.getElementsByTagName("a")[0].href=S;},validator:L.isString});this.setAttributeConfig("c
 ontentVisible",{value:R.contentVisible,method:function(S){if(S){I.removeClass(this.get(C),this.HIDDEN_CLASSNAME);if(this.get(B)){if(!this._loading&&!(this.get(H)&&this.get(P))){this._dataConnect();}}}else{I.addClass(this.get(C),this.HIDDEN_CLASSNAME);}},validator:L.isBoolean});},_dataConnect:function(){if(!D.Connect){return false;}I.addClass(this.get(C).parentNode,this.LOADING_CLASSNAME);this._loading=true;this.dataConnection=D.Connect.asyncRequest(this.get(N),this.get(B),{success:function(R){this.loadHandler.success.call(this,R);this.set(H,true);this.dataConnection=null;I.removeClass(this.get(C).parentNode,this.LOADING_CLASSNAME);this._loading=false;},failure:function(R){this.loadHandler.failure.call(this,R);this.dataConnection=null;I.removeClass(this.get(C).parentNode,this.LOADING_CLASSNAME);this._loading=false;},scope:this,timeout:this.get(A)},this.get(F));},_createTabElement:function(R){var V=document.createElement("li"),S=document.createElement("a"),U=R.label||null,T=R.
 labelEl||null;S.href=R.href||"#";V.appendChild(S);if(T){if(!U){U=this._getLabel();}}else{T=this._createLabelEl();}S.appendChild(T);return V;},_getLabelEl:function(){return this.getElementsByTagName(this.LABEL_TAGNAME)[0];},_createLabelEl:function(){var R=document.createElement(this.LABEL_TAGNAME);return R;},_getLabel:function(){var R=this.get(G);if(!R){return undefined;}return R.innerHTML;},_onActivate:function(U,T){var S=this,R=false;D.Event.preventDefault(U);if(S===T.get(M)){R=true;}T.set(M,S,R);},_onActivationEventChange:function(S){var R=this;if(S.prevValue!=S.newValue){R.removeListener(S.prevValue,R._onActivate);R.addListener(S.newValue,R._onActivate,this,R);}}});YAHOO.widget.Tab=E;})();YAHOO.register("tabview",YAHOO.widget.TabView,{version:"2.8.0r4",build:"2449"});
\ No newline at end of file



Mime
View raw message