<script type="text/javascript">
    /*
     *
     * Define global javascript variables
     *
     */
    var base_url = "<?php echo base_url(); ?>"; // Base URL
    var site_url = "<?php echo site_url(); ?>"; // Site URL
    var icon_dot_url = "<?php echo base_url(); ?>assets/images/dot.png";
    // get the user_callsign from session
    var my_call = "<?php echo $this->session->userdata('user_callsign'); ?>".toUpperCase();
    // get the user_gridsquare from session or view data
    var my_gridsquare = "<?php echo isset($my_gridsquare) ? $my_gridsquare : $this->session->userdata('user_locator'); ?>";
    // get the user's measurement preference
    var measurement_base = "<?php echo $this->session->userdata('user_measurement_base') ? $this->session->userdata('user_measurement_base') : $this->config->item('measurement_base'); ?>";
</script>

<script>
    /*
    General Language
    */
    var lang_general_word_qso_data = "<?php echo lang('general_word_qso_data'); ?>";
    var lang_general_word_danger = "<?php echo lang('general_word_danger'); ?>";
    var lang_general_word_attention = "<?php echo lang('general_word_attention'); ?>";
    var lang_general_word_warning = "<?php echo lang('general_word_warning'); ?>";
    var lang_general_word_cancel = "<?php echo lang('general_word_cancel'); ?>";
    var lang_general_word_ok = "<?php echo lang('general_word_ok'); ?>";
    var lang_qso_delete_warning = "<?php echo lang('qso_delete_warning'); ?>";
    var lang_general_word_colors = "<?php echo lang('general_word_colors'); ?>";
    var lang_general_word_confirmed = "<?php echo lang('general_word_confirmed'); ?>";
    var lang_general_word_worked_not_confirmed = "<?php echo lang('general_word_worked_not_confirmed'); ?>";
    var lang_general_word_not_worked = "<?php echo lang('general_word_not_worked'); ?>";
    var lang_admin_close = "<?php echo lang('admin_close'); ?>";
</script>
<!-- General JS Files used across Cloudlog -->
<script src="<?php echo base_url(); ?>assets/js/jquery-3.3.1.min.js"></script>
<script src="<?php echo base_url(); ?>assets/js/jquery.fancybox.min.js"></script>
<script src="<?php echo base_url(); ?>assets/js/bootstrap.bundle.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/leaflet/leaflet.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/leaflet/Control.FullScreen.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/leaflet/L.Maidenhead.qrb.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/leaflet/L.Terminator.js"></script>
<?php if ($this->uri->segment(1) == "activators") { ?>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/leaflet/L.Maidenhead.activators.js"></script>
<?php } ?>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/leaflet/leaflet.geodesic.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/radiohelpers.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/darkmodehelpers.js"></script>
<script src="<?php echo base_url(); ?>assets/js/bootstrapdialog/js/bootstrap-dialog.min.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/easyprint.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/sections/common.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/sections/eqslcharcounter.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/sections/version_dialog.js"></script>

<script src="<?php echo base_url(); ?>assets/js/htmx.min.js"></script>

<script>
    // Reinitialize tooltips after new content has been loaded
    document.addEventListener('htmx:afterSwap', function(event) {
        $('[data-bs-toggle="tooltip"]').tooltip();
    });
</script>
<!-- Version Dialog START -->

<?php
if ($this->session->userdata('user_id') != null) {
    $versionDialog = $this->optionslib->get_option('version_dialog');
    if (empty($versionDialog)) {
        $this->optionslib->update('version_dialog', 'release_notes', 'yes');
    }
    $versionDialogHeader = $this->optionslib->get_option('version_dialog_header');
    if (empty($versionDialogHeader)) {
        $this->optionslib->update('version_dialog_header', $this->lang->line('options_version_dialog'), 'yes');
    }
    if ($versionDialog != "disabled") {
        $confirmed = $this->user_options_model->get_options('version_dialog', array('option_name' => 'confirmed'))->result();
        $confirmation_value = (isset($confirmed[0]->option_value)) ? $confirmed[0]->option_value : 'false';
        if ($confirmation_value != 'true') {
            $this->user_options_model->set_option('version_dialog', 'confirmed', array('boolean' => $confirmation_value));
?><script>
                displayVersionDialog();
            </script><?php
                    }
                }
            }
                        ?>

<!-- Version Dialog END -->

<?php if ($this->uri->segment(1) == "oqrs") { ?>
    <script src="<?php echo base_url(); ?>assets/js/sections/oqrs.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "options") { ?>
    <script>
        $('#sendTestMailButton').click(function() {
            $.ajax({
                url: base_url + 'index.php/options/sendTestMail',
                type: 'POST',
            });
        });
    </script>
<?php } ?>

<?php if ($this->uri->segment(1) == "awards" && ($this->uri->segment(2) == "cq")) { ?>
    <script src="<?php echo base_url(); ?>assets/js/Polyline.encoded.js"></script>
    <script id="cqmapjs" type="text/javascript" src="<?php echo base_url(); ?>assets/js/sections/cqmap.js" tileUrl="<?php echo $this->optionslib->get_option('option_map_tile_server'); ?>"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "awards" && ($this->uri->segment(2) == "iota")) { ?>
    <script id="iotamapjs" type="text/javascript" src="<?php echo base_url(); ?>assets/js/sections/iotamap.js" tileUrl="<?php echo $this->optionslib->get_option('option_map_tile_server'); ?>"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "awards" && ($this->uri->segment(2) == "dxcc")) { ?>
    <script id="dxccmapjs" type="text/javascript" src="<?php echo base_url(); ?>assets/js/sections/dxccmap.js" tileUrl="<?php echo $this->optionslib->get_option('option_map_tile_server'); ?>"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "statistics") { ?>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/chart.js"></script>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/chartjs-plugin-piechart-outlabels.js"></script>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/sections/statistics.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "propagationadvisor") { ?>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/sections/propagationadvisor.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "continents") { ?>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/chart.js"></script>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/chartjs-plugin-piechart-outlabels.js"></script>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/sections/continents.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "adif" || $this->uri->segment(1) == "qrz" || $this->uri->segment(1) == "hrdlog" || $this->uri->segment(1) == "webadif" || $this->uri->segment(1) == "sattimers") { ?>
    <!-- Javascript used for ADIF Import and Export Areas -->
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/moment.min.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "maintenance") { ?>
    <script src="<?php echo base_url(); ?>assets/js/sections/maintenance.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "adif") { ?>
    <script src="<?php echo base_url(); ?>assets/js/sections/adif.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "notes" && ($this->uri->segment(2) == "add" || $this->uri->segment(2) == "edit")) { ?>
    <!-- Javascript used for Notes Area -->
    <script src="<?php echo base_url(); ?>assets/plugins/quill/quill.min.js"></script>
    <script src="<?php echo base_url(); ?>assets/js/sections/notes.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "notes" && ($this->uri->segment(2) == "" || $this->uri->segment(2) == NULL || $this->uri->segment(2) == "view")) { ?>
    <!-- Javascript for Notes list/view (modal wiring) -->
    <script src="<?php echo base_url(); ?>assets/js/sections/notes_list.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "logbooks" && $this->uri->segment(2) == "edit") { ?>
    <script>
        function removeSlug() {
            var slugLink = document.getElementById("slugLink");
            if (slugLink !== null) {
                slugLink.style.display = "none";
            }
            document.getElementById('publicSlugInput').value = ''
        }
    </script>
<?php } ?>

<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/datatables.min.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/dataTables.buttons.min.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/buttons.html5.min.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>assets/js/selectize.js"></script>

<?php if ($this->uri->segment(1) == "mostworked") { ?>
<script>
$(document).ready(function() {
    $('#mostworked_table').DataTable({
        "pageLength": 25,
        "responsive": true,
        "order": [[ 0, "asc" ]],
        "columnDefs": [
            { "orderable": false, "targets": 0 },
            { "type": "num", "targets": 2 }
        ],
        "language": {
            url: getDataTablesLanguageUrl()
        }
    });
    
    // Clear filters button
    $('#clear_filters').click(function() {
        $('#mostworked_filter_form')[0].reset();
        $('#mostworked_filter_form').submit();
    });
});
</script>
<?php } ?>

<?php if ($this->uri->segment(1) == "station") { ?>
    <script language="javascript" src="<?php echo base_url(); ?>assets/js/HamGridSquare.js"></script>
    <script src="<?php echo base_url(); ?>assets/js/sections/station_locations.js"></script>
    <script>
        var position;

        function getLocation() {
            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(showPosition);
            } else {
                console.log('Geolocation is not supported by this browser.');
            }
        }

        function showPosition(position) {
            gridsquare = latLonToGridSquare(position.coords.latitude, position.coords.longitude);
            document.getElementById("stationGridsquareInput").value = gridsquare;
        }
    </script>
<?php } ?>

<?php if ($this->uri->segment(1) == "logbooks") { ?>
    <script src="<?php echo base_url(); ?>assets/js/sections/station_logbooks.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "debug") { ?>
    <script type="text/javascript">
        function copyURL(url) {
            var urlField = $('#baseUrl');
            navigator.clipboard.writeText(url).then(function() {});
            urlField.addClass('flash-copy')
                .delay('1000').queue(function() {
                    urlField.removeClass('flash-copy').dequeue();
                });
        }

        $(function() {
            $('[data-bs-toggle="tooltip"]').tooltip({
                'delay': {
                    show: 500,
                    hide: 0
                },
                'placement': 'right'
            });
        });
    </script>
<?php } ?>

<?php if ($this->uri->segment(1) == "api"  && $this->uri->segment(2) == "help") { ?>
    <script type="text/javascript">
        function copyApiKey(apiKey) {
            var apiKeyField = $('#' + apiKey);
            navigator.clipboard.writeText(apiKey).then(function() {});
            apiKeyField.addClass('flash-copy')
                .delay('1000').queue(function() {
                    apiKeyField.removeClass('flash-copy').dequeue();
                });
        }

        function copyApiUrl() {
            var apiUrlField = $('#apiUrl');
            navigator.clipboard.writeText("<?php echo base_url(); ?>").then(function() {});
            apiUrlField.addClass('flash-copy')
                .delay('1000').queue(function() {
                    apiUrlField.removeClass('flash-copy').dequeue();
                });
        }

        $(function() {
            $('[data-bs-toggle="tooltip"]').tooltip({
                'delay': {
                    show: 500,
                    hide: 0
                },
                'placement': 'right'
            });
        });
    </script>
<?php } ?>

<?php if ($this->uri->segment(1) == "search" && $this->uri->segment(2) == "filter") { ?>

    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/query-builder.standalone.min.js"></script>

    <script type="text/javascript">
        $(".search-results-box").hide();

        $('#builder').queryBuilder({
            filters: [
                <?php foreach ($get_table_names->result() as $row) {
                    $value_name = str_replace("COL_", "", $row->Field);
                    if ($value_name != "PRIMARY_KEY" && strpos($value_name, 'MY_') === false && strpos($value_name, '_INTL') == false) { ?> {
                            id: '<?php echo $row->Field; ?>',
                            label: '<?php echo $value_name; ?>',
                            <?php if (strpos($row->Type, 'int(') !== false) { ?>
                                type: 'integer',
                                operators: ['equal', 'not_equal', 'less', 'less_or_equal', 'greater', 'greater_or_equal']
                            <?php } elseif (strpos($row->Type, 'double') !== false) { ?>
                                type: 'double',
                                operators: ['equal', 'not_equal', 'less', 'less_or_equal', 'greater', 'greater_or_equal']
                            <?php } elseif (strpos($row->Type, 'datetime') !== false) { ?>
                                type: 'datetime',
                                operators: ['equal', 'not_equal', 'less', 'less_or_equal', 'greater', 'greater_or_equal']
                            <?php } else { ?>
                                type: 'string',
                                operators: ['equal', 'not_equal', 'begins_with', 'contains', 'ends_with', 'is_empty', 'is_not_empty', 'is_null', 'is_not_null']
                            <?php } ?>
                        },
                    <?php } ?>
                <?php } ?>
            ]
        });


        function export_search_result() {
            var result = $('#builder').queryBuilder('getRules');
            if (!$.isEmptyObject(result)) {
                xhttp = new XMLHttpRequest();
                xhttp.onreadystatechange = function() {
                    var a;
                    if (xhttp.readyState === 4 && xhttp.status === 200) {
                        // Trick for making downloadable link
                        a = document.createElement('a');
                        a.href = window.URL.createObjectURL(xhttp.response);
                        // Give filename you wish to download
                        a.download = "advanced_search_export.adi";
                        a.style.display = 'none';
                        document.body.appendChild(a);
                        a.click();
                    }
                };
                // Post data to URL which handles post request
                xhttp.open("POST", "<?php echo site_url('search/export_to_adif'); ?>", true);
                xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                // You should set responseType as blob for binary responses
                xhttp.responseType = 'blob';
                xhttp.send("search=" + JSON.stringify(result, null, 2));
            }
        }

        function export_stored_query(id) {
            xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = function() {
                var a;
                if (xhttp.readyState === 4 && xhttp.status === 200) {
                    // Trick for making downloadable link
                    a = document.createElement('a');
                    a.href = window.URL.createObjectURL(xhttp.response);
                    // Give filename you wish to download
                    a.download = "advanced_search_export.adi";
                    a.style.display = 'none';
                    document.body.appendChild(a);
                    a.click();
                }
            };
            // Post data to URL which handles post request
            xhttp.open("POST", "<?php echo site_url('search/export_stored_query_to_adif'); ?>", true);
            xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            // You should set responseType as blob for binary responses
            xhttp.responseType = 'blob';
            xhttp.send("id=" + id);
        }

        $('#btn-save').on('click', function() {
            var resultquery = $('#builder').queryBuilder('getRules');
            if (!$.isEmptyObject(resultquery)) {
                let message = 'Description: <input class="form-control input-group-sm getqueryname">'

                BootstrapDialog.confirm({
                    title: 'Query description',
                    size: BootstrapDialog.SIZE_NORMAL,
                    cssClass: 'description-dialog',
                    closable: true,
                    nl2br: false,
                    message: message,
                    btnCancelLabel: 'Cancel',
                    btnOKLabel: 'Save',
                    callback: function(result) {
                        if (result) {
                            $.post("<?php echo site_url('search/save_query'); ?>", {
                                    search: JSON.stringify(resultquery, null, 2),
                                    description: $(".getqueryname").val()
                                })
                                .done(function(data) {
                                    $(".alert").remove();
                                    $(".card-body.main").append('<div class="alert alert-success">Your query has been saved!</div>');
                                    if ($("#querydropdown option").length == 0) {
                                        var dropdowninfo = ' <button class="btn btn-sm btn-primary" onclick="edit_stored_query_dialog()" id="btn-edit">Edit queries</button></p>' +
                                            '<div class="mb-3 row querydropdownform">' +
                                            '<label class="col-md-2 control-label" for="querydropdown">  Stored queries:</label>' +
                                            '<div class="col-md-3">' +
                                            '<select id="querydropdown" name="querydropdown" class="form-select form-select-sm">' +
                                            '</select>' +
                                            '</div>' +
                                            '<button class="btn btn-sm btn-primary ld-ext-right runbutton" onclick="run_query()">Run Query<div class="ld ld-ring ld-spin"></div></button>' +
                                            '</div>';
                                        $("#btn-save").after(dropdowninfo);
                                    }
                                    $('#querydropdown').append(new Option(data.description, data.id)); // We add the saved query to the dropdown
                                });
                        }
                    },
                });

            } else {
                BootstrapDialog.show({
                    title: 'Stored Queries',
                    type: BootstrapDialog.TYPE_WARNING,
                    size: BootstrapDialog.SIZE_NORMAL,
                    cssClass: 'queries-dialog',
                    nl2br: false,
                    message: 'You need to make a query before you search!',
                    buttons: [{
                        label: lang_admin_close,
                        action: function(dialogItself) {
                            dialogItself.close();
                        }
                    }]
                });
            }
        });

        function run_query() {
            $(".alert").remove();
            $(".runbutton").addClass('running');
            $(".runbutton").prop('disabled', true);
            let id = $('#querydropdown').val();
            $.post("<?php echo site_url('search/run_query'); ?>", {
                    id: id
                })
                .done(function(data) {

                    $('.exportbutton').html('<button class="btn btn-sm btn-primary" onclick="export_stored_query(' + id + ')">Export to ADIF</button>');
                    $('.card-body.result').empty();
                    $(".search-results-box").show();

                    $('.card-body.result').append(data);
                    $('.table').DataTable({
                        "pageLength": 25,
                        responsive: false,
                        ordering: false,
                        "scrollY": "400px",
                        "scrollCollapse": true,
                        "paging": false,
                        "scrollX": true,
                        "language": {
                            url: getDataTablesLanguageUrl(),
                        },
                        dom: 'Bfrtip',
                        buttons: [
                            'csv'
                        ]
                    });
                    // change color of csv-button if dark mode is chosen
                    if (isDarkModeTheme()) {
                        $(".buttons-csv").css("color", "white");
                    }
                    $('[data-bs-toggle="tooltip"]').tooltip();
                    $(".runbutton").removeClass('running');
                    $(".runbutton").prop('disabled', false);
                });
        }

        function delete_stored_query(id) {
            BootstrapDialog.confirm({
                title: 'DANGER',
                message: 'Warning! Are you sure you want delete this stored query?',
                type: BootstrapDialog.TYPE_DANGER,
                closable: true,
                draggable: true,
                btnOKClass: 'btn-danger',
                callback: function(result) {
                    if (result) {
                        $.ajax({
                            url: base_url + 'index.php/search/delete_query',
                            type: 'post',
                            data: {
                                'id': id
                            },
                            success: function(data) {
                                $(".bootstrap-dialog-message").prepend('<div class="alert alert-danger">The stored query has been deleted!</div>');
                                $("#query_" + id).remove(); // removes query from table in dialog
                                $("#querydropdown option[value='" + id + "']").remove(); // removes query from dropdown
                                if ($("#querydropdown option").length == 0) {
                                    $("#btn-edit").remove();
                                    $('.querydropdownform').remove();
                                };
                            },
                            error: function() {
                                $(".bootstrap-dialog-message").prepend('<div class="alert alert-danger">The stored query could not be deleted. Please try again!</div>');
                            },
                        });
                    }
                }
            });
        }

        function edit_stored_query(id) {
            $('#description_' + id).attr('contenteditable', 'true');
            $('#description_' + id).focus();
            $('#edit_' + id).html('<a class="btn btn-primary btn-sm" href="javascript:save_edited_query(' + id + ');">Save</a>'); // Change to save button
        }

        function save_edited_query(id) {
            $('#description_' + id).attr('contenteditable', 'false');
            $('#edit_' + id).html('<a class="btn btn-outline-primary btn-sm" href="javascript:edit_stored_query(' + id + ');">Edit</a>');
            $.ajax({
                url: base_url + 'index.php/search/save_edited_query',
                type: 'post',
                data: {
                    id: id,
                    description: $('#description_' + id).html(),
                },
                success: function(html) {
                    $('#edit_' + id).html('<a class="btn btn-outline-primary btn-sm" href="javascript:edit_stored_query(' + id + ');">Edit</a>'); // Change to edit button
                    $(".bootstrap-dialog-message").prepend('<div class="alert alert-success">The query description has been updated!</div>');
                    $("#querydropdown option[value='" + id + "']").text($('#description_' + id).html()); // Change text in dropdown
                },
                error: function() {
                    $(".bootstrap-dialog-message").prepend('<div class="alert alert-danger">Something went wrong with the save. Please try again!</div>');
                },
            });
        }

        function edit_stored_query_dialog() {
            $(".alert").remove();
            $.ajax({
                url: base_url + 'index.php/search/get_stored_queries',
                type: 'post',
                success: function(html) {
                    BootstrapDialog.show({
                        title: 'Stored Queries',
                        size: BootstrapDialog.SIZE_WIDE,
                        cssClass: 'queries-dialog',
                        nl2br: false,
                        message: html,
                        buttons: [{
                            label: lang_admin_close,
                            action: function(dialogItself) {
                                dialogItself.close();
                            }
                        }]
                    });
                }
            });
        }

        $('#btn-get').on('click', function() {
            $(".alert").remove();
            var result = $('#builder').queryBuilder('getRules');
            if (!$.isEmptyObject(result)) {
                $(".searchbutton").addClass('running');
                $(".searchbutton").prop('disabled', true);

                $.post("<?php echo site_url('search/search_result'); ?>", {
                        search: JSON.stringify(result, null, 2),
                        temp: "testvar"
                    })
                    .done(function(data) {
                        $('.exportbutton').html('<button class="btn btn-sm btn-primary" onclick="export_search_result();">Export to ADIF</button>');

                        $('.card-body.result').empty();
                        $(".search-results-box").show();

                        $('.card-body.result').append(data);
                        $('.table').DataTable({
                            "pageLength": 25,
                            responsive: false,
                            ordering: false,
                            "scrollY": "400px",
                            "scrollCollapse": true,
                            "paging": false,
                            "scrollX": true,
                            "language": {
                                url: getDataTablesLanguageUrl(),
                            },
                            dom: 'Bfrtip',
                            buttons: [
                                'csv'
                            ]
                        });
                        // change color of csv-button if dark mode is chosen
                        if (isDarkModeTheme()) {
                            $(".buttons-csv").css("color", "white");
                        }
                        $('[data-bs-toggle="tooltip"]').tooltip();
                        $(".searchbutton").removeClass('running');
                        $(".searchbutton").prop('disabled', false);
                        $("#btn-save").show();
                        $('.table-responsive .dropdown-toggle').off('mouseenter').on('mouseenter', function() {
                            showQsoActionsMenu($(this).closest('.dropdown'));
                        });
                    });
            } else {
                BootstrapDialog.show({
                    title: 'Stored Queries',
                    type: BootstrapDialog.TYPE_WARNING,
                    size: BootstrapDialog.SIZE_NORMAL,
                    cssClass: 'queries-dialog',
                    nl2br: false,
                    message: 'You need to make a query before you search!',
                    buttons: [{
                        label: lang_admin_close,
                        action: function(dialogItself) {
                            dialogItself.close();
                        }
                    }]
                });
            }
        });

        $('#btn-set').on('click', function() {
            //$('#builder').queryBuilder('setRules', rules_basic);
            var result = $('#builder').queryBuilder('getRules');
            if (!$.isEmptyObject(result)) {
                rules_basic = result;
            }
        });

        //When rules changed :
        $('#builder').on('getRules.queryBuilder.filter', function(e) {
            //$log.info(e.value);
        });
    </script>

<?php } ?>

