tableX.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. /**
  2. * 表格扩展模块
  3. * date:2019-07-12 License By http://easyweb.vip
  4. */
  5. layui.define(['layer', 'table', 'laytpl', 'form', 'util', 'contextMenu'], function (exports) {
  6. var $ = layui.jquery;
  7. var layer = layui.layer;
  8. var table = layui.table;
  9. var laytpl = layui.laytpl;
  10. var form = layui.form;
  11. var util = layui.util;
  12. var contextMenu = layui.contextMenu;
  13. var device = layui.device;
  14. var tbSearchAttr = 'tb-search'; // 前端搜索属性
  15. var tbRefreshAttr = 'tb-refresh'; // 刷新按钮属性
  16. var tbExportAttr = 'tb-export'; // 导出按钮属性
  17. var txFieldPre = 'txField_'; // templte列filed前缀
  18. var tableX = {
  19. // 合并相同单元格
  20. merges: function (tableId, indexs, fields, sort) {
  21. // 检查参数是否为空
  22. if (!tableId) {
  23. console.error('table filter not be null');
  24. return;
  25. }
  26. if (!indexs) {
  27. console.warn('merge indexs not be null');
  28. return;
  29. }
  30. if (typeof fields === 'boolean') {
  31. sort = fields;
  32. fields = undefined;
  33. }
  34. var $tb = $('[lay-filter="' + tableId + '"]+.layui-table-view>.layui-table-box>.layui-table-body>table');
  35. var $trs = $tb.find('>tbody>tr');
  36. $tb.addClass('layui-table-x');
  37. // 合并一列
  38. function merge(tableId, index, field) {
  39. var data = table.cache[tableId];
  40. if (data.length > 0) {
  41. var lastValue, spanNum = 1;
  42. if (field) {
  43. lastValue = data[0][field];
  44. } else {
  45. lastValue = $trs.eq(0).find('td').eq(index).find('.layui-table-cell').html();
  46. }
  47. for (var i = 1; i < data.length; i++) {
  48. var currentValue;
  49. if (field) {
  50. currentValue = data[i][field];
  51. } else {
  52. currentValue = $trs.eq(i).find('td').eq(index).find('.layui-table-cell').html();
  53. }
  54. if (currentValue == lastValue) {
  55. spanNum++;
  56. if (i == data.length - 1) {
  57. $trs.eq(i - spanNum + 1).find('td').eq(index).attr('rowspan', spanNum);
  58. for (var j = 1; j < spanNum; j++) {
  59. $trs.eq(i - j + 1).find('td').eq(index).attr('del', 'true');
  60. }
  61. }
  62. } else {
  63. $trs.eq(i - spanNum).find('td').eq(index).attr('rowspan', spanNum);
  64. for (var j = 1; j < spanNum; j++) {
  65. $trs.eq(i - j).find('td').eq(index).attr('del', 'true');
  66. }
  67. spanNum = 1;
  68. lastValue = currentValue;
  69. }
  70. }
  71. }
  72. }
  73. // 循环合并每一列
  74. for (var i = 0; i < indexs.length; i++) {
  75. if (!fields) {
  76. merge(tableId, indexs[i], undefined);
  77. } else {
  78. merge(tableId, indexs[i], fields[i]);
  79. }
  80. }
  81. $trs.find('[del="true"]').remove(); // 移除多余的单元格
  82. // 监听排序事件
  83. (sort == undefined) && (sort = true);
  84. if (sort) {
  85. table.on('sort(' + tableId + ')', function (obj) {
  86. tableX.merges(tableId, indexs, fields);
  87. });
  88. }
  89. },
  90. // 导出表格数据
  91. exportData: function (param) {
  92. var cols = param.cols; // 表头
  93. var dataList = param.data; // 数据
  94. var fileName = param.fileName; // 文件名
  95. var fileType = param.expType; // 类型,xls、csv
  96. var option = param.option; // url方式加载的配置
  97. if (device.ie) return layer.msg('不支持ie导出');
  98. // data为url先请求数据
  99. if (dataList && typeof dataList === 'string') {
  100. var loadIndex = layer.msg('加载中..', {icon: 16, shade: 0.01, time: 0});
  101. option.url = dataList;
  102. tableX.loadUrl(option, function (res) {
  103. layer.close(loadIndex);
  104. param.data = res;
  105. tableX.exportData(param);
  106. });
  107. }
  108. // 列参数补全
  109. for (var i = 0; i < cols.length; i++) {
  110. for (var j = 0; j < cols[i].length; j++) {
  111. if (cols[i][j].type == undefined) {
  112. cols[i][j].type = 'normal';
  113. }
  114. if (cols[i][j].hide == undefined) {
  115. cols[i][j].hide = false;
  116. }
  117. }
  118. }
  119. var titles = [], fields = [], expData = [];
  120. // 获取表头和表头字段名
  121. table.eachCols(undefined, function (i, item) {
  122. if (item.type == 'normal' && !item.hide) {
  123. titles.push(item.title ? item.title : '');
  124. fields.push(item.field ? item.field : (txFieldPre + i));
  125. }
  126. }, cols);
  127. // 格式化数据
  128. var allList = tableX.parseTbData(cols, tableX.deepClone(dataList), true);
  129. for (var i = 0; i < allList.length; i++) {
  130. var rowItem = [];
  131. for (var j = 0; j < fields.length; j++) {
  132. var itemVal = allList[i][fields[j]];
  133. if (typeof itemVal == 'string') {
  134. itemVal = itemVal.replace(/,/g, ',');
  135. }
  136. rowItem.push(itemVal);
  137. }
  138. expData.push(rowItem);
  139. }
  140. // 创建下载文件的a标签
  141. var textType = ({csv: 'text/csv', xls: 'application/vnd.ms-excel'})[fileType];
  142. var alink = document.createElement("a");
  143. var getDataStr = function () {
  144. var dataTitle = [], dataMain = [];
  145. layui.each(expData, function (i1, item1) {
  146. var vals = [];
  147. layui.each(titles, function (i, item) {
  148. i1 == 0 && dataTitle.push(item || '');
  149. });
  150. layui.each(table.clearCacheKey(item1), function (i2, item2) {
  151. vals.push(item2);
  152. });
  153. dataMain.push(vals.join(','))
  154. });
  155. return titles.join(',') + '\r\n' + expData.join('\r\n');
  156. };
  157. alink.href = 'data:' + textType + ';charset=utf-8,\ufeff' + encodeURIComponent(getDataStr());
  158. alink.download = (fileName || 'table') + '.' + (fileType ? fileType : 'xls');
  159. document.body.appendChild(alink);
  160. alink.click();
  161. document.body.removeChild(alink);
  162. },
  163. // 渲染表格,后端排序
  164. render: function (param) {
  165. var tableId = $(param.elem).attr('lay-filter');
  166. param.autoSort = false; // 关闭默认排序
  167. var insTb = table.render(param); // 渲染表格
  168. // 排序监听
  169. table.on('sort(' + tableId + ')', function (obj) {
  170. var sortField = obj.field, sortType = obj.type; // 排序字段、类型
  171. var sortWhere = $.extend(param.where, {sort: sortField, order: sortType});
  172. insTb.reload({where: sortWhere, page: {curr: 1}});
  173. });
  174. return insTb;
  175. },
  176. // 渲染表格,前端分页
  177. renderFront: function (param) {
  178. var insTb, tableId = $(param.elem).attr('lay-filter');
  179. param.autoSort = false; // 关闭默认排序
  180. // 没有field的templet列补上,因为排序必须有filed字段,否则点击排序会报错
  181. for (var i = 0; i < param.cols.length; i++) {
  182. for (var j = 0; j < param.cols[i].length; j++) {
  183. if (param.cols[i][j].templet && !param.cols[i][j].field) {
  184. param.cols[i][j].field = txFieldPre + i + '_' + j;
  185. }
  186. }
  187. }
  188. if (param.url) { // url方式
  189. var xParam = tableX.deepClone(param);
  190. xParam.data = [], xParam.url = '';
  191. insTb = table.render(xParam); // 先渲染表格结构
  192. // 提供刷新方法
  193. insTb.reloadUrl = function (p) {
  194. var reParam = tableX.deepClone(param);
  195. p && (reParam = $.extend(reParam, p));
  196. var loadIndex = layer.msg('加载中..', {icon: 16, shade: 0.01, time: 0});
  197. tableX.loadUrl(reParam, function (data) { // 获取url数据
  198. layer.close(loadIndex);
  199. tableX.parseTbData(reParam.cols, data); // 解析temple列
  200. tableX.putTbData(tableId, data); // 缓存数据
  201. $('input[' + tbSearchAttr + '="' + tableId + '"]').val(''); // 清空搜索输入框
  202. window.tbX.cacheSearch[tableId] = undefined; // 重置搜索结果
  203. insTb.reload({url: '', data: data, page: {curr: 1}});
  204. });
  205. };
  206. // 请求数据
  207. var loadIndex = layer.msg('加载中..', {icon: 16, shade: 0.01, time: 0});
  208. tableX.loadUrl(param, function (data) { // 获取url数据
  209. layer.close(loadIndex);
  210. tableX.parseTbData(param.cols, data); // 解析temple列
  211. tableX.putTbData(tableId, data); // 缓存数据
  212. insTb.reload({url: '', data: data, page: {curr: 1}});
  213. });
  214. tableX.renderAllTool(insTb); // 渲染工具组件
  215. } else {
  216. tableX.parseTbData(param.cols, param.data); // 解析temple列
  217. tableX.putTbData(tableId, param.data); // 缓存数据
  218. insTb = table.render(param); // 渲染表格
  219. tableX.renderAllTool(insTb); // 渲染工具组件
  220. // 提供刷新的方法
  221. insTb.reloadData = function (p) {
  222. insTb.reload(p);
  223. tableX.parseTbData(param.cols, p.data); // 解析temple列
  224. tableX.putTbData(tableId, p.data);
  225. $('input[' + tbSearchAttr + '="' + tableId + '"]').val(''); // 清空搜索输入框
  226. window.tbX.cacheSearch[tableId] = undefined; // 重置搜索结果
  227. };
  228. }
  229. return insTb;
  230. },
  231. // 渲染所有组件
  232. renderAllTool: function (insTb) {
  233. renderRefresh(insTb); // 刷新
  234. renderFrontSort(insTb); // 排序
  235. renderFrontSearch(insTb); // 搜索
  236. renderExport(insTb); // 导出
  237. },
  238. // 加载表格数据
  239. loadUrl: function (options, callback) {
  240. // 响应数据的自定义格式
  241. options.response = $.extend({
  242. statusName: 'code',
  243. statusCode: 0,
  244. msgName: 'msg',
  245. dataName: 'data',
  246. countName: 'count'
  247. }, options.response);
  248. var request = options.request, response = options.response, params = {};
  249. var data = $.extend(params, options.where); // 参数
  250. if (options.contentType && options.contentType.indexOf("application/json") == 0) {
  251. data = JSON.stringify(data); // 提交 json 格式
  252. }
  253. $.ajax({
  254. type: options.method || 'get',
  255. url: options.url,
  256. contentType: options.contentType,
  257. data: data,
  258. dataType: 'json',
  259. headers: options.headers || {},
  260. success: function (res) {
  261. // 如果有数据解析的回调,则获得其返回的数据
  262. if (typeof options.parseData === 'function') {
  263. res = options.parseData(res) || res;
  264. }
  265. // 检查数据格式是否符合规范
  266. if (res[response.statusName] != response.statusCode) {
  267. var msgText = res[response.msgName] || ('返回的数据不符合规范,正确的成功状态码 (' + response.statusName + ') 应为:' + response.statusCode);
  268. layer.msg(msgText, {icon: 2});
  269. } else {
  270. callback(res[response.dataName]);
  271. }
  272. },
  273. error: function (e, m) {
  274. layer.msg('数据接口请求异常:' + m, {icon: 2});
  275. }
  276. });
  277. },
  278. // 解析数据表格templet列
  279. parseTbData: function (cols, dataList, overwrite) {
  280. var templets = []; // 需要解析的列
  281. table.eachCols(undefined, function (i, item) {
  282. if (item.templet) {
  283. var one = {field: ((item.field && (overwrite || item.field.indexOf(txFieldPre) == 0)) ? item.field : ('txField_' + i))};
  284. if (typeof item.templet === 'string') {
  285. one.templet = function (d) { // templet列使用laytpl渲染
  286. var rsStr = undefined;
  287. laytpl($(item.templet).html()).render(d, function (html) {
  288. rsStr = html;
  289. });
  290. return rsStr;
  291. }
  292. } else {
  293. one.templet = item.templet;
  294. }
  295. templets.push(one);
  296. }
  297. }, cols);
  298. for (var i = 0; i < dataList.length; i++) {
  299. var current = dataList[i];
  300. for (var j = 0; j < templets.length; j++) {
  301. var htmlStr = '<div>' + templets[j].templet(current) + '</div>';
  302. current[templets[j].field] = $(htmlStr).not('.export-hide').text().replace(/(^\s*)|(\s*$)/g, ''); // 去除前后空格
  303. }
  304. }
  305. return dataList;
  306. },
  307. // 获取表格缓存的数据
  308. getTbData: function (tableId) {
  309. var dataList = window.tbX.cache[tableId];
  310. if (dataList == undefined) {
  311. dataList = table.cache[tableId];
  312. }
  313. return tableX.deepClone(dataList);
  314. },
  315. // 缓存表格的数据
  316. putTbData: function (tableId, dataList) {
  317. window.tbX.cache[tableId] = dataList;
  318. return dataList;
  319. },
  320. // 行绑定鼠标右键
  321. bindCtxMenu: function (tableId, items) {
  322. var dataList = table.cache[tableId];
  323. var elem = '#' + tableId + '+.layui-table-view .layui-table-body tr';
  324. $(elem).bind('contextmenu', function (e) {
  325. var $tr = $(this);
  326. var trIndex = $(this).attr('data-index');
  327. var tempItems = [];
  328. for (var i = 0; i < items.length; i++) {
  329. var item = items[i];
  330. tempItems.push({
  331. icon: item.icon,
  332. name: item.name,
  333. click: function () {
  334. var layId = $(this).attr('lay-id');
  335. items[parseInt(layId.substring(8))].click(dataList[trIndex]);
  336. $tr.removeClass('layui-table-click');
  337. }
  338. });
  339. }
  340. $(elem).removeClass('layui-table-click');
  341. $tr.addClass('layui-table-click');
  342. contextMenu.show(tempItems, e.clientX, e.clientY);
  343. return false;
  344. });
  345. },
  346. // 搜索数据
  347. filterData: function (dataList, searchName, searchValue) {
  348. var newList = [], sfs;
  349. for (var i = 0; i < dataList.length; i++) {
  350. var obj = dataList[i];
  351. if (!sfs) { // 搜索的字段
  352. if (!searchName) {
  353. sfs = [];
  354. for (var f in obj) {
  355. sfs.push(f);
  356. }
  357. } else {
  358. sfs = searchName.split(',');
  359. }
  360. }
  361. for (var j = 0; j < sfs.length; j++) {
  362. if (tableX.isContains(obj[sfs[j]], searchValue)) {
  363. newList.push(obj);
  364. break;
  365. }
  366. }
  367. }
  368. return newList;
  369. },
  370. // 字符串是否包含
  371. isContains: function (str1, str2) {
  372. str1 || (str1 = '');
  373. str2 || (str2 = '');
  374. str1 = str1.toString().toLowerCase();
  375. str2 = str2.toString().toLowerCase();
  376. if (str1 == str2 || str1.indexOf(str2) != -1) {
  377. return true;
  378. }
  379. return false;
  380. },
  381. // 深度克隆对象
  382. deepClone: function (obj) {
  383. var result;
  384. var oClass = tableX.isClass(obj);
  385. if (oClass === "Object") {
  386. result = {};
  387. } else if (oClass === "Array") {
  388. result = [];
  389. } else {
  390. return obj;
  391. }
  392. for (var key in obj) {
  393. var copy = obj[key];
  394. if (tableX.isClass(copy) == "Object") {
  395. result[key] = arguments.callee(copy);//递归调用
  396. } else if (tableX.isClass(copy) == "Array") {
  397. result[key] = arguments.callee(copy);
  398. } else {
  399. result[key] = obj[key];
  400. }
  401. }
  402. return result;
  403. },
  404. // 获取变量类型
  405. isClass: function (o) {
  406. if (o === null)
  407. return "Null";
  408. if (o === undefined)
  409. return "Undefined";
  410. return Object.prototype.toString.call(o).slice(8, -1);
  411. }
  412. };
  413. // 创建数据缓存对象
  414. window.tbX || (window.tbX = new Object());
  415. window.tbX.cache || (window.tbX.cache = new Object());
  416. window.tbX.cacheSearch || (window.tbX.cacheSearch = new Object());
  417. // 前端搜索
  418. var renderFrontSearch = function (insTb) {
  419. var tableId = insTb.config.id, $input = $('input[' + tbSearchAttr + '="' + tableId + '"]');
  420. if (!($input && $input.length > 0)) {
  421. return;
  422. }
  423. if (!$input.attr('placeholder')) {
  424. $input.attr('placeholder', '输入关键字按回车键搜索');
  425. }
  426. $input.off('keydown').on('keydown', function (event) {
  427. if (event.keyCode != 13) {
  428. return;
  429. }
  430. var searchName = $input.attr('name'); // 搜索的字段名,用逗号分隔
  431. var searchValue = $input.val().replace(/(^\s*)|(\s*$)/g, ''); // 搜索关键字
  432. var loadIndex = layer.msg('搜索中..', {icon: 16, shade: 0.01, time: 0});
  433. var dataList = tableX.getTbData(tableId);
  434. var newDataList = tableX.filterData(dataList, searchName, searchValue);
  435. window.tbX.cacheSearch[tableId] = newDataList; // 缓存搜索后的数据用于排序
  436. insTb.reload({url: '', data: newDataList, page: {curr: 1}});
  437. layer.close(loadIndex);
  438. });
  439. };
  440. // 前端排序
  441. var renderFrontSort = function (insTb) {
  442. var tableId = insTb.config.id;
  443. table.on('sort(' + tableId + ')', function (obj) {
  444. var sortField = obj.field, sortType = obj.type; // 排序字段、类型
  445. var loadIndex = layer.msg('加载中..', {icon: 16, shade: 0.01, time: 0});
  446. var dataList = window.tbX.cacheSearch[tableId]; // 表格搜索后的数据
  447. dataList || (dataList = tableX.getTbData(tableId));
  448. if (sortType) {
  449. dataList = dataList.sort(function (o1, o2) {
  450. var o1Str = o1[sortField], o2Str = o2[sortField];
  451. if (sortType == 'asc') { // 升序
  452. return (o1Str == o2Str) ? 0 : ((o1Str < o2Str) ? -1 : 1);
  453. } else { // 降序
  454. return (o1Str == o2Str) ? 0 : ((o1Str < o2Str) ? 1 : -1);
  455. }
  456. });
  457. }
  458. insTb.reload({initSort: obj, url: '', data: dataList, page: {curr: 1}});
  459. layer.close(loadIndex);
  460. });
  461. };
  462. // 表格刷新按鈕
  463. var renderRefresh = function (insTb) {
  464. $('[' + tbRefreshAttr + '="' + insTb.config.id + '"]').off('click').on('click', function () {
  465. if (insTb.reloadUrl) {
  466. insTb.reloadUrl();
  467. } else {
  468. insTb.reload({page: {curr: 1}});
  469. }
  470. });
  471. };
  472. // 渲染导出按钮
  473. var renderExport = function (insTb) {
  474. var tableId = insTb.config.id;
  475. $('[' + tbExportAttr + '="' + tableId + '"]').off('click').on('click', function (event) {
  476. if ($(this).find('.tbx-dropdown-menu').length > 0) {
  477. return;
  478. }
  479. if (event !== void 0) {
  480. event.preventDefault();
  481. event.stopPropagation();
  482. }
  483. var htmlStr = '<div class="tbx-dropdown-menu">';
  484. htmlStr += ' <div class="tbx-dropdown-menu-item" data-type="check">导出选中数据</div>';
  485. htmlStr += ' <div class="tbx-dropdown-menu-item" data-type="current">导出当前页数据</div>';
  486. htmlStr += ' <div class="tbx-dropdown-menu-item" data-type="all">导出全部数据</div>';
  487. htmlStr += ' </div>';
  488. $(this).append(htmlStr);
  489. $(this).addClass('tbx-dropdown-btn');
  490. $(this).parent().css('position', 'relative');
  491. $(this).parent().css('z-index', '9998');
  492. $('.tbx-dropdown-menu').off('click').on('click', '.tbx-dropdown-menu-item', function (event) {
  493. var type = $(this).data('type');
  494. if (type == 'check') {
  495. var checkRows = table.checkStatus(tableId);
  496. if (checkRows.data.length == 0) {
  497. layer.msg('请选择要导出的数据', {icon: 2});
  498. } else {
  499. $('.tbx-dropdown-menu').remove();
  500. tableX.exportData({
  501. fileName: insTb.config.title,
  502. cols: insTb.config.cols,
  503. data: checkRows.data
  504. });
  505. }
  506. } else if (type == 'current') {
  507. tableX.exportData({
  508. fileName: insTb.config.title,
  509. cols: insTb.config.cols,
  510. data: table.cache[tableId]
  511. });
  512. } else if (type == 'all') {
  513. tableX.exportData({
  514. fileName: insTb.config.title,
  515. cols: insTb.config.cols,
  516. data: tableX.getTbData(tableId)
  517. });
  518. }
  519. if (event !== void 0) {
  520. event.preventDefault();
  521. event.stopPropagation();
  522. }
  523. });
  524. });
  525. $(document).off('click.tbxDropHide').on('click.tbxDropHide', function () {
  526. $('.tbx-dropdown-menu').remove();
  527. });
  528. };
  529. // css样式
  530. var getCommonCss = function () {
  531. // 下拉菜单样式
  532. var cssStr = '.tbx-dropdown-btn {';
  533. cssStr += ' position: relative;';
  534. cssStr += ' }';
  535. cssStr += ' .tbx-dropdown-btn:hover {';
  536. cssStr += ' opacity: 1';
  537. cssStr += ' }';
  538. cssStr += ' .tbx-dropdown-menu {';
  539. cssStr += ' position: absolute;';
  540. cssStr += ' top: 100%;';
  541. cssStr += ' right: 0;';
  542. cssStr += ' padding: 5px 0;';
  543. cssStr += ' margin: 5px 0 0 0;';
  544. cssStr += ' overflow: visible;';
  545. cssStr += ' min-width: 110px;';
  546. cssStr += ' background: #fff;';
  547. cssStr += ' border-radius: 2px;';
  548. cssStr += ' box-shadow: 0 2px 4px rgba(0, 0, 0, .12);';
  549. cssStr += ' border: 1px solid #d2d2d2;';
  550. cssStr += ' z-index: 9998;';
  551. cssStr += ' cursor: default;';
  552. cssStr += ' }';
  553. cssStr += ' .tbx-dropdown-menu .tbx-dropdown-menu-item {';
  554. cssStr += ' display: block;';
  555. cssStr += ' color: #555;';
  556. cssStr += ' font-size: 14px;';
  557. cssStr += ' padding: 10px 15px;';
  558. cssStr += ' text-decoration: none;';
  559. cssStr += ' white-space: nowrap;';
  560. cssStr += ' cursor: pointer;';
  561. cssStr += ' user-select: none;';
  562. cssStr += ' line-height: normal;';
  563. cssStr += ' }';
  564. cssStr += ' .tbx-dropdown-menu .tbx-dropdown-menu-item:hover {';
  565. cssStr += ' background-color: #eeeeee;';
  566. cssStr += ' }';
  567. cssStr += ' .export-show {';
  568. cssStr += ' display: none;';
  569. cssStr += ' }';
  570. return cssStr;
  571. };
  572. $('head').append('<style>' + getCommonCss() + '</style>');
  573. exports("tableX", tableX);
  574. });