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 2016/11/23 15:50:49 UTC

svn commit: r1770992 [19/23] - in /myfaces/tobago/trunk: src/site/fml/ tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/ tobago-theme/ tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/ tobago-theme/tobago-theme-c...

Added: myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-layout.js
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-layout.js?rev=1770992&view=auto
==============================================================================
--- myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-layout.js (added)
+++ myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-layout.js Wed Nov 23 15:50:47 2016
@@ -0,0 +1,269 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.Layout = {};
+
+Tobago.Layout.Orientation = {
+  HORIZONTAL: true,
+  VERTICAL: false
+};
+
+function init(table) {
+
+  var elements = table.children("tbody").children("tr").children("td").children();
+  elements.each(function () {
+    var element = jQuery(this);
+    var data = element.data("tobago-layout");
+    if (data !== undefined) {
+      var width = data.width;
+      if (width == null && element.prop("tagName") == "img") {
+        width = element.outerWidth();
+      }
+      if (width != null) {
+        element.css("width", width + "px");
+      }
+
+      var height = data.height;
+      if (height == null && element.prop("tagName") == "img") {
+        height = element.outerHeight();
+      }
+      if (height != null) {
+        element.css("height", height + "px");
+      }
+    }
+  });
+}
+
+function layoutGrid(table, orientation) {
+  var cells;
+  var banks;
+  var tokens;
+  var css;
+  var desired;
+
+  var tobagoLayout = table.data("tobago-layout");
+  if (! tobagoLayout) {
+    return;
+  }
+
+  if (orientation == Tobago.Layout.Orientation.HORIZONTAL) {
+//    cells = table.find("tr:first>td");
+    banks = table.children("colgroup").children("col");
+    tokens = tobagoLayout.columns;
+    css = "width";
+    desired = table.outerWidth();
+//    desired = table.parent().data("tobago-style").width.replace("px", ""); // todo: data("tobago-layout") wohl doch nicht so gut...? der wert wurde ja schon berechnet...
+  } else { // Tobago.Layout.Orientation.VERTICAL
+//    cells = table.find("tr");
+    banks = table.children("tbody").children("tr");
+    tokens = tobagoLayout.rows;
+    css = "height";
+    desired = table.outerHeight();
+//    desired = table.parent().data("tobago-style").height.replace("px", ""); // todo: data("tobago-layout")
+  }
+
+  if (tokens) {
+    table.css(css, "0px");
+    var i;
+    var cell;
+    var sumRelative = 0;
+    var sumUsed = 0;
+    for (i = 0; i < tokens.length; i++) {
+//      cell = cells.eq(i);
+      cell = banks.eq(i);
+      switch (typeof tokens[i]) {
+        case "number":
+          // a relative value
+          sumRelative += tokens[i];
+          break;
+        case "string":
+          // a string, currently only "auto" is supported
+          if ("auto" == tokens[i]) {
+            // nothing to do
+            sumUsed += orientation == Tobago.Layout.Orientation.HORIZONTAL ? cell.outerWidth() : cell.outerHeight();
+          } else {
+            console.warn("currently only 'auto' is supported, but found: '" + tokens[i] + "'");  // @DEV_ONLY
+          }
+          break;
+        case "object":
+          var m = tokens[i].measure;
+          if (m) {
+            setLength(table, banks, i, css, m);
+            if (/^\d+px$/.test(m)) {
+              sumUsed += m.substr(0, m.length - 2);
+            }
+          } else {
+            console.warn("can't find  measure in object: '" + tokens[i] + "'");  // @DEV_ONLY
+          }
+          break;
+        default:
+          console.warn("unsupported type of: '" + tokens[i] + "'");  // @DEV_ONLY
+          break;
+      }
+    }
+
+    table.css(css, "");
+    var rest = desired - sumUsed;
+    if (rest > 0 && sumRelative > 0) {
+      for (i = 0; i < tokens.length; i++) {
+        if (typeof tokens[i] == "number") {
+          setLength(table, banks, i, css, rest * tokens[i] / sumRelative + "px");
+        }
+      }
+    }
+  }
+}
+
+function setLength(table, banks, i, css, length) {
+  banks.eq(i).css(css, length);
+  /*
+   if (css == "width") {
+   var trs = table.children("tbody").children("tr");
+   trs.each(function () {
+   jQuery(this).children("td").eq(i).children().css(css, length);
+   });
+   } else {
+   var tr = table.children("tbody").children("tr").eq(i);
+   tr.children("td").children().css(css, length);
+   }
+   */
+}
+
+function setLength2(banks, i, css, length) {
+  banks.eq(i).css(css, length);
+}
+
+function layoutFlex(container, orientation) {
+
+  // todo: modernizr
+  // if (!Modernizr.flexbox && !Modernizr.flexboxtweener) ... do other
+
+  var cells;
+  var banks;
+  var tokens;
+  var css;
+
+  var tobagoLayout = container.data("tobago-layout");
+  if (! tobagoLayout) {
+    return;
+  }
+
+  if (orientation == Tobago.Layout.Orientation.HORIZONTAL) {
+    banks = container.children();
+    tokens = tobagoLayout.columns;
+    css = "width";
+  } else { // Tobago.Layout.Orientation.VERTICAL
+    banks = container.children();
+    tokens = tobagoLayout.rows;
+    css = "height";
+  }
+
+  if (tokens) {
+    var i;
+    var cell;
+    for (i = 0; i < tokens.length; i++) {
+      cell = banks.eq(i);
+      switch (typeof tokens[i]) {
+        case "number":
+          // a relative value
+          // todo: check for "any other" (non-layout) elements
+          var flex = "flex";
+          if (Tobago.browser.isMsie678910) { // todo: modernizr
+            flex = "-ms-flex";
+          }
+          // using "0px" and not "0", because IE11 needs the "px"
+          //container.children().eq(i).css(Modernizr.prefixed("flex"), tokens[i] + " 0 0px");  // todo: modernizr
+
+          var child = container.children().eq(i);
+          if (typeof child != 'undefined' && child.hasClass('tobago-box')) {
+            // XXX Is needed for IE11, otherwise tc:box doesn't displayed properly.
+            container.children().eq(i).css(flex, tokens[i] + " 0 auto");
+          } else {
+            container.children().eq(i).css(flex, tokens[i] + " 0 0px");
+          }
+          break;
+        case "string":
+          // a string, currently only "auto" is supported
+          break;
+        case "object":
+          if (tokens[i].measure) {
+            setLength2(banks, i, css, tokens[i].measure);
+          } else {
+            console.warn("can't find measure in object: '" + tokens[i] + "'");  // @DEV_ONLY
+          }
+          break;
+        default:
+          console.warn("unsupported type of: '" + tokens[i] + "'");  // @DEV_ONLY
+          break;
+      }
+    }
+  }
+}
+
+Tobago.Layout.init = function (elements) {
+
+  var gridLayouts = Tobago.Utils.selectWithJQuery(elements, ".tobago-gridLayout");
+
+  gridLayouts.each(function () {
+    var table = jQuery(this);
+    init(table);
+  });
+
+  gridLayouts.each(function () {
+    var table = jQuery(this);
+    layoutGrid(table, Tobago.Layout.Orientation.HORIZONTAL);
+    layoutGrid(table, Tobago.Layout.Orientation.VERTICAL);
+  });
+
+  //////////////////////////////////////////////
+
+  // the flex stuff.
+
+  var flexLayouts = Tobago.Utils.selectWithJQuery(elements, ".tobago-flexLayout");
+
+  flexLayouts.each(function () {
+    var container = jQuery(this);
+    layoutFlex(container, Tobago.Layout.Orientation.HORIZONTAL);
+    layoutFlex(container, Tobago.Layout.Orientation.VERTICAL);
+  });
+
+  //////////////////////////////////////////////
+
+  // fixing fixed header/footer: content should not scroll behind the footer
+  // XXX Is there a CSS solution?
+  // TODO: this might be reevaluated after a "resize"
+
+  var header = Tobago.Utils.selectWithJQuery(elements, ".navbar-fixed-top");
+  header.each(function () {
+    var content = header.next();
+    content.css({
+      marginTop: (parseInt(content.css("margin-top").replace("px", "")) + header.outerHeight(true)) + "px"
+    });
+  });
+
+  var footer = Tobago.Utils.selectWithJQuery(elements, ".navbar-fixed-bottom");
+  footer.each(function () {
+    var content = footer.prev();
+    content.css({
+      marginBottom: (parseInt(content.css("margin-bottom").replace("px", "")) + footer.outerHeight(true)) + "px"
+    });
+  });
+
+};
+
+Tobago.registerListener(Tobago.Layout.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.Layout.init, Tobago.Phase.AFTER_UPDATE);

