| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535 |
- /*jslint nomen: false*/
- /*global Trex, $tom, $tx, _FALSE, _NULL, _TRUE */
- Trex.TableUtil = {
- /**
- * isDaumTable
- * @param {Element} table
- * @return {boolean}
- */
- isDaumTable: function (table) {
- return $tx.hasClassName(table, "txc-table");
- },
- /**
- * cloneNodeForEmptyTd
- * @param {Element} node
- */
- cloneNodeForEmptyTd: function (node) {
- var newNode;
- newNode = node.cloneNode(_FALSE);
- Trex.TableUtil.emptyTd(newNode);
- return newNode;
- },
- emptyTd: function (node) {
- node.innerHTML = " ";
- },
- /**
- * splitWidthByColSpan
- * @param {Element} td
- */
- splitWidthByColSpan: function (td) {
- var styleWidth;
- if (1 < td.colSpan && td.style.width) {
- styleWidth = parseInt(td.style.width, 10);
- $tom.setStyles(td, {
- width: Math.floor(styleWidth / td.colSpan) + "px"
- }, _TRUE);
- }
- },
- /**
- * splitHeightByRowSpan
- * @param {Element} td
- */
- splitHeightByRowSpan: function (td) {
- var styleHeight;
- if (1 < td.rowSpan && td.style.height) {
- styleHeight = parseInt(td.style.height, 10);
- $tom.setStyles(td, {
- height: Math.floor(styleHeight / td.rowSpan) + "px"
- }, _TRUE);
- }
- },
- /**
- * collapseCaret
- * @param {Trex.Canvas.WysiwygPanel} wysiwygPanel
- * @param {Element} node
- */
- collapseCaret: function (wysiwygPanel, node) {
- var range;
- try {
- range = wysiwygPanel.getProcessor().createGoogRangeFromNodes(node, 0, node, 0);
- range.select();
- } catch (ignore) {}
- //td space bug from create textnode.
- //wysiwygPanel.getProcessor().moveCaretTo(node);
- },
- /**
- * getClosestByTagNames
- * @param {Array} tagNames
- * @param {Element} el
- * @return {Element}
- */
- getClosestByTagNames: function (tagNames, el) {
- var tagName;
- if (el && typeof el.tagName === "string") {
- tagName = el.tagName.toLowerCase();
- if (tagName !== "body") {
- if (tagNames.contains(tagName)) {
- return el;
- } else {
- return arguments.callee(tagNames, el.parentNode);
- }
- }
- }
- return _NULL;
- },
- /**
- * getTableIndexerFromTd
- * @param {Element} td
- * @return {Trex.TableUtil.Indexer}
- */
- getTableIndexerFromTd: function (td) {
- var currentTable;
- currentTable = Trex.TableUtil.getClosestByTagNames(["table"], td);
- return new Trex.TableUtil.Indexer(currentTable);
- }
- };
- //////////////////////////////////////////////////////////
- /**
- * Trex.TableUtil.Boundary class
- * @param {Object} indexs (optional)
- */
- Trex.TableUtil.Boundary = Trex.Class.create({
- initialize: function (indexs) {
- this.top = -1;
- this.left = -1;
- this.bottom = -1;
- this.right = -1;
- if (indexs) {
- this.set(indexs);
- }
- },
- /**
- * getTop
- * @return {number} start row index
- */
- getTop: function () {
- return this.top;
- },
- /**
- * getLeft
- * @return {number} start col index
- */
- getLeft: function () {
- return this.left;
- },
- /**
- * getBottom
- * @return {number} end row index
- */
- getBottom: function () {
- return this.bottom;
- },
- /**
- * getRight
- * @return {number} end col index
- */
- getRight: function () {
- return this.right;
- },
- /**
- * setTop
- * @param {number} index
- */
- setTop: function (index) {
- this.top = index;
- },
- /**
- * setLeft
- * @param {number} index
- */
- setLeft: function (index) {
- this.left = index;
- },
- /**
- * setBottom
- * @param {number} index
- */
- setBottom: function (index) {
- this.bottom = index;
- },
- /**
- * setRight
- * @param {number} index
- */
- setRight: function (index) {
- this.right = index;
- },
- /**
- * set
- * @param {Object} indexs
- */
- set: function (indexs) {
- if ("top" in indexs) {
- this.setTop(indexs.top);
- }
- if ("left" in indexs) {
- this.setLeft(indexs.left);
- }
- if ("bottom" in indexs) {
- this.setBottom(indexs.bottom);
- }
- if ("right" in indexs) {
- this.setRight(indexs.right);
- }
- },
- /**
- * isValid
- * @return {boolean}
- */
- isValid: function () {
- if (this.top === -1) {
- return _FALSE;
- }
- if (this.left === -1) {
- return _FALSE;
- }
- if (this.bottom === -1) {
- return _FALSE;
- }
- if (this.right === -1) {
- return _FALSE;
- }
- return _TRUE;
- },
- /**
- * addBoundary
- * @param {number} rowIndex
- * @param {number} colIndex
- * @return {boolean} changed
- */
- addBoundary: function (rowIndex, colIndex) {
- var changedStart, changedEnd;
- changedStart = this.addStartBoundary(rowIndex, colIndex);
- changedEnd = this.addEndBoundary(rowIndex, colIndex);
- return changedStart || changedEnd;
- },
- /**
- * merge
- * @param {Trex.TableUtil.Boundary} boundary
- * @return {boolean} changed
- */
- merge: function (boundary) {
- var changedStart, changedEnd;
- changedStart = this.addStartBoundary(boundary.top, boundary.left);
- changedEnd = this.addEndBoundary(boundary.bottom, boundary.right);
- return changedStart || changedEnd;
- },
- /**
- * addStartBoundary
- * @private
- * @param {number} rowIndex
- * @param {number} colIndex
- * @return {boolean} changed
- */
- addStartBoundary: function (rowIndex, colIndex) {
- var changed;
- changed = _FALSE;
- if (this.top === -1 || rowIndex < this.top) {
- this.top = rowIndex;
- changed = _TRUE;
- }
- if (this.left === -1 || colIndex < this.left) {
- this.left = colIndex;
- changed = _TRUE;
- }
- return changed;
- },
- /**
- * addEndBoundary
- * @private
- * @param {number} rowIndex
- * @param {number} colIndex
- * @return {boolean} changed
- */
- addEndBoundary: function (rowIndex, colIndex) {
- var changed;
- changed = _FALSE;
- if (this.bottom === -1 || this.bottom < rowIndex) {
- this.bottom = rowIndex;
- changed = _TRUE;
- }
- if (this.right === -1 || this.right < colIndex) {
- this.right = colIndex;
- changed = _TRUE;
- }
- return changed;
- }
- });
- //////////////////////////////////////////////////////////
- // Indexer 는 사람에게 보이는대로의 index 로 table 을
- // 조작하는데 도움을 준다. DOM 에서는 rowSpan 과
- // colSpan 때문에 보이는 index 와 일치하지 않기 때문임.
- /**
- * Trex.TableUtil.Indexer class
- * @param {Element} table
- */
- Trex.TableUtil.Indexer = Trex.Class.create({
- initialize: function (table) {
- this.indexData = _NULL;
- this.table = _NULL;
-
- this.resetIndex();
- this.setTable(table);
- this.makeIndex();
- },
- /**
- * getRowSize
- * @return {number}
- */
- getRowSize: function () {
- return this.indexData.length;
- },
- /**
- * getColSize
- * @return {number}
- */
- getColSize: function () {
- if (0 < this.indexData.length) {
- return this.indexData[0].length;
- }
- return 0;
- },
- /**
- * getTd
- * rowIndex 와 colIndex 에 매칭되는 td 를 가져온다.
- * @param {number} rowIndex
- * @param {number} colIndex
- * @return {Elememt} td
- */
- getTd: function (rowIndex, colIndex) {
- if (this.indexData[rowIndex]) {
- if (this.indexData[rowIndex][colIndex]) {
- return this.indexData[rowIndex][colIndex];
- }
- }
- return _NULL;
- },
- /**
- * getTdArr
- * Boundary 에 포함되는 td 들을 가져온다.
- * @param {Trex.TableUtil.Boundary} boundary
- * @return {Array} tdArr [td, td, ...] (order by top-left)
- */
- getTdArr: function (boundary) {
- var result, rowIndex, cells, colIndex;
- result = [];
- rowIndex = boundary.top;
- while (rowIndex <= boundary.bottom) {
- cells = this.indexData[rowIndex];
- colIndex = boundary.left;
- while (colIndex <= boundary.right) {
- if (result.contains(cells[colIndex]) === _FALSE) {
- result.push(cells[colIndex]);
- }
- colIndex += 1;
- }
- rowIndex += 1;
- }
- return result;
- },
-
- /**
- * getTdArrHasTop
- * 해당하는 row index 를 top 으로 가지는 cell 들을 가져온다.
- * @param {number} index
- * @return {Array} tdArr [td, td, ...] (order by left-top)
- */
- getTdArrHasTop: function (index) {
- var result, currentCell, adjoiningCell, len, i;
- result = [];
- len = this.getColSize();
- for (i = 0; i < len; i += 1) {
- currentCell = this.getTd(index, i);
- adjoiningCell = this.getTd(index - 1, i);
- this.uniquePushWhenDifferent(result, currentCell, adjoiningCell);
- }
- return result;
- },
- /**
- * getTdArrHasBottom
- * 해당하는 row index 를 bottom 으로 가지는 cell 들을 가져온다.
- * @param {number} index
- * @return {Array} tdArr [td, td, ...] (order by left-top)
- */
- getTdArrHasBottom: function (index) {
- var result, currentCell, adjoiningCell, len, i;
- result = [];
- len = this.getColSize();
- for (i = 0; i < len; i += 1) {
- currentCell = this.getTd(index, i);
- adjoiningCell = this.getTd(index + 1, i);
- this.uniquePushWhenDifferent(result, currentCell, adjoiningCell);
- }
- return result;
- },
- /**
- * getTdArrHasLeft
- * 해당하는 row index 를 left 로 가지는 cell 들을 가져온다.
- * @param {number} index
- * @return {Array} tdArr [td, td, ...] (order by left-top)
- */
- getTdArrHasLeft: function (index) {
- var result, currentCell, adjoiningCell, len, i;
- result = [];
- len = this.getRowSize();
- for (i = 0; i < len; i += 1) {
- currentCell = this.getTd(i, index);
- adjoiningCell = this.getTd(i, index - 1);
- this.uniquePushWhenDifferent(result, currentCell, adjoiningCell);
- }
- return result;
- },
- /**
- * getTdArrHasRight
- * 해당하는 row index 를 right 로 가지는 cell 들을 가져온다.
- * @param {number} index
- * @return {Array} tdArr [td, td, ...] (order by left-top)
- */
- getTdArrHasRight: function (index) {
- var result, currentCell, adjoiningCell, len, i;
- result = [];
- len = this.getRowSize();
- for (i = 0; i < len; i += 1) {
- currentCell = this.getTd(i, index);
- adjoiningCell = this.getTd(i, index + 1);
- this.uniquePushWhenDifferent(result, currentCell, adjoiningCell);
- }
- return result;
- },
-
- /**
- * getBoundary
- * td 에 해당하는 boundary 를 구한다.
- * @param {Elememt} td
- * @return {Trex.TableUtil.Boundary} boundary
- */
- getBoundary: function (td) {
- var result, rows, rowLen, rowIndex, cells, cellLen, colIndex;
- result = new Trex.TableUtil.Boundary();
- rows = this.indexData;
- rowLen = rows.length;
- for (rowIndex = 0; rowIndex < rowLen; rowIndex += 1) {
- cells = rows[rowIndex];
- if (cells) {
- cellLen = cells.length;
- for (colIndex = 0; colIndex < cellLen; colIndex += 1) {
- if (cells[colIndex] === td) {
- result.addBoundary(rowIndex, colIndex);
- }
- }
- }
- }
- return result;
- },
- /**
- * reload
- * 인덱스 갱신(테이블이 변경되었을 때).
- */
- reload: function () {
- this.resetIndex();
- this.makeIndex();
- },
- /**
- * uniquePushWhenDifferent
- * currentCell 과 adjoiningCell 이 다르면 currentCell 를 tdArr 에 중복없이 push 한다.
- * @private
- * @param {Array} tdArr
- * @param {Element} currentCell
- * @param {Element} adjoiningCell
- */
- uniquePushWhenDifferent: function (tdArr, currentCell, adjoiningCell) {
- if (currentCell !== adjoiningCell) {
- if (tdArr.contains(currentCell) === _FALSE) {
- tdArr.push(currentCell);
- }
- }
- },
- /**
- * resetIndex
- * @private
- */
- resetIndex: function () {
- this.indexData = [];
- },
- /**
- * setTable
- * @private
- * @param {Element} table
- */
- setTable: function (table) {
- this.table = table;
- },
- /**
- * makeIndex
- * rowSpan 과 colSpan 을 펼친 형태의 array 에 table cell 들을 매칭시킨다.
- * @private
- */
- makeIndex: function () {
- var rows, rowLen, rowIndex, row, cells, cellLen, colIndex, cell;
- rows = this.table.rows;
- rowLen = rows.length;
- for (rowIndex = 0; rowIndex < rowLen; rowIndex += 1) {
- row = rows[rowIndex];
- cells = row.cells;
- cellLen = cells.length;
- for (colIndex = 0; colIndex < cellLen; colIndex += 1) {
- cell = cells[colIndex];
- this.addCellIndex(rowIndex, cell);
- }
- }
- },
- /**
- * addCellIndex
- * 만들고 있는 indexData 에 해당 cell 에 대한 index 를 추가한다.
- * @private
- * @param {number} rowIndex
- * @param {Element} cell
- */
- addCellIndex: function (rowIndex, cell) {
- var viewIndexOfCell, row, rowSpan, calculatedRowIndex, col, colSpan;
- viewIndexOfCell = this.getNextCellIndex(this.indexData[rowIndex]);
- rowSpan = cell.rowSpan;
- for (row = 0; row < rowSpan; row += 1) {
- calculatedRowIndex = rowIndex + row;
- if (! this.indexData[calculatedRowIndex]) {
- this.indexData[calculatedRowIndex] = [];
- }
- colSpan = cell.colSpan;
- for (col = 0; col < colSpan; col += 1) {
- this.indexData[calculatedRowIndex][viewIndexOfCell + col] = cell;
- }
- }
- },
- /**
- * getNextCellIndex
- * arr 를 순환하면서 처음으로 만난 빈 요소의 index 를 반환한다.
- * arr 가 없으면 0 을 반환, 빈 요소가 없으면 length 를 반환한다.
- * @private
- * @param {Array} arr
- * @return {number} cell index
- */
- getNextCellIndex: function (arr) {
- var i, len;
- if (! arr) {
- return 0;
- }
- len = arr.length;
- for (i = 0; i < len; i += 1) {
- if (! arr[i]) {
- break;
- }
- }
- return i;
- }
- });
|