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 2022/10/20 20:39:14 UTC

[myfaces-tobago] branch main updated: demo: Internal search for the demo (#3355)

This is an automated email from the ASF dual-hosted git repository.

lofwyr pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git


The following commit(s) were added to refs/heads/main by this push:
     new f81d51120e demo: Internal search for the demo (#3355)
f81d51120e is described below

commit f81d51120eb75c245ca3168480c9259a0e6626eb
Author: Udo Schnurpfeil <gi...@schnurpfeil.de>
AuthorDate: Thu Oct 20 22:39:09 2022 +0200

    demo: Internal search for the demo (#3355)
    
    Base impl
    
    issue: TOBAGO-2160
---
 .../renderkit/renderer/CommandRendererBase.java    |  2 +-
 .../tobago/example/demo/NavigationNode.java        | 18 ++++++-
 .../tobago/example/demo/NavigationState.java       | 21 ++++++++
 .../tobago/example/demo/NavigationTree.java        | 21 +++++++-
 .../myfaces/tobago/example/demo/Outcome.java       |  2 +
 .../myfaces/tobago/example/demo/SearchIndex.java   | 36 +++++++++++++
 .../tobago-example-demo/src/main/ts/demo-all.ts    |  1 -
 .../tobago-example-demo/src/main/ts/demo-search.ts | 59 ----------------------
 .../content/000-intro/05-search/Search.xhtml       | 42 +++++++++++++++
 .../000-intro/93-server-info/Server_Info.xhtml}    |  0
 .../000-intro/96-logging-info/Logging_Info.xhtml}  |  0
 .../src/main/webapp/content/000-intro/Intro.xhtml  | 24 ++-------
 .../src/main/webapp/js/demo-all.js                 |  1 -
 .../src/main/webapp/js/demo-all.js.map             |  2 +-
 .../src/main/webapp/js/demo-search.js              | 51 -------------------
 .../src/main/webapp/js/demo-search.js.map          |  1 -
 .../tobago-example-demo/src/main/webapp/js/demo.js | 51 -------------------
 .../src/main/webapp/js/demo.js.map                 |  2 +-
 .../tobago-example-demo/src/main/webapp/menu.xhtml | 20 ++++----
 19 files changed, 156 insertions(+), 198 deletions(-)

diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java
index fce07e7912..3b1dbb9e48 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java
@@ -130,7 +130,7 @@ public abstract class CommandRendererBase<T extends AbstractUICommand> extends D
       if (form != null) {
         writer.writeAttribute(DataAttributes.DEFAULT, form.getClientId(facesContext), false);
       } else {
-        LOG.warn("No from found for {}", clientId);
+        LOG.warn("No form found for {}", clientId);
       }
     }
 
diff --git a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationNode.java b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationNode.java
index 329f0ac13f..f2709f7e29 100644
--- a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationNode.java
+++ b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationNode.java
@@ -21,19 +21,23 @@ package org.apache.myfaces.tobago.example.demo;
 
 import org.apache.myfaces.tobago.internal.util.StringUtils;
 import org.apache.myfaces.tobago.model.TreePath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.swing.tree.DefaultMutableTreeNode;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 public class NavigationNode extends DefaultMutableTreeNode implements Comparable<NavigationNode> {
+  private static final Logger LOG = LoggerFactory.getLogger(NavigationNode.class);
 
   private final String name;
   private final String label;
+  private String labelPath;
   private final String branch;
   private final String outcome;
 
-  private NavigationTree tree;
+  private final NavigationTree tree;
 
   /** Cache the TreePath for optimization. */
   private TreePath treePath;
@@ -64,6 +68,14 @@ public class NavigationNode extends DefaultMutableTreeNode implements Comparable
 
   public void evaluateTreePath() {
     treePath = new TreePath(this);
+
+    final StringBuilder builder = new StringBuilder(this.getLabel());
+    NavigationNode parent = (NavigationNode) this.getParent();
+    while (parent != null && parent != tree.getTree()) {
+      builder.insert(0, parent.getLabel() + " → ");
+      parent = (NavigationNode) parent.getParent();
+    }
+    labelPath = builder.toString();
   }
 
   @Override
@@ -88,6 +100,10 @@ public class NavigationNode extends DefaultMutableTreeNode implements Comparable
     return label;
   }
 
+  public String getLabelPath() {
+    return labelPath;
+  }
+
   public String getOutcome() {
     return outcome;
   }