<script>
    $(document).ready(function() {
        $('#create_station_profile #country').val($("#dxcc_select option:selected").text());
        $("#create_station_profile #dxcc_select").change(function() {
            $('#country').val($("#dxcc_select option:selected").text());

        });
    });
</script>

<script>
    function printWarning() {
        if ($("#dxcc_select option:selected").text().includes("<?php echo lang('gen_hamradio_deleted_dxcc'); ?>")) {
            $('#warningMessageDXCC').show();
            $('#dxcc_select').css('border', '2px solid rgb(217, 83, 79)');
            $('#warningMessageDXCC').text("<?php echo lang('station_location_dxcc_warning'); ?>");
        } else {
            $('#dxcc_select').css('border', '');
            $('#warningMessageDXCC').hide();
        }
    }
    $('#dxcc_select').ready(function() {
        printWarning();
    });

    $('#dxcc_select').on('change', function() {
        printWarning();
    });
</script>

<script>
    var $ = jQuery.noConflict();
    $('[data-fancybox]').fancybox({
        toolbar: false,
        smallBtn: true,
        iframe: {
            preload: false
        }
    });

    // Here we capture ALT-L to invoke the Quick lookup
    document.onkeyup = function(e) {
        if (e.altKey && e.which == 76) {
            spawnLookupModal();
        }
        if (e.altKey && e.which == 81) {
            spawnQrbCalculator();
        }
    };

    function newpath(latlng1, latlng2, locator1, locator2) {
        // If map is already initialized
        var container = L.DomUtil.get('mapqrbcontainer');

        if (container != null) {
            container._leaflet_id = null;
            container.remove();
            $("#mapqrb").append('<div id="mapqrbcontainer" style="Height: 500px"></div>');
        }

        var map = new L.Map('mapqrbcontainer', {
            fullscreenControl: true,
            fullscreenControlOptions: {
                position: 'topleft'
            },
        }).setView([30, 0], 1.5);

        // Need to fix so that marker is placed at same place as end of line, but this only needs to be done when longitude is < -170
        if (latlng2[1] < -170) {
            latlng2[1] = parseFloat(latlng2[1]) + 360;
        }
        if (latlng1[1] < -170) {
            latlng1[1] = parseFloat(latlng1[1]) + 360;
        }

        map.fitBounds([
            [latlng1[0], latlng1[1]],
            [latlng2[0], latlng2[1]]
        ]);

        var maidenhead = L.maidenheadqrb().addTo(map);

        var osmUrl = '<?php echo $this->optionslib->get_option('option_map_tile_server'); ?>';
        var osmAttrib = 'Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors';
        var osm = new L.TileLayer(osmUrl, {
            minZoom: 1,
            maxZoom: 12,
            attribution: osmAttrib
        });

        var redIcon = L.icon({
            iconUrl: icon_dot_url,
            iconSize: [10, 10], // size of the icon
        });

        map.addLayer(osm);

        var marker = L.marker([latlng1[0], latlng1[1]], {
            closeOnClick: false,
            autoClose: false
        }).addTo(map).bindPopup(locator1);

        var marker2 = L.marker([latlng2[0], latlng2[1]], {
            closeOnClick: false,
            autoClose: false
        }).addTo(map).bindPopup(locator2);

        const multiplelines = [];
        multiplelines.push(
            new L.LatLng(latlng1[0], latlng1[1]),
            new L.LatLng(latlng2[0], latlng2[1])
        )

        const geodesic = L.geodesic(multiplelines, {
            weight: 3,
            opacity: 1,
            color: 'red',
            wrap: false,
            steps: 100
        }).addTo(map);
    }

    function showActivatorsMap(call, count, grids) {

        let re = /,/g;
        grids = grids.replace(re, ', ');

        var result = "Callsign: " + call.replace('0', '&Oslash;') + "<br />";
        result += "Count: " + count + "<br/>";
        result += "Grids: " + grids + "<br/><br />";

        $(".activatorsmapResult").html(result);

        // If map is already initialized
        var container = L.DomUtil.get('mapactivators');

        if (container != null) {
            container._leaflet_id = null;
        }

        const map = new L.map('mapactivators').setView([30, 0], 1.5);

        var grid_four = grids.split(', ');

        var maidenhead = new L.maidenheadactivators(grid_four).addTo(map);

        var osmUrl = '<?php echo $this->optionslib->get_option('option_map_tile_server'); ?>';
        var osmAttrib = 'Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors';
        var osm = new L.TileLayer(osmUrl, {
            minZoom: 1,
            maxZoom: 12,
            attribution: osmAttrib
        });

        map.addLayer(osm);
    }
</script>

<?php if ($this->uri->segment(1) == "map" && $this->uri->segment(2) == "custom") { ?>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/leaflet/L.Maidenhead.js"></script>
    <script id="leafembed" type="text/javascript" src="<?php echo base_url(); ?>assets/js/leaflet/leafembed.js" tileUrl="<?php echo $this->optionslib->get_option('option_map_tile_server'); ?>"></script>
    <script type="text/javascript">
        $(function() {
            $('[data-bs-toggle="tooltip"]').tooltip()
        });

        <?php if ($qra == "set") { ?>
            var q_lat = <?php echo $qra_lat; ?>;
            var q_lng = <?php echo $qra_lng; ?>;
        <?php } else { ?>
            var q_lat = 40.313043;
            var q_lng = -32.695312;
        <?php } ?>

        var qso_loc = '<?php echo site_url('map/map_plot_json/'); ?>';
        var q_zoom = 3;

        $(document).ready(function() {
            <?php if ($this->config->item('map_gridsquares') != FALSE) { ?>
                var grid = "Yes";
            <?php } else { ?>
                var grid = "No";
            <?php } ?>
            initmap(grid, 'custommap', {
                'initmap_only': true
            });
            // Check and change date if to < from //
            $('.custom-map-QSOs input[name="to"]').off('change').on('change', function() {
                if ($('.custom-map-QSOs input[name="to"]').val().replaceAll('-', '') < $('.custom-map-QSOs input[name="from"]').val().replaceAll('-', '')) {
                    $('.custom-map-QSOs input[name="from"]').val($('.custom-map-QSOs input[name="to"]').val());
                }
            });
            $('.custom-map-QSOs input[name="from"]').off('change').on('change', function() {
                if ($('.custom-map-QSOs input[name="from"]').val().replaceAll('-', '') > $('.custom-map-QSOs input[name="to"]').val().replaceAll('-', '')) {
                    $('.custom-map-QSOs input[name="to"]').val($('.custom-map-QSOs input[name="from"]').val());
                }
            });
            // Form "submit" //
            $('.custom-map-QSOs .btn_submit_map_custom').off('click').on('click', function() {
                // Show loading spinner and disable button
                const $button = $(this);
                const $spinner = $('#load-spinner');
                
                $button.prop('disabled', true);
                $spinner.removeClass('d-none');
                
                // Hide any previous alerts
                $('.warningOnSubmit').hide();
                $('#map-success-alert').addClass('d-none');
                
                // Failsafe timeout to prevent stuck spinner (60 seconds)
                const failsafeTimeout = setTimeout(function() {
                    console.warn('Map loading timed out - forcing spinner hide');
                    $button.prop('disabled', false);
                    $spinner.addClass('d-none');
                    $('.warningOnSubmit .warningOnSubmit_txt').text('Map loading timed out. Please try again.');
                    $('.warningOnSubmit').show();
                }, 60000);
                
                var customdata = {
                    'dataPost': {
                        'date_from': $('.custom-map-QSOs input[name="from"]').val(),
                        'date_to': $('.custom-map-QSOs input[name="to"]').val(),
                        'band': $('.custom-map-QSOs select[name="band"]').val(),
                        'mode': $('.custom-map-QSOs select[name="mode"]').val(),
                        'prop_mode': $('.custom-map-QSOs select[name="prop_mode"]').val(),
                        'isCustom': true
                    },
                    'map_id': '#custommap'
                };
                
                // Add success and error callbacks to the customdata
                customdata.onSuccess = function(plotjson) {
                    console.log('Map loading success callback called with data:', plotjson);
                    
                    // Clear the failsafe timeout
                    clearTimeout(failsafeTimeout);
                    
                    try {
                        // Update statistics
                        if (typeof updateMapStatistics === 'function') {
                            console.log('Calling updateMapStatistics function');
                            updateMapStatistics(plotjson);
                        } else {
                            console.warn('updateMapStatistics function not found');
                        }
                        
                        // Show success message
                        const qsoCount = plotjson['markers'] ? plotjson['markers'].length : 0;
                        console.log('QSO count:', qsoCount);
                        $('#qso-count-display').text(`Loaded ${qsoCount} QSOs successfully`);
                        $('#map-success-alert').removeClass('d-none');
                        
                        setTimeout(() => {
                            $('#map-success-alert').addClass('d-none');
                        }, 3000);
                    } catch (error) {
                        console.error('Error in success callback:', error);
                        $('.warningOnSubmit .warningOnSubmit_txt').text('Map loaded but encountered an error displaying statistics.');
                        $('.warningOnSubmit').show();
                    } finally {
                        // Always re-enable button and hide spinner
                        console.log('Re-enabling button and hiding spinner');
                        $button.prop('disabled', false);
                        $spinner.addClass('d-none');
                    }
                };
                
                customdata.onError = function() {
                    console.log('Map loading error callback called');
                    
                    // Clear the failsafe timeout
                    clearTimeout(failsafeTimeout);
                    
                    $('.warningOnSubmit .warningOnSubmit_txt').text('Failed to load map data. Please try again.');
                    $('.warningOnSubmit').show();
                    
                    // Re-enable button and hide spinner
                    $button.prop('disabled', false);
                    $spinner.addClass('d-none');
                };
                
                initplot(qso_loc, customdata);
            })
        });

        function get_oldest_qso_date() {
            $.ajax({
                url: base_url + 'index.php/map/get_oldest_qso_date',
                type: 'post',
                success: function(data) {
                    document.getElementById('from').value = data;
                    document.getElementById('to').value = new Date().toISOString().split('T')[0];
                    // Update the date range display
                    if (typeof updateDateRangeDisplay === 'function') {
                        updateDateRangeDisplay();
                    }
                },
                error: function() {},
            });
        }
    </script>
<?php } ?>

<?php if ($this->uri->segment(1) == "" || $this->uri->segment(1) == "dashboard") { ?>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/leaflet/L.Maidenhead.js"></script>

    <script>
        var iconsList = {
            'qso': {
                'color': '#FF0000',
                'icon': 'fas fa-dot-circle'
            }
        };
    </script>

    <script>
        // jquery onready
        $(document).ready(function() {
            $.ajax({
                url: base_url + 'index.php/user_options/get_map_custom',
                type: 'GET',
                dataType: 'json',
                error: function() {
                    console.log('[ERROR] ajax get_map_custom() function return error.');
                },
                success: function(json_mapinfo) {
                    console.log(json_mapinfo);
                    if (typeof json_mapinfo.qso !== "undefined") {
                        iconsList = json_mapinfo;
                    }
                }
            });
        });

        console.log(iconsList);
    </script>

    <script type="text/javascript">
        $(function() {
            $('[data-bs-toggle="tooltip"]').tooltip()
        });

        <?php if ($qra == "set") { ?>
            var q_lat = <?php echo $qra_lat; ?>;
            var q_lng = <?php echo $qra_lng; ?>;
        <?php } else { ?>
            var q_lat = 40.313043;
            var q_lng = -32.695312;
        <?php } ?>

        var qso_loc = '<?php echo site_url('map/map_plot_json'); ?>';
        var q_zoom = 3;
        var osmUrl = '<?php echo $this->optionslib->get_option('option_map_tile_server'); ?>';
        var osmCopyright = '<?php echo $this->optionslib->get_option('map_tile_server_copyright'); ?>';

        var redIconImg = L.icon({
            iconUrl: icon_dot_url,
            iconSize: [10, 10]
        });

        $(document).ready(function() {
            <?php if ($this->config->item('map_gridsquares') != FALSE) { ?>
                var ShowGrid = "Yes";
            <?php } else { ?>
                var ShowGrid = "No";
            <?php } ?>

            var layer = L.tileLayer(osmUrl, {
                maxZoom: 18,
                attribution: osmCopyright,
            });

            var map = L.map('map', {
                layers: [layer],
                center: [q_lat, q_lng],
                zoom: q_zoom,
                fullscreenControl: true,
                fullscreenControlOptions: {
                    position: 'topleft'
                },
            });

            var markersLayer = L.layerGroup().addTo(map);

            var baseLayers = {
                "Map": layer
            };
            var overlays = {
                "QSOs": markersLayer
            };

            var greylineEnabled = <?php echo (isset($dashboard_map_greyline) && $dashboard_map_greyline) ? 'true' : 'false'; ?>;
            var greyline = L.terminator({
                color: '#4a6fa5',
                fillColor: '#001f3f',
                fillOpacity: 0.18,
                weight: 1.5,
                interactive: false
            });
            var greylineIntervalId = null;

            function refreshGreyline() {
                greyline.setTime(new Date());
            }

            function startGreylineUpdates() {
                if (greylineIntervalId !== null) {
                    return;
                }
                refreshGreyline();
                greylineIntervalId = setInterval(refreshGreyline, 60000);
            }

            function stopGreylineUpdates() {
                if (greylineIntervalId !== null) {
                    clearInterval(greylineIntervalId);
                    greylineIntervalId = null;
                }
            }

            overlays["Greyline"] = greyline;

            if (greylineEnabled) {
                greyline.addTo(map);
                startGreylineUpdates();
            }

            L.control.layers(baseLayers, overlays, {
                collapsed: true
            }).addTo(map);

            map.on('overlayadd', function(event) {
                if (event.layer === greyline) {
                    startGreylineUpdates();
                }
            });

            map.on('overlayremove', function(event) {
                if (event.layer === greyline) {
                    stopGreylineUpdates();
                }
            });

            map.on('unload', function() {
                stopGreylineUpdates();
            });

            /*var printer = L.easyPrint({
                sizeModes: ['Current'],
                filename: 'myMap',
                exportOnly: true,
                hideControlContainer: true
            }).addTo(map);*/

            var markers = {};

            function loadMarkers() {
                fetch(qso_loc)
                    .then(response => response.json())
                    .then(data => {
                        if (data.error !== "No QSOs found") {
                            var newMarkers = {};
                            data.markers.forEach(marker => {
                                var key = `${marker.lat},${marker.lng}`;
                                var html = `<h3>${marker.flag}${marker.label}</h3> ${marker.html}`;
                                newMarkers[key] = marker;
                                if (!markers[key]) {
                                    var icon = L.divIcon({
                                        className: 'custom-icon',
                                        html: `<i class="${iconsList.qso.icon}" style="color:${iconsList.qso.color}"></i>`
                                    });

                                    markers[key] = L.marker([marker.lat, marker.lng], {
                                            icon: icon
                                        })
                                        .addTo(markersLayer)
                                        .bindPopup(html);
                                }
                            });
                            Object.keys(markers).forEach(key => {
                                if (!newMarkers[key]) {
                                    markersLayer.removeLayer(markers[key]);
                                }
                            });
                            Object.keys(markers).forEach(key => {
                                if (newMarkers[key]) {
                                    newMarkers[key] = markers[key];
                                }
                            });
                            markers = newMarkers;
                        } else {
                            console.log("No QSOs found to populate dashboard map.");
                        }
                    });
            }

            loadMarkers();
            setInterval(loadMarkers, 5000);

        });
    </script>
<?php } ?>



<?php if ($this->uri->segment(1) == "radio") { ?>
    <!-- If this is the admin/radio page run the JS -->
    <script type="text/javascript">
        $(document).ready(function() {
            // Load radio status immediately on page load
            function loadRadioStatus() {
                $.get('radio/status/', function(result) {
                    $('#radio-loading').hide();
                    $('.status').html(result).show();
                });
            }
            
            // Load immediately
            loadRadioStatus();
            
            // Then refresh every 2 seconds
            setInterval(loadRadioStatus, 2000);
        });
    </script>
<?php } ?>



<script type="text/javascript">
    $(function() {
        $('[data-bs-toggle="tooltip"]').tooltip()
    });
</script>

<?php if ($this->uri->segment(1) == "search") { ?>
    <script type="text/javascript">
        i = 0;

        function findduplicates() {
            event.preventDefault();
            $('#partial_view').load(base_url + "index.php/logbook/search_duplicates/" + $("#station_id").val(), function() {
                $('.qsolist').DataTable({
                    "pageLength": 25,
                    responsive: false,
                    ordering: false,
                    "scrollY": "500px",
                    "scrollCollapse": true,
                    "paging": false,
                    "scrollX": true,
                    "language": {
                        url: getDataTablesLanguageUrl(),
                    },
                    dom: 'Bfrtip',
                    buttons: [
                        'csv'
                    ]
                });
                // change color of csv-button if dark mode is chosen
                if (isDarkModeTheme()) {
                    $(".buttons-csv").css("color", "white");
                }
            });
        }

        function findlotwunconfirmed() {
            event.preventDefault();
            $('#partial_view').load(base_url + "index.php/logbook/search_lotw_unconfirmed/" + $("#station_id").val(), function() {
                $('.qsolist').DataTable({
                    "pageLength": 25,
                    responsive: false,
                    ordering: false,
                    "scrollY": "500px",
                    "scrollCollapse": true,
                    "paging": false,
                    "scrollX": true,
                    "language": {
                        url: getDataTablesLanguageUrl(),
                    },
                    dom: 'Bfrtip',
                    buttons: [
                        'csv'
                    ]
                });
                // change color of csv-button if dark mode is chosen
                if (isDarkModeTheme()) {
                    $(".buttons-csv").css("color", "white");
                }
            });
        }

        function findincorrectcqzones() {
            event.preventDefault();
            $('#partial_view').load(base_url + "index.php/logbook/search_incorrect_cq_zones/" + $("#station_id").val(), function() {
                $('.qsolist').DataTable({
                    "pageLength": 25,
                    responsive: false,
                    ordering: false,
                    "scrollY": "500px",
                    "scrollCollapse": true,
                    "paging": false,
                    "scrollX": true,
                    "language": {
                        url: getDataTablesLanguageUrl(),
                    },
                    dom: 'Bfrtip',
                    buttons: [
                        'csv'
                    ]
                });
                // change color of csv-button if dark mode is chosen
                if (isDarkModeTheme()) {
                    $(".buttons-csv").css("color", "white");
                }
            });
        }

        function searchButtonPress() {
            event.preventDefault()
            if ($('#callsign').val()) {
                let fixedcall = $('#callsign').val();
                $('#partial_view').load("logbook/search_result/" + fixedcall.replace('Ø', '0'), function() {
                    $('[data-bs-toggle="tooltip"]').tooltip()
                });
            }
        }

        $(document).ready(function() {

            <?php if ($this->input->post('callsign') != "") { ?>
                $('#partial_view').load("logbook/search_result/<?php echo str_replace("Ø", "0", $this->input->post('callsign')); ?>", function() {
                    $('[data-bs-toggle="tooltip"]').tooltip()
                });
            <?php } ?>

            $($('#callsign')).on('keypress', function(e) {
                if (e.which == 13) {

                    if ($('#callsign').val()) {
                        let fixedcall = $('#callsign').val();
                        $('#partial_view').load("logbook/search_result/" + fixedcall.replace('Ø', '0'), function() {
                            $('[data-bs-toggle="tooltip"]').tooltip()
                        });
                    }

                    event.preventDefault();
                    return false;
                }
            });


        });
    </script>
<?php } ?>

