Initial commit

This commit is contained in:
Torsten Brendgen
2026-04-13 10:26:01 +02:00
commit bc1258ae76
116 changed files with 30409 additions and 0 deletions

265
classic/megamenu-classic.js Normal file
View File

@@ -0,0 +1,265 @@
/**
* SharePoint MegaMenu for Classic Pages
* Version: 1.0.2
*
* This version uses standalone services that replicate the SPFx logic
* without requiring the SharePoint Framework.
*
* Prerequisites:
* 1. megamenu-services-standalone.js must be loaded first
* 2. MegaMenu.css must be included
* 3. SP.js and SP.Taxonomy.js must be available
*
* Usage:
* <link rel="stylesheet" href="/SiteAssets/megamenu/MegaMenu.css" />
* <script src="/SiteAssets/megamenu/megamenu-services-standalone.js"></script>
* <script src="/SiteAssets/megamenu/megamenu-classic.js"></script>
*/
(function() {
'use strict';
var MEGAMENU_UCA_ID = 'abc3361f-bb2d-491f-aba3-cd51c19a299b'; // Same as in MegaMenuApplicationCustomizer.ts
var config = window.MegaMenuConfig || {
containerId: 's4-titlerow',
debug: false
};
function log(message, data) {
if (config.debug && console && console.log) {
console.log('[MegaMenu Classic] ' + message, data || '');
}
}
// Wait for dependencies: SharePoint JSOM, Taxonomy, and our standalone services
function waitForDependencies(callback) {
if (typeof SP !== 'undefined' &&
SP.SOD &&
typeof SP.Taxonomy !== 'undefined' &&
typeof window.MegaMenuServices !== 'undefined' &&
document.readyState === 'complete') {
callback();
} else {
setTimeout(function() { waitForDependencies(callback); }, 100);
}
}
// Classic SharePoint context wrapper
function createClassicContext() {
return {
pageContext: {
site: {
absoluteUrl: _spPageContextInfo.siteAbsoluteUrl
},
web: {
absoluteUrl: _spPageContextInfo.webAbsoluteUrl,
permissions: {
hasPermission: function(permission) {
return _spPageContextInfo.isSiteAdmin === true;
}
}
}
}
};
}
// Configuration reader using REST API (same logic as MegaMenuSettings.ts)
function readMegaMenuConfiguration(callback) {
log('Reading MegaMenu configuration from UserCustomAction...');
var restUrl = _spPageContextInfo.siteAbsoluteUrl +
"/_api/site/userCustomActions?$filter=ClientSideComponentId eq guid'" + MEGAMENU_UCA_ID + "'";
fetch(restUrl, {
method: 'GET',
headers: {
'Accept': 'application/json;odata=nometadata'
}
})
.then(function(response) {
if (!response.ok) {
throw new Error('HTTP ' + response.status + ' - ' + response.statusText);
}
return response.json();
})
.then(function(data) {
if (data && data.value && data.value.length > 0) {
var uca = data.value[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: '' });
}
} else {
log('No UserCustomAction found - using defaults');
callback({ termSetName: 'Navigation', cssUrl: '' });
}
})
.catch(function(error) {
log('Error reading configuration: ' + error.message);
callback({ termSetName: 'Navigation', cssUrl: '' });
});
}
// 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...');
// Check if services are available
if (!window.MegaMenuServices) {
console.error('[MegaMenu] Standalone services not found! Please include megamenu-services-standalone.js first.');
return;
}
readMegaMenuConfiguration(function(props) {
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
);
// Load menu items
taxonomyService.getMenuItems()
.then(function(menuItems) {
log('Menu items loaded:', menuItems);
// Find target container
var container = document.getElementById(config.containerId);
if (!container) {
log('Container not found: ' + config.containerId + '. Creating fallback container.');
// Create fallback container at top of page
container = document.createElement('div');
container.id = 'megamenu-fallback-container';
document.body.insertBefore(container, document.body.firstChild);
}
// Create menu wrapper
var menuWrapper = document.createElement('div');
menuWrapper.className = 'megamenu-classic-container';
// Insert menu wrapper
if (container.nextSibling) {
container.parentNode.insertBefore(menuWrapper, container.nextSibling);
} else {
container.parentNode.appendChild(menuWrapper);
}
// Create renderer using standalone implementation
var renderer = new window.MegaMenuServices.MegaMenuRenderer(
context,
menuItems,
function(updatedProps) {
log('Properties updated (not persisted in classic mode):', updatedProps);
}
);
// Render the menu
renderer.render(menuWrapper);
log('✅ MegaMenu rendered successfully!');
})
.catch(function(error) {
console.error('[MegaMenu] Error loading menu items:', error);
// Show error message to user
var container = document.getElementById(config.containerId);
if (container) {
var errorDiv = document.createElement('div');
errorDiv.style.cssText = 'background:#ffebee;color:#c62828;padding:10px;border:1px solid #ef5350;margin:5px 0;';
errorDiv.innerHTML = '<strong>MegaMenu Error:</strong> ' + error.message +
'<br><small>Check browser console for details.</small>';
if (container.nextSibling) {
container.parentNode.insertBefore(errorDiv, container.nextSibling);
} else {
container.parentNode.appendChild(errorDiv);
}
}
});
});
}
// Bootstrap function
function bootstrap() {
log('Bootstrapping MegaMenu...');
// Wait for SharePoint JSOM to be ready
if (typeof SP === 'undefined' || !SP.SOD) {
setTimeout(bootstrap, 100);
return;
}
// Load required SharePoint libraries
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function() {
SP.SOD.executeFunc('sp.taxonomy.js', 'SP.Taxonomy.TaxonomySession', function() {
// Wait for all dependencies and initialize
waitForDependencies(function() {
initMegaMenu();
});
});
});
}
// Auto-start based on DOM state
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', bootstrap);
} else {
// DOM already loaded
setTimeout(bootstrap, 100);
}
// Expose public API
window.MegaMenuClassic = {
init: initMegaMenu,
bootstrap: bootstrap,
config: config,
// Utility methods
setConfig: function(newConfig) {
Object.assign(config, newConfig);
},
reload: function() {
// Remove existing menu and reload
var existing = document.querySelector('.megamenu-classic-container');
if (existing) {
existing.remove();
}
initMegaMenu();
}
};
log('MegaMenu Classic wrapper loaded. Waiting for dependencies...');
})();