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 2021/01/27 14:51:04 UTC
[myfaces-tobago] branch master updated: use bootstrap-dropdown.js
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
The following commit(s) were added to refs/heads/master by this push:
new 26fefde use bootstrap-dropdown.js
26fefde is described below
commit 26fefdeb8b9e20fdba5c02c9ae10a00b7bd0c18e
Author: Henning Noeth <hn...@apache.org>
AuthorDate: Tue Jan 26 17:02:57 2021 +0100
use bootstrap-dropdown.js
* tobago-dropdown.ts only move the dropdown-menu to page-menu-store
* html rendering changed to bootstrap5
* adjust styles
* adjust tests
---
tobago-core/npm/scss/_tobago.scss | 2 +
.../renderkit/renderer/CommandRendererBase.java | 3 +-
.../renderer/buttons/separator-inside-buttons.html | 2 +-
.../renderer/in/input-group-dropdown-after.html | 2 +-
.../renderer/in/input-group-dropdown-before.html | 2 +-
.../resources/renderer/link/booleanInsideLink.html | 2 +-
.../resources/renderer/link/manyInsideLink.html | 4 +-
.../resources/renderer/link/radioInsideLink.html | 2 +-
.../renderer/link/separatorInsideLink.html | 2 +-
.../renderer/links/link-inside-links-sub.html | 4 +-
.../010-input/50-input-group/Group.test.js | 72 +++---
.../npm/ts/tobago-dropdown.ts | 280 +--------------------
12 files changed, 65 insertions(+), 312 deletions(-)
diff --git a/tobago-core/npm/scss/_tobago.scss b/tobago-core/npm/scss/_tobago.scss
index 7847094..779e3b0 100644
--- a/tobago-core/npm/scss/_tobago.scss
+++ b/tobago-core/npm/scss/_tobago.scss
@@ -287,6 +287,8 @@ workaround for Bootstrap Modal (Popup) with vanillajs-datepicker
/* dropdown ------------------------------------------------------- */
tobago-dropdown {
+ display: inline-block; //make tobago-dropdown height the same the inner button. Important for dropdown-menu position
+
@include dropdownMenuFormCheckComponents();
&.tobago-dropdown-submenu {
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 0ec670f..05c2b45 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
@@ -107,7 +107,8 @@ public abstract class CommandRendererBase<T extends AbstractUICommand> extends D
HtmlRendererUtils.writeDataAttributes(facesContext, writer, component);
if (parentOfCommands) {
- writer.writeAttribute(DataAttributes.TOGGLE, "dropdown", false);
+ writer.writeAttribute(DataAttributes.BS_TOGGLE, "dropdown", false);
+ writer.writeAttribute(Arias.EXPANDED, Boolean.FALSE.toString(), false);
}
final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, component);
writer.writeAttribute(HtmlAttributes.TITLE, title, true);
diff --git a/tobago-core/src/test/resources/renderer/buttons/separator-inside-buttons.html b/tobago-core/src/test/resources/renderer/buttons/separator-inside-buttons.html
index 16d33ff..a958501 100644
--- a/tobago-core/src/test/resources/renderer/buttons/separator-inside-buttons.html
+++ b/tobago-core/src/test/resources/renderer/buttons/separator-inside-buttons.html
@@ -19,7 +19,7 @@ CSS class of "tobago-dropdown" has changed from btn-group to dropdown
-->
<tobago-buttons id='list' class='btn-group' role='group'>
<tobago-dropdown id='id' class='dropdown btn-group'>
- <button type='button' id='id::command' name='id' data-toggle='dropdown' class='tobago-button btn btn-secondary dropdown-toggle'><tobago-behavior event='click' client-id='id' field-id='id::command'></tobago-behavior><span>button</span></button>
+ <button type='button' id='id::command' name='id' data-bs-toggle='dropdown' aria-expanded='false' class='tobago-button btn btn-secondary dropdown-toggle'><tobago-behavior event='click' client-id='id' field-id='id::command'></tobago-behavior><span>button</span></button>
<div class='dropdown-menu' aria-labelledby='id::command' name='id'>
<button type='button' id='sub1' name='sub1' class='tobago-link dropdown-item'><tobago-behavior event='click' client-id='sub1'></tobago-behavior><span>sub1</span></button>
<tobago-separator id='separator1' class='dropdown-divider'>
diff --git a/tobago-core/src/test/resources/renderer/in/input-group-dropdown-after.html b/tobago-core/src/test/resources/renderer/in/input-group-dropdown-after.html
index 3a62574..c356f12 100644
--- a/tobago-core/src/test/resources/renderer/in/input-group-dropdown-after.html
+++ b/tobago-core/src/test/resources/renderer/in/input-group-dropdown-after.html
@@ -22,7 +22,7 @@ dropdown-menu-right is temporarily not here (in the div with dropdown-menu), XXX
<div class='input-group'>
<input type='text' name='id' id='id::field' class='tobago-in form-control'>
<tobago-dropdown id='button' class='dropdown'>
- <button type='button' id='button::command' name='button' data-toggle='dropdown' class='tobago-button btn btn-secondary dropdown-toggle'><tobago-behavior event='click' client-id='button' field-id='button::command' omit='omit'></tobago-behavior><span>dropdown</span></button>
+ <button type='button' id='button::command' name='button' data-bs-toggle='dropdown' aria-expanded='false' class='tobago-button btn btn-secondary dropdown-toggle'><tobago-behavior event='click' client-id='button' field-id='button::command' omit='omit'></tobago-behavior><span>dropdown</span></button>
<div class='dropdown-menu' aria-labelledby='button::command' name='button'>
<button type='button' id='l1' name='l1' class='tobago-link dropdown-item'><tobago-behavior event='click' client-id='l1'></tobago-behavior><span>Link 1</span></button>
<button type='button' id='l2' name='l2' class='tobago-link dropdown-item'><tobago-behavior event='click' client-id='l2'></tobago-behavior><span>Link 2</span></button>
diff --git a/tobago-core/src/test/resources/renderer/in/input-group-dropdown-before.html b/tobago-core/src/test/resources/renderer/in/input-group-dropdown-before.html
index 911125a..b42a3ec 100644
--- a/tobago-core/src/test/resources/renderer/in/input-group-dropdown-before.html
+++ b/tobago-core/src/test/resources/renderer/in/input-group-dropdown-before.html
@@ -19,7 +19,7 @@
<div class='tobago-input-group-outer'>
<div class='input-group'>
<tobago-dropdown id='button' class='dropdown'>
- <button type='button' id='button::command' name='button' data-toggle='dropdown' class='tobago-button btn btn-secondary dropdown-toggle'><tobago-behavior event='click' client-id='button' field-id='button::command' omit='omit'></tobago-behavior><span>dropdown</span></button>
+ <button type='button' id='button::command' name='button' data-bs-toggle='dropdown' aria-expanded='false' class='tobago-button btn btn-secondary dropdown-toggle'><tobago-behavior event='click' client-id='button' field-id='button::command' omit='omit'></tobago-behavior><span>dropdown</span></button>
<div class='dropdown-menu' aria-labelledby='button::command' name='button'>
<button type='button' id='l1' name='l1' class='tobago-link dropdown-item'><tobago-behavior event='click' client-id='l1'></tobago-behavior><span>Link 1</span></button>
<button type='button' id='l2' name='l2' class='tobago-link dropdown-item'><tobago-behavior event='click' client-id='l2'></tobago-behavior><span>Link 2</span></button>
diff --git a/tobago-core/src/test/resources/renderer/link/booleanInsideLink.html b/tobago-core/src/test/resources/renderer/link/booleanInsideLink.html
index 3e2a0d0..e6235ae 100644
--- a/tobago-core/src/test/resources/renderer/link/booleanInsideLink.html
+++ b/tobago-core/src/test/resources/renderer/link/booleanInsideLink.html
@@ -16,7 +16,7 @@
-->
<tobago-dropdown id='id' class='dropdown'>
- <button type='button' id='id::command' name='id' data-toggle='dropdown' class='tobago-link btn btn-link dropdown-toggle'><tobago-behavior event='click' client-id='id' field-id='id::command'></tobago-behavior><span>dropdown</span></button>
+ <button type='button' id='id::command' name='id' data-bs-toggle='dropdown' aria-expanded='false' class='tobago-link btn btn-link dropdown-toggle'><tobago-behavior event='click' client-id='id' field-id='id::command'></tobago-behavior><span>dropdown</span></button>
<div class='dropdown-menu' aria-labelledby='id::command' name='id'>
<tobago-select-boolean-checkbox id='id' class='form-check dropdown-item'>
<input class='form-check-input' type='checkbox' value='true' name='id' id='id::field'>
diff --git a/tobago-core/src/test/resources/renderer/link/manyInsideLink.html b/tobago-core/src/test/resources/renderer/link/manyInsideLink.html
index 9601fe6..89e669b 100644
--- a/tobago-core/src/test/resources/renderer/link/manyInsideLink.html
+++ b/tobago-core/src/test/resources/renderer/link/manyInsideLink.html
@@ -16,7 +16,7 @@
-->
<tobago-dropdown id='id' class='dropdown'>
- <button type='button' id='id::command' name='id' data-toggle='dropdown' class='tobago-link btn btn-link dropdown-toggle'><tobago-behavior event='click' client-id='id' field-id='id::command'></tobago-behavior><span>dropdown</span></button>
+ <button type='button' id='id::command' name='id' data-bs-toggle='dropdown' aria-expanded='false' class='tobago-link btn btn-link dropdown-toggle'><tobago-behavior event='click' client-id='id' field-id='id::command'></tobago-behavior><span>dropdown</span></button>
<div class='dropdown-menu' aria-labelledby='id::command' name='id'>
<tobago-select-many-checkbox>
<div class='form-check dropdown-item'>
@@ -29,4 +29,4 @@
</div>
</tobago-select-many-checkbox>
</div>
-</tobago-dropdown>
\ No newline at end of file
+</tobago-dropdown>
diff --git a/tobago-core/src/test/resources/renderer/link/radioInsideLink.html b/tobago-core/src/test/resources/renderer/link/radioInsideLink.html
index f3e71c6..9bfa0eb 100644
--- a/tobago-core/src/test/resources/renderer/link/radioInsideLink.html
+++ b/tobago-core/src/test/resources/renderer/link/radioInsideLink.html
@@ -16,7 +16,7 @@
-->
<tobago-dropdown id='id' class='dropdown'>
- <button type='button' id='id::command' name='id' data-toggle='dropdown' class='tobago-link btn btn-link dropdown-toggle'><tobago-behavior event='click' client-id='id' field-id='id::command'></tobago-behavior><span>dropdown</span></button>
+ <button type='button' id='id::command' name='id' data-bs-toggle='dropdown' aria-expanded='false' class='tobago-link btn btn-link dropdown-toggle'><tobago-behavior event='click' client-id='id' field-id='id::command'></tobago-behavior><span>dropdown</span></button>
<div class='dropdown-menu' aria-labelledby='id::command' name='id'>
<tobago-select-one-radio>
<div class='form-check dropdown-item'>
diff --git a/tobago-core/src/test/resources/renderer/link/separatorInsideLink.html b/tobago-core/src/test/resources/renderer/link/separatorInsideLink.html
index 43674b2..a945d81 100644
--- a/tobago-core/src/test/resources/renderer/link/separatorInsideLink.html
+++ b/tobago-core/src/test/resources/renderer/link/separatorInsideLink.html
@@ -16,7 +16,7 @@
-->
<tobago-dropdown id='id' class='dropdown'>
- <button type='button' id='id::command' name='id' data-toggle='dropdown' class='tobago-link btn btn-link dropdown-toggle'><tobago-behavior event='click' client-id='id' field-id='id::command'></tobago-behavior><span>dropdown</span></button>
+ <button type='button' id='id::command' name='id' data-bs-toggle='dropdown' aria-expanded='false' class='tobago-link btn btn-link dropdown-toggle'><tobago-behavior event='click' client-id='id' field-id='id::command'></tobago-behavior><span>dropdown</span></button>
<div class='dropdown-menu' aria-labelledby='id::command' name='id'>
<a id='link1' name='link1' href='https://www.apache.org/' class='tobago-link dropdown-item'><tobago-behavior event='click' client-id='link1' omit='omit'></tobago-behavior><span>Link 1</span></a>
<tobago-separator id='separator' class='dropdown-divider'>
diff --git a/tobago-core/src/test/resources/renderer/links/link-inside-links-sub.html b/tobago-core/src/test/resources/renderer/links/link-inside-links-sub.html
index 9a04122..1c4d575 100644
--- a/tobago-core/src/test/resources/renderer/links/link-inside-links-sub.html
+++ b/tobago-core/src/test/resources/renderer/links/link-inside-links-sub.html
@@ -21,11 +21,11 @@ CSS class nav-item has moved from "tobago-dropdown" to "li"
<ul class='nav'>
<li class='nav-item'>
<tobago-dropdown id='id' class='dropdown'>
- <button type='button' id='id::command' name='id' data-toggle='dropdown' class='tobago-link btn btn-link dropdown-toggle nav-link'><tobago-behavior event='click' client-id='id' field-id='id::command'></tobago-behavior><span>apache</span></button>
+ <button type='button' id='id::command' name='id' data-bs-toggle='dropdown' aria-expanded='false' class='tobago-link btn btn-link dropdown-toggle nav-link'><tobago-behavior event='click' client-id='id' field-id='id::command'></tobago-behavior><span>apache</span></button>
<div class='dropdown-menu' aria-labelledby='id::command' name='id'>
<a id='sub' name='sub' href='https://www.apache.org/' class='tobago-link dropdown-item nav-link'><tobago-behavior event='click' client-id='sub' omit='omit'></tobago-behavior><span>sub</span></a>
</div>
</tobago-dropdown>
</li>
</ul>
-</tobago-links>
\ No newline at end of file
+</tobago-links>
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/50-input-group/Group.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/50-input-group/Group.test.js
index 851b425..63e881f 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/50-input-group/Group.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/50-input-group/Group.test.js
@@ -37,36 +37,36 @@ it("ajax: chat send button", function (done) {
it("ajax: dropdown button", function (done) {
let buttonFn = querySelectorFn("#page\\:mainForm\\:lsendtoc\\:\\:command");
let buttonLabelFn = querySelectorFn("#page\\:mainForm\\:lsendtoc\\:\\:command span");
+ let dropdownMenu = querySelectorFn(".dropdown-menu[name='page:mainForm:lsendtoc']");
let sendToPeterFn = querySelectorFn("#page\\:mainForm\\:sendToPeter");
let sendToBobFn = querySelectorFn("#page\\:mainForm\\:sendToBob");
let sendToAllFn = querySelectorFn("#page\\:mainForm\\:sendToAll");
const test = new JasmineTestTool(done);
- test.do(() => fail("not implemented yet; fix dropdown first"));
- /*TTT.action(function () {
- buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
- sendToPeterFn().dispatchEvent(new Event("click", {bubbles: true}));
- });
- TTT.waitForResponse();
- TTT.asserts(1, function () {
- assert.equal(buttonLabelFn().textContent, "SendTo: Peter");
- });
- TTT.action(function () {
- buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
- sendToBobFn().dispatchEvent(new Event("click", {bubbles: true}));
- });
- TTT.waitForResponse();
- TTT.asserts(1, function () {
- assert.equal(buttonLabelFn().textContent, "SendTo: Bob");
- });
- TTT.action(function () {
- buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
- sendToAllFn().dispatchEvent(new Event("click", {bubbles: true}));
- });
- TTT.waitForResponse();
- TTT.asserts(1, function () {
- assert.equal(buttonLabelFn().textContent, "SendTo: All");
- });*/
+ test.setup(() => !dropdownMenu().parentElement.classList.contains("tobago-page-menuStore"),
+ null, "click", buttonFn);
+ test.setup(() => buttonLabelFn().textContent !== "SendTo: Peter",
+ null, "click", sendToAllFn);
+ test.do(() => expect(dropdownMenu().parentElement.classList).not.toContain("tobago-page-menuStore"));
+ test.do(() => expect(buttonLabelFn().textContent).not.toBe("SendTo: Peter"));
+
+ test.event("click", buttonFn, () => dropdownMenu().parentElement.classList.contains("tobago-page-menuStore"));
+ test.do(() => expect(dropdownMenu().parentElement.classList).toContain("tobago-page-menuStore"));
+ test.event("click", sendToPeterFn, () => buttonLabelFn().textContent === "SendTo: Peter");
+ test.do(() => expect(dropdownMenu().parentElement.classList).not.toContain("tobago-page-menuStore"));
+ test.do(() => expect(buttonLabelFn().textContent).toBe("SendTo: Peter"));
+
+ test.event("click", buttonFn, () => dropdownMenu().parentElement.classList.contains("tobago-page-menuStore"));
+ test.do(() => expect(dropdownMenu().parentElement.classList).toContain("tobago-page-menuStore"));
+ test.event("click", sendToBobFn, () => buttonLabelFn().textContent === "SendTo: Bob");
+ test.do(() => expect(dropdownMenu().parentElement.classList).not.toContain("tobago-page-menuStore"));
+ test.do(() => expect(buttonLabelFn().textContent).toBe("SendTo: Bob"));
+
+ test.event("click", buttonFn, () => dropdownMenu().parentElement.classList.contains("tobago-page-menuStore"));
+ test.do(() => expect(dropdownMenu().parentElement.classList).toContain("tobago-page-menuStore"));
+ test.event("click", sendToAllFn, () => buttonLabelFn().textContent === "SendTo: All");
+ test.do(() => expect(dropdownMenu().parentElement.classList).not.toContain("tobago-page-menuStore"));
+ test.do(() => expect(buttonLabelFn().textContent).toBe("SendTo: All"));
test.start();
});
@@ -77,8 +77,7 @@ it("ajax: currency change event", function (done) {
let outputFn = querySelectorFn("#page\\:mainForm\\:valueInEuro tobago-out");
const test = new JasmineTestTool(done);
- test.setup(() => parseInt(inputFn().value.replaceAll(".", "")) === 1000
- && outputFn().textContent === "1.000,00",
+ test.setup(() => convertInt(outputFn().textContent) === 100000,
() => {
inputFn().value = "1000";
optionsFn().item(0).selected = false; // Yen
@@ -93,23 +92,30 @@ it("ajax: currency change event", function (done) {
test.do(() => optionsFn().item(1).selected = false); // Trinidad-Tobago Dollar
test.do(() => optionsFn().item(2).selected = false); // US Dollar
test.do(() => optionsFn().item(3).selected = false); // Euro
- test.event("change", selectFn, () => outputFn().textContent === "8,85");
- test.do(() => expect(outputFn().textContent).toBe("8,85"));
+ test.event("change", selectFn, () => convertInt(outputFn().textContent) === 885);
+ test.do(() => expect(convertInt(outputFn().textContent)).toBe(885));
test.do(() => inputFn().value = "2000");
test.do(() => optionsFn().item(0).selected = false); // Yen
test.do(() => optionsFn().item(1).selected = true); // Trinidad-Tobago Dollar
test.do(() => optionsFn().item(2).selected = false); // US Dollar
test.do(() => optionsFn().item(3).selected = false); // Euro
- test.event("change", selectFn, () => outputFn().textContent === "267,50");
- test.do(() => expect(outputFn().textContent).toBe("267,50"));
+ test.event("change", selectFn, () => convertInt(outputFn().textContent) === 26750);
+ test.do(() => expect(convertInt(outputFn().textContent)).toBe(26750));
test.do(() => inputFn().value = "3000");
test.do(() => optionsFn().item(0).selected = false); // Yen
test.do(() => optionsFn().item(1).selected = false); // Trinidad-Tobago Dollar
test.do(() => optionsFn().item(2).selected = true); // US Dollar
test.do(() => optionsFn().item(3).selected = false); // Euro
- test.event("change", selectFn, () => outputFn().textContent === "2.688,29");
- test.do(() => expect(outputFn().textContent).toBe("2.688,29"));
+ test.event("change", selectFn, () => convertInt(outputFn().textContent) === 268829);
+ test.do(() => expect(convertInt(outputFn().textContent)).toBe(268829));
test.start();
});
+
+/**
+ * need this function, because chrome displays "1.000,00" and firefox displays "1,000.00"
+ */
+function convertInt(string) {
+ return parseInt(string.replaceAll(",", "").replaceAll(".", ""));
+}
diff --git a/tobago-theme/tobago-theme-standard/npm/ts/tobago-dropdown.ts b/tobago-theme/tobago-theme-standard/npm/ts/tobago-dropdown.ts
index 7b03c73..df26fe2 100644
--- a/tobago-theme/tobago-theme-standard/npm/ts/tobago-dropdown.ts
+++ b/tobago-theme/tobago-theme-standard/npm/ts/tobago-dropdown.ts
@@ -15,10 +15,9 @@
* limitations under the License.
*/
-import {createPopper} from "@popperjs/core";
// import {createPopper} from "@popperjs/core/dist/esm/popper";
-const Event = {
+const TobagoDropdownEvent = {
HIDE: "tobago.dropdown.hide",
HIDDEN: "tobago.dropdown.hidden",
SHOW: "tobago.dropdown.show",
@@ -26,142 +25,38 @@ const Event = {
};
/**
- * The dropdown implementation of Bootstrap does not support submenus. Therefore we need an own dropdown implementation.
+ * The dropdown implementation of Bootstrap does not move the menu to the tobago-page-menuStore. This behavior is
+ * implemented in this class.
*/
class Dropdown extends HTMLElement {
- private dropdownEntries: DropdownEntry[] = [];
-
constructor() {
super();
if (!this.classList.contains("tobago-dropdown-submenu")) { // ignore submenus
- const root = this.getRootNode() as ShadowRoot | Document;
-
- this.createDropdownEntries(this.dropdownMenu, null);
-
- this.toggleButton.addEventListener("click", this.toggleDropdown.bind(this));
- root.addEventListener("mouseup", this.mouseupOnDocument.bind(this));
- root.addEventListener("keydown", this.keydownOnDocument.bind(this));
+ this.addEventListener("shown.bs.dropdown", this.openDropdown.bind(this));
+ this.addEventListener("hidden.bs.dropdown", this.closeDropdown.bind(this));
}
}
connectedCallback(): void {
}
- toggleDropdown(event: Event): void {
- event.preventDefault();
- event.stopPropagation();
- if (this.dropdownVisible()) {
- this.closeDropdown();
- } else {
- this.openDropdown();
- }
- }
-
- mouseupOnDocument(event: MouseEvent): void {
- if (!this.toggleButtonSelected(event) && this.dropdownVisible()
- && !this.dropdownMenu.contains(event.target as HTMLElement)) {
- this.closeDropdown();
- }
- }
-
- keydownOnDocument(event: KeyboardEvent): void {
- if (this.toggleButtonSelected(event) && !this.dropdownVisible()
- && (event.code === "ArrowUp" || event.code === "ArrowDown")) {
- event.preventDefault();
- event.stopPropagation();
- this.openDropdown();
-
- const interval = setInterval(() => {
- if (this.dropdownVisible()) {
-
- if (this.activeDropdownEntry) {
- this.activeDropdownEntry.focus();
- } else {
- this.dropdownEntries[0].focus();
- }
- clearInterval(interval);
- }
- }, 0);
- } else if (this.dropdownVisible()
- && (event.code === "ArrowUp" || event.code === "ArrowDown"
- || event.code === "ArrowLeft" || event.code === "ArrowRight"
- || event.code === "Tab")) {
- event.preventDefault();
- event.stopPropagation();
-
- if (!this.activeDropdownEntry) {
- this.dropdownEntries[0].focus();
- } else if (event.code === "ArrowUp" && this.activeDropdownEntry.previous) {
- this.activeDropdownEntry.previous.focus();
- } else if (event.code === "ArrowDown" && this.activeDropdownEntry.next) {
- this.activeDropdownEntry.next.focus();
- } else if (event.code === "ArrowRight" && this.activeDropdownEntry.children.length > 0) {
- this.activeDropdownEntry.children[0].focus();
- } else if (event.code === "ArrowLeft" && this.activeDropdownEntry.parent) {
- this.activeDropdownEntry.parent.focus();
- } else if (!event.shiftKey && event.code === "Tab") {
- if (this.activeDropdownEntry.children.length > 0) {
- this.activeDropdownEntry.children[0].focus();
- } else if (this.activeDropdownEntry.next) {
- this.activeDropdownEntry.next.focus();
- } else {
- let parent: DropdownEntry = this.activeDropdownEntry.parent;
- while (parent) {
- if (parent.next) {
- this.activeDropdownEntry.clear();
- parent.next.focus();
- break;
- } else {
- parent = parent.parent;
- }
- }
- }
- } else if (event.shiftKey && event.code === "Tab") {
- if (this.activeDropdownEntry.previous) {
- this.activeDropdownEntry.previous.focus();
- } else if (this.activeDropdownEntry.parent) {
- this.activeDropdownEntry.parent.focus();
- }
- }
- } else if (this.dropdownVisible() && event.code === "Escape") {
- event.preventDefault();
- event.stopPropagation();
- this.closeDropdown();
- }
- }
-
openDropdown(): void {
- this.dispatchEvent(new CustomEvent(Event.SHOW));
+ this.dispatchEvent(new CustomEvent(TobagoDropdownEvent.SHOW));
if (!this.inStickyHeader()) {
this.menuStore.appendChild(this.dropdownMenu);
- createPopper(this.toggleButton, this.dropdownMenu, {
- placement: "bottom-start"
- });
}
- for (const dropdownEntry of this.dropdownEntries) {
- dropdownEntry.clear();
- }
-
- this.dropdownMenu.classList.add("show");
- this.dispatchEvent(new CustomEvent(Event.SHOWN));
+ this.dispatchEvent(new CustomEvent(TobagoDropdownEvent.SHOWN));
}
closeDropdown(): void {
- this.dispatchEvent(new CustomEvent(Event.HIDE));
- this.dropdownMenu.classList.remove("show");
- this.appendChild(this.dropdownMenu);
- this.dispatchEvent(new CustomEvent(Event.HIDDEN));
- }
-
- private get toggleButton(): HTMLElement {
- return this.querySelector(":scope > button[data-toggle='dropdown']");
- }
-
- private toggleButtonSelected(event: Event): boolean {
- return this.toggleButton.contains(event.target as HTMLElement);
+ this.dispatchEvent(new CustomEvent(TobagoDropdownEvent.HIDE));
+ if (!this.inStickyHeader()) {
+ this.appendChild(this.dropdownMenu);
+ }
+ this.dispatchEvent(new CustomEvent(TobagoDropdownEvent.HIDDEN));
}
private inStickyHeader(): boolean {
@@ -173,161 +68,10 @@ class Dropdown extends HTMLElement {
return root.querySelector(".dropdown-menu[name='" + this.id + "']");
}
- private dropdownVisible(): boolean {
- return this.dropdownMenu.classList.contains("show");
- }
-
private get menuStore(): HTMLDivElement {
const root = this.getRootNode() as ShadowRoot | Document;
return root.querySelector(".tobago-page-menuStore");
}
-
- private get activeDropdownEntry(): DropdownEntry {
- for (const dropdownEntry of this.dropdownEntries) {
- if (dropdownEntry.active) {
- return dropdownEntry;
- }
- }
- return null;
- }
-
- private createDropdownEntries(dropdownMenu: HTMLDivElement, parent: DropdownEntry): void {
- let lastDropdownEntry: DropdownEntry = null;
-
- for (const dropdownItem of dropdownMenu.children) {
- if (dropdownItem.classList.contains("dropdown-item")) {
- const entry = this.createDropdownEntry(dropdownItem as HTMLElement, parent, lastDropdownEntry);
-
- lastDropdownEntry = entry;
- this.dropdownEntries.push(entry);
-
- if (dropdownItem.classList.contains("tobago-dropdown-submenu")) {
- this.createDropdownEntries(dropdownItem.querySelector(".dropdown-menu"), entry);
- }
- } else {
- const dropdownItems: NodeListOf<HTMLElement> = dropdownItem.querySelectorAll(".dropdown-item");
- for (const dropdownItem of dropdownItems) {
- const entry = this.createDropdownEntry(dropdownItem, parent, lastDropdownEntry);
-
- lastDropdownEntry = entry;
- this.dropdownEntries.push(entry);
- }
- }
- }
- }
-
- private createDropdownEntry(
- dropdownItem: HTMLElement, parent: DropdownEntry, previous: DropdownEntry): DropdownEntry {
-
- const entry = new DropdownEntry(dropdownItem);
- if (parent) {
- entry.parent = parent;
- parent.children.push(entry);
- }
-
- if (previous) {
- previous.next = entry;
- entry.previous = previous;
- }
-
- return entry;
- }
-}
-
-class DropdownEntry {
-
- private _previous: DropdownEntry;
- private _next: DropdownEntry;
- private _parent: DropdownEntry;
- private _children: DropdownEntry[] = [];
- private readonly _baseElement: HTMLElement;
- private readonly focusElement: HTMLElement;
- private _active: boolean;
-
- constructor(dropdownItem: HTMLElement) {
- this._baseElement = dropdownItem;
- if (dropdownItem.classList.contains("tobago-dropdown-submenu")) {
- this.focusElement = dropdownItem.querySelector(".tobago-link");
- } else if (dropdownItem.tagName === "LABEL") {
- const root = dropdownItem.getRootNode() as ShadowRoot | Document;
- this.focusElement = root.getElementById(dropdownItem.getAttribute("for"));
- } else {
- this.focusElement = dropdownItem;
- }
-
- this._baseElement.addEventListener("mouseenter", this.activate.bind(this));
- this._baseElement.addEventListener("mouseleave", this.deactivate.bind(this));
- }
-
- activate(event: MouseEvent): void {
- this.active = true;
- }
-
- deactivate(event: MouseEvent): void {
- this.active = false;
- }
-
- get previous(): DropdownEntry {
- return this._previous;
- }
-
- set previous(value: DropdownEntry) {
- this._previous = value;
- }
-
- get next(): DropdownEntry {
- return this._next;
- }
-
- set next(value: DropdownEntry) {
- this._next = value;
- }
-
- get parent(): DropdownEntry {
- return this._parent;
- }
-
- set parent(value: DropdownEntry) {
- this._parent = value;
- }
-
- get children(): DropdownEntry[] {
- return this._children;
- }
-
- set children(value: DropdownEntry[]) {
- this._children = value;
- }
-
- get active(): boolean {
- return this._active;
- }
-
- set active(value: boolean) {
- this._active = value;
- }
-
- public focus(): void {
- this.previous?.clear();
- this.next?.clear();
- if (this.parent) {
- this.parent.active = false;
- this.parent._baseElement.classList.add("tobago-dropdown-open");
- }
- for (const child of this.children) {
- child.clear();
- }
- this._baseElement.classList.remove("tobago-dropdown-open");
- this._baseElement.classList.add("tobago-dropdown-selected");
- this.active = true;
- this.focusElement.focus();
- }
-
- public clear(): void {
- this._baseElement.classList.remove("tobago-dropdown-open");
- this._baseElement.classList.remove("tobago-dropdown-selected");
- this.active = false;
- }
}
document.addEventListener("tobago.init", function (event: Event): void {