<?php if ($this->uri->segment(1) == "logbook" && $this->uri->segment(2) != "view") { ?>
    <!-- Quill editor for Station Diary modal -->
    <script src="<?php echo base_url(); ?>assets/plugins/quill/quill.min.js"></script>
    
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/leaflet/L.Maidenhead.js"></script>
    <script id="leafembed" type="text/javascript" src="<?php echo base_url(); ?>assets/js/leaflet/leafembed.js" tileUrl="<?php echo $this->optionslib->get_option('option_map_tile_server'); ?>"></script>
    <script type="text/javascript">
        $(function() {
            $('[data-bs-toggle="tooltip"]').tooltip()
        });
    </script>
    <script type="text/javascript">
        <?php if ($qra == "set") { ?>
            var q_lat = <?php echo $qra_lat; ?>;
            var q_lng = <?php echo $qra_lng; ?>;
        <?php } else { ?>
            var q_lat = 40.313043;
            var q_lng = -32.695312;
        <?php } ?>

        var qso_loc = '<?php echo site_url('map/map_plot_json'); ?>';
        var q_zoom = 3;

        <?php if ($this->config->item('map_gridsquares') != FALSE) { ?>
            var grid = "Yes";
        <?php } else { ?>
            var grid = "No";
        <?php } ?>
        initmap(grid, 'map', {
            'dataPost': {
                'nb_qso': '25',
                'offset': '<?php echo $this->uri->segment(3); ?>'
            }
        });
    </script>
<?php } ?>

<?php if ($this->uri->segment(1) == "qso") { ?>

    <script src="<?php echo base_url(); ?>assets/js/qra-utils.js"></script>
    <script src="<?php echo base_url(); ?>assets/js/sections/qso.js"></script>
    <script src="<?php echo base_url(); ?>assets/js/cw-sidetone.js"></script>
    <?php if (isset($isRemoteOperationEnabled) ? $isRemoteOperationEnabled : $this->session->userdata('isRemoteOperationEnabled')) { ?>
        <script src="<?php echo base_url(); ?>assets/js/remote-operation.js"></script>
    <?php } ?>
    <?php if ($this->session->userdata('isWinkeyEnabled') && !$this->session->userdata('isWinkeyWebsocketEnabled')) { ?>
        <script src="<?php echo base_url(); ?>assets/js/winkey.js"></script>
    <?php } elseif ($this->session->userdata('isWinkeyEnabled') && $this->session->userdata('isWinkeyWebsocketEnabled')) { ?>
        <script>
            console.log('Winkey Websocket enabled');
            
            // Mode detection for WebSocket Winkey
            document.addEventListener('DOMContentLoaded', function() {
                const ModeSelected = document.getElementById('mode');
                
                function toggleWinkeyVisibility() {
                    const winkeyElement = document.getElementById('winkey');
                    if (ModeSelected && winkeyElement) {
                        if (ModeSelected.value === 'CW') {
                            winkeyElement.style.display = 'block';
                        } else {
                            winkeyElement.style.display = 'none';
                        }
                    }
                }
                
                // Check initial mode
                toggleWinkeyVisibility();
                
                // Listen for mode changes
                if (ModeSelected) {
                    ModeSelected.addEventListener('change', toggleWinkeyVisibility);
                }
            });
        </script>

        <script>
            let ws = null;
            let wsRelayEnabled = false;
            let wsRelayRoom = 'cw_room';
            let wsRelayToken = '';
            let wsRelayUrl = 'wss://relay.cloudlog.org/';

            const RELAY_STORAGE = {
                enabled: 'cloudlog.winkeyRelay.enabled',
                url: 'cloudlog.winkeyRelay.url',
                token: 'cloudlog.winkeyRelay.token',
                room: 'cloudlog.winkeyRelay.room'
            };

            async function loadRelaySettingsFromAccount() {
                try {
                    const response = await fetch(base_url + 'index.php/qso/winkeyrelaysettings_json');
                    const data = await response.json();

                    if (data.status === 'ok' && data.settings) {
                        wsRelayEnabled = !!data.settings.enabled;
                        wsRelayUrl = data.settings.url || 'wss://relay.cloudlog.org/';
                        wsRelayRoom = data.settings.room || 'cw_room';
                        wsRelayToken = data.settings.token || '';
                        return;
                    }
                } catch (error) {
                    console.error('Failed to load relay settings from account', error);
                }

                // Backward compatibility fallback from previous localStorage implementation.
                wsRelayEnabled = localStorage.getItem(RELAY_STORAGE.enabled) === '1';
                wsRelayUrl = localStorage.getItem(RELAY_STORAGE.url) || 'wss://relay.cloudlog.org/';
                wsRelayRoom = localStorage.getItem(RELAY_STORAGE.room) || 'cw_room';
                wsRelayToken = localStorage.getItem('cloudlog.winkeyRelay.token') || '';
            }

            async function saveRelaySettingsToAccount(config) {
                const payload = new URLSearchParams();
                payload.append('enabled', config.enabled ? '1' : '0');
                payload.append('url', config.url);
                payload.append('room', config.room);
                payload.append('token', config.token);

                const response = await fetch(base_url + 'index.php/qso/winkeyrelaysettings_save', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
                    },
                    body: payload.toString()
                });

                const data = await response.json();
                if (!response.ok || data.status !== 'ok') {
                    throw new Error(data.message || 'Failed to save relay token');
                }

                wsRelayEnabled = config.enabled;
                wsRelayUrl = config.url;
                wsRelayRoom = config.room;
                wsRelayToken = config.token;

                // Clear legacy local storage keys after successful account save.
                localStorage.removeItem(RELAY_STORAGE.enabled);
                localStorage.removeItem(RELAY_STORAGE.url);
                localStorage.removeItem(RELAY_STORAGE.room);
                localStorage.removeItem(RELAY_STORAGE.token);
            }

            function getRelayConfig() {
                return {
                    enabled: wsRelayEnabled,
                    url: wsRelayUrl,
                    token: wsRelayToken,
                    room: wsRelayRoom
                };
            }

            function setSocketStatus(text, className) {
                const statusBadge = document.getElementById('cw_socket_status');
                if (!statusBadge) {
                    return;
                }

                statusBadge.className = className;
                statusBadge.innerHTML = text;
            }

            function getTransportLabel() {
                return wsRelayEnabled ? 'Relay' : 'Direct';
            }

            function openWinkeyRelaySettings() {
                const config = getRelayConfig();

                const enabledField = document.getElementById('winkeyRelayEnabled');
                const urlField = document.getElementById('winkeyRelayUrl');
                const tokenField = document.getElementById('winkeyRelayToken');
                const roomField = document.getElementById('winkeyRelayRoom');

                if (enabledField) {
                    enabledField.checked = config.enabled;
                }
                if (urlField) {
                    urlField.value = config.url;
                }
                if (tokenField) {
                    tokenField.value = config.token;
                }
                if (roomField) {
                    roomField.value = config.room;
                }

                const modalEl = document.getElementById('winkeyRelaySettingsModal');
                if (modalEl) {
                    bootstrap.Modal.getOrCreateInstance(modalEl).show();
                }
            }

            async function saveWinkeyRelaySettings() {
                const enabledField = document.getElementById('winkeyRelayEnabled');
                const urlField = document.getElementById('winkeyRelayUrl');
                const tokenField = document.getElementById('winkeyRelayToken');
                const roomField = document.getElementById('winkeyRelayRoom');

                const config = {
                    enabled: enabledField ? enabledField.checked : false,
                    url: urlField ? urlField.value.trim() : '',
                    token: tokenField ? tokenField.value.trim() : '',
                    room: roomField ? roomField.value.trim() : 'cw_room'
                };

                if (config.enabled) {
                    if (!config.url.startsWith('ws://') && !config.url.startsWith('wss://')) {
                        alert('Relay URL must start with ws:// or wss://');
                        return;
                    }

                    if (config.token.length < 8) {
                        alert('Relay token must be at least 8 characters');
                        return;
                    }

                    if (config.room === '') {
                        alert('Relay room is required');
                        return;
                    }
                }

                if (config.room === '') {
                    config.room = 'cw_room';
                }

                try {
                    await saveRelaySettingsToAccount(config);
                } catch (error) {
                    alert(error.message || 'Failed to save relay settings');
                    return;
                }

                const modalEl = document.getElementById('winkeyRelaySettingsModal');
                if (modalEl) {
                    bootstrap.Modal.getOrCreateInstance(modalEl).hide();
                }

                logMessage('Relay settings saved');
                connectWebSocket();
            }

            function connectWebSocket() {
                if (ws !== null) {
                    ws.close();
                }

                const relayConfig = getRelayConfig();
                wsRelayEnabled = relayConfig.enabled;
                wsRelayRoom = relayConfig.room || 'cw_room';
                wsRelayUrl = relayConfig.url || 'wss://relay.cloudlog.org/';
                wsRelayToken = relayConfig.token || '';

                if (wsRelayEnabled) {
                    if ((!wsRelayUrl.startsWith('ws://') && !wsRelayUrl.startsWith('wss://')) || wsRelayToken.length < 8) {
                        setSocketStatus('Status: Relay Config Error', 'badge bg-danger');
                        logMessage('Relay settings are invalid. Open Relay settings to fix URL/token.');
                        return;
                    }
                }

                const wsUrl = wsRelayEnabled
                    ? wsRelayUrl
                    : `ws://localhost:8181?chatRoom=${encodeURIComponent(wsRelayRoom)}`;

                setSocketStatus('Status: Connecting (' + getTransportLabel() + ')', 'badge bg-warning text-dark');
                logMessage('Connecting to ' + wsUrl);

                ws = new WebSocket(wsUrl);

                ws.onopen = function() {
                    if (wsRelayEnabled) {
                        const joinMessage = {
                            op: 'join',
                            token: wsRelayToken,
                            role: 'browser',
                            rooms: [wsRelayRoom]
                        };

                        ws.send(JSON.stringify(joinMessage));
                        setSocketStatus('Status: Authenticating (Relay)', 'badge bg-warning text-dark');
                        logMessage('Sent relay join request for room: ' + wsRelayRoom);
                    } else {
                        setSocketStatus('Status: Connected (Direct)', 'badge bg-success');
                        logMessage('Connected to WebSocket server in room: ' + wsRelayRoom);
                        setTimeout(getCwSpeed, 1000);
                    }
                };

                ws.onclose = function() {
                    setSocketStatus('Status: Disconnected (' + getTransportLabel() + ')', 'badge bg-secondary');
                    logMessage('Disconnected from WebSocket server');
                    ws = null;
                };

                ws.onerror = function(error) {
                    setSocketStatus('Status: Error', 'badge bg-danger');
                    logMessage('WebSocket Error: ' + error);
                };

                ws.onmessage = function(event) {
                    let message = event.data;

                    if (wsRelayEnabled) {
                        try {
                            const relayMessage = JSON.parse(event.data);
                            if (relayMessage && relayMessage.op === 'joined') {
                                setSocketStatus('Status: Connected (Relay)', 'badge bg-success');
                                logMessage('Relay joined room: ' + wsRelayRoom);
                                setTimeout(getCwSpeed, 1000);
                                return;
                            }

                            if (relayMessage && relayMessage.op === 'frame') {
                                if (relayMessage.room !== wsRelayRoom) {
                                    return;
                                }

                                message = relayMessage.data;
                            } else if (relayMessage && relayMessage.op === 'error') {
                                setSocketStatus('Status: Relay Error', 'badge bg-danger');
                                logMessage('Relay error: ' + (relayMessage.message || 'unknown'));
                                return;
                            }
                        } catch (e) {
                            // Keep compatibility with plain text payloads.
                        }
                    }

                    logMessage('Received: ' + message);

                    if (message.startsWith('CWSPEED SET:')) {
                        const match = message.match(/CWSPEED SET: (\d+) WPM/);
                        if (match) {
                            updateSpeedDisplay(parseInt(match[1]));
                        }
                    } else if (message.startsWith('CWSPEED:')) {
                        const match = message.match(/CWSPEED: (\d+) WPM/);
                        if (match) {
                            updateSpeedDisplay(parseInt(match[1]));
                        }
                    }
                };
            }

            function disconnectWebSocket() {
                if (ws !== null) {
                    ws.close();
                }
            }

            function sendWinkeyCommand(command, quiet) {
                if (!ws || ws.readyState !== WebSocket.OPEN) {
                    if (!quiet) {
                        alert('Please connect to the WebSocket server first');
                    }
                    return;
                }

                if (wsRelayEnabled) {
                    const relayFrame = {
                        op: 'frame',
                        room: wsRelayRoom,
                        data: command
                    };
                    ws.send(JSON.stringify(relayFrame));
                } else {
                    ws.send(command);
                }

                logMessage('Sent: ' + command);
            }

            function logMessage(message) {
                const messageLog = document.getElementById('messageLog');
                if (!messageLog) {
                    return;
                }
                messageLog.value += message + '\n';
                // Auto-scroll to bottom
                messageLog.scrollTop = messageLog.scrollHeight;
            }

            document.addEventListener('DOMContentLoaded', function() {
                const sendTextElement = document.getElementById('sendText');
                if (sendTextElement) {
                    sendTextElement.addEventListener('keydown', function(e) {
                        if (e.key === 'Enter') {
                            e.preventDefault();
                            sendMyMessage();
                        }
                    });
                }

                const saveRelayButton = document.getElementById('saveWinkeyRelaySettings');
                if (saveRelayButton) {
                    saveRelayButton.addEventListener('click', saveWinkeyRelaySettings);
                }

                loadRelaySettingsFromAccount().finally(function() {
                    connectWebSocket();
                });
            });
        </script>

        <script>
            function morsekey_func1() {
                const textToSend = UpdateMacros(function1Macro);
                console.log("F1: " + textToSend);
                const cwMessage = 'CW:' + textToSend;
                sendWinkeyCommand(cwMessage, false);
                if (window.cloudlogCwSidetone) {
                    window.cloudlogCwSidetone.playText(textToSend, currentCwSpeed || 20);
                }
            }

            function morsekey_func2() {
                const textToSend = UpdateMacros(function2Macro);
                console.log("F2: " + textToSend);
                const cwMessage = 'CW:' + textToSend;
                sendWinkeyCommand(cwMessage, false);
                if (window.cloudlogCwSidetone) {
                    window.cloudlogCwSidetone.playText(textToSend, currentCwSpeed || 20);
                }
            }

            function morsekey_func3() {
                const textToSend = UpdateMacros(function3Macro);
                console.log("F3: " + textToSend);
                const cwMessage = 'CW:' + textToSend;
                sendWinkeyCommand(cwMessage, false);
                if (window.cloudlogCwSidetone) {
                    window.cloudlogCwSidetone.playText(textToSend, currentCwSpeed || 20);
                }
            }

            function morsekey_func4() {
                const textToSend = UpdateMacros(function4Macro);
                console.log("F4: " + textToSend);
                const cwMessage = 'CW:' + textToSend;
                sendWinkeyCommand(cwMessage, false);
                if (window.cloudlogCwSidetone) {
                    window.cloudlogCwSidetone.playText(textToSend, currentCwSpeed || 20);
                }
            }

            function morsekey_func5() {
                const textToSend = UpdateMacros(function5Macro);
                console.log("F5: " + textToSend);
                const cwMessage = 'CW:' + textToSend;
                sendWinkeyCommand(cwMessage, false);
                if (window.cloudlogCwSidetone) {
                    window.cloudlogCwSidetone.playText(textToSend, currentCwSpeed || 20);
                }
            }

            let function1Name, function1Macro, function2Name, function2Macro, function3Name, function3Macro, function4Name, function4Macro, function5Name, function5Macro;

            getMacros();

            document.addEventListener('keydown', function(event) {

                if (event.key === 'F1') {
                    event.preventDefault();
                    morsekey_func1();
                }

                if (event.key === 'F2') {
                    event.preventDefault();
                    morsekey_func2();
                }

                if (event.key === 'F3') {
                    event.preventDefault();
                    morsekey_func3();
                }

                if (event.key === 'F4') {
                    event.preventDefault();
                    morsekey_func4();
                }

                if (event.key === 'F5') {
                    event.preventDefault();
                    morsekey_func5();
                }
            });

            function UpdateMacros(macrotext) {

                // Get the values from the form set to uppercase
                let CALL = document.getElementById("callsign").value.toUpperCase();
                let RSTS = document.getElementById("rst_sent").value;

                let newString;
                newString = macrotext.replace(/\[MYCALL\]/g, my_call);
                newString = newString.replace(/\[CALL\]/g, CALL);
                newString = newString.replace(/\[RSTS\]/g, RSTS);
                console.log(newString);
                return newString;
            }

            // Call url and store the returned json data as variables
            function getMacros() {
                fetch(base_url + 'index.php/qso/cwmacros_json')
                    .then(response => response.json())
                    .then(data => {
                        function1Name = data.function1_name;
                        function1Macro = data.function1_macro;
                        function2Name = data.function2_name;
                        function2Macro = data.function2_macro;
                        function3Name = data.function3_name;
                        function3Macro = data.function3_macro;
                        function4Name = data.function4_name;
                        function4Macro = data.function4_macro;
                        function5Name = data.function5_name;
                        function5Macro = data.function5_macro;

                        const morsekey_func1_Button = document.getElementById('morsekey_func1');
                        morsekey_func1_Button.textContent = 'F1 (' + function1Name + ')';

                        const morsekey_func2_Button = document.getElementById('morsekey_func2');
                        morsekey_func2_Button.textContent = 'F2 (' + function2Name + ')';

                        const morsekey_func3_Button = document.getElementById('morsekey_func3');
                        morsekey_func3_Button.textContent = 'F3 (' + function3Name + ')';

                        const morsekey_func4_Button = document.getElementById('morsekey_func4');
                        morsekey_func4_Button.textContent = 'F4 (' + function4Name + ')';

                        const morsekey_func5_Button = document.getElementById('morsekey_func5');
                        morsekey_func5_Button.textContent = 'F5 (' + function5Name + ')';
                    });
            }


            function sendMyMessage() {
                const message = document.getElementById('sendText').value;
                if (message.trim() === '') {
                    alert('Please enter a message');
                    return;
                }

                const cwMessage = 'CW:' + message;
                sendWinkeyCommand(cwMessage, false);
                if (window.cloudlogCwSidetone) {
                    window.cloudlogCwSidetone.playText(message, currentCwSpeed || 20);
                }

                // Clear the input field and return focus so the next message can be typed immediately
                const sendTextEl = document.getElementById('sendText');
                sendTextEl.value = '';
                setTimeout(function() { sendTextEl.focus(); }, 0);
            }

            // CW Speed Control Functions
            let currentCwSpeed = 20; // Default speed

            function adjustCwSpeed(change) {
                if (ws === null) {
                    alert('Please connect to WebSocket first');
                    return;
                }

                const newSpeed = Math.max(5, Math.min(99, currentCwSpeed + change));
                
                if (newSpeed !== currentCwSpeed) {
                    const speedMessage = 'CWSPEED:' + newSpeed;
                    sendWinkeyCommand(speedMessage, false);
                    // Get updated speed after changing it
                    setTimeout(getCwSpeed, 500);
                }
            }

            function getCwSpeed() {
                if (ws === null) {
                    return;
                }

                sendWinkeyCommand('GETCWSPEED', true);
            }

            function updateSpeedDisplay(speed) {
                currentCwSpeed = speed;
                const speedDisplay = document.getElementById('cwSpeedDisplay');
                if (speedDisplay) {
                    speedDisplay.textContent = speed + ' WPM';
                }
            }

            // Removed constant polling functions to prevent WebSocket disruption
            // Speed is now only read on initial connection and after speed changes

            // Message log toggle function
            function toggleMessageLog() {
                const logContainer = document.getElementById('messageLogContainer');
                const toggleButton = document.getElementById('toggleLogButton');
                
                if (logContainer.style.display === 'none') {
                    logContainer.style.display = 'block';
                    toggleButton.innerHTML = '<i class="fas fa-eye-slash"></i>';
                    toggleButton.title = 'Hide Message Log';
                } else {
                    logContainer.style.display = 'none';
                    toggleButton.innerHTML = '<i class="fas fa-list"></i>';
                    toggleButton.title = 'Show Message Log';
                }
            }
        </script>
    <?php } ?>
    
    <?php

    $this->load->model('stations');
    $active_station_id = $this->stations->find_active();
    $station_profile = $this->stations->profile($active_station_id);
    $active_station_info = $station_profile->row();

    if (strpos($active_station_info->station_gridsquare, ',') !== false) {
        $gridsquareArray = explode(',', $active_station_info->station_gridsquare);
        $user_gridsquare = $gridsquareArray[0];
    } else {
        $user_gridsquare = $active_station_info->station_gridsquare;
    }
    ?>

    <script>
        var markers = L.layerGroup();
        var pos = [51.505, -0.09];
        var mymap = L.map('qsomap').setView(pos, 12);
        $.ajax({
            url: base_url + 'index.php/logbook/qralatlngjson',
            type: 'post',
            data: {
                <?php if ($active_station_info->station_gridsquare != "") { ?>
                    qra: '<?php echo $user_gridsquare; ?>',
                <?php } else if (null !== $this->config->item('locator')) { ?>
                    qra: '<?php echo $this->config->item('locator'); ?>',
                <?php } else { ?>
                    // Fallback to London in case all else fails
                    qra: 'IO91WM',
                <?php } ?>
            },
            success: function(data) {
                result = JSON.parse(data);
                if (typeof result[0] !== "undefined" && typeof result[1] !== "undefined") {
                    mymap.panTo([result[0], result[1]]);
                    pos = result;
                }
            },
            error: function() {},
        });

        L.tileLayer('<?php echo $this->optionslib->get_option('option_map_tile_server'); ?>', {
            maxZoom: 18,
            attribution: '<?php echo $this->optionslib->get_option('option_map_tile_server_copyright'); ?>',
            id: 'mapbox.streets'
        }).addTo(mymap);
    </script>

    <script type="text/javascript">
        var manual = <?php echo $_GET['manual']; ?>;

        $(document).ready(function() {

            $('.callsign-suggest').hide();

            setRst($(".mode").val());

            /* On Page Load */
            var catcher = function(e) {
                // Skip warning if callsign field is empty
                var callsignField = $('#callsign');
                if (callsignField.length > 0 && !callsignField.val().trim()) {
                    return; // No warning if callsign is empty
                }
                
                var changed = false;
                $('form').each(function() {
                    if ($(this).data('initialForm') != $(this).serialize()) {
                        changed = true;
                        $(this).addClass('changed');
                    } else {
                        $(this).removeClass('changed');
                    }
                });
                if (changed) {
                    // For external navigation (closing tab/window), browsers require native dialog
                    e.preventDefault();
                    e.returnValue = 'You have unsaved changes. Are you sure you want to leave?';
                    return e.returnValue;
                }
            };

            $(function() {
                $('form').each(function() {
                    $(this).data('initialForm', $(this).serialize());
                }).submit(function(e) {
                    var formEl = this;
                    var changed = false;
                    $('form').each(function() {
                        if (this != formEl && $(this).data('initialForm') != $(this).serialize()) {
                            changed = true;
                            $(this).addClass('changed');
                        } else {
                            $(this).removeClass('changed');
                        }
                    });
                    if (changed && !confirm('You have an unsaved QSO. Continue with QSO?')) {
                        e.preventDefault();
                    } else {
                        $(window).unbind('beforeunload', catcher);
                    }
                });
                $(window).bind('beforeunload', catcher);
                
                // Intercept internal link clicks to show custom modal
                $(document).on('click', 'a[href]:not([href^="#"]):not([target="_blank"]):not(.no-confirm):not([data-bs-toggle])', function(e) {
                    var href = $(this).attr('href');
                    
                    // Skip if it's a javascript: link, empty, or hash link
                    if (!href || href === '#' || href.indexOf('javascript:') === 0) {
                        return true;
                    }
                    
                    // Skip warning if callsign field is empty
                    var callsignField = $('#callsign');
                    if (callsignField.length > 0 && !callsignField.val().trim()) {
                        return true; // No warning if callsign is empty
                    }
                    
                    // Check if form has unsaved changes
                    var hasChanges = false;
                    $('form').each(function() {
                        if ($(this).data('initialForm') != $(this).serialize()) {
                            hasChanges = true;
                            return false;
                        }
                    });
                    
                    if (hasChanges) {
                        e.preventDefault();
                        
                        // Check if custom modal element exists in DOM at click time
                        var modalEl = document.getElementById('leaveQsoModal');
                        if (modalEl && typeof bootstrap !== 'undefined' && bootstrap.Modal) {
                            // Use custom modal
                            window.pendingNavigation = href;
                            var modal = bootstrap.Modal.getInstance(modalEl);
                            if (!modal) {
                                modal = new bootstrap.Modal(modalEl);
                            }
                            modal.show();
                        } else {
                            // Fallback to confirm dialog on pages without custom modal
                            if (confirm('You have unsaved changes. Are you sure you want to leave QSO entry?')) {
                                $(window).unbind('beforeunload', catcher);
                                window.location.href = href;
                            }
                        }
                        return false;
                    }
                });
            });

            // Callsign always has focus on load
            $("#callsign").focus();

            if (!manual) {
                $(function($) {
                    resetTimers(0);
                });
            }
        });

        <?php if ($this->session->userdata('user_qso_end_times')  == 1) { ?>
            $('#callsign').focusout(function() {
                if (!manual && $('#callsign').val() != '') {
                    clearInterval(handleStart);
                    clearInterval(handleDate);
                }
            });
            $('#start_time').focusout(function() {
                if (manual && $('#start_time').val() != '') {
                    $('#end_time').val($('#start_time').val());
                }
            });
        <?php } ?>

        jQuery(function($) {
            var input = $('#callsign');
            input.on('keydown', function() {
                var key = event.keyCode || event.charCode;

                if (key == 8 || key == 46) {
                    reset_fields();
                }
            });

            $(document).keyup(function(e) {
                if (e.charCode === 0) {
                    let fixedcall = $('#callsign').val();
                    $('#callsign').val(fixedcall.replace('Ø', '0'));
                }
                if (e.key === "Escape") { // escape key maps to keycode `27`
                    const escHandledAt = Number(window.cloudlogQsoEscHandledAt || 0);
                    if (escHandledAt && (Date.now() - escHandledAt) < 500) {
                        return;
                    }
                    reset_fields();
                    if (!manual) {
                        resetTimers(0)
                    }
                    $('#callsign').val("");
                    $("#callsign").focus();
                    updateFromCAT();
                    if (document.querySelector('#radio').value != '0') {
                        updateFromCAT();
                    }
                }
            });
        });

        <?php if ($this->session->userdata('user_sota_lookup') == 1) { ?>
            $('#sota_ref').change(function() {
                var sota = $('#sota_ref').val();
                if (sota.length > 0) {
                    $.ajax({
                        url: base_url + 'index.php/qso/get_sota_info',
                        type: 'post',
                        data: {
                            'sota': sota
                        },
                        success: function(res) {
                            $('#qth').val(res.name);
                            $('#locator').val(res.locator);
                        },
                        error: function() {
                            $('#qth').val('');
                            $('#locator').val('');
                        },
                    });
                }
            });
        <?php } ?>

        <?php if ($this->session->userdata('user_wwff_lookup') == 1) { ?>
            $('#wwff_ref').change(function() {
                var wwff = $('#wwff_ref').val();
                if (wwff.length > 0) {
                    $.ajax({
                        url: base_url + 'index.php/qso/get_wwff_info',
                        type: 'post',
                        data: {
                            'wwff': wwff
                        },
                        success: function(res) {
                            $('#qth').val(res.name);
                            $('#locator').val(res.locator);
                        },
                        error: function() {
                            $('#qth').val('');
                            $('#locator').val('');
                        },
                    });
                }
            });
        <?php } ?>

        <?php if ($this->session->userdata('user_pota_lookup') == 1) { ?>
            $('#pota_ref').change(function() {
                var pota = ($('#pota_ref').val() || '').split(',')[0].trim();
                if (pota.length > 0) {
                    $.ajax({
                        url: base_url + 'index.php/qso/get_pota_info',
                        type: 'post',
                        data: {
                            'pota': pota
                        },
                        success: function(res) {
                            $('#qth').val(res.name);
                            $('#locator').val(res.grid6);
                        },
                        error: function() {
                            $('#qth').val('');
                            $('#locator').val('');
                        },
                    });
                }
            });
        <?php } ?>

        $('#stationProfile').change(function() {
            var stationProfile = $('#stationProfile').val();
            $.ajax({
                url: base_url + 'index.php/qso/get_station_power',
                type: 'post',
                data: {
                    'stationProfile': stationProfile
                },
                success: function(res) {
                    $('#transmit_power').val(res.station_power);
                },
                error: function() {
                    $('#transmit_power').val('');
                },
            });
            // [eQSL default msg] change value on change station profle //
            qso_set_eqsl_qslmsg(stationProfile, false, '.qso_panel');
        });
        // [eQSL default msg] change value on clic //
        $('.qso_panel .qso_eqsl_qslmsg_update').off('click').on('click', function() {
            qso_set_eqsl_qslmsg($('.qso_panel #stationProfile').val(), true, '.qso_panel');
            $('#charsLeft').text(" ");
        });

        <?php if ($this->session->userdata('user_qth_lookup') == 1) { ?>
            $('#qth').focusout(function() {
                if ($('#locator').val() === '') {
                    var lat = 0;
                    var lon = 0;
                    $.ajax({
                        async: false,
                        type: 'GET',
                        dataType: "json",
                        url: "https://nominatim.openstreetmap.org/?city=" + $(this).val() + "&format=json&addressdetails=1&limit=1",
                        data: {},
                        success: function(data) {
                            if (typeof data[0].lat !== 'undefined') {
                                lat = parseFloat(data[0].lat);
                            }
                            if (typeof data[0].lon !== 'undefined') {
                                lon = parseFloat(data[0].lon);
                            }
                        },
                    });
                    if (lat !== 0 && lon !== 0) {
                        var qthloc = LatLng2Loc(lat, lon, 10);
                        if (qthloc.length > 0) {
                            $('#locator').val(qthloc.substr(0, 6)).trigger('focusout');
                        }
                    }
                }
            });

            LatLng2Loc = function(y, x, num) {
                if (x < -180) {
                    x = x + 360;
                }
                if (x > 180) {
                    x = x - 360;
                }
                var yqth, yi, yk, ydiv, yres, ylp, y;
                var ycalc = new Array(0, 0, 0);
                var yn = new Array(0, 0, 0, 0, 0, 0, 0);

                var ydiv_arr = new Array(10, 1, 1 / 24, 1 / 240, 1 / 240 / 24);
                ycalc[0] = (x + 180) / 2;
                ycalc[1] = y + 90;

                for (yi = 0; yi < 2; yi++) {
                    for (yk = 0; yk < 5; yk++) {
                        ydiv = ydiv_arr[yk];
                        yres = ycalc[yi] / ydiv;
                        ycalc[yi] = yres;
                        if (ycalc[yi] > 0) ylp = Math.floor(yres);
                        else ylp = Math.ceil(yres);
                        ycalc[yi] = (ycalc[yi] - ylp) * ydiv;
                        yn[2 * yk + yi] = ylp;
                    }
                }

                var qthloc = "";
                if (num >= 2) qthloc += String.fromCharCode(yn[0] + 0x41) + String.fromCharCode(yn[1] + 0x41);
                if (num >= 4) qthloc += String.fromCharCode(yn[2] + 0x30) + String.fromCharCode(yn[3] + 0x30);
                if (num >= 6) qthloc += String.fromCharCode(yn[4] + 0x41) + String.fromCharCode(yn[5] + 0x41);
                if (num >= 8) qthloc += ' ' + String.fromCharCode(yn[6] + 0x30) + String.fromCharCode(yn[7] + 0x30);
                if (num >= 10) qthloc += String.fromCharCode(yn[8] + 0x61) + String.fromCharCode(yn[9] + 0x61);
                return qthloc;
            }
        <?php } ?>
    </script>

