Page 1 of 1

Prevent nubuilder from going to the record when hyperlink is clicked in Browse form

Posted: Mon Oct 13, 2025 3:52 pm
by Paul
I want nuBuilder to NOT open the record when clicking on a hyperlink in the Browse form.
click-hyperlink.png
but its not working. I got the added code from ChatGPT and I already tried asking ChatGPT several times for fixed code, but none of it is working.
No errors are presented.

Here is my Browse js code:

Code: Select all

// Prevent duplicate initialization
if (!window.hyperlinkColumnsInitialized) {
    window.hyperlinkColumnsInitialized = true;

    // =====================================
    // Define hyperlink column names (editable)
    // =====================================
    const hyperlinkColumnNames = ['All Audio Zip File', 'All Video Zip File', 'All Photo Zip File', 'All History Zip File', 'Audio 1 URL', 'Audio 2 URL','Audio 3 URL','Audio 4 URL','Audio 5 URL','Audio 6 URL','Audio 7 URL','Audio 8 URL','Audio 9 URL','Audio 10 URL','Photo 1 URL','Photo 2 URL','Photo 3 URL','Photo 4 URL','Photo 5 URL','Photo 6 URL','Photo 7 URL','Photo 8 URL','Photo 9 URL','Photo 10 URL','Video 1 URL','Video 2 URL','Video 3 URL','Video 4 URL','Video 5 URL','Video 6 URL','Video 7 URL','Video 8 URL','Video 9 URL','Video 10 URL'];

    // =====================================
    // Resolve column names to their indexes
    // =====================================
    function getColumnIndexesByNames(names) {
        const indexes = [];
        const headers = document.querySelectorAll('#nuRECORD .nuBrowseTitle');

        names.forEach(name => {
            for (let i = 0; i < headers.length; i++) {
                const headerText = headers[i].textContent.trim().toLowerCase();
                if (headerText === name.toLowerCase()) {
                    indexes.push(i);
                    break;
                }
            }
        });

        return indexes;
    }

    // Get the resolved indexes dynamically
    const hyperlinkColumns = getColumnIndexesByNames(hyperlinkColumnNames);



// =====================================
// Make URLs in hyperlink columns clickable (open in new tab), prevent record/row open
// =====================================
function nuOnLoad() {
    const browseDiv = document.getElementById('nuRECORD');
    if (!browseDiv) return;

    browseDiv.addEventListener('click', function (e) {
        const cell = e.target.closest('.nuCell');
        if (!cell) return;

        const colIndex = parseInt(cell.getAttribute('data-nu-column'));
        if (!hyperlinkColumns.includes(colIndex)) return;

        const url = cell.textContent.trim();
        if (!url) return;

        // Prevent nuBuilder from following the row link
        e.preventDefault();
        e.stopPropagation();

        // Open link in new tab
        window.open(url, '_blank');
    }, true); 
}







    // =====================================
    // Column hide/show logic
    // =====================================

    function hideColumns(cols) {
        cols.forEach(i => nuSetBrowseColumnSize(i, 0));
    }

    function showColumns(cols) {
        cols.forEach(i => nuSetBrowseColumnSize(i, 'auto'));
    }

    // Hide columns by default (non-admins only)
    if (!nuGlobalAccess()) {
        hideColumns(hyperlinkColumns);
    
}
    // =====================================
    // Hook into nuPrint()
    // =====================================

    (function() {
        if (!window.nuPrintWrapped) {
            window.nuPrintWrapped = true;
            const originalNuPrint = window.nuPrint;

            window.nuPrint = function() {
                // Before print: show hyperlink columns
                showColumns(hyperlinkColumns);

                // Call original print
                originalNuPrint();

                // Re-hide columns after print
                setTimeout(() => {
                    if (!nuGlobalAccess()) hideColumns(hyperlinkColumns);
                }, 0);
            };
        }
    })();

    // =====================================
    // Hide blank columns logic (unchanged)
    // =====================================

    if (!nuGlobalAccess()) {
        var columnIndex = 0;
        nuSetBrowseColumnSize(columnIndex, 0);
    }

    {
        const hiddenColumns = hideBlankColumns();

        if (!nuGlobalAccess()) var columnIndex = 0;

        const columnsToExclude = [...new Set([columnIndex, ...hiddenColumns])];
        nuPrintExcludeColumns(columnsToExclude);
    }

    function hideBlankColumns() {
        const hiddenColumns = [];
        const browseDiv = document.getElementById('nuRECORD');
        if (!browseDiv) return hiddenColumns;

        const headers = browseDiv.querySelectorAll('.nuBrowseTitle');
        if (headers.length === 0) return hiddenColumns;

        const colCount = headers.length;
        const isColumnBlank = new Array(colCount).fill(true);
        const dataCells = browseDiv.querySelectorAll('.nuCell[data-nu-column]');

        dataCells.forEach(cell => {
            const colIndex = parseInt(cell.getAttribute('data-nu-column'));
            const content = cell.textContent.trim();
            if (content !== '' && colIndex >= 0) isColumnBlank[colIndex] = false;
        });

        for (let j = 0; j < colCount; j++) {
            if (isColumnBlank[j]) {
                nuSetBrowseColumnSize(j, 0);
                hiddenColumns.push(j);
            }
        }
        return hiddenColumns;
    }
}
This snippet in particular, is the code in question:

