FancyMenu JavaScript API
FancyMenu injects a JavaScript bridge into every MCEF-backed feature (for example the Browser element). The bridge lets web content:
- run any FancyMenu action directly from JavaScript,
- read any FancyMenu placeholder asynchronously.
Two globals expose the API:
window.fancymenu– primary namespacewindow.FancyMenu– alias (mirrors the exact shape offancymenu)
Use the fancymenu-ready event, or feature detection, to ensure the bridge is available before calling it.
1. Namespaces & Structure
fancymenu.actions– execute FancyMenu actions from the browser.fancymenu.placeholders– read FancyMenu placeholder values asynchronously.FancyMenumirrorsfancymenu, so both expose the same sub-namespaces.
Actions expose two helpers:
fancymenu.actions.execute(actionType, actionValue?)fancymenu.actions.executeWithCallback(actionType, actionValue?, onSuccess?, onFailure?)
2. Availability
if (typeof fancymenu !== 'undefined') {
// safe to use
}
window.addEventListener('fancymenu-ready', () => {
console.log('FancyMenu API is ready');
});
Content may also be hosted locally: place HTML files in <game-directory>/config/fancymenu/assets/ and load them through URLs of the form file:///config/fancymenu/assets/<name>.html.
3. Executing Actions
Use the fancymenu.actions namespace. Each call mirrors the action strings used in FancyMenu scripts.
Quick Calls
fancymenu.actions.execute('quitgame'); // action without value
fancymenu.actions.execute('opengui', 'title_screen'); // action with value
fancymenu.actions.execute('set_variable', 'hp:20'); // value uses name:value format
With Callbacks
fancymenu.actions.executeWithCallback(
'opengui',
'title_screen',
result => console.log('Opened title screen'),
error => console.error('Open failed:', error)
);
// The value parameter is optional. When omitted, pass the callbacks directly after actionType.
fancymenu.actions.executeWithCallback(
'quitgame',
result => console.log('Quit triggered'),
error => console.error('Quit failed:', error)
);
Legacy helpers fancymenu.execute(...) and fancymenu.executeWithCallback(...) still delegate to the actions namespace.
Common Action Types
quitgame– immediately quits the game (no value)back_to_last_screen– returns to the previous GUI (no value)opengui– opens a FancyMenu or vanilla screen (value: screen identifier)openlink– launches a browser (value: URL)sendmessage– posts a chat line (value: message text)set_variable– assigns a FancyMenu variable (value:name:value)joinserver– connects to a server (value: address)disconnect_server_or_world– disconnects and moves to a target screen (value: screen identifier)
Every action that exists in FancyMenu is available through the bridge; see action scripts for the complete catalog.
4. Reading Placeholders
FancyMenu’s placeholder system is exposed through fancymenu.placeholders (and FancyMenu.placeholders). Both helper methods return Promise<string>:
fancymenu.placeholders.get(identifier: string): Promise<string>
fancymenu.placeholders.getWithVars(identifier: string, ...vars: string[]): Promise<string>
Supplying Variables
- Variables are strings in
name:valueform. The bridge splits on the first colon only, so the value can contain additional colons. - Names and values are trimmed; empty names are rejected.
- Provide as many variables as the placeholder requires. Omit optional ones.
Examples
// No variables
fancymenu.placeholders.get('playername')
.then(name => console.log('Player:', name));
// One variable
fancymenu.placeholders.getWithVars('uptime_duration', 'output_as_millis:false')
.then(seconds => console.log('Uptime (s):', seconds));
// Multiple variables
fancymenu.placeholders.getWithVars(
'split_text',
'input:apple|banana|carrot',
'regex:\\|',
'max_parts:-1',
'split_index:1'
).then(part => console.log('Selected part:', part));
Error Model
Rejected promises contain a structured error:
interface PlaceholderError {
code: 'NOT_FOUND' | 'MISSING_VARIABLE' | 'INVALID_VARIABLE' | 'EVALUATION_ERROR' | 'INTERNAL_ERROR';
message: string;
details?: unknown;
}
Example handling:
fancymenu.placeholders.get('unknown')
.catch(error => console.warn(error.code, error.message));
5. Complete Example
<!DOCTYPE html>
<html>
<head>
<title>FancyMenu Integration</title>
</head>
<body>
<h1>Game Controls</h1>
<button onclick="quitGame()">Quit Game</button>
<button onclick="openTitleScreen()">Title Screen</button>
<button onclick="disconnectFromServer()">Disconnect</button>
<button onclick="setVariable()">Set Variable</button>
<button onclick="loadPlaceholders()">Load Placeholders</button>
<div id="placeholderOutput" style="margin-top:16px;font-family:monospace"></div>
<script>
function getActions() {
if (typeof fancymenu === 'undefined') {
console.warn('FancyMenu API is not available yet.');
return null;
}
return fancymenu.actions || fancymenu;
}
function quitGame() {
const actions = getActions();
if (!actions) return;
actions.execute('quitgame');
}
function openTitleScreen() {
const actions = getActions();
if (!actions) return;
actions.executeWithCallback(
'opengui',
'title_screen',
() => console.log('Title screen opened!'),
err => console.error('Error:', err)
);
}
function disconnectFromServer() {
const actions = getActions();
if (!actions) return;
actions.execute('disconnect_server_or_world', 'title_screen');
}
function setVariable() {
const actions = getActions();
if (!actions) return;
var varName = prompt('Variable name:');
var varValue = prompt('Variable value:');
if (varName && varValue) {
actions.execute('set_variable', varName + ':' + varValue);
}
}
function loadPlaceholders() {
if (typeof fancymenu === 'undefined' || !fancymenu.placeholders) {
console.warn('FancyMenu placeholder API is not available yet.');
return;
}
Promise.all([
fancymenu.placeholders.get('playername'),
fancymenu.placeholders.getWithVars('uptime_duration', 'output_as_millis:false'),
fancymenu.placeholders.getWithVars(
'split_text',
'input:apple|banana|carrot',
'regex:\\|',
'max_parts:-1',
'split_index:1'
)
]).then(([playerName, uptimeSeconds, secondFruit]) => {
document.getElementById('placeholderOutput').textContent =
'Player: ' + playerName + '\n' +
'Uptime (seconds): ' + uptimeSeconds + '\n' +
'Second fruit: ' + secondFruit;
}).catch(error => {
console.error('Placeholder request failed:', error);
});
}
</script>
</body>
</html>
6. Best Practices & Notes
- Detect the bridge before using it, or listen for
fancymenu-ready. - Handle errors (callbacks for actions,
.catchfor placeholders) to present useful feedback. - Validate input before passing it to actions or placeholder variables.
- Throttle requests; avoid spamming the bridge with rapid-fire calls (especially placeholder refresh loops).
- Security: Browser content can invoke any registered FancyMenu action, including file, network, command, clipboard, resource-pack, link, and quit actions. Load only trusted pages, and validate all data received from web content.
7. Troubleshooting
- Confirm the page is loaded in a FancyMenu-controlled MCEF browser.
- Check the browser console for JavaScript errors.
- Verify the placeholder identifier or action type is correct and that required values are supplied.
- Review the Minecraft log (
latest.log) for FancyMenu error messages if execution fails unexpectedly.