<?php } ?>
<?php if ($this->uri->segment(1) == "qso" || ($this->uri->segment(1) == "contesting" && $this->uri->segment(2) != "add")) { ?>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/moment.min.js"></script>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/datetime-moment.js"></script>
    <script>
        $('#notice-alerts').delay(1000).fadeOut(5000);

        function setRst(mode) {
            if (mode == 'JT65' || mode == 'JT65B' || mode == 'JT6C' || mode == 'JTMS' || mode == 'ISCAT' || mode == 'MSK144' || mode == 'JTMSK' || mode == 'QRA64' || mode == 'FT8' || mode == 'FT4' || mode == 'JS8' || mode == 'JT9' || mode == 'JT9-1' || mode == 'ROS' || mode == 'Q65' || mode == 'FST4' || mode == 'FST4W') {
                $('#rst_sent').val('-5');
                $('#rst_rcvd').val('-5');
            } else if (mode == 'FSK441' || mode == 'JT6M') {
                $('#rst_sent').val('26');
                $('#rst_rcvd').val('26');
            } else if (mode == 'CW' || mode == 'RTTY' || mode == 'PSK31' || mode == 'PSK63') {
                $('#rst_sent').val('599');
                $('#rst_rcvd').val('599');
            } else {
                $('#rst_sent').val('59');
                $('#rst_rcvd').val('59');
            }
        }

        function getUTCTimeStamp(el) {
            var now = new Date();
            var localTime = now.getTime();
            var utc = localTime + (now.getTimezoneOffset() * 60000);
            $(el).attr('value', ("0" + now.getUTCHours()).slice(-2) + ':' + ("0" + now.getUTCMinutes()).slice(-2) + ':' + ("0" + now.getUTCSeconds()).slice(-2));
        }

        function getUTCDateStamp(el) {
            var now = new Date();
            var localTime = now.getTime();
            var utc = localTime + (now.getTimezoneOffset() * 60000);
            
            // Get user's date format preference
            var userDateFormat = '<?php 
                if ($this->session->userdata('user_date_format')) {
                    echo $this->session->userdata('user_date_format');
                } else {
                    echo $this->config->item('qso_date_format');
                }
            ?>';
            
            // Format date according to user preference
            var day = ("0" + now.getUTCDate()).slice(-2);
            var month = ("0" + (now.getUTCMonth() + 1)).slice(-2);
            var year2 = now.getUTCFullYear().toString().slice(-2);
            var year4 = now.getUTCFullYear();
            
            var formattedDate;
            switch(userDateFormat) {
                case 'd/m/y':
                    formattedDate = day + '/' + month + '/' + year2;
                    break;
                case 'd/m/Y':
                    formattedDate = day + '/' + month + '/' + year4;
                    break;
                case 'm/d/y':
                    formattedDate = month + '/' + day + '/' + year2;
                    break;
                case 'm/d/Y':
                    formattedDate = month + '/' + day + '/' + year4;
                    break;
                case 'd.m.Y':
                    formattedDate = day + '.' + month + '.' + year4;
                    break;
                case 'y/m/d':
                    formattedDate = year2 + '/' + month + '/' + day;
                    break;
                case 'Y-m-d':
                    formattedDate = year4 + '-' + month + '-' + day;
                    break;
                case 'M d, Y':
                    var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
                    formattedDate = months[now.getUTCMonth()] + ' ' + now.getUTCDate() + ', ' + year4;
                    break;
                case 'M d, y':
                    var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
                    formattedDate = months[now.getUTCMonth()] + ' ' + now.getUTCDate() + ', ' + year2;
                    break;
                default:
                    // Fallback to original format if no match
                    formattedDate = day + '-' + month + '-' + year4;
            }
            
            $(el).attr('value', formattedDate);
        }
    </script>

    <script>
        let catRequestCounter = 0;
        let lastProcessedCatRequest = 0;
        let catSelectionContextVersion = 0;
        let consecutiveCatPollFailures = 0;
        let catPollTimer = null;
        let lastSuccessfulCatUpdateAt = null;
        let lockSatelliteFieldsToUserInput = false;

        window.cloudlogLastCatData = null;
        window.cloudlogLastCatRadioId = null;

        const CAT_POLL_BASE_INTERVAL_MS = 3000;
        const CAT_POLL_MAX_INTERVAL_MS = 15000;
        const CAT_POLL_WARNING_THRESHOLD = 3;

        // Helper function to update a UI element with CAT data
        const cat2UI = (ui, cat, allowEmpty = true, allowZero = true, callbackOnUpdate) => {
            if (
                cat == null ||
                (!allowEmpty && cat === '') ||
                (!allowZero && cat === '0')
            ) return;

            if (ui.data('catValue') != cat) {
                ui.val(cat).data('catValue', cat);
                if (typeof callbackOnUpdate === 'function') callbackOnUpdate(cat);
            }
        };

        // Update UI from CAT data
        const updateFromCAT = (radioID) => {
            if (!radioID || radioID === '0' || radioID === 'undefined') return;

            const requestedRadioID = String(radioID);
            const requestId = ++catRequestCounter;
            const requestContextVersion = catSelectionContextVersion;

            $.ajax({
                url: `radio/json/${requestedRadioID}`,
                dataType: 'json',
                cache: false,
                success: (data) => {
                    const currentSelectedRadioID = String($('select.radios option:selected').val() || '0');

                    // Ignore stale CAT responses when radio selection changed or newer requests have already been applied.
                    if (
                        requestContextVersion !== catSelectionContextVersion ||
                        currentSelectedRadioID !== requestedRadioID ||
                        requestId < lastProcessedCatRequest
                    ) {
                        return;
                    }

                    lastProcessedCatRequest = requestId;

                    if (data.error) {
                        if (data.error === 'not_logged_in') {
                            handleLoginError();
                        }
                        handleCATPollFailure(requestedRadioID);
                        return;
                    }

                    clearLoginError();
                    handleCATPollSuccess();
                    window.cloudlogLastCatData = data || null;
                    window.cloudlogLastCatRadioId = requestedRadioID;
                    updateUIWithCATData(data);
                },
                error: () => {
                    handleCATPollFailure(requestedRadioID);
                }
            });
        };

        const getNextCATPollDelay = () => {
            if (consecutiveCatPollFailures <= 0) {
                return CAT_POLL_BASE_INTERVAL_MS;
            }

            return Math.min(
                CAT_POLL_MAX_INTERVAL_MS,
                CAT_POLL_BASE_INTERVAL_MS * Math.pow(2, consecutiveCatPollFailures - 1)
            );
        };

        const clearCATPollWarning = () => {
            $('.radio_poll_warning').remove();
        };

        const showCATPollWarning = () => {
            const secondsSinceSuccess = lastSuccessfulCatUpdateAt === null
                ? null
                : Math.max(0, Math.floor((Date.now() - lastSuccessfulCatUpdateAt) / 1000));

            let warningText = 'Live rig sync is temporarily unstable. Retrying automatically.';
            if (secondsSinceSuccess !== null) {
                warningText += ` Last successful update was ${secondsSinceSuccess} seconds ago.`;
            }

            if ($('.radio_poll_warning').length === 0) {
                $('#radio_status').prepend(
                    `<div class="alert alert-warning radio_poll_warning" role="alert"><i class="fas fa-exclamation-triangle"></i> ${warningText}</div>`
                );
            } else {
                $('.radio_poll_warning').html(`<i class="fas fa-exclamation-triangle"></i> ${warningText}`);
            }
        };

        const handleCATPollSuccess = () => {
            consecutiveCatPollFailures = 0;
            lastSuccessfulCatUpdateAt = Date.now();
            clearCATPollWarning();
            scheduleNextCATPoll(CAT_POLL_BASE_INTERVAL_MS);
        };

        const handleCATPollFailure = (radioID) => {
            const currentSelectedRadioID = String($('select.radios option:selected').val() || '0');
            if (!radioID || currentSelectedRadioID !== String(radioID)) {
                return;
            }

            consecutiveCatPollFailures += 1;

            if (consecutiveCatPollFailures >= CAT_POLL_WARNING_THRESHOLD) {
                showCATPollWarning();
            }

            scheduleNextCATPoll(getNextCATPollDelay());
        };

        const scheduleNextCATPoll = (delayMs) => {
            if (catPollTimer !== null) {
                clearTimeout(catPollTimer);
            }

            catPollTimer = setTimeout(() => {
                pollSelectedRadio();
            }, delayMs);
        };

        const pollSelectedRadio = () => {
            const selectedRadioID = String($('select.radios option:selected').val() || '0');
            if (selectedRadioID !== '0') {
                updateFromCAT(selectedRadioID);
                return;
            }

            consecutiveCatPollFailures = 0;
            clearCATPollWarning();
            scheduleNextCATPoll(CAT_POLL_BASE_INTERVAL_MS);
        };

        // Handle login error display
        const handleLoginError = () => {
            $(".radio_cat_state").remove();
            if ($('.radio_login_error').length === 0) {
                $('.qso_panel').prepend(
                    '<div class="alert alert-danger radio_login_error" role="alert">' +
                    '<i class="fas fa-broadcast-tower"></i> You\'re not logged in. ' +
                    'Please <a href="<?php echo base_url(); ?>">login</a></div>'
                );
            }
        };

        // Clear login error
        const clearLoginError = () => {
            $(".radio_login_error").remove();
        };

        // Update UI elements with CAT data
        const updateUIWithCATData = (data) => {
            cat2UI($('#frequency'), data.frequency, false, true, (d) => {
                $("#band").val(frequencyToBand(d));
            });
            cat2UI($('#frequency_rx'), data.frequency_rx, false, true, (d) => {
                $("#band_rx").val(frequencyToBand(d));
            });
            cat2UI($('.mode'), data.mode, false, false, () => {
                setRst($(".mode").val());
                // If the data.mode is winkey show the div with id winkey if not hide it
                if (data.mode === 'CW') {
                    $('#winkey').show();
                } else {
                    $('#winkey').hide();
                }
            });
            if (!lockSatelliteFieldsToUserInput) {
                const satNameFromCat = String(data.satname || '').trim();
                const satModeFromCat = String(data.satmode || '').trim();
                const propModeFromCat = String(data.prop_mode || '').trim();

                // If CAT does not provide satellite fields for this radio, clear stale values
                // so we do not carry over sat details from a previous save or radio.
                if (satNameFromCat === '') {
                    $('#sat_name').val('').removeData('catValue');
                } else {
                    cat2UI($('#sat_name'), satNameFromCat, false, false);
                }

                if (satModeFromCat === '') {
                    $('#sat_mode').val('').removeData('catValue');
                } else {
                    cat2UI($('#sat_mode'), satModeFromCat, false, false);
                }

                if (propModeFromCat === '') {
                    $('#selectPropagation').val('').removeData('catValue');
                } else {
                    cat2UI($('#selectPropagation'), propModeFromCat, false, false);
                }
            }
            cat2UI($('#transmit_power'), data.power, false, false);

            handleCATTimeout(data);
        };

        // Handle CAT timeout
        const handleCATTimeout = (data) => {
            const minutes = Math.floor(<?php echo $this->optionslib->get_option('cat_timeout_interval'); ?> / 60);

            if (data.updated_minutes_ago > minutes) {
                $(".radio_cat_state").remove();
                const errorText = `Radio connection timed-out: ${$('select.radios option:selected').text()} data is ${data.updated_minutes_ago} minutes old.`;
                if ($('.radio_timeout_error').length === 0) {
                    $('#radio_status').prepend(
                        `<div class="alert alert-danger radio_timeout_error" role="alert"><i class="fas fa-broadcast-tower"></i> ${errorText}</div>`
                    );
                } else {
                    $('.radio_timeout_error').html(errorText);
                }
            } else {
                $(".radio_timeout_error").remove();
                updateCATStatusDisplay(data);
            }
        };

        // Update the status display
        const updateCATStatusDisplay = (data) => {
            let text = `<i class="fas fa-broadcast-tower"></i><span style="margin-left:10px;"></span><b>TX:</b> ${(Math.round(parseInt(data.frequency) / 100) / 10000).toFixed(4)} MHz`;
            if (data.mode) text += `<span style="margin-left:10px"></span>${data.mode}`;
            if (data.power && data.power !== 0) text += `<span style="margin-left:10px"></span>${data.power} W`;

            let ptext = '';
            if (data.prop_mode) {
                ptext = data.prop_mode;
                if (data.prop_mode === 'SAT') ptext += ` ${data.satname}`;
            }
            if (data.frequency_rx && data.frequency_rx !== 0) {
                ptext += `<span style="margin-left:10px"></span><b>RX:</b> ${(Math.round(parseInt(data.frequency_rx) / 1000) / 1000).toFixed(3)} MHz`;
            }
            if (ptext) text += `<span style="margin-left:10px"></span>(${ptext})`;

            if (!$('#radio_cat_state').length) {
                $('#radio_status').prepend(
                    `<div aria-hidden="true"><div id="radio_cat_state" class="alert alert-success radio_cat_state" role="alert">${text}</div></div>`
                );
            } else {
                $('#radio_cat_state').html(text);
            }
        };

        // Reset UI when no radio is selected
        const resetUI = () => {
            lockSatelliteFieldsToUserInput = false;
            window.cloudlogLastCatData = null;
            window.cloudlogLastCatRadioId = null;
            $("#sat_name, #sat_mode, #frequency, #frequency_rx, #band_rx").val("");
            $("#selectPropagation").val($("#selectPropagation option:first").val());
            // Clear CAT value cache so re-selecting a radio with identical values still repopulates fields.
            $('#frequency, #frequency_rx, #sat_name, #sat_mode, #transmit_power, #selectPropagation, #mode').removeData('catValue');
            $(".radio_timeout_error").remove();
            clearCATPollWarning();
        };

        // Event listeners
        $(document).ready(() => {

            /**
             * Prevents multiple form submissions by tracking submission state
             * 
             * This script prevents duplicate QSO (contact) submissions by:
             * - Maintaining an isSubmitting flag to track form submission state
             * - Adding an event listener to the 'qso_input' form
             * - Preventing form submission if a submission is already in progress
             * - Setting the flag to true when a valid submission begins
             * 
             * @since Unknown
             * @global boolean isSubmitting Flag to track if form is currently being submitted
             */
            let isSubmitting = false;
            document.getElementById('qso_input').addEventListener('submit', function(e) {
                if (isSubmitting) {
                    e.preventDefault();
                    return false;
                }
                isSubmitting = true;
            });

            scheduleNextCATPoll(CAT_POLL_BASE_INTERVAL_MS);

            $('#sat_name, #sat_mode, #selectPropagation').on('input change', function() {
                const satName = String($('#sat_name').val() || '').trim();
                const satMode = String($('#sat_mode').val() || '').trim();
                const propMode = String($('#selectPropagation').val() || '').trim().toUpperCase();
                lockSatelliteFieldsToUserInput = satName !== '' || satMode !== '' || propMode === 'SAT';
            });

            // Trigger updateFromCAT when any <select> with class 'radios' changes
            $('.radios').on('change', function() {
                catSelectionContextVersion++;
                consecutiveCatPollFailures = 0;
                clearCATPollWarning();
                lockSatelliteFieldsToUserInput = false;
                const selectedRadioID = $(this).val();
                if (selectedRadioID === '0') {
                    resetUI();
                    scheduleNextCATPoll(CAT_POLL_BASE_INTERVAL_MS);
                } else {
                    updateFromCAT(selectedRadioID);
                }
            });
        });
    </script>

    <script>
        $(document).ready(function() {
            // Load saved radio selection from localStorage
            var savedRadio = localStorage.getItem("selectedRadio");
            if (savedRadio !== null && savedRadio !== undefined) {
                $('.radios').val(savedRadio);
            }

            // Synchronize the two selects and save to localStorage
            $('.radios').on('change', function() {
                const selectedValue = $(this).val(); // Get the selected value
                $('.radios').not(this).val(selectedValue); // Update other selects to match
                localStorage.setItem("selectedRadio", selectedValue); // Save to localStorage
            });
        });
    </script>



<?php } ?>

