You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lo...@apache.org on 2012/02/08 10:30:17 UTC

svn commit: r1241833 - in /myfaces/tobago/branches/tobago-tree-table: tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/ tobago-example/tobago-example-test/src/main/webapp/tc/tree/ tobago-theme/tobago-theme-scarborough/src/main/jav...

Author: lofwyr
Date: Wed Feb  8 09:30:17 2012
New Revision: 1241833

URL: http://svn.apache.org/viewvc?rev=1241833&view=rev
Log:
TOBAGO-1049: Tree inside of the Sheet (aka TreeTable)
 - working on the "expanded" hidden field(s): 
    - fixed: after expanding a node, all nodes are expanded, when there is no model
    - refactoring: using only one hidden field for expansion per tree instead of one per node

Modified:
    myfaces/tobago/branches/tobago-tree-table/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIData.java
    myfaces/tobago/branches/tobago-tree-table/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeNode.java
    myfaces/tobago/branches/tobago-tree-table/tobago-example/tobago-example-test/src/main/webapp/tc/tree/tree-select.xhtml
    myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeIconRenderer.java
    myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeIndentRenderer.java
    myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeNodeRenderer.java
    myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeRenderer.java
    myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tree.js

Modified: myfaces/tobago/branches/tobago-tree-table/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIData.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-tree-table/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIData.java?rev=1241833&r1=1241832&r2=1241833&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-tree-table/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIData.java (original)
+++ myfaces/tobago/branches/tobago-tree-table/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIData.java Wed Feb  8 09:30:17 2012
@@ -25,6 +25,7 @@ import javax.faces.component.NamingConta
 import javax.faces.context.FacesContext;
 import javax.faces.model.DataModel;
 import javax.swing.tree.DefaultMutableTreeNode;
+import java.util.List;
 
 public class AbstractUIData extends javax.faces.component.UIData {
 
@@ -40,9 +41,16 @@ public class AbstractUIData extends java
    */
   private TreeDataModel dataModel;
 
-  // is transient
+  // is transient, for internal use
+  // XXX is introduced temporarily:
+  @Deprecated
   private Integer submittedMarked;
 
+  // is transient, for internal use
+  // XXX is introduced temporarily:
+  @Deprecated
+  private List<Integer> submittedExpanded;
+
   @Override
   protected DataModel getDataModel() {
     if (!initialized) {
@@ -108,11 +116,27 @@ public class AbstractUIData extends java
     return false;
   }
 
+  // XXX is introduced temporarily:
+  @Deprecated
   public Integer getSubmittedMarked() {
     return submittedMarked;
   }
 
+  // XXX is introduced temporarily:
+  @Deprecated
   public void setSubmittedMarked(Integer submittedMarked) {
     this.submittedMarked = submittedMarked;
   }
+
+  // XXX is introduced temporarily:
+  @Deprecated
+  public List<Integer> getSubmittedExpanded() {
+    return submittedExpanded;
+  }
+
+  // XXX is introduced temporarily:
+  @Deprecated
+  public void setSubmittedExpanded(List<Integer> submittedExpanded) {
+    this.submittedExpanded = submittedExpanded;
+  }
 }

Modified: myfaces/tobago/branches/tobago-tree-table/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeNode.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-tree-table/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeNode.java?rev=1241833&r1=1241832&r2=1241833&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-tree-table/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeNode.java (original)
+++ myfaces/tobago/branches/tobago-tree-table/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeNode.java Wed Feb  8 09:30:17 2012
@@ -58,7 +58,7 @@ public abstract class AbstractUITreeNode
     DataModel model = data.getDataModel();
     if (model instanceof TreeDataModel) {
       final TreeDataModel treeDataModel = (TreeDataModel) model;
-      treeDataModel.setRowExpanded(isExpanded());
+      treeDataModel.setRowExpanded(isExpandedWithTemporaryState());
       treeDataModel.setRowClientId(getClientId(facesContext));
     }
 
@@ -148,13 +148,13 @@ public abstract class AbstractUITreeNode
       if (FacesUtils.hasValueBindingOrValueExpression(this, Attributes.EXPANDED)) {
         try {
           FacesUtils.setValueOfBindingOrExpression(getFacesContext(), expanded, this, Attributes.EXPANDED);
+          // after processing this, we remove the value, so we'll got the value from the model while rendering
+          ComponentUtils.findAncestor(this, AbstractUIData.class).setSubmittedExpanded(null);
         } catch (Exception e) {
           if (LOG.isDebugEnabled()) {
             LOG.debug("Can't set expanded.", e);
           }
         }
-      } else {
-        setExpanded(expanded);
       }
     }
     if (event instanceof TreeMarkedEvent) {
@@ -298,4 +298,28 @@ public abstract class AbstractUITreeNode
   public abstract boolean isSelected();
 
   public abstract void setSelected(boolean selected);
+
+  // XXX is introduced temporarily:
+  @Deprecated
+  public boolean isMarkedWithTemporaryState() {
+    final AbstractUIData data = ComponentUtils.findAncestor(this, AbstractUIData.class);
+    final Integer submittedMarked = data.getSubmittedMarked();
+    if (submittedMarked != null) {
+      return submittedMarked.equals(data.getRowIndex());
+    }
+    return isMarked();
+  }
+
+  // XXX is introduced temporarily:
+  @Deprecated
+  public boolean isExpandedWithTemporaryState() {
+    final AbstractUIData data = ComponentUtils.findAncestor(this, AbstractUIData.class);
+    final List<Integer> submittedExpanded = data.getSubmittedExpanded();
+    if (submittedExpanded != null) {
+      return submittedExpanded.contains(data.getRowIndex());
+    }
+    return isExpanded();
+  }
+
+
 }

Modified: myfaces/tobago/branches/tobago-tree-table/tobago-example/tobago-example-test/src/main/webapp/tc/tree/tree-select.xhtml
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-tree-table/tobago-example/tobago-example-test/src/main/webapp/tc/tree/tree-select.xhtml?rev=1241833&r1=1241832&r2=1241833&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-tree-table/tobago-example/tobago-example-test/src/main/webapp/tc/tree/tree-select.xhtml (original)
+++ myfaces/tobago/branches/tobago-tree-table/tobago-example/tobago-example-test/src/main/webapp/tc/tree/tree-select.xhtml Wed Feb  8 09:30:17 2012
@@ -25,7 +25,7 @@
   <tc:page>
     <tc:gridLayoutConstraint width="600px" height="300px"/>
     <f:facet name="layout">
-      <tc:gridLayout rows="*;auto"/>
+      <tc:gridLayout rows="*;auto;auto"/>
     </f:facet>
 
     <tc:tree id="tree" selectable="single" showRoot="true" showRootJunction="true" value="#{tree.tree}" var="node">
@@ -35,6 +35,7 @@
       </tc:treeNode>
     </tc:tree>
 
+    <tc:in required="true"/>
     <tc:button label="Submit"/>
 
   </tc:page>

Modified: myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeIconRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeIconRenderer.java?rev=1241833&r1=1241832&r2=1241833&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeIconRenderer.java (original)
+++ myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeIconRenderer.java Wed Feb  8 09:30:17 2012
@@ -50,7 +50,7 @@ public class TreeIconRenderer extends La
     final UITreeIcon image = (UITreeIcon) component;
     final UITreeNode node = ComponentUtils.findAncestor(image, UITreeNode.class);
     final boolean folder = node.isFolder();
-    final boolean expanded = folder && node.isExpanded();
+    final boolean expanded = folder && node.isExpandedWithTemporaryState();
 
     String source;
     final String openSource;

Modified: myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeIndentRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeIndentRenderer.java?rev=1241833&r1=1241832&r2=1241833&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeIndentRenderer.java (original)
+++ myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeIndentRenderer.java Wed Feb  8 09:30:17 2012
@@ -55,7 +55,7 @@ public class TreeIndentRenderer extends 
     final boolean showJunctions = indent.isShowJunctions();
     // todo: sheet
     final boolean showRootJunction = data instanceof UITree && ((UITree) data).isShowRootJunction();
-    final boolean expanded = folder && node.isExpanded();
+    final boolean expanded = folder && node.isExpandedWithTemporaryState();
 
     final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
 