Added: myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-logging.js
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-logging.js?rev=1770992&view=auto
==============================================================================
--- myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-logging.js (added)
+++ myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-logging.js Wed Nov 23 15:50:47 2016
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Logging helper class.
+ * All calls with level higher than LOG.level (with default LOG.INFO) are logged into the console object (if any).
+ * To set the level you may put this tag into the tc:page
+ *       <tc:dataAttribute name="tobago-log-level" value="DEBUG"/>
+ * This methods are only used in development mode, not in production mode.
+ */
+var LOG = {
+
+  DEBUG: 1,
+  INFO:  2,
+  WARN:  3,
+  ERROR: 4,
+
+  hasConsole: typeof console != "undefined",
+  level: 2, // INFO
+  maximumSeverity: 0, // lower than DEBUG
+
+  init: function(elements) {
+    var page = Tobago.Utils.selectWithJQuery(elements, "[data-tobago-log-level]");
+    var levelString = page.data("tobago-log-level");
+    switch (levelString) {
+      case "DEBUG":
+        this.level = this.DEBUG;
+        break;
+      case "INFO":
+        this.level = this.INFO;
+        break;
+      case "WARN":
+        this.level = this.WARN;
+        break;
+      case "ERROR":
+        this.level = this.ERROR;
+        break;
+    }
+  },
+
+  getMaximumSeverity: function() {
+    return this.maximumSeverity;
+  },
+
+  adjustMaximumSeverity: function (currentSeverity) {
+    if (currentSeverity >= this.maximumSeverity) {
+      this.maximumSeverity = currentSeverity;
+    }
+  },
+
+  debug: function(text) {
+    this.adjustMaximumSeverity(this.DEBUG);
+    if (this.hasConsole && this.DEBUG >= this.level) {
+      console.log(text);
+    }
+  },
+
+  info  : function(text) {
+    this.adjustMaximumSeverity(this.INFO);
+    if (this.hasConsole && this.INFO >= this.level) {
+      console.info(text);
+    }
+  },
+
+  warn: function(text) {
+    this.adjustMaximumSeverity(this.WARN);
+    if (this.hasConsole && this.WARN >= this.level) {
+      console.warn(text);
+    }
+  },
+
+  error: function(text) {
+    this.adjustMaximumSeverity(this.ERROR);
+    if (this.hasConsole && this.ERROR >= this.level) {
+      console.error(text);
+    }
+  },
+
+  /** @deprecated */
+  show: function() {
+    this.warn("Menthod LOG.show() is deprecated!");
+  },
+
+  /** @deprecated */
+  getMessages: function(severity) {
+    this.warn("Menthod LOG.getMessages() is deprecated!");
+  },
+
+  /** @deprecated */
+  getSeverityName: function(severity) {
+    this.warn("Menthod LOG.getSeverityName() is deprecated!");
+  },
+
+  /** @deprecated */
+  addAppender: function(appender) {
+    this.warn("Menthod LOG.addAppender() is deprecated!");
+  },
+
+  /** @deprecated */
+  addMessage: function(msg) {
+    this.warn("Menthod LOG.addMessage() is deprecated!");
+  },
+
+  /** @deprecated */
+  bindOnWindow: function() {
+    this.warn("Menthod LOG.bindOnWindow() is deprecated!");
+  },
+
+  /** @deprecated */
+  listScriptFiles: function() {
+    this.warn("Menthod LOG.listScriptFiles() is deprecated!");
+  },
+
+  /** @deprecated */
+  listThemeConfig : function() {
+    this.warn("Menthod LOG.listThemeConfig() is deprecated!");
+  },
+
+  /** @deprecated */
+  debugAjaxComponents: function() {
+    this.warn("Menthod LOG.debugAjaxComponents() is deprecated!");
+  }
+};

Added: myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-overlay.js
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-overlay.js?rev=1770992&view=auto
==============================================================================
--- myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-overlay.js (added)
+++ myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-overlay.js Wed Nov 23 15:50:47 2016
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Create a overlay barrier and animate it.
+ */
+
+Tobago.Config.set("Tobago", "waitOverlayDelay", 1000);
+Tobago.Config.set("Ajax", "waitOverlayDelay", 1000);
+
+(function ($) {
+
+  $.widget("tobago.overlay", {
+
+    options: {
+      /**
+       * This boolean indicates, if the overlay is "error" or "wait".
+       */
+      error: false,
+      /**
+       * Is this overlay for an AJAX request, or an normal submit?
+       * We need this information, because AJAX need to clone the animated image, but for a normal submit
+       * we must not clone it, because the animation stops in some browsers.
+       */
+      ajax: false,
+      /**
+       * The delay for the wait overlay. If not set the default delay is read from Tobago.Config.
+       */
+      waitOverlayDelay: undefined
+    },
+
+    overlay: null,
+
+    _create: function () {
+
+      // create the overlay
+
+      this.overlay = jQuery("<div>").addClass("tobago-page-overlay");
+      if (this.options.error) {
+        this.overlay.addClass("tobago-page-overlay-markup-error");
+      } else {
+        this.overlay.addClass("tobago-page-overlay-markup-wait");
+      }
+
+      var overlayOffset = {top: 0, left: 0};
+      if (this.element.is("body")) {
+        this.overlay.css({
+          position: "fixed",
+          zIndex: 1500 // greater than the bootstrap navbar
+        });
+      } else {
+        overlayOffset = this.element.offset();
+        this.overlay.outerWidth(this.element.outerWidth());
+        this.overlay.outerHeight(this.element.outerHeight());
+        this.overlay.css({
+          position: "absolute" // XXX is set via class, but seams to be overridden in IE11?
+        });
+      }
+
+      jQuery("body").append(this.overlay);
+
+      var wait = jQuery("<div>").addClass("tobago-page-overlayCenter");
+      this.overlay.append(wait);
+
+      var image = jQuery("<i>");
+      if (this.options.error) {
+        image.addClass("fa fa-flash fa-3x");
+        wait.addClass("alert-danger");
+      } else {
+        image.addClass("fa fa-refresh fa-3x fa-spin").css({opacity: 0.4});
+      }
+      wait.append(image);
+      wait.show();
+
+      var waitOverlayDelay = this.options.waitOverlayDelay
+          ? this.options.waitOverlayDelay
+          : Tobago.Config.get(this.options.ajax ? "Ajax" : "Tobago", "waitOverlayDelay");
+
+      if (Tobago.browser.isMsie678) {
+        this.overlay.css({filter: 'alpha(opacity=80)'});
+      }
+
+      this.overlay.css({
+        backgroundColor: jQuery('.tobago-page').css("background-color"),
+        opacity: 0})
+          .show()
+          .offset(overlayOffset)
+          .delay(this.options.error ? 0 : waitOverlayDelay)
+          .animate({opacity: '0.8'}, this.options.error ? 0 : 250, "linear");
+    },
+
+    _setOption: function (key, value) {
+
+      switch (key) {
+        case "error":
+          // If the error property has been changed, recreate the overlay.
+          var changed = key == 'error' && value != this.options.error;
+          if (changed) {
+            this.options.error = value;
+            this._destroy();
+            this._create();
+          }
+          break;
+        case "ajax":
+          // Changing of the ajax property seems not to make sense and is not supported.
+          break;
+      }
+
+      this._super("_setOption", key, value);
+
+    },
+
+    _destroy: function () {
+      this.overlay.remove();
+      this.overlay = null;
+    }
+
+  });
+
+}(jQuery));

Added: myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-popup.js
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-popup.js?rev=1770992&view=auto
==============================================================================
--- myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-popup.js (added)
+++ myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-popup.js Wed Nov 23 15:50:47 2016
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.Popup = {};
+
+/**
+ * Init popup for bootstrap
+ */
+Tobago.Popup.init = function (elements) {
+
+  var popups = Tobago.Utils.selectWithJQuery(elements, ".modal");
+  popups.each(function () {
+    var $popup = jQuery(this);
+    var $hidden = Tobago.Collapse.findHidden($popup);
+    if ($hidden.val() == "false") {
+      // XXX hack: this is needed for popups open by AJAX.
+      // XXX currently the DOM replacement done by Tobago doesn't remove the modal-backdrop
+      jQuery(".modal-backdrop").remove();
+
+      jQuery(this).modal("show"); // inits and opens the popup
+    } else {
+      jQuery(this).modal("hide"); // inits and hides the popup
+    }
+  });
+};
+
+Tobago.Popup.close = function (button) {
+  jQuery(button).parents('.modal:first').modal("hide");
+
+};
+
+Tobago.registerListener(Tobago.Popup.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.Popup.init, Tobago.Phase.AFTER_UPDATE);
+
+Tobago.Collapse = {};
+
+Tobago.Collapse.findHidden = function ($element) {
+  return jQuery(Tobago.Utils.escapeClientId($element.attr("id") + "::collapse"));
+};
+
+Tobago.Collapse.execute = function (collapse) {
+  var transition = collapse.transition;
+  var $for = jQuery(Tobago.Utils.escapeClientId(collapse.forId));
+  var $hidden = Tobago.Collapse.findHidden($for);
+  var isPopup = $for.hasClass("tobago-popup");
+  var newCollapsed;
+  switch (transition) {
+    case "hide":
+      newCollapsed = true;
+      break;
+    case "show":
+      newCollapsed = false;
+      break;
+    default:
+      console.error("unknown transition: '" + transition + "'");
+  }
+  if (newCollapsed) {
+    if (isPopup) {
+      $for.modal("hide");
+    } else {
+      $for.addClass("tobago-collapsed");
+    }
+  } else {
+    if (isPopup) {
+      $for.modal("show");
+    } else {
+      $for.removeClass("tobago-collapsed");
+    }
+  }
+  $hidden.val(newCollapsed);
+};

