Schema Editor iframe Integration Guide
This guide explains how to embed the schema editor in your application using iframes, including configuration options and communication patterns.
Basic iframe Integration
Embedding an iframe allows you to integrate external applications into your web application. Below is information on how to integrate an iframe and set up message communication using the postMessage
method.
Simple iframe Embedding
<!DOCTYPE html>
<html>
<head>
<style>
.container {
height: 100vh;
display: flex;
flex-direction: column;
}
iframe {
flex-grow: 1;
border: none;
}
</style>
</head>
<body>
<div class="container">
<!-- create iframe using js -->
<div class="controls">
<button id="openModalBtn">Open in modal window</button>
<span id="messageDisplay"></span>
</div>
<!-- or html -->
<iframe src="/app/venues/2/schemas/150" width="100%" height="100%"></iframe>
</div>
</body>
</html>
Modal Window Integration
Creating a Modal with an iframe
document.getElementById('openModalBtn').addEventListener('click', function() {
const modal = document.createElement('div');
modal.style.position = 'fixed';
modal.style.top = '0';
modal.style.left = '0';
modal.style.width = '100%';
modal.style.height = '100%';
modal.style.backgroundColor = 'rgba(0,0,0,0.5)';
const iframe = document.createElement('iframe');
iframe.src = '/app/venues/2/schemas/150?hideNavbar=true';
iframe.style.width = '95%';
iframe.style.height = '95%';
modal.appendChild(iframe);
document.body.appendChild(modal);
});
Message Communication
Message Types
The schema editor supports several message types for communication between the parent application and the iframe.
1. MODAL_CLOSING
Allows closing the modal window safely preventing accidental data loss.
Parent Application Behavior
document.getElementById('closeBtn').addEventListener('click', function() {
iframe.contentWindow.postMessage({ type: 'MODAL_CLOSING' }, '*');
});
iframe Application Behavior
window.addEventListener('message', (event) => {
if (event.data.type === 'MODAL_CLOSING') {
// Check for unsaved changes
if (hasUnsavedChanges) {
const shouldClose = window.confirm('You have unsaved changes. Close anyway?');
window.parent.postMessage({
type: 'MODAL_CLOSE_RESPONSE',
canClose: shouldClose
}, '*');
} else {
window.parent.postMessage({
type: 'MODAL_CLOSE_RESPONSE',
canClose: true
}, '*');
}
}
});
2. SCHEMA_CHANGED
Allows the iframe to notify the parent application about data modifications.
iframe Application Behavior
// In a state management selector or change detection logic
if (window !== window.parent) {
window.parent.postMessage({
type: 'SCHEMA_CHANGED',
hasChanges: detectChanges(),
changedEntities: ['seats', 'rows', 'sections']
}, '*');
}
Parent Application Behavior
window.addEventListener('message', function (event) {
if (event.data.type === 'SCHEMA_CHANGED') {
console.log('Schema changed:', event.data.hasChanges);
// Update UI, trigger save prompts, etc.
updateSaveStatus(event.data.hasChanges);
}
});
Schema Editing Screen Configuration
The schema editing interface can be accessed through two primary URL patterns:
/app/venues/{venueId}/schemas/{schemaId} // Edit existing schema
/app/venues/{venueId}/schemas/new // Create new schema
Where venueId
is the ID of the venue and schemaId
is the ID of the schema to edit, or “new” to create a new schema.
Customizing the UI with URL Parameters
The schema editor interface can be customized using various URL parameters:
1. Hiding UI Elements
Use the hidden
parameter to hide specific toolbar elements:
/app/venues/2/schemas/150?hidden=pricing,save,shape
The example above would hide the pricing mode button, save button, and shape tools from the interface.
2. Hiding the Navbar
To create a more embedded experience, you can hide the top navigation bar:
/app/venues/2/schemas/150?hideNavbar=true
This is particularly useful for iframe integration, providing a cleaner interface with only the editor components.
3. Forcing Pricing Tools Display
Even if pricing tools are hidden by default or through the hidden
parameter, you can force them to appear:
/app/venues/2/schemas/150?showPricing=true
4. Combining Parameters
These parameters can be combined to create a highly customized editing experience:
/app/venues/2/schemas/150?hideNavbar=true&hidden=save,shape&showPricing=true
Complete Implementation Example
Here’s a complete example that demonstrates embedding the schema editor in a modal with customized UI and message handling:
function openSchemaEditor(venueId, schemaId, options = {}) {
// Create modal container
const modal = document.createElement('div');
modal.style.position = 'fixed';
modal.style.top = '0';
modal.style.left = '0';
modal.style.width = '100%';
modal.style.height = '100%';
modal.style.backgroundColor = 'rgba(0,0,0,0.5)';
modal.style.zIndex = '9999';
modal.style.display = 'flex';
modal.style.justifyContent = 'center';
modal.style.alignItems = 'center';
// Create close button
const closeBtn = document.createElement('button');
closeBtn.textContent = 'Close';
closeBtn.style.position = 'absolute';
closeBtn.style.top = '10px';
closeBtn.style.right = '10px';
closeBtn.style.zIndex = '10000';
modal.appendChild(closeBtn);
// Create iframe
const iframe = document.createElement('iframe');
// Build the base URL
let url = `/app/venues/${venueId}/schemas/${schemaId}`;
// Build query parameters
const params = new URLSearchParams();
// Hide specific UI elements if specified
if (options.hiddenElements && options.hiddenElements.length > 0) {
params.set('hidden', options.hiddenElements.join(','));
}
// Hide navbar if specified (default to true for modal)
if (options.hideNavbar !== false) {
params.set('hideNavbar', 'true');
}
// Force show pricing if specified
if (options.showPricing) {
params.set('showPricing', 'true');
}
// Append parameters if any exist
if (params.toString()) {
url += `?${params.toString()}`;
}
iframe.src = url;
iframe.style.width = '95%';
iframe.style.height = '95%';
iframe.style.border = 'none';
modal.appendChild(iframe);
document.body.appendChild(modal);
let hasUnsavedChanges = false;
// Set up message listener for schema changes
window.addEventListener('message', function(event) {
// Handle schema changes
if (event.data.type === 'SCHEMA_CHANGED') {
console.log('Schema modified:', event.data);
hasUnsavedChanges = event.data.hasChanges;
// Update UI to indicate unsaved changes
if (hasUnsavedChanges) {
closeBtn.textContent = 'Close*';
} else {
closeBtn.textContent = 'Close';
}
}
// Handle close confirmation response
if (event.data.type === 'MODAL_CLOSE_RESPONSE' && event.data.canClose) {
document.body.removeChild(modal);
}
});
// Set up close button handler with confirmation
closeBtn.addEventListener('click', function() {
if (hasUnsavedChanges) {
iframe.contentWindow.postMessage({ type: 'MODAL_CLOSING' }, '*');
} else {
document.body.removeChild(modal);
}
});
// Return control functions
return {
close: function() {
if (hasUnsavedChanges) {
iframe.contentWindow.postMessage({ type: 'MODAL_CLOSING' }, '*');
} else {
document.body.removeChild(modal);
}
},
getIframe: function() {
return iframe;
}
};
}
// Example usage:
document.getElementById('openEditorBtn').addEventListener('click', function() {
const editor = openSchemaEditor(2, 150, {
hiddenElements: ['save', 'tool.shape.circle', 'tool.shape.polygon'],
showPricing: true
});
});
Available UI Elements
The schema editor toolbar consists of several modes and tools that can be selectively hidden:
Editor Modes
// Mode options that can be hidden
const modes = {
'mode.schema': 'Schema editing mode',
'mode.underlay': 'Underlay/background editing',
'mode.venueShape': 'Venue shape editing',
'mode.pricingZones': 'Pricing zones configuration',
'mode.pricing': 'Pricing management',
'mode.section': 'Section editing mode'
};
Schema Tools
// Tools available in Schema mode
const schemaTools = {
'tool.select': 'Selection tool',
'tool.seatRows': 'Add seat rows tool',
'tool.table': 'Add table tool',
'tool.shape': 'Add shapes (all types)',
'tool.shape.rect': 'Add rectangle shape',
'tool.shape.circle': 'Add circle shape',
'tool.shape.line': 'Add line shape',
'tool.shape.polygon': 'Add polygon shape',
'tool.label': 'Add label tool'
};
Section Tools
// Tools available in Section mode
const sectionTools = {
'tool.selectSeats': 'Select individual seats',
'tool.selectRows': 'Select entire rows',
'tool.addSeat': 'Add individual seats',
'tool.numberSeats': 'Number seats automatically'
};
Pricing Tools
// Tools available in Pricing modes
const pricingTools = {
'tool.selectSeats': 'Select individual seats',
'tool.selectRows': 'Select entire rows',
'tool.selectSections': 'Select entire sections'
};
Underlay Tools
// Tools available in Underlay mode
const underlayTools = {
'tool.importSvgBackground': 'Import SVG as background',
'tool.exportSvgBackground': 'Export SVG background',
'tool.removeSvgBackground': 'Remove SVG background',
'tool.viewbox': 'Adjust viewbox'
};
Global Tools
// Global tools
const globalTools = {
'tool.save': 'Save changes',
'tool.publish': 'Publish schema (only appears when in draft mode)',
'tool.preview': 'Preview schema (only appears when event ID is available)'
};
Hiding Elements in the URL
You can use either the full identifier (e.g., mode.schema
) or the short identifier (e.g., schema
) in the URL parameter:
?hidden=schema,pricing,save
Or using full identifiers:
?hidden=mode.schema,mode.pricing,tool.save
Editor Layout Adjustments
When hiding the navbar using hideNavbar=true
, the editor automatically adjusts its layout:
- The top navigation bar is completely removed
- The content area and sidebar heights are increased to fill the available space
- The publish button is hidden in the sidebar (controlled by the
hidePublishing
prop)
This creates a cleaner, more focused editing experience ideal for iframe embedding.
Use Cases and Examples
1. Read-Only View for Customers
// Open a read-only view of the schema with minimal UI
openSchemaEditor(2, 150, {
hideNavbar: true,
hiddenElements: [
'save', 'tool.shape', 'tool.table', 'tool.label', 'tool.seatRows',
'mode.underlay', 'mode.venueShape', 'mode.pricingZones', 'mode.pricing',
'tool.addSeat', 'tool.numberSeats'
]
});
2. Pricing-Focused Editor
// Open editor focused on pricing configuration
openSchemaEditor(2, 150, {
hideNavbar: true,
showPricing: true,
hiddenElements: [
'mode.schema', 'mode.underlay', 'mode.venueShape',
'tool.shape', 'tool.label', 'tool.seatRows', 'tool.table'
]
});
3. Schema Creation Wizard
// Open editor for creating a new schema with step-by-step guidance
openSchemaEditor(2, 'new', {
hideNavbar: true,
hiddenElements: [
'mode.pricing', 'mode.pricingZones',
'tool.shape.polygon', 'tool.shape.line'
]
});
Implementing Custom Message Types
You can extend the message communication between the parent application and the schema editor by implementing custom message types:
// In the parent application
function sendCustomCommand(iframe, command, data) {
iframe.contentWindow.postMessage({
type: 'CUSTOM_COMMAND',
command: command,
data: data
}, '*');
}
// Example: Set zoom level
sendCustomCommand(editorIframe, 'SET_ZOOM', { level: 0.75 });
// Example: Focus on a specific section
sendCustomCommand(editorIframe, 'FOCUS_SECTION', { sectionId: 'A3' });
These custom commands would need corresponding handlers in the iframe application.