<?php if ($this->uri->segment(1) == "logbook" && $this->uri->segment(2) == "view") { ?>
    <script>
        var mymap = L.map('map').setView([lat, long], 5);

        L.tileLayer('<?php echo $this->optionslib->get_option('option_map_tile_server'); ?>', {
            maxZoom: 18,
            attribution: '<?php echo $this->optionslib->get_option('option_map_tile_server_copyright'); ?>',
            id: 'mapbox.streets'
        }).addTo(mymap);



        var printer = L.easyPrint({
            tileLayer: tiles,
            sizeModes: ['Current', 'A4Landscape', 'A4Portrait'],
            filename: 'myMap',
            exportOnly: true,
            hideControlContainer: true
        }).addTo(mymap);

        var redIcon = L.icon({
            iconUrl: icon_dot_url,
            iconSize: [18, 18], // size of the icon
        });

        L.marker([lat, long], {
                icon: redIcon
            }).addTo(mymap)
            .bindPopup(callsign);

        mymap.on('click', onMapClick);
    </script>
<?php } ?>

<?php if ($this->uri->segment(1) == "update") { ?>
    <script>
        $(document).ready(function() {
            $('#btn_update_dxcc').bind('click', function() {
                // Show spinner and disable button
                $('#dxcc_spinner').show();
                $('#btn_text').text('Updating...');
                $('#btn_update_dxcc').prop('disabled', true);
                
                // Show initial status immediately
                $('#dxcc_update_status').show().html('Starting update...<br/>');
                
                $.ajax({
                    url: "update/dxcc"
                });
                
                // Start polling immediately, then every 2 seconds for more responsive updates
                setTimeout(update_stats, 1000);
            });

            function update_stats() {
                console.log('Polling status at: ' + new Date().toLocaleTimeString());
                
                $.get('<?php echo base_url() ?>index.php/update/get_status')
                    .done(function(response) {
                        console.log('Status response:', response);
                        
                        // Always update the status display with the response
                        if (response && response.trim() !== '') {
                            $('#dxcc_update_status').html(response);
                        }
                        
                        // Check if update is complete
                        if (response && typeof response === 'string' && response.substring(0, 4) === "DONE") {
                            console.log('Update completed!');
                            // Update is done - hide spinner and re-enable button
                            $('#dxcc_spinner').hide();
                            $('#btn_text').text('Update DXCC Data');
                            $('#btn_update_dxcc').prop('disabled', false);
                        } else {
                            // Continue polling if not done - reduced interval for better responsiveness
                            setTimeout(update_stats, 2000);
                        }
                    })
                    .fail(function(xhr, status, error) {
                        console.log('Error loading status: ' + status + ' - ' + error);
                        $('#dxcc_update_status').html('Error loading status... Retrying...<br/>');
                        
                        // Reset button state on persistent error
                        if (xhr.status === 0 || xhr.status >= 500) {
                            $('#dxcc_spinner').hide();
                            $('#btn_text').text('Update DXCC Data');
                            $('#btn_update_dxcc').prop('disabled', false);
                        }
                        
                        setTimeout(update_stats, 5000); // Retry in 5 seconds on error
                    });

            }

        });
    </script>

<?php } ?>

<?php if ($this->uri->segment(1) == "awards" && $this->uri->segment(2) == "wab") { ?>
    <!-- WAB map handled by assets/js/sections/wab.js -->
<?php } ?>

<?php if ($this->uri->segment(1) == "gridsquares" && !empty($this->uri->segment(2))) { ?>
    <script>
        var gridsquaremap = true;
    </script>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/leaflet/L.MaidenheadColoured.js"></script>

    <script>
        var layer = L.tileLayer('<?php echo $this->optionslib->get_option('option_map_tile_server'); ?>', {
            maxZoom: 18,
            attribution: '<?php echo $this->optionslib->get_option('option_map_tile_server_copyright'); ?>',
            id: 'mapbox.streets'
        });

        var map = L.map('gridsquare_map', {
            layers: [layer],
            center: [19, 0],
            zoom: 2,
            minZoom: 1,
            fullscreenControl: true,
            fullscreenControlOptions: {
                position: 'topleft'
            },
        });

        var printer = L.easyPrint({
            tileLayer: layer,
            sizeModes: ['Current'],
            filename: 'myMap',
            exportOnly: true,
            hideControlContainer: true
        }).addTo(map);

        var grid_two = <?php echo $grid_2char; ?>;
        var grid_four = <?php echo $grid_4char; ?>;
        var grid_six = <?php echo $grid_6char; ?>;

        var grid_two_count = grid_two.length;
        var grid_four_count = grid_four.length;
        var grid_six_count = grid_six.length;

        var grid_two_confirmed = <?php echo $grid_2char_confirmed; ?>;
        var grid_four_confirmed = <?php echo $grid_4char_confirmed; ?>;
        var grid_six_confirmed = <?php echo $grid_6char_confirmed; ?>;

        var grid_two_confirmed_count = grid_two_confirmed.length;
        var grid_four_confirmed_count = grid_four_confirmed.length;
        var grid_six_confirmed_count = grid_six_confirmed.length;

        if (grid_four_confirmed_count > 0) {
            var span = document.getElementById('confirmed_grids');
            span.innerText = span.textContent = '(' + grid_four_confirmed_count + ' <?php echo lang('gridsquares_grid_squares'); ?>' + (grid_four_confirmed_count != 1 ? 's' : '') + ') ';
        }
        if ((grid_four_count - grid_four_confirmed_count) > 0) {
            var span = document.getElementById('worked_grids');
            span.innerText = span.textContent = '(' + (grid_four_count - grid_four_confirmed_count) + ' <?php echo lang('gridsquares_grid_squares'); ?>' + (grid_four_count - grid_four_confirmed_count != 1 ? 's' : '') + ') ';
        }
        var span = document.getElementById('sum_grids');
        span.innerText = span.textContent = ' <?php echo lang('gridsquares_total_count'); ?>' + ': ' + grid_four_count + ' <?php echo lang('gridsquares_grid_squares'); ?>' + (grid_four_count != 1 ? 's' : '');

        var maidenhead = L.maidenhead().addTo(map);

        map.on('click', onMapClick);

        function onMapClick(event) {
            var LatLng = event.latlng;
            var lat = LatLng.lat;
            var lng = LatLng.lng;
            var locator = LatLng2Loc(lat, lng, 10);
            var loc_4char = locator.substring(0, 4);

            if (map.getZoom() > 2) {
                <?php if ($this->session->userdata('user_callsign')) { ?>
                    spawnGridsquareModal(loc_4char);
                <?php } ?>
            }
        };

        function spawnGridsquareModal(loc_4char) {
            var band = '';
            var search_type = "<?php echo $this->uri->segment(2); ?>";
            if (search_type == "satellites") {
                band = 'SAT';
            } else {
                band = "<?php echo $this->uri->segment(3); ?>";
            }
            $(".modal-body").empty();
            $.ajax({
                url: base_url + 'index.php/awards/qso_details_ajax',
                type: 'post',
                data: {
                    'Searchphrase': loc_4char,
                    'Band': band,
                    'Mode': 'All',
                    'Type': 'VUCC'
                },
                success: function(html) {
                    $(".modal-body").html(html);
                    $(".modal-body table").addClass('table-sm');
                    $(".modal-body h5").empty();
                    var count = $('.table tr').length;
                    count = count - 1;
                    $('#qso_count').text(count);
                    if (count > 1) {
                        $('#gt1_qso').text("s");
                    } else {
                        $('#gt1_qso').text("");
                    }

                    if (count > 0) {
                        $('#square_number').text(loc_4char);
                        $('#exampleModal').modal('show');
                        $('[data-bs-toggle="tooltip"]').tooltip({
                            boundary: 'window'
                        });
                    }
                    $('.table-responsive .dropdown-toggle').off('mouseenter').on('mouseenter', function() {
                        showQsoActionsMenu($(this).closest('.dropdown'));
                    });
                }
            });
        }

        <?php if ($this->uri->segment(1) == "gridsquares" && $this->uri->segment(2) == "band") { ?>

            var bands_available = <?php echo $bands_available; ?>;
            $('#gridsquare_bands').append('<option value="All">All</option>')
            $.each(bands_available, function(key, value) {
                $('#gridsquare_bands')
                    .append($("<option></option>")
                        .attr("value", value)
                        .text(value));
            });

            var num = "<?php echo $this->uri->segment(3); ?>";
            $("#gridsquare_bands option").each(function() {
                if ($(this).val() == num) { // EDITED THIS LINE
                    $(this).attr("selected", "selected");
                }
            });

            $(function() {
                // bind change event to select
                $('#gridsquare_bands').on('change', function() {
                    var url = $(this).val(); // get selected value
                    if (url) { // require a URL
                        window.location = "<?php echo site_url('gridsquares/band/'); ?>" + url
                    }
                    return false;
                });
            });
        <?php } ?>
    </script>
<?php } ?>

<?php if ($this->uri->segment(1) == "activated_grids" && !empty($this->uri->segment(2))) { ?>

    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/leaflet/L.MaidenheadColoured.js"></script>

    <script>
        var layer = L.tileLayer('<?php echo $this->optionslib->get_option('option_map_tile_server'); ?>', {
            maxZoom: 18,
            attribution: '<?php echo $this->optionslib->get_option('option_map_tile_server_copyright'); ?>',
            id: 'mapbox.streets'
        });


        var map = L.map('gridsquare_map', {
            layers: [layer],
            center: [19, 0],
            zoom: 2,
            minZoom: 1,
            fullscreenControl: true,
            fullscreenControlOptions: {
                position: 'topleft'
            },
        });

        var grid_two = <?php echo $grid_2char; ?>;
        var grid_four = <?php echo $grid_4char; ?>;
        var grid_six = <?php echo $grid_6char; ?>;

        var grid_two_count = grid_two.length;
        var grid_four_count = grid_four.length;
        var grid_six_count = grid_six.length;

        var grid_two_confirmed = <?php echo $grid_2char_confirmed; ?>;
        var grid_four_confirmed = <?php echo $grid_4char_confirmed; ?>;
        var grid_six_confirmed = <?php echo $grid_6char_confirmed; ?>;

        var grid_two_confirmed_count = grid_two_confirmed.length;
        var grid_four_confirmed_count = grid_four_confirmed.length;
        var grid_six_confirmed_count = grid_six_confirmed.length;

        if (grid_four_confirmed_count > 0) {
            var span = document.getElementById('confirmed_grids');
            span.innerText = span.textContent = '(' + grid_four_confirmed_count + ' <?php echo lang('gridsquares_grid_squares'); ?>' + (grid_four_confirmed_count != 1 ? 's' : '') + ') ';
        }
        if ((grid_four_count - grid_four_confirmed_count) > 0) {
            var span = document.getElementById('activated_grids');
            span.innerText = span.textContent = '(' + (grid_four_count - grid_four_confirmed_count) + ' <?php echo lang('gridsquares_grid_squares'); ?>' + (grid_four_count - grid_four_confirmed_count != 1 ? 's' : '') + ') ';
        }
        var span = document.getElementById('sum_grids');
        span.innerText = span.textContent = ' <?php echo lang('gridsquares_total_count'); ?>' + ': ' + grid_four_count + ' <?php echo lang('gridsquares_grid_squares'); ?>' + (grid_four_count != 1 ? 's' : '');

        var maidenhead = L.maidenhead().addTo(map);

        map.on('click', onMapClick);

        function onMapClick(event) {
            var LatLng = event.latlng;
            var lat = LatLng.lat;
            var lng = LatLng.lng;
            var locator = LatLng2Loc(lat, lng, 10);
            var loc_4char = locator.substring(0, 4);

            if (map.getZoom() > 2) {
                <?php if ($this->session->userdata('user_callsign')) { ?>
                    var band = '';
                    var search_type = "<?php echo $this->uri->segment(2); ?>";
                    if (search_type == "satellites") {
                        band = 'SAT';
                    } else {
                        band = "<?php echo $this->uri->segment(3); ?>";
                    }
                    $(".modal-body").empty();
                    $.ajax({
                        url: base_url + 'index.php/activated_grids/qso_details_ajax',
                        type: 'post',
                        data: {
                            'Searchphrase': loc_4char,
                            'Band': band,
                            'Mode': 'All',
                        },
                        success: function(html) {
                            $(".modal-body").html(html);
                            $(".modal-body table").addClass('table-sm');
                            $(".modal-body h5").empty();
                            var count = $('.table tr').length;
                            count = count - 1;
                            $('#qso_count').text(count);
                            if (count > 1) {
                                $('#gt1_qso').text("s");
                            } else {
                                $('#gt1_qso').text("");
                            }

                            if (count > 0) {
                                $('#square_number').text(loc_4char);
                                $('#exampleModal').modal('show');
                                $('[data-bs-toggle="tooltip"]').tooltip({
                                    boundary: 'window'
                                });
                            }
                            $('.table-responsive .dropdown-toggle').off('mouseenter').on('mouseenter', function() {
                                showQsoActionsMenu($(this).closest('.dropdown'));
                            });
                        }
                    });
                <?php } ?>
            }
        };

        <?php if ($this->uri->segment(1) == "activated_grids" && $this->uri->segment(2) == "band") { ?>

            var bands_available = <?php echo $bands_available; ?>;
            $('#gridsquare_bands').append('<option value="All">All</option>')
            $.each(bands_available, function(key, value) {
                $('#gridsquare_bands')
                    .append($("<option></option>")
                        .attr("value", value)
                        .text(value));
            });

            var num = "<?php echo $this->uri->segment(3); ?>";
            $("#gridsquare_bands option").each(function() {
                if ($(this).val() == num) { // EDITED THIS LINE
                    $(this).attr("selected", "selected");
                }
            });

            $(function() {
                // bind change event to select
                $('#gridsquare_bands').on('change', function() {
                    var url = $(this).val(); // get selected value
                    if (url) { // require a URL
                        window.location = "<?php echo site_url('activated_grids/band/'); ?>" + url
                    }
                    return false;
                });
            });
        <?php } ?>
    </script>
<?php } ?>