Added: myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-sheet.js
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-sheet.js?rev=1770992&view=auto
==============================================================================
--- myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-sheet.js (added)
+++ myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-sheet.js Wed Nov 23 15:50:47 2016
@@ -0,0 +1,729 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.Sheets = {
+  sheets: {},
+
+  get: function(id) {
+    return this.sheets[id];
+  },
+
+  put: function(sheet) {
+    this.sheets[sheet.id] = sheet;
+  }
+};
+
+Tobago.Sheet = function(
+    sheetId, unused1, unused2, unused3, unused4,
+    clickActionId, clickReloadComponentId, dblClickActionId, dblClickReloadComponentId, behaviorCommands) {
+  console.debug("New Sheet with id " + sheetId); // @DEV_ONLY
+  console.time("[tobago-sheet] constructor"); // @DEV_ONLY
+  this.id = sheetId;
+  Tobago.Sheets.put(this);
+  this.clickActionId = clickActionId;
+  this.clickReloadComponentId = clickReloadComponentId;
+  this.dblClickActionId = dblClickActionId;
+  this.dblClickReloadComponentId = dblClickReloadComponentId;
+  this.behaviorCommands = behaviorCommands;
+
+  this.setup();
+
+  console.timeEnd("[tobago-sheet] constructor"); // @DEV_ONLY
+};
+
+Tobago.Sheet.init = function(elements) {
+  console.time("[tobago-sheet] init"); // @DEV_ONLY
+  var sheets = Tobago.Utils.selectWithJQuery(elements, ".tobago-sheet");
+  sheets.each(function initSheets() {
+    var sheet = jQuery(this);
+    var id = sheet.attr("id");
+    var commands = sheet.data("tobago-row-action");
+    var click = commands ? commands.click : undefined;
+    var dblclick = commands ? commands.dblclick : undefined;
+    new Tobago.Sheet(id, undefined, undefined, undefined, undefined,
+        click != undefined ? click.action  : undefined,
+        click != undefined ? click.partially : undefined, // fixme: partially no longer used
+        dblclick != undefined ? dblclick.action : undefined,
+        dblclick != undefined ? dblclick.partially: undefined, // fixme: partially no longer used
+        sheet.data("tobago-behavior-commands")); // type array
+
+    //////////////////////////////////////////////
+    // XXX bugfix for IE11 (lower than IE11 isn't supported for that feature)
+    // if a max-height is set on the sheet,
+    if (Tobago.browser.isMsie && sheet.css("max-height") != "none") {
+      sheet.css("height", sheet.css("height")); // reset the height to the same value
+    }
+  });
+
+  Tobago.Sheet.setup2(sheets);
+
+  Tobago.Utils.selectWithJQuery(elements, "button[data-tobago-command=sheetSelectAll]").click(function(event) {
+    Tobago.Sheet.selectAll(jQuery(event.target).closest(".tobago-sheet"));
+  });
+  Tobago.Utils.selectWithJQuery(elements, "button[data-tobago-command=sheetDeselectAll]").click(function(event) {
+    Tobago.Sheet.deselectAll(jQuery(event.target).closest(".tobago-sheet"));
+  });
+  Tobago.Utils.selectWithJQuery(elements, "button[data-tobago-command=sheetToggleAll]").click(function(event) {
+    Tobago.Sheet.toggleAll(jQuery(event.target).closest(".tobago-sheet"));
+  });
+
+  console.timeEnd("[tobago-sheet] init"); // @DEV_ONLY
+};
+
+Tobago.registerListener(Tobago.Sheet.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.Sheet.init, Tobago.Phase.AFTER_UPDATE);
+
+Tobago.Sheet.prototype.reloadWithAction = function(source, action) {
+    console.debug("reload sheet with action '" + action + "'"); // @DEV_ONLY
+  var executeIds = this.id;
+  var renderIds = this.id;
+  if (this.behaviorCommands && this.behaviorCommands.reload) {
+    if (this.behaviorCommands.reload.execute) {
+      executeIds +=  " " + behaviorCommands.reload.execute;
+    }
+    if (this.behaviorCommands.reload.render) {
+      renderIds +=  " " + this.behaviorCommands.reload.render;
+    }
+  }
+  jsf.ajax.request(
+      action,
+      null,
+      {
+        "javax.faces.behavior.event": "reload",
+        execute: executeIds,
+        render: renderIds
+      });
+};
+
+Tobago.Sheet.setup2 = function (sheets) {
+
+  jQuery(sheets).each(function() {
+    Tobago.Sheet.resetInputFieldSize(jQuery(this));
+  });
+
+  // synchronize column widths
+  jQuery(sheets).each(function() {
+
+    // basic idea: there are two possible sources for the sizes:
+    // 1. the columns attribute of <tc:sheet> like columns="3*;200px;3*", held by data attribute "tobago-layout"
+    // 2. the hidden field which may contain a value like ",300,200,100,"
+    //
+    // The 1st source usually is the default set by the developer.
+    // The 2nd source usually is the value set by the user manipulating the column widths.
+    //
+    // So, if the 2nd is set, we use it, if not set, we use the 1st source.
+    //
+
+    var $sheet = jQuery(this);
+
+    var hidden = Tobago.Sheet.findHiddenWidths($sheet);
+
+    if (hidden.length > 0 && hidden.val()) {
+      // if the hidden has a value, than also the colgroup/col are set correctly
+      var columnWidths = jQuery.parseJSON(hidden.val());
+      console.info("columnWidths: " + columnWidths); // @DEV_ONLY
+      console.info(columnWidths); // @DEV_ONLY
+    } else {
+      // otherwise use the layout definition
+      var layout = $sheet.data("tobago-layout");
+      if (layout && layout.columns && layout.columns.length > 0) {
+        var tokens = layout.columns;
+        var rendered = jQuery.parseJSON(Tobago.Sheet.findHiddenRendered($sheet).val());
+
+        var $headerTable = $sheet.children("header").children("table");
+        var $headerCol = $headerTable.children("colgroup").children("col");
+        var $bodyTable = $sheet.children("div").children("table");
+        var $bodyCol = $bodyTable.children("colgroup").children("col");
+
+        console.assert($headerCol.length - 1 == $bodyCol.length, "header and body column number doesn't match");  // @DEV_ONLY
+
+        var i;
+        var sumRelative = 0;
+        var widthRelative = $bodyTable.width();
+        for (i = 0; i < tokens.length; i++) {
+          if (rendered[i] == "true") {
+            if (typeof tokens[i] == "number") {
+              sumRelative += tokens[i];
+            } else if (typeof tokens[i] == "object" && tokens[i].measure != undefined) {
+              var intValue = parseInt(tokens[i].measure);
+              if (tokens[i].measure.lastIndexOf("px") > 0) {
+                widthRelative -= intValue;
+              } else if (tokens[i].measure.lastIndexOf("%") > 0) {
+                widthRelative -= parseInt($bodyTable.width() / 100 * intValue);
+              }
+            }
+          }
+        }
+        if (widthRelative < 0) {
+          widthRelative = 0;
+        }
+
+        var headerBodyColCount = 0;
+        for (i = 0; i < tokens.length; i++) {
+          var colWidth = 0;
+          if (rendered[i] == "true") {
+            if (typeof tokens[i] == "number") {
+              colWidth = parseInt((tokens[i] * widthRelative) / sumRelative);
+            } else if (typeof tokens[i] == "object" && tokens[i].measure != undefined) {
+              var intValue = parseInt(tokens[i].measure);
+              if (tokens[i].measure.lastIndexOf("px") > 0) {
+                colWidth = intValue;
+              } else if (tokens[i].measure.lastIndexOf("%") > 0) {
+                colWidth = parseInt($bodyTable.width() / 100 * intValue);
+              }
+            }
+            $headerCol.eq(headerBodyColCount).attr("width", colWidth);
+            $bodyCol.eq(headerBodyColCount).attr("width", colWidth);
+            headerBodyColCount++;
+          }
+        }
+      }
+    }
+    Tobago.Sheet.addHeaderFillerWidth($sheet);
+  });
+
+  // resize: mouse events
+  jQuery(sheets).find(".tobago-sheet-headerResize").each(function () {
+    jQuery(this).click(function () {
+      return false;
+    });
+    jQuery(this).mousedown(function (event) {
+      // begin resizing
+      console.info("down"); // @DEV_ONLY
+      var columnIndex = jQuery(this).data("tobago-column-index");
+      var body = jQuery("body");
+      var sheet = jQuery(this).closest(".tobago-sheet");
+      var headerTable = sheet.find(".tobago-sheet-headerTable");
+      var bodyTable = sheet.find(".tobago-sheet-bodyTable");
+      var headerColumn = headerTable.children("colgroup").children("col").eq(columnIndex);
+      var bodyColumn = bodyTable.children("colgroup").children("col").eq(columnIndex);
+      var data = {
+        columnIndex: columnIndex,
+        originalClientX: event.clientX,
+        headerColumn: headerColumn,
+        bodyColumn: bodyColumn,
+        originalHeaderColumnWidth: parseInt(headerColumn.attr("width"))
+      };
+
+      // Set width attribute: Avoid scrollBar position flip to 0.
+      headerTable.css("width", headerTable.outerWidth());
+      bodyTable.css("width", bodyTable.outerWidth());
+
+      body.on("mousemove", data, function(event) {
+        console.info("move"); // @DEV_ONLY
+        var delta = event.clientX - event.data.originalClientX;
+        delta = -Math.min(-delta, event.data.originalHeaderColumnWidth - 10);
+        var columnWidth = event.data.originalHeaderColumnWidth + delta;
+        event.data.headerColumn.attr("width", columnWidth);
+        event.data.bodyColumn.attr("width", columnWidth);
+        Tobago.Sheet.resetInputFieldSize(headerColumn.closest("table"));
+        Tobago.clearSelection();
+        return false;
+      });
+      body.one("mouseup", function(event) {
+        // switch off the mouse move listener
+        jQuery("body").off("mousemove");
+        console.info("up"); // @DEV_ONLY
+        // copy the width values from the header to the body, (and build a list of it)
+        var tokens = sheet.data("tobago-layout").columns;
+        var rendered = jQuery.parseJSON(Tobago.Sheet.findHiddenRendered(sheet).val());
+        var hidden = Tobago.Sheet.findHiddenWidths(sheet);
+        var hiddenWidths;
+        if (hidden.length > 0 && hidden.val()) {
+          hiddenWidths = jQuery.parseJSON(hidden.val());
+        }
+        var headerCols = headerTable.find("col");
+        var bodyCols = bodyTable.find("col");
+        var widths = [];
+        var oldWidthList = [];
+        var i;
+        for (i = 0; i < bodyCols.length; i++) {
+          oldWidthList[i] = bodyCols.eq(i).width();
+        }
+        var usedWidth = 0;
+        var headerBodyColCount = 0;
+        for (i = 0; i < rendered.length; i++) {
+          if (rendered[i] == "true") {
+            // last column is the filler column
+            var newWidth = headerCols.eq(headerBodyColCount).width();
+            // for the hidden field
+            widths[i] = newWidth;
+            usedWidth += newWidth;
+
+            var oldWidth = bodyCols.eq(headerBodyColCount).width();
+            if (oldWidth != newWidth) {
+              // set to the body
+              bodyCols.eq(headerBodyColCount).attr("width", newWidth);
+              // reset the width inside of the cells (TD) if the value was changed.
+              var tds = jQuery("td:nth-child(" + (headerBodyColCount + 1) + ")", bodyTable);
+              if (tds.size() > 0) {
+                var innerWidth = tds.children().eq(0).width() - oldWidthList[headerBodyColCount] + newWidth;
+                // setting all sizes of the inner cells to the same value
+                tds.children().width(innerWidth);
+                // XXX later, if we have box-sizing: border-box we can set the width to 100%
+              }
+            }
+            headerBodyColCount++;
+          } else if (hiddenWidths != undefined && hiddenWidths.length >= i) {
+            widths[i] = hiddenWidths[i];
+          } else {
+            if (typeof tokens[i] == "number") {
+              widths[i] = 100;
+            } else if (typeof tokens[i] == "object" && tokens[i].measure != undefined) {
+              var intValue = parseInt(tokens[i].measure);
+              if (tokens[i].measure.lastIndexOf("px") > 0) {
+                widths[i] = intValue;
+              } else if (tokens[i].measure.lastIndexOf("%") > 0) {
+                widths[i] = parseInt(bodyTable.width() / 100 * intValue);
+              }
+            }
+          }
+        }
+        // Remove width attribute: Avoid scrollBar position flip to 0.
+        headerTable.css("width", "");
+        bodyTable.css("width", "");
+
+        // store the width values in a hidden field
+        Tobago.Sheet.findHiddenWidths(sheet).val(JSON.stringify(widths));
+        return false;
+      });
+    });
+  });
+
+  // scrolling
+  jQuery(sheets).find(".tobago-sheet-body").bind("scroll", function () {
+    var sheetBody = jQuery(this);
+    var scrollLeft = sheetBody.prop("scrollLeft");
+    var scrollTop = sheetBody.prop("scrollTop");
+
+    // scrolling the table should move the header
+    sheetBody.siblings(".tobago-sheet-header").prop("scrollLeft", scrollLeft);
+
+    // store the position in a hidden field
+    var hidden = Tobago.Sheet.findHiddenScrollPosition(sheetBody.parent());
+    hidden.val(Math.round(scrollLeft) + ";" + Math.round(scrollTop));
+  });
+
+  // restore scroll position
+  jQuery(sheets).each(function () {
+    var sheet = jQuery(this);
+    var hidden = Tobago.Sheet.findHiddenScrollPosition(sheet);
+    var sep = hidden.val().indexOf(";");
+    if (sep != -1) {
+      var scrollLeft = hidden.val().substr(0, sep);
+      var scrollTop = hidden.val().substr(sep + 1);
+      var body = sheet.children(".tobago-sheet-body");
+      body.prop("scrollLeft", scrollLeft);
+      body.prop("scrollTop", scrollTop);
+      sheet.children(".tobago-sheet-header").prop("scrollLeft", scrollLeft);
+    }
+  });
+
+  // add selection listeners
+  jQuery(sheets).each(function () {
+    var sheet = jQuery(this);
+    var selectionMode = sheet.data("tobago-selection-mode");
+    if (selectionMode == "single" || selectionMode == "singleOrNone" || selectionMode == "multi") {
+      Tobago.Sheet.getRows(sheet).each(function () {
+        var row = jQuery(this);
+        row.bind("mousedown", function (event) {
+          sheet.data("tobago-mouse-down-x", event.clientX);
+          sheet.data("tobago-mouse-down-y", event.clientY);
+        });
+        row.click(function (event) {
+          var $target = jQuery(event.target);
+          var $row = jQuery(this);
+          if ($target.hasClass("tobago-sheet-columnSelector") || !Tobago.Sheet.isInputElement($target)) {
+            var $sheet = $row.closest(".tobago-sheet");
+
+            if (Math.abs($sheet.data("tobago-mouse-down-x") - event.clientX)
+                + Math.abs($sheet.data("tobago-mouse-down-y") - event.clientY) > 5) {
+              // The user has moved the mouse. We assume, the user want to select some text inside the sheet,
+              // so we doesn't select the row.
+              return;
+            }
+
+            Tobago.clearSelection();
+
+            var $rows = Tobago.Sheet.getRows($sheet);
+            var $selector = Tobago.Sheet.getSelectorCheckbox($row);
+
+            var selectionMode = $sheet.data("tobago-selection-mode");
+
+            if ((!event.ctrlKey && !event.metaKey && $selector.size() == 0)
+                || selectionMode == "single" || selectionMode == "singleOrNone") {
+              Tobago.Sheet.deselectAll($sheet);
+              Tobago.Sheet.resetSelected($sheet);
+            }
+
+            var lastClickedRowIndex = $sheet.data("tobago-last-clicked-row-index");
+            if (event.shiftKey && selectionMode == "multi" && lastClickedRowIndex > -1) {
+              if (lastClickedRowIndex <= $row.index()) {
+                Tobago.Sheet.selectRange($sheet, $rows, lastClickedRowIndex, $row.index(), true, false);
+              } else {
+                Tobago.Sheet.selectRange($sheet, $rows, $row.index(), lastClickedRowIndex, true, false);
+              }
+            } else if (selectionMode != "singleOrNone" || !Tobago.Sheet.isRowSelected($sheet, $row)) {
+              Tobago.Sheet.toggleSelection($sheet, $row, $selector);
+            }
+            var commands = sheet.data("tobago-row-action");
+            var click = commands ? commands.click : undefined;
+            var clickActionId = click ? click.action : undefined;
+            var clickExecuteIds = click ? click.execute : undefined;
+            var clickRenderIds = click ? click.render : undefined;
+
+            var id = $sheet.attr("id");
+
+            if (clickActionId) {
+              var action;
+              var index = clickActionId.indexOf(id);
+              var rowIndex = Tobago.Sheet.getDataIndex($sheet, $row);
+              if (index >= 0) {
+                action = id + ":" + rowIndex + ":" + clickActionId.substring(index + id.length +1);
+              } else {
+                action = id + ":" + rowIndex + ":" + clickActionId;
+              }
+              if (clickExecuteIds && clickExecuteIds.length > 0) {
+                //Tobago.reloadComponent($target.get(0), clickReloadComponentId, action)
+                jsf.ajax.request(
+                    action,
+                    event,
+                    {
+                      //"javax.faces.behavior.event": "click",
+                      execute: clickExecuteIds,
+                      render: clickRenderIds
+                    });
+              } else {
+                Tobago.submitAction($target.get(0), action);
+              }
+            }
+          }
+        });
+        // todo:
+        if (Tobago.Sheets.get(sheet.attr("id")).dblClickActionId) {
+          row.bind("dblclick", function (event) {
+            // todo: re-implement
+            Tobago.Sheets.get(sheet.attr("id")).doDblClick(event);
+          });
+        }
+      });
+    }
+    sheet.find("input.tobago-sheet-columnSelector").click(function(event) {event.preventDefault()});
+  });
+
+    // init reload
+  jQuery(sheets).filter("[data-tobago-reload]").each(function() {
+    var sheet = jQuery(this);
+    Tobago.Sheets.get(sheet.attr("id")).initReload();
+  });
+
+  // init paging by pages
+  jQuery(sheets).find(".tobago-sheet-pagingText").each(function() {
+    var pagingText = jQuery(this);
+    pagingText.click(function () {
+      var text = jQuery(this);
+      text.children(".tobago-sheet-pagingOutput").hide();
+      text.children(".tobago-sheet-pagingInput").show().focus().select();
+    });
+    pagingText.children(".tobago-sheet-pagingInput")
+        .blur(function () {
+          Tobago.Sheet.hideInputOrSubmit(jQuery(this));
+        }).keydown(function (event) {
+          if (event.keyCode == 13) {
+            event.stopPropagation();
+            event.preventDefault();
+            jQuery(this).blur();
+          }
+        });
+  });
+};
+
+Tobago.Sheet.hideInputOrSubmit = function(input) {
+  var output = input.siblings(".tobago-sheet-pagingOutput");
+  var changed = output.html() != input.val();
+  var sheetId = input.parents(".tobago-sheet:first").attr("id");
+  output.html(input.val());
+  if (changed) {
+    Tobago.Sheets.get(sheetId).reloadWithAction(input.get(0), input.attr("id"));
+  } else {
+    console.info("no update needed"); // @DEV_ONLY
+    input.hide();
+    output.show();
+  }
+};
+
+Tobago.Sheet.findHiddenSelected = function($sheet){
+  var id = $sheet.attr("id") + Tobago.SUB_COMPONENT_SEP + "selected";
+  return jQuery(Tobago.Utils.escapeClientId(id));
+};
+
+Tobago.Sheet.findHiddenScrollPosition = function($sheet){
+  var id = $sheet.attr("id") + Tobago.SUB_COMPONENT_SEP + "scrollPosition";
+  return jQuery(Tobago.Utils.escapeClientId(id));
+};
+
+Tobago.Sheet.findHiddenWidths = function($sheet){
+  var id = $sheet.attr("id") + Tobago.SUB_COMPONENT_SEP + "widths";
+  return jQuery(Tobago.Utils.escapeClientId(id));
+};
+
+Tobago.Sheet.findHiddenRendered = function($sheet){
+  var id = $sheet.attr("id") + Tobago.SUB_COMPONENT_SEP + "rendered";
+  return jQuery(Tobago.Utils.escapeClientId(id));
+};
+
+Tobago.Sheet.addHeaderFillerWidth = function($sheet) {
+  var $headerTable = $sheet.find(".tobago-sheet-headerTable");
+  var $headerCols = $headerTable.find("col");
+  $headerCols.last().attr("width", Tobago.Sheet.getScrollBarSize());
+};
+
+Tobago.Sheet.getScrollBarSize = function() {
+  var $outer = $('<div>').css({visibility: 'hidden', width: 100, overflow: 'scroll'}).appendTo('body'),
+      widthWithScroll = $('<div>').css({width: '100%'}).appendTo($outer).outerWidth();
+  $outer.remove();
+  return 100 - widthWithScroll;
+};
+
+Tobago.Sheet.prototype.setup = function() {
+  console.time("[tobago-sheet] setup"); // @DEV_ONLY
+  this.initReload();
+  console.timeEnd("[tobago-sheet] setup"); // @DEV_ONLY
+};
+
+Tobago.Sheet.prototype.initReload = function() {
+  var sheet = jQuery(Tobago.Utils.escapeClientId(this.id));
+  var reload = sheet.data("tobago-reload");
+  if (typeof reload == "number") {
+    Tobago.addReloadTimeout(this.id, Tobago.bind2(this, "reloadWithAction", null, this.id), reload);
+  }
+};
+
+Tobago.Sheet.prototype.doDblClick = function(event) {
+    if (! event) {
+      event = window.event;
+    }
+
+    var srcElement;
+    if (event.target) {
+      // W3C DOM level 2
+      srcElement = event.target;
+    } else {
+      // IE
+      srcElement = event.srcElement;
+    }
+
+    if (!Tobago.Sheet.isInputElement(jQuery(srcElement))) {
+      var row = jQuery(srcElement).closest("tr");
+      var sheet = row.closest(".tobago-sheet");
+      var rowIndex = row.index() + sheet.data("tobago-first");
+      if (this.dblClickActionId) {
+        var action;
+        var index = this.dblClickActionId.indexOf(this.id);
+        if (index >= 0) {
+          action = this.id + ":" + rowIndex + ":" + this.dblClickActionId.substring(index + this.id.length +1);
+        } else {
+          action = this.id + ":" + rowIndex + ":" + this.dblClickActionId;
+        }
+        if (this.dblClickReloadComponentId && this.dblClickReloadComponentId.length > 0) {
+          //Tobago.reloadComponent(srcElement, this.dblClickReloadComponentId, action);
+          jsf.ajax.request(
+              action,
+              event,
+              {
+                //"javax.faces.behavior.event": "dblclick",
+                execute: this.dblClickReloadComponentId,
+                render: this.dblClickReloadComponentId
+              });
+        } else {
+          Tobago.submitAction(srcElement, action);
+        }
+      }
+    }
+  };
+
+/**
+ * Get the element, which indicates the selection
+ * @param row as a jQuery object
+ */
+Tobago.Sheet.getSelectorCheckbox = function(row) {
+  return row.find(">td>input.tobago-sheet-columnSelector");
+};
+
+Tobago.Sheet.prototype.getSiblingRow = function(row, i) {
+  return row.parentNode.childNodes[i];
+};
+
+Tobago.Sheet.getRows = function($sheet) {
+  return $sheet.find(">div>table>tbody>tr");
+};
+
+Tobago.Sheet.isRowSelected = function(sheet, row) {
+  var rowIndex = +row.data("tobago-row-index");
+  if (!rowIndex) {
+    rowIndex = row.index() + sheet.data("tobago-first");
+  }
+  return Tobago.Sheet.isSelected(sheet, rowIndex);
+};
+
+Tobago.Sheet.isSelected = function(sheet, rowIndex) {
+  return Tobago.Sheet.findHiddenSelected(sheet).val().indexOf("," + rowIndex + ",") >= 0;
+};
+
+Tobago.Sheet.resetSelected = function($sheet) {
+  Tobago.Sheet.findHiddenSelected($sheet).val(",");
+};
+
+Tobago.Sheet.toggleSelection = function($sheet, $row, $checkbox) {
+  $sheet.data("tobago-last-clicked-row-index", $row.index());
+  if (!$checkbox.is(":disabled")) {
+    var $selected = Tobago.Sheet.findHiddenSelected($sheet);
+    var rowIndex = Tobago.Sheet.getDataIndex($sheet, $row);
+    if (Tobago.Sheet.isSelected($sheet, rowIndex)) {
+      Tobago.Sheet.deselectRow($selected, rowIndex, $row, $checkbox);
+    } else {
+      Tobago.Sheet.selectRow($selected, rowIndex, $row, $checkbox);
+    }
+  }
+};
+
+Tobago.Sheet.selectAll = function($sheet) {
+  var $rows = Tobago.Sheet.getRows($sheet);
+  Tobago.Sheet.selectRange($sheet, $rows, 0, $rows.size() - 1, true, false);
+};
+
+Tobago.Sheet.deselectAll = function($sheet) {
+  var $rows = Tobago.Sheet.getRows($sheet);
+  Tobago.Sheet.selectRange($sheet, $rows, 0, $rows.size() - 1, false, true);
+};
+
+Tobago.Sheet.toggleAll = function(sheet) {
+  var rows = Tobago.Sheet.getRows(sheet);
+  Tobago.Sheet.selectRange(sheet, rows, 0, rows.size() - 1, true, true);
+};
+
+Tobago.Sheet.selectRange = function($sheet, $rows, first, last, selectDeselected, deselectSelected) {
+  if ($rows.size() == 0) {
+    return;
+  }
+  var selected = Tobago.Sheet.findHiddenSelected($sheet);
+  for (var i = first; i <= last; i++) {
+    var row = $rows.eq(i);
+    var checkbox = Tobago.Sheet.getSelectorCheckbox(row);
+    if (!checkbox.is(":disabled")) {
+      var rowIndex = Tobago.Sheet.getDataIndex($sheet, row);
+      var on = selected.val().indexOf("," + rowIndex + ",") >= 0;
+      if (selectDeselected && !on) {
+        Tobago.Sheet.selectRow(selected, rowIndex, row, checkbox);
+      } else if (deselectSelected && on) {
+        Tobago.Sheet.deselectRow(selected, rowIndex, row, checkbox);
+      }
+    }
+  }
+};
+
+Tobago.Sheet.getDataIndex = function(sheet, row) {
+  var rowIndex = row.data("tobago-row-index");
+  if (rowIndex) {
+    return +rowIndex;
+  } else {
+    return row.index() + sheet.data("tobago-first");
+  }
+};
+
+/**
+ * @param $selected input-element type=hidden: Hidden field with the selection state information
+ * @param rowIndex int: zero based index of the row.
+ * @param $row tr-element: the row.
+ * @param $checkbox input-element: selector in the row.
+ */
+Tobago.Sheet.selectRow = function($selected, rowIndex, $row, $checkbox) {
+  $selected.val($selected.val() + rowIndex + ",");
+  $row.addClass("tobago-sheet-row-markup-selected table-info");
+//  checkbox.prop("checked", true);
+  setTimeout(function() {$checkbox.prop("checked", true);}, 0);
+};
+
+/**
+ * @param $selected input-element type=hidden: Hidden field with the selection state information
+ * @param rowIndex int: zero based index of the row.
+ * @param $row tr-element: the row.
+ * @param $checkbox input-element: selector in the row.
+ */
+Tobago.Sheet.deselectRow = function($selected, rowIndex, $row, $checkbox) {
+  $selected.val($selected.val().replace(new RegExp("," + rowIndex + ","), ","));
+  $row.removeClass("tobago-sheet-row-markup-selected table-info");
+//  checkbox.prop("checked", false); Async because of TOBAGO-1312
+  setTimeout(function() {$checkbox.prop("checked", false);}, 0);
+};
+
+Tobago.Sheet.resetInputFieldSize = function (table) {
+  var span = table.find("td>div>span");
+  span.children("input,select").each(function () {
+    var input = jQuery(this);
+    input.outerWidth(input.parent().width());
+  });
+};
+
+Tobago.Sheet.isInputElement = function($element) {
+  return ["INPUT", "TEXTAREA", "SELECT", "A", "BUTTON"].indexOf($element.prop("tagName")) > -1;
+};
+
+(function(jQuery){
+ jQuery.fn.borderBoxWidth = function(width) {
+    return this.each(function() {
+       obj = jQuery(this);
+       var extraWidth = obj.outerWidth() - obj.width();
+       obj.width(width - extraWidth);
+    });
+ };
+})(jQuery);
+
+/*
+ var header = $(".tobago-sheet-headerTable");
+ var body = $(".tobago-sheet-bodyTable");
+
+ header;
+ body;
+
+ header.find("col").each(function(){
+
+ console.info($(this).attr("width"));
+ $(this).attr("width", 100);
+ ;
+ })
+
+ header.find("col").each(function(){
+
+ console.info($(this).attr("width"));
+ ;
+ })
+
+
+ body.find("col").each(function(){
+
+ console.info($(this).attr("width"));
+ $(this).attr("width", 100);
+ ;
+ })
+
+ body.find("col").each(function(){
+
+ console.info($(this).attr("width"));
+ ;
+ })
+ */

