Includes new page templates (fitness-gym, nonprofit, online-course, photography-studio, real-estate, startup-company, travel-blog, wedding-invitation) with thumbnail SVGs, test specs, documentation files, and minor updates to index.html, router.php, and playwright config. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
225 lines
7.5 KiB
HTML
225 lines
7.5 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Anchor Editable Field Test</title>
|
|
<style>
|
|
body {
|
|
padding: 40px;
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
}
|
|
|
|
.test-section {
|
|
margin: 30px 0;
|
|
padding: 20px;
|
|
border: 2px solid #e5e7eb;
|
|
border-radius: 8px;
|
|
}
|
|
|
|
.test-section h2 {
|
|
margin-top: 0;
|
|
color: #1f2937;
|
|
}
|
|
|
|
.test-section p {
|
|
color: #6b7280;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
/* Editor-only anchor visualization (simulates canvas styles) */
|
|
.editor-anchor {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
min-height: 28px;
|
|
border: 1px dashed #9ca3af;
|
|
padding: 4px 8px;
|
|
background: rgba(59,130,246,0.05);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.editor-anchor .anchor-icon {
|
|
font-size: 14px;
|
|
color: #6b7280;
|
|
line-height: 1;
|
|
}
|
|
|
|
.editor-anchor .anchor-name-input {
|
|
border: none;
|
|
background: transparent;
|
|
color: #374151;
|
|
font-size: 12px;
|
|
font-family: Inter, sans-serif;
|
|
font-weight: 500;
|
|
padding: 2px 4px;
|
|
outline: none;
|
|
min-width: 80px;
|
|
}
|
|
|
|
.editor-anchor .anchor-name-input:focus {
|
|
background: rgba(255,255,255,0.5);
|
|
border-radius: 2px;
|
|
}
|
|
|
|
/* Preview mode hiding */
|
|
.preview-mode .editor-anchor,
|
|
.preview-mode .editor-anchor .anchor-icon,
|
|
.preview-mode .editor-anchor .anchor-name-input {
|
|
display: none !important;
|
|
}
|
|
|
|
.toggle-btn {
|
|
padding: 10px 20px;
|
|
background: #3b82f6;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.toggle-btn:hover {
|
|
background: #2563eb;
|
|
}
|
|
|
|
.mode-indicator {
|
|
display: inline-block;
|
|
padding: 4px 12px;
|
|
background: #10b981;
|
|
color: white;
|
|
border-radius: 4px;
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
margin-left: 10px;
|
|
}
|
|
|
|
.preview-mode .mode-indicator {
|
|
background: #f59e0b;
|
|
}
|
|
|
|
.content-block {
|
|
background: #f9fafb;
|
|
padding: 20px;
|
|
border-radius: 6px;
|
|
margin: 10px 0;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Anchor Editable Field Test</h1>
|
|
<p>This page simulates the anchor behavior in the site builder.</p>
|
|
|
|
<button class="toggle-btn" onclick="toggleMode()">Toggle Preview Mode</button>
|
|
<span class="mode-indicator" id="mode-indicator">Editor Mode</span>
|
|
|
|
<div class="test-section" id="test-container">
|
|
<h2>Test 1: Editor Mode (Default)</h2>
|
|
<p>You should see the anchor with an editable text field below. Click on it to edit.</p>
|
|
|
|
<div class="content-block">
|
|
<p>Content before anchor</p>
|
|
|
|
<div data-anchor="true" id="anchor-1" class="editor-anchor">
|
|
<span class="anchor-icon">⚓</span>
|
|
<input type="text" class="anchor-name-input" value="anchor-1" placeholder="anchor-name" />
|
|
</div>
|
|
|
|
<p>Content after anchor</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h2>Test 2: Input Sync</h2>
|
|
<p>Edit the text field above and watch the ID update here:</p>
|
|
<div class="content-block">
|
|
<strong>Current Anchor ID:</strong> <code id="current-id">anchor-1</code>
|
|
</div>
|
|
<p><small>Try typing: "My Section", "pricing!", "Contact_Us", etc.</small></p>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h2>Test 3: Sanitization Rules</h2>
|
|
<div class="content-block">
|
|
<ul>
|
|
<li><strong>Spaces → hyphens:</strong> "My Section" becomes "my-section"</li>
|
|
<li><strong>Lowercase:</strong> "PRICING" becomes "pricing"</li>
|
|
<li><strong>Special chars removed:</strong> "contact!" becomes "contact"</li>
|
|
<li><strong>Underscores preserved:</strong> "section_1" stays "section_1"</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h2>Test 4: Preview Mode</h2>
|
|
<p>Click "Toggle Preview Mode" above. The anchor should become completely invisible.</p>
|
|
<div class="content-block">
|
|
<strong>Expected:</strong>
|
|
<ul>
|
|
<li>Icon hidden ✅</li>
|
|
<li>Input field hidden ✅</li>
|
|
<li>Dashed border hidden ✅</li>
|
|
<li>Content flows as if anchor doesn't exist ✅</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Simulate the sync logic from editor.js
|
|
const anchorInput = document.querySelector('.anchor-name-input');
|
|
const anchorContainer = anchorInput.closest('[data-anchor]');
|
|
const currentIdDisplay = document.getElementById('current-id');
|
|
|
|
function sanitizeId(value) {
|
|
return value
|
|
.toLowerCase()
|
|
.replace(/\s+/g, '-')
|
|
.replace(/[^a-z0-9-_]/g, '');
|
|
}
|
|
|
|
function updateIdFromInput() {
|
|
const newValue = anchorInput.value.trim();
|
|
if (newValue) {
|
|
const sanitized = sanitizeId(newValue);
|
|
anchorContainer.id = sanitized;
|
|
anchorInput.value = sanitized;
|
|
currentIdDisplay.textContent = sanitized;
|
|
}
|
|
}
|
|
|
|
// Prevent keyboard events from bubbling (simulating GrapesJS fix)
|
|
const stopPropagation = (e) => {
|
|
e.stopPropagation();
|
|
};
|
|
|
|
anchorInput.addEventListener('keydown', stopPropagation);
|
|
anchorInput.addEventListener('keyup', stopPropagation);
|
|
anchorInput.addEventListener('keypress', stopPropagation);
|
|
|
|
anchorInput.addEventListener('input', updateIdFromInput);
|
|
anchorInput.addEventListener('blur', updateIdFromInput);
|
|
|
|
// Toggle preview mode
|
|
function toggleMode() {
|
|
const container = document.getElementById('test-container');
|
|
const indicator = document.getElementById('mode-indicator');
|
|
const body = document.body;
|
|
|
|
body.classList.toggle('preview-mode');
|
|
|
|
if (body.classList.contains('preview-mode')) {
|
|
indicator.textContent = 'Preview Mode';
|
|
container.querySelector('h2').textContent = 'Test 1: Preview Mode (Anchor Hidden)';
|
|
container.querySelector('p').textContent = 'The anchor should be completely invisible now.';
|
|
} else {
|
|
indicator.textContent = 'Editor Mode';
|
|
container.querySelector('h2').textContent = 'Test 1: Editor Mode (Default)';
|
|
container.querySelector('p').textContent = 'You should see the anchor with an editable text field below. Click on it to edit.';
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|