feat: Add support for flyout menu mode in MegaMenu

- Introduced `MegaMenuMode` type and `normalizeMegaMenuMode` function to handle menu modes.
- Updated `MegaMenuApplicationCustomizer` to accept `menuMode` property.
- Enhanced `MegaMenuRenderer` to render flyout menus based on the selected mode.
- Created new HTML previews for both flyout and mega menu modes.
- Removed unused mock services and user custom action service interfaces.
This commit is contained in:
Torsten Brendgen
2026-07-20 20:37:32 +02:00
parent e75b11117f
commit bc61166267
27 changed files with 1320 additions and 1833 deletions

View File

@@ -1,6 +1,6 @@
/**
* SharePoint MegaMenu for Classic Pages
* Version: 1.0.2
* Version: 2.1.0
*
* This version uses standalone services that replicate the SPFx logic
* without requiring the SharePoint Framework.
@@ -21,10 +21,9 @@
var MEGAMENU_UCA_ID = 'c0abbffb-355d-4d4e-bd38-9e15fb811506'; // Same as in MegaMenuApplicationCustomizer.ts
var config = window.MegaMenuConfig || {
containerId: 's4-titlerow',
debug: false
};
var config = window.MegaMenuConfig || {};
config.containerId = config.containerId || 's4-titlerow';
config.debug = config.debug === true;
function log(message, data) {
if (config.debug && console && console.log) {
@@ -84,44 +83,30 @@
return response.json();
})
.then(function(data) {
if (data && data.value && data.value.length > 0) {
var uca = data.value[0];
var actions = data && data.value
? data.value
: (data && data.d && data.d.results ? data.d.results : []);
if (actions.length > 0) {
var uca = actions[0];
try {
var props = JSON.parse(uca.ClientSideComponentProperties);
log('Configuration found', props);
callback(props);
} catch (e) {
log('Error parsing UserCustomAction properties: ' + e.message);
callback({ termSetName: 'Navigation', cssUrl: '' });
callback({ termSetName: 'Navigation', menuMode: 'megaMenu', debug: false });
}
} else {
log('No UserCustomAction found - using defaults');
callback({ termSetName: 'Navigation', cssUrl: '' });
callback({ termSetName: 'Navigation', menuMode: 'megaMenu', debug: false });
}
})
.catch(function(error) {
log('Error reading configuration: ' + error.message);
callback({ termSetName: 'Navigation', cssUrl: '' });
callback({ termSetName: 'Navigation', menuMode: 'megaMenu', debug: false });
});
}
// Load external CSS (same as SPFx version)
function loadExternalCSS(cssUrl) {
if (!cssUrl) return;
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = cssUrl;
link.onerror = function() {
log('Failed to load external CSS: ' + cssUrl);
};
link.onload = function() {
log('External CSS loaded successfully: ' + cssUrl);
};
document.head.appendChild(link);
}
// Main initialization
function initMegaMenu() {
log('Initializing MegaMenu for classic SharePoint...');
@@ -133,20 +118,16 @@
}
readMegaMenuConfiguration(function(props) {
config.debug = props.debug === true || config.debug === true;
log('Using configuration:', props);
// Load external CSS if specified
if (props.cssUrl) {
loadExternalCSS(props.cssUrl);
}
// Create context
var context = createClassicContext();
// Create taxonomy service using standalone implementation
var taxonomyService = new window.MegaMenuServices.TaxonomyNavigationService(
context,
props.termSetName
props.termSetId || props.termSetName
);
// Load menu items
@@ -179,9 +160,7 @@
var renderer = new window.MegaMenuServices.MegaMenuRenderer(
context,
menuItems,
function(updatedProps) {
log('Properties updated (not persisted in classic mode):', updatedProps);
}
props.menuMode === 'flyout' ? 'flyout' : 'megaMenu'
);
// Render the menu