Modified: myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeNodeRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeNodeRenderer.java?rev=1241833&r1=1241832&r2=1241833&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeNodeRenderer.java (original)
+++ myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeNodeRenderer.java Wed Feb  8 09:30:17 2012
@@ -24,16 +24,13 @@ import org.apache.myfaces.tobago.context
 import org.apache.myfaces.tobago.event.TreeExpansionEvent;
 import org.apache.myfaces.tobago.event.TreeMarkedEvent;
 import org.apache.myfaces.tobago.internal.component.AbstractUIData;
-import org.apache.myfaces.tobago.internal.component.AbstractUITree;
 import org.apache.myfaces.tobago.layout.Display;
 import org.apache.myfaces.tobago.layout.LayoutBase;
 import org.apache.myfaces.tobago.renderkit.LayoutComponentRendererBase;
 import org.apache.myfaces.tobago.renderkit.css.Classes;
 import org.apache.myfaces.tobago.renderkit.css.Style;
 import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
-import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
 import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
-import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
 import org.apache.myfaces.tobago.renderkit.html.util.HtmlRendererUtils;
 import org.apache.myfaces.tobago.util.ComponentUtils;
 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
@@ -43,6 +40,7 @@ import org.slf4j.LoggerFactory;
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 import java.io.IOException;
+import java.util.List;
 import java.util.Map;
 
 public class TreeNodeRenderer extends LayoutComponentRendererBase {
@@ -75,12 +73,11 @@ public class TreeNodeRenderer extends La
     final String id = node.getClientId(facesContext);
     final boolean folder = node.isFolder();
 
-    // expand state
+    // expanded
     if (folder) {
-      boolean expanded = Boolean.parseBoolean(
-          requestParameterMap.get(id + ComponentUtils.SUB_SEPARATOR + AbstractUITree.SUFFIX_EXPANDED));
-      if (node.isExpanded() != expanded) {
-        new TreeExpansionEvent(node, node.isExpanded(), expanded).queue();
+      final List<Integer> submittedExpanded = data.getSubmittedExpanded();
+      if (submittedExpanded != null && submittedExpanded.contains(rowIndex) != node.isExpanded()) {
+        new TreeExpansionEvent(node, node.isExpanded(), submittedExpanded.contains(rowIndex)).queue();
       }
     }
 
@@ -101,26 +98,17 @@ public class TreeNodeRenderer extends La
     super.prepareRender(facesContext, component);
 
     final UITreeNode node = (UITreeNode) component;
-    if (isMarked(node)) {
+    if (node.isMarkedWithTemporaryState()) {
       node.setCurrentMarkup(Markup.MARKED.add(node.getCurrentMarkup()));
     }
     if (node.isFolder()) {
       node.setCurrentMarkup(Markup.FOLDER.add(node.getCurrentMarkup()));
-      if (node.isExpanded()) {
+      if (node.isExpandedWithTemporaryState()) {
         node.setCurrentMarkup(Markup.EXPANDED.add(node.getCurrentMarkup()));
       }
     }
   }
   
-  private boolean isMarked(UITreeNode node) {
-    final AbstractUIData data = ComponentUtils.findAncestor(node, AbstractUIData.class);
-    final Integer submittedMarked = data.getSubmittedMarked();
-    if (submittedMarked != null && submittedMarked.equals(data.getRowIndex())) {
-      return true;
-    }
-    return node.isMarked();
-  }
-
   @Override
   public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
 
@@ -134,8 +122,6 @@ public class TreeNodeRenderer extends La
     final boolean root = level == 0;
     // todo: make it possible to have a showRoot in UISheet
     final boolean showRoot = data instanceof UITree && ((UITree) data).isShowRoot();
-    // if the root is hidden, the root node must be expanded (otherwise you will see nothing)
-    final boolean expanded = folder && node.isExpanded() || !showRoot && root;
     final String parentId = data.getRowParentClientId();
     final boolean visible = root ? showRoot : data.isRowVisible();
 
@@ -169,10 +155,6 @@ public class TreeNodeRenderer extends La
       widthString = "100%";
     }
     writer.writeStyleAttribute(widthString);
-
-    if (folder) {
-      encodeExpandedHidden(writer, node, clientId, expanded);
-    }
   }
 
   @Override
@@ -180,15 +162,4 @@ public class TreeNodeRenderer extends La
     final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
     writer.endElement(HtmlElements.DIV);
   }
