自定义dhtmlxGrid表头菜单

简介:

dhtmlxGrid可以定义表头菜单以及表格右键菜单,表格右键菜单可以自定义,但是表头菜单只能使用其提供的菜单。dhtmlxGrid默认的表头菜单可以决定表格中每一列是否在表格中显示,并没有提供更多的扩展,如果我想自定义表头菜单,该怎么做呢?本文就是基于自定义表格菜单,说说我的实现方式。 以下是dhtmlxGrid的表头菜单效果:

其功能过于单一,以下是表格右键菜单效果:

如果能够像表格菜单一样自定义表头菜单,那会是一件非常有意义的事情,因为dhtmlxGrid菜单都是一些针对行和单元格的操作,没有提过针对列的操作,比如我可能需要在某一列上实现该列的显示与隐藏、排序、改变列属性以及在该列右边添加一新的列,等等。 如何实现表头菜单的自定义呢?可不可将表格右键菜单移到表头上去呢? 首先,来看看context menu的实现方式,下面代码来自dhtmlxGrid Samples中的Context menu例子源码:

function onButtonClick(menuitemId, type) {
    var data = mygrid.contextID.split("_");
    //rowId_colInd;
    mygrid.setRowTextStyle(data[0], "color:" + menuitemId.split("_")[1]);
    return true;
}
menu = new dhtmlXMenuObject();
menu.setIconsPath("../common/images/");
menu.renderAsContextMenu();
menu.attachEvent("onClick", onButtonClick);
menu.loadXML("../common/_context.xml");
mygrid = new dhtmlXGridObject('gridbox');
mygrid.setImagePath("../../codebase/imgs/");
mygrid.setHeader("Author,Title");
mygrid.setInitWidths("250,250");
mygrid.enableAutoWidth(true);
mygrid.setColAlign("left,left");
mygrid.setColTypes("ro,link");
mygrid.setColSorting("str,str");
mygrid.enableContextMenu(menu);
mygrid.init();
mygrid.setSkin("dhx_skyblue");
mygrid.loadXML("../common/grid_links.xml");

上面代码创建了一个menu并将其作为context menu附件到grid上面去,下面为最关键的两行行代码:

menu.renderAsContextMenu();
mygrid.enableContextMenu(menu);

上面对于context menu提供的方法太少,这时候可以看看dhtmlxMenu api,看看有没有设置context menu生效位置的方法(指定context menu在哪片区域有效)。在dhtmlxMenu API Methods里没有找到需要的方法,这时候在官网论坛搜搜,也许可以找到点什么。 在论坛里可以找到一个例子,大致代码如下:

function onButtonClick(menuitemId, type) {
    var data = mygrid.contextID.split("_");
    //rowId_colInd;
    mygrid.setRowTextStyle(data[0], "color:" + menuitemId.split("_")[1]);
    return true;
}
menu = new dhtmlXMenuObject();
menu.setIconsPath("../common/images/");
menu.attachEvent("onClick", onButtonClick);
menu.loadXML("../common/_context.xml");

mygrid = new dhtmlXGridObject('gridbox');
mygrid.setImagePath("../../codebase/imgs/");
mygrid.setHeader("Author,Title");
mygrid.setInitWidths("250,250");
mygrid.enableAutoWidth(true);
mygrid.setColAlign("left,left");
mygrid.setColTypes("ro,link");
mygrid.setColSorting("str,str");
//mygrid.enableContextMenu(menu); //使其失效
mygrid.init();
mygrid.setSkin("dhx_skyblue");
mygrid.loadXML("../common/grid_links.xml");

mygrid.hdr.id = "header_id";
var header_row = mygrid.hdr.rows[1];
for ( var i = 0; i < header_row.cells.length; i++) {
   header_row.cells[i].id = "context_zone_" + i;
}
menu.addContextZone("header_id");

上面最关键的代码在最后几行,给dhtmlxGrid表头设置了一个id,然后调用menu的addContextZone()方法指定centext的有效区域。视乎这就是我们所需要的,但是你执行以上代码你会发现onButtonClick方法里mygrid.contextID会报错,原因是mygrid没有contextID属性(在context menu中通过该属性可以获知鼠标焦点在哪一行,但是现在在表头上强加了该menu,所以并不存在该属性了)。 剩下的问题是需要解决,菜单单击事件了。我们可以在表头的contextmenu事件处罚的时候获取鼠标焦点,并将自定义的菜单在该位置显示,该方法如下:

dhtmlxEvent(mygrid.hdr, "contextmenu", function(ev) {
	ev = ev || event;
	var el = ev.target || ev.srcElement;
	var zel = el;
	while (zel.tagName != "TABLE")
		zel = zel.parentNode;
	var grid = zel.grid;
	if (!grid)
		return;
	grid.setActive();

	el = grid.getFirstParentOfType(el, "TD")

	if ((grid) && (!grid._colInMove)) {
		grid.resized = null;
		if ((!grid._mCols) || (grid._mCols[el._cellIndex] == "true"))
			colId = el._cellIndex + 1;//获得表头右键菜单焦点所在列索引
	}

	function mouseCoords(ev) {
		if (ev.pageX || ev.pageY) {
			return {
				x : ev.pageX,
				y : ev.pageY
			};
		}
		var d = _isIE && document.compatMode != "BackCompat" ? 
	            document.documentElement: document.body;
		return {
			x : ev.clientX + d.scrollLeft - d.clientLeft,
			y : ev.clientY + d.scrollTop - d.clientTop
		};
	}

	var coords = mouseCoords(ev);
	menu.addContextZone("header_id");
	menu.showContextMenu(coords.x, coords.y);//强制显示
	return true;
});

在上面的代码里,我们获得表头右键菜单焦点所在列索引,将其值赋给colId,然后在菜单单击事件的时候添加一新的列并将colId重置:

function onButtonClick(menuitemId, type, e) {
	mygrid.insertColumn(colId, "12", "ed", 80);
	colId = 0;
	return true;
}

然后,需要禁止掉表格数据区域的菜单显示:

mygrid.attachEvent("onBeforeContextMenu", function(rid, cid, e) {
	return false;//禁止数据区域菜单
});

最后的最后,最后的代码如下:

var mygrid, colId;

function onButtonClick(menuitemId, type, e) {
	mygrid.insertColumn(colId, "12", "ed", 80);
	colId = 0;
	return true;
}

menu = new dhtmlXMenuObject();
menu.setIconsPath("../common/images/");
menu.renderAsContextMenu();
menu.attachEvent("onClick", onButtonClick);
menu.loadXML("../common/_context.xml");
menu.attachEvent("onBeforeContextMenu", function(zoneId, e) {
	var hdr = document.getElementById(zoneId)
	return true;
});

