@madj2k/fe-frontend-kit 2.0.37 → 2.0.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +1 -0
- package/index.scss +1 -0
- package/menus/flyout-menu/flyout-menu-2.0.js +94 -52
- package/menus/flyout-menu/flyout-menu-2.0.scss +6 -0
- package/menus/slide-menu/Examples/TYPO3/JsonMenuViewHelper.php +146 -0
- package/menus/slide-menu/Examples/TYPO3/Templates.html +165 -0
- package/menus/slide-menu/index.js +2 -0
- package/menus/slide-menu/index.scss +1 -0
- package/menus/slide-menu/slide-menu-2.0.js +848 -0
- package/menus/slide-menu/slide-menu-2.0.scss +129 -0
- package/package.json +1 -1
- package/readme.md +322 -26
- package/sass/bootstrap-5.3/10_mixins/_colors.scss +107 -13
- package/sass/bootstrap-5.3/10_mixins/_section.scss +51 -9
- package/sass/bootstrap-5.3/10_mixins/_toggle-list.scss +26 -12
- package/sass/bootstrap-5.3/10_mixins/_toggle.scss +8 -0
package/index.js
CHANGED
package/index.scss
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @author Steffen Kroggel <developer@steffenkroggel.de>
|
|
9
9
|
* @copyright 2025 Steffen Kroggel
|
|
10
|
-
* @version 2.0.
|
|
10
|
+
* @version 2.0.4
|
|
11
11
|
* @license GNU General Public License v3.0
|
|
12
12
|
* @see https://www.gnu.org/licenses/gpl-3.0.en.html
|
|
13
13
|
*
|
|
@@ -49,11 +49,13 @@ class Madj2kFlyoutMenu {
|
|
|
49
49
|
menuCloseClass: "js-flyout-close",
|
|
50
50
|
menuContainerClass: "js-flyout-container",
|
|
51
51
|
menuInnerClass: "js-flyout-inner",
|
|
52
|
+
hoverParentClass: 'nav-main',
|
|
52
53
|
heightCalculationClass: 'calculate',
|
|
53
54
|
heightMode: 'full',
|
|
55
|
+
heightModeClassPrefix: 'height-mode',
|
|
56
|
+
scrollMode: 'default',
|
|
57
|
+
scrollModeClassPrefix: 'scroll-mode',
|
|
54
58
|
eventMode: 'click',
|
|
55
|
-
eventModeOpen: '',
|
|
56
|
-
eventModeClose: '',
|
|
57
59
|
paddingBehavior: 0,
|
|
58
60
|
paddingViewPortMinWidth: 0,
|
|
59
61
|
animationDuration: 500,
|
|
@@ -77,6 +79,11 @@ class Madj2kFlyoutMenu {
|
|
|
77
79
|
this.settings.$menuContainer = this.settings.$menu.querySelector(`.${this.settings.menuContainerClass}`);
|
|
78
80
|
this.settings.$menuInner = this.settings.$menu.querySelector(`.${this.settings.menuInnerClass}`);
|
|
79
81
|
|
|
82
|
+
// add mode classes
|
|
83
|
+
this.settings.$menu.classList.add(this.settings.heightModeClassPrefix + '-' + this.settings.heightMode);
|
|
84
|
+
this.settings.$menuInner.classList.add(this.settings.scrollModeClassPrefix + '-' + this.settings.scrollMode);
|
|
85
|
+
|
|
86
|
+
// Bind persistent event handlers
|
|
80
87
|
this.initNoScrollHelper();
|
|
81
88
|
this.resizeAndPositionMenu();
|
|
82
89
|
this.paddingMenu();
|
|
@@ -115,40 +122,102 @@ class Madj2kFlyoutMenu {
|
|
|
115
122
|
}
|
|
116
123
|
}
|
|
117
124
|
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Handles mouseleave on menu container
|
|
128
|
+
* @param {MouseEvent} e
|
|
129
|
+
*/
|
|
130
|
+
containerLeaveEvent(e) {
|
|
131
|
+
const to = e.relatedTarget;
|
|
132
|
+
const parentContainer = this.$element.closest(this.settings.hoverParentSelector) || null;
|
|
133
|
+
if (to && this.$element.contains(to)) return;
|
|
134
|
+
if (to && parentContainer?.contains(to)) return;
|
|
135
|
+
if (this.$element.classList.contains(this.settings.openStatusClass)) {
|
|
136
|
+
document.dispatchEvent(new CustomEvent('madj2k-flyoutmenu-close'));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Handles mouseleave on trigger element
|
|
142
|
+
* @param {MouseEvent} e
|
|
143
|
+
*/
|
|
144
|
+
triggerLeaveEvent(e) {
|
|
145
|
+
const to = e.relatedTarget;
|
|
146
|
+
const parentContainer = this.$element.closest('.' + this.settings.hoverParentClass) || null;
|
|
147
|
+
|
|
148
|
+
if (to && this.settings.$menu.contains(to)) return;
|
|
149
|
+
if (to && parentContainer?.contains(to)) return;
|
|
150
|
+
if (this.$element.classList.contains(this.settings.openStatusClass)) {
|
|
151
|
+
document.dispatchEvent(new CustomEvent('madj2k-flyoutmenu-close'));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Handles touchstart outside the flyout menu
|
|
157
|
+
* @param {TouchEvent} e
|
|
158
|
+
*/
|
|
159
|
+
touchStartEvent(e) {
|
|
160
|
+
const target = e.target;
|
|
161
|
+
if (!target) return;
|
|
162
|
+
if (this.settings.$menuInner.contains(target)) return;
|
|
163
|
+
if (this.$element.classList.contains(this.settings.openStatusClass)) {
|
|
164
|
+
document.dispatchEvent(new CustomEvent('madj2k-flyoutmenu-close'));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
118
168
|
/**
|
|
119
169
|
* Binds all necessary event listeners
|
|
120
170
|
*/
|
|
121
171
|
bindEvents() {
|
|
122
172
|
if (this.settings.$closeBtn) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
this.settings.$closeBtn.addEventListener(this.settings.eventModeClose, e => this.closeEvent(e));
|
|
126
|
-
} else {
|
|
127
|
-
this.settings.$closeBtn.addEventListener(this.settings.eventMode, e => this.closeEvent(e));
|
|
128
|
-
}
|
|
173
|
+
const closeEvent = this.settings.eventMode === 'mouseover' ? 'mouseenter' : 'click';
|
|
174
|
+
this.settings.$closeBtn.addEventListener(closeEvent, e => this.closeEvent(e));
|
|
129
175
|
this.settings.$closeBtn.addEventListener('keydown', e => this.keyboardEvent(e));
|
|
130
176
|
}
|
|
131
177
|
|
|
132
|
-
if (this.settings.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
this.$element.addEventListener(this.settings.eventModeClose, e => this.closeEvent(e));
|
|
138
|
-
}
|
|
178
|
+
if (this.settings.eventMode === 'mouseover') {
|
|
179
|
+
this.$element.addEventListener('mouseenter', e => this.openEvent(e));
|
|
180
|
+
this.$element.addEventListener('mouseleave',e => this.triggerLeaveEvent(e));
|
|
181
|
+
this.settings.$menuContainer?.addEventListener('mouseleave', e => this.containerLeaveEvent(e));
|
|
182
|
+
document.addEventListener('touchstart', e => this.touchStartEvent(e), { passive: true });
|
|
139
183
|
} else {
|
|
140
|
-
this.$element.addEventListener(
|
|
184
|
+
this.$element.addEventListener('click', e => this.toggleEvent(e));
|
|
141
185
|
}
|
|
142
186
|
|
|
143
187
|
this.$element.addEventListener('keydown', e => this.keyboardEvent(e));
|
|
144
|
-
|
|
145
188
|
this.settings.$menu.querySelectorAll('a,button,input,textarea,select')
|
|
146
189
|
.forEach(el => el.addEventListener('keydown', e => this.keyboardEvent(e)));
|
|
147
|
-
|
|
148
190
|
document.addEventListener('madj2k-flyoutmenu-close', e => this.closeEvent(e));
|
|
149
191
|
document.addEventListener('madj2k-flyoutmenu-resize', e => this.resizeAndPositionMenuEvent(e));
|
|
150
192
|
}
|
|
151
193
|
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Removes all event listeners (including dynamic hover/touch)
|
|
197
|
+
*/
|
|
198
|
+
destroyEvents() {
|
|
199
|
+
if (this.settings.$closeBtn) {
|
|
200
|
+
const closeEvent = this.settings.eventMode === 'mouseover' ? 'mouseenter' : 'click';
|
|
201
|
+
this.settings.$closeBtn.removeEventListener(closeEvent, e => this.closeEvent(e));
|
|
202
|
+
this.settings.$closeBtn.removeEventListener('keydown', e => this.keyboardEvent(e));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (this.settings.eventMode === 'mouseover') {
|
|
206
|
+
this.$element.removeEventListener('mouseenter', e => this.openEvent(e));
|
|
207
|
+
this.settings.$menuContainer?.removeEventListener('mouseleave', e => this.containerLeaveEvent(e));
|
|
208
|
+
document.removeEventListener('touchstart', e => this.touchStartEvent(e), { passive: true });
|
|
209
|
+
} else {
|
|
210
|
+
this.$element.removeEventListener('click', e => this.toggleEvent(e));
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
this.$element.removeEventListener('keydown', e => this.keyboardEvent(e));
|
|
214
|
+
this.settings.$menu.querySelectorAll('a,button,input,textarea,select')
|
|
215
|
+
.forEach(el => el.removeEventListener('keydown', e => this.keyboardEvent(e)));
|
|
216
|
+
document.removeEventListener('madj2k-flyoutmenu-close', e => this.closeEvent(e));
|
|
217
|
+
document.removeEventListener('madj2k-flyoutmenu-resize', e => this.resizeAndPositionMenuEvent(e));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
|
|
152
221
|
/**
|
|
153
222
|
* Initializes ResizeObserver to auto-resize menu
|
|
154
223
|
*/
|
|
@@ -172,37 +241,6 @@ class Madj2kFlyoutMenu {
|
|
|
172
241
|
}
|
|
173
242
|
}
|
|
174
243
|
|
|
175
|
-
/**
|
|
176
|
-
* Unbinds all event listeners
|
|
177
|
-
*/
|
|
178
|
-
destroyEvents() {
|
|
179
|
-
if (this.settings.$closeBtn) {
|
|
180
|
-
if (this.settings.eventModeClose) {
|
|
181
|
-
this.settings.$closeBtn.removeEventListener(this.settings.eventModeClose, e => this.closeEvent(e));
|
|
182
|
-
} else {
|
|
183
|
-
this.settings.$closeBtn.removeEventListener(this.settings.eventMode, e => this.closeEvent(e));
|
|
184
|
-
}
|
|
185
|
-
this.settings.$closeBtn.removeEventListener('keydown', e => this.keyboardEvent(e));
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if (this.settings.eventModeOpen || this.settings.eventModeClose) {
|
|
189
|
-
if (this.settings.eventModeOpen) {
|
|
190
|
-
this.$element.removeEventListener(this.settings.eventModeOpen, e => this.openEvent(e));
|
|
191
|
-
}
|
|
192
|
-
if (this.settings.eventModeClose) {
|
|
193
|
-
this.$element.removeEventListener(this.settings.eventModeClose, e => this.closeEvent(e));
|
|
194
|
-
}
|
|
195
|
-
} else {
|
|
196
|
-
this.$element.removeEventListener(this.settings.eventMode, e => this.toggleEvent(e));
|
|
197
|
-
}
|
|
198
|
-
this.$element.removeEventListener('keydown', e => this.keyboardEvent(e));
|
|
199
|
-
|
|
200
|
-
this.settings.$menu.querySelectorAll('a,button,input,textarea,select')
|
|
201
|
-
.forEach(el => el.removeEventListener('keydown', e => this.keyboardEvent(e)));
|
|
202
|
-
|
|
203
|
-
document.removeEventListener('madj2k-flyoutmenu-close', e => this.closeEvent(e));
|
|
204
|
-
document.removeEventListener('madj2k-flyoutmenu-resize', e => this.resizeAndPositionMenuEvent(e));
|
|
205
|
-
}
|
|
206
244
|
|
|
207
245
|
/**
|
|
208
246
|
* Destroys ResizeObserver
|
|
@@ -412,6 +450,10 @@ class Madj2kFlyoutMenu {
|
|
|
412
450
|
newHeight = `${innerHeight}px`;
|
|
413
451
|
}
|
|
414
452
|
|
|
453
|
+
if (this.settings.scrollMode === 'inner') {
|
|
454
|
+
this.settings.$menuInner.style.height = newHeight;
|
|
455
|
+
}
|
|
456
|
+
|
|
415
457
|
// set max-height again so that longer flyouts do not lead to scrolling on smaller ones
|
|
416
458
|
this.settings.$menu.classList.remove(this.settings.heightCalculationClass);
|
|
417
459
|
this.settings.$menu.style.height = newHeight;
|
|
@@ -436,6 +478,7 @@ class Madj2kFlyoutMenu {
|
|
|
436
478
|
|
|
437
479
|
if (!this.settings.$paddingReference) return;
|
|
438
480
|
if (this.settings.paddingBehavior === 0) return;
|
|
481
|
+
|
|
439
482
|
// should be re-evaluated on a resize event after re-opening the menu
|
|
440
483
|
// if (this.settings.paddingBehavior === 1 && this.settings.$menuInner.hasAttribute('data-padding-set')) return;
|
|
441
484
|
|
|
@@ -472,8 +515,7 @@ class Madj2kFlyoutMenu {
|
|
|
472
515
|
*/
|
|
473
516
|
toggleNoScroll() {
|
|
474
517
|
|
|
475
|
-
|
|
476
|
-
if (this.settings.heightMode === 'full' || this.settings.fullHeight === true) {
|
|
518
|
+
if (this.settings.scrollHelper) {
|
|
477
519
|
const body = document.body;
|
|
478
520
|
const helper = body.querySelector('.no-scroll-helper');
|
|
479
521
|
const inner = body.querySelector('.no-scroll-helper-inner');
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* This file is part of the TYPO3 CMS project.
|
|
5
|
+
*
|
|
6
|
+
* It is free software; you can redistribute it and/or modify it under
|
|
7
|
+
* the terms of the GNU General Public License, either version 2
|
|
8
|
+
* of the License, or any later version.
|
|
9
|
+
*
|
|
10
|
+
* For the full copyright and license information, please read the
|
|
11
|
+
* LICENSE.txt file that was distributed with this source code.
|
|
12
|
+
*
|
|
13
|
+
* The TYPO3 project - inspiring people to share!
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
17
|
+
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
|
18
|
+
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
|
|
19
|
+
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Class JsonMenuViewHelper
|
|
23
|
+
*
|
|
24
|
+
* @author Steffen Kroggel <developer@steffenkroggel.de>
|
|
25
|
+
* @copyright Steffen Kroggel <developer@steffenkroggel.de>
|
|
26
|
+
* @package Madj2k_SiteDefault
|
|
27
|
+
* @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
|
|
28
|
+
*/
|
|
29
|
+
class JsonMenuViewHelper extends AbstractViewHelper
|
|
30
|
+
{
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Initialize arguments
|
|
34
|
+
*
|
|
35
|
+
* @return void
|
|
36
|
+
*/
|
|
37
|
+
public function initializeArguments(): void
|
|
38
|
+
{
|
|
39
|
+
parent::initializeArguments();
|
|
40
|
+
$this->registerArgument('items', 'array', 'The recursive menu-array');
|
|
41
|
+
$this->registerArgument('parseFuncTSPath', 'string', 'Path to the TypoScript parseFunc setup.', false, '');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @param array $arguments
|
|
47
|
+
* @param \Closure $renderChildrenClosure
|
|
48
|
+
* @param \TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface $renderingContext
|
|
49
|
+
* @return string
|
|
50
|
+
*/
|
|
51
|
+
public static function renderStatic(
|
|
52
|
+
array $arguments,
|
|
53
|
+
\Closure $renderChildrenClosure,
|
|
54
|
+
RenderingContextInterface $renderingContext
|
|
55
|
+
): string {
|
|
56
|
+
|
|
57
|
+
/** @var array $items */
|
|
58
|
+
$items = $arguments['items'];
|
|
59
|
+
|
|
60
|
+
/** @var string $parseFuncTSPath */
|
|
61
|
+
$parseFuncTSPath = $arguments['parseFuncTSPath'];
|
|
62
|
+
|
|
63
|
+
/** @var \Psr\Http\Message\ServerRequestInterface $request */
|
|
64
|
+
$request = $renderingContext->getRequest();
|
|
65
|
+
|
|
66
|
+
/** @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObject */
|
|
67
|
+
$contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
|
68
|
+
$contentObject->setRequest($request);
|
|
69
|
+
$contentObject->start([]);
|
|
70
|
+
|
|
71
|
+
$result = [];
|
|
72
|
+
foreach ($items as $item) {
|
|
73
|
+
$result[] = self::callback($item, $contentObject, $parseFuncTSPath);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return json_encode($result);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @param array $item
|
|
82
|
+
* @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObject
|
|
83
|
+
* @param string $parseFuncTSPath
|
|
84
|
+
* @return array
|
|
85
|
+
*/
|
|
86
|
+
public static function callback (
|
|
87
|
+
array $item,
|
|
88
|
+
ContentObjectRenderer $contentObject,
|
|
89
|
+
string $parseFuncTSPath = ''
|
|
90
|
+
): array {
|
|
91
|
+
|
|
92
|
+
/*
|
|
93
|
+
Build a reduced structure:
|
|
94
|
+
"data": {"uid": 2, "pid": 1, "title": "Lorem Ipsum"},
|
|
95
|
+
"title": "Lorem Ipsum",
|
|
96
|
+
"link": "\/lorem\/Ipsum",
|
|
97
|
+
"target": "_blank",
|
|
98
|
+
"active": 1,
|
|
99
|
+
"current": 0,
|
|
100
|
+
"spacer": 0,
|
|
101
|
+
"hasSubpages": 1,
|
|
102
|
+
"children": [ ]
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
$result = $item;
|
|
106
|
+
$result['data'] = [
|
|
107
|
+
'uid' => $item['data']['uid'],
|
|
108
|
+
'pid' => $item['data']['pid'],
|
|
109
|
+
'title'=> $item['data']['title'],
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
$result['children'] = [];
|
|
113
|
+
if (
|
|
114
|
+
(isset($item['children']))
|
|
115
|
+
&& (is_array($item['children']))
|
|
116
|
+
){
|
|
117
|
+
foreach ($item['children'] as $child) {
|
|
118
|
+
$result['children'][] = self::callback($child, $contentObject, $parseFuncTSPath);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!isset($result['hasSubpages'])) {
|
|
123
|
+
$result['hasSubpages'] = $result['children'] ? 1 : 0;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (isset($item['data']['doktype'])) {
|
|
127
|
+
$result['linkType'] = $item['data']['doktype'];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Parse title with HTML-parser
|
|
131
|
+
if ($parseFuncTSPath) {
|
|
132
|
+
$result['title'] = $contentObject->parseFunc($result['title'], null, '< ' . $parseFuncTSPath);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// do not link sites, that only link to the next subpage!
|
|
136
|
+
$result['isLinked'] = 1;
|
|
137
|
+
if (
|
|
138
|
+
($item['data']['doktype'] == 4)
|
|
139
|
+
&& (in_array($item['data']['shortcut_mode'], [1,3]))
|
|
140
|
+
){
|
|
141
|
+
$result['isLinked'] = 0;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return $result;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
|
2
|
+
xmlns:siteDefault="http://typo3.org/ns/Madj2k/SiteDefault/ViewHelpers"
|
|
3
|
+
data-namespace-typo3-fluid="true"
|
|
4
|
+
>
|
|
5
|
+
|
|
6
|
+
<f:if condition="{menuItems}">
|
|
7
|
+
<f:then>
|
|
8
|
+
<f:comment>
|
|
9
|
+
<!--
|
|
10
|
+
Templates for mobile menu. We don't want this to be loaded on default because
|
|
11
|
+
it would duplicate the menu for search engines and would enlarge the body to parse
|
|
12
|
+
-->
|
|
13
|
+
</f:comment>
|
|
14
|
+
<template class="js-slide-nav-tmpl" data-type="menuWrap">
|
|
15
|
+
<div class="slide-nav-container js-slide-nav-container">
|
|
16
|
+
<div class="slide-nav-card js-slide-nav-card %levelClass%" id="slide-card-%uid%">
|
|
17
|
+
<div class="slide-nav-inner pd-3">
|
|
18
|
+
<ul class="slide-nav-list" role="none">
|
|
19
|
+
<li class="slide-nav-headline %levelClass%" role="none">
|
|
20
|
+
<a href="/"
|
|
21
|
+
title="{f:translate(key:'menu.home', extensionName:'siteDefault')}"
|
|
22
|
+
role="menuitem"
|
|
23
|
+
class="slide-nav-headline-link level-1">
|
|
24
|
+
<span>{f:translate(key:'menu.home', extensionName:'siteDefault')}</span>
|
|
25
|
+
</a>
|
|
26
|
+
</li>
|
|
27
|
+
|
|
28
|
+
<li class="slide-nav-wrap">
|
|
29
|
+
<ul class="slide-nav-list toggle-list" role="none">
|
|
30
|
+
%menuItems%
|
|
31
|
+
</ul>
|
|
32
|
+
</li>
|
|
33
|
+
|
|
34
|
+
<f:if condition="{topMenuItems}">
|
|
35
|
+
<li class="slide-nav-item-footer" role="none">
|
|
36
|
+
<ul class="slide-nav-meta-list" role="none">
|
|
37
|
+
<f:for each="{topMenuItems}" as="menuItem" iteration="iterator">
|
|
38
|
+
<li class="slide-nav-meta-item level1{f:if(condition:'{menuItem.active}', then:' active')}" role="none">
|
|
39
|
+
<a class="slide-nav-meta-link level1{f:if(condition:'{menuItem.active}', then:' active')}"
|
|
40
|
+
href="{menuItem.link}"
|
|
41
|
+
target="{menuItem.target}"
|
|
42
|
+
title="{menuItem.data.title}"
|
|
43
|
+
role="menuitem"
|
|
44
|
+
>
|
|
45
|
+
<span><f:format.html parseFuncTSPath="lib.parseFunc_Inline">{menuItem.title}</f:format.html></span>
|
|
46
|
+
</a>
|
|
47
|
+
</li>
|
|
48
|
+
</f:for>
|
|
49
|
+
</ul>
|
|
50
|
+
</li>
|
|
51
|
+
</f:if>
|
|
52
|
+
|
|
53
|
+
<f:if condition="{footerMenuItems}">
|
|
54
|
+
<li class="slide-nav-item-footer" role="none">
|
|
55
|
+
<ul class="slide-nav-meta-list" role="none">
|
|
56
|
+
<f:for each="{footerMenuItems}" as="menuItem" iteration="iterator">
|
|
57
|
+
<li class="slide-nav-meta-item level1{f:if(condition:'{menuItem.active}', then:' active')}" role="none">
|
|
58
|
+
<a class="slide-nav-meta-link level1{f:if(condition:'{menuItem.active}', then:' active')}"
|
|
59
|
+
href="{menuItem.link}"
|
|
60
|
+
target="{menuItem.target}"
|
|
61
|
+
title="{menuItem.data.title}"
|
|
62
|
+
role="menuitem"
|
|
63
|
+
>
|
|
64
|
+
<span><f:format.html parseFuncTSPath="lib.parseFunc_Inline">{menuItem.title}</f:format.html></span>
|
|
65
|
+
</a>
|
|
66
|
+
</li>
|
|
67
|
+
</f:for>
|
|
68
|
+
</ul>
|
|
69
|
+
</li>
|
|
70
|
+
</f:if>
|
|
71
|
+
</ul>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</template>
|
|
76
|
+
|
|
77
|
+
<template class="js-slide-nav-tmpl" data-type="menuItem">
|
|
78
|
+
<li class="slide-nav-item toggle-list-item js-slide-nav-item %activeClass% %hasChildrenClass%" role="none">
|
|
79
|
+
<f:comment><!-- normal link that opens the menu-item --></f:comment>
|
|
80
|
+
|
|
81
|
+
%ifHasNoChildrenStart%
|
|
82
|
+
<a href="%link%"
|
|
83
|
+
title="%titleRaw%"
|
|
84
|
+
role="menuitem"
|
|
85
|
+
class="slide-nav-link toggle-list-link %activeClass% %hasChildrenClass%"
|
|
86
|
+
target="%target%"
|
|
87
|
+
aria-current="%ariaCurrent%">
|
|
88
|
+
<span class="toggle-list-text">%title%</span>
|
|
89
|
+
</a>
|
|
90
|
+
%ifHasNoChildrenEnd%
|
|
91
|
+
|
|
92
|
+
<f:comment><!-- link that opens next card --></f:comment>
|
|
93
|
+
%ifHasChildrenStart%
|
|
94
|
+
<a class="slide-nav-link slide-nav-next toggle-list-link js-slide-nav-next %activeClass% %hasChildrenClass%"
|
|
95
|
+
href="#"
|
|
96
|
+
role="button"
|
|
97
|
+
title="{f:translate(key:'menu.openSubmenu', extensionName:'siteDefault')}"
|
|
98
|
+
aria-label="{f:translate(key:'menu.openSubmenu', extensionName:'siteDefault')}"
|
|
99
|
+
aria-haspopup="true"
|
|
100
|
+
aria-expanded="%ariaExpanded%"
|
|
101
|
+
aria-controls="slide-card-%uid%">
|
|
102
|
+
<span class="toggle-list-text">%title%</span><span class="icon-arrow-right icon"></span>
|
|
103
|
+
</a>
|
|
104
|
+
%ifHasChildrenEnd%
|
|
105
|
+
|
|
106
|
+
%submenu%
|
|
107
|
+
</li>
|
|
108
|
+
</template>
|
|
109
|
+
|
|
110
|
+
<template class="js-slide-nav-tmpl" data-type="subMenuWrap">
|
|
111
|
+
<div class="slide-nav-card js-slide-nav-card %activeClass% %levelClass%" id="slide-card-%uid%">
|
|
112
|
+
<div class="slide-nav-inner pd-3">
|
|
113
|
+
<ul class="slide-nav-list">
|
|
114
|
+
<li class="slide-nav-item-back" role="none">
|
|
115
|
+
<button class="slide-nav-back js-slide-nav-back"
|
|
116
|
+
title="{f:translate(key:'menu.levelUp', extensionName:'siteDefault')}"
|
|
117
|
+
aria-haspopup="true"
|
|
118
|
+
aria-label="{f:translate(key:'menu.levelUp', extensionName:'siteDefault')}"
|
|
119
|
+
aria-controls="slide-card-%uid%"
|
|
120
|
+
data-parent-card="slide-card-%parentUid%"><span class="icon-arrow-left icon"></span><span
|
|
121
|
+
class="slide-nav-back-label">{f:translate(key:'menu.back', extensionName:'siteDefault')}</span>
|
|
122
|
+
</button>
|
|
123
|
+
</li>
|
|
124
|
+
<li class="slide-nav-headline %levelClass%" role="none">
|
|
125
|
+
|
|
126
|
+
<f:comment><!-- normal parent --></f:comment>
|
|
127
|
+
%ifIsNotLinkedStart%
|
|
128
|
+
<span class="slide-nav-headline-text %currentClass% %isLinkedClass%">%title%</span>
|
|
129
|
+
%ifIsNotLinkedEnd%
|
|
130
|
+
|
|
131
|
+
<f:comment><!-- linked parent --></f:comment>
|
|
132
|
+
%ifIsLinkedStart%
|
|
133
|
+
<a href="%link%"
|
|
134
|
+
title="%titleRaw%"
|
|
135
|
+
role="menuitem"
|
|
136
|
+
class="slide-nav-headline-link %currentClass% %hasChildrenClass% %isLinkedClass%"
|
|
137
|
+
target="%target%"
|
|
138
|
+
aria-current="%ariaCurrent%">
|
|
139
|
+
<span>%title%</span>
|
|
140
|
+
</a>
|
|
141
|
+
%ifIsLinkedEnd%
|
|
142
|
+
</li>
|
|
143
|
+
|
|
144
|
+
<li class="slide-nav-wrap">
|
|
145
|
+
<ul class="slide-nav-list toggle-list" role="none">
|
|
146
|
+
%menuItems%
|
|
147
|
+
</ul>
|
|
148
|
+
</li>
|
|
149
|
+
|
|
150
|
+
</ul>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</template>
|
|
154
|
+
|
|
155
|
+
<script>
|
|
156
|
+
let slideNavItems = <f:format.raw><siteDefault:jsonMenu items="{menuItems}" parseFuncTSPath="lib.parseFunc_Inline" /></f:format.raw>;
|
|
157
|
+
</script>
|
|
158
|
+
</f:then>
|
|
159
|
+
<f:else>
|
|
160
|
+
<script>
|
|
161
|
+
let slideNavItems = {};
|
|
162
|
+
</script>
|
|
163
|
+
</f:else>
|
|
164
|
+
</f:if>
|
|
165
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@forward './slide-menu-2.0';
|