Code: Select all

// =====================================
// Make URLs in hyperlink columns clickable (open in new tab), prevent record/row open
// =====================================
function nuOnLoad() {
    const browseDiv = document.getElementById('nuRECORD');
    if (!browseDiv) return;

    browseDiv.addEventListener('click', function (e) {
        const cell = e.target.closest('.nuCell');
        if (!cell) return;

        const colIndex = parseInt(cell.getAttribute('data-nu-column'));
        if (!hyperlinkColumns.includes(colIndex)) return;

        const url = cell.textContent.trim();
        if (!url) return;

        // Prevent nuBuilder from following the row link
        e.preventDefault();
        e.stopPropagation();

        // Open link in new tab
        window.open(url, '_blank');
    }, true); 
}

Re: Prevent nubuilder from going to the record when hyperlink is clicked in Browse form

Posted: Tue Oct 14, 2025 3:41 am
by kev1n
nuSelectBrowse() might be the answer: Check if the clicked cell contains a hyperlink and then return false, otherwise open the form in edit mode with nuForm(...)

Re: Prevent nubuilder from going to the record when hyperlink is clicked in Browse form

Posted: Tue Oct 14, 2025 8:38 am
by Paul
After several attempts/re-writes with ChatGPT, AI finally got it working for me!

I hope others find at least some of this code useful.

Code: Select all

