Beyond Compare 2 是一款很好的文件比较工具,并且可以很方便地将结果导出为html格式显示,如图所示 :
原图结果:
而不像他的桌面客户端一样可以各个文件可以拖动比较,而是整个窗口出现滚动条了,不方便在两个文件的同一行数据的同一位置进行比较。
改进分析:
1.结果 html 采用 table 显示数据,两个文件的同一位置代码位于 table 的同一行不同 td ,而 table 采用 auto table-layout 而使得代码表格撑破浏览器窗口了,应使用固定表格布局。
2.代码文字直接显示在 td 中,而滚动条则不能出现在 td 上。应在 td 中嵌套 div 从而使得 div 拥有滚动条可以滚动,并且滚动条div还要嵌套入数据div,并使得所有数据div具有相同宽度(最大宽度),使得即使很短的代码表格文本也可以滚动,同步长代码行。
3.需要一种最底层滚动条,使得其可以控制所有上述table的所有单元格同步滚动。
4.对于两个大文件的对比,要利用分时计算来防止浏览器失去响应。(当文件超过200K,建议使用chrome,否则请耐心等待)
图示分析:
改进结果:
上述步鄹都可以在原始页面载入后,利用 javascript 遍历 DOM 树来进行样式以及结构的调整 ,即只需要在原html 代码 中加入
<script src="patch.js"></script>
即可。
改进后:
代码注释讲解 (示例附件 ):
/* Beyond Compare 2 patch for html result author:yiminghe.iteye.com try MIT licence */ Ext.onReady(function () { var mask = Ext.getBody().mask("start process ... "); var maskMessage = Ext.getBody()._maskMsg.dom.firstChild; /* 分时计算,防止僵死 修改自 : http://www.nczonline.net/blog/2009/08/11/timed-array-processing-in-javascript/ */ function timedChunk(items, process, context, callback) { var index = items.getCount() - 1; var total = index; setTimeout(function () { var start = +new Date(); do { //console.log(index); maskMessage.innerHTML = ("current step remain : " + ((index * 100) / total).toFixed(1) + "%"); process.call(context, items.item(index)); index--; } while (index >= 0 && (+new Date() - start < 50)); if (index >= 0) { setTimeout(arguments.callee, 25); } else { callback(items); } }, 25); } var maxScrollWidth = -1; //设定固定布局,防止自动撑破 Ext.select("table.fc").setStyle({ "table-layout": "fixed" }); //为固定布局设置宽度 var tbody = Ext.DomQuery.selectNode("table.fc > tbody"); var firstTds = Ext.get(tbody).select(" > tr:first-child td"); var widths = [2, 45, 5, 2, 45]; firstTds.each(function (el, _tds, index_) { el.setStyle({ width: widths[index_] + "%" }); }); var trs = Ext.get(tbody).select("> tr", true); timedChunk(trs, function adjustDiff(el) { for (var i = 0; i < 2; i++) { var turn = i ? (5) : 2; //console.log(el); var cel = el.child(">td:nth-child(" + turn + ")"); //console.log(cel); cel.dom.style.overflow = "hidden"; cel.dom.innerHTML = "<div>" + cel.dom.innerHTML + "</div>"; //里层文字div不允许换行 Ext.get(cel.dom.firstChild).setStyle({ "white-space": "nowrap" }); //外层滚动条div,隐藏滚动条,注意 td 出不来滚动条 //ie6 td 内 div 设置 width 100%,才能完全填充 td Ext.get(cel.dom.firstChild).wrap({ tag: 'div', cls: 'code', style: { "overflow": "hidden", width: "100%" // for ie6 } }); //获取外层滚动的最大宽度 var cur = cel.dom.firstChild.scrollWidth; if (maxScrollWidth < cur) { maxScrollWidth = cur; } } }, null, setDiff); function setDiff() { timedChunk(trs, function (el) { for (var i = 0; i < 2; i++) { var turn = i ? (5) : 2; var cel = el.child(">td:nth-child(" + turn + ")"); var cur = cel.dom.firstChild.scrollWidth; //将文字div设置为所有格子最大滚动宽度,使得可以统一滚动 if (maxScrollWidth > cur) { cel.dom.firstChild.firstChild.style.width = maxScrollWidth + "px"; } } }, null, createScroll); //最后一行显示的滚动条创建,ie会根据宽度设置自动出现滚动条,firefox不会,只能设置scroll function createScroll() { Ext.DomHelper.append(tbody, { tag: "tr", cn: [{ tag: "td", html: ' ' }, { tag: "td", cn: [{ tag: 'div', id: "scrollDiv0", cls: 'code', style: { "overflow-x": "scroll", //for firefox width: "100%" // for ie6 }, cn: [{ tag: "div", html: ' ', //for firefox style: { width: maxScrollWidth + "px" } }] }] }, { tag: "td", html: ' ' }, { tag: "td", html: ' ' }, { tag: "td", style: { //"overflow-x":"scroll" }, cn: [{ tag: 'div', id: "scrollDiv1", cls: 'code', style: { "overflow-x": "scroll", //for firefox width: "100%" // for ie6 }, cn: [{ tag: "div", html: ' ', //for firefox style: { width: maxScrollWidth + "px" } }] }] }] }); //当底层滚动条滚动时,所有格子的滚动条都一起滚动,造成同一列属于一个整体的假象 var scrollCells = Ext.select(".code"); for (var i = 0; i < 2; i++) { var lsDiv = Ext.get("scrollDiv" + i); lsDiv.on("scroll", (function (i) { return function () { var srollDiv = this; scrollCells.each(function (el) { el.dom.scrollLeft = srollDiv.dom.scrollLeft; }); } })(i)); } Ext.getBody().unmask(); } } });