<?php if ($this->uri->segment(1) == "dayswithqso") { ?>
    <script src="<?php echo base_url(); ?>assets/js/chart.js"></script>
    <script src="<?php echo base_url(); ?>assets/js/sections/dayswithqso.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "distances") { ?>
    <script src="<?php echo base_url(); ?>assets/js/highstock.js"></script>
    <script src="<?php echo base_url(); ?>assets/js/highstock/exporting.js"></script>
    <script src="<?php echo base_url(); ?>assets/js/highstock/offline-exporting.js"></script>
    <script src="<?php echo base_url(); ?>assets/js/highstock/export-data.js"></script>
    <script src="<?php echo base_url(); ?>assets/js/sections/distances.js"></script>
<?php } ?>


<?php if ($this->uri->segment(1) == "hrdlog") { ?>
    <script src="<?php echo base_url(); ?>assets/js/sections/hrdlog.js"></script>
<?php } ?>
<?php if ($this->uri->segment(1) == "qrz") { ?>
    <script src="<?php echo base_url(); ?>assets/js/sections/qrzlogbook.js"></script>
<?php } ?>
<?php if ($this->uri->segment(1) == "webadif") { ?>
    <script src="<?php echo base_url(); ?>assets/js/sections/webadif.js"></script>
<?php } ?>

<script>
    function displayQso(id) {
        var baseURL = "<?php echo base_url(); ?>";
        $.ajax({
            url: baseURL + 'index.php/logbook/view/' + id,
            type: 'post',
            success: function(html) {
                BootstrapDialog.show({
                    title: lang_general_word_qso_data,
                    cssClass: 'qso-dialog',
                    size: BootstrapDialog.SIZE_WIDE,
                    nl2br: false,
                    message: html,
                    onshown: function(dialog) {
                        var qsoid = $("#qsoid").text();
                        $(".editButton").html('<a class="btn btn-primary" id="edit_qso" href="javascript:qso_edit(' + qsoid + ')"><i class="fas fa-edit"></i><?php echo lang('general_edit_qso'); ?></a>');
                        var lat = $("#lat").text();
                        var long = $("#long").text();
                        var callsign = $("#callsign").text();
                        var mymap = L.map('mapqso').setView([lat, long], 5);

                        var tiles = L.tileLayer('<?php echo $this->optionslib->get_option('option_map_tile_server'); ?>', {
                            maxZoom: 18,
                            attribution: '<?php echo $this->optionslib->get_option('option_map_tile_server_copyright'); ?>',
                        }).addTo(mymap);


                        var printer = L.easyPrint({
                            tileLayer: tiles,
                            sizeModes: ['Current'],
                            filename: 'myMap',
                            exportOnly: true,
                            hideControlContainer: true
                        }).addTo(mymap);

                        var redIcon = L.icon({
                            iconUrl: icon_dot_url,
                            iconSize: [18, 18], // size of the icon
                        });

                        L.marker([lat, long], {
                                icon: redIcon
                            }).addTo(mymap)
                            .bindPopup(callsign);

                    },
                });

            }
        });
    }
</script>


<?php if ($this->uri->segment(2) == "dxcc") { ?>
    <script>
        $('.tabledxcc').DataTable({
            "pageLength": 25,
            responsive: false,
            ordering: false,
            "scrollY": "400px",
            "scrollCollapse": true,
            "paging": false,
            "scrollX": true,
            "language": {
                url: getDataTablesLanguageUrl(),
            },
            dom: 'Bfrtip',
            buttons: [
                'csv'
            ]
        });

        $('.tablesummary').DataTable({
            info: false,
            searching: false,
            ordering: false,
            "paging": false,
            "language": {
                url: getDataTablesLanguageUrl(),
            },
            dom: 'Bfrtip',
            buttons: [
                'csv'
            ]
        });

        // change color of csv-button if dark mode is chosen
        if (isDarkModeTheme()) {
            $(".buttons-csv").css("color", "white");
        }
    </script>
<?php } ?>

<?php if ($this->uri->segment(2) == "waja") { ?>
    <script>
        $('.tablewaja').DataTable({
            "pageLength": 25,
            responsive: false,
            ordering: false,
            "scrollY": "400px",
            "scrollCollapse": true,
            "paging": false,
            "scrollX": true,
            "language": {
                url: getDataTablesLanguageUrl(),
            },
            dom: 'Bfrtip',
            buttons: [
                'csv'
            ]
        });

        $('.tablesummary').DataTable({
            info: false,
            searching: false,
            ordering: false,
            "paging": false,
            "language": {
                url: getDataTablesLanguageUrl(),
            },
            dom: 'Bfrtip',
            buttons: [
                'csv'
            ]
        });

        // change color of csv-button if dark mode is chosen
        if (isDarkModeTheme()) {
            $(".buttons-csv").css("color", "white");
        }
    </script>
<?php } ?>

<?php if ($this->uri->segment(2) == "vucc_band") { ?>
    <script>
        $('.tablevucc').DataTable({
            "pageLength": 25,
            responsive: false,
            ordering: false,
            "scrollY": "400px",
            "scrollCollapse": true,
            "paging": false,
            "scrollX": true,
            "language": {
                url: getDataTablesLanguageUrl(),
            },
            dom: 'Bfrtip',
            buttons: [
                'csv'
            ]
        });

        // change color of csv-button if dark mode is chosen
        if (isDarkModeTheme()) {
            $(".buttons-csv").css("color", "white");
        }
    </script>
<?php } ?>

<?php if ($this->uri->segment(2) == "iota") { ?>
    <script>
        $('.tableiota').DataTable({
            "pageLength": 25,
            responsive: false,
            ordering: false,
            "scrollY": "400px",
            "scrollCollapse": true,
            "paging": false,
            "scrollX": true,
            "language": {
                url: getDataTablesLanguageUrl(),
            },
            dom: 'Bfrtip',
            buttons: [
                'csv'
            ]
        });

        $('.tablesummary').DataTable({
            info: false,
            searching: false,
            ordering: false,
            "paging": false,
            "language": {
                url: getDataTablesLanguageUrl(),
            },
            dom: 'Bfrtip',
            buttons: [
                'csv'
            ]
        });

        // change color of csv-button if dark mode is chosen
        if (isDarkModeTheme()) {
            $(".buttons-csv").css("color", "white");
        }
    </script>

<?php } ?>