// Prevent duplicate initialization
if (!window.hyperlinkColumnsInitialized) {
    window.hyperlinkColumnsInitialized = true;

    // =====================================
    // Define hyperlink column names (editable)
    // =====================================
    const hyperlinkColumnNames = [
        'All Audio Zip File', 'All Video Zip File', 'All Photo Zip File', 'All History Zip File',
        'Audio 1 URL', 'Audio 2 URL','Audio 3 URL','Audio 4 URL','Audio 5 URL','Audio 6 URL',
        'Audio 7 URL','Audio 8 URL','Audio 9 URL','Audio 10 URL',
        'Photo 1 URL','Photo 2 URL','Photo 3 URL','Photo 4 URL','Photo 5 URL','Photo 6 URL',
        'Photo 7 URL','Photo 8 URL','Photo 9 URL','Photo 10 URL',
        'Video 1 URL','Video 2 URL','Video 3 URL','Video 4 URL','Video 5 URL','Video 6 URL',
        'Video 7 URL','Video 8 URL','Video 9 URL','Video 10 URL'
    ];

    // =====================================
    // Resolve column names to their indexes
    // =====================================
    function getColumnIndexesByNames(names) {
        const indexes = [];
        const headers = document.querySelectorAll('#nuRECORD .nuBrowseTitle');
        names.forEach(name => {
            for (let i = 0; i < headers.length; i++) {
                const headerText = headers[i].textContent.trim().toLowerCase();
                if (headerText === name.toLowerCase()) {
                    indexes.push(i);
                    break;
                }
            }
        });
        return indexes;
    }

    const hyperlinkColumns = getColumnIndexesByNames(hyperlinkColumnNames);

    // =====================================
    // Column hide/show logic
    // =====================================
    function hideColumns(cols) {
        cols.forEach(i => nuSetBrowseColumnSize(i, 0));
    }

    function showColumns(cols) {
        cols.forEach(i => nuSetBrowseColumnSize(i, 'auto'));
    }

    // =====================================
    // Main browse click handler
    // =====================================
    function nuOnLoad() {
        const browseDiv = document.getElementById('nuRECORD');
        if (!browseDiv) return;

        if (!browseDiv.dataset.hyperlinkHandlerBound) {
            browseDiv.dataset.hyperlinkHandlerBound = true;

            // Capture phase so it runs before nuSelectBrowse
            browseDiv.addEventListener('click', function (e) {
                const cell = e.target.closest('.nuCell');
                if (!cell) return;

                const colIndex = parseInt(cell.getAttribute('data-nu-column'));
                if (!hyperlinkColumns.includes(colIndex)) return;

                // Check for <a> link first
                const link = cell.querySelector('a[href]');
                if (link && link.href) {
                    e.stopImmediatePropagation();
                    e.preventDefault();
                    window.open(link.href, '_blank');
                    return;
                }

                // Then check for plain text URL
                const text = cell.textContent.trim();
                if (!text) return;

                const urlPattern = /^(https?:\/\/|www\.)[^\s]+$/i;
                if (urlPattern.test(text)) {
                    e.stopImmediatePropagation();
                    e.preventDefault();
                    const url = text.startsWith('http') ? text : 'https://' + text;
                    window.open(url, '_blank');
                }
            }, true);
        }

        // Hide hyperlink columns for non-admins
        if (!nuGlobalAccess()) {
            hideColumns(hyperlinkColumns);
        }
    }

    // =====================================
    // Hook into nuPrint()
    // =====================================
    (function() {
        if (!window.nuPrintWrapped) {
            window.nuPrintWrapped = true;
            const originalNuPrint = window.nuPrint;

            window.nuPrint = function() {
                // Show hyperlink columns before print
                showColumns(hyperlinkColumns);

                // Print
                originalNuPrint();

                // Hide again after print
                setTimeout(() => {
                    if (!nuGlobalAccess()) hideColumns(hyperlinkColumns);
                }, 200);
            };
        }
    })();

    // =====================================
    // Hide blank columns logic
    // =====================================
    if (!nuGlobalAccess()) {
        var columnIndex = 0;
        nuSetBrowseColumnSize(columnIndex, 0);
    }

    {
        const hiddenColumns = hideBlankColumns();

        if (!nuGlobalAccess()) var columnIndex = 0;

        const columnsToExclude = [...new Set([columnIndex, ...hiddenColumns])];
        nuPrintExcludeColumns(columnsToExclude);
    }

    function hideBlankColumns() {
        const hiddenColumns = [];
        const browseDiv = document.getElementById('nuRECORD');
        if (!browseDiv) return hiddenColumns;

        const headers = browseDiv.querySelectorAll('.nuBrowseTitle');
        if (headers.length === 0) return hiddenColumns;

        const colCount = headers.length;
        const isColumnBlank = new Array(colCount).fill(true);
        const dataCells = browseDiv.querySelectorAll('.nuCell[data-nu-column]');

        dataCells.forEach(cell => {
            const colIndex = parseInt(cell.getAttribute('data-nu-column'));
            const content = cell.textContent.trim();
            if (content !== '' && colIndex >= 0) isColumnBlank[colIndex] = false;
        });

        for (let j = 0; j < colCount; j++) {
            if (isColumnBlank[j]) {
                nuSetBrowseColumnSize(j, 0);
                hiddenColumns.push(j);
            }
        }
        return hiddenColumns;
    }

    // Initialize after browse load
    nuOnLoad();
}