Added: myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-suggest.js
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-suggest.js?rev=1770992&view=auto
==============================================================================
--- myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-suggest.js (added)
+++ myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-suggest.js Wed Nov 23 15:50:47 2016
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.Suggest = {};
+
+Tobago.Suggest.loadFromServer = function (input) {
+
+  var timeout;
+
+  return function findMatches(query, syncResults, asyncResults) {
+
+    var suggest = jQuery(Tobago.Utils.escapeClientId(input.data("tobago-suggest-for")));
+
+    if (suggest.val() != query) {
+
+      if (timeout) {
+        clearTimeout(timeout);
+      }
+
+      var delay = suggest.data("tobago-suggest-delay");
+
+      timeout = setTimeout(function() {
+        suggest.val(query);
+        suggest.data("tobago-suggest-callback", asyncResults);
+        suggest.removeData("tobago-suggest-data"); // clear jQuery-data-cache
+        var id = suggest.attr("id");
+        console.info("query: '" + query + "'"); // @DEV_ONLY
+
+        jsf.ajax.request(
+            id,
+            null, // todo: event?
+            {
+              "javax.faces.behavior.event": "suggest",
+              execute: id,
+              render: id
+            });
+      }, delay);
+
+    }
+  };
+};
+
+Tobago.Suggest.fromClient = function (data) {
+  return function findMatches(query, syncResults) {
+    var result = [];
+    for (i = 0; i < data.length; i++) {
+      if (data[i].indexOf(query) >= 0) {
+        result.push(data[i]);
+      }
+    }
+    syncResults(result);
+  };
+};
+
+Tobago.Suggest.init = function (elements) {
+
+  var suggests = Tobago.Utils.selectWithJQuery(elements, ".tobago-suggest");
+
+  suggests.each(function () {
+    var suggest = jQuery(this);
+    var input = jQuery(Tobago.Utils.escapeClientId(suggest.data("tobago-suggest-for")));
+
+    var minChars = suggest.data("tobago-suggest-min-chars");
+    var maxItems = suggest.data("tobago-suggest-max-items");
+
+    var update = typeof suggest.data("tobago-suggest-update") != "undefined";
+    var totalCount = suggest.data("tobago-suggest-total-count"); // todo
+
+    if (update && input.hasClass("tt-input")) { // already initialized: so only update data
+      var asyncResults = suggest.data("tobago-suggest-callback"); // comes from "findMatches()"
+      if (asyncResults) {
+        var data1 = suggest.data("tobago-suggest-data");
+        asyncResults(data1);
+      }
+    } else { // new
+      input.data("tobago-suggest-for", suggest.attr("id"));
+      input.attr("autocomplete", "off");
+
+      var source;
+      if (update) {
+        source = Tobago.Suggest.loadFromServer(input);
+      } else {
+        var data2 = suggest.data("tobago-suggest-data");
+        source = Tobago.Suggest.fromClient(data2);
+      }
+
+      input.typeahead({
+        minLength: minChars,
+        hint: true,// todo
+        highlight: true // todo
+      }, {
+        //name: 'test',// todo
+        limit: maxItems,
+        source: source
+      });
+    }
+  });
+};
+
+// using "EARLY", because it must be called before Tobago.Layout.init
+// this is because the suggest puts a span around the input field and doesn't copy the style.
+Tobago.registerListener(Tobago.Suggest.init, Tobago.Phase.DOCUMENT_READY, Tobago.Phase.Order.EARLY);
+Tobago.registerListener(Tobago.Suggest.init, Tobago.Phase.AFTER_UPDATE, Tobago.Phase.Order.EARLY);