<?php if ($this->uri->segment(2) == "cq") { ?>
    <script>
        // Initialize DataTable for summary
        $('.tablesummary').DataTable({
            info: false,
            searching: false,
            ordering: false,
            "paging": false,
            "language": {
                url: getDataTablesLanguageUrl(),
            },
            dom: 'Bfrtip',
            buttons: [
                'csv'
            ]
        });

        // Helper function to update statistics cards based on visible rows
        function updateCqStatistics() {
            const table = document.getElementById('cq_table');
            const rows = table.querySelectorAll('tbody tr');
            
            let workedCount = 0;
            let confirmedCount = 0;
            
            rows.forEach((row, rowIndex) => {
                // Check if row is actually visible (not display:none)
                const isVisible = row.offsetParent !== null || row.style.display === '';
                if (isVisible || row.style.display !== 'none') {
                    const cells = row.querySelectorAll('td');
                    
                    if (cells.length > 1) {  // At least zone + one band
                        // Check all band columns (starting from column 1, after zone)
                        let hasWorked = false;
                        let hasConfirmed = false;
                        
                        for (let i = 1; i < cells.length; i++) {
                            const cellValue = cells[i].textContent.trim();
                            // If cell is not empty and not a dash, it's worked
                            if (cellValue && cellValue !== '-') {
                                hasWorked = true;
                                // If it contains 'C', it's confirmed
                                if (cellValue.toUpperCase().includes('C')) {
                                    hasConfirmed = true;
                                }
                            }
                        }
                        
                        if (hasWorked) workedCount++;
                        if (hasConfirmed) confirmedCount++;
                    }
                }
            });
            
            // Update the stats cards
            const statsCards = document.querySelectorAll('.stats-card');
            statsCards.forEach(card => {
                const labels = card.querySelectorAll('.progress-label');
                labels.forEach(label => {
                    const parent = label.parentElement;
                    if (label.textContent.includes('Total Worked')) {
                        const numberDiv = parent.querySelector('.stats-number');
                        if (numberDiv) {
                            numberDiv.textContent = workedCount;
                        }
                    } else if (label.textContent.includes('Total Confirmed')) {
                        const numberDiv = parent.querySelector('.stats-number');
                        if (numberDiv) {
                            numberDiv.textContent = confirmedCount;
                        }
                    }
                });
            });
            
            // Update milestone indicators
            const milestoneCard = document.querySelector('.stats-card.milestone');
            if (milestoneCard) {
                const cols = milestoneCard.querySelectorAll('.col-6');
                cols.forEach(col => {
                    const label = col.querySelector('div:first-child');
                    const indicator = col.querySelector('div:nth-child(2)');
                    
                    if (label && indicator) {
                        if (label.textContent.includes('All Worked')) {
                            indicator.textContent = workedCount === 40 ? '✓' : '✗';
                            indicator.style.color = workedCount === 40 ? '#28a745' : '#dc3545';
                        } else if (label.textContent.includes('All Confirmed')) {
                            indicator.textContent = confirmedCount === 40 ? '✓' : '✗';
                            indicator.style.color = confirmedCount === 40 ? '#28a745' : '#dc3545';
                        }
                    }
                });
            }
        }

        // Call on page load to initialize with filtered data
        document.addEventListener('DOMContentLoaded', function() {
            setTimeout(function() {
                updateCqStatistics();
            }, 500);
        });

        // Table search functionality
        const searchInput = document.getElementById('searchInput');
        if (searchInput) {
            searchInput.addEventListener('keyup', function() {
                const searchTerm = this.value.toLowerCase();
                const table = document.getElementById('cq_table');
                const rows = table.querySelectorAll('tbody tr');

                rows.forEach(row => {
                    const cqZone = row.querySelectorAll('td')[0].textContent.toLowerCase();
                    
                    if (cqZone.includes(searchTerm)) {
                        row.style.display = '';
                    } else {
                        row.style.display = 'none';
                    }
                });
                
                updateCqStatistics();
            });
        }

        // Sortable column functionality
        document.querySelectorAll('.sortable').forEach(header => {
            header.addEventListener('click', function() {
                const table = document.getElementById('cq_table');
                const column = parseInt(this.dataset.column);
                const tbody = table.querySelector('tbody');
                const rows = Array.from(tbody.querySelectorAll('tr'));
                
                // Toggle sort direction
                const isAsc = this.classList.contains('asc');
                document.querySelectorAll('.sortable').forEach(h => h.classList.remove('asc', 'desc'));
                
                if (isAsc) {
                    this.classList.add('desc');
                    rows.reverse();
                } else {
                    this.classList.add('asc');
                    rows.sort((a, b) => {
                        const aVal = a.querySelectorAll('td')[column].textContent.trim();
                        const bVal = b.querySelectorAll('td')[column].textContent.trim();
                        
                        // Try numeric sort first
                        const aNum = parseFloat(aVal);
                        const bNum = parseFloat(bVal);
                        if (!isNaN(aNum) && !isNaN(bNum)) {
                            return aNum - bNum;
                        }
                        
                        // Fall back to string sort
                        return aVal.localeCompare(bVal);
                    });
                }
                
                rows.forEach(row => tbody.appendChild(row));
                updateCqStatistics();
            });
        });

        // change color of csv-button if dark mode is chosen
        if (isDarkModeTheme()) {
            $(".buttons-csv").css("color", "white");
        }
    </script>
    <script>
        // Preset filter functions
        function applyPreset(preset) {
            const form = document.getElementById('cqForm');
            
            // Reset all checkboxes first
            form.querySelectorAll('input[type="checkbox"]').forEach(cb => cb.checked = false);
            
            // All QSL types
            const allQslTypes = ['qsl', 'lotw', 'eqsl'];
            
            switch(preset) {
                case 'confirmed':
                    document.getElementById('confirmed').checked = true;
                    allQslTypes.forEach(type => {
                        const el = document.getElementById(type);
                        if (el) el.checked = true;
                    });
                    break;
                case 'worked':
                    document.getElementById('worked').checked = true;
                    allQslTypes.forEach(type => {
                        const el = document.getElementById(type);
                        if (el) el.checked = true;
                    });
                    break;
                case 'unworked':
                    document.getElementById('notworked').checked = true;
                    allQslTypes.forEach(type => {
                        const el = document.getElementById(type);
                        if (el) el.checked = true;
                    });
                    break;
            }
            
            form.submit();
        }
        
        function resetFilters() {
            const form = document.getElementById('cqForm');
            form.reset();
            // Make sure worked, confirmed, and QSL types are checked by default
            document.getElementById('worked').checked = true;
            document.getElementById('confirmed').checked = true;
            document.getElementById('qsl').checked = true;
            document.getElementById('lotw').checked = true;
            form.submit();
        }

        // CSV Export functionality
        function exportTableToCSV(filename) {
            const table = document.getElementById('cq_table');
            let csv = [];
            
            // Add header row
            const headers = Array.from(table.querySelectorAll('thead tr td')).map(h => h.textContent.trim());
            csv.push(headers.join(','));
            
            // Add data rows
            const rows = table.querySelectorAll('tbody tr');
            rows.forEach(row => {
                if (row.style.display !== 'none') {  // Only export visible rows
                    const cells = Array.from(row.querySelectorAll('td')).map(cell => {
                        let text = cell.textContent.trim();
                        // Escape quotes and wrap in quotes if contains comma
                        text = text.replace(/"/g, '""');
                        return '"' + text + '"';
                    });
                    csv.push(cells.join(','));
                }
            });
            
            // Create blob and download
            const blob = new Blob([csv.join('\n')], { type: 'text/csv' });
            const url = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = filename;
            document.body.appendChild(a);
            a.click();
            window.URL.revokeObjectURL(url);
            document.body.removeChild(a);
        }
    </script>
<?php } ?>

<?php if ($this->uri->segment(2) == "was") { ?>
    <script>
        // Initialize DataTable for summary
        $('.tablesummary').DataTable({
            info: false,
            searching: false,
            ordering: false,
            "paging": false,
            "language": {
                url: getDataTablesLanguageUrl(),
            },
            dom: 'Bfrtip',
            buttons: [
                'csv'
            ]
        });

        // Helper function to update statistics cards based on visible rows
        function updateWasStatistics() {
            const table = document.getElementById('was_table');
            const rows = table.querySelectorAll('tbody tr');
            
            let workedCount = 0;
            let confirmedCount = 0;
            
            rows.forEach((row, rowIndex) => {
                // Check if row is actually visible (not display:none)
                const isVisible = row.offsetParent !== null || row.style.display === '';
                if (isVisible || row.style.display !== 'none') {
                    const cells = row.querySelectorAll('td');
                    
                    if (cells.length > 1) {  // At least state + one band
                        // Check all band columns (starting from column 1, after state name)
                        let hasWorked = false;
                        let hasConfirmed = false;
                        
                        for (let i = 1; i < cells.length; i++) {
                            const cellValue = cells[i].textContent.trim();
                            // If cell is not empty and not a dash, it's worked
                            if (cellValue && cellValue !== '-') {
                                hasWorked = true;
                                // If it contains 'C', it's confirmed
                                if (cellValue.toUpperCase().includes('C')) {
                                    hasConfirmed = true;
                                }
                            }
                        }
                        
                        if (hasWorked) workedCount++;
                        if (hasConfirmed) confirmedCount++;
                    }
                }
            });
            
            // Update the stats cards
            const statsCards = document.querySelectorAll('.stats-card');
            statsCards.forEach(card => {
                const labels = card.querySelectorAll('.progress-label');
                labels.forEach(label => {
                    const parent = label.parentElement;
                    if (label.textContent.includes('Total Worked')) {
                        const numberDiv = parent.querySelector('.stats-number');
                        if (numberDiv) {
                            numberDiv.textContent = workedCount;
                        }
                    } else if (label.textContent.includes('Total Confirmed')) {
                        const numberDiv = parent.querySelector('.stats-number');
                        if (numberDiv) {
                            numberDiv.textContent = confirmedCount;
                        }
                    }
                });
            });
            
            // Update milestone indicators
            const milestoneCard = document.querySelector('.stats-card.milestone');
            if (milestoneCard) {
                const cols = milestoneCard.querySelectorAll('.col-6');
                cols.forEach(col => {
                    const label = col.querySelector('div:first-child');
                    const indicator = col.querySelector('div:nth-child(2)');
                    
                    if (label && indicator) {
                        if (label.textContent.includes('All Worked')) {
                            indicator.textContent = workedCount === 50 ? '✓' : '✗';
                            indicator.style.color = workedCount === 50 ? '#28a745' : '#dc3545';
                        } else if (label.textContent.includes('All Confirmed')) {
                            indicator.textContent = confirmedCount === 50 ? '✓' : '✗';
                            indicator.style.color = confirmedCount === 50 ? '#28a745' : '#dc3545';
                        }
                    }
                });
            }
        }

        // Call on page load to initialize with filtered data
        document.addEventListener('DOMContentLoaded', function() {
            setTimeout(function() {
                updateWasStatistics();
            }, 500);
        });

        // Table search functionality
        const searchInput = document.getElementById('searchInput');
        if (searchInput) {
            searchInput.addEventListener('keyup', function() {
                const searchTerm = this.value.toLowerCase();
                const table = document.getElementById('was_table');
                const rows = table.querySelectorAll('tbody tr');

                rows.forEach(row => {
                    const state = row.querySelectorAll('td')[0].textContent.toLowerCase();
                    
                    if (state.includes(searchTerm)) {
                        row.style.display = '';
                    } else {
                        row.style.display = 'none';
                    }
                });
                
                updateWasStatistics();
            });
        }

        // Sortable column functionality
        document.querySelectorAll('.sortable').forEach(header => {
            header.addEventListener('click', function() {
                const table = document.getElementById('was_table');
                const column = parseInt(this.dataset.column);
                const tbody = table.querySelector('tbody');
                const rows = Array.from(tbody.querySelectorAll('tr'));
                
                // Toggle sort direction
                const isAsc = this.classList.contains('asc');
                document.querySelectorAll('.sortable').forEach(h => h.classList.remove('asc', 'desc'));
                
                if (isAsc) {
                    this.classList.add('desc');
                    rows.reverse();
                } else {
                    this.classList.add('asc');
                    rows.sort((a, b) => {
                        const aVal = a.querySelectorAll('td')[column].textContent.trim();
                        const bVal = b.querySelectorAll('td')[column].textContent.trim();
                        
                        // Try numeric sort first
                        const aNum = parseFloat(aVal);
                        const bNum = parseFloat(bVal);
                        if (!isNaN(aNum) && !isNaN(bNum)) {
                            return aNum - bNum;
                        }
                        
                        // Fall back to string sort
                        return aVal.localeCompare(bVal);
                    });
                }
                
                rows.forEach(row => tbody.appendChild(row));
                updateWasStatistics();
            });
        });

        // change color of csv-button if dark mode is chosen
        if (isDarkModeTheme()) {
            $(".buttons-csv").css("color", "white");
        }
    </script>
    <script>
        // Preset filter functions
        function applyPreset(preset) {
            const form = document.getElementById('wasForm');
            
            // Reset all checkboxes first
            form.querySelectorAll('input[type="checkbox"]').forEach(cb => cb.checked = false);
            
            // All QSL types
            const allQslTypes = ['qsl', 'lotw', 'eqsl'];
            
            switch(preset) {
                case 'confirmed':
                    document.getElementById('confirmed').checked = true;
                    allQslTypes.forEach(type => {
                        const el = document.getElementById(type);
                        if (el) el.checked = true;
                    });
                    break;
                case 'worked':
                    document.getElementById('worked').checked = true;
                    allQslTypes.forEach(type => {
                        const el = document.getElementById(type);
                        if (el) el.checked = true;
                    });
                    break;
                case 'unworked':
                    document.getElementById('notworked').checked = true;
                    allQslTypes.forEach(type => {
                        const el = document.getElementById(type);
                        if (el) el.checked = true;
                    });
                    break;
            }
            
            form.submit();
        }
        
        function resetFilters() {
            const form = document.getElementById('wasForm');
            form.reset();
            // Make sure worked, confirmed, and QSL types are checked by default
            document.getElementById('worked').checked = true;
            document.getElementById('confirmed').checked = true;
            document.getElementById('qsl').checked = true;
            document.getElementById('lotw').checked = true;
            form.submit();
        }

        // CSV Export functionality
        function exportTableToCSV(filename) {
            const table = document.getElementById('was_table');
            let csv = [];
            
            // Add header row
            const headers = Array.from(table.querySelectorAll('thead tr td')).map(h => h.textContent.trim());
            csv.push(headers.join(','));
            
            // Add data rows
            const rows = table.querySelectorAll('tbody tr');
            rows.forEach(row => {
                if (row.style.display !== 'none') {  // Only export visible rows
                    const cells = Array.from(row.querySelectorAll('td')).map(cell => {
                        let text = cell.textContent.trim();
                        // Escape quotes and wrap in quotes if contains comma
                        text = text.replace(/"/g, '""');
                        return '"' + text + '"';
                    });
                    csv.push(cells.join(','));
                }
            });
            
            // Create blob and download
            const blob = new Blob([csv.join('\n')], { type: 'text/csv' });
            const url = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = filename;
            document.body.appendChild(a);
            a.click();
            window.URL.revokeObjectURL(url);
            document.body.removeChild(a);
        }
    </script>
<?php } ?>

<script>
    function selectize_usa_county() {
        var baseURL = "<?php echo base_url(); ?>";
        $('#stationCntyInputEdit').selectize({
            delimiter: ';',
            maxItems: 1,
            closeAfterSelect: true,
            loadThrottle: 250,
            valueField: 'name',
            labelField: 'name',
            searchField: 'name',
            options: [],
            create: false,
            load: function(query, callback) {
                var state = $("#input_usa_state_edit option:selected").text();

                if (!query || state == "") return callback();
                $.ajax({
                    url: baseURL + 'index.php/qso/get_county',
                    type: 'GET',
                    dataType: 'json',
                    data: {
                        query: query,
                        state: state,
                    },
                    error: function() {
                        callback();
                    },
                    success: function(res) {
                        callback(res);
                    }
                });
            }
        });
    }

    function qso_save() {
        var baseURL = "<?php echo base_url(); ?>";
        var myform = document.getElementById("qsoform");
        var fd = new FormData(myform);
        $.ajax({
            url: baseURL + 'index.php/qso/qso_save_ajax',
            data: fd,
            cache: false,
            processData: false,
            contentType: false,
            type: 'POST',
            success: function(dataofconfirm) {
                $(".edit-dialog").modal('hide');
                $(".qso-dialog").modal('hide');
                <?php if ($this->uri->segment(1) != "search" && $this->uri->segment(2) != "filter" && $this->uri->segment(1) != "qso" && $this->uri->segment(1) != "logbookadvanced") { ?>location.reload();
            <?php } ?>
            },
            error: function(xhr, status, error) {
                console.log(xhr.responseText);
            }
        });
    }
</script>
<?php if ($this->uri->segment(1) == "timeline") { ?>
    <script>
        if ($('.timelinetable').length) {
            $('.timelinetable').DataTable({
                "pageLength": 25,
                responsive: false,
                ordering: false,
                "scrollY": "500px",
                "scrollCollapse": true,
                "paging": false,
                "scrollX": true,
                "language": {
                    url: getDataTablesLanguageUrl(),
                },
                dom: 'Bfrtip',
                buttons: [
                    'csv'
                ]
            });
        }

        // change color of csv-button if dark mode is chosen
        if (isDarkModeTheme()) {
            $(".buttons-csv").css("color", "white");
        }

        function displayTimelineContacts(querystring, band, mode, type) {
            var baseURL = "<?php echo base_url(); ?>";
            var modalElement = document.getElementById('timelineDetailsModal');
            var modalBody = document.getElementById('timelineDetailsBody');
            if (!modalElement || !modalBody) {
                return;
            }

            modalBody.innerHTML = '<div class="d-flex justify-content-center py-4"><div class="spinner-border" role="status" aria-hidden="true"></div></div>';

            var modal = bootstrap.Modal.getOrCreateInstance(modalElement);
            modal.show();

            if (window.htmx) {
                htmx.ajax('POST', baseURL + 'index.php/timeline/details', {
                    target: '#timelineDetailsBody',
                    swap: 'innerHTML',
                    values: {
                        Querystring: querystring,
                        Band: band,
                        Mode: mode,
                        Type: type
                    }
                });
            } else {
                $.post(baseURL + 'index.php/timeline/details', {
                    Querystring: querystring,
                    Band: band,
                    Mode: mode,
                    Type: type
                }).done(function(html) {
                    modalBody.innerHTML = html;
                    initTimelineDetailsTable();
                });
            }
        }

        function initTimelineDetailsTable() {
            $('[data-bs-toggle="tooltip"]').tooltip();

            var detailsTable = $('.contacttable');
            if (detailsTable.length) {
                if ($.fn.dataTable.isDataTable(detailsTable)) {
                    detailsTable.DataTable().destroy();
                }

                detailsTable.DataTable({
                    "pageLength": 10,
                    responsive: false,
                    ordering: false,
                    "scrollY": "55vh",
                    "scrollCollapse": true,
                    "paging": true,
                    "scrollX": true,
                    "language": {
                        url: getDataTablesLanguageUrl(),
                    },
                    dom: 'Bfrtip',
                    buttons: [
                        'csv'
                    ]
                });
            }

            $('.table-responsive .dropdown-toggle').off('mouseenter').on('mouseenter', function() {
                showQsoActionsMenu($(this).closest('.dropdown'));
            });
        }

        if (window.htmx) {
            document.body.addEventListener('htmx:afterSwap', function(evt) {
                if (evt.target && evt.target.id === 'timelineDetailsBody') {
                    initTimelineDetailsTable();
                }
            });
        }
    </script>
<?php } ?>
<?php if ($this->uri->segment(1) == "activators") { ?>
    <script>
        $('.activatorstable').DataTable({
            "pageLength": 25,
            responsive: false,
            ordering: false,
            "scrollY": "500px",
            "scrollCollapse": true,
            "paging": false,
            "scrollX": true,
            "language": {
                url: getDataTablesLanguageUrl(),
            },
            dom: 'Bfrtip',
            buttons: [
                'csv'
            ]
        });

        // change color of csv-button if dark mode is chosen
        if (isDarkModeTheme()) {
            $(".buttons-csv").css("color", "white");
        }

        $(document).ready(function() {
            $('#band').change(function() {
                if ($(this).val() == "SAT") {
                    $('#leogeo').show();
                } else {
                    $('#leogeo').hide();
                }
            });
            <?php if ($this->input->post('band') != "SAT") { ?>
                $('#leogeo').hide();
            <?php } ?>
        });

        function displayActivatorsContacts(call, band, leogeo) {
            var baseURL = "<?php echo base_url(); ?>";
            $.ajax({
                url: baseURL + 'index.php/activators/details',
                type: 'post',
                data: {
                    'Callsign': call,
                    'Band': band,
                    'LeoGeo': leogeo
                },
                success: function(html) {
                    BootstrapDialog.show({
                        title: lang_general_word_qso_data,
                        size: BootstrapDialog.SIZE_WIDE,
                        cssClass: 'qso-was-dialog',
                        nl2br: false,
                        message: html,
                        onshown: function(dialog) {
                            $('[data-bs-toggle="tooltip"]').tooltip();
                        },
                        buttons: [{
                            label: lang_admin_close,
                            action: function(dialogItself) {
                                dialogItself.close();
                            }
                        }]
                    });
                }
            });
        }
    </script>
<?php } ?>

<?php if ($this->uri->segment(1) == "mode") { ?>
    <script src="<?php echo base_url(); ?>assets/js/sections/mode.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "band") { ?>
    <script src="<?php echo base_url(); ?>assets/js/sections/bands.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "award") { ?>
    <script src="<?php echo base_url(); ?>assets/js/sections/awards.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "accumulated") { ?>
    <script src="<?php echo base_url(); ?>assets/js/chart.js"></script>
    <script src="<?php echo base_url(); ?>assets/js/sections/accumulatedstatistics.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "timeplotter") { ?>
    <script src="<?php echo base_url(); ?>assets/js/highstock.js"></script>
    <script src="<?php echo base_url(); ?>assets/js/highstock/exporting.js"></script>
    <script src="<?php echo base_url(); ?>assets/js/highstock/offline-exporting.js"></script>
    <script src="<?php echo base_url(); ?>assets/js/highstock/export-data.js"></script>
    <script src="<?php echo base_url(); ?>assets/js/sections/timeplot.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "qsl" || $this->uri->segment(1) == "eqsl") {
    // Get Date format
    if ($this->session->userdata('user_date_format')) {
        // If Logged in and session exists
        $custom_date_format = $this->session->userdata('user_date_format');
    } else {
        // Get Default date format from /config/cloudlog.php
        $custom_date_format = $this->config->item('qso_date_format');
    }

    switch ($custom_date_format) {
        case 'd/m/y':
            $usethisformat = 'D/MM/YY';
            break;
        case 'd/m/Y':
            $usethisformat = 'D/MM/YYYY';
            break;
        case 'm/d/y':
            $usethisformat = 'MM/D/YY';
            break;
        case 'm/d/Y':
            $usethisformat = 'MM/D/YYYY';
            break;
        case 'd.m.Y':
            $usethisformat = 'D.MM.YYYY';
            break;
        case 'y/m/d':
            $usethisformat = 'YY/MM/D';
            break;
        case 'Y-m-d':
            $usethisformat = 'YYYY-MM-D';
            break;
        case 'M d, Y':
            $usethisformat = 'MMM D, YYYY';
            break;
        case 'M d, y':
            $usethisformat = 'MMM D, YY';
            break;
    }

?>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/moment.min.js"></script>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/datetime-moment.js"></script>
    <script>
        $.fn.dataTable.moment('<?php echo $usethisformat ?>');
        $.fn.dataTable.ext.buttons.clear = {
            className: 'buttons-clear',
            action: function(e, dt, node, config) {
                dt.search('').draw();
            }
        };
        <?php if ($this->uri->segment(1) == "qsl") { ?>
            $('.qsltable').DataTable({
                    <?php } else if ($this->uri->segment(1) == "eqsl") { ?>
                        $('.eqsltable').DataTable({
                        <?php } ?> "pageLength": 25,
                        responsive: false,
                        ordering: true,
                        "scrollY": "500px",
                        "scrollCollapse": true,
                        "paging": false,
                        "scrollX": true,
                        "language": {
                            url: getDataTablesLanguageUrl(),
                        },
                        "order": [2, 'desc'],
                        dom: 'Bfrtip',
                        buttons: [{
                            extend: 'clear',
                            text: 'Clear'
                        }]
                        });
                        // change color of csv-button if dark mode is chosen
                        if (isDarkModeTheme()) {
                            $('[class*="buttons"]').css("color", "white");
                        }
    </script>
<?php } ?>


<script>
    function viewQsl(picture, callsign) {
        let title = '';
        const baseURL = "<?php echo base_url(); ?>";
        const textAndPic = $('<div></div>').append('<center><img class="img-fluid w-qsl" style="height:auto;width:auto;"src="' + baseURL + '/assets/qslcard/' + picture + '" /><center>');

        if (callsign == null) {
            title = 'QSL Card';
        } else {
            title = 'QSL Card for ' + callsign.replace('0', '&Oslash;');
        }

        BootstrapDialog.show({
            title: title,
            size: BootstrapDialog.SIZE_WIDE,
            message: textAndPic,
            buttons: [{
                label: lang_admin_close,
                action: function(dialogRef) {
                    dialogRef.close();
                }
            }]
        });
    }
</script>
<script>
    function deleteQsl(id) {
        const baseURL = "<?php echo base_url(); ?>";
        BootstrapDialog.confirm({
            title: 'DANGER',
            message: 'Warning! Are you sure you want to delete this QSL card?',
            type: BootstrapDialog.TYPE_DANGER,
            closable: true,
            draggable: true,
            btnOKClass: 'btn-danger',
            callback: function(result) {
                if (result) {
                    $.ajax({
                        url: baseURL + 'index.php/qsl/delete',
                        type: 'post',
                        data: {
                            'id': id
                        },
                        success: function(data) {
                            $("#" + id).parent("tr:first").remove(); // removes qsl from table

                            // remove qsl from carousel
                            $(".carousel-indicators li:last-child").remove();
                            $(".carouselimageid_" + id).remove();
                            $('#carouselExampleIndicators').find('.carousel-item').first().addClass('active');

                            // remove table and hide tab if all qsls are deleted
                            if ($('.qsltable tr').length == 1) {
                                $('.qsltable').remove();
                                $('.qslcardtab').attr('hidden', '');
                            }
                        }
                    });
                }
            }
        });
    }
</script>
<script>
    function viewSstv(picture) {
        const title = 'SSTV Image';
        const baseURL = "<?php echo base_url(); ?>";
        const textAndPic = $('<div></div>').append(`<center><img class="img-fluid w-qsl" style="height:auto;width:auto;"src="${baseURL}/assets/sstvimages/${picture}" /><center>`);

        BootstrapDialog.show({
            title: title,
            size: BootstrapDialog.SIZE_WIDE,
            message: textAndPic,
            buttons: [{
                label: lang_admin_close,
                action: function(dialogRef) {
                    dialogRef.close();
                }
            }]
        });
    }

    function deleteSstv(id) {
        const baseURL = "<?php echo base_url(); ?>";
        BootstrapDialog.confirm({
            title: 'DANGER',
            message: 'Warning! Are you sure you want to delete this SSTV Image?',
            type: BootstrapDialog.TYPE_DANGER,
            closable: true,
            draggable: true,
            btnOKClass: 'btn-danger',
            callback: function(result) {
                if (result) {
                    $.ajax({
                        url: baseURL + 'index.php/sstv/delete',
                        type: 'post',
                        data: {
                            'id': id
                        },
                        success: function(data) {
                            // remove selected sstv image from table
                            $("#" + id).parent("tr:first").remove();

                            // remove sstv image from carousel
                            $("#sstvCarouselIndicators .carousel-indicators li:last-child").remove();
                            $("#sstvCarouselIndicators .carouselimageid_" + id).remove();
                            $('#sstvCarouselIndicators').find('.carousel-item').first().addClass('active');

                            // remove table and hide tab if all sstv images are deleted
                            if ($('.sstvtable tr').length == 1) {
                                $('.sstvtable').remove();
                                $('.sstvimagetab').attr('hidden', '');
                            }
                        }
                    });
                }
            }
        });
    }
</script>

<script>
    function viewEqsl(picture, callsign) {
        var baseURL = "<?php echo base_url(); ?>";
        var $textAndPic = $('<div></div>');
        $textAndPic.append('<img class="img-fluid" style="height:auto;width:auto;"src="' + baseURL + 'images/eqsl_card_images/' + picture + '" />');
        var title = '';
        if (callsign == null) {
            title = 'eQSL Card';
        } else {
            title = 'eQSL Card for ' + callsign.replace('0', '&Oslash;');
        }

        BootstrapDialog.show({
            title: title,
            size: BootstrapDialog.SIZE_WIDE,
            message: $textAndPic,
            buttons: [{
                label: lang_admin_close,
                action: function(dialogRef) {
                    dialogRef.close();
                }
            }]
        });
    }
</script>
<script>
    $('#displayAwardInfo').click(function(event) {
        var awardInfoLines = [
            lang_award_info_ln2,
            lang_award_info_ln3,
            lang_award_info_ln4
        ];
        var awardInfoContent = "";
        awardInfoLines.forEach(function(line) {
            awardInfoContent += line + "<br><br>";
        });
        BootstrapDialog.alert({
            title: "<h4>" + lang_award_info_ln1 + "</h4>",
            message: awardInfoContent,
        });
    });
</script>
<script>
    /*
     * Used to fetch QSOs from the logbook in the awards
     */
    function displayContacts(searchphrase, band, mode, type, qsl) {
        var baseURL = "<?php echo base_url(); ?>";
        $.ajax({
            url: baseURL + 'index.php/awards/qso_details_ajax',
            type: 'post',
            data: {
                'Searchphrase': searchphrase,
                'Band': band,
                'Mode': mode,
                'Type': type,
                'QSL': qsl
            },
            success: function(html) {
                BootstrapDialog.show({
                    title: lang_general_word_qso_data,
                    size: BootstrapDialog.SIZE_WIDE,
                    cssClass: 'qso-dialog',
                    nl2br: false,
                    message: html,
                    onshown: function(dialog) {
                        $('[data-bs-toggle="tooltip"]').tooltip();
                        $('.contacttable').DataTable({
                            "pageLength": 7,
                            responsive: false,
                            ordering: false,
                            "scrollY": "550px",
                            "scrollCollapse": true,
                            "paging": true,
                            "scrollX": true,
                            "language": {
                                url: getDataTablesLanguageUrl(),
                            },
                            dom: 'Bfrtip',
                            buttons: [
                                'csv'
                            ]
                        });
                        $('.table-responsive .dropdown-toggle').off('mouseenter').on('mouseenter', function() {
                            showQsoActionsMenu($(this).closest('.dropdown'));
                        });
                    },
                    buttons: [{
                        label: lang_admin_close,
                        action: function(dialogItself) {
                            dialogItself.close();
                        }
                    }]
                });
            }
        });
    }

    function displayContactsOnMap(target, searchphrase, band, mode, type, qsl) {
        $.ajax({
            url: base_url + 'index.php/awards/qso_details_ajax',
            type: 'post',
            data: {
                'Searchphrase': searchphrase,
                'Band': band,
                'Mode': mode,
                'Type': type,
                'QSL': qsl
            },
            success: function(html) {
                var dialog = new BootstrapDialog({
                    title: lang_general_word_qso_data,
                    size: BootstrapDialog.SIZE_WIDE,
                    cssClass: 'qso-dialog',
                    nl2br: false,
                    message: html,
                    onshown: function(dialog) {
                        $('[data-bs-toggle="tooltip"]').tooltip();
                        $('.contacttable').DataTable({
                            "pageLength": 25,
                            responsive: false,
                            ordering: false,
                            "scrollY": "550px",
                            "scrollCollapse": true,
                            "paging": false,
                            "scrollX": true,
                            "language": {
                                url: getDataTablesLanguageUrl(),
                            },
                            dom: 'Bfrtip',
                            buttons: [
                                'csv'
                            ]
                        });
                        $('.table-responsive .dropdown-toggle').off('mouseenter').on('mouseenter', function() {
                            showQsoActionsMenu($(this).closest('.dropdown'));
                        });
                    },
                    buttons: [{
                        label: lang_admin_close,
                        action: function(dialogItself) {
                            dialogItself.close();
                        }
                    }]
                });
                dialog.realize();
                target.append(dialog.getModal());
                dialog.open();
            }
        });
    }

    function createTable(title, type) {
        const tableClass = type === 'sstv' ? 'sstvtable' : 'qsltable';
        return `<table style="width:100%" class="${tableClass} table table-sm table-bordered table-hover table-striped table-condensed">` +
            '<thead>' +
            '<tr>' +
            '<th style="text-align: center">' + title + '</th>' +
            '<th style="text-align: center"></th>' +
            '<th style="text-align: center"></th>' +
            '</tr>' +
            '</thead>' +
            '<tbody></tbody>' +
            '</table>'
    }

    function createTableRow(image, type) {
        const viewFunction = type === 'sstv' ? 'viewSstv' : 'viewQsl';
        const deleteFunction = type === 'sstv' ? 'deleteSstv' : 'deleteQsl';
        return '<tr><td style="text-align: center">' + image.filename + '</td>' +
            `<td id="${image.insertid}" style="text-align: center"><button onclick="${deleteFunction}(${image.insertid});" class="btn btn-sm btn-danger">Delete</button></td>` +
            `<td style="text-align: center"><button onclick="${viewFunction}('${image.filename}')" class="btn btn-sm btn-success">View</button></td>` +
            '</tr>'
    }

    function handleSSTVImageUpload(sstvImage) {
        const baseURL = "<?php echo base_url(); ?>";
        const numCarouselItems = $('#sstv-carousel-indicators li').length;

        // Next, append card to the table
        $('.sstvtable').length === 0 ? $("#sstvupload").prepend(createTable("SSTV image file", "sstv")) : null;
        $('.sstvtable tbody:last').append(createTableRow(sstvImage, "sstv"));

        // Append card to the carousel
        const newCarouselItem = '<div class="' + (numCarouselItems === 0 ? 'active ' : '') + 'carousel-item carouselimageid_' + sstvImage.insertid + '"><img class="img-fluid w-qsl" src="' + baseURL + '/assets/sstvimages/' + sstvImage.filename + '" alt="QSL picture"></div>';
        $("#sstv-carousel-inner").append(newCarouselItem);

        // Append new carousel indicator
        const newCarouselIndicator = '<li class="' + (numCarouselItems === 0 ? 'active ' : '') + '" data-bs-target="#sstvCarouselIndicators" data-bs-slide-to="' + numCarouselItems + '"></li>';
        $("#sstv-carousel-indicators").append(newCarouselIndicator);

        // Initialize the bootstrap carousel
        $("#sstvCarouselIndicators").carousel();
    }

    function uploadSSTV() {
        const baseURL = "<?php echo base_url(); ?>";
        const formdata = new FormData(document.getElementById("sstvinfo"));

        $.ajax({
            url: baseURL + 'index.php/sstv/uploadsstv',
            type: 'post',
            data: formdata,
            enctype: 'multipart/form-data',
            processData: false,
            contentType: false,
            success: function(data) {
                // Iterate over each SSTV image and handle it
                data.forEach((sstvImage) => {
                    if (sstvImage.status == 'Success') {
                        // Show the SSTV image tab
                        $('.sstvimagetab').removeAttr('hidden');

                        // Handle the SSTV image upload
                        handleSSTVImageUpload(sstvImage);
                    } else if (sstvImage.status != '') {
                        $("#sstvupload").append('<div class="alert alert-danger">SSTV image:' +
                            sstvImage.error +
                            '</div>');
                    }
                    // Reset the image inputs
                    $("#sstvimages").val(null);
                })
            }
        });
    }

    function handleQslCardUpload(qslCard) {
        const baseURL = "<?php echo base_url(); ?>";
        const numCarouselItems = $('#qsl-carousel-indicators li').length;

        // append card to the qsl management table
        $('.qsltable').length === 0 ? $("#qslupload").prepend(createTable("QSL image file", "qsl")) : null;
        $('.qsltable tbody:last').append(createTableRow(qslCard, "qsl"));

        // Append card image to the carousel
        const newCarouselItem = '<div class="' + (numCarouselItems === 0 ? 'active ' : '') + 'carousel-item carouselimageid_' + qslCard.insertid + '"><img class="img-fluid w-qsl" src="' + baseURL + '/assets/qslcard/' + qslCard.filename + '" alt="QSL picture"></div>';
        $("#qsl-carousel-inner").append(newCarouselItem);

        // Append carousel indicator for the new card
        const newCarouselIndicator = '<li class="' + (numCarouselItems === 0 ? 'active ' : '') + '" data-bs-target="#qslCarouselIndicators" data-bs-slide-to="' + numCarouselItems + '"></li>';
        $("#qsl-carousel-indicators").append(newCarouselIndicator);

        // Initialize the bootstrap carousel
        $("#qslCarouselIndicators").carousel();
    }

    function uploadQsl() {
        const baseURL = "<?php echo base_url(); ?>";
        const formdata = new FormData(document.getElementById("fileinfo"));

        $.ajax({
            url: baseURL + 'index.php/qsl/uploadqsl',
            type: 'post',
            data: formdata,
            enctype: 'multipart/form-data',
            processData: false,
            contentType: false,
            success: function(data) {
                const qslCard = data.status || {}
                if (data.status.front.status == 'Success') {
                    handleQslCardUpload(qslCard.front);
                } else if (qslCard.front.status != '') {
                    $("#qslupload").append('<div class="alert alert-danger">Front QSL Card:' +
                        qslCard.front.error +
                        '</div>');
                }

                if (qslCard.back.status == 'Success') {
                    handleQslCardUpload(qslCard.back);
                } else if (qslCard.back.status != '') {
                    $("#qslupload").append('<div class="alert alert-danger">\nBack QSL Card: ' +
                        qslCard.back.error +
                        '</div>');
                }

                // Show the QSL card tab
                $('.qslcardtab').removeAttr('hidden');

                // Reset the image inputs
                $("#qslcardfront").val(null);
                $("#qslcardback").val(null);
            }
        });
    }
</script>
<script>
    function addQsosToQsl(filename) {
        var title = 'Add additional QSOs to a QSL Card';

        var baseURL = "<?php echo base_url(); ?>";
        $.ajax({
            url: baseURL + 'index.php/qsl/loadSearchForm',
            type: 'post',
            data: {
                'filename': filename
            },
            success: function(html) {
                BootstrapDialog.show({
                    title: title,
                    size: BootstrapDialog.SIZE_WIDE,
                    cssClass: 'qso-search_results',
                    nl2br: false,
                    message: html,
                    buttons: [{
                        label: lang_admin_close,
                        action: function(dialogItself) {
                            dialogItself.close();
                        }
                    }]
                });
            }
        });
    }

    function addQsoToQsl(qsoid, filename, id) {
        var title = 'Add additional QSOs to a QSL Card';

        var baseURL = "<?php echo base_url(); ?>";
        $.ajax({
            url: baseURL + 'index.php/qsl/addQsoToQsl',
            type: 'post',
            data: {
                'filename': filename,
                'qsoid': qsoid
            },
            success: function(html) {
                if (html.status == 'Success') {
                    location.reload();
                } else {
                    $(".alert").remove();
                    $('#searchresult').prepend('<div class="alert alert-danger">Something went wrong. Please try again!</div>');
                }
            }
        });
    }

    function searchAdditionalQsos(filename) {
        var baseURL = "<?php echo base_url(); ?>";
        $.ajax({
            url: baseURL + 'index.php/qsl/searchQsos',
            type: 'post',
            data: {
                'callsign': $('#callsign').val(),
                'filename': filename
            },
            success: function(html) {
                $('#searchresult').empty();
                $('#searchresult').append(html);
            }
        });
    }
</script>
<?php if ($this->uri->segment(1) == "contesting" && ($this->uri->segment(2) != "add" && $this->uri->segment(2) != "edit")) { ?>
    <script>
        var manual = <?php echo $_GET['manual']; ?>;
    </script>
    <script src="<?php echo base_url(); ?>assets/js/sections/contesting.js?v2"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "station") { ?>
    <script>
        var baseURL = "<?php echo base_url(); ?>";

        $(document).ready(function() {
            function checkSelectedValue() {
                var selectedValue = $('#dxcc_select').val();
                var valuesToShow = [223, 279, 294, 265, 106, 122];

                if (valuesToShow.includes(Number(selectedValue))) {
                    $('#WABbox').show();
                } else {
                    $('#WABbox').hide();
                }
            }

            // Call on page load
            checkSelectedValue();

            // Call on change event
            $('#dxcc_select').change(checkSelectedValue);
        });

        var state = $("#StateHelp option:selected").text();
        if (state != "") {
            $("#stationCntyInput").prop('disabled', false);
            station_profile_selectize_usa_county();
        }

        $('#StateHelp').change(function() {
            var state = $("#StateHelp option:selected").text();
            if (state != "") {
                $("#stationCntyInput").prop('disabled', false);
                station_profile_selectize_usa_county();
            } else {
                $("#stationCntyInput").prop('disabled', true);
                //$('#stationCntyInput')[0].selectize.destroy();
                $("#stationCntyInput").val("");
            }
        });

        function station_profile_selectize_usa_county() {
            $('#stationCntyInput').selectize({
                maxItems: 1,
                closeAfterSelect: true,
                loadThrottle: 250,
                valueField: 'name',
                labelField: 'name',
                searchField: 'name',
                options: [],
                create: false,
                load: function(query, callback) {
                    var state = $("#StateHelp option:selected").text();

                    if (!query || state == "") return callback();
                    $.ajax({
                        url: baseURL + 'index.php/station/get_county',
                        type: 'GET',
                        dataType: 'json',
                        data: {
                            query: query,
                            state: state,
                        },
                        error: function() {
                            callback();
                        },
                        success: function(res) {
                            callback(res);
                        }
                    });
                }
            });
        }
    </script>

<?php } ?>

<?php if ($this->uri->segment(2) == "counties" || $this->uri->segment(2) == "counties_details") { ?>
    <script>
        $('.countiestable').DataTable({
            "pageLength": 25,
            responsive: false,
            ordering: false,
            "scrollY": "390px",
            "scrollCollapse": true,
            "paging": false,
            "scrollX": true,
            "language": {
                url: getDataTablesLanguageUrl(),
            },
            dom: 'Bfrtip',
            buttons: [
                'csv'
            ]
        });

        // change color of csv-button if dark mode is chosen
        if (isDarkModeTheme()) {
            $(".buttons-csv").css("color", "white");
        }

        function displayCountyContacts(state, county) {
            var baseURL = "<?php echo base_url(); ?>";
            $.ajax({
                url: baseURL + 'index.php/awards/counties_details_ajax',
                type: 'post',
                data: {
                    'State': state,
                    'County': county
                },
                success: function(html) {
                    BootstrapDialog.show({
                        title: lang_general_word_qso_data,
                        size: BootstrapDialog.SIZE_WIDE,
                        cssClass: 'qso-counties-dialog',
                        nl2br: false,
                        message: html,
                        onshown: function(dialog) {
                            $('[data-bs-toggle="tooltip"]').tooltip();
                        },
                        buttons: [{
                            label: lang_admin_close,
                            action: function(dialogItself) {
                                dialogItself.close();
                            }
                        }]
                    });
                }
            });
        }
    </script>
<?php } ?>

<?php if ($this->uri->segment(2) == "sig_details") { ?>
    <script>
        $('.tablesig').DataTable({
            "pageLength": 25,
            responsive: false,
            ordering: false,
            "scrollY": "400px",
            "scrollCollapse": true,
            "paging": false,
            "scrollX": true,
            "language": {
                url: getDataTablesLanguageUrl(),
            },
            dom: 'Bfrtip',
            buttons: [
                'csv'
            ]
        });

        // change color of csv-button if dark mode is chosen
        if (isDarkModeTheme()) {
            $(".buttons-csv").css("color", "white");
        }
    </script>
<?php } ?>

<?php if ($this->uri->segment(1) == "contesting" && $this->uri->segment(2) == "add") { ?>
    <script src="<?php echo base_url(); ?>assets/js/sections/contestingnames.js"></script>
<?php } ?>

<?php if ($this->uri->segment(1) == "themes") { ?>
    <script>
        function deleteTheme(id, name) {
            BootstrapDialog.confirm({
                title: 'DANGER',
                message: 'Warning! Are you sure you want to delete the following theme: ' + name + '?',
                type: BootstrapDialog.TYPE_DANGER,
                closable: true,
                draggable: true,
                btnOKClass: 'btn-danger',
                callback: function(result) {
                    if (result) {
                        $.ajax({
                            url: base_url + 'index.php/themes/delete',
                            type: 'post',
                            data: {
                                'id': id
                            },
                            success: function(data) {
                                $(".theme_" + id).parent("tr:first").remove(); // removes mode from table
                            }
                        });
                    }
                }
            });
        }

        function addThemeDialog() {
            $.ajax({
                url: base_url + 'index.php/themes/add',
                type: 'post',
                success: function(html) {
                    BootstrapDialog.show({
                        title: 'Create Theme',
                        size: BootstrapDialog.SIZE_WIDE,
                        cssClass: 'create-theme-dialog',
                        nl2br: false,
                        message: html,
                        buttons: [{
                            label: lang_admin_close,
                            action: function(dialogItself) {
                                dialogItself.close();
                            }
                        }]
                    });
                }
            });
        }

        function addTheme(form) {
            if (form.name.value != '') {
                $.ajax({
                    url: base_url + 'index.php/themes/add',
                    type: 'post',
                    data: {
                        'name': form.name.value,
                        'foldername': form.foldername.value,
                    },
                    success: function(html) {
                        location.reload();
                    }
                });
            }
        }
    </script>
<?php } ?>


<?php if ($this->uri->segment(1) == "eqsl") { ?>
    <script>
        $('.qsotable').DataTable({
            "stateSave": true,
            "pageLength": 25,
            responsive: false,
            "scrollY": "400px",
            "scrollCollapse": true,
            "paging": false,
            "scrollX": true,
            "language": {
                url: getDataTablesLanguageUrl(),
            },
            "ordering": true,
            "order": [0, 'desc'],
        });
    </script>
<?php } ?>

<?php if ($this->uri->segment(1) == "awards") {
    // Get Date format
    if ($this->session->userdata('user_date_format')) {
        // If Logged in and session exists
        $custom_date_format = $this->session->userdata('user_date_format');
    } else {
        // Get Default date format from /config/cloudlog.php
        $custom_date_format = $this->config->item('qso_date_format');
    }

    switch ($custom_date_format) {
        case 'd/m/y':
            $usethisformat = 'D/MM/YY';
            break;
        case 'd/m/Y':
            $usethisformat = 'D/MM/YYYY';
            break;
        case 'm/d/y':
            $usethisformat = 'MM/D/YY';
            break;
        case 'm/d/Y':
            $usethisformat = 'MM/D/YYYY';
            break;
        case 'd.m.Y':
            $usethisformat = 'D.MM.YYYY';
            break;
        case 'y/m/d':
            $usethisformat = 'YY/MM/D';
            break;
        case 'Y-m-d':
            $usethisformat = 'YYYY-MM-D';
            break;
        case 'M d, Y':
            $usethisformat = 'MMM D, YYYY';
            break;
        case 'M d, y':
            $usethisformat = 'MMM D, YY';
            break;
    }

?>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/moment.min.js"></script>
    <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/datetime-moment.js"></script>
    <?php if ($this->uri->segment(2) == "wwff") { ?>
        <script>
            $.fn.dataTable.moment('<?php echo $usethisformat ?>');
            $.fn.dataTable.ext.buttons.clear = {
                className: 'buttons-clear',
                action: function(e, dt, node, config) {
                    dt.search('').draw();
                }
            };
            $('#wwfftable').DataTable({
                "pageLength": 25,
                responsive: false,
                ordering: true,
                "scrollY": "500px",
                "scrollCollapse": true,
                "paging": false,
                "scrollX": true,
                "language": {
                    url: getDataTablesLanguageUrl(),
                },
                "order": [0, 'asc'],
                dom: 'Bfrtip',
                buttons: [{
                        extend: 'csv'
                    },
                    {
                        extend: 'clear',
                        text: 'Clear'
                    }
                ]
            });
            // change color of csv-button if dark mode is chosen
            if (isDarkModeTheme()) {
                $('[class*="buttons"]').css("color", "white");
            }
        </script>
    <?php } else if ($this->uri->segment(2) == "pota") { ?>
        <script>
            $.fn.dataTable.moment('<?php echo $usethisformat ?>');
            $.fn.dataTable.ext.buttons.clear = {
                className: 'buttons-clear',
                action: function(e, dt, node, config) {
                    dt.search('').draw();
                }
            };
            $('#potatable').DataTable({
                "pageLength": 25,
                responsive: false,
                ordering: true,
                "scrollY": "500px",
                "scrollCollapse": true,
                "paging": false,
                "scrollX": true,
                "language": {
                    url: getDataTablesLanguageUrl(),
                },
                "order": [0, 'asc'],
                dom: 'Bfrtip',
                buttons: [{
                        extend: 'csv'
                    },
                    {
                        extend: 'clear',
                        text: 'Clear'
                    }
                ]
            });
            // change color of csv-button if dark mode is chosen
            if (isDarkModeTheme()) {
                $('[class*="buttons"]').css("color", "white");
            }
        </script>
    <?php } else if ($this->uri->segment(2) == "dok") { ?>
        <script>
            $.fn.dataTable.ext.buttons.clear = {
                className: 'buttons-clear',
                action: function(e, dt, node, config) {
                    dt.search('').draw();
                }
            };
            $('#doktable').DataTable({
                "pageLength": 25,
                responsive: false,
                ordering: false,
                "scrollY": "500px",
                "scrollCollapse": true,
                "paging": false,
                "scrollX": true,
                "language": {
                    url: getDataTablesLanguageUrl(),
                },
                dom: 'Bfrtip',
                buttons: [{
                        extend: 'csv'
                    },
                    {
                        extend: 'clear',
                        text: 'Clear'
                    }
                ]
            });
            // change color of csv-button if dark mode is chosen
            if (isDarkModeTheme()) {
                $('[class*="buttons"]').css("color", "white");
            }
        </script>
    <?php } ?>
<?php } ?>

<?php if ($this->uri->segment(1) == "user") { ?>
    <!-- [MAP Custom] select list with icons -->
    <script>
        $(document).ready(function() {
            $('.icon_selectBox').off('click').on('click', function() {
                var boxcontent = $(this).attr('data-boxcontent');
                if ($('.icon_selectBox_data[data-boxcontent="' + boxcontent + '"]').is(":hidden")) {
                    $('.icon_selectBox_data[data-boxcontent="' + boxcontent + '"]').show();
                } else {
                    $('.icon_selectBox_data[data-boxcontent="' + boxcontent + '"]').hide();
                }
            });
            $('.icon_selectBox_data').off('mouseleave').on('mouseleave', function() {
                if ($(this).is(":visible")) {
                    $(this).hide();
                }
            });
            $('.icon_selectBox_data label').off('click').on('click', function() {
                var boxcontent = $(this).closest('.icon_selectBox_data').attr('data-boxcontent');
                $('input[name="user_map_' + boxcontent + '_icon"]').attr('value', $(this).attr('data-value'));
                if ($(this).attr('data-value') != "0") {
                    $('.user_icon_color[data-icon="' + boxcontent + '"]').show();
                    $('.icon_selectBox[data-boxcontent="' + boxcontent + '"] .icon_overSelect').html($(this).html());
                } else {
                    $('.user_icon_color[data-icon="' + boxcontent + '"]').hide();
                    $('.icon_selectBox[data-boxcontent="' + boxcontent + '"] .icon_overSelect').html($(this).html().substring(0, 10) + '.');
                }
                $('.icon_selectBox_data[data-boxcontent="' + boxcontent + '"]').hide();
            });

            $('.collapse').on('shown.bs.collapse', function(e) {
                var $card = $(this).closest('.accordion-item');
                var $open = $($(this).data('parent')).find('.collapse.show');

                var additionalOffset = 0;
                if ($card.prevAll().filter($open.closest('.accordion-item')).length !== 0) {
                    additionalOffset = $open.height();
                }
                $('html,body').animate({
                    scrollTop: $card.offset().top - additionalOffset
                }, 300);
            });
        });
    </script>
<?php } ?>

<?php
if (isset($scripts) && is_array($scripts)) {
    foreach ($scripts as $script) {
?><script type="text/javascript" src="<?php echo base_url() . $script; ?>"></script>
<?php
    }
}
?>
<script>
    <?php
    echo "var lang_datatables_language = '" . lang("datatables_language") . "';"
    ?>
</script>
</body>

</html>