diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/af-commons/v1/clientlibs/tabs/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/af-commons/v1/clientlibs/tabs/.content.xml
new file mode 100644
index 0000000000..aaa876c946
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/af-commons/v1/clientlibs/tabs/.content.xml
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/af-commons/v1/clientlibs/tabs/js.txt b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/af-commons/v1/clientlibs/tabs/js.txt
new file mode 100644
index 0000000000..9f3b9ebc04
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/af-commons/v1/clientlibs/tabs/js.txt
@@ -0,0 +1,18 @@
+###############################################################################
+# Copyright 2023 Adobe
+#
+# Licensed 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.
+###############################################################################
+
+#base=js
+common.js
\ No newline at end of file
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/af-commons/v1/clientlibs/tabs/js/common.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/af-commons/v1/clientlibs/tabs/js/common.js
new file mode 100644
index 0000000000..ecfe9c6bd5
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/af-commons/v1/clientlibs/tabs/js/common.js
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright 2024 Adobe
+ *
+ * Licensed 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.
+ ******************************************************************************/
+
+
+(function () {
+
+ function TabsMixin(Base) {
+ return class extends Base {
+
+ /**
+ * Private property for storing the active tab ID.
+ * @type {string}
+ */
+ #_active;
+
+ /**
+ * Private property for storing the IS.
+ * @type {string}
+ */
+ #_IS;
+ /**
+ * Private property for storing the namespace.
+ * @type {string}
+ */
+ #_NS;
+ /**
+ * Private property for storing the selectors.
+ * @type {object}
+ */
+ #_selectors;
+
+ constructor(params, ns, is, selectors) {
+ super(params);
+ this.#_IS = is;
+ this.#_NS = ns;
+ this.#_selectors = selectors;
+ const { element } = params;
+ this.#cacheElements(element);
+ this.#_active = this.getActiveTabId(this.#getCachedTabs());
+ this.#refreshActive();
+ }
+
+ /**
+ * Gets the cached tab panels.
+ * @returns {NodeList} The cached tab panels.
+ * @private
+ */
+ #getCachedTabPanels() {
+ return this._elements["tabpanel"]
+ }
+
+ /**
+ * Gets the cached tabs.
+ * @returns {NodeList} The cached tabs.
+ * @private
+ */
+ #getCachedTabs() {
+ return this._elements["tab"];
+ }
+
+ /**
+ * Caches the Tabs elements as defined via the {@code data-tabs-hook="ELEMENT_NAME"} markup API.
+ * @private
+ * @param {HTMLElement} wrapper - The Tabs wrapper element.
+ */
+ #cacheElements(wrapper) {
+ this._elements = {};
+ this._elements.self = wrapper;
+ var hooks = this._elements.self.querySelectorAll("[data-" + this.#_NS + "-hook-" + this.#_IS + "]");
+
+ for (var i = 0; i < hooks.length; i++) {
+ var hook = hooks[i];
+ if (hook.closest("[data-cmp-is=" + this.#_IS + "]") === this._elements.self) { // only process own tab elements
+ var lowerCased = this.#_IS.toLowerCase();
+ var capitalized = lowerCased.charAt(0).toUpperCase() + lowerCased.slice(1);
+ var key = hook.dataset[this.#_NS + "Hook" + capitalized];
+ if (this._elements[key]) {
+ if (!Array.isArray(this._elements[key])) {
+ var tmp = this._elements[key];
+ this._elements[key] = [tmp];
+ }
+ this._elements[key].push(hook);
+ } else {
+ this._elements[key] = [hook];
+ }
+ }
+ }
+ }
+
+ /**
+ * Refreshes the tab markup based on the current active index.
+ * @private
+ */
+ #refreshActive() {
+ var tabpanels = this.#getCachedTabPanels();
+ var tabs = this.#getCachedTabs();
+ if (tabpanels) {
+ for (var i = 0; i < tabpanels.length; i++) {
+ if(tabs[i]) {
+ if (tabs[i].id === this.#_active) {
+ tabpanels[i].classList.add(this.#_selectors.active.tabpanel);
+ tabpanels[i].removeAttribute("aria-hidden");
+ tabs[i].classList.add(this.#_selectors.active.tab);
+ tabs[i].setAttribute("aria-selected", true);
+ tabs[i].setAttribute("tabindex", "0");
+ tabs[i].setAttribute("aria-current", "true");
+ } else {
+ tabpanels[i].classList.remove(this.#_selectors.active.tabpanel);
+ tabpanels[i].setAttribute("aria-hidden", true);
+ tabs[i].classList.remove(this.#_selectors.active.tab);
+ tabs[i].setAttribute("aria-selected", false);
+ tabs[i].setAttribute("tabindex", "-1");
+ tabs[i].setAttribute("aria-current", "false");
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the id of the active tab, if no tab is active returns 0th element id
+ *
+ * @param {Array} tabs Tab elements
+ * @returns {Number} Id of the active tab, 0th element id if none is active
+ */
+ getActiveTabId(tabs) {
+ if (tabs) {
+ var result = tabs[0].id;
+ for (var i = 0; i < tabs.length; i++) {
+ if (tabs[i].classList.contains(this.#_selectors.active.tab)) {
+ result = tabs[i].id;
+ break;
+ }
+ }
+ return result;
+ }
+ }
+
+ /**
+ * Navigates to the tab at the provided index
+ *
+ * @private
+ * @param {Number} index The index of the tab to navigate to
+ */
+ navigate(index) {
+ this.#_active = index;
+ this.#refreshActive();
+ }
+ }
+ }
+
+ window.Forms = window.Forms || {};
+ window.Forms.CoreComponentsCommons = window.Forms.CoreComponentsCommons || {};
+ window.Forms.CoreComponentsCommons.TabsMixin = TabsMixin;
+
+}());
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/accordion.html b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/accordion.html
index 8d42a320a4..0ad0b906f3 100644
--- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/accordion.html
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/accordion.html
@@ -84,6 +84,6 @@
data-sly-test="${(wcmmode.edit || wcmmode.preview) && accordion.items.size < 1}">
+ data-sly-call="${clientlib.js @ categories='core.forms.components.accordion.v1.contentframe'}"/>
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/commons/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/commons/.content.xml
new file mode 100644
index 0000000000..7f8a033ed9
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/commons/.content.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/commons/js.txt b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/commons/js.txt
new file mode 100644
index 0000000000..9f3b9ebc04
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/commons/js.txt
@@ -0,0 +1,18 @@
+###############################################################################
+# Copyright 2023 Adobe
+#
+# Licensed 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.
+###############################################################################
+
+#base=js
+common.js
\ No newline at end of file
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/commons/js/common.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/commons/js/common.js
new file mode 100644
index 0000000000..0d112b1c02
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/commons/js/common.js
@@ -0,0 +1,260 @@
+/*******************************************************************************
+ * Copyright 2024 Adobe
+ *
+ * Licensed 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.
+ ******************************************************************************/
+
+
+(function () {
+
+ function AccordionMixin(Base) {
+ return class extends Base {
+ static NS = "cmp";
+ static IS = "adaptiveFormAccordion";
+ static bemBlock = 'cmp-accordion';
+ static selectors = {
+ self: "[data-" + this.NS + '-is="' + this.IS + '"]'
+ };
+
+
+ static idSuffixes = {
+ item: "-item",
+ button: "-button",
+ panel: "-panel"
+ }
+
+ static cacheKeys = {
+ buttonKey: "button",
+ panelKey: "panel",
+ itemKey: "item"
+ }
+
+ static cssClasses = {
+ button: {
+ disabled: "cmp-accordion__button--disabled",
+ expanded: "cmp-accordion__button--expanded"
+ },
+ panel: {
+ hidden: "cmp-accordion__panel--hidden",
+ expanded: "cmp-accordion__panel--expanded"
+ }
+ };
+
+ static delay = 100;
+
+ static dataAttributes = {
+ item: {
+ expanded: "data-cmp-expanded"
+ }
+ };
+
+ constructor(params) {
+ super(params);
+ }
+
+ getCachedItems() {
+ return (this._elements[this.constructor.cacheKeys.itemKey] != null) ? this._elements[this.constructor.cacheKeys.itemKey] : [];
+ }
+
+ getCachedPanels() {
+ return this._elements[this.constructor.cacheKeys.panelKey];
+ }
+
+ getCachedButtons() {
+ return this._elements[this.constructor.cacheKeys.buttonKey]
+ }
+
+ getItemById(itemId) {
+ var items = this.getCachedItems();
+ if (items) {
+ for (var i = 0; i < items.length; i++) {
+ if (items[i].id === itemId) {
+ return items[i];
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Returns all expanded items.
+ *
+ * @private
+ * @returns {HTMLElement[]} The expanded items
+ */
+ getExpandedItems() {
+ var expandedItems = [];
+
+ for (var i = 0; i < this.getCachedItems().length; i++) {
+ var item = this.getCachedItems()[i];
+ var expanded = this.isItemExpanded(item);
+ if (expanded) {
+ expandedItems.push(item);
+ }
+ }
+
+ return expandedItems;
+ }
+
+ /**
+ * Gets an item's expanded state.
+ *
+ * @private
+ * @param {HTMLElement} item The item for checking its expanded state
+ * @returns {Boolean} true if the item is expanded, false otherwise
+ */
+ isItemExpanded(item) {
+ return item && item.dataset && item.dataset["cmpExpanded"] !== undefined;
+ }
+
+ /**
+ * Caches the Accordion elements as defined via the {@code data-accordion-hook="ELEMENT_NAME"} markup API.
+ *
+ * @private
+ * @param {HTMLElement} wrapper The Accordion wrapper element
+ */
+ cacheElements(wrapper) {
+ this._elements = {};
+ this._elements.self = wrapper;
+ var hooks = this._elements.self.querySelectorAll("[data-" + this.constructor.NS + "-hook-" + this.constructor.IS + "]");
+
+ for (var i = 0; i < hooks.length; i++) {
+ var hook = hooks[i];
+ if (hook.closest("[data-cmp-is=" + this.constructor.IS + "]") === this._elements.self) { // only process own accordion elements
+ var lowerCased = this.constructor.IS.toLowerCase();
+ var capitalized = lowerCased.charAt(0).toUpperCase() + lowerCased.slice(1);
+ var key = hook.dataset[this.constructor.NS + "Hook" + capitalized];
+ if (this._elements[key]) {
+ if (!Array.isArray(this._elements[key])) {
+ var tmp = this._elements[key];
+ this._elements[key] = [tmp];
+ }
+ this._elements[key].push(hook);
+ } else {
+ this._elements[key] = [hook];
+ }
+ }
+ }
+ }
+
+ collapseAllOtherItems(itemId) {
+ var itemToToggle = this.getItemById(itemId);
+ var itemList = this.getCachedItems();
+ for (var i = 0; i < itemList.length; i++) {
+ if (itemList[i] !== itemToToggle) {
+ var expanded = this.isItemExpanded(itemList[i]);
+ if (expanded) {
+ this.collapseItem(this.getCachedItems()[i]);
+ }
+ }
+ }
+ }
+
+ /**
+ * General handler for toggle of an item.
+ *
+ * @private
+ * @param {Number} id The id of the item to toggle
+ */
+ toggle(id) {
+ var itemToToggle = this.getItemById(id);
+ if (itemToToggle) {
+ (this.isItemExpanded(itemToToggle) === false) ? this.expandItem(itemToToggle) : this.collapseItem(itemToToggle);
+ }
+ }
+
+
+ /**
+ * Refreshes an item based on its expanded state.
+ *
+ * @private
+ * @param {HTMLElement} item The item to refresh
+ */
+ refreshItem(item) {
+ var expanded = this.isItemExpanded(item);
+ if (expanded) {
+ this.expandItem(item);
+ } else {
+ this.collapseItem(item);
+ }
+ }
+
+ /**
+ * Refreshes all items based on their expanded state.
+ *
+ * @private
+ */
+ refreshItems() {
+ for (var i = 0; i < this.getCachedItems().length; i++) {
+ this.refreshItem(this.getCachedItems()[i]);
+ }
+ }
+
+
+ /**
+ * Annotates the item and its internals with
+ * the necessary style and accessibility attributes to indicate it is expanded.
+ *
+ * @private
+ * @param {HTMLElement} item The item to annotate as expanded
+ */
+ expandItem(item) {
+ var index = this.getCachedItems().indexOf(item);
+ if (index > -1) {
+ item.setAttribute(this.constructor.dataAttributes.item.expanded, "");
+ var button = this.getCachedButtons()[index];
+ var panel = this.getCachedPanels()[index];
+ button.classList.add(this.constructor.cssClasses.button.expanded);
+ // used to fix some known screen readers issues in reading the correct state of the 'aria-expanded' attribute
+ // e.g. https://bugs.webkit.org/show_bug.cgi?id=210934
+ setTimeout(function () {
+ button.setAttribute("aria-expanded", true);
+ }, this.constructor.delay);
+ panel.classList.add(this.constructor.cssClasses.panel.expanded);
+ panel.classList.remove(this.constructor.cssClasses.panel.hidden);
+ panel.setAttribute("aria-hidden", false);
+ }
+ }
+
+ /**
+ * Annotates the item and its internals with
+ * the necessary style and accessibility attributes to indicate it is not expanded.
+ *
+ * @private
+ * @param {HTMLElement} item The item to annotate as not expanded
+ */
+ collapseItem(item) {
+ var index = this.getCachedItems().indexOf(item);
+ if (index > -1) {
+ item.removeAttribute(this.constructor.dataAttributes.item.expanded);
+ var button = this.getCachedButtons()[index];
+ var panel = this.getCachedPanels()[index];
+ button.classList.remove(this.constructor.cssClasses.button.expanded);
+ // used to fix some known screen readers issues in reading the correct state of the 'aria-expanded' attribute
+ // e.g. https://bugs.webkit.org/show_bug.cgi?id=210934
+ setTimeout(function () {
+ button.setAttribute("aria-expanded", false);
+ }, this.constructor.delay);
+ panel.classList.add(this.constructor.cssClasses.panel.hidden);
+ panel.classList.remove(this.constructor.cssClasses.panel.expanded);
+ panel.setAttribute("aria-hidden", true);
+ }
+ }
+ }
+ }
+
+ window.Forms = window.Forms || {};
+ window.Forms.CoreComponentsCommons = window.Forms.CoreComponentsCommons || {};
+ window.Forms.CoreComponentsCommons.AccordionMixin = AccordionMixin;
+
+}());
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/contentframe/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/contentframe/.content.xml
new file mode 100644
index 0000000000..3f029c4283
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/contentframe/.content.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/contentframe/js.txt b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/contentframe/js.txt
new file mode 100644
index 0000000000..093ea3890d
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/contentframe/js.txt
@@ -0,0 +1,18 @@
+###############################################################################
+# Copyright 2023 Adobe
+#
+# Licensed 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.
+###############################################################################
+
+#base=js
+accordion.js
\ No newline at end of file
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/contentframe/js/accordion.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/contentframe/js/accordion.js
new file mode 100644
index 0000000000..145a0f21f3
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/contentframe/js/accordion.js
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright 2024 Adobe
+ *
+ * Licensed 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.
+ ******************************************************************************/
+
+
+(function () {
+
+ const AccordionMixin = window.Forms.CoreComponentsCommons.AccordionMixin;
+
+ class Accordion extends AccordionMixin(class {}) {
+
+ constructor(params) {
+ super(params);
+ const { element } = params;
+ this.cacheElements(element);
+ if (this.getCachedItems()) {
+ var expandedItems = this.getExpandedItems();
+ // multiple expanded items annotated, display the last item open.
+ if (expandedItems.length > 1) {
+ var lastExpandedItem = expandedItems[expandedItems.length - 1]
+ this.expandItem(lastExpandedItem);
+ this.collapseAllOtherItems(lastExpandedItem.id);
+ }
+ this.refreshItems();
+ }
+ element.removeAttribute("data-" + this.constructor.NS + "-is");
+
+ if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) {
+ /*
+ * Editor message handling:
+ * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
+ * - check that the message data panel container type is correct and that the id (path) matches this specific Accordion component
+ * - if so, route the "navigate" operation to enact a navigation of the Accordion based on index data
+ */
+ window.CQ.CoreComponents.MESSAGE_CHANNEL = window.CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window);
+ var _self = this;
+ window.CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function (message) {
+ if (message.data && message.data.type === "cmp-accordion" && message.data.id === _self._elements.self.dataset["cmpPanelcontainerId"]) {
+ if (message.data.operation === "navigate" && _self.getCachedItems()[message.data.index] !== undefined) {
+ _self.toggle(_self.getCachedItems()[message.data.index].id);
+ _self.collapseAllOtherItems(_self.getCachedItems()[message.data.index].id);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * Document ready handler and DOM mutation observers. Initializes Tabs components as necessary.
+ *
+ * @private
+ */
+ function onDocumentReady() {
+
+ var elements = document.querySelectorAll(Accordion.selectors.self);
+ for (var i = 0; i < elements.length; i++) {
+ new Accordion({ element: elements[i] });
+ }
+
+ var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
+ var body = document.querySelector("body");
+ var observer = new MutationObserver(function(mutations) {
+ mutations.forEach(function(mutation) {
+ // needed for IE
+ var nodesArray = [].slice.call(mutation.addedNodes);
+ if (nodesArray.length > 0) {
+ nodesArray.forEach(function(addedNode) {
+ if (addedNode.querySelectorAll) {
+ var elementsArray = [].slice.call(addedNode.querySelectorAll(Accordion.selectors.self));
+ elementsArray.forEach(function(element) {
+ new Accordion({ element: element });
+ });
+ }
+ });
+ }
+ });
+ });
+
+ observer.observe(body, {
+ subtree: true,
+ childList: true,
+ characterData: true
+ });
+ }
+
+ if (document.readyState !== "loading") {
+ onDocumentReady();
+ } else {
+ document.addEventListener("DOMContentLoaded", onDocumentReady);
+ }
+}());
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/site/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/site/.content.xml
index e052b09882..b9ceb86eb4 100644
--- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/site/.content.xml
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/site/.content.xml
@@ -19,4 +19,4 @@
allowProxy="{Boolean}true"
categories="[core.forms.components.accordion.v1.runtime]"
jsProcessor="[default:none,min:none]"
- dependencies="[core.wcm.components.commons.site.container,core.forms.components.runtime.base,core.forms.components.container.v2.runtime,core.wcm.components.accordion.v1]"/>
+ dependencies="[core.wcm.components.commons.site.container,core.forms.components.runtime.base,core.forms.components.container.v2.runtime,core.forms.components.accordion.v1.commons]"/>
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/site/js/accordionview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/site/js/accordionview.js
index c624dea2a6..a31e0146f8 100644
--- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/site/js/accordionview.js
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/accordion/v1/accordion/clientlibs/site/js/accordionview.js
@@ -15,11 +15,11 @@
******************************************************************************/
(function () {
- class Accordion extends FormView.FormPanel {
+ const AccordionMixin = window.Forms.CoreComponentsCommons.AccordionMixin;
+
+ class Accordion extends AccordionMixin(FormView.FormPanel) {
static NS = FormView.Constants.NS;
- static IS = "adaptiveFormAccordion";
- static bemBlock = 'cmp-accordion';
static DATA_ATTRIBUTE_VISIBLE = 'data-cmp-visible';
_templateHTML = {};
static selectors = {
@@ -32,29 +32,6 @@
item: `.${Accordion.bemBlock}__item`
};
- static idSuffixes = {
- item: "-item",
- button: "-button",
- panel: "-panel"
- }
-
- static cacheKeys = {
- buttonKey: "button",
- panelKey: "panel",
- itemKey: "item"
- }
-
- static cssClasses = {
- button: {
- disabled: "cmp-accordion__button--disabled",
- expanded: "cmp-accordion__button--expanded"
- },
- panel: {
- hidden: "cmp-accordion__panel--hidden",
- expanded: "cmp-accordion__panel--expanded"
- }
- };
-
static keyCodes = {
ENTER: 13,
SPACE: 32,
@@ -66,47 +43,21 @@
ARROW_DOWN: 40
};
- static delay = 100;
-
- static dataAttributes = {
- item: {
- expanded: "data-cmp-expanded"
- }
- };
-
constructor(params) {
super(params);
const {element} = params;
- this.#cacheElements(element);
- if (this.#getCachedItems()) {
- var expandedItems = this.#getExpandedItems();
+ this.cacheElements(element);
+ if (this.getCachedItems()) {
+ var expandedItems = this.getExpandedItems();
// multiple expanded items annotated, display the last item open.
if (expandedItems.length > 1) {
var lastExpandedItem = expandedItems[expandedItems.length - 1]
- this.#expandItem(lastExpandedItem);
- this.#collapseAllOtherItems(lastExpandedItem.id);
+ this.expandItem(lastExpandedItem);
+ this.collapseAllOtherItems(lastExpandedItem.id);
}
- this.#refreshItems();
+ this.refreshItems();
this.#bindEvents();
}
- if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) {
- /*
- * Editor message handling:
- * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
- * - check that the message data panel container type is correct and that the id (path) matches this specific Accordion component
- * - if so, route the "navigate" operation to enact a navigation of the Accordion based on index data
- */
- window.CQ.CoreComponents.MESSAGE_CHANNEL = window.CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window);
- var _self = this;
- window.CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function (message) {
- if (message.data && message.data.type === "cmp-accordion" && message.data.id === _self._elements.self.dataset["cmpPanelcontainerId"]) {
- if (message.data.operation === "navigate") {
- _self.#toggle(_self.#getCachedItems()[message.data.index].id);
- _self.#collapseAllOtherItems(_self.#getCachedItems()[message.data.index].id);
- }
- }
- });
- }
}
getClass() {
@@ -141,98 +92,37 @@
super.setFocus(id);
this.setActive();
this.#collapseAllItems();
- const item = this.#getItemById(id + '-item');
- this.#expandItem(item)
+ const item = this.getItemById(id + '-item');
+ this.expandItem(item)
}
#collapseAllItems() {
- var items = this.#getCachedItems();
+ var items = this.getCachedItems();
if (items) {
for (var i = 0; i < items.length; i++) {
- if (this.#isItemExpanded(items[i])) {
- this.#collapseItem(items[i])
- }
- }
- }
- }
-
- /**
- * Caches the Accordion elements as defined via the {@code data-accordion-hook="ELEMENT_NAME"} markup API.
- *
- * @private
- * @param {HTMLElement} wrapper The Accordion wrapper element
- */
- #cacheElements(wrapper) {
- this._elements = {};
- this._elements.self = wrapper;
- var hooks = this._elements.self.querySelectorAll("[data-" + Accordion.NS + "-hook-" + Accordion.IS + "]");
-
- for (var i = 0; i < hooks.length; i++) {
- var hook = hooks[i];
- if (hook.closest("[data-cmp-is=" + Accordion.IS + "]") === this._elements.self) { // only process own accordion elements
- var lowerCased = Accordion.IS.toLowerCase();
- var capitalized = lowerCased.charAt(0).toUpperCase() + lowerCased.slice(1);
- var key = hook.dataset[Accordion.NS + "Hook" + capitalized];
- if (this._elements[key]) {
- if (!Array.isArray(this._elements[key])) {
- var tmp = this._elements[key];
- this._elements[key] = [tmp];
- }
- this._elements[key].push(hook);
- } else {
- this._elements[key] = [hook];
+ if (this.isItemExpanded(items[i])) {
+ this.collapseItem(items[i])
}
}
}
}
- /**
- * Returns all expanded items.
- *
- * @private
- * @returns {HTMLElement[]} The expanded items
- */
- #getExpandedItems() {
- var expandedItems = [];
-
- for (var i = 0; i < this.#getCachedItems().length; i++) {
- var item = this.#getCachedItems()[i];
- var expanded = this.#isItemExpanded(item);
- if (expanded) {
- expandedItems.push(item);
- }
- }
-
- return expandedItems;
- }
-
- /**
- * Gets an item's expanded state.
- *
- * @private
- * @param {HTMLElement} item The item for checking its expanded state
- * @returns {Boolean} true if the item is expanded, false otherwise
- */
- #isItemExpanded(item) {
- return item && item.dataset && item.dataset["cmpExpanded"] !== undefined;
- }
-
/**
* Binds Accordion event handling.
*
* @private
*/
#bindEvents() {
- var buttons = this.#getCachedButtons();
+ var buttons = this.getCachedButtons();
if (buttons) {
var _self = this;
for (var i = 0; i < buttons.length; i++) {
(function (index) {
buttons[index].addEventListener("click", function (event) {
var itemDivId = _self.#convertToItemDivId(buttons[index].id);
- _self.#toggle(itemDivId);
- _self.#collapseAllOtherItems(itemDivId);
+ _self.toggle(itemDivId);
+ _self.collapseAllOtherItems(itemDivId);
_self.#focusButton(buttons[index].id);
});
buttons[index].addEventListener("keydown", function (event) {
@@ -254,8 +144,8 @@
var button = this.#getButtonById(buttonId);
button.addEventListener("click", function (event) {
var itemDivId = _self.#convertToItemDivId(buttonId);
- _self.#toggle(itemDivId);
- _self.#collapseAllOtherItems(itemDivId);
+ _self.toggle(itemDivId);
+ _self.collapseAllOtherItems(itemDivId);
_self.#focusButton(buttonId);
});
button.addEventListener("keydown", function (event) {
@@ -271,7 +161,7 @@
* @param {Number} id The id of the button triggering the event
*/
#onButtonKeyDown(event, id) {
- var buttons = this.#getCachedButtons();
+ var buttons = this.getCachedButtons();
var lastIndex = buttons.length - 1;
var index = this.#getButtonIndexById(id);
@@ -302,8 +192,8 @@
case Accordion.keyCodes.SPACE:
event.preventDefault();
var itemDivId = this.#convertToItemDivId(buttons[index].id);
- this.#toggle(itemDivId);
- this.#collapseAllOtherItems(itemDivId);
+ this.toggle(itemDivId);
+ this.collapseAllOtherItems(itemDivId);
this.#focusButton(buttons[index].id);
break;
default:
@@ -311,96 +201,6 @@
}
}
- /**
- * General handler for toggle of an item.
- *
- * @private
- * @param {Number} id The id of the item to toggle
- */
- #toggle(id) {
- var itemToToggle = this.#getItemById(id);
- if (itemToToggle) {
- (this.#isItemExpanded(itemToToggle) === false) ? this.#expandItem(itemToToggle) : this.#collapseItem(itemToToggle);
- }
- }
-
- /**
- * Refreshes an item based on its expanded state.
- *
- * @private
- * @param {HTMLElement} item The item to refresh
- */
- #refreshItem(item) {
- var expanded = this.#isItemExpanded(item);
- if (expanded) {
- this.#expandItem(item);
- } else {
- this.#collapseItem(item);
- }
- }
-
- /**
- * Refreshes all items based on their expanded state.
- *
- * @private
- */
- #refreshItems() {
- for (var i = 0; i < this.#getCachedItems().length; i++) {
- this.#refreshItem(this.#getCachedItems()[i]);
- }
- }
-
-
- /**
- * Annotates the item and its internals with
- * the necessary style and accessibility attributes to indicate it is expanded.
- *
- * @private
- * @param {HTMLElement} item The item to annotate as expanded
- */
- #expandItem(item) {
- var index = this.#getCachedItems().indexOf(item);
- if (index > -1) {
- item.setAttribute(Accordion.dataAttributes.item.expanded, "");
- var button = this.#getCachedButtons()[index];
- var panel = this.#getCachedPanels()[index];
- button.classList.add(Accordion.cssClasses.button.expanded);
- // used to fix some known screen readers issues in reading the correct state of the 'aria-expanded' attribute
- // e.g. https://bugs.webkit.org/show_bug.cgi?id=210934
- setTimeout(function () {
- button.setAttribute("aria-expanded", true);
- }, Accordion.delay);
- panel.classList.add(Accordion.cssClasses.panel.expanded);
- panel.classList.remove(Accordion.cssClasses.panel.hidden);
- panel.setAttribute("aria-hidden", false);
- }
- }
-
- /**
- * Annotates the item and its internals with
- * the necessary style and accessibility attributes to indicate it is not expanded.
- *
- * @private
- * @param {HTMLElement} item The item to annotate as not expanded
- */
- #collapseItem(item) {
- var index = this.#getCachedItems().indexOf(item);
- if (index > -1) {
- item.removeAttribute(Accordion.dataAttributes.item.expanded);
- var button = this.#getCachedButtons()[index];
- var panel = this.#getCachedPanels()[index];
- button.classList.remove(Accordion.cssClasses.button.expanded);
- // used to fix some known screen readers issues in reading the correct state of the 'aria-expanded' attribute
- // e.g. https://bugs.webkit.org/show_bug.cgi?id=210934
- setTimeout(function () {
- button.setAttribute("aria-expanded", false);
- }, Accordion.delay);
- panel.classList.add(Accordion.cssClasses.panel.hidden);
- panel.classList.remove(Accordion.cssClasses.panel.expanded);
- panel.setAttribute("aria-hidden", true);
- }
- }
-
/**
* Focuses the button at the provided index.
*
@@ -446,31 +246,31 @@
handleChildAddition(childView) {
var itemDivToExpand;
- this.#cacheElements(this._elements.self);
+ this.cacheElements(this._elements.self);
this.#bindEventsToAddedChild(childView.id);
if (childView.getInstanceManager().getModel().minOccur != undefined && childView.getInstanceManager().children.length > childView.getInstanceManager().getModel().minOccur) {
- itemDivToExpand = this.#getItemById(childView.id + Accordion.idSuffixes.item);
+ itemDivToExpand = this.getItemById(childView.id + Accordion.idSuffixes.item);
} else {
//this will run at initial runtime loading when the repeatable panel is being added minOccur no of times.
// in this case we want the focus to stay at first tab
- itemDivToExpand = this.findFirstVisibleChild(this.#getCachedItems());
+ itemDivToExpand = this.findFirstVisibleChild(this.getCachedItems());
}
- this.#expandItem(itemDivToExpand);
- this.#collapseAllOtherItems(itemDivToExpand.id);
+ this.expandItem(itemDivToExpand);
+ this.collapseAllOtherItems(itemDivToExpand.id);
this.#showHideRepeatableButtons(childView.getInstanceManager());
}
handleChildRemoval(removedInstanceView) {
var removedAccordionItemDivId = removedInstanceView.element.id + Accordion.idSuffixes.item;
- var removedAccordionItemDiv = this.#getItemById(removedAccordionItemDivId);
+ var removedAccordionItemDiv = this.getItemById(removedAccordionItemDivId);
removedAccordionItemDiv.remove();
this.children.splice(this.children.indexOf(removedInstanceView), 1);
- this.#cacheElements(this._elements.self);
- var cachedItems = this.#getCachedItems();
+ this.cacheElements(this._elements.self);
+ var cachedItems = this.getCachedItems();
if (cachedItems && cachedItems.length > 0) {
var firstItem = cachedItems[0];
- this.#expandItem(firstItem);
- this.#collapseAllOtherItems(firstItem.id);
+ this.expandItem(firstItem);
+ this.collapseAllOtherItems(firstItem.id);
}
this.#showHideRepeatableButtons(removedInstanceView.getInstanceManager());
}
@@ -485,13 +285,13 @@
syncMarkupWithModel() {
super.syncMarkupWithModel();
this.#syncLabel();
- for (var itemDiv of this.#getCachedItems()) {
+ for (var itemDiv of this.getCachedItems()) {
this.#syncAccordionMarkup(itemDiv);
}
}
getChildViewByIndex(index) {
- var accordionPanels = this.#getCachedPanels();
+ var accordionPanels = this.getCachedPanels();
var fieldId = accordionPanels[index].id.substring(0, accordionPanels[index].id.lastIndexOf("-"));
return this.getChild(fieldId);
}
@@ -504,7 +304,7 @@
var closestRepeatableFieldInstanceManagerIds = this._templateHTML[instanceManagerId]['closestRepeatableFieldInstanceManagerIds'];
var indexToInsert = this.getIndexToInsert(closestNonRepeatableFieldId, closestRepeatableFieldInstanceManagerIds);
if (indexToInsert > 0) {
- result.beforeViewElement = this.#getCachedItems()[indexToInsert - 1];
+ result.beforeViewElement = this.getCachedItems()[indexToInsert - 1];
} else {
result.parentElement = this.element;
}
@@ -559,51 +359,14 @@
if (childView.getInstanceManager() != null && (this._templateHTML == null || this._templateHTML[childView.getInstanceManager().getId()] == null)) {
var accordionItemDivId = childView.element.id + Accordion.idSuffixes.item;
var instanceManagerId = childView.getInstanceManager().getId();
- var accordionItemDiv = this.#getItemById(accordionItemDivId);
+ var accordionItemDiv = this.getItemById(accordionItemDivId);
this._templateHTML[instanceManagerId] = {};
this._templateHTML[instanceManagerId]['accordionItemDiv'] = accordionItemDiv;
}
}
- #collapseAllOtherItems(itemId) {
- var itemToToggle = this.#getItemById(itemId);
- var itemList = this.#getCachedItems();
- for (var i = 0; i < itemList.length; i++) {
- if (itemList[i] !== itemToToggle) {
- var expanded = this.#isItemExpanded(itemList[i]);
- if (expanded) {
- this.#collapseItem(this.#getCachedItems()[i]);
- }
- }
- }
- }
-
-
- #getCachedItems() {
- return (this._elements[Accordion.cacheKeys.itemKey] != null) ? this._elements[Accordion.cacheKeys.itemKey] : [];
- }
-
- #getCachedPanels() {
- return this._elements[Accordion.cacheKeys.panelKey];
- }
-
- #getCachedButtons() {
- return this._elements[Accordion.cacheKeys.buttonKey]
- }
-
- #getItemById(itemId) {
- var items = this.#getCachedItems();
- if (items) {
- for (var i = 0; i < items.length; i++) {
- if (items[i].id === itemId) {
- return items[i];
- }
- }
- }
- }
-
#getButtonById(buttonId) {
- var buttons = this.#getCachedButtons();
+ var buttons = this.getCachedButtons();
if (buttons) {
for (var i = 0; i < buttons.length; i++) {
if (buttons[i].id === buttonId) {
@@ -614,7 +377,7 @@
}
#getButtonIndexById(buttonId) {
- var buttons = this.#getCachedButtons();
+ var buttons = this.getCachedButtons();
if (buttons) {
for (var i = 0; i < buttons.length; i++) {
if (buttons[i].id === buttonId) {
@@ -656,17 +419,17 @@
}
updateChildVisibility(visible, state) {
- this.updateVisibilityOfNavigationElement(this.#getItemById(state.id + Accordion.idSuffixes.item), visible);
+ this.updateVisibilityOfNavigationElement(this.getItemById(state.id + Accordion.idSuffixes.item), visible);
if (!visible) {
- var expandedItems = this.#getExpandedItems();
+ var expandedItems = this.getExpandedItems();
for (let i = 0; i < expandedItems.length; i++) {
if (expandedItems[i].getAttribute(Accordion.DATA_ATTRIBUTE_VISIBLE) === 'false') {
- this.#collapseItem(expandedItems[i]);
+ this.collapseItem(expandedItems[i]);
}
}
- let child = this.findFirstVisibleChild(this.#getCachedItems());
+ let child = this.findFirstVisibleChild(this.getCachedItems());
if (child) {
- this.#expandItem(child);
+ this.expandItem(child);
}
}
}
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/clientlibs/contentframe/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/clientlibs/contentframe/.content.xml
new file mode 100644
index 0000000000..0e3dd79b23
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/clientlibs/contentframe/.content.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/clientlibs/contentframe/js.txt b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/clientlibs/contentframe/js.txt
new file mode 100644
index 0000000000..7cb945cd83
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/clientlibs/contentframe/js.txt
@@ -0,0 +1,18 @@
+###############################################################################
+# Copyright 2023 Adobe
+#
+# Licensed 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.
+###############################################################################
+
+#base=js
+tabs.js
\ No newline at end of file
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/clientlibs/contentframe/js/tabs.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/clientlibs/contentframe/js/tabs.js
new file mode 100644
index 0000000000..be37e3d278
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/clientlibs/contentframe/js/tabs.js
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright 2024 Adobe
+ *
+ * Licensed 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.
+ ******************************************************************************/
+
+
+(function () {
+
+ const TabsMixin = window.Forms.CoreComponentsCommons.TabsMixin;
+
+ class Tabs extends TabsMixin(class {}) {
+ static NS = "cmp";
+ static IS = "adaptiveFormTabs";
+ static bemBlock = "cmp-tabs";
+ static selectors = {
+ self: "[data-" + this.NS + '-is="' + this.IS + '"]',
+ active: {
+ tab: "cmp-tabs__tab--active",
+ tabpanel: "cmp-tabs__tabpanel--active"
+ },
+ };
+
+ constructor(params) {
+ super(params, Tabs.NS, Tabs.IS, Tabs.selectors)
+ params.element.removeAttribute("data-" + Tabs.NS + "-is");
+
+ if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) {
+ /*
+ * Editor message handling:
+ * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
+ * - check that the message data panel container type is correct and that the id (path) matches this specific Tabs component
+ * - if so, route the "navigate" operation to enact a navigation of the Tabs based on index data
+ */
+ CQ.CoreComponents.MESSAGE_CHANNEL = CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window);
+ var _self = this;
+ CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function (message) {
+ if (message.data && message.data.type === "cmp-tabs" && message.data.id === _self._elements.self.dataset["cmpPanelcontainerId"]) {
+ if (message.data.operation === "navigate" && _self._elements["tab"][message.data.index] !== undefined) {
+ _self.navigate(_self._elements["tab"][message.data.index].id);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * Document ready handler and DOM mutation observers. Initializes Tabs components as necessary.
+ *
+ * @private
+ */
+ function onDocumentReady() {
+
+ var elements = document.querySelectorAll(Tabs.selectors.self);
+ for (var i = 0; i < elements.length; i++) {
+ new Tabs({ element: elements[i] });
+ }
+
+ var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
+ var body = document.querySelector("body");
+ var observer = new MutationObserver(function(mutations) {
+ mutations.forEach(function(mutation) {
+ // needed for IE
+ var nodesArray = [].slice.call(mutation.addedNodes);
+ if (nodesArray.length > 0) {
+ nodesArray.forEach(function(addedNode) {
+ if (addedNode.querySelectorAll) {
+ var elementsArray = [].slice.call(addedNode.querySelectorAll(Tabs.selectors.self));
+ elementsArray.forEach(function(element) {
+ new Tabs({ element: element });
+ });
+ }
+ });
+ }
+ });
+ });
+
+ observer.observe(body, {
+ subtree: true,
+ childList: true,
+ characterData: true
+ });
+ }
+
+ if (document.readyState !== "loading") {
+ onDocumentReady();
+ } else {
+ document.addEventListener("DOMContentLoaded", onDocumentReady);
+ }
+}());
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/clientlibs/site/js/tabs.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/clientlibs/site/js/tabs.js
index 13c323cb4f..4dd738e70b 100644
--- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/clientlibs/site/js/tabs.js
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/clientlibs/site/js/tabs.js
@@ -37,23 +37,6 @@
constructor(params) {
super(params, Tabs.NS, Tabs.IS, Tabs.selectors);
- if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) {
- /*
- * Editor message handling:
- * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
- * - check that the message data panel container type is correct and that the id (path) matches this specific Tabs component
- * - if so, route the "navigate" operation to enact a navigation of the Tabs based on index data
- */
- CQ.CoreComponents.MESSAGE_CHANNEL = CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window);
- var _self = this;
- CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function (message) {
- if (message.data && message.data.type === "cmp-tabs" && message.data.id === _self._elements.self.dataset["cmpPanelcontainerId"]) {
- if (message.data.operation === "navigate" && _self._elements["tab"][message.data.index] != undefined) {
- _self.navigate(_self._elements["tab"][message.data.index].id);
- }
- }
- });
- }
}
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/tabsontop.html b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/tabsontop.html
index ab946ee8f5..c86f0a19c5 100644
--- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/tabsontop.html
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/tabsontop/v1/tabsontop/tabsontop.html
@@ -63,6 +63,6 @@
data-sly-test="${(wcmmode.edit || wcmmode.preview)}">
-
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/clientlibs/contentframe/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/clientlibs/contentframe/.content.xml
new file mode 100644
index 0000000000..edb9403aa3
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/clientlibs/contentframe/.content.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/clientlibs/contentframe/js.txt b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/clientlibs/contentframe/js.txt
new file mode 100644
index 0000000000..2702421cd2
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/clientlibs/contentframe/js.txt
@@ -0,0 +1,18 @@
+###############################################################################
+# Copyright 2024 Adobe
+#
+# Licensed 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.
+###############################################################################
+
+#base=js
+verticaltabs.js
\ No newline at end of file
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/clientlibs/contentframe/js/verticaltabs.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/clientlibs/contentframe/js/verticaltabs.js
new file mode 100644
index 0000000000..4db1b36749
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/clientlibs/contentframe/js/verticaltabs.js
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright 2024 Adobe
+ *
+ * Licensed 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.
+ ******************************************************************************/
+
+
+(function () {
+
+ const TabsMixin = window.Forms.CoreComponentsCommons.TabsMixin;
+
+ class VerticalTabs extends TabsMixin(class {}) {
+ static NS = "cmp";
+ static IS = "adaptiveFormVerticalTabs";
+ static bemBlock = "cmp-verticaltabs";
+ static selectors = {
+ self: "[data-" + this.NS + '-is="' + this.IS + '"]',
+ active: {
+ tab: "cmp-verticaltabs__tab--active",
+ tabpanel: "cmp-verticaltabs__tabpanel--active"
+ },
+ };
+
+ constructor(params) {
+ super(params, VerticalTabs.NS, VerticalTabs.IS, VerticalTabs.selectors)
+ params.element.removeAttribute("data-" + VerticalTabs.NS + "-is");
+
+ if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) {
+ /*
+ * Editor message handling:
+ * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
+ * - check that the message data panel container type is correct and that the id (path) matches this specific Tabs component
+ * - if so, route the "navigate" operation to enact a navigation of the Tabs based on index data
+ */
+ CQ.CoreComponents.MESSAGE_CHANNEL = CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window);
+ var _self = this;
+ CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function (message) {
+ if (message.data && message.data.type === "cmp-verticaltabs" && message.data.id === _self._elements.self.dataset["cmpPanelcontainerId"]) {
+ if (message.data.operation === "navigate" && _self._elements["tab"][message.data.index] !== undefined) {
+ _self.navigate(_self._elements["tab"][message.data.index].id);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * Document ready handler and DOM mutation observers. Initializes Tabs components as necessary.
+ *
+ * @private
+ */
+ function onDocumentReady() {
+
+ var elements = document.querySelectorAll(VerticalTabs.selectors.self);
+ for (var i = 0; i < elements.length; i++) {
+ new VerticalTabs({ element: elements[i] });
+ }
+
+ var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
+ var body = document.querySelector("body");
+ var observer = new MutationObserver(function(mutations) {
+ mutations.forEach(function(mutation) {
+ // needed for IE
+ var nodesArray = [].slice.call(mutation.addedNodes);
+ if (nodesArray.length > 0) {
+ nodesArray.forEach(function(addedNode) {
+ if (addedNode.querySelectorAll) {
+ var elementsArray = [].slice.call(addedNode.querySelectorAll(VerticalTabs.selectors.self));
+ elementsArray.forEach(function(element) {
+ new VerticalTabs({ element: element });
+ });
+ }
+ });
+ }
+ });
+ });
+
+ observer.observe(body, {
+ subtree: true,
+ childList: true,
+ characterData: true
+ });
+ }
+
+ if (document.readyState !== "loading") {
+ onDocumentReady();
+ } else {
+ document.addEventListener("DOMContentLoaded", onDocumentReady);
+ }
+}());
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/clientlibs/site/js/verticaltabs.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/clientlibs/site/js/verticaltabs.js
index 3b272b089d..69667ae682 100644
--- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/clientlibs/site/js/verticaltabs.js
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/clientlibs/site/js/verticaltabs.js
@@ -37,23 +37,6 @@
constructor(params) {
super(params, VerticalTabs.NS, VerticalTabs.IS, VerticalTabs.selectors);
- if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) {
- /*
- * Editor message handling:
- * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
- * - check that the message data panel container type is correct and that the id (path) matches this specific Tabs component
- * - if so, route the "navigate" operation to enact a navigation of the Tabs based on index data
- */
- CQ.CoreComponents.MESSAGE_CHANNEL = CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window);
- var _self = this;
- CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function (message) {
- if (message.data && message.data.type === "cmp-verticaltabs" && message.data.id === _self._elements.self.dataset["cmpPanelcontainerId"]) {
- if (message.data.operation === "navigate" && _self._elements["tab"][message.data.index] != undefined) {
- _self.navigate(_self._elements["tab"][message.data.index].id);
- }
- }
- });
- }
}
getClass() {
@@ -63,7 +46,9 @@
setFocus(id) {
super.setFocus(id);
this.setActive();
- this.navigateAndFocusTab(id + '__tab');
+ if(id) {
+ this.navigateAndFocusTab(id + '__tab');
+ }
}
getWidget() {
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/verticaltabs.html b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/verticaltabs.html
index e6c810e3df..ea042f2561 100644
--- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/verticaltabs.html
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/verticaltabs/v1/verticaltabs/verticaltabs.html
@@ -64,6 +64,6 @@
data-sly-test="${(wcmmode.edit || wcmmode.preview)}">
-
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/commons/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/commons/.content.xml
new file mode 100644
index 0000000000..118c0b592c
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/commons/.content.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/commons/js.txt b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/commons/js.txt
new file mode 100644
index 0000000000..90e023d251
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/commons/js.txt
@@ -0,0 +1,18 @@
+###############################################################################
+# Copyright 2024 Adobe
+#
+# Licensed 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.
+###############################################################################
+
+#base=js
+common.js
\ No newline at end of file
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/commons/js/common.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/commons/js/common.js
new file mode 100644
index 0000000000..061e27e306
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/commons/js/common.js
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright 2024 Adobe
+ *
+ * Licensed 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.
+ ******************************************************************************/
+
+
+(function () {
+
+ function WizardMixin(Base) {
+ return class extends Base {
+ static NS = "cmp";
+ static IS = "adaptiveFormWizard";
+ static bemBlock = "cmp-adaptiveform-wizard";
+ static DATA_ATTRIBUTE_VISIBLE = 'data-cmp-visible';
+
+ static selectors = {
+ self: "[data-" + this.NS + '-is="' + this.IS + '"]',
+ active: {
+ tab: "cmp-adaptiveform-wizard__tab--active",
+ wizardpanel: "cmp-adaptiveform-wizard__wizardpanel--active"
+ }
+ };
+
+ _active;
+
+ constructor(params) {
+ super(params);
+ }
+
+ /**
+ * Caches the Tabs elements as defined via the {@code data-tabs-hook="ELEMENT_NAME"} markup API
+ *
+ * @private
+ * @param {HTMLElement} wrapper The Tabs wrapper element
+ */
+ cacheElements(wrapper) {
+ this._elements = {};
+ this._elements.self = wrapper;
+ const hooks = this._elements.self.querySelectorAll("[data-" + this.constructor.NS + "-hook-" + this.constructor.IS + "]");
+
+ for (let i = 0; i < hooks.length; i++) {
+ let hook = hooks[i];
+ if (hook.closest("[data-cmp-is=" + this.constructor.IS + "]") === this._elements.self) { // only process own tab elements
+ let key = hook.dataset[this.constructor.NS + "Hook" + "Adaptiveformwizard"];
+ if (this._elements[key]) {
+ if (!Array.isArray(this._elements[key])) {
+ let tmp = this._elements[key];
+ this._elements[key] = [tmp];
+ }
+ this._elements[key].push(hook);
+ } else {
+ this._elements[key] = [hook];
+ }
+ }
+ }
+ }
+
+ setActive(tabs) {
+ if (tabs) {
+ tabs[0].classList.add(this.constructor.selectors.active.tab);
+ }
+ }
+
+ /**
+ * Returns the index of the active tab, if no tab is active returns 0
+ *
+ * @param {Array} tabs Tab elements
+ * @returns {Number} Index of the active tab, 0 if none is active
+ */
+ getActiveIndex(tabs) {
+ if (tabs) {
+ for (let i = 0; i < tabs.length; i++) {
+ if (tabs[i].classList.contains(this.constructor.selectors.active.tab)) {
+ return i;
+ }
+ }
+ }
+ return 0;
+ }
+
+ getCachedTabs() {
+ return this._elements["tab"];
+ }
+
+ getCachedWizardPanels() {
+ return this._elements["wizardpanel"]
+ }
+
+ /**
+ * Navigates to the tab at the provided index
+ *
+ * @private
+ * @param {Number} index The index of the tab to navigate to
+ */
+ navigate(index) {
+ this._active = index;
+ this.refreshActive();
+ }
+
+ /**
+ * Refreshes the tab markup based on the current {@code Tabs_active} index
+ *
+ * @private
+ */
+ refreshActive() {
+ const wizardPanels = this.getCachedWizardPanels();
+ const tabs = this.getCachedTabs();
+ if (wizardPanels) {
+ for (let i = 0; i < wizardPanels.length; i++) {
+ if( wizardPanels[i] && tabs[i]) {
+ if (i === parseInt(this._active)) {
+ wizardPanels[i].classList.add(this.constructor.selectors.active.wizardpanel);
+ wizardPanels[i].removeAttribute("aria-hidden");
+ tabs[i].classList.add(this.constructor.selectors.active.tab);
+ tabs[i].setAttribute("aria-selected", true);
+ tabs[i].setAttribute("tabindex", "0");
+ } else {
+ wizardPanels[i].classList.remove(this.constructor.selectors.active.wizardpanel);
+ wizardPanels[i].setAttribute("aria-hidden", true);
+ tabs[i].classList.remove(this.constructor.selectors.active.tab);
+ tabs[i].setAttribute("aria-selected", false);
+ tabs[i].setAttribute("tabindex", "-1");
+ }
+ }
+ }
+ }
+ if (this.hideUnhideNavButtons) {
+ this.hideUnhideNavButtons(this._active);
+ }
+ }
+ }
+ }
+
+ window.Forms = window.Forms || {};
+ window.Forms.CoreComponentsCommons = window.Forms.CoreComponentsCommons || {};
+ window.Forms.CoreComponentsCommons.WizardMixin = WizardMixin;
+
+}());
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/contentframe/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/contentframe/.content.xml
new file mode 100644
index 0000000000..abbbd1c97a
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/contentframe/.content.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/contentframe/js.txt b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/contentframe/js.txt
new file mode 100644
index 0000000000..fd5429b6f7
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/contentframe/js.txt
@@ -0,0 +1,18 @@
+###############################################################################
+# Copyright 2024 Adobe
+#
+# Licensed 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.
+###############################################################################
+
+#base=js
+wizard.js
\ No newline at end of file
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/contentframe/js/wizard.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/contentframe/js/wizard.js
new file mode 100644
index 0000000000..bb8a2932ef
--- /dev/null
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/contentframe/js/wizard.js
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright 2024 Adobe
+ *
+ * Licensed 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.
+ ******************************************************************************/
+
+
+(function () {
+
+ const WizardMixin = window.Forms.CoreComponentsCommons.WizardMixin;
+
+ class Wizard extends WizardMixin(class {}) {
+
+ constructor(params) {
+ super(params);
+ const {element} = params;
+ this.cacheElements(element);
+ this.setActive(this.getCachedTabs())
+ this._active = this.getActiveIndex(this.getCachedTabs());
+ this.refreshActive();
+
+ element.removeAttribute("data-" + Wizard.NS + "-is");
+
+ if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) {
+ /*
+ * Editor message handling:
+ * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
+ * - check that the message data panel container type is correct and that the id (path) matches this specific Tabs component
+ * - if so, route the "navigate" operation to enact a navigation of the Tabs based on index data
+ */
+ CQ.CoreComponents.MESSAGE_CHANNEL = CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window);
+ const _self = this;
+ CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function (message) {
+ if (message.data && message.data.type === "cmp-adaptiveform-wizard" && message.data.id === _self._elements.self.dataset["cmpPanelcontainerId"]) {
+ if (message.data.operation === "navigate") {
+ _self.navigate(message.data.index);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * Document ready handler and DOM mutation observers. Initializes Tabs components as necessary.
+ *
+ * @private
+ */
+ function onDocumentReady() {
+
+ var elements = document.querySelectorAll(Wizard.selectors.self);
+ for (var i = 0; i < elements.length; i++) {
+ new Wizard({ element: elements[i] });
+ }
+
+ var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
+ var body = document.querySelector("body");
+ var observer = new MutationObserver(function(mutations) {
+ mutations.forEach(function(mutation) {
+ // needed for IE
+ var nodesArray = [].slice.call(mutation.addedNodes);
+ if (nodesArray.length > 0) {
+ nodesArray.forEach(function(addedNode) {
+ if (addedNode.querySelectorAll) {
+ var elementsArray = [].slice.call(addedNode.querySelectorAll(Wizard.selectors.self));
+ elementsArray.forEach(function(element) {
+ new Wizard({ element: element });
+ });
+ }
+ });
+ }
+ });
+ });
+
+ observer.observe(body, {
+ subtree: true,
+ childList: true,
+ characterData: true
+ });
+ }
+
+ if (document.readyState !== "loading") {
+ onDocumentReady();
+ } else {
+ document.addEventListener("DOMContentLoaded", onDocumentReady);
+ }
+}());
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/site/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/site/.content.xml
index ca7663dbfc..f783007439 100644
--- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/site/.content.xml
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/site/.content.xml
@@ -19,5 +19,5 @@
allowProxy="{Boolean}true"
categories="[core.forms.components.wizard.v1.runtime]"
jsProcessor="[default:none,min:none]"
- dependencies="[core.forms.components.runtime.base,core.forms.components.container.v2.runtime,core.wcm.components.commons.site.container]"
+ dependencies="[core.forms.components.runtime.base,core.forms.components.container.v2.runtime,core.wcm.components.commons.site.container,core.forms.components.wizard.v1.commons]"
/>
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/site/js/wizardview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/site/js/wizardview.js
index 815bd476fa..903a16b793 100644
--- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/site/js/wizardview.js
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/clientlibs/site/js/wizardview.js
@@ -25,20 +25,15 @@
ARROW_DOWN: 40
};
+ const WizardMixin = window.Forms.CoreComponentsCommons.WizardMixin;
- class Wizard extends FormView.FormPanel {
+ class Wizard extends WizardMixin(FormView.FormPanel) {
_templateHTML = {};
- #_active;
static NS = FormView.Constants.NS;
- static IS = "adaptiveFormWizard";
- static bemBlock = "cmp-adaptiveform-wizard";
static #tabIdSuffix = "_wizard-item-nav";
static #wizardPanelIdSuffix = "__wizardpanel";
- maxEnabledTab = 0;
- minEnabledTab = 0;
- static DATA_ATTRIBUTE_VISIBLE = 'data-cmp-visible';
static selectors = {
self: "[data-" + Wizard.NS + '-is="' + Wizard.IS + '"]',
@@ -63,59 +58,14 @@
constructor(params) {
super(params);
const {element} = params;
- this.#cacheElements(element);
- this.#setActive(this.#getCachedTabs())
- this.#_active = this.#getActiveIndex(this.#getCachedTabs());
+ this.cacheElements(element);
+ this.setActive(this.getCachedTabs())
+ this._active = this.getActiveIndex(this.getCachedTabs());
this.#setNavigationRange();
- this.#hideUnhideNavButtons(this.#_active);
- this.#refreshActive();
+ this.#hideUnhideNavButtons(this._active);
+ this.refreshActive();
this.#bindEvents();
- if (window.Granite && window.Granite.author && window.Granite.author.MessageChannel) {
- /*
- * Editor message handling:
- * - subscribe to "cmp.panelcontainer" message requests sent by the editor frame
- * - check that the message data panel container type is correct and that the id (path) matches this specific Tabs component
- * - if so, route the "navigate" operation to enact a navigation of the Tabs based on index data
- */
- CQ.CoreComponents.MESSAGE_CHANNEL = CQ.CoreComponents.MESSAGE_CHANNEL || new window.Granite.author.MessageChannel("cqauthor", window);
- const _self = this;
- CQ.CoreComponents.MESSAGE_CHANNEL.subscribeRequestMessage("cmp.panelcontainer", function (message) {
- if (message.data && message.data.type === "cmp-adaptiveform-wizard" && message.data.id === _self._elements.self.dataset["cmpPanelcontainerId"]) {
- if (message.data.operation === "navigate") {
- _self.#navigate(message.data.index);
- }
- }
- });
- }
- }
-
- /**
- * Caches the Tabs elements as defined via the {@code data-tabs-hook="ELEMENT_NAME"} markup API
- *
- * @private
- * @param {HTMLElement} wrapper The Tabs wrapper element
- */
- #cacheElements(wrapper) {
- this._elements = {};
- this._elements.self = wrapper;
- const hooks = this._elements.self.querySelectorAll("[data-" + Wizard.NS + "-hook-" + Wizard.IS + "]");
-
- for (let i = 0; i < hooks.length; i++) {
- let hook = hooks[i];
- if (hook.closest("[data-cmp-is=" + Wizard.IS + "]") === this._elements.self) { // only process own tab elements
- let key = hook.dataset[Wizard.NS + "Hook" + "Adaptiveformwizard"];
- if (this._elements[key]) {
- if (!Array.isArray(this._elements[key])) {
- let tmp = this._elements[key];
- this._elements[key] = [tmp];
- }
- this._elements[key].push(hook);
- } else {
- this._elements[key] = [hook];
- }
- }
- }
}
getClass() {
@@ -126,7 +76,7 @@
super.setFocus(id);
this.setActive();
const index = this.#getTabIndexById(id + '_wizard-item-nav');
- this.#navigate(index);
+ this.navigate(index);
}
getWidget() {
@@ -183,30 +133,6 @@
}
- /**
- * Returns the index of the active tab, if no tab is active returns 0
- *
- * @param {Array} tabs Tab elements
- * @returns {Number} Index of the active tab, 0 if none is active
- */
- #getActiveIndex(tabs) {
- if (tabs) {
- for (let i = 0; i < tabs.length; i++) {
- if (tabs[i].classList.contains(Wizard.selectors.active.tab)) {
- return i;
- }
- }
- }
- return 0;
- }
-
-
- #setActive(tabs) {
- if (tabs) {
- tabs[0].classList.add(Wizard.selectors.active.tab);
- }
- }
-
/**
* Handles tab keydown events
*
@@ -214,9 +140,9 @@
* @param {Object} event The keydown event
*/
#onKeyDown(event) {
- const index = this.#_active;
+ const index = this._active;
- const lastIndex = this.#getCachedTabs().length - 1;
+ const lastIndex = this.getCachedTabs().length - 1;
switch (event.keyCode) {
case keyCodes.ARROW_LEFT:
@@ -247,33 +173,13 @@
}
/**
- * Refreshes the tab markup based on the current {@code Tabs#_active} index
+ * Refreshes the tab markup based on the current {@code Tabs_active} index
*
* @private
*/
- #refreshActive() {
- const wizardPanels = this.#getCachedWizardPanels();
- const tabs = this.#getCachedTabs();
- if (wizardPanels) {
- for (let i = 0; i < wizardPanels.length; i++) {
- if(tabs[i]) {
- if (i === parseInt(this.#_active)) {
- wizardPanels[i].classList.add(Wizard.selectors.active.wizardpanel);
- wizardPanels[i].removeAttribute(FormView.Constants.ARIA_HIDDEN);
- tabs[i].classList.add(Wizard.selectors.active.tab);
- tabs[i].setAttribute(FormView.Constants.ARIA_SELECTED, true);
- tabs[i].setAttribute(FormView.Constants.TABINDEX, "0");
- } else {
- wizardPanels[i].classList.remove(Wizard.selectors.active.wizardpanel);
- wizardPanels[i].setAttribute(FormView.Constants.ARIA_HIDDEN, true);
- tabs[i].classList.remove(Wizard.selectors.active.tab);
- tabs[i].setAttribute(FormView.Constants.ARIA_SELECTED, false);
- tabs[i].setAttribute(FormView.Constants.TABINDEX, "-1");
- }
- }
- }
- }
- this.#hideUnhideNavButtons(this.#_active);
+ refreshActive() {
+ super.refreshActive();
+ this.#hideUnhideNavButtons(this._active);
}
/**
@@ -290,8 +196,8 @@
#navigateToNextTab() {
- const activeIndex = this.#_active;
- const activeTabElement = this.#getCachedTabs()[activeIndex];
+ const activeIndex = this._active;
+ const activeTabElement = this.getCachedTabs()[activeIndex];
const activeChildId = activeTabElement.id.substring(0, activeTabElement.id.lastIndexOf(Wizard.#tabIdSuffix));
const activeChildView = this.getChild(activeChildId);
let activeChildModel;
@@ -306,13 +212,13 @@
validationErrorList = activeChildModel.validate();
}
if (validationErrorList === undefined || validationErrorList.length == 0) {
- let tabs = this.#getCachedTabs();
+ let tabs = this.getCachedTabs();
let nextVisibleIndex = this.#findNextVisibleChildIndex(activeIndex);
if (tabs && nextVisibleIndex >= 0) {
this.#navigateAndFocusTab(nextVisibleIndex);
}
}
- this.#hideUnhideNavButtons(this.#_active);
+ this.#hideUnhideNavButtons(this._active);
}
#isAuthoring() {
@@ -320,13 +226,13 @@
}
#navigateToPreviousTab() {
- const activeIndex = this.#_active;
- const tabs = this.#getCachedTabs();
+ const activeIndex = this._active;
+ const tabs = this.getCachedTabs();
const lastVisibleIndex = this.#findLastVisibleChildIndex(activeIndex);
if (tabs && lastVisibleIndex >= 0) {
this.#navigateAndFocusTab(lastVisibleIndex);
}
- this.#hideUnhideNavButtons(this.#_active);
+ this.#hideUnhideNavButtons(this._active);
}
/**
@@ -337,7 +243,7 @@
* @param {Number} total number of tabs
*/
#hideUnhideNavButtons(activeTabIndex) {
- const tabsLength = this.#getCachedTabs() ? this.#getCachedTabs().length : 0;
+ const tabsLength = this.getCachedTabs() ? this.getCachedTabs().length : 0;
const nextVisible = this.#findNextVisibleChildIndex(activeTabIndex);
const previousVisible = this.#findLastVisibleChildIndex(activeTabIndex);
@@ -364,26 +270,26 @@
}
#setNavigationRange() {
- const wizardPanels = this.#getCachedWizardPanels();
+ const wizardPanels = this.getCachedWizardPanels();
if(wizardPanels) {
this.maxEnabledTab = wizardPanels.length-1;
this.minEnabledTab = 0;
for (let i = 0; i < wizardPanels.length; i++) {
- if(!this.#childComponentVisible(this.#getCachedWizardPanels()[i])) {
+ if(!this.#childComponentVisible(this.getCachedWizardPanels()[i])) {
this.minEnabledTab = i+1;
} else {
break;
}
}
for (let i = wizardPanels.length - 1; i >= 0; i--) {
- if(!this.#childComponentVisible(this.#getCachedWizardPanels()[i])) {
+ if(!this.#childComponentVisible(this.getCachedWizardPanels()[i])) {
this.maxEnabledTab = i;
} else {
break;
}
}
this.minEnabledTab = Math.max(0, this.minEnabledTab);
- this.maxEnabledTab = Math.min(this.#getCachedTabs().length-1, this.maxEnabledTab);
+ this.maxEnabledTab = Math.min(this.getCachedTabs().length-1, this.maxEnabledTab);
}
}
@@ -392,7 +298,7 @@
}
#findNextVisibleChildIndex(currentIndex) {
- const tabs = this.#getCachedTabs();
+ const tabs = this.getCachedTabs();
const tabsLength = tabs? tabs.length : 0;
for (let i = currentIndex + 1; i < tabsLength; i++) {
let isVisible = tabs[i].getAttribute(Wizard.DATA_ATTRIBUTE_VISIBLE);
@@ -404,7 +310,7 @@
}
#findLastVisibleChildIndex(currentIndex) {
- const tabs = this.#getCachedTabs();
+ const tabs = this.getCachedTabs();
if(tabs) {
for (let i = currentIndex - 1; i >= 0; i--) {
let isVisible = tabs[i].getAttribute(Wizard.DATA_ATTRIBUTE_VISIBLE);
@@ -416,18 +322,6 @@
return -1;
}
-
- /**
- * Navigates to the tab at the provided index
- *
- * @private
- * @param {Number} index The index of the tab to navigate to
- */
- #navigate(index) {
- this.#_active = index;
- this.#refreshActive();
- }
-
/**
* Navigates to the item at the provided index and ensures the active tab gains focus
*
@@ -435,13 +329,13 @@
* @param {Number} index The index of the item to navigate to
*/
#navigateAndFocusTab(index) {
- this.#navigate(index);
- this.focusWithoutScroll(this.#getCachedTabs()[index]);
+ this.navigate(index);
+ this.focusWithoutScroll(this.getCachedTabs()[index]);
}
#syncWizardNavLabels() {
- const tabs = this.#getCachedTabs();
- const wizardPanels = this.#getCachedWizardPanels();
+ const tabs = this.getCachedTabs();
+ const wizardPanels = this.getCachedWizardPanels();
if (tabs) {
for (let i = 0; i < tabs.length; i++) {
let id = wizardPanels[i].querySelectorAll("[data-cmp-is]")[0].id;
@@ -452,7 +346,7 @@
}
#syncWizardPanels() {
- const wizardPanels = this.#getCachedWizardPanels();
+ const wizardPanels = this.getCachedWizardPanels();
if (wizardPanels) {
for (let i = 0; i < wizardPanels.length; i++) {
let id = wizardPanels[i].querySelectorAll("[data-cmp-is]")[0].id;
@@ -484,7 +378,7 @@
let tabListParentElement = this.#getTabListElement();
tabListParentElement.insertBefore(navigationTabToBeRepeated, tabListParentElement.firstChild);
} else {
- let beforeElement = this.#getCachedTabs()[indexToInsert - 1];
+ let beforeElement = this.getCachedTabs()[indexToInsert - 1];
beforeElement.after(navigationTabToBeRepeated);
}
} else {
@@ -492,10 +386,10 @@
let beforeElement = this.#getTabNavElementById(beforeTabNavElementId);
beforeElement.after(navigationTabToBeRepeated);
}
- this.#cacheElements(this._elements.self);
+ this.cacheElements(this._elements.self);
let repeatedWizardPanel = this.#getWizardPanelElementById(childView.id + Wizard.#wizardPanelIdSuffix);
repeatedWizardPanel.setAttribute("aria-labelledby", childView.id + Wizard.#tabIdSuffix);
- this.#refreshActive();
+ this.refreshActive();
this.#getTabIndexById();
if (childView.getInstanceManager().getModel().minOccur != undefined && childView.getInstanceManager().children.length > childView.getInstanceManager().getModel().minOccur) {
this.#navigateAndFocusTab(this.#getTabIndexById(navigationTabToBeRepeated.id));
@@ -511,9 +405,9 @@
tabNavElement.remove();
wizardPanelElement.remove();
this.children.splice(this.children.indexOf(removedInstanceView), 1);
- this.#cacheElements(this._elements.self);
- this.#_active = this.#getActiveIndex(this.#getCachedTabs());
- this.#refreshActive();
+ this.cacheElements(this._elements.self);
+ this._active = this.getActiveIndex(this.getCachedTabs());
+ this.refreshActive();
}
addChild(childView) {
@@ -525,11 +419,11 @@
this.handleHiddenChildrenVisibility();
}
this.#setNavigationRange();
- this.#hideUnhideNavButtons(this.#_active);
+ this.#hideUnhideNavButtons(this._active);
}
getChildViewByIndex(index) {
- let wizardPanels = this.#getCachedWizardPanels();
+ let wizardPanels = this.getCachedWizardPanels();
let fieldId = wizardPanels[index].id.substring(0, wizardPanels[index].id.lastIndexOf("__"));
return this.getChild(fieldId);
}
@@ -563,16 +457,8 @@
}
}
- #getCachedTabs() {
- return this._elements["tab"];
- }
-
- #getCachedWizardPanels() {
- return this._elements["wizardpanel"]
- }
-
#getTabNavElementById(tabId) {
- let tabs = this.#getCachedTabs();
+ let tabs = this.getCachedTabs();
if (tabs) {
for (let i = 0; i < tabs.length; i++) {
if (tabs[i].id === tabId) {
@@ -583,7 +469,7 @@
}
#getWizardPanelElementById(wizardPanelId) {
- let wizardPanels = this.#getCachedWizardPanels();
+ let wizardPanels = this.getCachedWizardPanels();
if (wizardPanels) {
for (let i = 0; i < wizardPanels.length; i++) {
if (wizardPanels[i].id === wizardPanelId) {
@@ -594,7 +480,7 @@
}
#getTabIndexById(tabId) {
- let tabs = this.#getCachedTabs();
+ let tabs = this.getCachedTabs();
if (tabs) {
for (let i = 0; i < tabs.length; i++) {
if (tabs[i].id === tabId) {
@@ -612,7 +498,7 @@
let closestNonRepeatableFieldId = this._templateHTML[instanceManagerId]['closestNonRepeatableFieldId'];
let closestRepeatableFieldInstanceManagerIds = this._templateHTML[instanceManagerId]['closestRepeatableFieldInstanceManagerIds'];
let indexToInsert = this.getIndexToInsert(closestNonRepeatableFieldId, closestRepeatableFieldInstanceManagerIds);
- let wizardPanels = this.#getCachedWizardPanels();
+ let wizardPanels = this.getCachedWizardPanels();
if (indexToInsert > 0) {
result.beforeViewElement = this.#getWizardPanelElementById(wizardPanels[indexToInsert - 1].id);
} else {
@@ -632,11 +518,11 @@
updateChildVisibility(visible, state) {
this.updateVisibilityOfNavigationElement(this.#getTabNavElementById(state.id + Wizard.#tabIdSuffix), visible);
- let activeTabNavElement = this.#getCachedTabs()[this.#_active];
+ let activeTabNavElement = this.getCachedTabs()[this._active];
this.#setNavigationRange();
- this.#hideUnhideNavButtons(this.#_active);
+ this.#hideUnhideNavButtons(this._active);
if (!visible && activeTabNavElement.id === state.id + Wizard.#tabIdSuffix) {
- let child = this.findFirstVisibleChild(this.#getCachedTabs());
+ let child = this.findFirstVisibleChild(this.getCachedTabs());
if (child) {
this.#navigateAndFocusTab(this.#getTabIndexById(child.id));
}
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/wizard.html b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/wizard.html
index 2e0967c8ec..565ee7130d 100644
--- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/wizard.html
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v1/wizard/wizard.html
@@ -77,6 +77,6 @@
-
+
diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v2/wizard/wizard.html b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v2/wizard/wizard.html
index a052d40b54..b377027624 100644
--- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v2/wizard/wizard.html
+++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/wizard/v2/wizard/wizard.html
@@ -78,6 +78,6 @@
-
+
diff --git a/ui.tests/test-module/specs/accordion/accordion.authoring.spec.js b/ui.tests/test-module/specs/accordion/accordion.authoring.spec.js
index 468cfa396c..d5831802a1 100644
--- a/ui.tests/test-module/specs/accordion/accordion.authoring.spec.js
+++ b/ui.tests/test-module/specs/accordion/accordion.authoring.spec.js
@@ -84,6 +84,22 @@ describe('Page - Authoring', function () {
cy.deleteComponentByPath(accordionEditPath);
});
+ it('runtime time library should not be loaded', function() {
+ cy.intercept('GET', /jcr:content\/guideContainer\/accordion\.html/).as('accordionRequest');
+ dropAccordionInContainer()
+ cy.wait('@accordionRequest').then((interception) => {
+ const htmlContent = interception.response.body;
+ const parser = new DOMParser();
+ const doc = parser.parseFromString(htmlContent, 'text/html');
+ const runtimeUrlPattern = /core\/fd\/af-clientlibs\/core-forms-components-runtime-base/;
+ const scriptTags = Array.from(doc.querySelectorAll('script[src]'));
+ console.log("tags ", scriptTags);
+ const isClientLibraryLoaded = scriptTags.some(script => runtimeUrlPattern.test(script.src));
+ expect(isClientLibraryLoaded).to.be.false;
+ })
+ cy.deleteComponentByPath(accordionEditPath);
+ })
+
it('open edit dialog of Accordion', {retries: 3}, function () {
cy.cleanTest(accordionEditPath).then(function() {
testAccordionBehaviour(accordionPathSelector, accordionEditPath);
diff --git a/ui.tests/test-module/specs/tabsontop/tabsontop.authoring.spec.js b/ui.tests/test-module/specs/tabsontop/tabsontop.authoring.spec.js
index f7dade60a6..9f3fd84df3 100644
--- a/ui.tests/test-module/specs/tabsontop/tabsontop.authoring.spec.js
+++ b/ui.tests/test-module/specs/tabsontop/tabsontop.authoring.spec.js
@@ -98,6 +98,21 @@ describe.only('Page - Authoring', function () {
cy.deleteComponentByPath(tabsPath);
});
+ it('runtime library should not be loaded', function() {
+ cy.intercept('GET', /jcr:content\/guideContainer\/tabsontop\.html/).as('tabsRequest');
+ dropTabsInContainer()
+ cy.wait('@tabsRequest').then((interception) => {
+ const htmlContent = interception.response.body;
+ const parser = new DOMParser();
+ const doc = parser.parseFromString(htmlContent, 'text/html');
+ const runtimeUrlPattern = /core\/fd\/af-clientlibs\/core-forms-components-runtime-base/;
+ const scriptTags = Array.from(doc.querySelectorAll('script[src]'));
+ const isClientLibraryLoaded = scriptTags.some(script => runtimeUrlPattern.test(script.src));
+ expect(isClientLibraryLoaded).to.be.false;
+ })
+ cy.deleteComponentByPath(tabsPath);
+ })
+
it('drop element in tabs on top', {retries: 3}, function () {
cy.cleanTest(tabsPath).then(function () {
diff --git a/ui.tests/test-module/specs/verticaltabs/verticaltabs.authoring.spec.js b/ui.tests/test-module/specs/verticaltabs/verticaltabs.authoring.spec.js
index 9670a02ebd..411753b934 100644
--- a/ui.tests/test-module/specs/verticaltabs/verticaltabs.authoring.spec.js
+++ b/ui.tests/test-module/specs/verticaltabs/verticaltabs.authoring.spec.js
@@ -97,6 +97,21 @@ describe.only('Page - Authoring', function () {
cy.deleteComponentByPath(tabsPath);
});
+ it('runtime library should not be loaded', function() {
+ cy.intercept('GET', /jcr:content\/guideContainer\/verticaltabs\.html/).as('verticaltabsRequest');
+ dropTabsInContainer()
+ cy.wait('@verticaltabsRequest').then((interception) => {
+ const htmlContent = interception.response.body;
+ const parser = new DOMParser();
+ const doc = parser.parseFromString(htmlContent, 'text/html');
+ const runtimeUrlPattern = /core\/fd\/af-clientlibs\/core-forms-components-runtime-base/;
+ const scriptTags = Array.from(doc.querySelectorAll('script[src]'));
+ const isClientLibraryLoaded = scriptTags.some(script => runtimeUrlPattern.test(script.src));
+ expect(isClientLibraryLoaded).to.be.false;
+ })
+ cy.deleteComponentByPath(tabsPath);
+ })
+
it ('open edit dialog of Vertical Tabs',{ retries: 3 }, function(){
cy.cleanTest(tabsPath).then(function() {
testPanelBehaviour(tabsContainerPathSelector, tabsPath);
diff --git a/ui.tests/test-module/specs/wizard/wizard.authoring.spec.js b/ui.tests/test-module/specs/wizard/wizard.authoring.spec.js
index 2d4ad015df..29d4290f94 100644
--- a/ui.tests/test-module/specs/wizard/wizard.authoring.spec.js
+++ b/ui.tests/test-module/specs/wizard/wizard.authoring.spec.js
@@ -66,6 +66,21 @@ describe('Page - Authoring', function () {
cy.openAuthoring(pagePath);
});
+ it('runtime library should not be loaded', function() {
+ cy.intercept('GET', /jcr:content\/guideContainer\/wizard\.html/).as('wizardRequest');
+ dropWizardInContainer();
+ cy.wait('@wizardRequest').then((interception) => {
+ const htmlContent = interception.response.body;
+ const parser = new DOMParser();
+ const doc = parser.parseFromString(htmlContent, 'text/html');
+ const runtimeUrlPattern = /core\/fd\/af-clientlibs\/core-forms-components-runtime-base/;
+ const scriptTags = Array.from(doc.querySelectorAll('script[src]'));
+ const isClientLibraryLoaded = scriptTags.some(script => runtimeUrlPattern.test(script.src));
+ expect(isClientLibraryLoaded).to.be.false;
+ })
+ cy.deleteComponentByPath(wizardLayoutDrop);
+ })
+
it('verify Basic tab in edit dialog of Wizard', function () {
dropWizardInContainer();
cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + wizardEditPathSelector).then(() => {