# easy-invoice/2.4.2/templates/invoices/live-preview.php

Easy Invoice – Invoice Generator, PDF Quotes &amp; Payments, version 2.4.2. 292 lines.

- Page: https://pluginprobe.com/plugins/easy-invoice/2.4.2/code/templates/invoices/live-preview.php
- Raw: https://pluginprobe.com/plugins/easy-invoice/2.4.2/raw/templates/invoices/live-preview.php
- Modified: 2026-09-29T05:21:04+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/easy-invoice/2.4.2/code/templates/invoices/live-preview.php#L10-L20`.

```php
<?php
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}
?> <div class="bg-white shadow rounded-lg" style="padding: 10px;">

                    <div class="px-6 py-5 border-b border-gray-200" style="margin-bottom: 10px;">
                        <div class="flex justify-between items-center">
                        <div class="flex items-center">
                            <div class="flex-shrink-0 bg-indigo-100 rounded-lg p-3">
                                <i class="fas fa-eye text-indigo-600 text-xl"></i>
                            </div>
                            <div class="ml-4">
                                <h2 class="text-lg font-medium text-gray-900"><?php esc_html_e('Invoice Preview', 'easy-invoice'); ?></h2>
                                <p class="mt-1 text-sm text-gray-500"><?php esc_html_e('Live preview of your invoice', 'easy-invoice'); ?></p>
                            </div>
                            </div>
                            <?php if($invoice_id > 0 ){ ?>
                            <a href="<?php echo esc_url(get_permalink($invoice_id)); ?>" target="_blank" class="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
                                <i class="fas fa-external-link-alt mr-2"></i>
                                Full Preview
                            </a>
                            <?php } ?>
                        </div>
                    </div>

                    <?php
                    // Get the current template (default to 'standard')
                    $current_template = $invoice ? $invoice->getTemplate() : 'standard';
                    if (empty($current_template)) {
                        $current_template = 'standard';
                    }
                    $template_class = 'template-' . $current_template;

                    // Initialize formatter for the invoice templates
                    $formatter = new \EasyInvoice\Helpers\InvoiceFormatter($invoice);
                    ?>

                    <div id="invoice-container" class="invoice-container">
                        <?php
                        // Add custom template builder CSS if using a custom template
                        if ($invoice && method_exists($invoice, 'getId')) {
                            $template_id = get_post_meta($invoice->getId(), '_easy_invoice_invoice_template', true);
                            if ($template_id && class_exists('\EasyInvoicePro\TemplateParser') && class_exists('\EasyInvoicePro\Addons\CustomTemplates\Controllers\TemplateBuilderController')) {
                                $templateData = \EasyInvoicePro\TemplateParser::parseTemplateFromDatabase($template_id);
                                if ($templateData && isset($templateData['elements'])) {
                                    echo '<style>';
                                    // Canvas settings
                                    $canvas = $templateData['canvas'] ?? [];
                                    $canvasWidth = $canvas['width'] ?? 794;
                                    $canvasHeight = $canvas['height'] ?? 1123;
                                    $canvasDesignCSS = \EasyInvoicePro\Addons\CustomTemplates\Controllers\TemplateBuilderController::generateCanvasCSS($templateData);
                                    
                                    echo "#canvas { position: relative; width: " . floatval($canvasWidth) . "px; height: " . floatval($canvasHeight) . "px; margin: 0; overflow: visible; ";
                                    if ($canvasDesignCSS) {
                                        echo wp_strip_all_tags(str_replace('!important;', ';', $canvasDesignCSS)); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- CSS inside a <style> element; tags stripped, entities are not decoded there.
                                    }
                                    echo " }\n";
                                    
                                    // Element styles
                                    foreach ($templateData['elements'] as $element) {
                                        $elementId = $element['id'] ?? '';
                                        if (!$elementId) continue;
                                        
                                        echo '#' . esc_attr($elementId) . ' { position: absolute; ';
                                        if (isset($element['position']['left'])) echo "left: " . floatval($element['position']['left']) . "px; ";
                                        if (isset($element['position']['top'])) echo "top: " . floatval($element['position']['top']) . "px; ";
                                        if (isset($element['dimensions']['width'])) echo "width: " . floatval($element['dimensions']['width']) . "px; ";
                                        if (isset($element['dimensions']['height'])) echo "min-height: " . floatval($element['dimensions']['height']) . "px; ";
                                        
                                        if (isset($element['styles']) && is_array($element['styles'])) {
                                            foreach ($element['styles'] as $property => $value) {
                                                if ($value !== '' && !in_array($property, ['position', 'dimensions'])) {
                                                    echo esc_attr($property) . ": " . esc_attr($value) . "; ";
                                                }
                                            }
                                        }
                                        echo "}\n";
                                    }
                                    echo '</style>';
                                }
                            }
                        }

                        // Dynamically load the selected template
                        $template_file = easy_invoice_design_template( 'invoice', (string) $current_template );
                        if ( ! $invoice instanceof \EasyInvoice\Models\Invoice ) {
                            // Nothing to render yet. The designs read the model
                            // directly, so including one here would be fatal.
                            ?>
                            <div class="ei-preview-empty" style="text-align:center;padding:48px 24px;color:#64748b;">
                                <p style="margin:0;font-size:14px;"><?php esc_html_e( 'Your invoice will appear here as you fill in the form.', 'easy-invoice' ); ?></p>
                            </div>
                            <?php
                        } elseif (file_exists($template_file)) {
                            include_once $template_file;
                        } else {
                            // Show template not found message
                            ?>
                            <div class="template-not-found">
                                <div class="template-not-found-icon">
                                    <i class="fas fa-exclamation-circle"></i>
                                </div>
                                <h3><?php esc_html_e('Template Not Found', 'easy-invoice'); ?></h3>
                                <p>The selected template "<?php echo esc_html($current_template); ?>" does not exist.</p>
                                <p><?php esc_html_e('Please select a different template or contact support if you believe this is an error.', 'easy-invoice'); ?></p>
                            </div>
                            <style>
                                .template-not-found {
                                    text-align: center;
                                    padding: 40px;
                                    background: #fff;
                                    border-radius: 8px;
                                    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
                                }
                                .template-not-found-icon {
                                    font-size: 48px;
                                    color: #dc3545;
                                    margin-bottom: 20px;
                                }
                                .template-not-found h3 {
                                    font-size: 24px;
                                    color: #32325d;
                                    margin-bottom: 10px;
                                }
                                .template-not-found p {
                                    color: #8898aa;
                                    margin-bottom: 10px;
                                }
                            </style>
                <?php
                        }
                ?>
</div>
                </div>

<style>
/* Loading state styles */
.loading-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(255, 255, 255, 0.9);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 1000;
}

.loading-spinner {
    text-align: center;
}

.invoice-container.loading .loading-overlay {
    display: flex;
}

/* (Resize logic removed per request) */
</style>

<script>
// Localize easyInvoice object for this page
window.easyInvoice = window.easyInvoice || {};
window.easyInvoice.isPro = <?php echo easy_invoice_has_pro() ? 'true' : 'false'; ?>;
window.easyInvoice.ajaxUrl = '<?php echo esc_url(admin_url('admin-ajax.php')); ?>';
window.easyInvoice.nonce = '<?php echo esc_attr(wp_create_nonce('easy_invoice_nonce')); ?>';

jQuery(document).ready(function($) {
    // Function to update the live preview
    function updateLivePreview(templateId) {
        // Show loading state
        $('#invoice-container').addClass('loading');

        // Make AJAX call to load the template
        $.ajax({
            url: window.easyInvoice.ajaxUrl,
            type: 'POST',
            data: {
                action: 'easy_invoice_load_template',
                template: templateId,
                form_data: jQuery('#invoice-form').length ? jQuery('#invoice-form').serialize() : '',
                invoice_id: '<?php echo esc_js($invoice_id); ?>',
                nonce: window.easyInvoice.nonce
            },
            success: function(response) {
                if (response.success) {
                    // Update the preview content
                    $('#invoice-container').html(response.data.html);
                } else {
                    // Show error message
                    $('#invoice-container').html(`
                        <div class="template-not-found">
                            <div class="template-not-found-icon">
                                <i class="fas fa-exclamation-circle"></i>
                            </div>
                            <h3><?php esc_html_e('Template Not Found', 'easy-invoice'); ?></h3>
                            <p>The selected template "${templateId}" does not exist.</p>
                            <p><?php esc_html_e('Please select a different template or contact support if you believe this is an error.', 'easy-invoice'); ?></p>
                        </div>
                    `);
                }
            },
            error: function(xhr, status, error) {
                // Show error message
                $('#invoice-container').html(`
                    <div class="template-not-found">
                        <div class="template-not-found-icon">
                            <i class="fas fa-exclamation-circle"></i>
                        </div>
                        <h3><?php esc_html_e('Error Loading Template', 'easy-invoice'); ?></h3>
                        <p><?php esc_html_e('There was an error loading the template. Please try again.', 'easy-invoice'); ?></p>
                    </div>
                `);
            },
            complete: function() {
                // Remove loading state
                $('#invoice-container').removeClass('loading');
            }
        });
    }

    // Listen for template changes from the template cards
    $('.template-card').on('click', function(e) {
        const templateId = $(this).data('template-id');

        // Check if this is a premium template in free version
        const isPremium = $(this).attr('data-is-premium') === 'true';
        const isFreeVersion = !window.easyInvoice || !window.easyInvoice.isPro;
         if (isPremium && isFreeVersion) {
            // Show premium upgrade modal instead of selecting the template
            if (typeof EasyInvoiceConfirmation !== 'undefined' && EasyInvoiceConfirmation.showFeatureUpgrade) {
                EasyInvoiceConfirmation.showFeatureUpgrade('<?php echo esc_js(__('Premium Templates', 'easy-invoice')); ?>', '<?php echo esc_js(__('Access all premium templates including Modern, Professional, Classic, and more to give your invoices a unique and professional look.', 'easy-invoice')); ?>');
            } else {
                alert('<?php echo esc_js(__('This is a premium feature. Please upgrade to Pro to access all templates.', 'easy-invoice')); ?>');
            }
            return;
        }

        updateLivePreview(templateId);
    });

    // Listen for template changes from the gallery
    $('.gallery-template-card').on('click', function() {
        const templateId = $(this).data('template-id');
        updateLivePreview(templateId);
    });


    // Live means live: re-render as the builder changes, not only when the
    // template changes. Debounced so typing a description does not fire a
    // request per keystroke.
    (function () {
        var $form = $('#invoice-form'); if (!$form.length) { return; }
        var timer = null;
        var current = function () { return $form.find('input[name="invoice_template"]').val() || $('.template-card.selected, .template-card.active').first().data('template-id') || 'standard'; };
        var schedule = function () { clearTimeout(timer); timer = setTimeout(function () { updateLivePreview(current()); }, 700); };
        $form.on('input change', 'input, textarea, select', schedule);
        $(document).on('click', '.add-item-button, .remove-item, .client-option, #remove-selected-client, .template-card', schedule);
        $(document).on('easy_invoice_items_changed easy_invoice_client_changed', schedule);
    })();

});
</script>

<script>
// Scale the A4 design to the preview pane instead of letting it reflow: the
// preview then shows the sheet the client will see, only smaller.
(function () {
    var box = document.getElementById('invoice-container');
    if (!box || !window.ResizeObserver) { return; }
    var SHEET = 794;
    function fit() {
        var sheet = box.querySelector('.template, [class*="template-"]');
        if (!sheet) { box.style.height = ''; return; }
        var avail = box.clientWidth;
        if (avail <= 0) { return; }
        var k = Math.min(1, avail / SHEET);
        sheet.style.width = SHEET + 'px';
        sheet.style.maxWidth = 'none';
        sheet.style.transformOrigin = 'top left';
        sheet.style.transform = k < 1 ? 'scale(' + k + ')' : '';
        box.style.overflow = 'hidden';
        box.style.height = k < 1 ? Math.ceil(sheet.offsetHeight * k) + 'px' : '';
    }
    new ResizeObserver(fit).observe(box);
    new MutationObserver(fit).observe(box, { childList: true, subtree: true });
    fit();
})();
</script>

```
