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 2019/05/10 15:00:22 UTC

[myfaces-tobago] branch master updated (bec2bf8 -> fb24c38)

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

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


    from bec2bf8  TOBAGO-1988 Sheet Tree is no longer rendered
     new 7dc1354  TOBAGO-1633: Use TypeScript instead of JavaScript
     new bec284e  TOBAGO-1633: Use TypeScript instead of JavaScript
     new 666b633  TOBAGO-1633: Use TypeScript instead of JavaScript
     new fb24c38  TOBAGO-1633: Use TypeScript instead of JavaScript

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../src/main/npm/ts/tobago-header-footer.ts        |  38 +++---
 .../src/main/npm/ts/tobago-in.ts                   |  43 +++++++
 .../src/main/npm/ts/tobago-jsf.ts                  | 141 +++++++++++----------
 .../src/main/npm/ts/tobago-reload.ts               | 104 +++++++--------
 .../src/main/npm/ts/tobago-sheet.ts                |  18 ++-
 .../src/main/npm/ts/tobago-utils.ts                |  32 +++++
 6 files changed, 225 insertions(+), 151 deletions(-)


[myfaces-tobago] 04/04: TOBAGO-1633: Use TypeScript instead of JavaScript

Posted by lo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit fb24c38a7d41c226c0b682e6e0c282a8edb4270e
Author: Udo Schnurpfeil <lo...@apache.org>
AuthorDate: Fri May 10 16:59:45 2019 +0200

    TOBAGO-1633: Use TypeScript instead of JavaScript
    
    * example: blue print for good component
---
 .../src/main/npm/ts/tobago-in.ts                   | 43 ++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-in.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-in.ts
index 4b326ae..6f61d12 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-in.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-in.ts
@@ -15,3 +15,46 @@
  * limitations under the License.
  */
 
+// XXX remove me
+function es6test() {
+  [1, 2, 3, 4].map((n) => n + 1);
+}
+
+// XXX regexp example only - blueprint
+namespace Tobago {
+
+  class RegExpTest {
+
+    private readonly element: HTMLInputElement;
+    private readonly regexp: RegExp;
+
+    constructor(element: HTMLInputElement) {
+
+      this.element = element;
+      this.regexp = new RegExp(this.element.dataset["regexp"]);
+
+      console.info("constructor: " + element.id);
+
+      this.element.addEventListener("change", this.checkValue.bind(this));
+    };
+
+    checkValue(event: TextEvent) {
+      console.info("changed: check if " + this.regexp + " is okay!");
+      if (!this.regexp.test(this.element.value)) {
+        this.element.classList.add("border-danger");
+      } else {
+        this.element.classList.remove("border-danger");
+      }
+    };
+
+    static init = function (element: HTMLElement): void {
+      for (const input of element.tobagoSelfOrElementsByClassName("tobago-in")) { // todo only for data-regexp
+        new RegExpTest(<HTMLInputElement>input);
+      }
+    };
+  }
+
+  Listener.register(RegExpTest.init, Phase.DOCUMENT_READY);
+  Listener.register(RegExpTest.init, Phase.AFTER_UPDATE);
+
+}
\ No newline at end of file


[myfaces-tobago] 02/04: TOBAGO-1633: Use TypeScript instead of JavaScript

Posted by lo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit bec284e5395327c035d88979af2b810f9284467c
Author: Udo Schnurpfeil <lo...@apache.org>
AuthorDate: Thu May 9 13:28:49 2019 +0200

    TOBAGO-1633: Use TypeScript instead of JavaScript
    
    * jsf adapter
---
 .../src/main/npm/ts/tobago-jsf.ts                  | 141 +++++++++++----------
 1 file changed, 71 insertions(+), 70 deletions(-)

diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-jsf.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-jsf.ts
index 07d9dbf..e084b28 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-jsf.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-jsf.ts
@@ -15,81 +15,82 @@
  * limitations under the License.
  */
 
