Welcome to the nuBuilder Forums!

Join our community by registering and logging in.
As a member, you'll get access to exclusive forums, resources, and content available only to registered users.

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

Questions related to customising nuBuilder Forte with JavaScript or PHP.
Post Reply
Paul
Posts: 175
Joined: Mon Aug 25, 2025 6:03 am
Has thanked: 32 times
Been thanked: 5 times

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

Unread post 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); 
}
You do not have the required permissions to view the files attached to this post.
kev1n
nuBuilder Team
Posts: 4601
Joined: Sun Oct 14, 2018 6:43 pm
Has thanked: 77 times
Been thanked: 547 times
Contact:

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

Unread post 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(...)
Paul
Posts: 175
Joined: Mon Aug 25, 2025 6:03 am
Has thanked: 32 times
Been thanked: 5 times

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

Unread post 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();
}
Post Reply