我在morningstar的第一项工作,本文作者:唐霜,转载请注明出处。【转载请注明来源】就是构建一个带分栏表头的grid表格。上【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。面的表格中,第一行是父栏,第二行是子栏,【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net第三行开始才是数据。而在table中还要【本文受版权保护】【本文首发于唐霜的博客】实现这样的表头,还是有点麻烦的。
【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】为了构建这种有父子栏的表头,我想到把表格【作者:唐霜】未经授权,禁止复制转载。头部的数据转化为按照table tr t【原创内容,转载请注明出处】【本文受版权保护】d的排列顺序,利用td的colspan,【本文受版权保护】【原创不易,请尊重版权】 rowspan来进行分割的原理,构建一【转载请注明来源】【版权所有】唐霜 www.tangshuang.net个按行分开的数据结果,利用这个数据结果按【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。照table的加载顺序,一个一个td进行转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】渲染。
【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。而我们拿到的原始数据往往是像下面这样的:
本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net【作者:唐霜】[
{"id":"a2","pid":"","name":"Name",type:"tree",align:"left","dataType":"VARCHAR"},
{"id":"a3","pid":"","name":"Ticker",type:"ro",align:"left","dataType":"VARCHAR"},
{"id":"a4","pid":"","name":"Inception Date",type:"ro",align:"left","dataType":"VARCHAR"},
{"id":"a5","pid":"","name":"Expense Ratios"},
{"id":"b1","pid":"a5","name":"Gross expense ratio",type:"ro",align:"left","dataType":"VARCHAR"},
{"id":"b2","pid":"a5","name":"Net expense ratio",type:"ro",align:"left","dataType":"VARCHAR"},
{"id":"b3","pid":"a5","name":"Contractual waiver through",type:"ro",align:"left","dataType":"VARCHAR"},
{"id":"a6","pid":"","name":"Average annual return [%]"},
{"id":"c1","pid":"a6","name":"Lastest week as of 02/11/2011"},
{"id":"d1","pid":"c1","name":"YTD",type:"ro",align:"left","dataType":"INT"},
{"id":"d2","pid":"c1","name":"1-Year",type:"ro",align:"left","dataType":"INT"},
{"id":"d3","pid":"c1","name":"3-Year",type:"ro",align:"left","dataType":"INT"},
{"id":"d4","pid":"c1","name":"5-Year",type:"ro",align:"left","dataType":"INT"},
{"id":"d5","pid":"c1","name":"10-Year",type:"ro",align:"left","dataType":"INT"},
{"id":"d6","pid":"c1","name":"Since Inception",type:"ro",align:"left","dataType":"INT"},
{"id":"c2","pid":"a6","name":"Lastest quarter as of 12/31/2010 [unadjusted]"},
{"id":"e1","pid":"c2","name":"YTD",type:"ro",align:"left","dataType":"INT"},
{"id":"e2","pid":"c2","name":"1-Year",type:"ro",align:"left","dataType":"INT"},
{"id":"e3","pid":"c2","name":"3-Year",type:"ro",align:"left","dataType":"INT"},
{"id":"e4","pid":"c2","name":"5-Year",type:"ro",align:"left","dataType":"INT"},
{"id":"e5","pid":"c2","name":"10-Year",type:"ro",align:"left","dataType":"INT"},
{"id":"e6","pid":"c2","name":"Since Inception",type:"ro",align:"left","dataType":"INT"},
{"id":"c3","pid":"a6","name":"Lastest week as of 02/11/2011 [adjusted]"},
{"id":"f1","pid":"c3","name":"YTD",type:"ro",align:"left","dataType":"INT"},
{"id":"f2","pid":"c3","name":"1-Year",type:"ro",align:"left","dataType":"INT"},
{"id":"f3","pid":"c3","name":"3-Year",type:"ro",align:"left","dataType":"INT"},
{"id":"f4","pid":"c3","name":"5-Year",type:"ro",align:"left","dataType":"INT"},
{"id":"f5","pid":"c3","name":"10-Year",type:"ro",align:"left","dataType":"INT"},
{"id":"f6","pid":"c3","name":"Since Inception",type:"ro",align:"left","dataType":"INT"},
{"id":"a7","pid":"","name":"Last return [%]",type:"ro",align:"left","dataType":"VARCHAR"}
]
我这里为了让每条数据之间的父子关系清晰一【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】点,把子栏目的数据都堆到了父栏目下面。但【未经授权禁止转载】未经授权,禁止复制转载。是实际上,我们拿到的数据也应该按照这个顺【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】序进行排列,否则你怎么确定父栏目与父栏目【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】之间的顺序,子栏目与子栏目之间的顺序。当原创内容,盗版必究。原创内容,盗版必究。然,如果更加理想化,我们可以增加一个or【本文受版权保护】【关注微信公众号:wwwtangshuangnet】der/sort字段,用来保存排列顺序,【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。并可以通过这个字段进行数组元素的排序计算【本文受版权保护】【版权所有,侵权必究】,这样就不怕给的原始数据是随机排序的了。【原创内容,转载请注明出处】未经授权,禁止复制转载。但是,我们本文仍然把这种情况排除,我们假著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net设data api返回的数据就是上面这样转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net的,已经确定好顺序了。
本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net
下面就是我进行处理的javascrip转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】t代码,需要在node下运算,或者改写成转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。可以在浏览器下运行的函数。
'use strtic';
require('jquery');
module.exports = function (origin) { // deep copy origin data, and origin data will not be change
var data = $.extend([],origin);
var origin = {};
for(var i = 0,len = data.length;i < len;i ++) {
var item = data[i];
item.children = [];
item.level = 1;
origin[item.id] = item;// change data to key=>value
}
/*
* build table tr
* find item children
* find item level
*/
var _nodes_ = [];
// add child to parent's children
for(var i = 0,len = data.length;i < len;i ++) {
var item = data[i];
if(item.pid != "") {
origin[item.pid].children.push(item.id);
}
}
function pushEndNodeToAncestors(item) {
var id = item.id;
var pid = item.pid;
if(pid == "" && item.children.length == 0) { // only one level (top) item
return;
}
while(pid != "") {
if(!_nodes_[pid]) _nodes_[pid] = [];
if(_nodes_[pid].indexOf(id) < 0) _nodes_[pid].push(id);
item = origin[pid];
pid = item.pid;
}
}
function pushLevelOfAncestors(item) {
var level = 1;
while(true) {
if(level > item.level) { // if this item is the same parent of different children
item.level = level;
}
if(level > headerRowsTotalCount) {
headerRowsTotalCount = level;
}
if(item.pid == "") {
break;
}
item = origin[item.pid];
level ++;
}
}
var headerRowsTotalCount = 1;
for(var i = 0,len = data.length,index = 0;i < len;i ++) {
var item = data[i];
if(item.children.length == 0) { // end nodes
item.index = index;
index ++;
pushEndNodeToAncestors(item);
pushLevelOfAncestors(item); // get headerRowsTotalCount at the same time
}
}
var headerRows = new Array(headerRowsTotalCount);
for(var i = 0,len = data.length;i < len;i ++) {
var item = data[i];
var nodes = _nodes_[item.id];
// kids
item.kids = item.children ? item.children.join(',') : "";
// (end)nodes
item.nodes = nodes ? nodes.join(',') : "";
// colspan
var colspan = 1;
if(nodes) {
colspan = nodes.length;
}
item.colspan = colspan;
// rowspan
var rowspan = 1;
if(item.pid == "") {
rowspan = 1 + (headerRowsTotalCount - item.level); // roots rowspan
}
else {
rowspan = origin[item.pid].level - item.level;
}
item.rowspan = rowspan;
// push item into table tr row
var row = headerRowsTotalCount - (item.level + item.rowspan - 1);
if(!headerRows[row]) headerRows[row] = [];
headerRows[row].push(item);
}
return headerRows;
}
完成上面的运算之后,实际上,我们得到的是转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net一个3xn的数组,数组整体上有三个元素,未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】每个元素都是一个数组,而这个数组中存放的【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。,就是每一行tr内应该显示的td相关信息【原创内容,转载请注明出处】【本文首发于唐霜的博客】。接下来,我们把这个数据结果赋值给dat【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.neta,并在页面内进行table的构建:
【本文受版权保护】【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。var td = '<td colspan="{%s}" rowspan="{%s}" align="{%s}" data-id="{%s}" data-pid="{%s}" data-kids="{%s}" data-nodes="{%s}" data-index="{%s}" title="{%s}" class="header-cell"><div class="header-name">{%s}</div></td>';
var table = '';
for(var i = 0,len = data.length;i < len;i ++) {
var rowItems = data[i]; table += '<tr>';
for(var c = 0,leng = rowItems.length;c < leng;c ++) {
var item = rowItems[c];
table += sprintf(td,item.colspan,item.rowspan,item.align,item.id,item.pid,item.kids,item.nodes,item.index,item.name,item.name);
}
table += '</tr>';
}
sprintf是我自己写的一个函数,用来【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。实现和c语言中sprintf一样的功能(【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net只能替换{%s}),你也可以自己写过。这【版权所有,侵权必究】原创内容,盗版必究。样,就可以在页面内构建能够分栏的tr行了本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】,把它们插入到你需要显示的地方即可。
【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。2016-07-26 3171