diff --git a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationState.java b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationState.java
index 0f6b6d1e93..dfa2eccd8a 100644
--- a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationState.java
+++ b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationState.java
@@ -34,6 +34,7 @@ import jakarta.inject.Inject;
 import jakarta.inject.Named;
 import java.io.Serializable;
 import java.lang.invoke.MethodHandles;
+import java.util.List;
 
 @SessionScoped
 @Named
@@ -50,6 +51,13 @@ public class NavigationState implements Serializable {
 
   private boolean viewSource = false;
 
+  private String searchString;
+  private List<NavigationNode> searchResult;
+
+  public List<NavigationNode> getSearchResult() {
+    return searchResult;
+  }
+
   @PostConstruct
   public void init() {
     currentNode = tree.findByViewId(FacesContext.getCurrentInstance().getViewRoot().getViewId());
@@ -116,6 +124,11 @@ public class NavigationState implements Serializable {
     }
   }
 
+  public String search() {
+    searchResult = tree.search(this.searchString);
+    return Outcome.SEARCH.toString();
+  }
+
   public boolean isFirst() {
     if (currentNode == null) {
       return false;
@@ -148,4 +161,12 @@ public class NavigationState implements Serializable {
   public void setViewSource(final boolean viewSource) {
     this.viewSource = viewSource;
   }
+
+  public String getSearchString() {
+    return searchString;
+  }
+
+  public void setSearchString(String searchString) {
+    this.searchString = searchString;
+  }
 }
diff --git a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationTree.java b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationTree.java
index 7eb7c205df..6614310678 100644
--- a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationTree.java
+++ b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationTree.java
@@ -62,6 +62,8 @@ public class NavigationTree implements Serializable {
   @Inject
   private ServletContext servletContext;
 
+  private final SearchIndex searchIndex = new SearchIndex();
+
   public NavigationTree() {
     LOG.info("<init> " + this);
   }
@@ -82,8 +84,8 @@ public class NavigationTree implements Serializable {
     // after sorting the first node is the root node.
     root = nodes.get(0);
 
+    // (why?)
     final Map<String, NavigationNode> map = new HashMap<>();
-
     for (final NavigationNode node : nodes) {
 //      LOG.debug("Creating node='{}' branch='{}'", node.getName(), node.getBranch());
       map.put(node.getBranch(), node);
@@ -93,6 +95,23 @@ public class NavigationTree implements Serializable {
       }
       node.evaluateTreePath();
     }
+
+    for (final NavigationNode node : nodes) {
+      searchIndex.add(node);
+    }
+  }
+
+  public List<NavigationNode> search(final String searchString) {
+    List<NavigationNode> result = new ArrayList<>(20);
+    for (String s : searchIndex.keySet()) {
+      if (s.contains(searchString.toLowerCase())) {
+        result.add(searchIndex.get(s));
+      }
+      if (result.size() >= 20) {
+        break;
+      }
+    }
+    return result;
   }
 
   private void addToResult(List<String> listWar, List<NavigationNode> nodes) {
diff --git a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Outcome.java b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Outcome.java
index f33cb652f6..54779aa52c 100644
--- a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Outcome.java
+++ b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Outcome.java
@@ -24,6 +24,8 @@ package org.apache.myfaces.tobago.example.demo;
  */
 public enum Outcome {
 
+  SEARCH(
+      "/content/000-intro/05-search/Search.xhtml?faces-redirect=true"),
   COMMAND(
       "/content/040-command/Command.xhtml?faces-redirect=true"),
   CONCEPT_LOCALE(
diff --git a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SearchIndex.java b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SearchIndex.java
new file mode 100644
index 0000000000..ce4dc25550
--- /dev/null
+++ b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SearchIndex.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import java.util.HashMap;
+
+public class SearchIndex extends HashMap<String, NavigationNode> {
+
+  public void add(NavigationNode node) {
+    String key = node.getLabel().toLowerCase();
+
+    // XXX little hack to have more than one result with same name
+    while (containsKey(key)) {
+      key = key + ".";
+    }
+
+    this.put(key, node);
+  }
+}
diff --git a/tobago-example/tobago-example-demo/src/main/ts/demo-all.ts b/tobago-example/tobago-example-demo/src/main/ts/demo-all.ts
index 13b138a25a..928c85e947 100644
--- a/tobago-example/tobago-example-demo/src/main/ts/demo-all.ts
+++ b/tobago-example/tobago-example-demo/src/main/ts/demo-all.ts
@@ -21,5 +21,4 @@ import "./demo-date";
 import "./demo-highlight";
 import "./demo-inspect";
 import "./demo-login";
-import "./demo-search";
 import "./demo-test";
diff --git a/tobago-example/tobago-example-demo/src/main/ts/demo-search.ts b/tobago-example/tobago-example-demo/src/main/ts/demo-search.ts
deleted file mode 100644
index 95555e59f4..0000000000
--- a/tobago-example/tobago-example-demo/src/main/ts/demo-search.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.
- */
-
-class DemoSearch extends HTMLElement {
-
-  static readonly GOOGLE = "https://www.google.com/search?q=site%3Atobago-vm.apache.org+demo-4-release+";
-
-  constructor() {
-    super();
-  }
-
-  connectedCallback(): void {
-    const input = this.input;
-    const a = this.a;
-    if (input && a) {
-      a.href = DemoSearch.GOOGLE;
-      input.addEventListener("change", this.change.bind(this));
-      input.addEventListener("keypress", this.keypress.bind(this));
-    }
-  }
-
-  change(event: Event): void {
-    this.a.href = DemoSearch.GOOGLE + encodeURI(this.input.value);
-  }
-
-  keypress(event): void {
-    if (event.which === 13) {
-      this.change(event);
-    }
-  }
-
-  get input(): HTMLInputElement {
-    return this.querySelector("input");
-  }
-
-  get a(): HTMLAnchorElement {
-    return this.querySelector("a");
-  }
-}
-
-document.addEventListener("DOMContentLoaded", function (event: Event): void {
-  if (window.customElements.get("demo-search") == null) {
-    window.customElements.define("demo-search", DemoSearch);
-  }
-});
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/000-intro/05-search/Search.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/000-intro/05-search/Search.xhtml
new file mode 100644
index 0000000000..951510b528
--- /dev/null
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/000-intro/05-search/Search.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * 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.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
+                xmlns:f="http://xmlns.jcp.org/jsf/core">
+
+  <tc:section label="Searching the Demo">
+
+    <tc:in label="Search" value="#{navigationState.searchString}">
+      <f:facet name="after">
+        <tc:button label="go" action="#{navigationState.search}" defaultCommand="true"/>
+      </f:facet>
+    </tc:in>
+
+    <ul>
+      <ui:repeat value="#{navigationState.searchResult}" var="node">
+        <tc:link label="#{node.labelPath}" link="#{node.outcome}"/><br/>
+      </ui:repeat>
+    </ul>
+
+  </tc:section>
+
+</ui:composition>
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/server-info.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/000-intro/93-server-info/Server_Info.xhtml
similarity index 100%
rename from tobago-example/tobago-example-demo/src/main/webapp/server-info.xhtml
rename to tobago-example/tobago-example-demo/src/main/webapp/content/000-intro/93-server-info/Server_Info.xhtml
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/logging-info.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/000-intro/96-logging-info/Logging_Info.xhtml
similarity index 100%
rename from tobago-example/tobago-example-demo/src/main/webapp/logging-info.xhtml
rename to tobago-example/tobago-example-demo/src/main/webapp/content/000-intro/96-logging-info/Logging_Info.xhtml
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/000-intro/Intro.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/000-intro/Intro.xhtml
index fea8b56756..c1894e85d5 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/000-intro/Intro.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/000-intro/Intro.xhtml
@@ -50,23 +50,9 @@
     </tc:section>
   </tc:section>
 
-  <tc:section label="Local Demo">
-    <p>In case that this demo already runs on your local machine,
-      you can follow the link to the
-      <tc:link label="public demo" link="http://tobago-vm.apache.org/"/>.</p>
-    <p>If this is the public demo and you want to build it on your own, read the following instructions.</p>
-    <tc:section label="Instructions">
-      <p>First of all you need
-        <tc:link label="Maven" link="https://maven.apache.org/"/> (at least version 3.0.4) and
-        <tc:link label="Java SE 8" link="http://www.oracle.com/technetwork/java/javase/downloads/"/> or higher.</p>
-      <p>After that, check out the source code from subversion repository.
-        <br/>
-        <code>git clone https://github.com/apache/myfaces-tobago</code>
-        <br/>
-        Alternatively you can get the source code from the
-        <tc:link label="download section" link="https://myfaces.apache.org/tobago/download.html"/>.</p>
-      <p>Go to the tobago3 directory, and build Tobago with <code>mvn install</code>.</p>
-      <p>Go to 'tobago3/tobago-example/tobago-example-demo' and start the demo with <code>mvn jetty:run</code>.</p>
-    </tc:section>
-  </tc:section>
+  <tc:in placeholder="Search" required="true" value="#{navigationState.searchString}" labelLayout="none"
+         label="Search" id="search">
+  </tc:in>
+  <tc:button id="go" label="go" action="#{navigationState.search}" defaultCommand="true"/>
+
 </ui:composition>
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/js/demo-all.js b/tobago-example/tobago-example-demo/src/main/webapp/js/demo-all.js
index e24d327e17..f92f46828f 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/js/demo-all.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/js/demo-all.js
@@ -20,6 +20,5 @@ import "./demo-date";
 import "./demo-highlight";
 import "./demo-inspect";
 import "./demo-login";
-import "./demo-search";
 import "./demo-test";
 //# sourceMappingURL=demo-all.js.map
\ No newline at end of file
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/js/demo-all.js.map b/tobago-example/tobago-example-demo/src/main/webapp/js/demo-all.js.map
index 47afcb8399..eca2448c4a 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/js/demo-all.js.map
+++ b/tobago-example/tobago-example-demo/src/main/webapp/js/demo-all.js.map
@@ -1 +1 @@
-{"version":3,"file":"demo-all.js","sourceRoot":"","sources":["../../ts/demo-all.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,cAAc,CAAC;AACtB,OAAO,0BAA0B,CAAC;AAClC,OAAO,aAAa,CAAC;AACrB,OAAO,kBAAkB,CAAC;AAC1B,OAAO,gBAAgB,CAAC;AACxB,OAAO,cAAc,CAAC;AACtB,OAAO,eAAe,CAAC;AACvB,OAAO,aAAa,CAAC"}
\ No newline at end of file
+{"version":3,"file":"demo-all.js","sourceRoot":"","sources":["../../ts/demo-all.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,cAAc,CAAC;AACtB,OAAO,0BAA0B,CAAC;AAClC,OAAO,aAAa,CAAC;AACrB,OAAO,kBAAkB,CAAC;AAC1B,OAAO,gBAAgB,CAAC;AACxB,OAAO,cAAc,CAAC;AACtB,OAAO,aAAa,CAAC"}
\ No newline at end of file
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/js/demo-search.js b/tobago-example/tobago-example-demo/src/main/webapp/js/demo-search.js
deleted file mode 100644
index 9992100e5b..0000000000
--- a/tobago-example/tobago-example-demo/src/main/webapp/js/demo-search.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.
- */
-class DemoSearch extends HTMLElement {
-    constructor() {
-        super();
-    }
-    connectedCallback() {
-        const input = this.input;
-        const a = this.a;
-        if (input && a) {
-            a.href = DemoSearch.GOOGLE;
-            input.addEventListener("change", this.change.bind(this));
-            input.addEventListener("keypress", this.keypress.bind(this));
-        }
-    }
-    change(event) {
-        this.a.href = DemoSearch.GOOGLE + encodeURI(this.input.value);
-    }
-    keypress(event) {
-        if (event.which === 13) {
-            this.change(event);
-        }
-    }
-    get input() {
-        return this.querySelector("input");
-    }
-    get a() {
-        return this.querySelector("a");
-    }
-}
-DemoSearch.GOOGLE = "https://www.google.com/search?q=site%3Atobago-vm.apache.org+demo-4-release+";
-document.addEventListener("DOMContentLoaded", function (event) {
-    if (window.customElements.get("demo-search") == null) {
-        window.customElements.define("demo-search", DemoSearch);
-    }
-});
-//# sourceMappingURL=demo-search.js.map
\ No newline at end of file
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/js/demo-search.js.map b/tobago-example/tobago-example-demo/src/main/webapp/js/demo-search.js.map
deleted file mode 100644
index 5f3aa6aae1..0000000000
--- a/tobago-example/tobago-example-demo/src/main/webapp/js/demo-search.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"file":"demo-search.js","sourceRoot":"","sources":["../../ts/demo-search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,UAAW,SAAQ,WAAW;IAIlC;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,iBAAiB;QACf,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QACjB,IAAI,KAAK,IAAI,CAAC,EAAE;YACd,CAAC,CAAC,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC;YAC3B,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACzD,KAAK,CAAC,gBAAgB,CAAC,UAAU,EAA [...]
\ No newline at end of file
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/js/demo.js b/tobago-example/tobago-example-demo/src/main/webapp/js/demo.js
index 26093611a4..2ba78926f2 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/js/demo.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/js/demo.js
@@ -2257,57 +2257,6 @@
         }
     });
 
-    /*
-     * 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.
-     */
-    class DemoSearch extends HTMLElement {
-        constructor() {
-            super();
-        }
-        connectedCallback() {
-            const input = this.input;
-            const a = this.a;
-            if (input && a) {
-                a.href = DemoSearch.GOOGLE;
-                input.addEventListener("change", this.change.bind(this));
-                input.addEventListener("keypress", this.keypress.bind(this));
-            }
-        }
-        change(event) {
-            this.a.href = DemoSearch.GOOGLE + encodeURI(this.input.value);
-        }
-        keypress(event) {
-            if (event.which === 13) {
-                this.change(event);
-            }
-        }
-        get input() {
-            return this.querySelector("input");
-        }
-        get a() {
-            return this.querySelector("a");
-        }
-    }
-    DemoSearch.GOOGLE = "https://www.google.com/search?q=site%3Atobago-vm.apache.org+demo-4-release+";
-    document.addEventListener("DOMContentLoaded", function (event) {
-        if (window.customElements.get("demo-search") == null) {
-            window.customElements.define("demo-search", DemoSearch);
-        }
-    });
-
     /*
      * Licensed to the Apache Software Foundation (ASF) under one or more
      * contributor license agreements.  See the NOTICE file distributed with
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/js/demo.js.map b/tobago-example/tobago-example-demo/src/main/webapp/js/demo.js.map
index 9dcaa943ea..128e427ffd 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/js/demo.js.map
+++ b/tobago-example/tobago-example-demo/src/main/webapp/js/demo.js.map
@@ -1 +1 @@
-{"version":3,"file":"demo.js","sources":["demo-alert.js","demo-copy-to-clipboard.js","demo-date.js","../../../../node_modules/prismjs/prism.js","demo-highlight.js","demo-inspect.js","demo-login.js","demo-search.js","demo-test.js"],"sourcesContent":["/*\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements.  See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses t [...]
\ No newline at end of file
+{"version":3,"file":"demo.js","sources":["demo-alert.js","demo-copy-to-clipboard.js","demo-date.js","../../../../node_modules/prismjs/prism.js","demo-highlight.js","demo-inspect.js","demo-login.js","demo-test.js"],"sourcesContent":["/*\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements.  See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You u [...]
\ No newline at end of file
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/menu.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/menu.xhtml
index 6f5f3ac114..dcd812a2b3 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/menu.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/menu.xhtml
@@ -106,8 +106,9 @@
             <tc:link omit="true" label="Client Info" id="headerInfo">
               <tc:operation name="show" for=":::info"/>
             </tc:link>
-            <tc:link outcome="/server-info.xhtml" immediate="true" label="Server Info" disabled="#{! serverInfo.enabled}"/>
-            <tc:link outcome="/logging-info.xhtml" immediate="true" label="Logging Info"
+            <tc:link outcome="/content/000-intro/93-server-info/Server_Info.xhtml" immediate="true" label="Server Info"
+                     disabled="#{! serverInfo.enabled}"/>
+            <tc:link outcome="/content/000-intro/96-logging-info/Logging_Info.xhtml" immediate="true" label="Logging Info"
                      disabled="#{! serverInfo.enabled}"/>
             <tc:separator/>
             <tc:link link="http://myfaces.apache.org/tobago" label="Tobago Home"/>
@@ -119,15 +120,14 @@
 
       <f:facet name="after">
         <tc:flexLayout columns="auto auto">
-          <tc:form id="search">
+          <tc:form id="searchForm">
             <tc:flexLayout columns="200px auto">
-              <demo-search>
-                <tc:in id="searchField" placeholder="Search by Google" labelLayout="skip">
-                    <f:facet name="after">
-                      <tc:button id="searchCommand" defaultCommand="true" label="go" link="test"/>
-                    </f:facet>
-                </tc:in>
-              </demo-search>
+              <tc:in placeholder="Search" required="true" value="#{navigationState.searchString}" labelLayout="none"
+              label="Search" id="search">
+                <f:facet name="after">
+                  <tc:button label="go" action="#{navigationState.search}" defaultCommand="true"/>
+                </f:facet>
+              </tc:in>
             </tc:flexLayout>
           </tc:form>
           <tc:form id="navbtns">