-Tobago4.Jsf = {
-  VIEW_STATE: "javax.faces.ViewState",
-  CLIENT_WINDOW: "javax.faces.ClientWindow",
-  VIEW_ROOT: "javax.faces.ViewRoot",
-  VIEW_HEAD: "javax.faces.ViewHead",
-  VIEW_BODY: "javax.faces.ViewBody",
-  RESOURCE: "javax.faces.Resource",
+namespace Tobago {
 
-  isId: function (id) {
-    switch (id) {
-      case Tobago4.Jsf.VIEW_STATE:
-      case Tobago4.Jsf.CLIENT_WINDOW:
-      case Tobago4.Jsf.VIEW_ROOT:
-      case Tobago4.Jsf.VIEW_HEAD:
-      case Tobago4.Jsf.VIEW_BODY:
-      case Tobago4.Jsf.RESOURCE:
-        return false;
-      default:
-        return true;
-    }
-  },
+  class Jsf {
 
-  isBody: function (id) {
-    switch (id) {
-      case Tobago4.Jsf.VIEW_ROOT:
-      case Tobago4.Jsf.VIEW_BODY:
-        return true;
-      default:
-        return false;
-    }
-  }
-};
+    static readonly VIEW_STATE: "javax.faces.ViewState";
+    static readonly CLIENT_WINDOW: "javax.faces.ClientWindow";
+    static readonly VIEW_ROOT: "javax.faces.ViewRoot";
+    static readonly VIEW_HEAD: "javax.faces.ViewHead";
+    static readonly VIEW_BODY: "javax.faces.ViewBody";
+    static readonly RESOURCE: "javax.faces.Resource";
 
-Tobago4.Jsf.init = function() {
-  jsf.ajax.addOnEvent(function (event) {
-    console.timeEnd("[tobago] jsf-ajax");
-    console.time("[tobago] jsf-ajax");
-    console.log("JSF event status: " + event.status);
-    if (event.status === "success") {
+    private static isId = function (id: string) {
+      switch (id) {
+        case Jsf.VIEW_STATE:
+        case Jsf.CLIENT_WINDOW:
+        case Jsf.VIEW_ROOT:
+        case Jsf.VIEW_HEAD:
+        case Jsf.VIEW_BODY:
+        case Jsf.RESOURCE:
+          return false;
+        default:
+          return true;
+      }
+    };
 
-      jQuery(event.responseXML).find("update").each(function () {
+    private static isBody = function (id) {
+      switch (id) {
+        case Jsf.VIEW_ROOT:
+        case Jsf.VIEW_BODY:
+          return true;
+        default:
+          return false;
+      }
+    };
 
-        const update = this;
-        const result: string[] = /<!\[CDATA\[(.*)]]>/s.exec(update.innerHTML);
-        const id = update.id;
-        if (result.length === 2 && result[1].startsWith("{\"reload\"")) {
-          // not modified on server, needs be reloaded after some time
-          console.debug("Found reload-JSON in response!");
-          Tobago.ReloadManager.instance.schedule(id, JSON.parse(result[1]).reload.frequency);
-        } else {
-          console.info("Update after jsf.ajax success: id='" + id + "'");
-          if (Tobago4.Jsf.isId(id)) {
-            console.debug("updating id: " + id);
-            Tobago.Listener.executeAfterUpdate(document.getElementById(id));
-          } else if (Tobago4.Jsf.isBody(id)) {
-            console.debug("updating body");
-            // there should be only one element with this class
-            Tobago.Listener.executeAfterUpdate(document.querySelector<HTMLElement>(".tobago-page"));
-          }
-        }
-      });
-    } else if (event.status === "complete") {
-      jQuery(event.responseXML).find("update").each(function () {
-        const update = this;
-        const id = update.id;
-        if ("javax.faces.ViewState" !== id) {
-          const oldElement = jQuery(Tobago4.Utils.escapeClientId(id));
-          console.info("Update after jsf.ajax complete: id='" + oldElement.attr("id") + "'");
-          if (oldElement.data("tobago-partial-overlay-set")) {
-            oldElement.overlay("destroy");
-          }
+    static init = function () {
+      jsf.ajax.addOnEvent(function (event) {
+        console.timeEnd("[tobago-jsf] jsf-ajax");
+        console.time("[tobago-jsf] jsf-ajax");
+        console.log("[tobago-jsf] JSF event status: " + event.status);
+        if (event.status === "success") {
+          event.responseXML.querySelectorAll("update").forEach(function (update: Element) {
+            const result: string[] = /<!\[CDATA\[(.*)]]>/s.exec(update.innerHTML);
+            const id = update.id;
+            if (result.length === 2 && result[1].startsWith("{\"reload\"")) {
+              // not modified on server, needs be reloaded after some time
+              console.debug("[tobago-jsf] Found reload-JSON in response!");
+              ReloadManager.instance.schedule(id, JSON.parse(result[1]).reload.frequency);
+            } else {
+              console.info("[tobago-jsf] Update after jsf.ajax success: #" + id);
+              if (Jsf.isId(id)) {
+                console.debug("[tobago-jsf] updating id: " + id);
+                Listener.executeAfterUpdate(document.getElementById(id));
+              } else if (Jsf.isBody(id)) {
+                console.debug("[tobago-jsf] updating body");
+                // there should be only one element with this class
+                Listener.executeAfterUpdate(document.querySelector<HTMLElement>(".tobago-page"));
+              }
+            }
+          });
+        } else if (event.status === "complete") {
+          event.responseXML.querySelectorAll("update").forEach(function (update: Element) {
+            const id = update.id;
+            if (Jsf.isId(id)) {
+              console.info("[tobago-jsf] Update after jsf.ajax complete: #" + id);
+              // XXX todo: re-implement overlay without jQuery!
+              const $oldElement = jQuery(document.getElementById(id));
+              if ($oldElement.data("tobago-partial-overlay-set")) {
+                 jQuery($oldElement).overlay("destroy");
+              }
+            }
+          });
         }
       });
-    }
-  });
-};
+    };
+  }
 
-Tobago.Listener.register(Tobago4.Jsf.init, Tobago.Phase.DOCUMENT_READY);
+  Listener.register(Jsf.init, Phase.DOCUMENT_READY);
+}


[myfaces-tobago] 01/04: TOBAGO-1633: Use TypeScript instead of JavaScript

Posted by lo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 7dc13543d150687c5282ebb3cd8bd91847c36a39
Author: Udo Schnurpfeil <lo...@apache.org>
AuthorDate: Thu May 9 10:56:44 2019 +0200

    TOBAGO-1633: Use TypeScript instead of JavaScript
    
    * refactoring: reload
---
 .../src/main/npm/ts/tobago-jsf.ts                  |   2 +-
 .../src/main/npm/ts/tobago-reload.ts               | 104 ++++++++++-----------
 .../src/main/npm/ts/tobago-sheet.ts                |  18 +++-
 .../src/main/npm/ts/tobago-utils.ts                |  18 ++++
 4 files changed, 80 insertions(+), 62 deletions(-)

diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-jsf.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-jsf.ts
index 1b2c42d..07d9dbf 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-jsf.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-jsf.ts
@@ -63,7 +63,7 @@ Tobago4.Jsf.init = function() {
         if (result.length === 2 && result[1].startsWith("{\"reload\"")) {
           // not modified on server, needs be reloaded after some time
           console.debug("Found reload-JSON in response!");
-          Tobago4.Reload.reschedule(id, JSON.parse(result[1]).reload.frequency);
+          Tobago.ReloadManager.instance.schedule(id, JSON.parse(result[1]).reload.frequency);
         } else {
           console.info("Update after jsf.ajax success: id='" + id + "'");
           if (Tobago4.Jsf.isId(id)) {
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-reload.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-reload.ts
index b863405..71c7139 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-reload.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-reload.ts
@@ -15,66 +15,58 @@
  * limitations under the License.
  */
 
-// todo: make a reload object
+namespace Tobago {
 
-Tobago4.Reload = {
-  timeoutMap: new Map<string, number>()
-};
+  // todo: remove "export" when everything is in namespace Tobago
+  export class ReloadManager {
 
-Tobago4.Reload.init = function (elements) {
-  elements = elements.jQuery ? elements : jQuery(elements); // fixme jQuery -> ES5
-  const reloads = Tobago4.Utils.selectWithJQuery(elements, "[data-tobago-reload]");
-  reloads.each(function () {
-    const reload = Number(this.dataset["tobagoReload"]);
-    if (reload > 0) {
-      Tobago4.Reload.addReloadTimeout(this.id, Tobago4.Reload.reloadWithAction, reload);
+    static instance: ReloadManager = new ReloadManager();
+
+    /**
+     * Map to store the scheduled timeouts by id, to prevent duplicate scheduling of the same elements.
+     */
+    private timeouts: Map<string, number>;
+
+    private constructor() {
+      this.timeouts = new Map<string, number>();
     }
-  });
-};
 
-Tobago4.Reload.reschedule = function (id: string, reloadMillis: number) {
-  if (reloadMillis > 0) {
-    Tobago4.Reload.addReloadTimeout(id, Tobago4.Reload.reloadWithAction, reloadMillis);
-  }
-};
+    static init = function (element: HTMLElement): void {
+      for (const reload of element.tobagoSelfOrQuerySelectorAll("[data-tobago-reload]")) {
+        ReloadManager.instance.schedule(reload.id, Number(reload.dataset["tobagoReload"]));
+      }
+    };
 
-Tobago4.Reload.addReloadTimeout = function (id, func, time) {
-  let oldTimeout = Tobago4.Reload.timeoutMap.get(id);
-  if (oldTimeout) {
-    console.debug("clearReloadTimer timeout='" + oldTimeout + "' id='" + id + "'");
-    clearTimeout(oldTimeout);
-    Tobago4.Reload.timeoutMap.delete(id);
-  }
-  let timeout = setTimeout(function () {
-    func(id);
-  }, time);
-  console.debug("addReloadTimer timeout='" + timeout + "' id='" + id + "'");
-  Tobago4.Reload.timeoutMap.set(id, timeout);
-};
+    public schedule = function (id: string, reloadMillis: number) {
+      if (reloadMillis > 0) {
 
-Tobago4.Reload.reloadWithAction = function (
-    elementId: string,
-    executeIds: string = elementId,
-    renderIds: string = executeIds) {
-  console.debug("reloadWithAction '" + elementId + "' '" + executeIds + "' '" + renderIds + "");
-  // XXX FIXME: behaviorCommands will probably be empty and not working!
-  // if (this.behaviorCommands && this.behaviorCommands.reload) {
-  //   if (this.behaviorCommands.reload.execute) {
-  //     executeIds += " " + this.behaviorCommands.reload.execute;
-  //   }
-  //   if (this.behaviorCommands.reload.render) {
-  //     renderIds += " " + this.behaviorCommands.reload.render;
-  //   }
-  // }
-  jsf.ajax.request(
-      elementId,
-      null,
-      {
-        "javax.faces.behavior.event": "reload",
-        execute: executeIds,
-        render: renderIds
-      });
-};
+        // may remove old schedule
+        let oldTimeout = this.timeouts.get(id);
+        if (oldTimeout) {
+          console.debug("clear reload timeout '" + oldTimeout + "' for #'" + id + "'");
+          window.clearTimeout(oldTimeout);
+          this.timeouts.delete(id);
+        }
+
+        // add new schedule
+        let timeout = window.setTimeout(function () {
+          console.debug("reloading #'" + id + "'");
+          jsf.ajax.request(
+              id,
+              null,
+              {
+                "javax.faces.behavior.event": "reload",
+                execute: id,
+                render: id
+              });
+        }, reloadMillis);
+        console.debug("adding reload timeout '" + timeout + "' for #'" + id + "'");
+        this.timeouts.set(id, timeout);
+      }
+    };
+
+  }
 
-Tobago.Listener.register(Tobago4.Reload.init, Tobago.Phase.DOCUMENT_READY);
-Tobago.Listener.register(Tobago4.Reload.init, Tobago.Phase.AFTER_UPDATE);
+  Listener.register(ReloadManager.init, Phase.DOCUMENT_READY);
+  Listener.register(ReloadManager.init, Phase.AFTER_UPDATE);
+}
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-sheet.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-sheet.ts
index 05978bb..991554c 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-sheet.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-sheet.ts
@@ -439,13 +439,21 @@ Tobago4.Sheet.setup2 = function (sheets) {
   });
 };
 
-Tobago4.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");
+Tobago4.Sheet.hideInputOrSubmit = function ($input) {
+  let $output = $input.siblings(".tobago-sheet-pagingOutput");
+  let changed = $output.html() !== $input.val();
+  let sheetId = $input.parents(".tobago-sheet:first").attr("id");
   $output.html($input.val());
   if (changed) {
-    Tobago4.Reload.reloadWithAction($input.attr("id"), sheetId);
+    console.debug("reloading sheet '" + $input.attr("id") + "' '" + sheetId + "'");
+    jsf.ajax.request(
+        $input.attr("id"),
+        null,
+        {
+          "javax.faces.behavior.event": "reload",
+          execute: sheetId,
+          render: sheetId
+        });
   } else {
     console.info("no update needed");
     $input.hide();
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-utils.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-utils.ts
index f4f0893..88ab419 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-utils.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-utils.ts
@@ -18,6 +18,8 @@
 interface HTMLElement {
   tobagoSelfOrElementsByClassName(className: string): Array<HTMLElement>;
 
+  tobagoSelfOrQuerySelectorAll(selectors: string): Array<HTMLElement>;
+
   tobagoPreviousElementSibling(): HTMLElement;
 
   tobagoNextElementSibling(): HTMLElement;
@@ -43,6 +45,22 @@ HTMLElement.prototype.tobagoSelfOrElementsByClassName = function (className: str
 };
 
 /**
+ * Find all elements (and also self) which have the attribute "attributeName".
+ * @param selectors Name of the attribute of the elements to find.
+ */
+// todo: may return NodeListOf<HTMLElementTagNameMap[K]> or something like that.
+HTMLElement.prototype.tobagoSelfOrQuerySelectorAll = function (selectors: string): Array<HTMLElement> {
+  const result: Array<HTMLElement> = new Array<HTMLElement>();
+  if (this.matches(selectors)) {
+    result.push(this);
+  }
+  for (const found of this.querySelectorAll(selectors)) {
+    result.push(found);
+  }
+  return result;
+};
+
+/**
  * Get the previous sibling element (without <style> elements).
  */
 HTMLElement.prototype.tobagoPreviousElementSibling = function (): HTMLElement {


[myfaces-tobago] 03/04: TOBAGO-1633: Use TypeScript instead of JavaScript

Posted by lo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 666b633d8385123c6a6d24c13abe950a7a127a0d
Author: Udo Schnurpfeil <lo...@apache.org>
AuthorDate: Thu May 9 14:44:43 2019 +0200

    TOBAGO-1633: Use TypeScript instead of JavaScript
    
    * refactor jQuery to Vanilla JS
---
 .../src/main/npm/ts/tobago-header-footer.ts        | 38 ++++++++++------------
 .../src/main/npm/ts/tobago-utils.ts                | 14 ++++++++
 2 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-header-footer.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-header-footer.ts
index 731841e..6824788 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-header-footer.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-header-footer.ts
@@ -23,15 +23,16 @@ namespace Tobago {
 
       // fixing fixed header/footer: content should not scroll behind the footer
 
-      const body: JQuery<NodeListOf<Element>> = Tobago4.Utils.selectWithJQuery(jQuery(element), "body");
-      const headers: JQuery<NodeListOf<Element>> = Tobago4.Utils.selectWithJQuery(jQuery(element), ".fixed-top");
-      const footers: JQuery<NodeListOf<Element>> = Tobago4.Utils.selectWithJQuery(jQuery(element), ".fixed-bottom");
+      const body = element.tobagoSelfOrQuerySelectorAll("body")[0];
+      const headers = element.tobagoSelfOrQuerySelectorAll(".fixed-top");
+      const footers = element.tobagoSelfOrQuerySelectorAll(".fixed-bottom");
 
       setMargins(body, headers, footers);
 
       let lastMaxHeaderHeight = 0;
       let lastMaxFooterHeight = 0;
-      jQuery(window).on("resize", function (): void {
+
+      window.addEventListener("resize", function (): void {
         const maxHeaderHeight: number = HeaderFooter.getMaxHeaderHeight(headers);
         const maxFooterHeight: number = HeaderFooter.getMaxFooterHeight(footers);
 
@@ -44,26 +45,23 @@ namespace Tobago {
         }
       });
 
-      function setMargins(
-          body: JQuery<NodeListOf<Element>>,
-          headers: JQuery<NodeListOf<Element>>,
-          footers: JQuery<NodeListOf<Element>>): void {
-        const maxHeaderHeight: number = HeaderFooter.getMaxHeaderHeight(headers);
-        const maxFooterHeight: number = HeaderFooter.getMaxFooterHeight(footers);
+      function setMargins(body: HTMLElement, headers: HTMLElement[], footers: HTMLElement[]): void {
+        const maxHeaderHeight = HeaderFooter.getMaxHeaderHeight(headers);
+        const maxFooterHeight = HeaderFooter.getMaxFooterHeight(footers);
 
         if (maxHeaderHeight > 0) {
-          body.css("margin-top", maxHeaderHeight + "px");
+          body.style.marginTop = maxHeaderHeight + "px";
         }
         if (maxFooterHeight > 0) {
-          body.css("margin-bottom", maxFooterHeight + "px");
+          body.style.marginBottom = maxFooterHeight + "px";
         }
       }
     };
 
-    static getMaxHeaderHeight = function (headers: JQuery<NodeListOf<Element>>): number {
-      let maxHeaderHeight: number = 0;
-      headers.each(function (): void {
-        const height: number = jQuery(this).outerHeight(true);
+    static getMaxHeaderHeight = function (headers: HTMLElement[]): number {
+      let maxHeaderHeight = 0;
+      headers.forEach(function (element: HTMLElement): void {
+        const height = element.outerHeightWithMargin();
         if (height > maxHeaderHeight) {
           maxHeaderHeight = height;
         }
@@ -71,10 +69,10 @@ namespace Tobago {
       return maxHeaderHeight;
     };
 
-    static getMaxFooterHeight = function (footers: JQuery<NodeListOf<Element>>): number {
-      let maxFooterHeight: number = 0;
-      footers.each(function (): void {
-        const height: number = jQuery(this).outerHeight(true);
+    static getMaxFooterHeight = function (footers: HTMLElement[]): number {
+      let maxFooterHeight = 0;
+      footers.forEach(function (element: HTMLElement): void {
+        const height = element.outerHeightWithMargin();
         if (height > maxFooterHeight) {
           maxFooterHeight = height;
         }
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-utils.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-utils.ts
index 88ab419..1b33e4f 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-utils.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-utils.ts
@@ -23,6 +23,10 @@ interface HTMLElement {
   tobagoPreviousElementSibling(): HTMLElement;
 
   tobagoNextElementSibling(): HTMLElement;
+
+  outerWidthWithMargin(): number;
+  outerHeightWithMargin(): number;
+
 }
 
 interface Document {
@@ -88,6 +92,16 @@ HTMLElement.prototype.tobagoNextElementSibling = function (): HTMLElement {
   return null;
 };
 
+HTMLElement.prototype.outerWidthWithMargin = function () {
+  const style = window.getComputedStyle(this);
+  return this.offsetWidth + parseInt(style.marginLeft) + parseInt(style.marginRight);
+};
+
+HTMLElement.prototype.outerHeightWithMargin = function () {
+  const style = window.getComputedStyle(this);
+  return this.offsetHeight + parseInt(style.marginTop) + parseInt(style.marginBottom);
+};
+
 Document.prototype.tobagoPage = function (): HTMLElement {
   const pages = this.getElementsByClassName("tobago-page");
   if (pages.length > 0) {