Don't render invisible elements

POC shows that basic idea works, but still throws a lot of errors
(already rendered for menubars and SimpleTabBox, setting Tab from TabBox
to invisible/visible does not work, menubars invisible at first
sometimes, etc.)
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/Outline.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/Outline.js
index 06077c2..3c4f0ad 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/Outline.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/outline/Outline.js
@@ -59,7 +59,8 @@
   // menu bars
   this.titleMenuBar = scout.create('MenuBar', {
     parent: this,
-    menuOrder: new scout.GroupBoxMenuItemsOrder()
+    menuOrder: new scout.GroupBoxMenuItemsOrder(),
+    preventInitialFocus: true
   });
   this.nodeMenuBar = scout.create('MenuBar', {
     parent: this,
@@ -182,7 +183,6 @@
 scout.Outline.prototype._renderTitleMenuBar = function() {
   if (this.titleVisible) {
     this.titleMenuBar.render(this.$title);
-    this.titleMenuBar.$container.addClass('prevent-initial-focus');
   }
 };
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewMenuTab.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewMenuTab.js
index d78fb5a..0b0af64 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewMenuTab.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/desktop/viewbutton/ViewMenuTab.js
@@ -101,7 +101,7 @@
  * @override
  */
 scout.ViewMenuTab.prototype._renderVisible = function() {
-  this.$container.setVisible(this.visible);
+  scout.ViewMenuTab.parent.prototype._renderVisible.call(this);
   this.invalidateLayoutTree();
 };
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.js
index 9c9e0b5..5ac4543 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/FormField.js
@@ -256,13 +256,14 @@
  * @override
  */
 scout.FormField.prototype._renderVisible = function() {
-  this.$container.setVisible(this.visible);
-  if (this.rendered) {
+  scout.FormField.parent.prototype._renderVisible.call(this);
+  if (this.rendered || this.invisible) {
     this.parent.invalidateLogicalGrid(false);
-    var htmlCompParent = this.htmlComp.getParent();
-    if (htmlCompParent) { // may be null if $container is detached
-      htmlCompParent.invalidateLayoutTree();
-    }
+    this.htmlComp.invalidateLayoutTree();
+//    var htmlCompParent = this.htmlComp.getParent();
+//    if (htmlCompParent) { // may be null if $container is detached
+//      htmlCompParent.invalidateLayoutTree();
+//    }
   }
 };
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBoxLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBoxLayout.js
index 20ae2ca..f9d3485 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBoxLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/groupbox/GroupBoxLayout.js
@@ -162,11 +162,9 @@
  * Return menu-bar when it exists and it is visible.
  */
 scout.GroupBoxLayout.prototype._htmlMenuBar = function() {
-  if (this._groupBox.menuBar && this._groupBox.menuBarVisible) {
+  if (this._groupBox.menuBar && this._groupBox.menuBarVisible && this._groupBox.menuBar.visible) {
     var htmlMenuBar = scout.HtmlComponent.get(this._groupBox.menuBar.$container);
-    if (htmlMenuBar.isVisible()) {
-      return htmlMenuBar;
-    }
+    return htmlMenuBar;
   }
   return null;
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/listbox/ListBoxLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/listbox/ListBoxLayout.js
index ec3cc46..d1d7aff 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/listbox/ListBoxLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/listbox/ListBoxLayout.js
@@ -22,7 +22,7 @@
     height = size.height,
     filterBoxHeight;
 
-  if (this.filterBox && this.filterBox.rendered && this.filterBox.$container.isVisible()) {
+  if (this.filterBox && this.filterBox.rendered && this.filterBox.visible) {
     filterBoxHeight = scout.HtmlComponent.get(this.filterBox.$container).prefSize().height;
     height -= filterBoxHeight;
   }
@@ -31,7 +31,7 @@
   var htmlTable = scout.HtmlComponent.get(this.table.$container);
   htmlTable.setSize(new scout.Dimension(size.width, height));
 
-  if (this.filterBox && this.filterBox.rendered && this.filterBox.$container.isVisible()) {
+  if (this.filterBox && this.filterBox.rendered && this.filterBox.visible) {
     var htmlFilterBox = scout.HtmlComponent.get(this.filterBox.$container);
     htmlFilterBox.setSize(new scout.Dimension(size.width, filterBoxHeight));
   }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/treebox/TreeBoxLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/treebox/TreeBoxLayout.js
index 7b18512..40a4cd8 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/treebox/TreeBoxLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/treebox/TreeBoxLayout.js
@@ -22,7 +22,7 @@
     height = size.height,
     filterBoxHeight;
 
-  if (this.filterBox && this.filterBox.rendered && this.filterBox.$container.isVisible()) {
+  if (this.filterBox && this.filterBox.rendered && this.filterBox.visible) {
     filterBoxHeight = scout.HtmlComponent.get(this.filterBox.$container).prefSize().height;
     height -= filterBoxHeight;
   }
@@ -31,7 +31,7 @@
   var htmlTree = scout.HtmlComponent.get(this.tree.$container);
   htmlTree.setSize(new scout.Dimension(size.width, height));
 
-  if (this.filterBox && this.filterBox.rendered && this.filterBox.$container.isVisible()) {
+  if (this.filterBox && this.filterBox.rendered && this.filterBox.visible) {
     var htmlFilterBox = scout.HtmlComponent.get(this.filterBox.$container);
     htmlFilterBox.setSize(new scout.Dimension(size.width, filterBoxHeight));
   }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBar.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBar.js
index a27234a..ee8c458 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBar.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/menu/menubar/MenuBar.js
@@ -104,7 +104,7 @@
  * @override
  */
 scout.MenuBar.prototype._renderVisible = function() {
-  this.$container.setVisible(this.visible);
+  scout.MenuBar.parent.prototype._renderVisible.call(this);
   this.invalidateLayoutTree();
 };
 
@@ -180,16 +180,17 @@
     this.link(menuItems);
   }
 
-  if (this.rendered) {
+  var wasVisible = this.visible;
+  this.updateVisibility();
+
+  if (wasVisible && this.rendered) {
     var hasUnrenderedMenuItems = this.menuItems.some(function(elem) {
       return !elem.rendered;
     });
     if (!sameMenuItems || hasUnrenderedMenuItems) {
-      this.updateVisibility();
       this.rebuildItems(); // Re-layout menubar
     } else {
       // Don't rebuild menubar, but update "markers"
-      this.updateVisibility();
       this.updateDefaultMenu();
       this.updateLastItemMarker();
       this.updateLeftOfButtonMarker();
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/planner/PlannerLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/planner/PlannerLayout.js
index 6f2faee..1b0415f 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/planner/PlannerLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/planner/PlannerLayout.js
@@ -26,12 +26,12 @@
     yearContainerHeight = 0,
     gridTop = 0,
     scaleTop = 0,
-    htmlMenuBar = scout.HtmlComponent.get(menuBar.$container),
+    htmlMenuBar = menuBar.htmlComp,
     htmlContainer = this.planner.htmlComp,
     containerSize = htmlContainer.availableSize()
     .subtract(htmlContainer.insets());
 
-  if (menuBar.$container.isVisible()) {
+  if (menuBar.visible) {
     menuBarSize = scout.MenuBarLayout.size(htmlMenuBar, containerSize);
     htmlMenuBar.setSize(menuBarSize);
     menuBarHeight = menuBarSize.height;
@@ -50,7 +50,7 @@
   yearContainerHeight = scaleTop + $yearContainer.cssMarginY();
   gridHeight = gridTop + $grid.cssMarginY();
 
-  if (menuBar.$container.isVisible() && menuBar.position === 'bottom') {
+  if (menuBar.visible && menuBar.position === 'bottom') {
     yearContainerHeight += menuBarHeight;
     gridHeight += menuBarHeight;
   }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabArea.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabArea.js
index e7d5164..f0c988e 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabArea.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabArea.js
@@ -45,11 +45,7 @@
 };
 
 scout.SimpleTabArea.prototype._renderVisible = function() {
-  if (this.visible && this.tabs.length > 0) {
-    this.attach();
-  } else {
-    this.detach();
-  }
+  scout.SimpleTabArea.parent.prototype._renderVisible.call(this);
   this.invalidateLayoutTree();
 };
 
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBox.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBox.js
index 58aa35f..d71329f 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBox.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBox.js
@@ -67,9 +67,7 @@
 scout.SimpleTabBox.prototype._renderTabArea = function() {
   this.tabArea.render();
   this.$tabArea = this.tabArea.$container;
-  if (this.tabArea.attached) {
-    this.$tabArea.insertBefore(this.$viewContent);
-  }
+  this.$tabArea.insertBefore(this.$viewContent);
 };
 
 scout.SimpleTabBox.prototype._renderView = function(view) {
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBoxLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBoxLayout.js
index 9d93409..18f6767 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBoxLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tabbox/SimpleTabBoxLayout.js
@@ -38,7 +38,10 @@
   if (!this.tabBox.rendered) {
     return new scout.Dimension(0,0);
   }
-  // exprected the tab area is layouted dynamically only
+  if (!this.tabBox.tabArea.visible) {
+    return new scout.Dimension(0,0);
+  }
+  // expected the tab area is layouted dynamically only
   var htmlViewTabs = scout.HtmlComponent.get(this.tabBox.$tabArea),
     prefSize = htmlViewTabs.prefSize(),
     margins = htmlViewTabs.margins();
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooter.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooter.js
index ab09664..fbe133a 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooter.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableFooter.js
@@ -485,7 +485,7 @@
     dataMargins = scout.graphics.margins(table.$data),
     dataMarginsHeight = dataMargins.top + dataMargins.bottom,
     menuBar = table.menuBar,
-    htmlMenuBar = scout.HtmlComponent.get(menuBar.$container),
+    htmlMenuBar = menuBar.htmlComp,
     footer = table.footer,
     htmlContainer = table.htmlComp,
     containerSize = htmlContainer.availableSize()
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeader.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeader.js
index deeba59..736d899 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeader.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableHeader.js
@@ -755,7 +755,7 @@
 };
 
 scout.TableHeader.prototype._onMenuBarPropertyChange = function(event) {
-  if (event.propertyName === 'visible') {
+  if (event.propertyName === 'visible' && this.rendered) {
     this.$menuBarContainer.setVisible(event.newValue);
   }
 };
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableLayout.js
index acf59ab..60216f0 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/table/TableLayout.js
@@ -17,6 +17,7 @@
 
 scout.TableLayout.prototype.layout = function($container) {
   var menuBarHeight = 0,
+    menuBarSize,
     footerHeight = 0,
     headerHeight = 0,
     controlContainerHeight = 0,
@@ -29,12 +30,12 @@
     header = this.table.header,
     visibleColumns = this.table.visibleColumns(),
     lastColumn = visibleColumns[visibleColumns.length - 1],
-    htmlMenuBar = scout.HtmlComponent.get(menuBar.$container),
+    htmlMenuBar = menuBar.htmlComp,
     htmlContainer = this.table.htmlComp,
-    containerSize = htmlContainer.availableSize().subtract(htmlContainer.insets()),
-    menuBarSize = scout.MenuBarLayout.size(htmlMenuBar, containerSize);
+    containerSize = htmlContainer.availableSize().subtract(htmlContainer.insets());
 
   if (menuBar.visible) {
+    menuBarSize = scout.MenuBarLayout.size(htmlMenuBar, containerSize);
     htmlMenuBar.setSize(menuBarSize);
     menuBarHeight = menuBarSize.height;
   }
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/TreeLayout.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/TreeLayout.js
index f8449b8..42958d0 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/TreeLayout.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/tree/TreeLayout.js
@@ -33,7 +33,7 @@
   }
 
   heightOffset = 0;
-  if (menuBar.$container.isVisible()) {
+  if (menuBar.visible) {
     menuBarSize = scout.MenuBarLayout.size(htmlMenuBar, containerSize);
     htmlMenuBar.setSize(menuBarSize);
     heightOffset += menuBarSize.height;
diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/widget/Widget.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/widget/Widget.js
index 60c0b77..082e208 100644
--- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/widget/Widget.js
+++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/widget/Widget.js
@@ -63,6 +63,7 @@
   this.keyStrokeContext = this._createKeyStrokeContext();
   // Widgets using scout.LogicalGridLayout may have a grid to calculate the grid data of the children
   this.logicalGrid;
+  this.allowInitialFocus = true;
 };
 
 /**
@@ -256,6 +257,11 @@
   }
   this.rendering = true;
   this.$parent = $parent || this.parent.$container;
+  if (!this.visible) {
+    this._renderVisible();
+    this.rendering = false;
+    return;
+  }
   this._render();
   this._renderProperties();
   this._renderInspectorInfo();
@@ -283,10 +289,12 @@
  * Here values of the model are applied to the DOM / UI.
  */
 scout.Widget.prototype._renderProperties = function() {
+  this._renderLayoutData();
   this._renderEnabled();
   this._renderVisible();
   this._renderCssClass();
   this._renderLoading();
+  this._renderPreventInitialFocus();
 };
 
 /**
@@ -566,14 +574,47 @@
 };
 
 scout.Widget.prototype.setVisible = function(visible) {
-  this.setProperty('visible', visible);
+  if (this.visible === visible) {
+    return;
+  }
+  this._setProperty('visible', visible);
+  if (this.rendered || this.invisible) {
+    this._renderVisible();
+  }
 };
 
 scout.Widget.prototype._renderVisible = function() {
-  if (!this.$container) {
-    return;
+  if (!this.visible) {
+    if (this.$placeholder && this.$placeholder.isAttached()) { // isAttached is necessary because someone could have called this.remove
+      return;
+    }
+
+    // replace content with a placeholder
+    this.$placeholder = this.$parent.appendDiv('hidden');
+    if (this.rendered) {
+      var $parent = this.$parent;
+      this.$placeholder.before(this.$container);
+      this.remove();
+      this.$parent = $parent;
+    }
+    this.$container = this.$placeholder;
+    this.htmlComp = scout.HtmlComponent.install(this.$container, this.session);
+    this.invisible = true;
+  } else {
+    if (!this.$placeholder) {
+      return;
+    }
+
+    // replace placeholder with the actual content
+    var $placeholder = this.$placeholder;
+    this.$placeholder = null;
+    this.$container = null;
+    this.render(this.$parent);
+    this.$container.after($placeholder);
+    // XXX move classes from $container? proposal: $container is the only element which is available in invisible state and may be modified (adding classes). or maybe we can even avoid that by by using widget.addClass
+    $placeholder.remove();
+    this.invisible = false;
   }
-  this.$container.setVisible(this.visible);
 };
 
 scout.Widget.prototype._setCssClass = function(cssClass) {
@@ -640,6 +681,17 @@
   this.loadingSupport.renderLoading();
 };
 
+scout.Widget.prototype.setPreventInitialFocus = function(preventInitialFocus) {
+  this.setProperty('preventInitialFocus', preventInitialFocus);
+};
+
+scout.Widget.prototype._renderPreventInitialFocus = function() {
+  if (!this.$container) {
+    return;
+  }
+  this.$container.toggleClass('prevent-initial-focus', this.preventInitialFocus);
+};
+
 //--- Layouting / HtmlComponent methods ---
 
 scout.Widget.prototype.pack = function() {
@@ -713,13 +765,14 @@
 };
 
 scout.Widget.prototype.setLayoutData = function(layoutData) {
-  if (!this.rendered) {
+  this.setProperty('layoutData', layoutData);
+};
+
+scout.Widget.prototype._renderLayoutData = function() {
+  if (!this.htmlComp) {
     return;
   }
-  if (!this.htmlComp) {
-    throw new Error('Function expects a htmlComp property');
-  }
-  this.htmlComp.layoutData = layoutData;
+  this.htmlComp.layoutData = this.layoutData;
 };
 
 /**