Added: myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tab.js
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tab.js?rev=1770992&view=auto
==============================================================================
--- myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tab.js (added)
+++ myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tab.js Wed Nov 23 15:50:47 2016
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.TabGroup = {};
+
+/**
+ * Initializes the tab-groups.
+ * @param elements  a jQuery object to initialize (ajax) or null for initializing the whole document (full load).
+ */
+Tobago.TabGroup.init = function(elements) {
+
+  var tabGroups = Tobago.Utils.selectWithJQuery(elements, ".tobago-tabGroup");
+
+  // setting the active index
+  tabGroups.each(function () {
+    jQuery(this).find(".tobago-tabGroup-header").first().children(".tobago-tab").not(".tobago-tab-markup-disabled")
+        .click(function () {
+      // Update the hidden field for the active index.
+      var tab = jQuery(this);
+      var tabGroup = tab.parents(".tobago-tabGroup:first");
+      var hidden = tabGroup.children("input");
+      var activeIndex = tab.attr("tabgroupindex");
+      hidden.val(activeIndex);
+    })
+  });
+
+  // initialize previous button
+  tabGroups.find("[data-tobago-tabgroup-toolbar-prev]").click(function() {
+    var tabGroup = jQuery(this).parents(".tobago-tabGroup:first");
+    var selected = tabGroup.find(".tobago-tab-markup-selected");
+    // the nearest of the previous siblings, which are not disabled
+    selected.prevAll(":not(.tobago-tab-markup-disabled):first").click();
+  });
+
+  // initialize next button
+  tabGroups.find("[data-tobago-tabgroup-toolbar-next]").click(function() {
+    var tabGroup = jQuery(this).parents(".tobago-tabGroup:first");
+    var selected = tabGroup.find(".tobago-tab-markup-selected");
+    // the nearest of the next siblings, which are not disabled
+    selected.nextAll(":not(.tobago-tab-markup-disabled):first").click();
+  });
+
+  // init scroll position
+  var header = tabGroups.find(".tobago-tabGroup-header");
+  header.each(function() {
+    Tobago.TabGroup.ensureScrollPosition(jQuery(this));
+  });
+
+    // tool tips
+  tabGroups.each(function() {
+    var tabGroup = jQuery(this);
+    tabGroup.find(".tobago-tab").each(function() {
+      var tab = jQuery(this);
+      var tabContent = tabGroup.find(".tobago-tab-content[tabgroupindex=" + tab.attr("tabgroupindex") + "]");
+      tabContent.attr("title", tab.attr("title"));
+    });
+  });
+
+
+  // XXX hack for webkit to avoid scrollbars in box
+//  jQuery('.tobago-tabGroup').hide();
+//  jQuery('.tobago-tabGroup').show();
+};
+
+Tobago.TabGroup.ensureScrollPosition = function (header) {
+  var tab = header.find(".tobago-tab-markup-selected");
+  if (tab.length > 0) {
+    var tabRight = tab.position().left + tab.outerWidth() - header.outerWidth();
+    if (tabRight > 0) {
+      header.scrollLeft(header.scrollLeft() + tabRight + 1); // +1 to avoid rounding problems
+    }
+    var tabLeft = tab.position().left;
+    if (tabLeft < 0) {
+      header.scrollLeft(header.scrollLeft() + tabLeft);
+    }
+  }
+};
+
+Tobago.registerListener(Tobago.TabGroup.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.TabGroup.init, Tobago.Phase.AFTER_UPDATE);

