dynamic_image_generator-1.0.x-dev/js/node-selection.js
js/node-selection.js
(function ($, Drupal, drupalSettings, once) {
'use strict';
function selectNodeForPreview(nodeId, nodeTitle) {
var autocompleteField = document.getElementById('edit-selected-node');
if (autocompleteField) {
autocompleteField.value = nodeTitle + ' (' + nodeId + ')';
autocompleteField.setAttribute('data-selected-node-id', nodeId);
autocompleteField.setAttribute('data-selected-node-title', nodeTitle);
console.log('Selected node for preview: ID=' + nodeId + ', Title=' + nodeTitle);
var event = new Event('change', { bubbles: true });
autocompleteField.dispatchEvent(event);
var closeEvent = new Event('autocompleteclose', { bubbles: true });
autocompleteField.dispatchEvent(closeEvent);
showLivePreviewButton();
} else {
console.error('Autocomplete field not found');
}
}
function showLivePreviewButton() {
var container = document.getElementById('live-preview-container');
if (container) {
container.style.display = 'block';
console.log('Live preview button shown');
} else {
console.error('Live preview container not found');
}
}
function hideLivePreviewButton() {
var container = document.getElementById('live-preview-container');
if (container) {
container.style.display = 'none';
console.log('Live preview button hidden');
}
}
// Make functions globally available
window.selectNodeForPreview = selectNodeForPreview;
window.showLivePreviewButton = showLivePreviewButton;
window.hideLivePreviewButton = hideLivePreviewButton;
Drupal.behaviors.nodeSelectionMonitor = {
attach: function (context, settings) {
console.log('NodeSelectionMonitor behavior attached');
// Check if live preview container exists
setTimeout(function() {
var container = document.getElementById('live-preview-container');
console.log('Live preview container found:', !!container);
if (container) {
console.log('Container display style:', container.style.display);
}
}, 1000);
// Use once properly with the imported once function
once('node-selection-monitor', '#edit-selected-node', context).forEach(function(element) {
var $field = $(element);
console.log('Monitoring autocomplete field:', $field.length);
function checkNodeSelection() {
var value = $field.val();
console.log('Checking node selection, field value:', value);
// Fixed regex pattern - no encoding issues in external JS file
if (value && value.match(/\((\d+)\)$/)) {
console.log('Valid node detected, showing live preview button');
showLivePreviewButton();
return true;
} else {
console.log('No valid node detected, hiding live preview button');
hideLivePreviewButton();
return false;
}
}
// Check initial state after a delay
setTimeout(function() {
checkNodeSelection();
}, 500);
// Monitor for autocomplete selections - this is the key event
$field.on('autocompleteselect', function(event, ui) {
console.log('Autocomplete select event triggered', ui);
if (ui && ui.item && ui.item.value) {
var value = ui.item.value;
console.log('Selected from autocomplete:', value);
var matches = value.match(/\((\d+)\)$/);
if (matches) {
var nodeId = matches[1];
var nodeTitle = value.replace(/\s*\(\d+\)$/, '');
$field.attr('data-selected-node-id', nodeId);
$field.attr('data-selected-node-title', nodeTitle);
console.log('Stored node selection: ID=' + nodeId + ', Title=' + nodeTitle);
// Force show the button after selection
setTimeout(function() {
showLivePreviewButton();
}, 100);
}
}
});
// Also monitor the autocompletechange event
$field.on('autocompletechange', function(event, ui) {
console.log('Autocomplete change event triggered');
setTimeout(checkNodeSelection, 200);
});
// Monitor for manual typing/changes
$field.on('input keyup paste change', function() {
setTimeout(checkNodeSelection, 300);
});
// Monitor for field being cleared or losing focus
$field.on('blur', function() {
setTimeout(checkNodeSelection, 200);
});
// Monitor for autocomplete close (when dropdown closes)
$field.on('autocompleteclose', function() {
setTimeout(checkNodeSelection, 200);
});
});
}
};
Drupal.behaviors.livePreviewHandler = {
attach: function (context, settings) {
// Use once properly with the imported once function
once('live-preview', '.live-preview-trigger', context).forEach(function(element) {
var $link = $(element);
// DISABLE the original AJAX behavior to prevent double-firing
if (Drupal.ajax && Drupal.ajax.instances) {
Drupal.ajax.instances = Drupal.ajax.instances.filter(function(instance) {
return instance && instance.element !== element;
});
}
// Remove any existing Drupal AJAX classes and attributes
$link.removeClass('use-ajax').removeAttr('data-dialog-type');
$link.off('click.livePreview').on('click.livePreview', function(e) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
// Prevent double-clicking
if ($link.data('processing')) {
return false;
}
$link.data('processing', true);
// Show loader immediately
var $loader = $('<div class="live-preview-loader" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 9999; display: flex; align-items: center; justify-content: center;">' +
'<div style="background: white; padding: 30px; border-radius: 8px; text-align: center; box-shadow: 0 4px 20px rgba(0,0,0,0.3);">' +
'<div style="width: 40px; height: 40px; border: 4px solid #f3f3f3; border-top: 4px solid #007bff; border-radius: 50%; animation: spin 1s linear infinite; margin: 0 auto 15px;"></div>' +
'<p style="margin: 0; font-weight: bold; color: #333;">Generating Live Preview...</p>' +
'<p style="margin: 5px 0 0; font-size: 0.9em; color: #666;">Using current HTML/CSS from form fields</p>' +
'</div>' +
'</div>');
// Add spinner animation CSS
if (!$('#live-preview-spinner-css').length) {
$('<style id="live-preview-spinner-css">@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }</style>').appendTo('head');
}
$('body').append($loader);
// Function to remove loader and reset state
function cleanupLoader() {
$loader.remove();
$link.removeData('processing');
// Force clean body state
$('body').removeClass('ui-dialog-open').css({
'overflow': 'auto',
'padding-right': '0px'
});
}
// Get the form data BEFORE making the request
var formData = {};
var selectedNodeValue = '';
// Find the autocomplete field
var autocompleteField = $('#edit-selected-node');
if (autocompleteField.length) {
var fieldValue = autocompleteField.val();
if (fieldValue && fieldValue.match(/\((\d+)\)$/)) {
selectedNodeValue = fieldValue;
}
}
// Build form data - CURRENT VALUES FROM FORM FIELDS (NOT SAVED DATA)
var htmlTextarea = $('textarea[name*="html"]').first();
if (htmlTextarea.length) {
formData.template_html = htmlTextarea.val();
}
var cssTextarea = $('textarea[name*="css"]').first();
if (cssTextarea.length) {
formData.template_css = cssTextarea.val();
}
if (selectedNodeValue) {
formData.selected_node = selectedNodeValue;
}
formData.preview_mode = 'live';
formData.trigger_type = 'live_preview_button';
// Make AJAX request
var originalHref = $link.attr('href');
$.ajax({
url: originalHref,
type: 'POST',
data: {
form_data: JSON.stringify(formData)
},
timeout: 30000,
success: function(response) {
// Remove loader first
cleanupLoader();
// Handle the AJAX response commands
if (response && response.length > 0) {
for (var i = 0; i < response.length; i++) {
var command = response[i];
if (command.command === 'openModalDialog' || command.command === 'openDialog') {
var dialogOptions = command.dialogOptions || {};
var title = dialogOptions.title || 'Live Preview';
var width = dialogOptions.width || 900;
var height = dialogOptions.height || 700;
// Check if we have actual content
if (!command.data || command.data.trim() === '') {
alert('Preview generated but no content received. Check server logs.');
return;
}
// SIMPLIFIED DIALOG APPROACH - Create a simple modal without jQuery UI complications
var modalId = 'live-preview-modal-' + Date.now();
var $modal = $('<div id="' + modalId + '" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 10000; display: flex; align-items: center; justify-content: center;">' +
'<div style="background: white; max-width: 90%; max-height: 90%; overflow: auto; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.5); position: relative;">' +
'<div style="padding: 20px; border-bottom: 1px solid #ddd; display: flex; justify-content: space-between; align-items: center; background: #f8f9fa;">' +
'<h3 style="margin: 0; color: #2c3e50;">' + title + '</h3>' +
'<button id="close-' + modalId + '" style="background: #dc3545; color: white; border: none; padding: 8px 12px; border-radius: 4px; cursor: pointer; font-size: 16px;">×</button>' +
'</div>' +
'<div style="padding: 20px; min-width: 800px; min-height: 500px;">' + command.data + '</div>' +
'</div>' +
'</div>');
// Add to body
$('body').append($modal);
// Add close functionality
$('#close-' + modalId + ', #' + modalId).on('click', function(e) {
if (e.target === this) {
$modal.remove();
cleanupLoader(); // Extra cleanup
}
});
// Prevent clicks inside modal from closing it
$modal.find('> div').on('click', function(e) {
e.stopPropagation();
});
break;
}
}
}
},
error: function(xhr, status, error) {
// Remove loader on error
cleanupLoader();
alert('Live preview request failed: ' + error);
}
});
return false;
});
});
// ALSO disable the original preview button to prevent confusion
once('disable-original-preview', 'input[value*="Preview"]', context).forEach(function(element) {
var $button = $(element);
if ($button.val().indexOf('Preview') !== -1 && !$button.hasClass('live-preview-trigger')) {
// Remove AJAX behavior
if (Drupal.ajax && Drupal.ajax.instances) {
Drupal.ajax.instances = Drupal.ajax.instances.filter(function(instance) {
return instance && instance.element !== element;
});
}
$button.removeClass('use-ajax').removeAttr('data-dialog-type');
// Hide the button instead of showing alert
$button.hide();
}
});
// Hide all sample data preview buttons
once('hide-sample-buttons', 'input[value*="sample"], input[value*="Sample"], input[value*="Test with sample"], input[value*="Preview"]', context).forEach(function(element) {
var $button = $(element);
if (!$button.hasClass('live-preview-trigger')) {
// Remove AJAX behavior
if (Drupal.ajax && Drupal.ajax.instances) {
Drupal.ajax.instances = Drupal.ajax.instances.filter(function(instance) {
return instance && instance.element !== element;
});
}
$button.removeClass('use-ajax').removeAttr('data-dialog-type');
// Hide the button completely
$button.hide();
}
});
}
};
})(jQuery, Drupal, drupalSettings, once);
