-
-
-
- Yükleniyor...
- Önizleme için içerik girin
-
+ x-transition
+ x-transition:enter="transition ease-out duration-200"
+ x-transition:enter-start="opacity-0"
+ x-transition:enter-end="opacity-100"
+ x-transition:leave="transition ease-in duration-150"
+ x-transition:leave-start="opacity-100"
+ x-transition:leave-end="opacity-0">
+
+
+
+
+
+ Yükleniyor...
+ Önizleme hazırlanıyor
+
+
+ İçerik işleniyor
+ Önizleme için HTML içeriği girin
+
+
@@ -64,176 +76,256 @@ function templatePreview(previewUrl, type, fieldName) {
isLoading: false,
content: '',
debounceTimer: null,
+ intervalId: null,
+ codeMirrorView: null,
init() {
- // Watch Livewire events for Filament form updates
- if (window.Livewire) {
- // Listen for form state updates
- Livewire.on('filament-forms::update-state', ({ statePath, state }) => {
- if (statePath === this.fieldName || statePath?.endsWith(this.fieldName)) {
- this.content = state || '';
- this.debouncedUpdate();
- }
- });
-
- // Listen for any Livewire updates
- document.addEventListener('livewire:update', () => {
- this.debouncedUpdate();
- });
- }
+ console.log('[Preview] Init:', { previewUrl, type, fieldName });
- // Watch CodeMirror editor directly
- this.watchCodeMirror();
-
- // Watch for direct input changes (fallback for code editor)
- const observer = new MutationObserver(() => {
- this.debouncedUpdate();
+ // Wait for everything to load
+ this.$nextTick(() => {
+ setTimeout(() => {
+ this.findCodeMirror();
+ this.setupWatchers();
+ this.updatePreview();
+ }, 1500);
});
-
- // Observe form changes
- const form = document.querySelector('form[wire\\:submit]');
- if (form) {
- observer.observe(form, {
- childList: true,
- subtree: true,
- characterData: true,
- });
- }
-
- // Initial update after a short delay
- setTimeout(() => {
- this.updatePreview();
- }, 1000);
-
- // Periodic update fallback (every 3 seconds)
- this.intervalId = setInterval(() => {
- this.updatePreview();
- }, 3000);
},
- watchCodeMirror() {
- // Try to find CodeMirror editor instance
- const findCodeMirror = () => {
- // Look for CodeMirror editor instances
- const editors = document.querySelectorAll('.cm-editor, [data-code-editor]');
- editors.forEach(editor => {
- // Check if this is our field
- const fieldWrapper = editor.closest('[data-field-name], .fi-fo-field-wrp');
- if (fieldWrapper) {
- const fieldLabel = fieldWrapper.querySelector('label');
- if (fieldLabel && fieldLabel.textContent.includes('HTML Content')) {
- // Found our editor, try to get CodeMirror instance
- const cmInstance = editor.__cm || editor.cm || editor;
- if (cmInstance && cmInstance.getValue) {
- // Watch for changes
- if (cmInstance.on) {
- cmInstance.on('change', () => {
- this.content = cmInstance.getValue();
- this.debouncedUpdate();
- });
+ findCodeMirror() {
+ console.log('[Preview] Looking for CodeMirror editor for field:', this.fieldName);
+
+ // Try multiple wrapper selectors for Filament 4 compatibility
+ const wrapperSelectors = [
+ '.fi-fo-field-wrp',
+ '.fi-input-wrp',
+ '[wire\\:id]',
+ ];
+
+ // Debug: List all field wrappers
+ let allWrappers = [];
+ wrapperSelectors.forEach(selector => {
+ const wrappers = document.querySelectorAll(selector);
+ if (wrappers.length > 0) {
+ console.log(`[Preview] Found ${wrappers.length} wrappers with selector: ${selector}`);
+ allWrappers = Array.from(wrappers);
+ }
+ });
+
+ // Remove duplicates
+ allWrappers = Array.from(new Set(allWrappers));
+ console.log('[Preview] Total unique field wrappers found:', allWrappers.length);
+
+ let targetWrapper = null;
+
+ // Method 1: Find by data-field-name attribute (anywhere in wrapper)
+ const dataFieldElements = document.querySelectorAll(`[data-field-name="${this.fieldName}"]`);
+ if (dataFieldElements.length > 0) {
+ console.log('[Preview] Found', dataFieldElements.length, 'elements with data-field-name');
+ // Try to find closest wrapper from any selector
+ for (const selector of wrapperSelectors) {
+ targetWrapper = dataFieldElements[0].closest(selector);
+ if (targetWrapper) break;
+ }
+ }
+
+ // Method 2: Find by name attribute in textarea or input
+ if (!targetWrapper) {
+ const input = document.querySelector(`textarea[name="${this.fieldName}"], input[name="${this.fieldName}"]`);
+ if (input) {
+ console.log('[Preview] Found input/textarea with name:', this.fieldName);
+ for (const selector of wrapperSelectors) {
+ targetWrapper = input.closest(selector);
+ if (targetWrapper) break;
+ }
+ }
+ }
+
+ // Method 3: Find all CodeMirror editors and check their wrappers
+ if (!targetWrapper) {
+ const cmEditors = document.querySelectorAll('.cm-editor');
+ console.log('[Preview] Found', cmEditors.length, 'CodeMirror editors');
+ cmEditors.forEach((cmEditor, idx) => {
+ for (const selector of wrapperSelectors) {
+ const wrapper = cmEditor.closest(selector);
+ if (wrapper) {
+ const label = wrapper.querySelector('label');
+ console.log(`[Preview] CM Editor ${idx} wrapper label:`, label?.textContent?.substring(0, 30));
+
+ // If this is the only CodeMirror editor, use it
+ // Or if label contains HTML/Content
+ if (cmEditors.length === 1 || (label && (label.textContent.toLowerCase().includes('html') || label.textContent.toLowerCase().includes('content')))) {
+ if (!targetWrapper) {
+ targetWrapper = wrapper;
+ console.log('[Preview] Selected wrapper for CM Editor', idx);
}
}
+ break;
+ }
+ }
+ });
+ }
+
+ // Method 4: Find by label text (fallback)
+ if (!targetWrapper && allWrappers.length > 0) {
+ allWrappers.forEach((wrapper) => {
+ const label = wrapper.querySelector('label');
+ if (label) {
+ const labelText = label.textContent.toLowerCase();
+ if ((labelText.includes('html') || labelText.includes('content')) && !targetWrapper) {
+ const hasEditor = wrapper.querySelector('.cm-editor, textarea');
+ if (hasEditor) {
+ targetWrapper = wrapper;
+ console.log('[Preview] Selected wrapper by label:', labelText.substring(0, 30));
+ }
}
}
});
- };
+ }
- // Try immediately and after a delay
- findCodeMirror();
- setTimeout(findCodeMirror, 1000);
- setTimeout(findCodeMirror, 2000);
+ if (!targetWrapper) {
+ console.warn('[Preview] Field wrapper not found. Available wrappers:', allWrappers.length);
+ console.warn('[Preview] Trying to find any CodeMirror editor...');
+
+ // Last resort: Use first CodeMirror editor found
+ const firstCmEditor = document.querySelector('.cm-editor');
+ if (firstCmEditor) {
+ for (const selector of wrapperSelectors) {
+ targetWrapper = firstCmEditor.closest(selector);
+ if (targetWrapper) break;
+ }
+ console.log('[Preview] Using first CodeMirror editor as fallback');
+ }
+ }
+
+ if (!targetWrapper) {
+ console.error('[Preview] Could not find field wrapper. Make sure the CodeEditor is rendered.');
+ return;
+ }
+
+ console.log('[Preview] Found field wrapper');
+
+ // Try to find CodeMirror editor
+ const cmEditor = targetWrapper.querySelector('.cm-editor');
+ if (cmEditor) {
+ console.log('[Preview] Found .cm-editor element');
+
+ // Try to get from cm-content (CodeMirror 6)
+ const cmContent = cmEditor.querySelector('.cm-content');
+ if (cmContent) {
+ console.log('[Preview] Found .cm-content element');
+
+ // Watch for changes
+ const observer = new MutationObserver(() => {
+ const newContent = cmContent.textContent || '';
+ if (newContent !== this.content) {
+ this.content = newContent;
+ console.log('[Preview] Content changed, length:', this.content.length);
+ this.debouncedUpdate();
+ }
+ });
+ observer.observe(cmContent, {
+ childList: true,
+ subtree: true,
+ characterData: true,
+ });
+
+ // Get initial content
+ this.content = cmContent.textContent || '';
+ console.log('[Preview] Initial content from .cm-content, length:', this.content.length);
+
+ if (this.content) {
+ return; // Success!
+ }
+ }
+
+ // Try CodeMirror 6 View
+ if (cmEditor.view || cmEditor._view) {
+ const view = cmEditor.view || cmEditor._view;
+ if (view.state && view.state.doc) {
+ this.content = view.state.doc.toString();
+ console.log('[Preview] Found CodeMirror 6 View, content length:', this.content.length);
+
+ if (view.dispatch) {
+ // Watch for changes
+ const originalDispatch = view.dispatch;
+ view.dispatch = (tr) => {
+ originalDispatch.call(view, tr);
+ this.content = view.state.doc.toString();
+ this.debouncedUpdate();
+ };
+ }
+
+ if (this.content) {
+ return; // Success!
+ }
+ }
+ }
+
+ // Try CodeMirror 5
+ const cmInstance = cmEditor.__cm || cmEditor.cm;
+ if (cmInstance) {
+ console.log('[Preview] Found CodeMirror 5 instance');
+ if (cmInstance.getValue) {
+ this.content = cmInstance.getValue();
+ cmInstance.on('change', () => {
+ this.content = cmInstance.getValue();
+ this.debouncedUpdate();
+ });
+ console.log('[Preview] CodeMirror 5 content length:', this.content.length);
+ if (this.content) {
+ return; // Success!
+ }
+ }
+ }
+ } else {
+ // Try textarea
+ const textarea = targetWrapper.querySelector('textarea');
+ if (textarea) {
+ console.log('[Preview] Found textarea');
+ this.content = textarea.value || '';
+ textarea.addEventListener('input', () => {
+ this.content = textarea.value;
+ this.debouncedUpdate();
+ });
+ console.log('[Preview] Textarea content length:', this.content.length);
+ } else {
+ console.warn('[Preview] No CodeMirror editor or textarea found in wrapper');
+ }
+ }
+ },
+
+ setupWatchers() {
+ // Watch for Livewire updates
+ if (window.Livewire) {
+ document.addEventListener('livewire:update', () => {
+ this.findCodeMirror();
+ this.debouncedUpdate();
+ });
+ }
+
+ // Periodic update
+ this.intervalId = setInterval(() => {
+ this.findCodeMirror();
+ this.updatePreview();
+ }, 3000);
},
debouncedUpdate() {
clearTimeout(this.debounceTimer);
this.debounceTimer = setTimeout(() => {
this.updatePreview();
- }, 500); // 500ms debounce
+ }, 800);
},
async updatePreview() {
- // Get content from Livewire - try different methods
- let content = this.content || '';
-
- try {
- // Method 1: Try CodeMirror editor directly (most reliable for CodeEditor)
- // Find editor by data-field-name attribute
- const fieldWrapper = document.querySelector(`[data-field-name="${this.fieldName}"]`);
- if (fieldWrapper) {
- const cmEditor = fieldWrapper.querySelector('.cm-editor');
- if (cmEditor) {
- const cmInstance = cmEditor.__cm || cmEditor.cm || window.CodeMirror?.fromTextArea?.(cmEditor.querySelector('textarea'));
- if (cmInstance && typeof cmInstance.getValue === 'function') {
- content = cmInstance.getValue() || '';
- } else if (cmEditor.querySelector('.cm-content')) {
- // Fallback: get text from content div
- content = cmEditor.querySelector('.cm-content').textContent || '';
- }
- }
- }
-
- // Method 1b: Try all CodeMirror editors if specific one not found
- if (!content) {
- const cmEditors = document.querySelectorAll('.cm-editor');
- for (const cmEditor of cmEditors) {
- const fieldWrapper = cmEditor.closest('[data-field-name]');
- if (fieldWrapper && fieldWrapper.getAttribute('data-field-name') === this.fieldName) {
- const cmInstance = cmEditor.__cm || cmEditor.cm;
- if (cmInstance && typeof cmInstance.getValue === 'function') {
- content = cmInstance.getValue() || '';
- if (content) break;
- } else if (cmEditor.querySelector('.cm-content')) {
- content = cmEditor.querySelector('.cm-content').textContent || '';
- if (content) break;
- }
- }
- }
- }
-
- // Method 2: Try to find CodeEditor textarea/input directly
- if (!content) {
- const codeEditor = document.querySelector(`textarea[name="${this.fieldName}"],
- textarea[wire\\:model*="${this.fieldName}"],
- .fi-fo-field-wrp textarea,
- .cm-content`);
-
- if (codeEditor) {
- content = codeEditor.value || codeEditor.textContent || '';
- }
- }
-
- // Method 3: Try Livewire $wire
- if (!content && window.Livewire) {
- // Find the Livewire component
- const livewireComponent = document.querySelector('[wire\\:id], form[wire\\:submit]');
- if (livewireComponent) {
- const wireId = livewireComponent.getAttribute('wire:id');
- if (wireId) {
- const livewire = window.Livewire.find(wireId);
- if (livewire && livewire.get) {
- content = livewire.get(this.fieldName) || '';
- }
- } else {
- // Try Alpine.js $wire
- const alpineData = Alpine.$data(livewireComponent);
- if (alpineData && alpineData.$wire && alpineData.$wire.get) {
- content = alpineData.$wire.get(this.fieldName) || '';
- }
- }
- }
- }
- } catch (e) {
- console.warn('Could not get content:', e);
+ // Try to refresh content
+ if (!this.content) {
+ this.findCodeMirror();
}
- // Use existing content if new fetch failed
- if (!content && this.content) {
- content = this.content;
- }
-
- this.content = content;
-
- if (!this.content || this.content.trim() === '') {
+ if (!this.content || !this.content.trim()) {
+ console.log('[Preview] No content, skipping update');
if (this.iframeSrc) {
URL.revokeObjectURL(this.iframeSrc);
this.iframeSrc = '';
@@ -244,13 +336,11 @@ function templatePreview(previewUrl, type, fieldName) {
this.isLoading = true;
try {
- // Create form data
const formData = new FormData();
formData.append('content', this.content);
formData.append('type', this.type);
formData.append('_token', document.querySelector('meta[name="csrf-token"]')?.content || '');
- // Fetch preview HTML
const response = await fetch(this.previewUrl, {
method: 'POST',
body: formData,
@@ -261,28 +351,38 @@ function templatePreview(previewUrl, type, fieldName) {
});
if (!response.ok) {
- throw new Error('Preview request failed');
+ throw new Error(`HTTP ${response.status}`);
}
const html = await response.text();
- // Create blob URL for iframe
- const blob = new Blob([html], { type: 'text/html; charset=utf-8' });
-
- // Revoke old URL if exists
if (this.iframeSrc) {
URL.revokeObjectURL(this.iframeSrc);
}
+ const blob = new Blob([html], { type: 'text/html; charset=utf-8' });
this.iframeSrc = URL.createObjectURL(blob);
this.isLoading = false;
+
+ console.log('[Preview] Updated successfully, content length:', this.content.length);
} catch (error) {
- console.error('Preview error:', error);
+ console.error('[Preview] Error:', error);
this.isLoading = false;
}
+ },
+
+ destroy() {
+ if (this.intervalId) {
+ clearInterval(this.intervalId);
+ }
+ if (this.debounceTimer) {
+ clearTimeout(this.debounceTimer);
+ }
+ if (this.iframeSrc) {
+ URL.revokeObjectURL(this.iframeSrc);
+ }
}
};
}
@endpush
-