Start Building Professional
Web Apps Today


 
Categories Question details Back To List
Question  posted by David Hutchings on Nov 07, 2008 12:54
open dhtmlx forum
Header Context Menu Added

We requried that a grid have a context menu linked to one of several header rows. Our goals were to:

- Allow a more visible method of sorting a column in either ASC or DESC direction (assuming sorting is enabled)
- Allow the user to show/hide only certain columns (enableHeaderMenu doesn't seem to support this and resulted in a menu that wasn't very customizeable)
- Allow the user to group by certain columns from within the grid

Below are the changes we made, which were built off the "enableContextMenu" functionality. All changes were made in the main dhtmlxgrid.js file, v.2.0 build 81009.

The first change expands the "_doContClick" function (expanded here for readability):
[code]

this._doContClick=function(ev){
        var el = this.getFirstParentOfType(_isIE ? ev.srcElement : ev.target, "TD");
        if ((!el)||(typeof(el.parentNode.idd)=="undefined")&&(typeof(this._ctmnhdr)!="object"||!this._ctmnhdr[el.parentNode.rowIndex])) return true;
        if (ev.button == 2||(_isMacOS&&ev.ctrlKey)){
            if (!this.callEvent("onRightClick", [el.parentNode.idd,el._cellIndex,ev])){
                var z = function(e){
                    document.body.oncontextmenu=Function("return true;");
                    (e||event).cancelBubble=true;
                    return false
                };
                if (_isIE)ev.srcElement.oncontextmenu=z;else if (!_isMacOS)document.body.oncontextmenu=z;
                return false
            };
            if (this._ctmndx){
                if (!(this.callEvent("onBeforeContextMenu", [el.parentNode.idd,el._cellIndex,this])))return true;
                if (_isIE)ev.srcElement.oncontextmenu=function(){
                    event.cancelBubble=true;
                    return false
                };
                if (this._ctmndx.showContextMenu){
                    this._ctmndx.showContextMenu(ev.clientX-1,ev.clientY-1)
                    this.contextID=el.parentNode.idd+"_"+el._cellIndex;
                    this._ctmndx._skip_hide=true
                }else {
                    el.contextMenuId=el.parentNode.idd+"_"+el._cellIndex;
                    el.contextMenu=this._ctmndx;
                    el.a=this._ctmndx._contextStart;
                    el.a(el, ev);
                    el.a=null
                }
            }
            if (typeof(this._ctmnhdr)=="object"&&this._ctmnhdr[el.parentNode.rowIndex]) {
                if (!(this.callEvent("onBeforeHeaderContextMenu", [el.parentNode.rowIndex,el._cellIndex,this])))return true;
                if (_isIE)ev.srcElement.oncontextmenu=function(){
                    event.cancelBubble=true;
                    return false
                };
                if (this._ctmnhdr[el.parentNode.rowIndex].showContextMenu){
                    this._ctmnhdr[el.parentNode.rowIndex].showContextMenu(ev.clientX-1,ev.clientY-1)
                    this.contextID=el.parentNode.rowIndex+"_"+el._cellIndex;
                    this._ctmnhdr[el.parentNode.rowIndex]._skip_hide=true
                }else {
                    el.contextMenuId=el.parentNode.rowIndex+"_"+el._cellIndex;
                    el.contextMenu=this._ctmnhdr[el.parentNode.rowIndex];
                    el.a=this._ctmnhdr[el.parentNode.rowIndex]._contextStart;
                    el.a(el, ev);
                    el.a=null
                }
            }
        }
        else if (this._ctmndx){
            if (this._ctmndx.hideContextMenu){this._ctmndx.hideContextMenu()}else{this._ctmndx._contextEnd()}
        }
        else if (typeof(this._ctmnhdr)=="object"&&this._ctmnhdr[el.parentNode.rowIndex]){
            if (this._ctmnhdr[el.parentNode.rowIndex].hideContextMenu){this._ctmnhdr[el.parentNode.rowIndex].hideContextMenu()}else{this._ctmnhdr[el.parentNode.rowIndex]._contextEnd()}
        };
        return true
    };

[/code]
The above enables a new event - onBeforeHeaderContextMenu - which will return the header index, column index and grid much the same as onBeforeContextMenu does for grid rows.

The only other change required was to add the prototype to enable linking a menu into a specific header index:
[code]

enableContextMenuHeader:function(menu,ind){if (typeof(this._ctmnhdr)!="object")this._ctmnhdr = new Array();this._ctmnhdr[ind]=menu;},

[/code]

Hopefully this will help others and be added to the codebase for future releases!

Thanks,
- Dave
Answer posted by Support on Nov 11, 2008 05:43
It looks as useful addition, we will check possibility of adding it as default functionality in next version of dhtmlxgrid