Added: myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tree.js
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tree.js?rev=1770992&view=auto
==============================================================================
--- myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tree.js (added)
+++ myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-tree.js Wed Nov 23 15:50:47 2016
@@ -0,0 +1,311 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.Tree = {};
+
+Tobago.Tree.toggleNode = function(element, event) {
+  var src;
+  var node = element.closest(".tobago-treeNode, .tobago-treeMenuNode");
+  var data = node.closest(".tobago-treeMenu, .tobago-tree, .tobago-sheet");
+  var expanded = data.children(".tobago-treeMenu-expanded, .tobago-tree-expanded, .tobago-sheet-expanded");
+  var toggle = node.find(".tobago-treeMenuNode-toggle, .tobago-treeNode-toggle");
+  var rowIndex = Tobago.Tree.rowIndex(node);
+  if (Tobago.Tree.isExpanded(node, expanded)) {
+    Tobago.Tree.hideChildren(node);
+    toggle.each(function() {
+      src = jQuery(this).data("tobago-src-close");
+      if (src == null) { // use the open icon if there is no close icon
+        src = jQuery(this).data("tobago-src-open");
+      }
+      jQuery(this).attr("src", src);
+    });
+    expanded.val(expanded.val().replace(new RegExp("," + rowIndex + ","), ","));
+    node.filter(".tobago-treeNode").removeClass("tobago-treeNode-markup-expanded");
+    node.filter(".tobago-treeMenuNode").removeClass("tobago-treeMenuNode-markup-expanded");
+  } else {
+    var reload = Tobago.Tree.showChildren(node, expanded);
+    expanded.val(expanded.val() + rowIndex + ",");
+    if (reload) {
+      //Tobago.reloadComponent(element, data.attr("id"), toggle.parent().attr("id"), {});
+      jsf.ajax.request(
+          toggle.parent().attr("id"),
+          event,
+          {
+            //"javax.faces.behavior.event": "click",
+            execute: data.attr("id"),
+            render: data.attr("id")
+          });
+    } else {
+      toggle.each(function() {
+        src = jQuery(this).data("tobago-src-open");
+        if (src == null) { // use the close icon if there is no open icon
+          src = jQuery(this).data("tobago-src-close");
+        }
+        jQuery(this).attr("src", src);
+      });
+      node.filter(".tobago-treeNode").addClass("tobago-treeNode-markup-expanded");
+      node.filter(".tobago-treeMenuNode").addClass("tobago-treeMenuNode-markup-expanded");
+    }
+  }
+};
+
+/**
+ * Hide all children of the node recursively.
+ * @param node A jQuery-Object as a node of the tree.
+ */
+Tobago.Tree.hideChildren = function (node) {
+  var inSheet = Tobago.Tree.isInSheet(node);
+  var children = Tobago.Tree.findChildren(node);
+  children.each(function() {
+    if (inSheet) {
+      jQuery(this).parent().parent().hide();
+    } else {
+      jQuery(this).hide();
+    }
+    Tobago.Tree.hideChildren(jQuery(this));
+  });
+};
+
+/**
+ * Show the children of the node recursively, there parents are expanded.
+ * @param node A jQuery-Object as a node of the tree.
+ * @return is reload needed (to get all nodes from the server)
+ */
+Tobago.Tree.showChildren = function (node, expanded) {
+  var inSheet = Tobago.Tree.isInSheet(node);
+  var children = Tobago.Tree.findChildren(node);
+  if (children.length == 0) {
+    // no children in DOM, reload it from the server
+    return true;
+  }
+  children.each(function() {
+    var child = jQuery(this);
+    if (inSheet) {
+      child.parent().parent().show();
+    } else {
+      child.show();
+    }
+    if (Tobago.Tree.isExpanded(child, expanded)) {
+      var reload = Tobago.Tree.showChildren(child, expanded);
+      if (reload) {
+        return true;
+      }
+    }
+  });
+  return false;
+};
+
+Tobago.Tree.init = function(elements) {
+  
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeNode-markup-folder .tobago-treeNode-toggle").click(function(event) {
+    Tobago.Tree.toggleNode(jQuery(this), event);
+    return false;
+  });
+
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeMenuNode-markup-folder .tobago-treeMenuNode-toggle")
+      .parent().each(function() {
+    // if there is no command, than the whole node element should be the toggle
+    var toggle = jQuery(this).children(".tobago-treeMenuCommand").size() == 0
+        ? jQuery(this)
+        : jQuery(this).find(".tobago-treeMenuNode-toggle");
+    toggle.click(function(event) {
+      Tobago.Tree.toggleNode(jQuery(this), event);
+    });
+  });
+
+  // normal hover effect (not possible with CSS in IE 6)
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeMenuNode").hover(function() {
+    jQuery(this).toggleClass("tobago-treeMenuNode-markup-hover");
+  });
+
+  // selected for treeNode
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeCommand").focus(function() {
+    var command = jQuery(this);
+    var node = command.parent(".tobago-treeNode");
+    var tree = node.closest(".tobago-tree");
+    var selected = tree.children(".tobago-tree-selected");
+    selected.val(Tobago.Tree.rowIndex(node));
+    tree.find(".tobago-treeNode").removeClass("tobago-treeNode-markup-selected");
+    node.addClass("tobago-treeNode-markup-selected");
+  });
+
+  // selected for treeSelect
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeSelect > input").change(function () {
+    var select = jQuery(this);
+    var selected = select.prop("checked");
+    var data = select.closest(".tobago-treeMenu, .tobago-tree, .tobago-sheet");
+    var hidden = data.children(".tobago-treeMenu-selected, .tobago-tree-selected, .tobago-sheet-selected");
+    var newValue;
+    if (select.attr("type") == "radio") {
+      newValue = "," + Tobago.Tree.rowIndex(select) + ",";
+    } else if (selected) {
+      newValue = hidden.val() + Tobago.Tree.rowIndex(select) + ",";
+    } else {
+      newValue = hidden.val().replace(new RegExp("," + Tobago.Tree.rowIndex(select) + ","), ",");
+    }
+    // XXX optimize: regexp and Tobago.Tree.rowIndex
+    hidden.val(newValue);
+  });
+
+  // selected for treeMenuNode
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeMenuCommand").focus(function() {
+    var command = jQuery(this);
+    var node = command.parent(".tobago-treeMenuNode");
+    var tree = node.closest(".tobago-treeMenu");
+    var selected = tree.children(".tobago-treeMenu-selected");
+    selected.val(Tobago.Tree.rowIndex(node));
+    tree.find(".tobago-treeMenuNode").removeClass("tobago-treeMenuNode-markup-selected");
+    node.addClass("tobago-treeMenuNode-markup-selected");
+  });
+
+  // init selected field
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeMenu, .tobago-tree, .tobago-sheet").each(function() {
+    var hidden = jQuery(this).children(".tobago-treeMenu-selected, .tobago-tree-selected, .tobago-sheet-selected");
+    var string = ",";
+    jQuery(this).find(".tobago-treeMenuNode-markup-selected, .tobago-treeNode-markup-selected").each(function() {
+      string += Tobago.Tree.rowIndex(jQuery(this)) + ",";
+    });
+    hidden.val(string);
+  });
+
+  // init expanded field
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeMenu, .tobago-tree, .tobago-sheet").each(function() {
+    var hidden = jQuery(this).children(".tobago-treeMenu-expanded, .tobago-tree-expanded, .tobago-sheet-expanded");
+    var string = ",";
+    jQuery(this).find(".tobago-treeMenuNode-markup-expanded, .tobago-treeNode-markup-expanded").each(function() {
+      string += Tobago.Tree.rowIndex(jQuery(this)) + ",";
+    });
+    hidden.val(string);
+  });
+
+  // init tree selection for multiCascade
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-tree[data-tobago-selectable=multiCascade]").each(function() {
+    var tree = jQuery(this);
+    tree.find("input[type=checkbox]").each(function() {
+      jQuery(this).change(function(event) {
+        var node = jQuery(event.target).parents(".tobago-treeNode");
+        var checked = node.find("input[type=checkbox]").prop("checked");
+        var children = Tobago.Tree.findChildren(node);
+        children.each(function() {
+          var childsCheckbox = jQuery(this).find("input[type=checkbox]");
+          childsCheckbox.prop("checked", checked);
+          childsCheckbox.change();
+        });
+      });
+    });
+  });
+
+};
+
+Tobago.Tree.isExpanded = function(node, expanded) {
+  var rowIndex = Tobago.Tree.rowIndex(node);
+  return expanded.val().indexOf("," + rowIndex + ",") > -1;
+};
+
+Tobago.Tree.rowIndex = function (node) {
+  return node.attr("id").replace(/.+\:(\d+)(\:\w+)+/, '$1');
+};
+
+Tobago.Tree.findChildren = function (node) {
+  var treeParentSelector = "[data-tobago-tree-parent='" + node.attr("id") + "']";
+  var children;
+  if (Tobago.Tree.isInSheet(node)) {
+    children = node.parent("td").parent("tr").nextAll().children().children(treeParentSelector);
+  } else { // normal tree
+    children = node.nextAll(treeParentSelector);
+  }
+  return children;
+};
+
+Tobago.Tree.isInSheet = function(node) {
+  return node.parent("td").size() == 1;
+};
+
+Tobago.registerListener(Tobago.Tree.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.Tree.init, Tobago.Phase.AFTER_UPDATE);
+
+
+Tobago.TreeListbox = {};
+
+Tobago.TreeListbox.init = function(elements) {
+
+  var treeListbox = Tobago.Utils.selectWithJQuery(elements, ".tobago-treeListbox");
+  // hide select tags for level > root
+  treeListbox.children().find("select:not(:first)").hide();
+
+  var listboxSelects = treeListbox.find("select");
+
+  listboxSelects.children("option").each(Tobago.TreeListbox.initNextLevel);
+  listboxSelects.each(Tobago.TreeListbox.initListeners);
+};
+
+// find all option tags and add the dedicated select tag in its data section.
+Tobago.TreeListbox.initNextLevel = function() {
+  var option = jQuery(this);
+  var select = option.closest(".tobago-treeListbox-level").next()
+      .find("[data-tobago-tree-parent='" + option.attr("id") + "']");
+  if (select.length == 1) {
+    option.data("tobago-select", select);
+  } else {
+    var empty = option.closest(".tobago-treeListbox-level").next().children(":first");
+    option.data("tobago-select", empty);
+  }
+};
+
+// add on change on all select tag, all options that are not selected hide there dedicated
+// select tag, and the selected option show its dedicated select tag.
+Tobago.TreeListbox.initListeners = function() {
+
+  jQuery(this).change(Tobago.TreeListbox.onChange);
+
+  jQuery(this).focus(function() {
+    jQuery(this).change();
+  });
+};
+
+Tobago.TreeListbox.onChange = function() {
+  var listbox = jQuery(this);
+  listbox.children("option:not(:selected)").each(function() {
+    jQuery(this).data("tobago-select").hide();
+  });
+  listbox.children("option:selected").each(function() {
+    jQuery(this).data("tobago-select").show();
+  });
+  Tobago.TreeListbox.setSelected(listbox);
+
+  // Deeper level (2nd and later) should only show the empty select tag.
+  // The first child is the empty selection.
+  listbox.parent().nextAll(":not(:first)").each(function() {
+    jQuery(this).children(":not(:first)").hide();
+    jQuery(this).children(":first").show();
+  });
+
+};
+
+Tobago.TreeListbox.setSelected = function(listbox) {
+  var hidden = listbox.closest(".tobago-treeListbox").children("[data-tobago-selection-mode]");
+  if (hidden.length == 1){
+    var selectedValue = ";";
+    listbox.children("option:selected").each(function() {
+      selectedValue += jQuery(this).attr("id") + ";";
+    });
+    hidden.val(selectedValue);
+  }
+};
+
+Tobago.registerListener(Tobago.TreeListbox.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.TreeListbox.init, Tobago.Phase.AFTER_UPDATE);