-
-  private void encodeExpandedHidden(
-      TobagoResponseWriter writer, UITreeNode node, String clientId, boolean expanded) throws IOException {
-    writer.startElement(HtmlElements.INPUT, node);
-    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN, false);
-    writer.writeClassAttribute(Classes.create(node, AbstractUITree.SUFFIX_EXPANDED, Markup.NULL));
-    writer.writeNameAttribute(clientId + ComponentUtils.SUB_SEPARATOR + AbstractUITree.SUFFIX_EXPANDED);
-    writer.writeAttribute(HtmlAttributes.VALUE, Boolean.toString(expanded), false);
-    writer.endElement(HtmlElements.INPUT);
-  }
-
 }

Modified: myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeRenderer.java?rev=1241833&r1=1241832&r2=1241833&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeRenderer.java (original)
+++ myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/TreeRenderer.java Wed Feb  8 09:30:17 2012
@@ -19,6 +19,7 @@ package org.apache.myfaces.tobago.render
 
 import org.apache.myfaces.tobago.component.UITreeNode;
 import org.apache.myfaces.tobago.internal.component.AbstractUITree;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
 import org.apache.myfaces.tobago.renderkit.LayoutComponentRendererBase;
 import org.apache.myfaces.tobago.renderkit.css.Classes;
 import org.apache.myfaces.tobago.renderkit.css.Style;
@@ -35,6 +36,7 @@ import org.slf4j.LoggerFactory;
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 import java.io.IOException;
+import java.util.List;
 
 public class TreeRenderer extends LayoutComponentRendererBase {
 
@@ -50,7 +52,18 @@ public class TreeRenderer extends Layout
     try {
       tree.setSubmittedMarked(Integer.parseInt(marked));
     } catch (NumberFormatException e) {
-      LOG.warn("marked: + " + marked + "'", e);
+      // should not happen
+      LOG.warn("Can't parse marked: + " + marked + "'", e);
+    }
+
+    // expanded
+    String expanded = (String) facesContext.getExternalContext().getRequestParameterMap()
+        .get(tree.getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + AbstractUITree.SUFFIX_EXPANDED);
+    try {
+      tree.setSubmittedExpanded(StringUtils.parseIntegerList(expanded));
+    } catch (Exception e) {
+      // should not happen
+      LOG.warn("Can't parse expanded: + " + expanded + "'", e);
     }
 
     // children
@@ -103,8 +116,18 @@ public class TreeRenderer extends Layout
     writer.writeNameAttribute(markedId);
     writer.writeIdAttribute(markedId);
     writer.writeClassAttribute(Classes.create(tree, AbstractUITree.SUFFIX_MARKED));
-    final Integer value = tree.getSubmittedMarked();
-    writer.writeAttribute(HtmlAttributes.VALUE, value != null ? Integer.toString(value) : "", false);
+    final Integer markedValue = tree.getSubmittedMarked();
+    writer.writeAttribute(HtmlAttributes.VALUE, markedValue != null ? Integer.toString(markedValue) : "", false);
+    writer.endElement(HtmlElements.INPUT);
+
+    writer.startElement(HtmlElements.INPUT, tree);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN, false);
+    final String expandedId = clientId + ComponentUtils.SUB_SEPARATOR + AbstractUITree.SUFFIX_EXPANDED;
+    writer.writeNameAttribute(expandedId);
+    writer.writeIdAttribute(expandedId);
+    writer.writeClassAttribute(Classes.create(tree, AbstractUITree.SUFFIX_EXPANDED));
+    final List<Integer> value = tree.getSubmittedExpanded();
+    writer.writeAttribute(HtmlAttributes.VALUE, value != null ? StringUtils.joinWithSurroundingSeparator(value) : "", false);
     writer.endElement(HtmlElements.INPUT);
 
     final int last = tree.hasRows() ? tree.getFirst() + tree.getRows() : Integer.MAX_VALUE;

