其它
·BJ-FANUC
【实战】xGird,来自jQuery的神器(二):xGrid是如何炼成的?
字数 17685阅读 5363评论 0赞 3
之前的一节中,大家应该已经体验到了xGrid这个控件的强大之处,xGird实际上部分地解决了Domino上的两大难题:1、检索,特别是复杂检索的性能,xGrid的检索是可以针对已经下载到缓存中的数据进行的,因此它不仅远远比Domino的FTSearch快,同时也比SQL快!但请注意,在大数据量的情况下,一次性加载也是需要一定的耗时的。
2、分类,OpenNTF上的这个xGrid的例子支持一级分类,但xGrid实际上可以做到多级分类,而且xGrid和dojo.Grid不一样,使用过dojo.Grid的同学应该有感觉,虽然同样是支持json数据的传输,但是如果想做出多级分类,甚至是树形结构的话,dojo.Grid所需要的json数据是一个比较复杂的结构的,产生这样一个结构的json数据要一定的经验和代码量,但xGrid则不一样,它对json的数据格式没有更多的要求,一个简单的2维结构即可(可以理解成是Excel数据,一行一行的),这个的巨大好处是,对于一些应用,你只需要制作一张比较大的视图即可,然后所有的筛选都可以由xGrid完成。
xGrid的确很强大,所以Victor给它冠上了“神器”的称号,这是一个可以大大改变Domino应用的CC,但这个CC为何如此强大?这样的一个CC又是如何设计出来的呢?下面我们将揭开谜底,并希望你能由此受到启发,体会到XPages开发中如何又快又好的设计一个CC。
下面进入正题:
在上一节的回复中,已经有朋友很不满的指出,所谓的xGrid其实是将XPages技术和jqGrid进行了结合,没错!xGrid之所以如此强大的原因在于它基于一个强大的jQuery Plugins--jqGrid,对此Victor绝对没有任何想隐藏的,从我们的题目中,Victor其实已经透露了xGrid来自于jQuery,呵呵。
jqGrid的官方网站为:http://www.trirand.com
另外还有一个非常帮的Demo站点,它的价值更高,在它的上面,你可以对jqGrid的整体功能有一个直观的体验:http://www.trirand.com/blog/jqgrid/jqgrid.html
在继续下面的内容之前,Victor强烈建议大家首先花一点时间在jqGrid Demo站点上完整的浏览体会一下,这很重要,因为Victor想说jqGrid能实现的所有功能,在xGrid都可以实现,我们的第4节的内容就将在xGrid原作者的基础上的,对xGrid进行增强,以实现多级分类和添加、编辑、删除功能,因此大家可以先对jqGrid的所有功能都有一个了解,然后既可以自己直接着手研究如何把jqGrid所有的功能都扩展到xGrid上来,也可以在我们结束了第4节的实战后来进行自己的扩展。另外就是,jqGrid的API真的是非常丰富,不首先对jqGrid的API有一个了解,正版的xGrid可能都吃不透,何况是自己再进行扩展?最后请注意,目前最新的jqGrid版本已经是4.4.1了,Victor第4节的实战内容将以4.4.1为基础,但正版的xGrid应该是4.3.x的版本,例如多层分类的功能在4.4.0之前是没有的。
下面我们从jqGrid上取一段Demo演示的代码,它是jqGrid的一个最基本应用,展示的链接地址是:
首先,Victor申明一点,我无法这里解说jQuery的语法,以及jqGrid的API,学习jQuery的话,国内有一本非常棒的书《锋利的jQuery》,现在已经是第二版了,而且实话实说jQuery的语法真心是比较容易和简洁的;而jqGrid的API,大家可以从jqGrid的官网上进行查询,也可以通过Demo站点一点点摸索,Victor就不做无谓的工作了。
- jQuery("#list2").jqGrid({
- url:'server.php?q=2',
- datatype: "json",
- colNames:['Inv No','Date', 'Client', 'Amount','Tax','Total','Notes'],
- colModel:[
- {name:'id',index:'id', width:55},
- {name:'invdate',index:'invdate', width:90},
- {name:'name',index:'name asc, invdate', width:100},
- {name:'amount',index:'amount', width:80, align:"right"},
- {name:'tax',index:'tax', width:80, align:"right"},
- {name:'total',index:'total', width:80,align:"right"},
- {name:'note',index:'note', width:150, sortable:false}
- ],
- rowNum:10,
- rowList:[10,20,30],
- pager: '#pager2',
- sortname: 'id',
- viewrecords: true,
- sortorder: "desc",
- caption:"JSON Example"
- });
- jQuery("#list2").jqGrid('navGrid','#pager2',{edit:false,add:false,del:false});
复制代码
下面我们用designer打开ccxGrid,你应该在设计区域可以看到如图中所示的一个类似于卷子,或者专业点说是类似于脚本的一个标志,选中它,对了别忘了上一节的内容,你可以通过左小角的outline看到自己选中的是什么元素,这样下次的时候,你可以通过outline更快地选定这个设计元素,通过outline我们知道了这个设计元素的类型是Output script,在右边的控件栏里你很有可能找不到这个控件,不要着急,我们后面会介绍如何加入这个设计元素,并且这个设计元素的作用是什么。
现在你需要注意的是在Output script这个设计元素的All properties里有一个value值,貌似里面有一些值看起来像是jQuery代码,选中value值,然后点击如图中的按钮,
你可以打开一个代码编辑框,看到如下的代码:
- $().ready(function(){
- jQuery("#listxGrid").jqGrid({
- url:'#{javascript:compositeData.url}',
- datatype: "json",
- colNames:#{javascript:compositeData.colNames},
- colModel:#{javascript:compositeData.colModel},
- jsonReader: {
- repeatitems: false,
- id: '#{javascript:compositeData.colID}',
- root: function (obj) {
- if ($.isArray(obj)) return obj;
- if ($.isArray(obj.items)) return obj.items;
- return [];
- },
- page: function () { return 1; },
- total: function () { return 1; },
- records: function (obj) {
- if ($.isArray(obj)) return obj.length;
- if ($.isArray(obj.items)) return obj.items.length;
- return 0;
- }
- },
- gridview: true,
- loadonce: #{javascript:compositeData.loadOnce},
- ignoreCase: #{javascript:compositeData.ignoreCase},
- rowNum: #{javascript:compositeData.rowNum},
- rowList: #{javascript:compositeData.rowList},
- rownumbers: #{javascript:compositeData.showRowNumbers},
- height: #{javascript:compositeData.height},
- caption: '#{javascript:compositeData.caption}',
- pager: '#pagerxGrid',
- viewrecords: true,
- emptyrecords: '#{javascript:compositeData.emptyRecords}',
- sortable:#{javascript:compositeData.allowReorder},
- grouping: #{javascript:compositeData.grouping},
- groupingView : {
- groupField : #{javascript:compositeData.groupField},
- groupDataSorted : true,
- groupColumnShow : #{javascript:compositeData.showGroupCol}
- }
- });
- if (#{javascript:compositeData.showFilterToolbar} == true){
- jQuery("#listxGrid").filterToolbar({stringResult: false, defaultSearch: 'cn', searchOnEnter: false});
- $("#listxGrid")[0].toggleToolbar();
- }
- jQuery("#listxGrid").jqGrid('navGrid','#pagerxGrid',{edit:false, add:false, del:false},
- {}, // default settings for edit
- {}, // default settings for add
- {}, // delete
- {closeOnEscape: true, multipleSearch: true, closeAfterSearch: true, showQuery: true, refreshstate:'current'} // search options
- );
- if (#{javascript:compositeData.showFilterToolbar} == true){
- jQuery("#listxGrid").filterToolbar({stringResult: false, defaultSearch: 'cn', searchOnEnter: false});
- jQuery("#listxGrid").jqGrid('navButtonAdd', "#pagerxGrid",{
- caption: "",
- title: "Toggle Search Bar",
- buttonicon: 'ui-icon-pin-s',
- onClickButton: function () {
- $("#listxGrid")[0].toggleToolbar()
- }
- });
- }
- jQuery("#listxGrid").jqGrid('navButtonAdd','#pagerxGrid',{
- caption: "",
- title: "Reorder Columns",
- onClickButton : function (){
- jQuery("#listxGrid").jqGrid('columnChooser');
- }
- });
- function editLinkFmatter(cellvalue, options, rowObject) {
- return "<a target='#{javascript:compositeData.target}' href='./#{javascript:compositeData.xpName}?documentId=" + rowObject["@unid"] +
- "&action=#{javascript:compositeData.action}' class='doclink'>" + cellvalue + "";
- }
- var myid = $("[id$=cbGroupingOptions]");
- jQuery(myid).change(function(){
- var vl = $(this).val();
- if(vl) {
- if(vl == "clear") {
- jQuery("#listxGrid").jqGrid('groupingRemove',true);
- } else {
- jQuery("#listxGrid").jqGrid('groupingGroupBy',vl);
- }
- }
- });
- });
复制代码 请比较一下这段代码和上面的jqGridDemo站点的代码的区别,不是太大吧?而且不管你是不是有jQuery的基础,甚至是否使用过jqGrid,我相信你都能看出来实际上xGrid的这个地方就是jqGrid代码,只不过比如url的这行代码中,jqGrid的Demo例子是:而xGrid是:- url:'#{javascript:compositeData.url}',
复制代码
好了,到目前为止出现了3个关键知识点,我们来总结说明一下,然后再继续,首先是上一节提到的compositeData,如果你回忆不起来的话,请参考上一节最后那部分的内容:http://www.lotuschina.net/club/thread-3058-1-1.html对于XPages的学习而言,没有搞明白CC的Custom Proerties和compositeData,那真的是连门都没入!第二个知识点是Output script,先说说它的作用吧,它其实就类似于在html中写了一个内置javascript,只不过Output script是XPages的内置javascript,XPages会自动将Output script中的value值内容视作内置javascript,因此你可以在Output script中书写客户端的Javascript,一般我们在XPages的开发中,将服务器端Javascript成为SSJS,而将客户端Javascript称为CSJS,请记住Output script中书写的CSJS,不是SSJS,这也是为什么我们可以直接将jqGrid的代码直接放到XPages(或者说是放到ccxGrid这个控件中来了);那么接下来的问题就是,右边的控件里没有Output script元素,我如何在CC或XPages里增加一个Output script呢?我们切换到Source模式下,看一眼就明白了,我们在手工添加了这个标签后,XPages会自动解析为Output script,正如我在介绍XPages时提到的,XPages基于JSF技术,是IBM在JSF基础上做的扩展标签,而XPages Extension Library是xe,另外还有xc,大家以后也会遇到。
第三个知识点应该有一些同学已经意识到了,既然是CSJS,那compositeData这个SSJS的对象是如何成功被使用的?我们再一次比较一下Demo的代码和xGrid的代码的区别:- url:'#{javascript:compositeData.url}',
复制代码 这是一个非常用的技巧,它使得你可以在CSJS中调用SSJS,compositeData.url是货真价实的SSJS,但当我们在CSJS中先用#{javascript:}声明后,compositeData.url就可以被XPages成功理解了!这个技术不是Victor发明的,我最先学习到这个技术的是在John Mackey的博客上:http://www.jmackey.net/groupwareinc/johnblog/johnblog.nsf/d6plinks/GROC-7GLFZG,所以暂且可以认为是John Mackey发明者中用法,大家也可以好好看看John Mackey的Blog,他是XPages的大神之一。从CSJS中调用SSJS是XPages开发必须会的一个好用技巧啊,一定要把这篇Blog看完后好好消化一下!
好了,三个知识点我们都理解完了,那接下来,我们切换到Source模式下看一眼ccxGrid的完整代码。就如你看到的那样,除去Output script部分,整个CC中的代码量很小(出去开头结尾,只剩下JS和CSS的引入,以及一个简单的布局了),因此核心的内容就是Output script中的内容,而前面我们也提到了Output script中的代码基本就是根据标准的jqGrid代码写的,而唯一要注意的就是,千万不要把值写死,而是应该尽可能统统转换为compositeData.xxx,然后在ccxGrid中定义xxx为Property Definition!这样一个高度可重用的CC就产生了!对,Victor说的是一个高度可重用的CC,而不仅仅是xGrid哦,从xGrid这个例子中,我们可以发现,所有jQuery插架都可以被转换为类似于xGrid这样的CC,实际上所有的dojo插件,ext插件,一切一切基于JS实现的插件都可以被我们CC化掉,然后我们就可以在自己的实际业务中使用,这是Victor向大家强烈推荐的将XPages技术和Web开发技术相结合的最佳模式,再比如前几天论坛上就有一个朋友问我在XPages上如何用div画一个对话框,然后如何呼出,然后如何绑定事件等等...Victor没有其他的意思,但是XPages的开发不应该是这个思路,因为你很难做出一个产品级别的对话框功能来,更别说像xGrid这样利用CC来模块化了,但实际上jQuery也好,dojo也好,其他框架也好都与非常好用的对话框功能,XPages的开发思路应该是如何在这些对话框中选取一个最好的,然后利用CC模块化之!比如我就推荐jQuery的Boxy,大家可以google一下之后,试试自己能不能把它CC化掉,有了这个对话框,你的XPages应用可以说又上了一个台阶。
好了,这节已经向大家介绍说明了xGrid是如何基于jqGrid设计出来的,并且结合内容介绍了Output script以及CSJS中调用SSJS这两个技术点,而最重要的实际上是Victor把自己开发XPages应用的开发思路推荐给了大家,Custom Control的存在使得我们可以讲一个东西模块化,因此XPages开发的思路和以前的传统开发思路会有较大的不同,我们不应该再自己造很多不能模块化的代码,而应该利用好CC的特性来选取成熟的控件,甚至是产品来进行CC化(不过要注意版权哦,万一侵权了Victor可不负责),当然,如果你们有足够的人力物力保证自主能实现一个产品级别的CC的话,可以完全鄙视并忽略Victor的这种思路。看起来xGrid的介绍已经要结束了,但其实还有一个更重头的内容没有引出,NSF中的数据是如何被传递给了我们的ccxGrid?我们在这节中多次提到了一行代码:- url:'#{javascript:compositeData.url}',
复制代码 而在xGrid的Demo库中,我们会发现ContactsSSJS.xsp的配置中,这个url是指向了另一个.xsp,事实上就是这个.xsp负责将NSF的数据返回给了ccxGrid,那么这个.xsp是如何完成了这项工作呢?请关注我们的下一节会介绍的更加精彩的内容,同时也是本系列实战中,可能最有价值的一节内容:【实战】xGird,来自jQuery的神器(三):JSON、REST和XAgent 如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!
赞3
添加新评论0 条评论