Added: myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-utils.js
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-utils.js?rev=1770992&view=auto
==============================================================================
--- myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-utils.js (added)
+++ myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/org/apache/myfaces/tobago/renderkit/html/standard/standard/script/tobago-utils.js Wed Nov 23 15:50:47 2016
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.Utils = {};
+
+/**
+ *
+ * @param id A JSF client id, type=string. Example: escapeClientId("page:input") -> "#page\\:input"
+ * @return A string which can be used as a jQuery selector.
+ */
+Tobago.Utils.escapeClientId = function(id) {
+  return '#' + id.replace(/([:\.])/g, '\\$1');
+};
+
+/**
+ * @deprecated since Tobago 2.0.5 because of misspelling
+ */
+Tobago.Utils.selectWidthJQuery = function(elements, selector) {
+  return Tobago.Utils.selectWithJQuery(elements, selector);
+};
+
+/**
+ * Helps to select either elements from the whole DOM or only find in sub trees
+ * (in the case of AJAX partial rendering)
+ * @param elements a jQuery object to initialize (ajax) or null for initializing the whole document (full load).
+ * @param selector a jQuery selector.
+ */
+Tobago.Utils.selectWithJQuery = function(elements, selector) {
+  return elements == null
+      ? jQuery(selector)
+      : elements.find(selector).add(elements.filter(selector));
+};
+
+Tobago.Utils.findSubComponent = function(element, subId) {
+  return jQuery(Tobago.Utils.getSubComponentId(element.attr('id'), subId));
+};
+
+Tobago.Utils.getSubComponentId = function(id, subId) {
+  if (id != null) {
+    return "#" + id.replace(/:/g, "\\:") + "\\:\\:" + subId;
+  } else {
+    return null;
+  }
+};
+
+/** @deprecated */
+Tobago.Utils.findSuperComponent = function(element) {
+  return jQuery(Tobago.Utils.getSuperComponentId(element.attr('id')));
+};
+
+Tobago.Utils.getSuperComponentId = function(id) {
+  return "#" + id.substring(0, id.lastIndexOf("::")).replace(/:/g, "\\:");
+};
+
+/**
+ * "a:b" -> "a"
+ * "a:b:c" -> "a:b"
+ * "a" -> null
+ * null -> null
+ * "a:b::sub-component" -> "a"
+ * "a::sub-component:b" -> "a::sub-component" // should currently not happen in Tobago
+ *
+ * @param id The clientId of a component.
+ * @return The clientId of the naming container.
+ */
+Tobago.Utils.getNamingContainerId = function (id) {
+  if (id == null) {
+    return null;
+  }
+  if (id.lastIndexOf(":") == -1) {
+    return null;
+  }
+  while (true) {
+    var sub = id.lastIndexOf("::");
+    if (sub == -1) {
+      break;
+    }
+    if (sub + 1 == id.lastIndexOf(":")) {
+      id = id.substring(0, sub);
+    } else {
+      break;
+    }
+  }
+  return id.substring(0, id.lastIndexOf(":"));
+};
+
+/**
+ * fix position, when the element it is outside of the current page
+ * @param elements is an jQuery Array of elements to be fixed.
+ */
+Tobago.Utils.keepElementInVisibleArea = function(elements) {
+  elements.each(function() {
+    var element = jQuery(this);
+    var page = jQuery(".tobago-page-content:first");
+    var left = element.offset().left;
+    var top = element.offset().top;
+    // fix menu position, when it is outside of the current page
+    left = Math.max(0, Math.min(left, page.outerWidth() - element.outerWidth()));
+    top = Math.max(0, Math.min(top, page.outerHeight() - element.outerHeight()));
+    element.css('left', left);
+    element.css('top', top);
+  });
+};
+
+/** @deprecated */
+Tobago.Utils.acceleratorKeyEvent = function() {
+  return Tobago.browser.isWebkit || Tobago.browser.isGecko ? 'keydown' : 'keypress';
+};
+