Modified: myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tree.js
URL: http://svn.apache.org/viewvc/myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tree.js?rev=1241833&r1=1241832&r2=1241833&view=diff
==============================================================================
--- myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tree.js (original)
+++ myfaces/tobago/branches/tobago-tree-table/tobago-theme/tobago-theme-standard/src/main/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tree.js Wed Feb  8 09:30:17 2012
@@ -20,9 +20,11 @@ Tobago.Tree = {};
 Tobago.Tree.toggleNode = function(element) {
   var src;
   var node = element.closest(".tobago-treeNode, .tobago-treeMenuNode");
-  var expanded = node.find(".tobago-treeMenuNode-expanded, .tobago-treeNode-expanded");
+  var expanded
+      = node.closest(".tobago-treeMenu, .tobago-tree").children(".tobago-treeMenu-expanded, .tobago-tree-expanded");
   var toggle = node.find(".tobago-treeMenuNode-toggle, .tobago-treeNode-toggle");
-  if ("true" == expanded.attr("value")) {
+  var rowIndex = Tobago.Tree.rowIndex(node);
+  if (Tobago.Tree.isExpanded(node, expanded)) {
     Tobago.Tree.hideChildren(node);
     toggle.each(function() {
       src = jQuery(this).data("tobago-srcclose");
@@ -32,11 +34,11 @@ Tobago.Tree.toggleNode = function(elemen
       jQuery(this).attr("src", src);
       Tobago.fixPngAlpha(this);
     });
-    expanded.attr("value", "false");
+    expanded.attr("value", expanded.attr("value").replace(new RegExp("," + rowIndex + ","), ","));
     node.filter(".tobago-treeNode").removeClass("tobago-treeNode-markup-expanded");
     node.filter(".tobago-treeMenuNode").removeClass("tobago-treeMenuNode-markup-expanded");
   } else {
-    Tobago.Tree.showChildren(node);
+    Tobago.Tree.showChildren(node, expanded);
     toggle.each(function() {
       src = jQuery(this).data("tobago-srcopen");
       if (src == null) { // use the close icon if there is no open icon
@@ -45,7 +47,7 @@ Tobago.Tree.toggleNode = function(elemen
       jQuery(this).attr("src", src);
       Tobago.fixPngAlpha(this);
     });
-    expanded.attr("value", "true");
+    expanded.attr("value", expanded.attr("value") + rowIndex + ",");
     node.filter(".tobago-treeNode").addClass("tobago-treeNode-markup-expanded");
     node.filter(".tobago-treeMenuNode").addClass("tobago-treeMenuNode-markup-expanded");
   }
@@ -74,7 +76,7 @@ Tobago.Tree.hideChildren = function (nod
  * Show the children of the node recursively, there parents are expanded.
  * @param node A jQuery-Object as a node of the tree.
  */
-Tobago.Tree.showChildren = function (node) {
+Tobago.Tree.showChildren = function (node, expanded) {
   var treeParentSelector = "[data-tobago-treeparent='" + node.attr("id") + "']";
   var children;
   if (node.parent("td").parent("tr").size() == 1) { // tree inside of a sheet
@@ -86,9 +88,8 @@ Tobago.Tree.showChildren = function (nod
   }
   children.each(function () {
     var child = jQuery(this);
-    var expanded = child.find(".tobago-treeMenuNode-expanded, .tobago-treeNode-expanded");
-    if ("true" == expanded.attr("value")) {
-      Tobago.Tree.showChildren(child);
+    if (Tobago.Tree.isExpanded(child, expanded)) {
+      Tobago.Tree.showChildren(child, expanded);
     }
   });
 };
@@ -178,6 +179,20 @@ Tobago.Tree.init = function(elements) {
     node.addClass("tobago-treeMenuNode-markup-marked");
   });
 
+  // init expanded field
+  Tobago.Utils.selectWidthJQuery(elements, ".tobago-treeMenu, .tobago-tree").each(function() {
+    var expanded = jQuery(this).children(".tobago-treeMenu-expanded, .tobago-tree-expanded");
+    var string = ",";
+    jQuery(this).children(".tobago-treeMenuNode-markup-expanded, .tobago-treeNode-markup-expanded").each(function() {
+      string += Tobago.Tree.rowIndex(jQuery(this)) + ",";
+    });
+    expanded.attr("value", string);
+  });
+};
+
+Tobago.Tree.isExpanded = function(node, expanded) {
+  var rowIndex = Tobago.Tree.rowIndex(node);
+  return expanded.attr("value").indexOf("," + rowIndex + ",") > -1;
 };
 
 Tobago.Tree.rowIndex = function (node) {