table2.js 72 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612
  1. /**
  2. @Name:表格插件
  3. @Author:ray
  4. @License:MIT
  5. */
  6. layui.define(["jquery"], function (exports, undef) {
  7. "use strict";
  8. var $ = layui.$,
  9. win = window,
  10. doc = document,
  11. tableCache = {
  12. tables: {},
  13. datas: {},
  14. cols: {},
  15. jqobjs: {}
  16. }, tableindex = 0, scrollGap = {}, $win = $(win), timer = null;
  17. $win.resize(function () {
  18. if (timer != null) clearTimeout(timer);
  19. timer = setTimeout(function () {
  20. timer = null;
  21. for (var t in tableCache.tables) {
  22. var that = tableCache.tables[t],
  23. data = tableCache.datas[that.tableIndex];
  24. if (!data || data.length === 0) continue;
  25. TableClass.utils.modifyStyle.call(that);
  26. }
  27. }, 20);
  28. });
  29. var TableClass = function (table, option) {
  30. this.elem = table;
  31. this.tableIndex = tableindex;
  32. var globalOptions = $.extend({}, TableClass.option);
  33. //option.page:true
  34. typeof option.page === "boolean" && option.page && (option.page = {});
  35. option.page && !globalOptions.page && (globalOptions.page = {});
  36. //option.page:false或则object
  37. this.options = $.extend(true, {}, TableClass.option2, globalOptions, option);
  38. //允许分页但没有设置limits
  39. this.options.page && !this.options.page.limits && (this.options.page.limits = [10, 20, 30, 40, 50, 60, 70, 80, 90]);
  40. //初始化
  41. TableClass.utils.init.call(this);
  42. return this;
  43. };
  44. //可被外部全局配置
  45. TableClass.option = {
  46. expandRow: false,//是否支持展开行
  47. nowrap: true,//是否自动换行,默认不换行
  48. minHeight: 80,//表格最小高度
  49. singleSelect: false,//可以选择多行
  50. localSort: true,//本地排序,默认true,如果不想使用本地排序,请配置成false
  51. cellMinWidth: 60, //所有单元格默认最小宽度
  52. loading: true, //请求数据时,是否显示loading
  53. even: true, //隔行换色,可选true|false,默认false
  54. serialField: "id"
  55. /* page: {
  56. align: 'right',
  57. groups: 5,//显示连续页码数量
  58. curr:1,
  59. count: -1,//总条数
  60. limit:10,
  61. limits:[10, 20, 30, 40, 50, 60, 70, 80, 90]
  62. }*/
  63. };
  64. //不可被外部全局配置
  65. TableClass.option2 = {
  66. version: "1.4",
  67. /* page: {
  68. align: 'right',//对齐方式,可选left|right | center,默认left
  69. groups: 5,//显示连续页码数量
  70. limit: 10, //每页显示的条数
  71. curr: 1,//当前页
  72. count: -1//总条数
  73. }*/
  74. };
  75. $.rayTableOptions = TableClass.option;
  76. //日期+时间
  77. var regOnlyTime = /^(20|21|22|23|(|[01])\d):(|[0-5])\d(|:(|[0-5])\d)$/;
  78. var regDateTime = /^[1-9]\d{3}\/((|0)[1-9]|1[0-2])\/((|0)[1-9]|[1-2][0-9]|3[0-1])(|\s(20|21|22|23|(|[01])\d):(|[0-5])\d(|:(|[0-5])\d))$/;
  79. Array.prototype.contains = function (needle) {
  80. for (var i in this) {
  81. if (this[i] === needle) return true;
  82. }
  83. return false;
  84. }
  85. Array.prototype.raysort = function (key, desc) {
  86. if (!key) return this;
  87. this.sort(function (o1, o2) {
  88. var v1 = o1[key], v2 = o2[key];
  89. //把空值放在前面
  90. if (v1 && !v2) {
  91. return 1;
  92. } else if (!v1 && v2) {
  93. return -1;
  94. }
  95. //类型不一致
  96. var type_v1 = typeof v1, type_v2 = typeof v2;
  97. if (type_v1 !== type_v2) {
  98. return v1 > v2 ? 1 : -1;
  99. }
  100. //return>0,交换位置
  101. //数字
  102. if (type_v1 === "number")
  103. return v1 - v2;
  104. //字符串数字
  105. if (!isNaN(v1) && !isNaN(v2))
  106. return parseFloat(v1) - parseFloat(v2);
  107. //时间
  108. var tmpV1 = v1.replace(/-/g, '/'), tmpV2 = v2.replace(/-/g, '/');
  109. var isdate_v1 = regDateTime.test(tmpV1) || regOnlyTime.test(tmpV1);
  110. var isdate_v2 = regDateTime.test(tmpV2) || regOnlyTime.test(tmpV2);
  111. if (isdate_v1 && isdate_v2) {
  112. return new Date(tmpV1) - new Date(tmpV2);
  113. }
  114. //字符
  115. return v1 > v2 ? 1 : -1;
  116. });
  117. desc && this.reverse(); //倒序
  118. return this;
  119. }
  120. var serialnum = 0;
  121. function getNum() {
  122. return serialnum++;
  123. }
  124. TableClass.utils = {
  125. //只运行一次
  126. initDefault: function () {
  127. //计算浏览横向滚动条的高度和竖向滚动条的宽度
  128. var $div = $("<div/>").appendTo($("body"));
  129. $div.width(100).height(100).css("overflow", "scroll");
  130. var elem = $div[0];
  131. scrollGap.width = elem.offsetHeight - elem.clientHeight;
  132. scrollGap.height = elem.offsetWidth - elem.clientWidth;
  133. $div.remove();
  134. },
  135. init: function () {
  136. var that = this,
  137. $t = $(this.elem),
  138. options = that.options;
  139. if (options.data && options.data instanceof Array)
  140. tableCache.datas[that.tableIndex] = options.data;
  141. else
  142. tableCache.datas[that.tableIndex] = [];
  143. var addExpand = false, cols = tableCache.cols[that.tableIndex] = [];
  144. options.colsCount = 0;
  145. options.autoColNums = 0;
  146. options.minWidth = 0;
  147. options.autoCols = {};
  148. debugger
  149. var cellcss = options.cellcss = {}, othercss = {},
  150. tableHead = (function () {
  151. var str = [];
  152. str.push('<table class="laytable-head"><thead>');
  153. $(options.cols).each(function (a1, list) {
  154. str.push('<tr>');
  155. //是否支持展开
  156. if (!addExpand && options.expandRow) {
  157. addExpand = true;
  158. str.push('<th rowspan="' + options.cols.length + '"><span class="laytable-expand"></span></th>');
  159. options.minWidth += 37;//左右padding各10px+内容16px+右边框1px
  160. }
  161. $(list).each(function (a, b) {
  162. //表头和数据共有样式
  163. var cellclass = "laytable-cell-" + that.tableIndex + "-" + (b.field ? b.field : getNum());
  164. var curCellCss = cellcss[cellclass] = {};
  165. //表头特有样式
  166. var headclass = "laytable-cell-head-" + that.tableIndex + "-" + (b.field ? b.field : getNum());
  167. var curheadCellCss = othercss[headclass] = {};
  168. //数据特有样式
  169. var curDataCellCss;
  170. if (b.field) {
  171. var dataclass = "laytable-cell-data-" + that.tableIndex + "-" + (b.field ? b.field : getNum());
  172. curDataCellCss = othercss[dataclass] = {};
  173. }
  174. b.field && cols.push(b);
  175. //计算css样式宽度
  176. if (!b.hidden && b.field) {
  177. if (b.width) {
  178. if (/^\d+$/.test(b.width)) {
  179. curCellCss.width = b.width + "px";
  180. curCellCss["min-width"] = Math.min(options.cellMinWidth, b.width) + "px";
  181. options.minWidth += b.width;
  182. } else if (/^\d+%$/.test(b.width) || b.width === "*") {
  183. options.widthType = true;
  184. curCellCss.width = b.width;
  185. curCellCss["min-width"] = options.cellMinWidth + "px";
  186. options.minWidth += options.cellMinWidth;
  187. }
  188. } else {
  189. var minW = b.minWidth || options.cellMinWidth;
  190. curCellCss["min-width"] = minW + "px";
  191. options.minWidth += minW;
  192. options.autoCols[b.field] = {};
  193. options.autoCols[b.field].minWidth = minW;
  194. options.autoColNums++;
  195. }
  196. options.colsCount++;
  197. }
  198. b.align && (curCellCss["text-align"] = b.align);
  199. //表头特有样式
  200. b.style && (function () {
  201. for (var c in b.style)
  202. curheadCellCss[c] = b.style[c];
  203. })();
  204. //数据特有样式
  205. (b.field && b.dataStyle) && (function () {
  206. for (var c in b.dataStyle)
  207. curDataCellCss[c] = b.dataStyle[c];
  208. })();
  209. str.push('<th class="' + cellclass);
  210. //是否可拖拽,因为动态隐藏滚动条问题,固定列不支持拖拽宽度,暂时
  211. str.push(b.field ? (b.resize ? " laytable-cell-resize" : "") : "");
  212. str.push(b.style ? ' ' + headclass : '');
  213. str.push(b.hidden ? ' hidden' : '');
  214. str.push(b.sort ? ' laytable-sort-th' : '');
  215. str.push(options.nowrap ? ' nowrap' : '');
  216. str.push('"');//class结束
  217. str.push(b.colspan ? ' colspan=' + b.colspan : '');
  218. str.push(b.fixed ? ' fixed=' + b.fixed : '');
  219. str.push(b.rowspan ? ' rowspan=' + b.rowspan : '');
  220. str.push(b.field ? ' data-field="' + b.field + '"' : '');
  221. str.push(b.islink ? ' islink' : '');
  222. //str.push(b.sort ? ' data-type="' + (typeof b.sort === "string" ? b.sort : 's') + '"' : '');
  223. str.push('>');//th前半开
  224. //内容
  225. var thContent;
  226. if (b.field === 'chk') {
  227. //checkbox
  228. thContent = '<input type="checkbox" class="rayui-chk" chk="all" ' + (options.singleSelect ? 'disabled' : '') + '/>';
  229. } else {
  230. thContent = b.title === undef ? "" : b.title;
  231. }
  232. thContent += (b.sort ? '<span class="laytable-sort-span"><i class="laytable-sort laytable-desc"></i><i class="laytable-sort laytable-asc" ></i></span>' : '');
  233. str.push(options.nowrap ? '<div class="' + cellclass + ' ' + headclass + '">' + thContent + '</div>' : thContent);
  234. str.push('</th>');
  235. });
  236. str.push("</tr>");
  237. });
  238. str.push("</thead></table>");
  239. return str.join('');
  240. })(),
  241. tablebody = '<table class="laytable-body"' + (options.even ? ' ray-even' : '') + '><tbody></tbody></table>',
  242. tableMain = [
  243. '<div class="laytable-box" style="',
  244. 'min-height:' + options.minHeight + 'px',
  245. options.width ? ';width:' + options.width + 'px' : '',
  246. '"',//end style
  247. options.skin ? ' skin="' + options.skin + '"' : '',
  248. '>',
  249. '<div class="laytable-head-boxmain">',
  250. '<div class="laytable-head-box">',
  251. tableHead,
  252. '</div>',
  253. '</div>',//end laytable-head-boxmain
  254. '<div class="laytable-body-boxmain">',
  255. '<div class="laytable-body-box" scroll-left=1>',
  256. tablebody,
  257. '</div>',
  258. '</div>',//end laytable-body-boxmain
  259. '<div class="laytable-fixed laytable-fixed-l"></div>',
  260. '<div class="laytable-fixed laytable-fixed-r"></div>',
  261. options.page ? '<div class="laytable-page-boxmain" style="text-align:' + options.page.align + '"></div>' : '',
  262. '<div class="laytable-style">',
  263. '</div>',
  264. '<style>',
  265. (function () {
  266. var ss = [], isempty;
  267. //这里只写其他样式,cell共有样式需要在首次初始化数据添加
  268. for (var css in othercss) {
  269. isempty = true;
  270. for (var key in othercss[css]) {
  271. if (isempty) {
  272. ss.push("." + css + "{");
  273. isempty = false;
  274. }
  275. ss.push(key + ":" + othercss[css][key] + ";");
  276. }
  277. if (!isempty)
  278. ss.push("}");
  279. }
  280. return ss.join('');
  281. })(),
  282. '</style>',
  283. '</div>'
  284. ].join('');
  285. $t.after(tableMain);
  286. //提前设定选择器
  287. TableClass.utils.jqSelector.call(that);
  288. //没有写url,认为是本地分页
  289. if (options.url) {
  290. TableClass.utils.initHeight.call(that);
  291. //ajax请求数据
  292. TableClass.utils.ajaxData.call(that);
  293. } else {
  294. TableClass.utils.onRecvData.call(that);
  295. }
  296. },
  297. jqSelector: function () {
  298. var that = this;
  299. var jqobjs = tableCache.jqobjs[that.tableIndex] = {};
  300. jqobjs.tb_box = $(this.elem).next("div.laytable-box");
  301. //固定表头和列
  302. jqobjs.tb_fixed = jqobjs.tb_box.find(">div.laytable-fixed");
  303. jqobjs.tb_fixed_l = jqobjs.tb_box.find(">div.laytable-fixed-l");
  304. jqobjs.tb_fixed_r = jqobjs.tb_box.find(">div.laytable-fixed-r");
  305. //thead
  306. jqobjs.tb_head_boxmain = jqobjs.tb_box.find("div.laytable-head-boxmain");
  307. jqobjs.tb_head_box = jqobjs.tb_head_boxmain.find("div.laytable-head-box");
  308. jqobjs.tb_head_fixed_l = jqobjs.tb_head_boxmain.find("div.laytable-fixed-l");
  309. jqobjs.tb_head_fixed_r = jqobjs.tb_head_boxmain.find("div.laytable-fixed-r");
  310. jqobjs.tb_head = jqobjs.tb_head_box.find(">table");
  311. //tbody
  312. jqobjs.tb_body_boxmain = jqobjs.tb_box.find("div.laytable-body-boxmain");
  313. jqobjs.tb_body_box = jqobjs.tb_body_boxmain.find("div.laytable-body-box");
  314. jqobjs.tb_body_fixed_l = jqobjs.tb_body_boxmain.find("div.laytable-fixed-l");
  315. jqobjs.tb_body_fixed_r = jqobjs.tb_body_boxmain.find("div.laytable-fixed-r");
  316. jqobjs.tb_body = jqobjs.tb_body_box.find(">table");
  317. //page
  318. jqobjs.tb_page_box = jqobjs.tb_box.find("div.laytable-page-boxmain");
  319. jqobjs.tb_head_body = jqobjs.tb_box.find("div.laytable-head-boxmain>div.laytable-head-box>table,div.laytable-body-boxmain>div.laytable-body-box>table");
  320. //css
  321. jqobjs.div_style = jqobjs.tb_box.find("div.laytable-style");
  322. },
  323. onRecvData: function () {
  324. var that = this,
  325. options = that.options;
  326. if (options.initComplete == undef) {
  327. options.initComplete = true;
  328. //设置样式
  329. var jqobjs = tableCache.jqobjs[that.tableIndex];
  330. //设置表格法最小宽度
  331. options.minWidth += options.colsCount;
  332. jqobjs.tb_head_body.css("min-width", options.minWidth + "px");
  333. //顺序不能变
  334. TableClass.utils.renderData.call(that);
  335. TableClass.utils.initStyle.call(that);
  336. TableClass.utils.initPage.call(that);
  337. //表头固定列
  338. TableClass.utils.initFixedHead.call(that);
  339. TableClass.utils.changePaging.call(that);
  340. TableClass.utils.modifyStyle.call(that);
  341. TableClass.utils.addEvents.call(that);
  342. } else {
  343. TableClass.utils.renderData.call(that);
  344. TableClass.utils.changePaging.call(that);
  345. TableClass.utils.modifyStyle.call(that);
  346. }
  347. },
  348. ajaxData: function () {
  349. var that = this,
  350. options = that.options;
  351. TableClass.utils.showError.call(that, 0);
  352. TableClass.utils.loading.call(that, 1);
  353. var data = {};
  354. if (options.where)
  355. $.extend(data, options.where);
  356. if (options.page)
  357. $.extend(data, { page: options.page.curr, limit: options.page.limit });
  358. if (options.initSort)
  359. $.extend(data, options.initSort);
  360. $.ajax({
  361. type: options.method || "get",
  362. url: options.url,
  363. data: data,
  364. dataType: "json",
  365. beforeSend: function (xhr) {
  366. if (typeof options.onAjaxBeforeSend === "function" &&
  367. options.onAjaxBeforeSend.call(this, xhr) === false) {
  368. xhr.abort();
  369. }
  370. },
  371. success: function (result) {
  372. //清除数据
  373. TableClass.utils.clearData.call(that);
  374. if (typeof options.onAjaxSuccess === "function")
  375. result = options.onAjaxSuccess.call(this, result) || result;
  376. //result数据格式:code,msg,count,data
  377. var code = result["ret"];
  378. if (code !== 0) {
  379. TableClass.utils.showError.call(that, (result["msg"] || "返回的数据状态异常"));
  380. }
  381. tableCache.datas[that.tableIndex] = result["data"] || [];
  382. options.page.count = result["count"] || 0;
  383. code === 0 && TableClass.utils.onRecvData.call(that);
  384. //所有处理完毕
  385. typeof options.onComplete === "function" && options.onComplete(result);
  386. },
  387. error: function (xhr, textStatus, errorThrown) {
  388. TableClass.utils.showError.call(that, "请求数据接口异常");
  389. //所有处理完毕
  390. typeof options.onAjaxError === "function" && options.onAjaxError.call(this, xhr, textStatus, errorThrown);
  391. },
  392. complete: function () {
  393. TableClass.utils.loading.call(that, 0);
  394. }
  395. });
  396. },
  397. //type:0关闭1显示
  398. loading: function (type) {
  399. var that = this,
  400. options = that.options;
  401. if (!options.loading) return;
  402. var jqobjs = tableCache.jqobjs[that.tableIndex],
  403. $tbox = jqobjs.tb_box,
  404. $loading = jqobjs.tb_box.find("div.laytable-loading");
  405. if (type === 0) {
  406. $loading.remove();
  407. return;
  408. }
  409. if (type === 1 && options.loading && options.url) {
  410. $('<div class="laytable-loading"/>')
  411. .css({ "width": $tbox.width() + "px", "height": $tbox.height() + "px" })
  412. .appendTo($tbox);
  413. }
  414. },
  415. showError: function (msg) {
  416. var that = this,
  417. jqobjs = tableCache.jqobjs[that.tableIndex],
  418. $diverr = jqobjs.tb_body_box.find("div.laytable-msg");
  419. if (msg === 0) {
  420. $diverr.remove();
  421. return;
  422. }
  423. if ($diverr.length === 0)
  424. $diverr = $('<div class="laytable-msg"/>').appendTo(jqobjs.tb_body_box);
  425. $diverr.html(msg);
  426. },
  427. initStyle: function () {
  428. var that = this,
  429. options = that.options,
  430. jqobjs = tableCache.jqobjs[that.tableIndex];
  431. //设置共有样式,只初始化时运行一次
  432. if (options.cellcss) {
  433. var cellcss = options.cellcss;
  434. var ss = [], isempty, css;
  435. ss.push("<style>");
  436. //这里只写其他样式,cell共有样式需要在首次初始化数据添加
  437. for (css in cellcss) {
  438. isempty = true;
  439. for (var key in cellcss[css]) {
  440. if (isempty) {
  441. ss.push("." + css + "{");
  442. isempty = false;
  443. }
  444. ss.push(key + ":" + cellcss[css][key] + ";");
  445. }
  446. if (!isempty)
  447. ss.push("}");
  448. }
  449. ss.push("</style>");
  450. jqobjs.div_style.html(ss.join(''));
  451. //设置自动列样式
  452. isempty = true;
  453. for (var field in options.autoCols) {
  454. isempty = false;
  455. css = ".laytable-cell-" + that.tableIndex + "-" + field;
  456. var style = TableClass.utils.getCssStyle.call(that, css);
  457. options.autoCols[field].style = style;
  458. }
  459. isempty && (options.autoCols = undef);
  460. options.cellcss = undef;
  461. }
  462. },
  463. modifyStyle: function () {
  464. var that = this;
  465. TableClass.utils.fullHeight.call(that);
  466. TableClass.utils.fullWidth.call(that);
  467. TableClass.utils.adjustPercentWidth.call(that);
  468. TableClass.utils.modifyFixedHeight.call(that);
  469. },
  470. initFixedHead: function () {
  471. var that = this,
  472. jqobjs = tableCache.jqobjs[that.tableIndex],
  473. $tbhead = jqobjs.tb_head,
  474. tbTop = jqobjs.tb_box.offset().top;
  475. var htmlL = [], htmlR = [], leftTop = -1000, rightTop = -1000, isInsertL, isInsertR;
  476. $tbhead.find("tr").each(function () {
  477. isInsertL = isInsertR = false;
  478. var $trobj = $(this);
  479. $(this).find("th").each(function () {
  480. var fixed = $(this).attr("fixed");
  481. var objClone;
  482. if (fixed === 'left') {
  483. leftTop === -1000 && (leftTop = $(this).offset().top);
  484. if (!isInsertL) { isInsertL = true; htmlL.push('<tr style="height:' + $trobj.height() + 'px">'); }
  485. objClone = $(this).clone();
  486. htmlL.push(objClone[0].outerHTML);
  487. } else if (fixed === 'right') {
  488. rightTop === -1000 && (rightTop = $(this).offset().top);
  489. if (!isInsertR) { isInsertR = true; htmlR.push('<tr style="height:' + $trobj.height() + 'px">'); }
  490. objClone = $(this).clone();
  491. htmlR.push(objClone[0].outerHTML);
  492. }
  493. });
  494. if (isInsertL) htmlL.push("</tr>");
  495. if (isInsertR) htmlR.push("</tr>");
  496. });
  497. if (htmlL.length !== 0) {
  498. var $headFixedL = $('<div class="laytable-head-box" />');
  499. $headFixedL.html('<table class="laytable-head"><thead>' + htmlL.join('') + "</thead></table>")
  500. .prependTo(jqobjs.tb_fixed_l.css("top", (leftTop - tbTop - 1) + "px"));
  501. }
  502. if (htmlR.length !== 0) {
  503. var $headFixedR = $('<div class="laytable-head-box" />');
  504. $headFixedR.html('<table class="laytable-head"><thead>' + htmlR.join('') + "</thead></table>")
  505. .prependTo(jqobjs.tb_fixed_r.css("top", (rightTop - tbTop - 1) + "px"));
  506. //右侧宽度滚动条问题
  507. jqobjs.tb_fixed_r.css("right", scrollGap.width + "px");
  508. jqobjs.tb_box.find(".laytable-fixed-amend")
  509. .height($headFixedR.height() - 1)//1:自己下边框
  510. .css("top", (rightTop - tbTop - 2) + "px") //2:自己和td的border
  511. .css("right", scrollGap.width - 49 + "px"); //amend宽度50,减去自己的左边框1px
  512. }
  513. },
  514. renderData: function () {
  515. var that = this,
  516. jqobjs = tableCache.jqobjs[that.tableIndex],
  517. $tbody = jqobjs.tb_body.find(">tbody"),
  518. options = that.options,
  519. data = TableClass.utils.getData.call(that);
  520. //清除数据
  521. TableClass.utils.clearData.call(that);
  522. //设置表头排序图标
  523. if (options.initSort)
  524. jqobjs.tb_box.find(".laytable-head th[data-field=" + options.initSort.sortField + "]").attr("sort-type", options.initSort.sortType);
  525. if (data.length === 0) {
  526. TableClass.utils.showError.call(that, "无数据");
  527. return;
  528. }
  529. //合并单元格,instanceof为field数组
  530. if (options.colspanDefs && options.colspanDefs instanceof Array) {
  531. var preValue = {}, firstData = data[0], count = data.length;
  532. if (count > 1) {
  533. $.each(options.colspanDefs, function (a, key) {
  534. if (firstData.hasOwnProperty(key)) {
  535. firstData[key + "rowspan"] = 1;
  536. preValue[key] = firstData;
  537. }
  538. });
  539. var i;
  540. for (i = 1; i < count; i++) {
  541. var model = data[i];
  542. for (var key in preValue) {
  543. if (model[key] === preValue[key][key]) {
  544. preValue[key][key + "rowspan"]++;
  545. model[key + "rowspan"] = -1;//默认隐藏
  546. } else {
  547. preValue[key] = model;
  548. model[key + "rowspan"] = 1;
  549. }
  550. }
  551. }
  552. }
  553. preValue = null;
  554. }
  555. //添加数据
  556. var $fixedtbodyl = jqobjs.tb_fixed_l.find("div.laytable-body-noscroll table>tbody"),
  557. $fixedtbodyr = jqobjs.tb_fixed_r.find("div.laytable-body-noscroll table>tbody");
  558. var cols = tableCache.cols[that.tableIndex], trs_fixed_l = [], trs_fixed_r = [];
  559. $(data).each(function (a, b) {
  560. var trs = [], trs_fixed_l_one = [], trs_fixed_r_one = [];
  561. //添加数据前
  562. typeof options.onBeforeAddRow === "function" && options.onBeforeAddRow(a, b);
  563. trs.push('<tr data-index=' + a + '>');
  564. if (options.expandRow) {
  565. trs.push('<td><a class="laytable-expand"></a></td>');
  566. }
  567. $.each(cols, function (c, opt) {
  568. var td = [],
  569. field = opt.field,
  570. cellCss = 'laytable-cell-' + that.tableIndex + '-' + field,
  571. rowspan = b[field + "rowspan"];
  572. td.push('<td data-field="' + field + '"');
  573. if (rowspan !== undef && rowspan > 1)
  574. td.push(' rowspan=' + rowspan);
  575. td.push(' class="' + cellCss);
  576. if (!options.nowrap)
  577. td.push(' laytable-cell-data-' + that.tableIndex + '-' + field);
  578. td.push(opt.hidden ? ' hidden' : '');
  579. td.push(options.nowrap ? ' nowrap' : '');
  580. if (rowspan !== undef && rowspan === -1)
  581. td.push(' hiddenImp');
  582. td.push('"');//end class
  583. td.push(opt.islink ? ' islink' : '');
  584. td.push('>');
  585. var value;
  586. if (typeof opt.formatter === "function") {
  587. //formatter函数
  588. value = opt.formatter(b[field], b, a);
  589. //模板
  590. } else if (field === 'chk') {
  591. //checkbox
  592. value = '<input type="checkbox" class="rayui-chk" chk="row"/>';
  593. } else {
  594. value = b[field];
  595. if (opt.dataType === "html" && value !== undef && value !== '')
  596. value = value.replace(/[<>&"]/g, function (c) { return { '<': '&lt;', '>': '&gt;', '&': '&amp;', '"': '&quot;' }[c]; });
  597. }
  598. if (value === undef || value === '')
  599. value = "&nbsp;";
  600. td.push(options.nowrap ? '<div class="' + cellCss + ' laytable-cell-data-' + that.tableIndex + '-' + field + '">' + value + '</div>' : value);
  601. td.push('</td>');
  602. var strTmp = td.join('');
  603. trs.push(strTmp);
  604. opt.fixed === 'left' && (trs_fixed_l_one.push(strTmp));
  605. opt.fixed === 'right' && (trs_fixed_r_one.push(strTmp));
  606. });
  607. trs.push("</tr>");
  608. var strHtml = trs.join('');
  609. var $tr = $("" + strHtml);
  610. $tr.appendTo($tbody);
  611. //首次复制数据设置行高度
  612. if (trs_fixed_l_one.length > 0) {
  613. trs_fixed_l.push('<tr data-index=' + a + ' style="height:' + $tr.height() + 'px">' + trs_fixed_l_one.join('') + "</tr>");
  614. trs_fixed_l_one = [];
  615. }
  616. if (trs_fixed_r_one.length > 0) {
  617. trs_fixed_r.push('<tr data-index=' + a + ' style="height:' + $tr.height() + 'px">' + trs_fixed_r_one.join('') + "</tr>");
  618. trs_fixed_r_one = [];
  619. }
  620. //添加数据后
  621. typeof options.onAddRow === "function" && options.onAddRow(a, $tr, b);
  622. });
  623. data = null;
  624. //添加固定列数据
  625. if (trs_fixed_l.length > 0) {
  626. if ($fixedtbodyl.length === 0) {
  627. $('<div class="laytable-body-noscroll" />').html($('<div class="laytable-body-box" />')
  628. .html('<table class="laytable-body"' + (options.even ? ' ray-even' : '') + '>' + trs_fixed_l.join('') + '</table>'))
  629. .appendTo(jqobjs.tb_fixed_l);
  630. } else {
  631. $fixedtbodyl.html(trs_fixed_l.join(''));
  632. }
  633. }
  634. if (trs_fixed_r.length > 0) {
  635. if ($fixedtbodyr.length === 0) {
  636. $('<div class="laytable-body-noscroll" />').html($('<div class="laytable-body-box" />')
  637. .html('<table class="laytable-body"' + (options.even ? ' ray-even' : '') + '>' + trs_fixed_r.join('') + '</table>'))
  638. .appendTo(jqobjs.tb_fixed_r);
  639. //添加补丁
  640. $('<div class="laytable-fixed-amend"/>').appendTo(jqobjs.tb_box);
  641. } else {
  642. $fixedtbodyr.html(trs_fixed_r.join(''));
  643. }
  644. }
  645. },
  646. initHeight: function () {
  647. var that = this,
  648. $t = $(this.elem),
  649. options = that.options,
  650. jqobjs = tableCache.jqobjs[that.tableIndex],
  651. $theaddiv = jqobjs.tb_head_box,
  652. $tpagediv = jqobjs.tb_page_box,
  653. $tbodydiv = jqobjs.tb_body_box,
  654. fullHeightGap;
  655. !options.heightSetting && (options.heightSetting = options.height);
  656. if (/^full-\d+$/.test(options.heightSetting)) {//full-差距值
  657. fullHeightGap = options.heightSetting.split('-')[1];
  658. options.height = $win.height() - fullHeightGap;
  659. } else if (/^sel-[#|.][\w]+-\d+$/.test(options.heightSetting)) { //sel-id序列-差距值
  660. fullHeightGap = $t.offset().top;
  661. var list = options.heightSetting.split('-');
  662. $("" + list[1]).each(function () {
  663. fullHeightGap += $(this).outerHeight();
  664. });
  665. if (list.length === 3) fullHeightGap += parseInt(list[2]);
  666. options.height = $win.height() - fullHeightGap;
  667. }
  668. //最终高度不能小于最小高度
  669. if (options.height < options.minHeight) options.height = options.minHeight;
  670. //数据高度-head-page-2px(laytable-box上下各1px border)
  671. var tmpH = options.height - $theaddiv.outerHeight() - $tpagediv.outerHeight() - 2;
  672. $tbodydiv.outerHeight(tmpH);//数据表格设置高度
  673. },
  674. fullHeight: function () {
  675. //计算高
  676. var that = this,
  677. options = that.options;
  678. var jqobjs = tableCache.jqobjs[that.tableIndex],
  679. $theaddiv = jqobjs.tb_head_box,
  680. $tbodydiv = jqobjs.tb_body_box;
  681. //如果设置的是固定高度,则无需再设置了,ajax时initHeight方法会调用两遍
  682. if (!/^\d+$/.test(options.heightSetting)) TableClass.utils.initHeight.call(that);
  683. var tbodydiv = $tbodydiv[0];
  684. if (tbodydiv.scrollHeight > tbodydiv.clientHeight) {
  685. //说明有竖向滚动条
  686. $theaddiv.css("margin-right", (scrollGap.width) + "px");
  687. //右侧固定和数据最右侧列还原右边框
  688. jqobjs.tb_fixed_r.find("tr>td:last,th:last").removeClass("last");
  689. jqobjs.tb_fixed_r.css("right", scrollGap.width + "px");
  690. } else {
  691. $theaddiv.css("margin-right", "0");
  692. //右侧固定和数据最右侧列移除右边框
  693. jqobjs.tb_fixed_r.find("tr").each(function () {
  694. $(this).find("td:last,th:last").addClass("last");
  695. });
  696. jqobjs.tb_fixed_r.css("right", "0");
  697. }
  698. //数据高度大于数据box高度时,body最后一行去除下边框
  699. var lastTrs = jqobjs.tb_box.find(".laytable-body").find("tr:last");
  700. if ($tbodydiv.find(".laytable-body").outerHeight() >= $tbodydiv.outerHeight()) {
  701. lastTrs.addClass("last");
  702. } else {
  703. lastTrs.removeClass("last");
  704. }
  705. },
  706. //自适应宽度以数据宽度为准
  707. fullWidth: function () {
  708. var that = this,
  709. options = that.options,
  710. jqobjs = tableCache.jqobjs[that.tableIndex],
  711. $tb_data_first_tr = jqobjs.tb_body.find("tr:first"),
  712. $tbodydiv = jqobjs.tb_body_box,
  713. tbodydiv = $tbodydiv[0];
  714. //有自适应列时动态修改表头宽度
  715. if (options.autoCols && !options.resized) {
  716. var field, w, autoMinWidth = 0;
  717. //必须,为了自适应数据宽度
  718. for (field in options.autoCols) {
  719. options.autoCols[field].style.style.width = "";
  720. autoMinWidth += options.autoCols[field].minWidth;
  721. }
  722. //如果table小于div宽度就100%
  723. tbodydiv.clientWidth > options.minWidth && (jqobjs.tb_head_body.css("width", "100%"));
  724. if (!options.nowrap) {
  725. //允许换行,使用table的自适应宽度
  726. for (field in options.autoCols) {
  727. //需要减去右边框1px,否则总是出现横向滚动条,不要使用width函数
  728. w = $tb_data_first_tr.find("td[data-field=" + field + "]").outerWidth();
  729. options.autoCols[field].style.style.width = w - 1 + "px";
  730. }
  731. } else {
  732. //不允许换行
  733. var obj, aver = 0;
  734. if (tbodydiv.clientWidth > options.minWidth) {
  735. var widthGap = tbodydiv.clientWidth - options.minWidth;
  736. aver = Math.floor(widthGap / options.autoColNums);
  737. }
  738. for (field in options.autoCols) {
  739. obj = options.autoCols[field];
  740. obj.style.style.width = obj.minWidth + aver + "px";
  741. }
  742. }
  743. //修正头部滚动条
  744. jqobjs.tb_head_box.scrollLeft($tbodydiv.scrollLeft());
  745. }
  746. //修改div宽度隐藏固定列滚动条
  747. var clientH = Math.min(tbodydiv.clientHeight, jqobjs.tb_body.height()),//取bodydiv和table的最小高度
  748. $tbody_fixed_box_noscroll = jqobjs.tb_box.find("div.laytable-fixed .laytable-body-noscroll");
  749. $tbody_fixed_box_noscroll.each(function () {
  750. var innerTablediv = $(this).find(">.laytable-body-box"),
  751. tbodyWidth = innerTablediv.find(".laytable-body").width();
  752. innerTablediv.outerHeight(clientH).outerWidth(tbodyWidth + scrollGap.width);
  753. $(this).outerWidth(tbodyWidth);
  754. });
  755. //判断是否去掉最后一列边框,数据宽度大于数据box可视宽度时去掉右边框
  756. if ($tbodydiv.find(".laytable-body").outerWidth() < tbodydiv.clientWidth) {
  757. jqobjs.tb_body.find("tr>td.last").removeClass("last");
  758. jqobjs.tb_head.find("tr>th.last").removeClass("last");
  759. } else {
  760. jqobjs.tb_body.find("tr").each(function () {
  761. $(this).find("td:last").addClass("last");
  762. });
  763. jqobjs.tb_head.find("tr").each(function () {
  764. $(this).find("th:last").addClass("last");
  765. });
  766. }
  767. },
  768. adjustPercentWidth: function () {
  769. var that = this,
  770. options = that.options,
  771. jqobjs = tableCache.jqobjs[that.tableIndex];
  772. //百分比宽度
  773. if (options.widthType && !options.resized) {
  774. var cols = tableCache.cols[that.tableIndex],
  775. totalWidth = jqobjs.tb_head_box.width() - cols.length,
  776. surplus = totalWidth, fieldStartCss, ww = 0;
  777. $.each(cols, function (c, opt) {
  778. var field = opt.field,
  779. cellClass = '.laytable-cell-' + that.tableIndex + '-' + field,
  780. cellCss = TableClass.utils.getCssStyle.call(that, cellClass);
  781. if (opt.width === "*") {
  782. fieldStartCss = cellCss;
  783. return true;
  784. }
  785. var percent = opt.width.replace("%", ""),
  786. width = totalWidth / 100 * (parseFloat(percent));
  787. width = Math.floor(width);//解决那零点几导致的横向滚动条
  788. cellCss.style.width = width + "px";
  789. if (width < options.cellMinWidth) cellCss.style["min-width"] = width + "px";
  790. surplus -= width;
  791. ww += width;
  792. return true;
  793. });
  794. if (fieldStartCss) {
  795. fieldStartCss.style.width = surplus + "px";
  796. if (surplus < options.cellMinWidth) fieldStartCss.style["min-width"] = surplus + "px";
  797. }
  798. }
  799. },
  800. modifyFixedHeight: function (isneedAmendHead) {
  801. var that = this,
  802. jqobjs = tableCache.jqobjs[that.tableIndex],
  803. tbody_box = jqobjs.tb_body_box[0],
  804. $fixed_r = jqobjs.tb_fixed_r,
  805. options = that.options;
  806. //修改复制数据的高度,数据不自动换行时不需要调整
  807. if (!options.nowrap) {
  808. //不管本地数据还是ajax数据
  809. var $tbody = jqobjs.tb_body.find(">tbody"),
  810. body_fixed = jqobjs.tb_fixed.find(".laytable-body-box>table");
  811. if (body_fixed.length > 0) {
  812. $tbody.find("tr").each(function (a) {
  813. body_fixed.find("tr:eq(" + a + ")").outerHeight($(this).outerHeight());
  814. });
  815. }
  816. }
  817. //有自动列宽时,或则拖拽时(由拖拽自己判断),动态修改固定列表头行高
  818. if (isneedAmendHead || options.autoColNums > 0) {
  819. //修改表头高度,如果设置表头宽度合理一般不用修改,设置不合理也不好看
  820. //注意多行固定问题,倒着修改正好
  821. var head_fixed_l = jqobjs.tb_fixed_l.find(".laytable-head"),
  822. head_fixed_r = jqobjs.tb_fixed_r.find(".laytable-head"),
  823. head = jqobjs.tb_head,
  824. trheadCount = head.find("tr").length;
  825. var trc = head_fixed_l.find("tr").length, tmp, index;
  826. if (trc > 0) {
  827. tmp = trheadCount - 1; index = trc - 1;
  828. while (index >= 0) {
  829. head_fixed_l.find("tr:eq(" + (index--) + ")").height(head.find("tr:eq(" + (tmp--) + ")").height());
  830. }
  831. }
  832. trc = head_fixed_r.find("tr").length;
  833. if (trc > 0) {
  834. tmp = trheadCount - 1; index = trc - 1;
  835. var trh = 0, datatrH;
  836. while (index >= 0) {
  837. datatrH = head.find("tr:eq(" + (tmp--) + ")").height();
  838. trh += datatrH;
  839. head_fixed_r.find("tr:eq(" + (index--) + ")").height(datatrH);
  840. }
  841. //修改amend的高度
  842. jqobjs.tb_box.find('div.laytable-fixed-amend').height(trh - 1);//1自己下边框
  843. }
  844. }//end if
  845. //判断是否隐藏右侧固定列
  846. if ($fixed_r.children().length > 0) {
  847. if (tbody_box.scrollWidth > tbody_box.clientWidth) {
  848. //有横向滚动条,有滚动条事件所以不能隐藏(隐藏后滚动无效),这里只能使用飘出
  849. $fixed_r.removeClass("blowout-right");
  850. //右侧固定列显示时,判断是否有竖向滚动条,有amend就显示
  851. if (tbody_box.scrollHeight > tbody_box.clientHeight)
  852. jqobjs.tb_box.find('div.laytable-fixed-amend').removeClass("hidden");
  853. } else {
  854. $fixed_r.addClass("blowout-right");
  855. //右侧固定列隐藏时,amend必须隐藏
  856. jqobjs.tb_box.find('div.laytable-fixed-amend').addClass("hidden");
  857. }
  858. }
  859. },
  860. getPageData: function () {
  861. var that = this,
  862. page = that.options.page,
  863. data = tableCache.datas[that.tableIndex],
  864. onePageData = [];
  865. var count = data.length, start = 0, end = data.length;
  866. if (page) {
  867. start = page.curr === 1 ? 0 : (page.curr - 1) * page.limit;
  868. end = page.curr * page.limit;
  869. }
  870. while (start < end) {
  871. if (start >= count) break;
  872. onePageData.push(data[start++]);
  873. }
  874. return onePageData;
  875. },
  876. initPage: function () {
  877. var that = this,
  878. jqobjs = tableCache.jqobjs[that.tableIndex],
  879. options = that.options,
  880. page = options.page;
  881. if (!page) return;
  882. var data = tableCache.datas[that.tableIndex];
  883. //如果没有数据则不显示分页
  884. if (data.length === 0) return;
  885. //分页limit是否在limits里
  886. if (!page.limits.contains(page.limit)) {
  887. page.limits.push(page.limit);
  888. page.limits.sort(function (a, b) { return a - b; });
  889. }
  890. if (!options.url && page.count === -1) page.count = data.length;
  891. if (page.count === 0) return;
  892. var $pagediv = jqobjs.tb_page_box,
  893. curr = page.curr,
  894. raylimits = (function () {
  895. return [
  896. /*'<select class="laytable-page-limits">',
  897. function () {
  898. var strTmp = [];
  899. $(page.limits).each(function (a, b) {
  900. strTmp.push('<option value="' + b + '" ' + (page.limit === b ? "selected" : "") + '>' + b + ' 条/页</option>');
  901. });
  902. return strTmp.join('');
  903. }(),
  904. '</select>',*/
  905. '&nbsp;&nbsp;',
  906. '<span class="laytable-page-count">共 ' + page.count + ' 条</span>',
  907. '<ul class="laytable-page-pagination">',
  908. '</ul>',
  909. '<span>到第&nbsp;</span>',
  910. '<input type="text" class="rayui-input laytable-page-input" min="1" value="' + curr + '" />&nbsp;页',
  911. '&nbsp;&nbsp;',
  912. '<a class="rayui-btn laytable-page-btnok">确定</a>'
  913. ].join('');
  914. })();
  915. $pagediv.html(raylimits);
  916. },
  917. changePaging: function () {
  918. var that = this,
  919. options = that.options;
  920. if (!options.page) return;
  921. var jqobjs = tableCache.jqobjs[that.tableIndex],
  922. $ul = jqobjs.tb_page_box.find(".laytable-page-pagination"),
  923. page = options.page,
  924. pages = Math.ceil(page.count / page.limit);
  925. page.pages = pages;
  926. if (page.curr <= 0) page.curr = 1;
  927. else if (page.curr > pages) page.curr = pages;
  928. var curr = page.curr,
  929. count = page.count,
  930. libtns = [
  931. '<li><a class="page-item page-prev' + (curr === 1 || count === 0 ? " rayui-disabled" : "") + '" value="-1">&lt;</a></li>',
  932. (function () {
  933. var groups = pages < page.groups ? pages : page.groups,
  934. halve = Math.floor((groups - 1) / 2),
  935. end = Math.max(groups, (curr + halve) > pages ? pages : (curr + halve)),
  936. start = (end - groups) < 1 ? 1 : end - groups + 1,
  937. strTmp = [];
  938. //分3部分加载
  939. //part1
  940. if (start > 1)
  941. strTmp.push('<li><a class="page-item" value="1">1</a></li>');
  942. //左分隔符
  943. if (start > 2)
  944. strTmp.push('<li>...</li>');
  945. //part2
  946. while (start <= end) {
  947. strTmp.push('<li><a class="page-item" value="' + start + '">' + (start++) + '</a></li>');
  948. }
  949. //part3
  950. //右分隔符
  951. if (end < pages - 1)
  952. strTmp.push('<li>...</li>');
  953. if (end < pages)
  954. strTmp.push('<li><a class="page-item" value="' + pages + '">' + pages + '</a></li>');
  955. return strTmp.join('');
  956. })(),
  957. '<li><a class="page-item page-last' + (curr === pages || count === 0 ? " rayui-disabled" : "") + '" value="+1">&gt;</a></li>'
  958. ];
  959. $ul.html(libtns.join(''));
  960. //选中当前页面
  961. $ul.find("li>a[value=" + page.curr + "]").addClass("page-active");
  962. //修改总条数
  963. jqobjs.tb_page_box.find(".laytable-page-count").html('共 ' + page.count + ' 条');
  964. },
  965. clearData: function () {
  966. var that = this,
  967. jqobjs = tableCache.jqobjs[that.tableIndex],
  968. $tbody = jqobjs.tb_body.find(">tbody"),
  969. $fixedtbodyl = jqobjs.tb_fixed_l.find("div.laytable-body-noscroll table>tbody"),
  970. $fixedtbodyr = jqobjs.tb_fixed_r.find("div.laytable-body-noscroll table>tbody");
  971. $tbody.html("");
  972. $fixedtbodyl.html("");
  973. $fixedtbodyr.html("");
  974. jqobjs.tb_fixed_l.find(".laytable-body-box").css("height", "");
  975. jqobjs.tb_fixed_r.find(".laytable-body-box").css("height", "");
  976. },
  977. deleteData: function (data) {
  978. var that = this,
  979. options = that.options,
  980. key = options.serialField,
  981. iskey = key !== undef,
  982. datas = tableCache.datas[that.tableIndex],
  983. start, end, count, dataStr;
  984. if (options.url || !options.page) {
  985. //ajax
  986. start = 0;
  987. end = datas.length - 1;
  988. count = datas.length;
  989. } else {
  990. //本地
  991. var page = options.page;
  992. start = page.curr === 1 ? 0 : (page.curr - 1) * page.limit;
  993. end = page.curr * page.limit;
  994. count = datas.length;
  995. }
  996. if (iskey && datas[0].hasOwnProperty(key)) {
  997. while (start < end) {
  998. if (start >= count) break;
  999. if (datas[start][key] === data[key]) {
  1000. datas.splice(start, 1);
  1001. return;
  1002. }
  1003. start++;
  1004. }
  1005. } else {
  1006. dataStr = JSON.stringify(data);
  1007. while (start < end) {
  1008. if (start >= count) break;
  1009. if (JSON.stringify(datas[start]) === dataStr) {
  1010. datas.splice(start, 1);
  1011. return;
  1012. }
  1013. start++;
  1014. }
  1015. }
  1016. },
  1017. reloadx: function (option) {
  1018. option !== undef && $.extend(true, this.options, option);
  1019. debugger
  1020. var that = this;
  1021. //options = that.options,
  1022. var options = option;
  1023. that.options = option;
  1024. that.elem = option.elem;
  1025. this.tableIndex = 0;
  1026. var page = options.page;
  1027. debugger
  1028. if (page) {
  1029. if (page.curr <= 0) page.curr = 1;
  1030. if (page.curr > page.pages) page.curr = page.pages;
  1031. }
  1032. if (options.url) {
  1033. TableClass.utils.ajaxData.call(that);
  1034. } else {
  1035. TableClass.utils.onRecvData.call(that);
  1036. }
  1037. },
  1038. reload: function (option) {
  1039. option !== undef && $.extend(true, this.options, option);
  1040. var that = this,
  1041. options = that.options,
  1042. page = options.page;
  1043. if (page) {
  1044. if (page.curr <= 0) page.curr = 1;
  1045. if (page.curr > page.pages) page.curr = page.pages;
  1046. }
  1047. if (options.url) {
  1048. TableClass.utils.ajaxData.call(that);
  1049. } else {
  1050. TableClass.utils.onRecvData.call(that);
  1051. }
  1052. },
  1053. getCssStyle: function (css) {
  1054. var that = this,
  1055. jqobjs = tableCache.jqobjs[that.tableIndex],
  1056. style = jqobjs.div_style.find("style")[0],
  1057. sheet = style.sheet || style.styleSheet,
  1058. rules = sheet.cssRules || sheet.rules;
  1059. var curCss;
  1060. $(rules).each(function (a, rr) {
  1061. if (css === rr.selectorText) {
  1062. curCss = rr;
  1063. return false;
  1064. }
  1065. return true;
  1066. });
  1067. //如果没有则添加一条,因为初始化的时候保证一定含有,所以这里没必要再添加了
  1068. return curCss;
  1069. },
  1070. getData: function () {
  1071. var that = this,
  1072. options = that.options,
  1073. datas = options.url ? tableCache.datas[that.tableIndex] : TableClass.utils.getPageData.call(that);
  1074. //如果开启本地排序则数据排序
  1075. if (datas.length > 1 && options.initSort && options.localSort)
  1076. datas.raysort(options.initSort.sortField, options.initSort.sortType === 'desc');
  1077. return datas;
  1078. },
  1079. addEvents: function () {
  1080. var that = this,
  1081. dict = {},
  1082. $doc = $(doc),
  1083. $body = $('body'),
  1084. jqobjs = tableCache.jqobjs[that.tableIndex],
  1085. $thisAllTable = jqobjs.tb_head_body,
  1086. $tbodydiv = jqobjs.tb_box.find("div.laytable-body-box"),
  1087. $page = jqobjs.tb_page_box,
  1088. options = that.options,
  1089. isresizing = false,
  1090. page = options.page;
  1091. //拖拽调整宽度
  1092. jqobjs.tb_box.find(".laytable-head").on('mousemove.laytable', "th[class*=laytable-cell-resize]", function (e) {
  1093. if (dict.resizeStart) return;
  1094. var othis = $(this),
  1095. oLeft = othis.offset().left,
  1096. pLeft = e.clientX - oLeft;
  1097. //是否处于拖拽允许区域
  1098. dict.allowResize = othis.outerWidth() - pLeft <= 10;
  1099. $body.css('cursor', (dict.allowResize ? 'col-resize' : ''));
  1100. }).on('mouseleave.laytable', "th[class*=laytable-cell-resize]", function () {
  1101. if (dict.resizeStart) return;
  1102. $body.css('cursor', '');
  1103. }).on('mousedown.laytable', "th[class*=laytable-cell-resize]", function (e) {
  1104. if (dict.allowResize) {
  1105. e.preventDefault();
  1106. var $othis = $(this);
  1107. dict.elem = this;
  1108. dict.width = $othis.width();
  1109. dict.resizeStart = true; //开始拖拽
  1110. var thcss = ".laytable-cell-" + that.tableIndex + "-" + $(dict.elem).data("field");
  1111. dict.cssRule = TableClass.utils.getCssStyle.call(that, thcss);
  1112. var cssminWidth = parseFloat($othis.css("min-width").replace("px", ""));
  1113. dict.minWidth = cssminWidth === 0 ? options.cellMinWidth : cssminWidth;
  1114. dict.offset = e.clientX; //记录初始坐标
  1115. var tbone = $thisAllTable.eq(0);
  1116. //记录当前table宽度
  1117. dict.tb_width = tbone.outerWidth();
  1118. dict.tb_minwidth = parseFloat(tbone.css("min-width").replace("px", ""));
  1119. }
  1120. });
  1121. //拖拽中
  1122. $doc.on('mousemove.laytable', function (e) {
  1123. if (dict.resizeStart) {
  1124. e.preventDefault();
  1125. if (dict.elem) {
  1126. options.resized = true;
  1127. var gap = e.clientX - dict.offset;
  1128. var setWidth = dict.width + gap;
  1129. if (setWidth > dict.minWidth) {
  1130. dict.cssRule.style.width = setWidth + "px";
  1131. var newTbW = dict.tb_width + gap;
  1132. //修改最小宽度和宽度
  1133. $thisAllTable.outerWidth(newTbW);
  1134. if (newTbW < dict.tb_minwidth)
  1135. $thisAllTable.css("min-width", newTbW + "px");
  1136. //修改固定数据的高度
  1137. TableClass.utils.fullWidth.call(that);
  1138. //修改固定数据的高度
  1139. TableClass.utils.modifyFixedHeight.call(that, true);
  1140. }
  1141. }
  1142. isresizing = true;
  1143. }
  1144. }).on('mouseup.laytable', function (e) {
  1145. if (dict.resizeStart) {
  1146. dict = {};
  1147. $body.css('cursor', '');
  1148. }
  1149. });
  1150. //行事件
  1151. var tables = jqobjs.tb_box.find("div.laytable-body-box>table");
  1152. if (tables.length > 1) {
  1153. tables.on("mouseenter.laytable", "tr", function () {
  1154. tables.find("tr:eq(" + $(this).index() + ")").addClass("laytable-tr-hover");
  1155. }).on("mouseleave.laytable", "tr", function () {
  1156. tables.find("tr:eq(" + $(this).index() + ")").removeClass("laytable-tr-hover");
  1157. });
  1158. }
  1159. //横竖向滚动条,$tbodydiv有3个,数据、左固定、右固定
  1160. var funcScrollTop = function () {
  1161. if ($(this).attr("scroll-left") === "1") jqobjs.tb_head_box.scrollLeft($(this).scrollLeft());
  1162. $tbodydiv.not(this).scrollTop($(this).scrollTop());
  1163. if($(this).scrollLeft()===0){
  1164. $(".laytable-fixed-l").css("box-shadow","");
  1165. }else{
  1166. $(".laytable-fixed-l").css("box-shadow","0px -1px 8px rgba(0,0,0,0.08)");
  1167. }
  1168. }
  1169. $tbodydiv.on("scroll.laytable", funcScrollTop);
  1170. $tbodydiv.hover(function () {
  1171. $tbodydiv.not(this).off("scroll.laytable", funcScrollTop);
  1172. }, function () {
  1173. //$tbodydiv.not(this).on("scroll.laytable", funcScrollTop);
  1174. //不能使用上面代码,因为当删除数据导致div没有时,数据的div无法绑定时间
  1175. $tbodydiv.off("scroll.laytable", funcScrollTop)
  1176. .on("scroll.laytable", funcScrollTop);
  1177. });
  1178. //checkbox
  1179. var tmpLength = jqobjs.tb_fixed_l.find(".laytable-head-box").length,
  1180. $obj = tmpLength > 0 ? jqobjs.tb_fixed_l : jqobjs.tb_box;
  1181. $obj.on("click.laytableChk", "input.rayui-chk", function () {
  1182. var chk = $(this).attr("chk"), value = this.checked, objChk;
  1183. //全选
  1184. if (chk === "all") {
  1185. jqobjs.tb_box.find("input.rayui-chk").not(this).prop("checked", value);
  1186. //回调事件
  1187. objChk = {
  1188. type: "all",
  1189. index: -1,
  1190. checked: value
  1191. };
  1192. typeof options.onCheck === "function" && (options.onCheck.call(this, objChk));
  1193. return;
  1194. }
  1195. var $tr = $(this).closest("tr"), index = $tr.index();
  1196. //行选
  1197. if (options.singleSelect) {
  1198. //当前表格内选中的checkbox排除当前checkbox
  1199. var $chked = $obj.find("input.rayui-chk:checked").not(this);
  1200. //所有表格内选中的checkbox排除当前checkbox
  1201. jqobjs.tb_box.find("input.rayui-chk:checked").not(this).prop("checked", false);
  1202. if ($chked.length > 0 && typeof options.onCheck === "function") {
  1203. var $trpre = $chked.closest("tr"), indexpre = $trpre.index();
  1204. $chked.prop("checked", false);
  1205. objChk = {
  1206. type: "one",
  1207. index: indexpre,
  1208. checked: false
  1209. };
  1210. options.onCheck.call($chked, objChk);
  1211. }
  1212. }
  1213. //同步数据表格当前行选中
  1214. tmpLength > 0 &&
  1215. (jqobjs.tb_box.find(".laytable-body").find("tr:eq(" + index + ") input.rayui-chk").prop("checked", value));
  1216. //如果是允许多选,需要判断all是否选中
  1217. if (!options.singleSelect) {
  1218. var chkbox = jqobjs.tb_box.find(".laytable-head input.rayui-chk"),
  1219. valTmp = !value ? false :
  1220. $obj.find(".laytable-body input.rayui-chk").length === $obj.find(".laytable-body input.rayui-chk:checked").length;
  1221. chkbox.prop("checked", valTmp);
  1222. }
  1223. //回调事件
  1224. objChk = {
  1225. type: "one",
  1226. index: index,
  1227. checked: value
  1228. };
  1229. typeof options.onCheck === "function" && (options.onCheck.call(this, objChk));
  1230. });
  1231. //page分页select
  1232. $page.on("change.laytable", "select.laytable-page-limits", function () {
  1233. var preLimit = page.limit;
  1234. page.limit = parseInt($(this).val());
  1235. //按照数据重新计算pages
  1236. page.pages = Math.ceil(page.count / page.limit);
  1237. options.onPageLimitChanged && options.onPageLimitChanged(preLimit, page.limit);
  1238. //重新设定page
  1239. TableClass.utils.reload.call(that);
  1240. });
  1241. //page页码
  1242. //-------2019年9月2日----byLJ-----
  1243. /* $page.on("click.laytableli", "ul.laytable-page-pagination a:not('.rayui-disabled')", function () {
  1244. var ss = $(this).attr("value"),
  1245. prePage = page.curr;
  1246. if (ss === "-1") page.curr -= 1;
  1247. else if (ss === "+1") page.curr += 1;
  1248. else page.curr = parseInt(ss);
  1249. options.onPageJump && options.onPageJump(prePage, page.curr);
  1250. //重新设定page
  1251. TableClass.utils.reload.call(that);
  1252. });*/
  1253. //input页码输入框
  1254. /* $page.on("keyup.laytable", ".laytable-page-input", function (e) {
  1255. var value = this.value
  1256. , keyCode = e.keyCode;
  1257. if (/^(37|38|39|40)$/.test(keyCode)) return;
  1258. if (/\D/.test(value)) {
  1259. this.value = value.replace(/\D/, '');
  1260. }
  1261. var w = (value.length - 4) * 4;
  1262. //修改宽度
  1263. $(this).width(30 + w);
  1264. if (keyCode === 13) $page.find("a.laytable-page-btnok").click();
  1265. });
  1266. //page输入页码跳转
  1267. $page.on("click.laytablebtn", "a.laytable-page-btnok", function () {
  1268. var $input = $page.find(".laytable-page-input"),
  1269. input = $input.val(),
  1270. value = parseInt(input),
  1271. prePage = page.curr;
  1272. if (input === '' || value < 1) return;
  1273. page.curr = value;
  1274. options.onPageJump && options.onPageJump(prePage, page.curr);
  1275. //重新设定page
  1276. TableClass.utils.reload.call(that);
  1277. $input.val(page.curr);
  1278. });*/
  1279. //排序
  1280. var sortThs = jqobjs.tb_box.find("th.laytable-sort-th");
  1281. jqobjs.tb_box.on("click.laytableSort", "th.laytable-sort-th,span.laytable-sort-span>i", function (e) {
  1282. e.stopPropagation();
  1283. if (isresizing) {
  1284. isresizing = false;
  1285. return;
  1286. }
  1287. //如果没有data-field,说明点击的是i
  1288. var tosortfield, tosorttype, $th;
  1289. if (this.tagName === "I") {
  1290. $th = $(this).closest("th");
  1291. tosortfield = $th.data("field");
  1292. tosorttype = $(this).prop("class").indexOf("asc") > -1 ? "asc" : "desc";
  1293. } else {
  1294. $th = $(this);
  1295. var nowSortType = $(this).attr("sort-type");
  1296. tosortfield = $(this).data("field");
  1297. tosorttype = nowSortType === undef ? "asc" : nowSortType === "asc" ? "desc" : "asc";
  1298. }
  1299. sortThs.attr("sort-type", "");
  1300. $th.attr("sort-type", tosorttype);
  1301. !options.initSort && (options.initSort = {});
  1302. options.initSort.sortField = tosortfield;
  1303. options.initSort.sortType = tosorttype;
  1304. typeof options.onSort === "function" && options.onSort(options.initSort);
  1305. TableClass.utils.reload.call(that);
  1306. });
  1307. //如果出现省略,则可查看更多
  1308. jqobjs.tb_box.on("click.laytableShow", 'td.nowrap:not("[islink]")', function () {
  1309. var obj = $(this).find("div")[0] || this;
  1310. if (obj.scrollWidth > $(obj).outerWidth()) {
  1311. var $p = $(".laytable-tips");
  1312. if ($p.length === 0) {
  1313. $p = $('<div class="laytable-tips"><div class="laytable-tips-content"></div></div>').appendTo($body);
  1314. $('<i class="laytable-tips-close"></i>')
  1315. .appendTo($p)
  1316. .click(function () {
  1317. $p.remove();
  1318. });
  1319. }
  1320. var $content = $p.find(".laytable-tips-content");
  1321. $content.html($(obj).html());
  1322. //计算left、top
  1323. var cwidth = $win.width(),
  1324. offset = $(this).offset(),
  1325. left, top = offset.top - 1,
  1326. width = $p.outerWidth();
  1327. width > 500 && (width = 500);
  1328. if (offset.left + width < cwidth) {
  1329. left = offset.left;
  1330. } else {
  1331. var tmpW = offset.left + $(obj).outerWidth();
  1332. if (width > tmpW)
  1333. width = tmpW;
  1334. left = tmpW - width;
  1335. }
  1336. $p.css({
  1337. width: width + "px",
  1338. top: top + "px",
  1339. left: left + "px"
  1340. });
  1341. }
  1342. });
  1343. },
  1344. on: function (event, func) {
  1345. if (typeof event !== "string" || typeof func !== "function") return;
  1346. var that = this,
  1347. options = that.options,
  1348. jqobjs = tableCache.jqobjs[that.tableIndex],
  1349. $tbody = jqobjs.tb_body;
  1350. switch (event) {
  1351. //工具条
  1352. case "tool":
  1353. jqobjs.tb_box.on("click.laytableTool", ".laytable-body td[data-field^=opts] *[event]", function () {
  1354. var evt = $(this).attr("event"),
  1355. $tr = $(this).closest("tr"),
  1356. index = $tr.data("index"),
  1357. datas = TableClass.utils.getData.call(that);
  1358. var data = datas[index],
  1359. $datatr = {
  1360. index: index,
  1361. data: data,
  1362. tr: $tbody.find("tr[data-index=" + index + "]"),
  1363. del: function () {
  1364. //删除本地数据
  1365. TableClass.utils.deleteData.call(that, data);
  1366. //修改页码总数
  1367. options.page && (options.page.count -= 1);
  1368. //本地重新渲染数据
  1369. TableClass.utils.onRecvData.call(that);
  1370. },
  1371. update: function () {
  1372. //本地重新渲染数据
  1373. TableClass.utils.onRecvData.call(that);
  1374. }
  1375. };
  1376. func.call(this, evt, $datatr);
  1377. });
  1378. break;
  1379. //展开行
  1380. case "expand":
  1381. jqobjs.tb_box.on("click.laytableExpand", "td>a.laytable-expand", function () {
  1382. var $tr = $(this).closest("tr"),
  1383. expand = $tr.attr("expand");
  1384. if (expand !== undef) {
  1385. if (expand === "1") {
  1386. $tr.next("tr").hide();
  1387. $tr.attr("expand", "0");
  1388. } else {
  1389. $tr.next("tr").show();
  1390. $tr.attr("expand", "1");
  1391. }
  1392. return;
  1393. }
  1394. var index = $tr.data("index"),
  1395. datas = TableClass.utils.getData.call(that),
  1396. data = datas[index],
  1397. $trAppend = $([
  1398. '<tr>',
  1399. '<td><span class="laytable-expand"></span></td>',
  1400. '<td colspan="' + options.colsCount + '">',
  1401. '<div class="laytable-expand-box">',
  1402. '</div>',
  1403. '</td>',
  1404. '</tr>'
  1405. ].join(''));
  1406. $tr.attr("expand", "1").after($trAppend);
  1407. var $container = $trAppend.find(".laytable-expand-box"),
  1408. str = func.call(this, index, data, $container);
  1409. str != null && $container.append(str);
  1410. });
  1411. break;
  1412. //以下事件写相应属性事件也是可以的
  1413. //排序
  1414. case "sort": options.onSort = func; break;
  1415. //选中
  1416. case "check": options.onCheck = func; break;
  1417. }
  1418. }
  1419. }
  1420. TableClass.prototype = {
  1421. on: function (event, callback) {
  1422. TableClass.utils.on.call(this, event, callback);
  1423. },
  1424. reload: function (option) {
  1425. TableClass.utils.reload.call(this, option);
  1426. },
  1427. getSelectedRows: function () {
  1428. var list = [],
  1429. that = this,
  1430. jqobjs = tableCache.jqobjs[that.tableIndex],
  1431. $tbody = jqobjs.tb_body,
  1432. datas = TableClass.utils.getData.call(that);
  1433. $tbody.find("input.rayui-chk").each(function (a) {
  1434. if (this.checked) {
  1435. list.push({
  1436. index: a,
  1437. data: datas[a]
  1438. });
  1439. }
  1440. });
  1441. return list;
  1442. },
  1443. getData: function () {
  1444. return TableClass.utils.getData.call(this);
  1445. },
  1446. getDataByIndex: function (index) {
  1447. if (index === -1) return [];
  1448. return TableClass.utils.getData.call(this)[index];
  1449. }
  1450. };
  1451. var table2 = {
  1452. options: TableClass.option,
  1453. render: function (option) {
  1454. scrollGap.width || function () {
  1455. //可以在这里加载css
  1456. TableClass.utils.initDefault();
  1457. }();
  1458. var obj = option.elem;
  1459. if ($(obj).length === 0) return "DOM对象不存在";
  1460. var classObj = new TableClass(obj, option);
  1461. tableCache.tables[tableindex++] = classObj;
  1462. return classObj;
  1463. },
  1464. reload: function (option) {
  1465. //var obj = option.elem;
  1466. //if ($(obj).length === 0) return "DOM对象不存在";
  1467. //var classObj = new TableClass(obj, option);
  1468. // tableCache.tables[tableindex++] = classObj;
  1469. this.options = option;
  1470. this.elem = option.elem;
  1471. TableClass.utils.reload(option);
  1472. }
  1473. }
  1474. exports("table2", table2);
  1475. });