EditorTable.js 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. Namespace.register("U.UF.E");
  2. //初始化table
  3. /**
  4. * 表格总接口
  5. * range为编辑器的光标对象
  6. */
  7. U.UF.E.table = function (range) {
  8. var _p,
  9. _inputo,
  10. _inputt,
  11. _frag = $$("frag"),
  12. _table = U.UF.E.table; //简写命名空间
  13. _table._range = range;
  14. _p = $$("p", { "style": { "cssText": "text-align: left;font-weight: bold;padding: 10px 0 0 15px;" }, "innerHTML": "表格尺寸: " }, _frag);
  15. _p = $$("p", { "style": { "cssText": "text-align: left;margin-top: 15px;font-size: 14px;padding-left: 30px;" }, "innerHTML": "列数: " }, _frag);
  16. _inputo = $$("input", { "type": "number", "style": { "cssText": "width: 80px;margin-left: 65px;" }, "min": "1" }, _p);
  17. _p = $$("p", { "style": { "cssText": "text-align: left;padding-left: 30px;margin-top: 15px;font-size: 14px;margin-bottom: 22px;" }, "innerHTML": "行数: " }, _frag);
  18. _inputt = $$("input", { "type": "number", "style": { "cssText": "width: 80px;margin-left: 65px;" }, "min": "1" }, _p);
  19. //弹出框的html代码
  20. U.UF.UI.confirm(_frag, function () { //弹框输入 行 和 列
  21. var _row = _inputo.value; //行
  22. var _col = _inputt.value; //列
  23. if (_row >= 1 && _col >= 1) { //如果 行和列的值大于1 则添加表格
  24. _table.addTable(_row, _col);
  25. }
  26. });
  27. U.selectEl(document).unbind('mousedown', U.UF.E.table.removeFocus); //先取消事件监听 在添加 防止重复绑定
  28. U.selectEl(document).bind('mousedown', U.UF.E.table.removeFocus); //添加点击时的聚焦效果 并且若存在textarea元素 则删除并获取textarea的值给td
  29. };
  30. //初始化整理table,功能作用: 给外部添加的table元素添加样式和事件
  31. U.UF.E.table.load = function (tableel) {
  32. var _table = U.UF.E.table; //简写命名空间
  33. var _tableEl = tableel;
  34. if (_tableEl.features) return; //如果已初始化 则直接返回
  35. _tableEl.features = true; //代表已初始化过
  36. var _pelDiv = _tableEl.parentNode; //父节点的初始化
  37. var _allTd = _tableEl.querySelectorAll("td");
  38. _allTd.forEach(function (v) { /*删除所有display为none的dt元素*/
  39. U.selectEl(v).rmAttr("width");
  40. var _value = U.selectEl(v).css("display");
  41. if (_value === "none") {
  42. v.remove();
  43. }
  44. });
  45. _pelDiv.style.cssText = "overflow-y:hidden;padding-bottom:5px;padding-right:7px;"; //_div的样式
  46. _tableEl.style.cssText = _tableEl.style.cssText + "border-spacing: 0;border-collapse: collapse;position: relative;";
  47. _tableEl.contentEditable = "false";
  48. _table.tableOver(_tableEl); //添加选中选出事件 防止选中td时 选中外面的元素 而报错
  49. var _trList = _tableEl.querySelectorAll("tr");
  50. var _tdList = U.selectEl(_tableEl).find("td");
  51. //列拉升处理
  52. for (var i = 0; i < _tdList.length; i++) {
  53. var _tdCopy = _tdList[i];
  54. _tdCopy.contentEditable = "true";
  55. _tdCopy.style.cssText += ";outline:0;box-sizing:border-box;position:relative;padding:0px;border:2px solid #333;" //这样子写csstext不会给覆盖
  56. var _tdWidth = _tdCopy.clientWidth;
  57. _tdCopy.style.width = _tdWidth + "px"; //给td添加width
  58. _table.loadCell(_tdCopy); //初始有合并单元格 的情况
  59. var _colRule = $$("div", { "style": { "outline": "0", "zIndex": "1", "position": "absolute", "top": 0, "right": 0, "cursor": "col-resize", "width": "3px", "height": "100%" }, "tabindex": "0", "contenteditable": "false", "className": "U_MD_O_W_Table_colRule", "inline": true }, _tdCopy); //列尺
  60. _table.colExpanding(_colRule); //给列尺 添加左右拉伸事件
  61. _table.dragCheckd(_tdCopy); //td拖拽的选中事件
  62. _table.rightClick(_tableEl); //添加右键
  63. }
  64. //行拉升处理
  65. for (var i = 0; i < _trList.length; i++) {
  66. var _trEl = _trList[i];
  67. _trEl.style.cssText += ";position:relative;overflow:hidden;";
  68. var _rowRule = $$("div", { "style": { "outline": "0", "zIndex": "1", "position": "absolute", "left": 0, "margin-top": _trEl.clientHeight + "px", cursor: "row-resize", height: "3px", width: "100%" }, tabindex: "0", "contenteditable": "false", "className": "U_MD_O_W_Table_rowRule", "inline": true }, _trEl); //行尺
  69. _table.rowExpanding(_rowRule); //行尺 上下拉伸事件
  70. };
  71. }
  72. /**
  73. * 初始有合并单元格 的情况
  74. * tdEl td元素
  75. */
  76. U.UF.E.table.loadCell = function (tdEl) {
  77. var _table = U.UF.E.table; //简写命名空间
  78. var _tableEl = _table.parentSelect(tdEl, "table"); //获取table元素
  79. var _colSpan = tdEl.colSpan - 1; //跨了_colSpan列
  80. var _rowSpan = tdEl.rowSpan - 1; //跨了_rowSpan行
  81. if (_colSpan >= 1) {
  82. for (var i = 0; i < _colSpan; i++) {
  83. var _newTd = $$("td");
  84. _newTd.style.display = "none";
  85. _table.After(tdEl, _newTd);
  86. }
  87. }
  88. if (_rowSpan >= 1) {
  89. var _tdIndex = _table.index(tdEl); //获取该td的所在索引
  90. var _trIndex = _table.index(tdEl.parentNode); //获取该行tr所在位置
  91. var _trList = _tableEl.querySelectorAll("tr"); //获取所有的tr
  92. for (var i = 1; i <= _rowSpan; i++) { //获取该tr的下_rowSpan个tr
  93. var _tdList = _trList[_trIndex + i].querySelectorAll("td"); //获取该tr的所有td
  94. var _td = _tdList[_tdIndex - 1];
  95. for (var j = 0; j <= _colSpan; j++) {
  96. var _newTd = $$("td");
  97. _newTd.style.display = "none";
  98. _table.After(_td, _newTd);
  99. }
  100. }
  101. }
  102. }
  103. /**
  104. * 创建表格
  105. * @param row 表格的行
  106. * @param col 表格的列
  107. */
  108. U.UF.E.table.addTable = function (row, col) {
  109. var i, j, _tr, _td,
  110. _frag = $$("frag"),
  111. _pel = U.UF.E.table.createTablePel(), //table父节点
  112. _table = $$("table", { style: { cssText: "border-spacing: 0;border-collapse: collapse;width: 100%;position: relative;table-layout:fixed;"} }, _pel),
  113. _tbody = $$("tbody", {}, _table),
  114. _width = Math.max(Math.floor(_table.clientWidth / col), 50)
  115. ;
  116. // var _width = Math.max(Math.floor(_table.clientWidth / col), 50);
  117. //循环创建tr td
  118. for (i = 0; i < row; i++) {
  119. _tr = $$("tr", {}, _frag); //创建tr
  120. for (j = 0; j < col; j++) {
  121. _td = $$("td", { style: { width: _width + "px" }, "innerHTML": "<br />" }, _tr);
  122. }
  123. }
  124. _tbody.appendChild(_frag); //修改
  125. U.UF.E.table.load(_table);
  126. };
  127. /**
  128. * 换行并返回该行的div 然后在该行下面创建空div(防止表格后无法聚焦)
  129. * return 创建表格的div(父节点)
  130. */
  131. U.UF.E.table.createTablePel = function () {
  132. var _table = U.UF.E.table;
  133. //console.log(_table._range);
  134. var _range = U.UF.E.table._range, //获取光标
  135. _div = U.UF.E.getLineElement(_range.startContainer); //获取光标所在行的div
  136. if (_div.textContent !== "") { //如果该行有内容 则新建一行div
  137. var _div = U.selectEl("#" + U.UF.E.key.addLine(_range).addLine)[0];
  138. }
  139. // U.selectEl(_div).attr("contenteditable", "false"); //无内容的div(表格的父节点) 取消编辑效果
  140. _div.style.cssText = "overflow-y:hidden;padding-bottom:5px;padding-right:7px;width:90%"; //_div的样式
  141. U.UF.E.key.addLine(_range); //在表格的父节点下添加div 防止无法聚焦
  142. _table.placeCaretAtEnd(_div);
  143. return _div;
  144. };
  145. /**
  146. * 将表格的第一个tr里的所有列尺元素 添加 zindex为1 的样式
  147. * tableEl 表格元素
  148. */
  149. U.UF.E.table.firstLinePeak = function (tableEl) {
  150. U.selectEl(tableEl).find(".U_UF_E_Table_peak").css("height", 0); //原来有列尺的元素高度清0
  151. U.selectEl(tableEl).find(".U_UF_E_Table_peak").removeClass("U_UF_E_Table_peak"); //改变 删除所有列尺的zIndex为1的样式
  152. var _height = tableEl.clientHeight; //获取表格的高
  153. var _colRuleList = tableEl.querySelectorAll("tr")[0].querySelectorAll(".U_MD_O_W_Table_colRule"); //获取第一行的列尺
  154. for (var i = 0, len = _colRuleList.length; i < len; i++) {
  155. var _colRule = _colRuleList[i];
  156. _colRule.style.height = _height + "px"; //所有列尺的高等于表格的高
  157. U.selectEl(_colRule).addClass("U_UF_E_Table_peak");
  158. }
  159. };
  160. /**
  161. *
  162. * @param table 防止选中事件时选中到表格外的元素而报错
  163. */
  164. U.UF.E.table.tableOver = function (table) {
  165. U.selectEl(table).bind('mouseover', function () { //判断鼠标是否在该table里 如果在 才可以选择区域
  166. this.over = true;
  167. });
  168. U.selectEl(table).bind('mouseout', function () {
  169. this.over = false;
  170. });
  171. };
  172. /**
  173. *
  174. * @param colrule 列尺(div) 添加左右拉伸事件
  175. */
  176. U.UF.E.table.colExpanding = function (colrule) {
  177. var _div = colrule;
  178. U.selectEl(_div).bind({
  179. 'mousedown': function (e) {
  180. U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove(); //删除右键元素
  181. U.UF.EV.stopBubble(e); //阻止冒泡
  182. this.style.backgroundColor = "#8cb3e0"; //修改列尺(div)的颜色
  183. var _table = U.UF.E.table;
  184. var _this = this;
  185. var _tdEl = this.parentNode; //获取td(每个列对应一个td父节点)
  186. var _tableEl = _table.parentSelect(this, "table"); //获取所在的table
  187. var _tableElWidth = _tableEl.clientWidth; //table当前的宽度
  188. var _trList = _tableEl.querySelectorAll("tr"); //获取所有的tr
  189. var _tdElIndex = _table.index(_tdEl); //获取td在tr的索引位置(列)
  190. var _dis, //移动的距离
  191. _disX; //移动后的位置
  192. var _oMouseX = e.pageX; //获取鼠标按下时的X坐标
  193. var _oX = parseInt(this.style.right); //获取当前Left坐标
  194. var expandingMove = function (e) { //拖拽时移动用的函数
  195. U.UF.EV.stopDefault(e); //取消默认拖拽
  196. var _mouseX = e.pageX; //鼠标移动时的x坐标
  197. _dis = _mouseX - _oMouseX; //移动的距离
  198. _disX = _dis + _oX; //移动后的位置
  199. U.selectEl(_this).css("right", -_disX + "px"); //同步当前的left
  200. };
  201. var expandingUp = function () { //拖拽时松开用的函数
  202. _this.style.backgroundColor = ""; //列尺颜色 变为空
  203. var _child;
  204. for (var i = 0, len = _trList.length; i < len; i++) {
  205. var _colTdEl = U.selectEl("td", _trList[i])[_tdElIndex]; //列的td _trList[i].querySelectorAll("td")
  206. _colTdEl.style.width = _colTdEl.offsetWidth + _disX + "px"; //同步宽度
  207. var _colRule = _colTdEl.querySelectorAll('.U_MD_O_W_Table_colRule'); //该td对应的列尺
  208. U.selectEl(_colRule).css("right", "0px"); //同步当前的left
  209. _child = U.selectEl("div", _trList[i]);
  210. _child[_child.length - 1].style.marginTop = _trList[i].offsetHeight + "px";
  211. }
  212. U.selectEl(document).unbind('mousemove', expandingMove);
  213. U.selectEl(document).unbind('mouseup', expandingUp);
  214. };
  215. U.selectEl(document).bind('mousemove', expandingMove);
  216. U.selectEl(document).bind('mouseup', expandingUp)
  217. },
  218. 'dblclick': function (e) {
  219. U.UF.EV.stopBubble(e); //阻止冒泡
  220. }, //阻止td的双击
  221. 'mousemove': function (e) {
  222. U.UF.EV.stopBubble(e); //阻止冒泡
  223. U.UF.EV.stopDefault(e); //取消默认拖拽
  224. }
  225. });
  226. };
  227. /**
  228. *
  229. * @param rowrule 行尺(div) 添加上下拉伸事件
  230. */
  231. U.UF.E.table.rowExpanding = function (rowrule) { //高度扩张
  232. var _div = rowrule;
  233. U.selectEl(_div).bind({
  234. 'mousedown': function (e) {
  235. U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove(); //删除右键元素
  236. this.style.backgroundColor = "#8cb3e0";
  237. U.UF.EV.stopBubble(e); //阻止冒泡
  238. var _oMouseY = e.pageY; //获取鼠标按下时的Y坐标
  239. var _this = this;
  240. var _oY = parseInt(this.style.marginTop); //获取当前Top坐标
  241. var _trEl = this.parentNode; //获取tr
  242. var expandingMove = function (e) { //拖拽时移动用的函数
  243. U.UF.EV.stopDefault(e); //取消默认拖拽
  244. var _mouseY = e.pageY; //鼠标移动时的Y坐标
  245. var _dis = _mouseY - _oMouseY + _oY; //移动的距离
  246. _dis = Math.max(30, _dis); //拉伸后的tr的高度不能小于30px
  247. _trEl.style.height = _dis + "px";
  248. var clienHeight = _trEl.clientHeight; //tr的高度 会根据内容有个最小值 因此 这个tr最后的高度 才是最终值
  249. _dis = Math.max(clienHeight, _dis);
  250. _trEl.style.height = _dis + "px";
  251. U.selectEl(_this).css("margin-top", _dis + "px");
  252. };
  253. var expandingUp = function () { //拖拽时松开用的函数
  254. var _table = U.UF.E.table; //简写命名空间
  255. var _tableEl = _table.parentSelect(_this, "table"); //获取table元素
  256. _table.firstLinePeak(_tableEl); //更新第一行的列尺高度
  257. _this.style.backgroundColor = "";
  258. U.selectEl(document).unbind('mousemove', expandingMove);
  259. U.selectEl(document).unbind('mouseup', expandingUp);
  260. };
  261. U.selectEl(document).bind('mousemove', expandingMove);
  262. U.selectEl(document).bind('mouseup', expandingUp)
  263. },
  264. 'mousemove': function (e) {
  265. U.UF.EV.stopBubble(e); //阻止冒泡
  266. U.UF.EV.stopDefault(e); //取消默认拖拽
  267. }
  268. });
  269. };
  270. /*
  271. * 添加文本框 并给文本框添加事件
  272. * parent td元素(文本框父元素)
  273. * text 为文本 可要可不要
  274. */
  275. U.UF.E.table.createTextArea = function (parent, text) {
  276. var _textArea = $$("textarea", { className: "U_UF_E_Table_tdText", value: text || "", contenteditable: "true", inline: true }, parent); //添加textarea 并且将td的内容放入textarea
  277. U.selectEl(_textArea).bind('mousedown', function (e) {
  278. U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove(); //删除右键元素 //阻止冒泡
  279. }); //阻止td的冒泡 (选中效果 和 聚焦效果)
  280. var autoHeight = function (el) { //表格自动适应高
  281. el.nodeType === 1 ? "" : el = el.target; //el只能为textarea
  282. el.scrollHeight ? el.style.height = el.scrollHeight + "px" : ""; //此处为textarea的高度跟随文字输入的内容自动增高
  283. var _rowRuleList = U.selectEl(".U_MD_O_W_Table_rowRule"); //获取所有行尺
  284. for (var i = 0, len = _rowRuleList.length; i < len; i++) {
  285. var _trPel = _rowRuleList[i].parentNode; //每个行尺 对应一个 tr元素
  286. _trPel.style.height = _trPel.clientHeight; //使每个tr的height 等于 clientHeight
  287. U.selectEl(_rowRuleList[i]).css("margin-top", _trPel.clientHeight + "px"); //同步margintop 的位置
  288. }
  289. };
  290. autoHeight(_textArea); //由于textarea输入自后td的高度会变化 因此所有行尺的位置重新定位
  291. U.selectEl(_textArea).bind('keydown', autoHeight); //键盘监听 自动适应高
  292. U.selectEl(_textArea).bind('keyup', autoHeight); //键盘监听 自动适应高
  293. U.selectEl(_textArea).bind('blur', function () {
  294. var _textla = U.selectEl(".U_UF_E_Table_tdText");
  295. var _tdEl = U.selectEl(".U_UF_E_Table_tdText")[0].parentNode;
  296. _tdEl.innerText = _textla[0].value;
  297. _textla.remove();
  298. });
  299. }
  300. /**
  301. *
  302. * @param td 添加鼠标拖拽效果的 td
  303. * 给td添加鼠标拖拽的选中效果
  304. */
  305. U.UF.E.table.dragCheckd = function (td) {
  306. var _tdEl = td;
  307. U.selectEl(_tdEl).bind('mousedown', function (e) {
  308. U.UF.EV.stopBubble(e); //阻止冒泡
  309. U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove(); //删除右键元素
  310. if (e.button != 2) {
  311. var _table = U.UF.E.table;
  312. //移除原本选中的效果
  313. U.selectEl(".U_UF_E_Table_tdCheckd").removeClass("U_UF_E_Table_tdCheckd");
  314. U.selectEl(".U_UF_E_Table_tdCurrent").removeClass("U_UF_E_Table_tdCurrent");
  315. //给td添加聚焦样式
  316. U.selectEl(this).addClass("U_UF_E_Table_tdCurrent");
  317. var _start = this; //获取点击元素
  318. var _startX = _table.index(_start); //记录x坐标轴
  319. var _startY = _table.index(this.parentNode); //获取y坐标轴
  320. var _checkFlag = true; //注意下面的_table.over是一个属性 防止选中区域在表格外面
  321. var _tableEl = _table.parentSelect(this, "table"); //获取父节点table
  322. //拖拽时移动用的函数
  323. var _drapMove = function (e) {
  324. var tagEl = e.path.filter(_filter)[0];
  325. if (tagEl) {
  326. U.UF.EV.stopBubble(e); //阻止冒泡
  327. if (!(_tableEl.over) || (tagEl === _start && _checkFlag)) return; //此处防止选中table外元素 与 鼠标必须选中两个td才会有选中效果
  328. _checkFlag = false; //如果不同 则选中过两个元素
  329. var _endX = _table.index(tagEl); //结束点的x坐标
  330. var _endY = _table.index(tagEl.parentNode); //结束点的y坐标
  331. U.selectEl(".U_UF_E_Table_tdCheckd").removeClass("U_UF_E_Table_tdCheckd");
  332. _table.tdAddClass(tagEl.parentNode, _startX, _startY, _endX, _endY); //给开始点和结束点组成的矩形 添加选中的class
  333. }
  334. };
  335. var _dragUp = function () { //拖拽时松开用的函数
  336. U.selectEl(document).unbind('mousemove', _drapMove);
  337. U.selectEl(document).unbind('mouseup', _dragUp);
  338. _checkFlag = true;
  339. };
  340. var _filter = function (el) {
  341. return el.nodeName && el.nodeName === "TD"
  342. }
  343. U.selectEl(document).bind('mousemove', _drapMove);
  344. U.selectEl(document).bind('mouseup', _dragUp);
  345. }
  346. });
  347. };
  348. /**
  349. * 添加右键
  350. * tableEl 表格元素
  351. */
  352. U.UF.E.table.rightClick = function (tableEl) {
  353. var _table = U.UF.E.table;
  354. var leftAddCol = {
  355. innerHTML: '左侧添加列',
  356. onclick: function () {
  357. _table.addColumn("left");
  358. U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove(); //删除右键元素
  359. },
  360. onmousedown: function (e) {
  361. U.UF.EV.stopBubble(e); //阻止冒泡
  362. }
  363. };
  364. var rightAddCol = {
  365. innerHTML: '右侧添加列',
  366. onclick: function () {
  367. _table.addColumn("right");
  368. U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove(); //删除右键元素
  369. },
  370. onmousedown: function (e) {
  371. U.UF.EV.stopBubble(e); //阻止冒泡
  372. }
  373. };
  374. var upAddLine = {
  375. innerHTML: '向上添加行',
  376. onclick: function () {
  377. _table.addTr("up");
  378. U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove(); //删除右键元素
  379. },
  380. onmousedown: function (e) {
  381. U.UF.EV.stopBubble(e); //阻止冒泡
  382. }
  383. };
  384. var downAddLine = {
  385. innerHTML: '向下添加行',
  386. onclick: function () {
  387. _table.addTr("down");
  388. U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove(); //删除右键元素
  389. },
  390. onmousedown: function (e) {
  391. U.UF.EV.stopBubble(e); //阻止冒泡
  392. }
  393. };
  394. var removeCol = {
  395. innerHTML: '删除列',
  396. onclick: function () {
  397. _table.removeColumn();
  398. U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove(); //删除右键元素
  399. },
  400. onmousedown: function (e) {
  401. U.UF.EV.stopBubble(e); //阻止冒泡
  402. }
  403. };
  404. var removeLine = {
  405. innerHTML: '删除行',
  406. onclick: function () {
  407. _table.removeTr();
  408. U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove(); //删除右键元素
  409. },
  410. onmousedown: function (e) {
  411. U.UF.EV.stopBubble(e); //阻止冒泡
  412. }
  413. };
  414. var mergeCells = {
  415. innerHTML: '合并单元格',
  416. onclick: function () {
  417. _table.mergeCells();
  418. U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove(); //删除右键元素
  419. },
  420. onmousedown: function (e) {
  421. U.UF.EV.stopBubble(e); //阻止冒泡
  422. }
  423. };
  424. var _arr = [leftAddCol, rightAddCol, upAddLine, downAddLine, removeCol, removeLine, mergeCells];
  425. U.selectEl(tableEl).bind('contextmenu', function (e) {
  426. U.UF.EV.stopBubble(e); //阻止冒泡
  427. U.UF.EV.stopDefault();
  428. U.UF.EL.rightMenu(_arr, tableEl);
  429. U.selectEl("#U_UF_EL_rightmenu").bind('contextmenu', function (e) { //右键元素属于table 因此需要阻止冒泡
  430. U.UF.EV.stopBubble(e); //阻止冒泡
  431. });
  432. });
  433. U.selectEl(tableEl).bind('mousedown', function (e) {
  434. U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove(); //删除右键元素
  435. });
  436. };
  437. /**
  438. *
  439. * @param direction 参数为 "left" 或 "right"
  440. * 左右侧添加列
  441. */
  442. U.UF.E.table.addColumn = function (direction) {
  443. var _table = U.UF.E.table;
  444. var tdList = U.selectEl(".U_UF_E_Table_tdCheckd");
  445. if (!tdList[0]) { //如果没有 选中的td
  446. if ($(".U_UF_E_Table_tdCurrent")[0]) { //再判断 有无聚焦的 td
  447. tdList = U.selectEl(".U_UF_E_Table_tdCurrent");
  448. } else {
  449. return; //如果没有 则直接返回
  450. }
  451. }
  452. var _tdEl;
  453. if (direction === "left") {
  454. _tdEl = tdList[0];
  455. } else if (direction === "right") {
  456. _tdEl = tdList[tdList.length - 1];
  457. }
  458. _table.insertTd(_tdEl, direction);
  459. };
  460. /**
  461. *
  462. * @param td td元素
  463. * @param direction 供添加左右列用的api 参数为 "left" 或 "right"
  464. * 向每个tr的列(td) 前方或后方插入td
  465. */
  466. U.UF.E.table.insertTd = function (td, direction) {
  467. var _table = U.UF.E.table;
  468. var _tdEl = td,
  469. _index = _table.index(_tdEl), //在tr中位于所有td的位置
  470. _dir = direction;
  471. var _tableEl = _table.parentSelect(_tdEl, 'table');
  472. var _trList = U.selectEl(_tableEl).find("tr");
  473. var _tableElWidth = _tableEl.offsetWidth; //记住当前的宽度
  474. for (var i = 0, len = _trList.length; i < len; i++) { //遍历每个tr的列(td) 在前方或后方插入td
  475. var _currentColumn = U.selectEl(_trList[i]).find("td")[_index]; //当前列
  476. var _tdElClone = _tdEl.cloneNode(); //克隆td
  477. if (_dir === "left") {
  478. _table.Before(_currentColumn, _tdElClone); //在列的前面添加td
  479. }
  480. else if (_dir === "right") {
  481. _table.After(_currentColumn, _tdElClone); //在列的后面添加td
  482. }
  483. var _colRule = $$("div", { style: { position: "absolute", top: 0, left: "-7px", "margin-left": _tdElClone.style.width, cursor: "col-resize", width: "7px" }, className: "U_MD_O_W_Table_colRule", inline: true }, _tdElClone); //列尺
  484. _table.colExpanding(_colRule); //添加左右拉伸事件
  485. _table.createTextArea(_tdElClone); //添加文本框
  486. _table.dragCheckd(_tdElClone); //td拖拽的选中事件
  487. U.selectEl(_tdElClone).removeClass("U_UF_E_Table_tdCheckd"); //清楚添加后的列的选中的样式
  488. U.selectEl(_tdElClone).removeClass("U_UF_E_Table_tdCurrent");
  489. }
  490. _tableEl.style.width = _tableElWidth + _tdEl.offsetWidth + "px";
  491. _table.firstLinePeak(_tableEl); //第一行tr的所有列尺添加zIndex为1
  492. };
  493. /**
  494. *
  495. * @param direction 参数为 "up" 或 "down"
  496. * 上下添加行
  497. */
  498. U.UF.E.table.addTr = function (direction) {
  499. var _table = U.UF.E.table;
  500. var tdList = U.selectEl(".U_UF_E_Table_tdCheckd");
  501. if (!tdList[0]) { //如果没有 选中的td
  502. if ($(".U_UF_E_Table_tdCurrent")[0]) { //再判断 有无聚焦的 td
  503. tdList = U.selectEl(".U_UF_E_Table_tdCurrent");
  504. } else {
  505. return; //如果没有 则直接返回
  506. }
  507. }
  508. var _trEl, _trElClone;
  509. if (direction === "up") {
  510. _trEl = tdList[0].parentNode;
  511. _trElClone = _table.cloneTr(_trEl); //克隆tr 并给td 添加表格事件
  512. _table.Before(_trEl, _trElClone);
  513. } else if (direction === "down") {
  514. _trEl = tdList[tdList.length - 1].parentNode; //向下插入行
  515. _trElClone = _table.cloneTr(_trEl); //克隆tr 并给td 添加表格事件
  516. _table.After(_trEl, _trElClone);
  517. }
  518. var _tableEl = _table.parentSelect(tdList[0], 'table');
  519. _table.firstLinePeak(_tableEl); //将表格的第一个tr里的所有列尺元素 添加 zindex为1 的样式
  520. };
  521. /**
  522. * 删除行
  523. */
  524. U.UF.E.table.removeTr = function () {
  525. var _table = U.UF.E.table;
  526. var tdList = U.selectEl(".U_UF_E_Table_tdCheckd");
  527. if (!tdList[0]) { //如果没有 选中的td
  528. if ($(".U_UF_E_Table_tdCurrent")[0]) { //再判断 有无聚焦的 td
  529. tdList = U.selectEl(".U_UF_E_Table_tdCurrent");
  530. } else {
  531. return; //如果没有 则直接返回
  532. }
  533. }
  534. var start = _table.index(tdList[0].parentNode);
  535. var end = _table.index(tdList[tdList.length - 1].parentNode);
  536. var _tableEl = _table.parentSelect(tdList[0], "table");
  537. var _parentDiv = _table.parentSelect(_tableEl, "div");
  538. var _trList = U.selectEl(_tableEl).find("tr");
  539. for (var i = start; i <= end; i++) {
  540. _trList[i].remove();
  541. }
  542. if (!(_tableEl.querySelectorAll("tr").length)) {
  543. _parentDiv.remove();
  544. return
  545. }
  546. _table.firstLinePeak(_tableEl); //将表格的第一个tr里的所有列尺元素 添加 zindex为1 的样式
  547. };
  548. /**
  549. *
  550. * @param tr 需要克隆的tr
  551. * 克隆tr 并添加表格事件
  552. */
  553. U.UF.E.table.cloneTr = function (tr) {
  554. var _table = U.UF.E.table;
  555. var _trNodes = tr.cloneNode(true); //带子节点的tr
  556. var _trClone = tr.cloneNode(); //无子节点的tr
  557. var _cloneTd = U.selectEl(_trNodes).find("td");
  558. for (var i = 0, len = _cloneTd.length; i < len; i++) {
  559. var _td = _cloneTd[i].cloneNode();
  560. U.selectEl(_td).rmAttr("rowspan"); //删除跨行的属性
  561. _trClone.appendChild(_td);
  562. var _colRule = $$("div", { style: { position: "absolute", top: 0, left: "-7px", "margin-left": _td.style.width, cursor: "col-resize", width: "7px" }, className: "U_MD_O_W_Table_colRule", inline: true }, _td); //列尺
  563. _table.colExpanding(_colRule); //添加左右拉伸事件
  564. //_table.tdDbClick(_td); //添加双击事件
  565. _table.createTextArea(_td);
  566. _table.dragCheckd(_td); //td拖拽的选中事件
  567. }
  568. var _rowRule = $$("div", { style: { position: "absolute", zIndex: "1", left: 0, "margin-top": "30px", cursor: "row-resize", height: "3px", width: "100%" }, className: "U_MD_O_W_Table_rowRule", inline: true }, _trClone); //行尺
  569. _table.rowExpanding(_rowRule); //上下拉伸事件
  570. U.selectEl(_trClone).find(".U_UF_E_Table_tdCheckd").removeClass("U_UF_E_Table_tdCheckd"); //删除所有选中表格和 聚焦表格的样式
  571. U.selectEl(_trClone).find(".U_UF_E_Table_tdCurrent").removeClass("U_UF_E_Table_tdCurrent");
  572. return _trClone;
  573. };
  574. /**
  575. * 合并单元格功能
  576. */
  577. U.UF.E.table.mergeCells = function () {
  578. var _table = U.UF.E.table;
  579. var _tdList = U.selectEl(".U_UF_E_Table_tdCheckd");
  580. if (_tdList.length <= 1) return;
  581. var _x1 = _table.index(_tdList[0]); //x坐标开始点
  582. var _y1 = _table.index(_tdList[0].parentNode); //y坐标开始点
  583. var _x2 = _table.index(_tdList[_tdList.length - 1]); //x坐标结束点
  584. var _y2 = _table.index(_tdList[_tdList.length - 1].parentNode); //y坐标结束点
  585. var _tableEl = _table.parentSelect(_tdList[0], "table"); //获取table元素
  586. var _trList = _tableEl.querySelectorAll("tr"); //获取table里所有tr
  587. var _text = ""; //合并后的总内容
  588. var allWidth = 0; //合并后的总宽度
  589. for (var i = _y1; i <= _y2; i++) { /*该循环*/
  590. var _trAllTd = _trList[i].querySelectorAll("td"); //获取选中表格的所在tr
  591. for (var j = _x1; j <= _x2; j++) { // 获取选中表格的 所在td
  592. var _tdEl = _trAllTd[j]; //获取每个选中的单元格
  593. _text += _tdEl.innerText; //合并内容
  594. if (i === _y1) { //只计算选中表格第一行 的总宽度
  595. allWidth += _tdEl.offsetWidth;
  596. }
  597. if (i === _y1 && j === _x1) continue; //第一个td就跳过 其他的则display为 none
  598. U.selectEl(_tdEl).css("display", "none");
  599. }
  600. }
  601. var _textNode = document.createTextNode(_text); //文字节点 _text为总内容
  602. var _firstNode = _table.getFirstText(_tdList[0]); //获取被合并单元格的td所在的文字节点
  603. _firstNode ? _firstNode.remove() : ""; //如果存在文字节点 则删除
  604. _tdList[0].appendChild(_textNode); //然后将新创建的总文字节点 添加到该单元格里
  605. _tdList[0].style.width = allWidth + "px"; //添加总宽度
  606. var _col = U.selectEl(_tdList[0]).attr("colspan");
  607. _col <= _x2 - _x1 + 1 ? U.selectEl(_tdList[0]).attr("colspan", _x2 - _x1 + 1) : ""; //跨的列数
  608. U.selectEl(_tdList[0]).attr("rowspan", _y2 - _y1 + 1); //跨的行数
  609. U.selectEl(_tdList[0].querySelector(".U_MD_O_W_Table_colRule")).css("margin-left", allWidth + 'px'); //更新 列尺的位置
  610. _table.firstLinePeak(_tableEl); //将表格的第一个tr里的所有列尺元素 添加 zindex为1 的样式
  611. };
  612. /**
  613. * 删除列
  614. */
  615. U.UF.E.table.removeColumn = function () {
  616. var _table = U.UF.E.table
  617. var tdList = U.selectEl(".U_UF_E_Table_tdCheckd");
  618. if (!tdList[0]) { //如果没有 选中的td
  619. if ($(".U_UF_E_Table_tdCurrent")[0]) { //再判断 有无聚焦的 td
  620. tdList = U.selectEl(".U_UF_E_Table_tdCurrent");
  621. } else {
  622. return; //如果没有 则直接返回
  623. }
  624. }
  625. var _start = _table.index(tdList[0]); //列的开始位置
  626. var _end = _table.index(tdList[tdList.length - 1]); //列的结束位置
  627. var _tableEl = _table.parentSelect(tdList[0], 'table');
  628. var _trList = U.selectEl(_tableEl).find("tr");
  629. var _widthSum = 0; //删除列的总宽
  630. for (var i = 0, len = _trList.length; i < len; i++) {
  631. var _tdList = U.selectEl(_trList[i]).find("td");
  632. for (var j = _start; j <= _end; j++) {
  633. i === 0 ? _widthSum += _tdList[j].offsetWidth : ""; //只计算第一行删除的列宽
  634. _tdList[j].remove();
  635. }
  636. }
  637. _tableEl.style.width = _tableEl.offsetWidth - _widthSum + "px";
  638. var _tdLen = _tableEl.querySelectorAll("td").length; //获取当前列的长度
  639. if (!_tdLen) { //如果table不存在td 则删除table和 table父节点(div)
  640. var _parentDiv = _table.parentSelect(_tableEl, "div");
  641. _parentDiv.remove();
  642. return
  643. }
  644. _table.firstLinePeak(_tableEl); //将表格的第一个tr里的所有列尺元素 添加 zindex为1 的样式
  645. };
  646. /**
  647. * 添加点击时的聚焦效果 并且若存在textarea元素 则删除并获取textarea的值给td
  648. */
  649. U.UF.E.table.removeFocus = function () { //添加点击时的聚焦效果 并且若存在textarea元素 则删除并获取textarea的值给td
  650. U.selectEl(".U_UF_E_Table_tdCheckd").removeClass("U_UF_E_Table_tdCheckd");
  651. U.selectEl(".U_UF_E_Table_tdCurrent").removeClass("U_UF_E_Table_tdCurrent");
  652. return;
  653. var _textArea = U.selectEl(".U_UF_E_Table_tdText")[0], //如果存在textarea元素 则将其变为文本
  654. _pel;
  655. _textArea ? _pel = _textArea.parentNode : ""; //如果textArea存在 先获取父节点td 然后将其变为文本
  656. if (_pel) {
  657. var _textNode = document.createTextNode(_textArea.value);
  658. _pel.appendChild(_textNode);
  659. _textArea.remove();
  660. }
  661. var _rowRuleList = U.selectEl(".U_MD_O_W_Table_rowRule"); //使div的margintop 及时更新
  662. for (var i = 0, len = _rowRuleList.length; i < len; i++) {
  663. var _trEl = _rowRuleList[i].parentNode;
  664. _trEl.style.height = _trEl.clientHeight;
  665. U.selectEl(_rowRuleList[i]).css("margin-top", _trEl.clientHeight + "px");
  666. }
  667. };
  668. /**
  669. *
  670. * @param tr 获取所有tr用的(遍历所有tr)
  671. * @param x1 开始点x坐标
  672. * @param y1 开始点y坐标
  673. * @param x2 结束点x坐标
  674. * @param y2 结束点y坐标
  675. */
  676. U.UF.E.table.tdAddClass = function (tr, x1, y1, x2, y2) { //获取首尾坐标轴 最后组成矩形 然后添加选中的class
  677. var _trList = tr.parentNode.querySelectorAll("tr");
  678. var _x1 = Math.min(x1, x2);
  679. var _x2 = Math.max(x1, x2);
  680. var _y1 = Math.min(y1, y2);
  681. var _y2 = Math.max(y1, y2);
  682. for (var i = _y1; i <= _y2; i++) {
  683. var _tdList = _trList[i].querySelectorAll("td");
  684. for (var j = _x1; j <= _x2; j++) {
  685. U.selectEl(_tdList[j]).addClass("U_UF_E_Table_tdCheckd");
  686. }
  687. }
  688. }
  689. /**
  690. *
  691. * @param el 元素
  692. * @returns {number} 返回当前元素在所有同类型元素 的第几个位置
  693. */
  694. U.UF.E.table.index = function (el) {
  695. var _el = el;
  696. var _name = _el.nodeName; //获取该元素的节点名
  697. var _list = _el.parentNode.querySelectorAll(_name); //获取父节下的所有自己的节点
  698. for (var i = 0, len = _list.length; i < len; i++) {
  699. if (_list[i] === _el) {
  700. return i; //返回在数组的索引
  701. }
  702. }
  703. };
  704. /**
  705. * 获取td的第一个文本元素
  706. */
  707. U.UF.E.table.getFirstText = function (td) {
  708. var _child = td.childNodes;
  709. for (var i = 0, len = _child.length; i < len; i++) {
  710. if (_child[i].nodeType === 3) {
  711. return _child[i];
  712. }
  713. }
  714. return false;
  715. }
  716. /*获取指定标签的父节点*/
  717. U.UF.E.table.parentSelect = function (el, type) {
  718. var _this = el;
  719. var type = type.toUpperCase();
  720. if (_this.tagName === type) return _this;
  721. var parent = _this.parentNode;
  722. while (parent.tagName !== type) {
  723. parent = parent.parentNode;
  724. }
  725. return parent;
  726. };
  727. /*在元素前面插入新元素*/
  728. U.UF.E.table.Before = function (el, newEl) {
  729. var _this = el;
  730. var parentEl = _this.parentNode;
  731. parentEl.insertBefore(newEl, _this);
  732. };
  733. /*在元素后面插入新元素*/
  734. U.UF.E.table.After = function (el, newEl) {
  735. var _this = el;
  736. if (_this && _this.parentNode) {
  737. var parentEl = _this.parentNode;
  738. var child = parentEl.childNodes;
  739. var last = child[child.length - 1] || parentEl.lastChild;
  740. if (last === _this) {
  741. parentEl.appendChild(newEl);
  742. } else {
  743. parentEl.insertBefore(newEl, _this.nextSibling);
  744. }
  745. return newEl;
  746. }
  747. };
  748. /**
  749. * 使光标聚焦在该元素后面
  750. * @param el 需要文字聚焦的 元素节点
  751. */
  752. U.UF.E.table.placeCaretAtEnd = function (el) { //传入光标要去的节点对象
  753. if (el.collapse) { //如果存在el.collapsed 则是range
  754. var range = el;
  755. range.collapse(false);
  756. var sel = window.getSelection();
  757. sel.removeAllRanges();
  758. sel.addRange(range);
  759. return;
  760. }
  761. if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") {
  762. el.focus && el.focus();
  763. var range = document.createRange();
  764. range.selectNodeContents(el);
  765. range.collapse(false);
  766. var sel = window.getSelection();
  767. sel.removeAllRanges();
  768. sel.addRange(range);
  769. } else if (typeof document.body.createTextRange != "undefined") {
  770. var textRange = document.body.createTextRange();
  771. textRange.moveToElementText(el);
  772. textRange.collapse(false);
  773. textRange.select();
  774. }
  775. };
  776. /*
  777. 合并单元格使用bug:
  778. 1.选中表格时 如出现行和列对不齐时 除了删除列不会有问题以外 其他都会出问题
  779. 解决思路:由于合并单元格后 每行的td都对不齐了 因此需要修改选中td的接口 不准出现参差不齐的情况
  780. 2.在合并单元格的那一列用添加列 删除列会有bug
  781. 解决思路: 由于合并单元格时 有占用两列或两行的情况 因此需要在添加列删除列那里将占用两列以上的情况考虑进去 针对colspan属性做判断
  782. 3.在合并单元格的那一行除了 向上添加行功能 其他都会有bug
  783. 解决思路:由于跨行合并单元格 会使第第一行变成占2行或以上 其他行display为none 因此如果向下添加行则需要将display为none 消掉 主要也是需要针对rowspan属性做判断
  784. */