# king-addons/51.1.76/includes/extensions/Custom_Code_Manager/assets/admin.js

King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder, version 51.1.76. 1,291 lines.

- Page: https://pluginprobe.com/plugins/king-addons/51.1.76/code/includes/extensions/Custom_Code_Manager/assets/admin.js
- Raw: https://pluginprobe.com/plugins/king-addons/51.1.76/raw/includes/extensions/Custom_Code_Manager/assets/admin.js
- Modified: 2026-07-14T18:33:24+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/king-addons/51.1.76/code/includes/extensions/Custom_Code_Manager/assets/admin.js#L10-L20`.

```javascript
/**
 * Custom Code Manager - Admin JavaScript
 */

(function($) {
    'use strict';

    // Global state
    let config = {};
    let editor = null;
    let currentType = 'css';
    let rules = [];
    let ruleIndex = 0;
    let importData = null;

    /**
     * Initialize
     */
    function init() {
        // Load initial config if available
        if (typeof window.kngCCInitialConfig !== 'undefined') {
            config = window.kngCCInitialConfig;
            rules = config.rules || [];
            currentType = config.type || 'css';
        }

        // Initialize components based on page
        initListPage();
        initEditorPage();
        initSettingsPage();
        initImportExportPage();
    }

    // =========================================================================
    // List Page
    // =========================================================================

    function initListPage() {
        const $list = $('#kng-cc-snippets-list');
        if (!$list.length) return;

        // Search filter
        $('#kng-cc-search').on('input', debounce(filterSnippets, 300));

        // Dropdown filters
        $('.kng-cc-filter').on('change', filterSnippets);

        // Select all checkbox
        $('.kng-cc-select-all').on('change', function() {
            const checked = $(this).prop('checked');
            $('.kng-cc-row-check:visible').prop('checked', checked);
        });

        // Bulk actions
        $('#kng-cc-bulk-apply').on('click', handleBulkAction);

        // Status toggle
        $(document).on('click', '.kng-cc-status-toggle', handleStatusToggle);

        // Duplicate button
        $(document).on('click', '.kng-cc-duplicate-btn', handleDuplicate);

        // Export single button
        $(document).on('click', '.kng-cc-export-btn', handleExportSingle);

        // Delete button
        $(document).on('click', '.kng-cc-delete-btn', handleDelete);

        // Pro upgrade popup
        $('#kng-cc-add-new-limit').on('click', showProPopup);
        $('#kng-cc-pro-popup-close, .kng-cc-pro-popup-dismiss').on('click', hideProPopup);
        $('#kng-cc-pro-popup').on('click', function(e) {
            if (e.target === this) hideProPopup();
        });
    }

    function filterSnippets() {
        const search = $('#kng-cc-search').val().toLowerCase();
        const typeFilter = $('[data-filter="type"]').val();
        const statusFilter = $('[data-filter="status"]').val();
        const locationFilter = $('[data-filter="location"]').val();

        $('.kng-cc-row').each(function() {
            const $row = $(this);
            const name = $row.find('.kng-cc-name-link').text().toLowerCase();
            const type = $row.data('type');
            const status = $row.data('status');
            const location = $row.data('location');

            let visible = true;

            if (search && !name.includes(search)) {
                visible = false;
            }
            if (typeFilter && type !== typeFilter) {
                visible = false;
            }
            if (statusFilter && status !== statusFilter) {
                visible = false;
            }
            if (locationFilter && location !== locationFilter) {
                visible = false;
            }

            $row.toggle(visible);
        });
    }

    function handleBulkAction() {
        const action = $('#kng-cc-bulk-action').val();
        if (!action) return;

        const ids = [];
        $('.kng-cc-row-check:checked').each(function() {
            ids.push($(this).val());
        });

        if (!ids.length) {
            showNotice(kngCCAdmin.strings.selectSnippets, 'warning');
            return;
        }

        if (action === 'delete' && !confirm(kngCCAdmin.strings.confirmBulkDelete)) {
            return;
        }

        $.ajax({
            url: kngCCAdmin.ajaxUrl,
            method: 'POST',
            data: {
                action: 'kng_cc_bulk_action',
                nonce: kngCCAdmin.nonce,
                bulk_action: action,
                ids: ids
            },
            success: function(response) {
                if (response.success) {
                    showNotice(response.data.message, 'success');
                    location.reload();
                } else {
                    showNotice(response.data.message || kngCCAdmin.strings.error, 'error');
                }
            },
            error: function() {
                showNotice(kngCCAdmin.strings.error, 'error');
            }
        });
    }

    function handleStatusToggle(e) {
        e.preventDefault();
        const $toggle = $(this);
        const id = $toggle.data('id');

        $.ajax({
            url: kngCCAdmin.ajaxUrl,
            method: 'POST',
            data: {
                action: 'kng_cc_toggle_snippet',
                nonce: kngCCAdmin.nonce,
                id: id
            },
            success: function(response) {
                if (response.success) {
                    const $row = $toggle.closest('.kng-cc-row');
                    $row.data('status', response.data.status);
                    $toggle.prop('checked', response.data.status === 'enabled');
                } else {
                    showNotice(response.data.message || kngCCAdmin.strings.error, 'error');
                    $toggle.prop('checked', !$toggle.prop('checked'));
                }
            },
            error: function() {
                showNotice(kngCCAdmin.strings.error, 'error');
                $toggle.prop('checked', !$toggle.prop('checked'));
            }
        });
    }

    function handleDuplicate(e) {
        e.preventDefault();
        const id = $(this).data('id');

        // Check limit client-side first
        if (!kngCCAdmin.hasPro) {
            const currentCount = $('.kng-cc-row').length;
            if (currentCount >= kngCCAdmin.freeLimit) {
                showProPopup();
                return;
            }
        }

        $.ajax({
            url: kngCCAdmin.ajaxUrl,
            method: 'POST',
            data: {
                action: 'kng_cc_duplicate_snippet',
                nonce: kngCCAdmin.nonce,
                id: id
            },
            success: function(response) {
                if (response.success) {
                    showNotice(kngCCAdmin.strings.duplicated, 'success');
                    location.reload();
                } else {
                    // If server returns limit error, show popup instead of error
                    if (!kngCCAdmin.hasPro && response.data && (response.data.limit || (response.data.message && response.data.message.indexOf('limit') !== -1))) {
                        showProPopup();
                    } else {
                        showNotice(response.data.message || kngCCAdmin.strings.error, 'error');
                    }
                }
            },
            error: function() {
                showNotice(kngCCAdmin.strings.error, 'error');
            }
        });
    }

    function handleExportSingle(e) {
        e.preventDefault();
        const id = $(this).data('id');

        $.ajax({
            url: kngCCAdmin.ajaxUrl,
            method: 'POST',
            data: {
                action: 'kng_cc_export_snippet',
                nonce: kngCCAdmin.nonce,
                id: id
            },
            success: function(response) {
                if (response.success && response.data.export.snippets && response.data.export.snippets.length) {
                    var snippet = response.data.export.snippets[0];
                    var code = snippet.code || '';
                    var type = snippet.type || 'txt';
                    var title = (snippet.title || 'snippet').replace(/[^a-zA-Z0-9_-]/g, '_');

                    var extMap = { css: '.css', js: '.js', html: '.html' };
                    var mimeMap = { css: 'text/css', js: 'application/javascript', html: 'text/html' };
                    var ext = extMap[type] || '.txt';
                    var mime = mimeMap[type] || 'text/plain';

                    var blob = new Blob([code], { type: mime });
                    var url = URL.createObjectURL(blob);
                    var a = document.createElement('a');
                    a.href = url;
                    a.download = title + ext;
                    document.body.appendChild(a);
                    a.click();
                    document.body.removeChild(a);
                    URL.revokeObjectURL(url);

                    showNotice(kngCCAdmin.strings.exportReady, 'success');
                } else {
                    showNotice(response.data.message || kngCCAdmin.strings.error, 'error');
                }
            },
            error: function() {
                showNotice(kngCCAdmin.strings.error, 'error');
            }
        });
    }

    function handleDelete(e) {
        e.preventDefault();
        
        if (!confirm(kngCCAdmin.strings.confirmDelete)) {
            return;
        }

        const id = $(this).data('id');

        $.ajax({
            url: kngCCAdmin.ajaxUrl,
            method: 'POST',
            data: {
                action: 'kng_cc_delete_snippet',
                nonce: kngCCAdmin.nonce,
                id: id
            },
            success: function(response) {
                if (response.success) {
                    $('[data-id="' + id + '"]').closest('.kng-cc-row').fadeOut(300, function() {
                        $(this).remove();
                    });
                } else {
                    showNotice(response.data.message || kngCCAdmin.strings.error, 'error');
                }
            },
            error: function() {
                showNotice(kngCCAdmin.strings.error, 'error');
            }
        });
    }

    // =========================================================================
    // Editor Page
    // =========================================================================

    function initEditorPage() {
        const $form = $('#kng-cc-editor-form');
        if (!$form.length) return;

        // Initialize CodeMirror
        initCodeMirror();

        // Type tabs
        $('.kng-cc-type-tab').on('click', handleTypeChange);

        // Status toggle label
        $('#kng-cc-status').on('change', updateStatusLabel);

        // Location change
        $('#kng-cc-location').on('change', handleLocationChange);

        // Scope mode change
        $('input[name="scope_mode"]').on('change', handleScopeModeChange);

        // Rules builder
        initRulesBuilder();

        // Form submit
        $form.on('submit', handleFormSubmit);

        // Fullscreen toggle
        $('#kng-cc-fullscreen').on('click', toggleFullscreen);

        // Collapsible sections
        $('[data-collapsible]').on('click', function() {
            $(this).toggleClass('is-collapsed');
            $(this).next('.kng-cc-section-content').slideToggle(200);
        });

        // Initialize state
        updateStatusLabel();
        handleLocationChange();
        handleScopeModeChange();
        renderRules();
    }

    function initCodeMirror() {
        const $textarea = $('#kng-cc-code');
        if (!$textarea.length) return;

        const modeMap = {
            'css': 'text/css',
            'js': 'application/javascript',
            'html': 'text/html'
        };

        const settings = wp.codeEditor.defaultSettings ? _.clone(wp.codeEditor.defaultSettings) : {};
        settings.codemirror = _.extend({}, settings.codemirror, {
            mode: modeMap[currentType] || 'text/css',
            lineNumbers: true,
            lineWrapping: true,
            indentUnit: 4,
            tabSize: 4,
            indentWithTabs: false,
            autoCloseBrackets: true,
            autoCloseTags: true,
            matchBrackets: true,
            matchTags: {bothTags: true},
            highlightSelectionMatches: {
                showToken: /\w/,
                annotateScrollbar: true
            },
            foldGutter: true,
            styleActiveLine: true,
            gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
            extraKeys: {
                'Ctrl-S': function() { saveSnippet(); },
                'Cmd-S': function() { saveSnippet(); },
                'Ctrl-Space': 'autocomplete',
                'F11': function(cm) {
                    cm.setOption('fullScreen', !cm.getOption('fullScreen'));
                },
                'Esc': function(cm) {
                    if (cm.getOption('fullScreen')) cm.setOption('fullScreen', false);
                }
            }
        });

        // Add autocomplete for CSS properties
        if (currentType === 'css' && window.CodeMirror && CodeMirror.hint && CodeMirror.hint.css) {
            settings.codemirror.hintOptions = {
                completeSingle: false
            };
        }

        editor = wp.codeEditor.initialize($textarea, settings);

        // Enhance editor instance
        if (editor && editor.codemirror) {
            const cm = editor.codemirror;
            
            // Auto-format on paste
            cm.on('paste', function() {
                setTimeout(function() {
                    if (currentType === 'css' || currentType === 'js') {
                        // Simple auto-indent
                        const totalLines = cm.lineCount();
                        cm.operation(function() {
                            for (let i = 0; i < totalLines; i++) {
                                cm.indentLine(i);
                            }
                        });
                    }
                }, 10);
            });
            
            // Show autocomplete on input for CSS
            if (currentType === 'css') {
                cm.on('inputRead', function(cm, change) {
                    if (change.text[0].match(/[a-z]/i)) {
                        CodeMirror.commands.autocomplete(cm, null, {completeSingle: false});
                    }
                });
            }
        }

        // Refresh on tab switch
        setTimeout(function() {
            if (editor && editor.codemirror) {
                editor.codemirror.refresh();
            }
        }, 100);
    }

    function handleTypeChange(e) {
        e.preventDefault();
        
        const $tab = $(this);
        if ($tab.is(':disabled') || $tab.hasClass('is-pro')) {
            if (!kngCCAdmin.hasPro) {
                showNotice(kngCCAdmin.strings.proRequired, 'warning');
            }
            return;
        }

        const type = $tab.data('type');
        currentType = type;

        // Update tabs
        $('.kng-cc-type-tab').removeClass('is-active').attr('aria-selected', 'false');
        $tab.addClass('is-active').attr('aria-selected', 'true');

        // Update hidden input
        $('#kng-cc-type').val(type);

        // Update CodeMirror mode
        if (editor && editor.codemirror) {
            const modeMap = {
                'css': 'text/css',
                'js': 'application/javascript',
                'html': 'text/html'
            };
            editor.codemirror.setOption('mode', modeMap[type] || 'text/css');
        }

        // Show/hide JS options
        $('#kng-cc-js-options').toggle(type === 'js');
    }

    function updateStatusLabel() {
        const enabled = $('#kng-cc-status').prop('checked');
        $('#kng-cc-status-label').text(enabled ? 'Enabled' : 'Disabled');
    }

    function handleLocationChange() {
        const location = $('#kng-cc-location').val();
        $('#kng-cc-custom-hook-wrap').toggle(location === 'custom_hook');
    }

    function handleScopeModeChange() {
        const mode = $('input[name="scope_mode"]:checked').val();
        
        // Update radio card visual
        $('.kng-cc-radio-card').removeClass('is-selected');
        $('input[name="scope_mode"]:checked').closest('.kng-cc-radio-card').addClass('is-selected');
        
        // Show/hide rules builder
        $('#kng-cc-rules-builder').toggle(mode !== 'global');
    }

    function handleFormSubmit(e) {
        e.preventDefault();
        saveSnippet();
    }

    function saveSnippet() {
        const $btn = $('#kng-cc-save-btn');
        const $text = $btn.find('.kng-cc-save-text');

        // Collect form data
        collectRulesFromForm();
        
        const snippet = {
            id: parseInt($('#kng-cc-id').val()) || 0,
            title: $('#kng-cc-title').val(),
            code: editor && editor.codemirror ? editor.codemirror.getValue() : $('#kng-cc-code').val(),
            type: $('#kng-cc-type').val(),
            status: $('#kng-cc-status').prop('checked') ? 'enabled' : 'disabled',
            location: $('#kng-cc-location').val(),
            custom_hook: $('#kng-cc-custom-hook').val(),
            priority: parseInt($('#kng-cc-priority').val()) || 10,
            js_dom_ready: $('#kng-cc-js-dom-ready').prop('checked'),
            js_defer: $('#kng-cc-js-defer').prop('checked'),
            js_async: $('#kng-cc-js-async').prop('checked'),
            js_module: $('#kng-cc-js-module').prop('checked'),
            scope_mode: $('input[name="scope_mode"]:checked').val(),
            rules: rules,
            match_mode: $('#kng-cc-match-mode').val() || 'any',
            notes: $('#kng-cc-notes').val()
        };

        // Validate
        if (!snippet.title.trim()) {
            showNotice('Please enter a snippet name', 'error');
            $('#kng-cc-title').focus();
            return;
        }

        // Show saving state
        $btn.removeClass('is-saved').addClass('is-saving');
        $text.text(kngCCAdmin.strings.saving);
        $btn.prop('disabled', true);

        $.ajax({
            url: kngCCAdmin.ajaxUrl,
            method: 'POST',
            data: {
                action: 'kng_cc_save_snippet',
                nonce: kngCCAdmin.nonce,
                snippet: JSON.stringify(snippet)
            },
            success: function(response) {
                if (response.success) {
                    // Show success state: green + checkmark
                    $btn.removeClass('is-saving').addClass('is-saved');
                    $text.text(kngCCAdmin.strings.saved);
                    
                    // Update ID if new snippet
                    if (!snippet.id && response.data.id) {
                        $('#kng-cc-id').val(response.data.id);
                        
                        // Update URL without reload
                        const newUrl = window.location.href.replace('view=new', 'view=edit&id=' + response.data.id);
                        window.history.replaceState({}, '', newUrl);
                    }

                    // Return to normal after delay
                    setTimeout(function() {
                        $btn.removeClass('is-saved');
                        $text.text('Save Snippet');
                        $btn.prop('disabled', false);
                    }, 2000);
                } else {
                    showNotice(response.data.message || kngCCAdmin.strings.error, 'error');
                    resetSaveButton();
                }
            },
            error: function() {
                showNotice(kngCCAdmin.strings.error, 'error');
                resetSaveButton();
            }
        });

        function resetSaveButton() {
            $btn.removeClass('is-saving is-saved');
            $text.text('Save Snippet');
            $btn.prop('disabled', false);
        }
    }

    function toggleFullscreen() {
        const $section = $('.kng-cc-code-section');
        $section.toggleClass('is-fullscreen');
        
        if (editor && editor.codemirror) {
            setTimeout(function() {
                editor.codemirror.refresh();
            }, 100);
        }
    }

    // =========================================================================
    // Rules Builder
    // =========================================================================

    function initRulesBuilder() {
        // Add rule button
        $('#kng-cc-add-rule').on('click', addRule);

        // Rule type change
        $(document).on('change', '.kng-cc-rule-type', handleRuleTypeChange);

        // Remove rule
        $(document).on('click', '.kng-cc-rule-remove', removeRule);

        // Set initial rule index
        ruleIndex = rules.length;
    }

    function renderRules() {
        const $list = $('#kng-cc-rules-list');
        $list.empty();

        rules.forEach(function(rule, index) {
            const html = createRuleHTML(index, rule);
            $list.append(html);
            renderRuleValue(index, rule);
        });
    }

    function createRuleHTML(index, rule) {
        const template = $('#kng-cc-rule-template').html();
        let html = template.replace(/\{\{index\}\}/g, index);
        
        const $rule = $(html);
        $rule.find('.kng-cc-rule-type').val(rule.type || 'page');
        
        return $rule;
    }

    function addRule() {
        const index = ruleIndex++;
        const rule = { type: 'page', value: '' };
        rules.push(rule);
        
        const html = createRuleHTML(index, rule);
        $('#kng-cc-rules-list').append(html);
        renderRuleValue(index, rule);
    }

    function removeRule() {
        const $rule = $(this).closest('.kng-cc-rule');
        const index = $rule.data('index');
        
        // Find and remove from rules array
        const ruleIndex = rules.findIndex((r, i) => {
            return $('[data-index="' + i + '"]').is($rule);
        });
        
        if (ruleIndex > -1) {
            rules.splice(ruleIndex, 1);
        }
        
        $rule.fadeOut(200, function() {
            $(this).remove();
        });
    }

    function handleRuleTypeChange() {
        const $rule = $(this).closest('.kng-cc-rule');
        const index = $rule.data('index');
        const type = $(this).val();
        
        // Update rule type
        const ruleData = getRuleByElement($rule);
        if (ruleData) {
            ruleData.type = type;
            ruleData.value = '';
        }
        
        renderRuleValue(index, { type: type, value: '' });
    }

    function getRuleByElement($rule) {
        const index = $rule.data('index');
        // Simple approach: use DOM order
        const domIndex = $rule.index();
        return rules[domIndex];
    }

    function renderRuleValue(index, rule) {
        const $rule = $('[data-index="' + index + '"]');
        const $valueContainer = $rule.find('.kng-cc-rule-value');
        $valueContainer.empty();

        let html = '';
        const type = rule.type || 'page';

        switch (type) {
            case 'page':
            case 'post':
                html = '<div class="kng-cc-rule-search-wrap">' +
                    '<input type="text" class="kng-v3-input kng-cc-rule-search" placeholder="Search by title or ID..." data-type="' + type + '" />' +
                    '<input type="hidden" class="kng-cc-rule-value-input" name="rules[' + index + '][value]" value="' + (rule.value || '') + '" />' +
                    '<div class="kng-cc-rule-search-results"></div>' +
                    '</div>';
                break;

            case 'post_type':
                html = '<select class="kng-v3-select kng-cc-rule-value-input" name="rules[' + index + '][value]">' +
                    '<option value="post">Posts</option>' +
                    '<option value="page">Pages</option>' +
                    '<option value="product">Products</option>' +
                    '</select>';
                break;

            case 'url_contains':
            case 'url_starts':
            case 'url_ends':
            case 'url_regex':
                html = '<input type="text" class="kng-v3-input kng-cc-rule-value-input" name="rules[' + index + '][value]" value="' + escapeHtml(rule.value || '') + '" placeholder="' + getPlaceholder(type) + '" />';
                break;

            case 'user_logged_in':
                html = '<select class="kng-v3-select kng-cc-rule-value-input" name="rules[' + index + '][value]">' +
                    '<option value="yes"' + (rule.value === 'yes' ? ' selected' : '') + '>Logged In</option>' +
                    '<option value="no"' + (rule.value === 'no' ? ' selected' : '') + '>Logged Out</option>' +
                    '</select>';
                break;

            case 'user_role':
                html = '<select class="kng-v3-select kng-cc-rule-value-input" name="rules[' + index + '][value]">' +
                    '<option value="administrator">Administrator</option>' +
                    '<option value="editor">Editor</option>' +
                    '<option value="author">Author</option>' +
                    '<option value="contributor">Contributor</option>' +
                    '<option value="subscriber">Subscriber</option>' +
                    '</select>';
                break;

            case 'device':
                html = '<select class="kng-v3-select kng-cc-rule-value-input" name="rules[' + index + '][value]">' +
                    '<option value="desktop"' + (rule.value === 'desktop' ? ' selected' : '') + '>Desktop</option>' +
                    '<option value="tablet"' + (rule.value === 'tablet' ? ' selected' : '') + '>Tablet</option>' +
                    '<option value="mobile"' + (rule.value === 'mobile' ? ' selected' : '') + '>Mobile</option>' +
                    '</select>';
                break;

            case 'front_page':
            case 'blog_page':
            case 'archive':
            case 'search':
            case '404':
                // No value needed
                html = '<div class="kng-cc-rule-no-value">No additional configuration needed</div>';
                break;

            default:
                html = '<input type="text" class="kng-v3-input kng-cc-rule-value-input" name="rules[' + index + '][value]" value="' + escapeHtml(rule.value || '') + '" />';
        }

        $valueContainer.html(html);

        // Set initial value for selects
        if (rule.value) {
            $valueContainer.find('select.kng-cc-rule-value-input').val(rule.value);
        }

        // Initialize search if needed
        if (type === 'page' || type === 'post') {
            initRuleSearch($rule.find('.kng-cc-rule-search'));
        }
    }

    function getPlaceholder(type) {
        const placeholders = {
            'url_contains': '/shop/',
            'url_starts': '/products',
            'url_ends': '/checkout/',
            'url_regex': '/\\/product\\/[0-9]+/'
        };
        return placeholders[type] || '';
    }

    function initRuleSearch($input) {
        let searchTimeout;
        
        $input.on('input', function() {
            const $wrap = $(this).closest('.kng-cc-rule-search-wrap');
            const $results = $wrap.find('.kng-cc-rule-search-results');
            const search = $(this).val();
            const type = $(this).data('type');

            clearTimeout(searchTimeout);

            if (search.length < 2) {
                $results.empty().hide();
                return;
            }

            searchTimeout = setTimeout(function() {
                $.ajax({
                    url: kngCCAdmin.ajaxUrl,
                    method: 'POST',
                    data: {
                        action: 'kng_cc_search_content',
                        nonce: kngCCAdmin.nonce,
                        search: search,
                        content_type: type
                    },
                    success: function(response) {
                        if (response.success && response.data.length) {
                            let html = '';
                            response.data.forEach(function(item) {
                                html += '<div class="kng-cc-search-result" data-id="' + item.id + '" data-title="' + escapeHtml(item.title) + '">' +
                                    escapeHtml(item.title) + ' <span style="color:var(--kng-v3-muted);font-size:12px;">(ID: ' + item.id + ')</span>' +
                                    '</div>';
                            });
                            $results.html(html).show();
                        } else {
                            $results.html('<div class="kng-cc-search-no-results">' + kngCCAdmin.strings.noResults + '</div>').show();
                        }
                    }
                });
            }, 300);
        });

        // Select result
        $(document).on('click', '.kng-cc-search-result', function() {
            const $wrap = $(this).closest('.kng-cc-rule-search-wrap');
            const id = $(this).data('id');
            const title = $(this).data('title');
            
            $wrap.find('.kng-cc-rule-search').val(title);
            $wrap.find('.kng-cc-rule-value-input').val(id);
            $wrap.find('.kng-cc-rule-search-results').empty().hide();
        });

        // Hide results on outside click
        $(document).on('click', function(e) {
            if (!$(e.target).closest('.kng-cc-rule-search-wrap').length) {
                $('.kng-cc-rule-search-results').empty().hide();
            }
        });
    }

    function collectRulesFromForm() {
        rules = [];
        
        $('.kng-cc-rule').each(function() {
            const $rule = $(this);
            const type = $rule.find('.kng-cc-rule-type').val();
            const value = $rule.find('.kng-cc-rule-value-input').val() || '';
            
            rules.push({
                type: type,
                value: value
            });
        });
    }

    // =========================================================================
    // Settings Page
    // =========================================================================

    function initSettingsPage() {
        const $form = $('#kng-cc-settings-form');
        if (!$form.length) return;

        $form.on('submit', function(e) {
            e.preventDefault();
            
            const settings = {
                enabled: $form.find('[name="enabled"]').prop('checked'),
                default_location_css: $form.find('[name="default_location_css"]').val(),
                default_location_js: $form.find('[name="default_location_js"]').val(),
                default_priority: parseInt($form.find('[name="default_priority"]').val()) || 10,
                debug_mode: $form.find('[name="debug_mode"]').prop('checked')
            };

            $.ajax({
                url: kngCCAdmin.ajaxUrl,
                method: 'POST',
                data: {
                    action: 'kng_cc_save_settings',
                    nonce: kngCCAdmin.nonce,
                    settings: JSON.stringify(settings)
                },
                success: function(response) {
                    if (response.success) {
                        showNotice(kngCCAdmin.strings.saved, 'success');
                    } else {
                        showNotice(response.data.message || kngCCAdmin.strings.error, 'error');
                    }
                },
                error: function() {
                    showNotice(kngCCAdmin.strings.error, 'error');
                }
            });
        });
    }

    // =========================================================================
    // Import/Export Page
    // =========================================================================

    function initImportExportPage() {
        const $exportBtn = $('#kng-cc-export-btn');
        const $importBtn = $('#kng-cc-import-btn');
        
        if (!$exportBtn.length && !$importBtn.length) return;

        // Export all
        $exportBtn.on('click', handleExportAll);

        // Import dropzone
        const $dropzone = $('#kng-cc-import-dropzone');
        const $fileInput = $('#kng-cc-import-file');

        $dropzone.on('click', function() {
            $fileInput.click();
        });

        $dropzone.on('dragover dragenter', function(e) {
            e.preventDefault();
            $(this).addClass('is-dragover');
        });

        $dropzone.on('dragleave dragend drop', function(e) {
            e.preventDefault();
            $(this).removeClass('is-dragover');
        });

        $dropzone.on('drop', function(e) {
            const files = e.originalEvent.dataTransfer.files;
            if (files.length) {
                handleFileSelect(files[0]);
            }
        });

        $fileInput.on('change', function() {
            if (this.files.length) {
                handleFileSelect(this.files[0]);
            }
        });

        // Remove file
        $(document).on('click', '.kng-cc-file-remove', function(e) {
            e.stopPropagation();
            importData = null;
            $dropzone.find('.kng-cc-dropzone-content').show();
            $dropzone.find('.kng-cc-dropzone-file').hide();
            $importBtn.prop('disabled', true);
            $fileInput.val('');
        });

        // Import button
        $importBtn.on('click', handleImport);
    }

    function handleExportAll() {
        $.ajax({
            url: kngCCAdmin.ajaxUrl,
            method: 'POST',
            data: {
                action: 'kng_cc_export_all',
                nonce: kngCCAdmin.nonce
            },
            success: function(response) {
                if (response.success) {
                    const filename = 'king-addons-snippets-' + new Date().toISOString().slice(0, 10) + '.json';
                    downloadJSON(response.data.export, filename);
                    showNotice(kngCCAdmin.strings.exportReady, 'success');
                } else {
                    showNotice(response.data.message || kngCCAdmin.strings.error, 'error');
                }
            },
            error: function() {
                showNotice(kngCCAdmin.strings.error, 'error');
            }
        });
    }

    function handleFileSelect(file) {
        if (!file.name.endsWith('.json')) {
            showNotice(kngCCAdmin.strings.invalidFile, 'error');
            return;
        }

        const reader = new FileReader();
        reader.onload = function(e) {
            try {
                importData = JSON.parse(e.target.result);
                
                if (!importData.snippets || !Array.isArray(importData.snippets)) {
                    throw new Error('Invalid format');
                }

                const $dropzone = $('#kng-cc-import-dropzone');
                $dropzone.find('.kng-cc-dropzone-content').hide();
                $dropzone.find('.kng-cc-dropzone-file').show();
                $dropzone.find('.kng-cc-file-name').text(file.name + ' (' + importData.snippets.length + ' snippets)');
                
                $('#kng-cc-import-btn').prop('disabled', false);
            } catch (err) {
                showNotice(kngCCAdmin.strings.invalidFile, 'error');
                importData = null;
            }
        };
        reader.readAsText(file);
    }

    function handleImport() {
        if (!importData) return;

        const mode = $('#kng-cc-import-mode').val();
        const $btn = $('#kng-cc-import-btn');
        
        $btn.prop('disabled', true).text('Importing...');

        $.ajax({
            url: kngCCAdmin.ajaxUrl,
            method: 'POST',
            data: {
                action: 'kng_cc_import',
                nonce: kngCCAdmin.nonce,
                import: JSON.stringify(importData),
                mode: mode
            },
            success: function(response) {
                if (response.success) {
                    $('#kng-cc-imported-count').text(response.data.imported);
                    $('#kng-cc-skipped-count').text(response.data.skipped);
                    $('#kng-cc-errors-count').text(response.data.errors);
                    $('#kng-cc-import-results').show();
                    
                    showNotice(kngCCAdmin.strings.importSuccess, 'success');
                } else {
                    showNotice(response.data.message || kngCCAdmin.strings.error, 'error');
                }
                
                $btn.prop('disabled', false).html(
                    '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18">' +
                    '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>' +
                    '<polyline points="17 8 12 3 7 8"/>' +
                    '<line x1="12" y1="3" x2="12" y2="15"/>' +
                    '</svg> Import Snippets'
                );
            },
            error: function() {
                showNotice(kngCCAdmin.strings.error, 'error');
                $btn.prop('disabled', false);
            }
        });
    }

    // =========================================================================
    // Utilities
    // =========================================================================

    function showProPopup() {
        $('#kng-cc-pro-popup').fadeIn(200);
    }

    function hideProPopup() {
        $('#kng-cc-pro-popup').fadeOut(150);
    }

    function showNotice(message, type) {
        // Remove existing notices
        $('.kng-cc-notice').remove();

        const typeClass = type === 'success' ? 'kng-cc-notice--success' : 
                         type === 'warning' ? 'kng-cc-notice--warning' : 
                         'kng-cc-notice--error';

        const $notice = $('<div class="kng-cc-notice ' + typeClass + '">' +
            '<span>' + escapeHtml(message) + '</span>' +
            '<button type="button" class="kng-cc-notice-close">&times;</button>' +
            '</div>');

        $('body').append($notice);
        
        setTimeout(function() {
            $notice.addClass('is-visible');
        }, 10);

        // Auto hide after 5 seconds
        setTimeout(function() {
            $notice.removeClass('is-visible');
            setTimeout(function() {
                $notice.remove();
            }, 300);
        }, 5000);

        // Close on click
        $notice.find('.kng-cc-notice-close').on('click', function() {
            $notice.removeClass('is-visible');
            setTimeout(function() {
                $notice.remove();
            }, 300);
        });
    }

    function downloadJSON(data, filename) {
        const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
    }

    function escapeHtml(str) {
        if (!str) return '';
        const div = document.createElement('div');
        div.appendChild(document.createTextNode(str));
        return div.innerHTML;
    }

    function debounce(func, wait) {
        let timeout;
        return function(...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    }

    // Initialize when DOM is ready
    $(document).ready(init);

})(jQuery);

// Add notice styles dynamically
(function() {
    const style = document.createElement('style');
    style.textContent = `
        .kng-cc-notice {
            position: fixed;
            top: 50px;
            right: 20px;
            padding: 14px 20px;
            background: #1d1d1f;
            color: #ffffff;
            border-radius: 10px;
            box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
            z-index: 999999;
            display: flex;
            align-items: center;
            gap: 12px;
            font-size: 14px;
            font-family: -apple-system, BlinkMacSystemFont, sans-serif;
            transform: translateX(120%);
            transition: transform 0.3s ease;
        }
        .kng-cc-notice.is-visible {
            transform: translateX(0);
        }
        .kng-cc-notice--success {
            background: #30d158;
        }
        .kng-cc-notice--warning {
            background: #ff9f0a;
            color: #1d1d1f;
        }
        .kng-cc-notice--error {
            background: #ff453a;
        }
        .kng-cc-notice-close {
            background: transparent;
            border: none;
            color: inherit;
            font-size: 20px;
            cursor: pointer;
            opacity: 0.7;
            line-height: 1;
        }
        .kng-cc-notice-close:hover {
            opacity: 1;
        }
        .kng-cc-rule-search-results {
            position: absolute;
            top: 100%;
            left: 0;
            right: 0;
            background: #ffffff;
            border: 1px solid #d2d2d7;
            border-radius: 8px;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
            z-index: 100;
            max-height: 200px;
            overflow-y: auto;
            display: none;
        }
        .kng-cc-search-result {
            padding: 10px 14px;
            cursor: pointer;
            border-bottom: 1px solid #e5e5e7;
        }
        .kng-cc-search-result:last-child {
            border-bottom: none;
        }
        .kng-cc-search-result:hover {
            background: #f5f5f7;
        }
        .kng-cc-search-no-results {
            padding: 12px 14px;
            color: #86868b;
            text-align: center;
        }
        .kng-cc-rule-search-wrap {
            position: relative;
        }
        .kng-cc-rule-no-value {
            font-size: 12px;
            color: #86868b;
            font-style: italic;
        }
    `;
    document.head.appendChild(style);
})();

// =========================================================================
// Theme Switcher (ka-v3-theme-segment)
// =========================================================================

(function initThemeSwitcher($) {
    'use strict';

    var $segment = $('#ka-v3-theme-segment');
    if (!$segment.length) return;

    var $buttons = $segment.find('.ka-v3-segmented-btn');
    var mql = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
    var mode = ($segment.attr('data-active') || 'dark').toString();
    var mqlHandler = null;

    function saveUISetting(value) {
        if (!window.kngCCAdmin) return;
        $.post(kngCCAdmin.ajaxUrl, {
            action: 'king_addons_save_dashboard_ui',
            nonce: kngCCAdmin.themeNonce,
            key: 'theme_mode',
            value: value
        });
    }

    function updateSegment(activeMode) {
        $segment.attr('data-active', activeMode);
        $buttons.each(function() {
            var theme = ($(this).data('theme') || 'dark').toString();
            $(this).attr('aria-pressed', theme === activeMode ? 'true' : 'false');
        });
    }

    function applyTheme(isDark) {
        $('body').toggleClass('ka-v3-dark', isDark);
        document.documentElement.classList.toggle('ka-v3-dark', isDark);
    }

    function setThemeMode(nextMode, save) {
        mode = (nextMode || 'dark').toString();
        updateSegment(mode);

        if (mqlHandler && mql) {
            if (mql.removeEventListener) {
                mql.removeEventListener('change', mqlHandler);
            } else if (mql.removeListener) {
                mql.removeListener(mqlHandler);
            }
            mqlHandler = null;
        }

        if (mode === 'auto') {
            applyTheme(!!(mql && mql.matches));
            mqlHandler = function(e) {
                if (mode !== 'auto') return;
                applyTheme(!!e.matches);
            };
            if (mql) {
                if (mql.addEventListener) {
                    mql.addEventListener('change', mqlHandler);
                } else if (mql.addListener) {
                    mql.addListener(mqlHandler);
                }
            }
        } else {
            applyTheme(mode === 'dark');
        }

        if (save) {
            saveUISetting(mode);
        }
    }

    $segment.on('click', '.ka-v3-segmented-btn', function(e) {
        e.preventDefault();
        setThemeMode(($(this).data('theme') || 'dark').toString(), true);
    });

    setThemeMode(mode, false);
})(jQuery);

```