mygrid = new dhtmlXGridObject('gridbox');
mygrid.setImagePath("../codebase/imgs/");
mygrid.setHeader("Sales,Book Title,Author,Price,In Store,Shipping,Bestseller,
          Date of Publication");
mygrid.setInitWidths("50,150,100,80,80,80,80,200");
mygrid.setColAlign("right,left,left,right,center,left,center,center");
mygrid.setColTypes("dyn,edtxt,ed,price,ch,co,ra,ro");

mygrid.init();
mygrid.setSkin("dhx_skyblue");
//mygrid.enableHeaderMenu();
mygrid.enableColumnMove(true);
mygrid.enableContextMenu(menu);
dhtmlxEvent(mygrid.hdr, "contextmenu", function(ev) {
	ev = ev || event;
	var el = ev.target || ev.srcElement;
	var zel = el;
	while (zel.tagName != "TABLE")
		zel = zel.parentNode;
	var grid = zel.grid;
	if (!grid)
		return;
	grid.setActive();

	el = grid.getFirstParentOfType(el, "TD")

	if ((grid) && (!grid._colInMove)) {
		grid.resized = null;
		if ((!grid._mCols) || (grid._mCols[el._cellIndex] == "true"))
                            //获得表头右键菜单焦点所在列索引
			colId = el._cellIndex + 1;
	}

	function mouseCoords(ev) {
		if (ev.pageX || ev.pageY) {
			return {
				x : ev.pageX,
				y : ev.pageY
			};
		}
		var d = _isIE && document.compatMode != "BackCompat" ? 
                         document.documentElement: document.body;
		return {
			x : ev.clientX + d.scrollLeft - d.clientLeft,
			y : ev.clientY + d.scrollTop - d.clientTop
		};
	}

	var coords = mouseCoords(ev);
	menu.addContextZone("header_id");
	menu.showContextMenu(coords.x, coords.y);//强制显示
	return true;
});

mygrid.attachEvent("onBeforeContextMenu", function(rid, cid, e) {
	return false;//禁止数据区域菜单
});

mygrid.loadXML("../common/grid_ml_16_rows_columns_manipulations.xml");

mygrid.hdr.id = "header_id";
var header_row = mygrid.hdr.rows[1];
for ( var i = 0; i < header_row.cells.length; i++) {
	header_row.cells[i].id = "context_zone_" + i;
}

效果图如下;

目录
相关文章
|
算法 数据挖掘 Go
文献速读|5分生信+免疫组化单细胞联合bulk转录组肿瘤预后模型
研究摘要: 在《Cancer Immunology Immunotherapy》上发表的一篇文章,通过整合Bulk和单细胞RNA-seq数据,探讨了非小细胞肺癌(NSCLC)中癌相关纤维细胞(CAF)的作用。研究者识别出CAF的预后标志物,构建了一个基于CAF的模型,该模型在四个独立队列中区分了预后良好的和较差的患者。WGCNA分析鉴定出CAF标记基因,而CAF分数与免疫微环境和免疫治疗反应相关。高CAF分数关联较差的免疫治疗反应,FBLIM1被发现为CAF的主要来源,其高表达预测了免疫疗法的不良反应。该研究揭示了CAF在NSCLC免疫抑制和治疗策略中的重要地位。
362 1
|
存储 前端开发 JavaScript
医院电子病历编辑器源码 (java语言)
电子病历(EMR,Electronic Medical Record)是用电子技术保存、管理、传输和重现的数字化的病人的医疗记录,取代手写纸张病历,将医务人员在医疗活动过程中,使用医疗机构管理系统生成的文字、符号、图表、图形、数据、影像等数字化内容,并能实现存储、管理、传输和重现的医疗记录,是病历的一种记录形式。
369 1
|
存储 IDE 前端开发
SpringBoot2.x系列教程02--新纪元之SpringBoot创建Web项目的常用方式
前言 在上一章节中,壹哥 给大家介绍了SpringBoot的优缺点,并重点介绍了其”约定大于配置“的思想,你现在还能记得吗? 而且上文中,壹哥 说我们创建SpringBoot项目有3种方式,我们已经学习了第一种创建项目的方式了,接下来还有另外两种创建项目的方式,这两种方式该怎么创建项目呢?今天 壹哥 就把剩余的两种方式也一股脑都抖搂给大家吧。 一. 以官网模板方式创建Web项目(了解) 首先 壹哥 给大家介绍第2种创建Web项目的方式,对于这种方式大家仅做了解即可,其原理与第一种以Spring Initializr创建项目的方式一样。 1. 在spring.io官网下载模板构建项目 首先我们
495 0
|
7月前
|
机器学习/深度学习 人工智能 弹性计算
AI剧本生成与动画创作解决方案评测:这项技术能为短视频创作带来哪些改变?
随着短视频行业的竞争加剧,创作速度和质量成为关键。阿里云的《AI剧本生成与动画创作》解决方案利用NLP和计算机视觉技术,通过简单的关键词或主题自动生成剧本和动画,显著提高创作效率并降低技术门槛。评测显示,该方案能在几小时内完成从剧本到动画的创作,适应市场热点需求。然而,AI在创意表达和细节处理上仍有一定局限性,尤其在高要求创作中表现不如手工精细。尽管如此,对于需要快速响应市场的创作者来说,这一工具无疑是一个巨大的助力,未来有望进一步提升创作灵活性和效率。
291 3
|
11月前
|
前端开发 安全 Android开发
跨平台开发的新纪元:Tauri 2.0 横空出世,移动端、桌面端一网打尽!
Tauri 2.0 正式版于 2024 年 10 月 2 日发布,带来了多项重大更新。此次更新不仅全面支持 iOS 和 Android,实现“一次编写,到处运行”,还升级了插件系统,增强了灵活性与可扩展性。安全性大幅提升,引入新的权限系统,并优化了 IPC 层,支持原始有效载荷传输,大幅提高性能。此外,Tauri 2.0 还支持热模块替换(HMR),简化了应用分发流程,成为跨平台开发的重要里程碑。
1587 0
跨平台开发的新纪元:Tauri 2.0 横空出世,移动端、桌面端一网打尽!
|
存储 安全 测试技术
Postman工具介绍
【6月更文挑战第1天】Postman是一款由Postman公司开发的API开发协作软件,广泛应用于API设计、构建、测试和安全管理。
|
关系型数据库 MySQL
MySQL 的 union 和union all 的区别
【5月更文挑战第4天】MySQL 的 union 和union all 的区别
475 7
|
人工智能 NoSQL atlas
如何用MongoDB Atlas和大语言模型,高效构建企业级AI应用?
利用生成式 AI 强化应用程序为客户打造令人叹服、真正差异化的体验意味着将人工智能建立在事实的基础之上
1991 0
|
负载均衡 NoSQL Java
Spring Boot + Redis 处理 Session 共享
Spring Boot + Redis 处理 Session 共享
154 1