Author Topic: Tool tips on Grpup level columns  (Read 744 times)

pbassey

  • Pro Ultimate
  • Jr. Member
  • *
  • Posts: 59
    • View Profile
Tool tips on Grpup level columns
« on: April 25, 2026, 12:31:50 am »
I have the following grid code:

    var obj = {
        height: 540,
        width: '100%',
        dataModel: {
            location: "remote", //server side call
            dataType: "jsonp",
            method: "GET",
            url: "/APS/Activity/grid_Activity?yearValue=" + theYear + "&sourceValue=" + source, //URL
            getData: function (dataJSON) {
                var data = dataJSON.data;
                return { curPage: dataJSON.curPage, totalRecords: dataJSON.totalRecords, data: data };
            }
        },
        numberCell: { width: 40 },
        freezeCols: 1,
        flex: { one: true },
        rowBorders: false,
        colModel: [
            { dataIndx: 'KeyRec', title: 'KeyRec', hidden: true, editable: false },
            { dataIndx: 'SummKeyRec', title: 'SummKeyRec', hidden: true, editable: false },

            { dataIndx: 'ActivityYear', title: 'ActivityYear', hidden: true, editable: false },

            { dataIndx: 'grp', title: 'ActivityId', tpHide: true, editable: false, menuInHide: true, minWidth: 150 },
            { dataIndx: "ActivityId", title: "FAS Activity", editable: false, hidden: true, filter: { groupIndx: 'Region' } },

            { dataIndx: "Project", title: 'Project Code', valign: "top", editable: false, valign: "top", minWidth: 110 },
            { dataIndx: "Source", title: 'Source', valign: "top", editable: false, valign: "top", minWidth: 70 },
            { dataIndx: "ProjBud", title: 'Project Budget', valign: "top", format: '$ #,###,###.00', editable: false, summary: { type: "sum" }, valign: "top", align: "right", minWidth: 100 },

            {
                dataIndx: "YTD_Tot", title: 'YTD Through<br>@lastMonthName', halign: "center", valign: "top", format: '$ #,###,###.00', style: "background-color: lightyellow;",
                editable: false, summary: { type: "sum" }, valign: "top", align: "right", minWidth: 100, format: '$ #,###,###.00',
                render: function (ui) {
                    try {
                        const formattedAmount = new Intl.NumberFormat('en-US'
                            , { style: 'currency', currency: 'USD' }).format(ui.cellData); //format to USD
                        var ActivityID = ui.rowData.ActivityId;
                        var Project = ui.rowData.Project;
                        var Source = ui.rowData.Source;
                        var link = "";
                        if (doesNotContainUnassigned(Project)) {

                            link = "<span onClick=javascript:OpenTranWindow(" + "'" + ActivityID + "','" + Project + "','History','" + Source + "') style='cursor: pointer;'>"
                                + formattedAmount +
                                "</span>";
                        }
                        else {
                            link = "<span onClick=javascript:OpenTranWindow(" + "'" + ActivityID + "','','History','" + Source + "') style='cursor: pointer;'>"
                                + formattedAmount +
                                "</span>";
                        }


                        return link;
                    } catch (error) {
                        // Code to handle the error
                        //console.error('An error occurred:', error.message);
                        return "";
                    }

                }
            },
            //Define the link for the first month of Projections
            {
                dataIndx: "FirstColumn", title: '@ViewBag.curMonthName', editor: { type: 'textbox', attr: 'maxlength="12"' },
                valign: "top", format: '$ #,###,###.00', editable: true, summary: { type: "sum" }, align: "right", minWidth: 80,
                style: "background-color: lightyellow;",
                render: function (ui) {
                    try {
                        const formattedAmount = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(ui.cellData);
                        var ActivityID = ui.rowData.ActivityId;
                        var Project = ui.rowData.Project;

                        if (Project== null || Project.indexOf("Unassigned") >-1)  {//Project.includes("Unassigned")){
                            Project = '';
                        }
                        var Source = ui.rowData.Source;
                        var link = "<span onClick=javascript:OpenLastMonthWindow(" + "'" + ActivityID + "','" + Project + "','" + Source + "') style='cursor: pointer;'>"
                                + formattedAmount +
                                "</span>";

                        //}

                        return link;
                    } catch (error) {
                        // Code to handle the error
                        console.log('An error occurred:', error.message);
                        return "";
                    }

                }
            },
            {
                title: "Projection Months", align: "center", collapsible: { last: true, on: false },
                colModel: [

                    //Define all subsequent months here
                    @foreach (var month in Model)
                    {
                        @: { dataIndx: "@month.DataIndx", title: '@month.Title', editor: { type: 'textbox', attr: 'maxlength="12"' }, valign: "top", format: '$ #,###,###.00', editable: true, summary: { type: "sum" }, align: "right", minWidth: 80 },
                    }


                    {
                        dataIndx: "TP", title: 'Total<br>Projections', halign: "center", valign: "top", format: '$ #,###,###.00',
                        //style: "background-color: lightyellow;",
                        editable: false, summary: { type: "sum" }, valign: "top", align: "right", minWidth: 100, format: '$ #,###,###.00',
                        render: function (ui) {
                            try {
                                const formattedAmount = new Intl.NumberFormat('en-US'
                                    , { style: 'currency', currency: 'USD' }).format(ui.cellData); //format to USD
                                var ActivityID = ui.rowData.ActivityId;
                                var Project = ui.rowData.Project;
                                var Source = ui.rowData.Source;
                                var link = "";
                                if (doesNotContainUnassigned(Project)) {

                                    link = "<span onClick=javascript:OpenProjWindow(" + "'" + ActivityID + "','" + Project + "','Projections','" + Source + "') style='cursor: pointer;'>"
                                        + formattedAmount +
                                        "</span>";
                                }
                                else {
                                    link = "<span onClick=javascript:OpenProjWindow(" + "'" + ActivityID + "','','Projections','" + Source + "') style='cursor: pointer;'>"
                                        + formattedAmount +
                                        "</span>";
                                }
                                return link;
                                return formattedAmount;
                            } catch (error) {
                                // Code to handle the error
                                console.log('An error occurred:', error.message);
                                return "";
                            }

                        }
                    }
                ]
            },
            { dataIndx: "TPS", title: 'Total<br>Projections<br>Spent', halign: "center", valign: "top", format: '$ #,###,###.00', editable: false, summary: { type: "sum" }, valign: "top", align: "right", minWidth: 90 },
            { dataIndx: "PA", title: 'Projections<br>Available', halign: "center", valign: "top", format: '$ #,###,###.00', editable: false, summary: { type: "sum" }, valign: "top", align: "right", minWidth: 90 },
            {
                dataIndx: "curMonAct", title: '@curMonthName<br>Actual', halign: "center", valign: "top", format: '$ #,###,###.00', style: "background-color: lightyellow;",
                editable: false, summary: { type: "sum" }, valign: "top", align: "right", minWidth: 100, format: '$ #,###,###.00',
                render: function (ui) {
                    try {
                        const formattedAmount = new Intl.NumberFormat('en-US'
                            , { style: 'currency', currency: 'USD' }).format(ui.cellData); //format to USD
                        var ActivityID = ui.rowData.ActivityId;
                        var Project = ui.rowData.Project;
                        var Source = ui.rowData.Source;
                        var link = "";
                        if (doesNotContainUnassigned(Project)) {

                            link = "<span onClick=javascript:OpenTranWindow(" + "'" + ActivityID + "','" + Project + "','Current','" + Source + "') style='cursor: pointer;'>"
                                + formattedAmount +
                                "</span>";
                        }
                        else {
                            link = "<span onClick=javascript:OpenTranWindow(" + "'" + ActivityID + "','','Current','" + Source + "') style='cursor: pointer;'>"
                                + formattedAmount +
                                "</span>";
                        }
                        return link;
                    } catch (error) {
                        // Code to handle the error
                        //console.error('An error occurred:', error.message);
                        return "";
                    }

                }
            }
        ],
        hoverMode: 'cell',
        editor: { select: true, type: 'textbox' },
        trackModel: { on: true },                      //to turn on the track changes.
        editable: true,
        change: function (evt, ui) {
            //saveChanges can also be called from change event.
            var gridChanges = ui.updateList;

            $.ajax({
                url: '/APS/Activity/updatecell',         //for ASP.NET
                data: {
                    list: JSON.stringify(gridChanges)
                },
                dataType: "json",
                type: "POST",
                async: true,
                beforeSend: function (jqXHR, settings) {
                    grid3.option("strLoading", "Saving CCI Projection update, please stand by..");
                    grid3.showLoading();
                },
                success: function (changes) {
                    //commit the changes.
                    grid3.commit({ type: 'update', rows: changes.updateList });
                },
                complete: function () {
                    grid3.hideLoading();
                    $("#grids").pqGrid("refreshDataAndView");

                    grid3.option("strLoading", $.paramquery.pqGrid.defaults.strLoading);
                    grid3.refreshDataAndView();
                }
            });

        },
        destroy: function () {
            //clear the interval upon destroy.
            clearInterval(interval1);
        },
        history: function (evt, ui) {
            var $tb = this.toolbar(),
                $undo = $tb.find("button:contains('Undo')"),
                $redo = $tb.find("button:contains('Redo')");

            if (ui.canUndo != null) {
                $undo.button("option", { disabled: !ui.canUndo });
            }
            if (ui.canRedo != null) {
                $redo.button("option", "disabled", !ui.canRedo);
            }
            $undo.button("option", { label: 'Undo (' + ui.num_undo + ')' });
            $redo.button("option", { label: 'Redo (' + ui.num_redo + ')' });
        },
        groupModel: {
            on: true,                  //grouping mode.
            pivot: false,                //pivotMode
            checkbox: false,
            checkboxHead: true,
            select: false,
            titleIndx: 'grp',             //v7.0.0: new option instead of titleInFirstCol
            indent: 20,
            fixCols: false,
            groupCols: ['Region'],          //grouping along column axis.
            header: false,                //hide grouping toolbar.
            grandSummary: true,          //show grand summary row.
            dataIndx: ['ActivityId'],       //grouping along row axis.
            collapsed: [false],
            useLabel: true,
            summaryEdit: false
        },
        summaryTitle: {
            sum: ""
        },
        postRenderInterval: -1,     //synchronous post render.
        showTitle: false,
        wrap: false,
        hwrap: false,

        toolPanel: {
            show: false             //show toolPanel initially.
        },

        formulas: [
            //["TP", function (rd) {
            //    var tot = eval(Number(rd.Month1) + Number(rd.Month2) + Number(rd.Month3) + Number(rd.Month4) + Number(rd.Month5) + Number(rd.Month6) + Number(rd.Month7) + Number(rd.Month8) + Number(rd.Month9) + Number(rd.Month10) + Number(rd.Month11) + Number(rd.Month12));
            //    return tot;
            //}],
            ["RegVariance", function (rd) {
                var tot = eval(Number(rd.RegTotal) + Number(rd.ActualYTD));
                var variance = eval(Number(rd.RegBudget) - tot);
                return variance;
            }]
        ],
        toolbar: {
            items: [
                {
                    type: 'textbox',
                    label: "Filter: ",
                    attr: 'placeholder="Enter text"',
                    listener: {
                        timeout: function (evt) {
                            var txt = $(evt.target).val();
                            var rules = this.getCMPrimary().map(function (col) {
                                return {
                                    dataIndx: col.dataIndx,
                                    condition: 'contain',
                                    value: txt
                                }
                            })
                            this.filter({
                                mode: 'OR',
                                rules: rules
                            })
                        }
                    }
                },
                {
                    type: 'select',
                    label: 'Export By: ',
                    cls: 'export-format',
                    //options: [{ xlsx: 'Excel', htm: 'Html', pdf: 'PDF', csv: 'Csv' }]
                    options: [{ csv: 'Excel', htm: 'Html' }]
                },
                {
                    type: 'button',
                    label: "Export&nbsp;&nbsp;",
                    icon: 'ui-icon-arrowthickstop-1-s',
                    listener: function () {
                        var grid = this,
                            format = grid.toolbar().find('.export-format').val(),
                            data = grid.exportData({
                                format: format,
                                cssTable: 'border-spacing:0;border-collapse:separate;',
                                cssRules: "td{border:0;}",
                                render: true
                            });

                        // Strip HTML from CSV output (the "Excel" option returns CSV)
                        if (format == 'csv' && typeof data === 'string') {
                            data = stripHtmlFromCsv(data);
                        }

                        if (format == 'pdf') {
                            var dd = {
                                footer: function (currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; },
                                pageOrientation: 'landscape',
                                content: [
                                    {
                                        table: data,
                                        layout: {
                                            hLineColor: '#aaaaaa',
                                            vLineColor: '#aaaaaa'
                                        }
                                    }
                                ]
                            };
                            grid.showLoading();
                            pq.getScripts(['/Scripts/pdfmake/pdfmake.min.js', '/Scripts/pdfmake/vfs_fonts.js'], function () {
                                grid.hideLoading();
                                pdfMake.createPdf(dd).download();
                            })
                        }
                        else {
                            pq.saveAs(data, "pqGrid." + format);
                        }
                    }
                }             
            ]
        },
        //use pivotCM event to make grouped columns collapsible.
        pivotCM: function (evt, ui) {
            //add collapsible to grouped parent columns.
            this.Columns().each(function (col) {
                var cm = col.colModel
                if (cm && cm.length > 1 && !col.collapsible)
                    col.collapsible = { on: true, last: true };
            }, ui.CM);
        }
    };
    var grid3 = pq.grid("#indActivity", obj);

    grid3.option("selectionModel", { type: 'row', mode: 'single' });


...and I would like to have a tooltip popup on the Group level field, ActivityId
            { dataIndx: 'grp', title: 'ActivityId', tpHide: true, editable: false, menuInHide: true, minWidth: 150 },
            { dataIndx: "ActivityId", title: "FAS Activity", editable: false, hidden: true, filter: { groupIndx: 'Region' } },

I would like the dataIndx column, ActivityDescription, to be the source of this tooltip popup whenever I hover over the ActivityID column.  How do I program that??


paramvir

  • Administrator
  • Hero Member
  • *****
  • Posts: 6552
    • View Profile
Re: Tool tips on Grpup level columns
« Reply #1 on: April 25, 2026, 07:38:22 am »
You can achieve this by using the column.render callback to inject a title attribute into the cell, which will then display as a native browser tooltip.

Code: [Select]
render( ui ){
    return {
        //here we inject html title attribute in each cell.
        attr: {
            title: (ui.rowData.ActivityDescription || "" ).replace(/"/g, '&quot;')
        }
    }
}

A quick optimization note:
I noticed you are manually using Intl.NumberFormat within the render callback while column.format is already defined. You can simplify this by using ui.formatVal inside your render function; this provides the already-formatted value based on your column settings, so you don't need to reformat it manually.