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);

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc