table.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. /**
  2. * @fileoverview
  3. * Table을 삽입하는 기능을 가진 Tool 'table' Source,
  4. * Class Trex.Tool.Table,Trex.Menu.Table,Trex.Menu.Table.TableEdit와 configuration 을 포함 하고있다.
  5. */
  6. TrexConfig.addTool(
  7. "table",
  8. {
  9. borderStyle: "1px solid #ccc",
  10. sync: _FALSE,
  11. status: _TRUE
  12. },
  13. function(root){
  14. var bgc = TrexConfig.get("canvas",root).styles.backgroundColor;
  15. if (bgc != "transparent") {
  16. TrexConfig.getTool("table",root).bgcolor = bgc;
  17. }
  18. }
  19. );
  20. TrexMessage.addMsg({
  21. '@table.alert': "1 이상 99 이하의 숫자만 입력 가능합니다."
  22. });
  23. Trex.Tool.Table = Trex.Class.create({
  24. $const: {
  25. __Identity: 'table',
  26. __DEFAULT_TABLE_PROPERTY:{
  27. "cellSpacing": 0,
  28. "cellPadding": 1,
  29. "border": 0,
  30. "style": {
  31. border: "none",
  32. borderCollapse:"collapse"
  33. }
  34. },
  35. __DEFAULT_TABLE_PROPERTY_STR: "cellspacing=\"0\" cellpadding=\"0\" border=\"0\"",
  36. __DEFAULT_TABLE_STYLE: "border:none;border-collapse:collapse;",
  37. __DEFAULT_TABLE_CLASS: "txc-table",
  38. __DEFAULT_TABLE_CELL_HEIGHT: 24
  39. },
  40. $extend: Trex.Tool,
  41. oninitialized: function(config) {
  42. var _self = this;
  43. this.tableSize = { row: 0, col:0 };
  44. var _canvas = this.canvas;
  45. var _toolHandler = this.handler = function(data) {
  46. _canvas.execute(function(processor) {
  47. // get table width
  48. var tableWidth = '100%';
  49. processor.executeUsingCaret(function(range, savedCaret){
  50. var endCaret = savedCaret.getCaret(_FALSE);
  51. if (!$tom.ancestor(endCaret, 'table')) {
  52. tableWidth = _self.getDefaultTableWidth();
  53. }
  54. });
  55. // insert empty table
  56. var table = _self.makeEmptyTable(data.row, data.col, tableWidth);
  57. var _tNode = processor.pasteContent(table, _TRUE);
  58. processor.bookmarkInto(_tNode);
  59. // open advanced toolbar
  60. if (_self.toolbar.tools.advanced) {
  61. _self.toolbar.tools.advanced.forceOpen();
  62. }
  63. });
  64. };
  65. /* button & menu weave */
  66. this.weave.bind(this)(
  67. /* button */
  68. new Trex.Button(this.buttonCfg),
  69. /* menu */
  70. new Trex.Menu.Table(this.menuCfg),
  71. /* handler */
  72. _toolHandler
  73. );
  74. },
  75. makeEmptyTable: function(row, col, tableWidth){
  76. var tableStringArr = [];
  77. tableStringArr.push("<table class=\""+Trex.Tool.Table.__DEFAULT_TABLE_CLASS+"\"");
  78. tableWidth && tableStringArr.push(' width="' + tableWidth + '"');
  79. tableStringArr.push(Trex.Tool.Table.__DEFAULT_TABLE_PROPERTY_STR);
  80. tableStringArr.push(" style=\"");
  81. tableStringArr.push(Trex.Tool.Table.__DEFAULT_TABLE_STYLE);
  82. tableStringArr.push(";font-family:");
  83. tableStringArr.push( this.editor.canvas.getStyle("fontFamily") );
  84. tableStringArr.push(";font-size:");
  85. tableStringArr.push( this.editor.canvas.getStyle("fontSize") );
  86. tableStringArr.push("\"><tbody>");
  87. var borderStyleText = this.config.borderStyle;
  88. var tdWidth = this.getDefaultCellWidth(col, tableWidth),
  89. tdHeight = this.getDefaultCellHeight(row);
  90. var basicBorder = ["border-bottom:",borderStyleText,";border-right:",borderStyleText,";"].join("");
  91. for( var i = 0; i < row; i++ ){
  92. tableStringArr.push("<tr>");
  93. for( var j = 0; j < col; j++ ){
  94. var border = [basicBorder];
  95. tableStringArr.push("<td style=\"width:");
  96. tableStringArr.push(tdWidth);
  97. tableStringArr.push(";");
  98. tableStringArr.push("height:",tdHeight,";");
  99. tableStringArr.push(basicBorder);
  100. if ( i == 0 ){
  101. tableStringArr.push("border-top:",borderStyleText,";");
  102. }
  103. if ( j == 0 ){
  104. tableStringArr.push("border-left:",borderStyleText,";");
  105. }
  106. tableStringArr.push(";\"><p>" + $tom.EMPTY_BOGUS + "</p></td>");
  107. }
  108. tableStringArr.push("</tr>")
  109. }
  110. tableStringArr.push("</tbody></table>");
  111. return tableStringArr.join("");
  112. },
  113. getDefaultCellWidth: function(columnCount, tableWidth) {
  114. var width;
  115. tableWidth = tableWidth || '100%';
  116. if (tableWidth.toString().indexOf('%') !== -1) {
  117. width = (100 / columnCount) + '%';
  118. } else {
  119. width = parseInt(parseInt(tableWidth,10)/columnCount, 10);
  120. if (isNaN(width)) {
  121. width = 0;
  122. }
  123. width = width.toPx();
  124. }
  125. return width;
  126. },
  127. getDefaultCellHeight: function(rowCount) {
  128. return Trex.Tool.Table.__DEFAULT_TABLE_CELL_HEIGHT.toPx();
  129. },
  130. getDefaultTableWidth: function(){ //NOTE: #FTDUEDTR-905
  131. var tableWidth = this.config.tableWidth;
  132. if (!tableWidth) {
  133. tableWidth = this.getCanvasInnerWidth();
  134. }
  135. return tableWidth;
  136. },
  137. getCanvasInnerWidth: function() {
  138. var padding = this.canvas.getSizeConfig().contentPadding || 8;
  139. return (this.canvas.getSizeConfig().contentWidth || 600) - padding * 2 - 20;
  140. }
  141. });
  142. Trex.Tool.Table.TemplateWizard = Trex.Class.create({
  143. initialize: function(){
  144. this.templateList = (typeof getTableTemplateList == "function")? getTableTemplateList() : [{
  145. klass: "ex1",
  146. common: {
  147. backgroundColor:"transparent",
  148. borderTop:"none",
  149. borderLeft:"none",
  150. borderRight: "1px solid #d9d9d9",
  151. borderBottom: "1px solid #d9d9d9"
  152. },
  153. firstRow: {
  154. borderTop: "1px solid #000"
  155. },
  156. firstCol: {
  157. borderLeft: "1px solid #000"
  158. },
  159. lastCol: {
  160. borderRight: "1px solid #000"
  161. },
  162. lastRow: {
  163. borderBottom: "1px solid #000"
  164. },
  165. evenRow: {},
  166. oddRow: {}
  167. }];
  168. this.currentTemplate = _NULL;
  169. },
  170. applyStyle: function(table, templateIndex){
  171. if ( isNaN( templateIndex ) ){
  172. return ;
  173. }
  174. var tableMatrixer = new Trex.Tool.Table.TableCellMatrixer(table);
  175. var tdMatrix = tableMatrixer.getTdMatrix();
  176. this.currentTemplate = this.templateList[templateIndex];
  177. for( var i = 0; i < tdMatrix.length; i++){
  178. for( var j = 0; j < tdMatrix[i].length; j++){
  179. this.setCellStyle(tdMatrix[i][j], {
  180. isEvenRow: (i % 2) == 1,
  181. isFirstRow: i == 0,
  182. isLastRow: i == tdMatrix.length - 1,
  183. isFirstCol: j == 0,
  184. isLastCol: (j == tdMatrix[i].length - 1)
  185. });
  186. }
  187. }
  188. },
  189. setCellStyle: function(elTd, truthMap){
  190. var t = this.currentTemplate;
  191. var style = Object.extend({}, t['common']);
  192. Object.extend(style, (truthMap.isEvenRow)?t['evenRow'] : t['oddRow']);
  193. Object.extend(style, (truthMap.isFirstRow)?t['firstRow'] : (truthMap.isLastRow)?t['lastRow'] : {});
  194. Object.extend(style, (truthMap.isLastCol)?t['lastCol'] : {});
  195. Object.extend(style, (truthMap.isFirstCol)?t['firstCol'] : {});
  196. txlib.setStyle(elTd, style);
  197. },
  198. getTemplateList: function(){
  199. return this.templateList;
  200. }
  201. });
  202. Trex.Tool.Table.TableCellMatrixer = Trex.Class.create({
  203. initialize: function(table){
  204. this.rowSize = this.initRowSize(table);
  205. this.colSize = this.initColSize(table);
  206. var context = $tom.first(table,"tbody") || table;
  207. this.tdMatrix = this.createTdMatrix(context);
  208. //this.table = table;
  209. for (var i = 0; i < this.tdMatrix.length; i++) {
  210. for (var j = 0; j < this.tdMatrix[i].length; j++) {
  211. var td = this.tdMatrix[i][j];
  212. if (td.cols > 1) {
  213. td.cols--;
  214. this.tdMatrix[i].splice(j+1, 0, td);
  215. }
  216. }
  217. }
  218. for( var i = 0; i< this.tdMatrix.length; i++ ){
  219. for( var j = 0; j < this.tdMatrix[i].length; j++ ){
  220. var td = this.tdMatrix[i][j];
  221. if ( td.rows > 1 ){
  222. td.rows--;
  223. this.tdMatrix[i + 1].splice(j, 0, td);
  224. }
  225. }
  226. }
  227. },
  228. createTdMatrix: function(tbody){
  229. var tdMatrix = [];
  230. var trArr = $tom.children(tbody, "tr");
  231. for( var i = 0, len = trArr.length; i < len; i++ ){
  232. tdMatrix.push(this.createTdArray(trArr[i]));
  233. }
  234. return tdMatrix;
  235. },
  236. createTdArray: function(tr){
  237. var tdArr = [];
  238. var tds = $tom.children(tr, "td");
  239. for( var i = 0, len = tds.length; i < len; i++ ){
  240. tdArr.push( this.decorateSingleTd( tds[i] ) );
  241. }
  242. return tdArr;
  243. },
  244. decorateSingleTd: function(td){
  245. var cols = parseInt( td.getAttribute("colSpan") || 1);
  246. var rows = parseInt( td.getAttribute("rowSpan") || 1);
  247. td.cols = cols;
  248. td.rows = (rows-1) * cols + 1;
  249. return td;
  250. },
  251. initRowSize: function(table){
  252. return table.rows.length;
  253. },
  254. initColSize: function(table){
  255. var colSize = 0;
  256. var tdArr = $tom.children( $tom.collect(table, "tr"), "td");
  257. tdArr.each(function(td){
  258. colSize += parseInt(td.getAttribute("colSpan") || 1);
  259. });
  260. return colSize;
  261. },
  262. getRowSize: function(){
  263. return this.rowSize;
  264. },
  265. getColSize: function(){
  266. return this.colSize;
  267. },
  268. getTdMatrix: function(){
  269. return this.tdMatrix;
  270. }
  271. });
  272. TrexMessage.addMsg({
  273. '@table.title.insert': '표삽입 &nbsp;',
  274. '@table.title.setDirectly': '표 직접설정',
  275. '@table.title.row': '열 개수',
  276. '@table.title.col': '행 개수'
  277. });
  278. Trex.MarkupTemplate.add(
  279. 'menu.table.direct', [
  280. '<div>@table.title.setDirectly</div>',
  281. '<div class="tx-table-input-area">',
  282. '<div class="tx-field tx-col-field">@table.title.row<input type="text" value="1"><a class="tx-btn tx-btn-add" href="javascript:;">@table.title.row+</a><a class="tx-btn tx-btn-sub" href="javascript:;">@table.title.row-</a></div>',
  283. '<div class="tx-field tx-row-field">@table.title.col<input type="text" value="1"><a class="tx-btn tx-btn-add" href="javascript:;">@table.title.col+</a><a class="tx-btn tx-btn-sub" href="javascript:;">@table.title.col-</a></div>',
  284. '</div>'
  285. ].join("")
  286. );
  287. /* Trex.Menu.Table ************************************************************************************/
  288. Trex.Menu.Table = Trex.Class.create({
  289. $const:{
  290. MAX_ROW:99,
  291. MAX_COL:99
  292. },
  293. $extend: Trex.Menu,
  294. ongenerated: function() {
  295. this.rowSize = 1;
  296. this.colSize = 1;
  297. this.elInnerPreview = $tom.collect(this.elMenu, 'div.tx-menu-inner .tx-menu-preview');
  298. this.dynamicSizer = this.generateDynamicSizer(this.elInnerPreview);
  299. this.elInnerRowCol = $tom.collect(this.elMenu, 'div.tx-menu-inner .tx-menu-rowcol');
  300. this.generateTextSizer(this.elInnerRowCol);
  301. this.elButtonArea = $tom.collect(this.elMenu, 'div.tx-menu-inner .tx-menu-enter');
  302. this.generateButtonArea(this.elButtonArea);
  303. },
  304. onregenerated: function() {
  305. this.showDynamicSizer();
  306. },
  307. showDynamicSizer: function(){
  308. this.dynamicSizer.clear();
  309. $tx.show( this.elInnerPreview );
  310. $tx.hide( this.elInnerRowCol );
  311. $tx.hide( this.elButtonArea );
  312. },
  313. showTextSizer: function(){
  314. $tx.hide(this.elInnerPreview);
  315. $tx.show(this.elInnerRowCol);
  316. $tx.show(this.elButtonArea);
  317. },
  318. generateDynamicSizer: function(elPreivewContext){
  319. var _self = this;
  320. var elRowCol= tx.span();
  321. var elDisplay = tx.div({className:"tx-dynamic-sizer-display"}, TXMSG('@table.title.insert'), elRowCol);
  322. elPreivewContext.appendChild( elDisplay );
  323. var dynamicSizer = new Trex.DynamicSizer({
  324. el: elPreivewContext,
  325. clickHandler: this.onSelect.bind(this),
  326. moveHandler: function(row, col){
  327. elRowCol.innerHTML = row + 'x' +col;
  328. }
  329. });
  330. var _elA = tx.a({href:"javascript:;"}, TXMSG('@table.title.setDirectly'));
  331. $tx.observe( _elA, "click", function(ev){
  332. _self.showTextSizer();
  333. $tx.stop(ev);
  334. _self.fireJobs(Trex.Ev.__MENU_LAYER_CHANGE_SIZE, {
  335. detail: {
  336. menu: _self
  337. }
  338. });
  339. });
  340. var _elButton = tx.div({className:"tx-more-button"});
  341. _elButton.appendChild(_elA);
  342. elPreivewContext.appendChild( _elButton );
  343. return dynamicSizer;
  344. },
  345. generateTextSizer: function(elContext) {
  346. var _self = this;
  347. Trex.MarkupTemplate.get('menu.table.direct').evaluateToDom({}, elContext);
  348. var calculator = {
  349. calculate: function(value, max, operand){
  350. value = parseInt(value);
  351. if ( value + operand > max || value + operand< 1){
  352. alert( TXMSG("@table.alert") );
  353. return value;
  354. }else{
  355. return value + operand;
  356. }
  357. },
  358. getValidValue:function(value, previousValue, max){
  359. if ( value <= 0 || value > max ){
  360. alert( TXMSG("@table.alert") );
  361. return previousValue;
  362. }else{
  363. return value;
  364. }
  365. }
  366. };
  367. var colInput = $tom.collect(elContext, "div.tx-col-field input");
  368. $tx.observe(colInput, "blur", function(){
  369. colInput.value = _self.colSize = calculator.getValidValue(colInput.value, _self.colSize, Trex.Menu.Table.MAX_COL);
  370. });
  371. $tx.observe( $tom.collect(elContext, "div.tx-col-field a.tx-btn-add"), "click", function(e){
  372. colInput.value = _self.colSize = calculator.calculate(_self.colSize, Trex.Menu.Table.MAX_COL, 1);
  373. $tx.stop(e);
  374. return _FALSE;
  375. });
  376. $tx.observe($tom.collect(elContext, "div.tx-col-field a.tx-btn-sub"), "click", function(e){
  377. colInput.value = _self.colSize = calculator.calculate(_self.colSize, Trex.Menu.Table.MAX_COL, -1);
  378. $tx.stop(e);
  379. return _FALSE;
  380. });
  381. var rowInput = $tom.collect(elContext, "div.tx-row-field input");
  382. $tx.observe(rowInput, "blur", function(){
  383. rowInput.value = _self.rowSize = calculator.getValidValue(rowInput.value, _self.rowSize, Trex.Menu.Table.MAX_ROW);
  384. });
  385. $tx.observe($tom.collect(elContext, "div.tx-row-field a.tx-btn-add"), "click", function(e){
  386. rowInput.value = _self.rowSize = calculator.calculate(_self.rowSize, Trex.Menu.Table.MAX_ROW, 1);
  387. $tx.stop(e);
  388. return _FALSE;
  389. });
  390. $tx.observe($tom.collect(elContext, "div.tx-row-field a.tx-btn-sub"), "click", function(e){
  391. rowInput.value = _self.rowSize = calculator.calculate(_self.rowSize, Trex.Menu.Table.MAX_ROW, -1);
  392. $tx.stop(e);
  393. return _FALSE;
  394. });
  395. },
  396. generateButtonArea: function(elContext){
  397. var _self = this;
  398. var elDiv = tx.div();
  399. var elAConfirm = tx.a({href:"javascript:;", className:"tx-btn-confirm"}, "확인");
  400. var elACancel = tx.a({href:"javascript:;", className:"tx-btn-cancel"}, "취소");
  401. $tx.observe( elAConfirm, "click", function(ev){
  402. _self.onSelect(ev, {
  403. row: _self.rowSize,
  404. col: _self.colSize
  405. });
  406. });
  407. $tx.observe(elACancel, "click", function(e) {
  408. $tx.stop(e);
  409. this.onCancel();
  410. return _FALSE;
  411. }.bindAsEventListener(this));
  412. elDiv.appendChild(elAConfirm);
  413. elDiv.appendChild(elACancel);
  414. elContext.appendChild(elDiv);
  415. }
  416. });