1 | CKEDITOR.on 'instanceCreated', ({editor}) -> editor.on 'pluginsLoaded', -> |
---|
2 | {TRISTATE_OFF: ENABLED, TRISTATE_DISABLED: DISABLED} = CKEDITOR |
---|
3 | RedrawSubMenuName = null |
---|
4 | OffsetsByLevel = [] |
---|
5 | |
---|
6 | row = editor.getMenuItem('tablerow') |
---|
7 | rowItems = row.getItems() |
---|
8 | row.getItems = -> |
---|
9 | sel = editor.getSelection() |
---|
10 | $.extend { |
---|
11 | tablerow_moveBefore: if isFirstRow(sel) then DISABLED else ENABLED |
---|
12 | tablerow_moveAfter: if isLastRow(sel) then DISABLED else ENABLED |
---|
13 | }, rowItems |
---|
14 | |
---|
15 | col = editor.getMenuItem('tablecolumn') |
---|
16 | colItems = col.getItems() |
---|
17 | col.getItems = -> |
---|
18 | sel = editor.getSelection() |
---|
19 | $.extend { |
---|
20 | tablecolumn_moveBefore: if isFirstColumn(sel) then DISABLED else ENABLED |
---|
21 | tablecolumn_moveAfter: if isLastColumn(sel) then DISABLED else ENABLED |
---|
22 | }, colItems |
---|
23 | |
---|
24 | editor.addMenuItems |
---|
25 | tablerow_moveBefore: |
---|
26 | label: 'Move Row Before' |
---|
27 | group: 'tablerow' |
---|
28 | command: 'rowMoveBefore' |
---|
29 | order: 11 |
---|
30 | tablerow_moveAfter: |
---|
31 | label: 'Move Row After' |
---|
32 | group: 'tablerow' |
---|
33 | command: 'rowMoveAfter' |
---|
34 | order: 12 |
---|
35 | tablecolumn_moveBefore: |
---|
36 | label: 'Move Column Before' |
---|
37 | group: 'tablecolumn' |
---|
38 | command: 'columnMoveBefore' |
---|
39 | order: 11 |
---|
40 | tablecolumn_moveAfter: |
---|
41 | label: 'Move Column After' |
---|
42 | group: 'tablecolumn' |
---|
43 | command: 'columnMoveAfter' |
---|
44 | order: 12 |
---|
45 | |
---|
46 | editor.addCommand "rowMoveBefore", |
---|
47 | exec: (editor) -> moveRowBefore editor.getSelection() |
---|
48 | editor.addCommand "rowMoveAfter", |
---|
49 | exec: (editor) -> moveRowAfter editor.getSelection() |
---|
50 | editor.addCommand "columnMoveBefore", |
---|
51 | exec: (editor) -> moveColumnBefore editor.getSelection() |
---|
52 | editor.addCommand "columnMoveAfter", |
---|
53 | exec: (editor) -> moveColumnAfter editor.getSelection() |
---|
54 | |
---|
55 | for key in ['rowInsertBefore', 'rowInsertAfter', 'columnInsertBefore', 'columnInsertAfter'] |
---|
56 | cmd = editor._.commands[key] |
---|
57 | continue if cmd._origExec |
---|
58 | subMenuName = "table#{ key.replace(/Insert.*/, '') }" |
---|
59 | do (cmd, subMenuName) -> |
---|
60 | cmd._origExec = cmd.exec |
---|
61 | cmd.exec = (args...) -> |
---|
62 | rv = @_origExec(args...) |
---|
63 | redrawContextMenu subMenuName |
---|
64 | return rv |
---|
65 | |
---|
66 | MenuElement = null |
---|
67 | CKEDITOR.ui.on 'ready', ({data}) -> |
---|
68 | MenuElement = data if data._?.panel |
---|
69 | |
---|
70 | editor.on 'menuShow', ({data}) -> |
---|
71 | return unless RedrawSubMenuName |
---|
72 | panel = data[0] |
---|
73 | level = panel._.definition.level |
---|
74 | setTimeout((-> |
---|
75 | panel.element.setStyles OffsetsByLevel[level] |
---|
76 | for item, idx in MenuElement.items |
---|
77 | continue unless item.name == RedrawSubMenuName |
---|
78 | do (MenuElement, idx) -> setTimeout((-> MenuElement._.showSubMenu idx), 100) |
---|
79 | RedrawSubMenuName = null |
---|
80 | return |
---|
81 | ), 1) |
---|
82 | |
---|
83 | # Utility functions to detect edge of tables. |
---|
84 | |
---|
85 | isFirstRow = (selection) -> |
---|
86 | cells = getSelectedCells( selection ) |
---|
87 | firstCell = cells[0] |
---|
88 | startRow = firstCell.getParent() |
---|
89 | startRowIndex = startRow.$.rowIndex |
---|
90 | return true if startRowIndex == 0 |
---|
91 | table = firstCell.getAscendant( 'table' ) |
---|
92 | rowCells = table.$.rows[0].cells |
---|
93 | maxRowSpan = Math.max((mapCell.rowSpan for mapCell in rowCells)...) |
---|
94 | return startRowIndex <= (maxRowSpan-1) |
---|
95 | |
---|
96 | isLastRow = (selection) -> |
---|
97 | cells = getSelectedCells( selection ) |
---|
98 | lastCell = cells[ cells.length - 1 ] |
---|
99 | table = lastCell.getAscendant( 'table' ) |
---|
100 | endRow = lastCell.getParent() |
---|
101 | rowCells = endRow.$.cells |
---|
102 | endRowIndex = endRow.$.rowIndex |
---|
103 | maxRowSpan = Math.max((mapCell.rowSpan for mapCell in rowCells)...) |
---|
104 | return ((endRowIndex + maxRowSpan) >= table.$.rows.length) |
---|
105 | |
---|
106 | isFirstColumn = (selection) -> |
---|
107 | cells = getSelectedCells( selection ) |
---|
108 | startColIndex = getColumnsIndices( cells, 1 ) |
---|
109 | return (startColIndex == 0) |
---|
110 | |
---|
111 | isLastColumn = (selection) -> |
---|
112 | cells = getSelectedCells( selection ) |
---|
113 | endColIndex = getColumnsIndices( cells ) |
---|
114 | lastRow = cells[ cells.length - 1 ].getParent() |
---|
115 | rowCells = lastRow.$.cells |
---|
116 | colIndex = -1 |
---|
117 | for mapCell in rowCells |
---|
118 | colIndex += mapCell.colSpan |
---|
119 | return false if colIndex > endColIndex |
---|
120 | return true |
---|
121 | |
---|
122 | $$ = (elm) -> new CKEDITOR.dom.element(elm) |
---|
123 | |
---|
124 | moveRowBefore = (selection) -> |
---|
125 | cells = getSelectedCells( selection ) |
---|
126 | endRow = cells[ cells.length - 1 ].getParent() |
---|
127 | firstCell = cells[ 0 ] |
---|
128 | startRowIndex = firstCell.getParent().$.rowIndex |
---|
129 | table = firstCell.getAscendant( 'table' ) |
---|
130 | prevRow = table.$.rows[startRowIndex - 1] |
---|
131 | $$(prevRow).insertAfter endRow |
---|
132 | redrawContextMenu 'tablerow' |
---|
133 | |
---|
134 | moveRowAfter = (selection) -> |
---|
135 | cells = getSelectedCells( selection ) |
---|
136 | startRow = cells[ 0 ].getParent() |
---|
137 | lastCell = cells[ cells.length - 1 ] |
---|
138 | endRowIndex = lastCell.getParent().$.rowIndex + lastCell.$.rowSpan - 1 |
---|
139 | table = lastCell.getAscendant( 'table' ) |
---|
140 | nextRow = table.$.rows[endRowIndex + 1] |
---|
141 | $$(nextRow).insertBefore startRow |
---|
142 | redrawContextMenu 'tablerow' |
---|
143 | |
---|
144 | moveColumn = (selection, isBefore) -> |
---|
145 | cells = getSelectedCells( selection ) |
---|
146 | table = cells[0].getAscendant( 'table' ) |
---|
147 | startColIndex = getColumnsIndices( cells, 1 ) |
---|
148 | endColIndex = getColumnsIndices( cells ) |
---|
149 | for row in table.$.rows |
---|
150 | rowCells = row.cells |
---|
151 | if isBefore |
---|
152 | $$(rowCells[startColIndex - 1]).insertAfter $$(rowCells[endColIndex]) |
---|
153 | else |
---|
154 | $$(rowCells[endColIndex + 1]).insertBefore $$(rowCells[startColIndex]) |
---|
155 | redrawContextMenu 'tablecolumn' |
---|
156 | |
---|
157 | moveColumnBefore = (selection) -> |
---|
158 | moveColumn selection, true |
---|
159 | |
---|
160 | moveColumnAfter = (selection) -> |
---|
161 | moveColumn selection, false |
---|
162 | |
---|
163 | redrawContextMenu = (subMenuName) -> |
---|
164 | RedrawSubMenuName = subMenuName |
---|
165 | for elm, idx in $('.cke_contextmenu').get() |
---|
166 | $parent = $(elm).parent() |
---|
167 | OffsetsByLevel[idx] = |
---|
168 | top: $parent.css('top') |
---|
169 | left: $parent.css('left') |
---|
170 | editor.execCommand 'contextMenu' |
---|
171 | |
---|
172 | # Everything below is copied from tabletools/plugin.js # |
---|
173 | cellNodeRegex = /^(?:td|th)$/ |
---|
174 | |
---|
175 | getSelectedCells = (selection) -> |
---|
176 | bookmarks = selection.createBookmarks() |
---|
177 | ranges = selection.getRanges() |
---|
178 | retval = [] |
---|
179 | database = {} |
---|
180 | i = 0 |
---|
181 | |
---|
182 | moveOutOfCellGuard = (node) -> |
---|
183 | return if retval.length > 0 |
---|
184 | if node.type is CKEDITOR.NODE_ELEMENT and cellNodeRegex.test(node.getName()) and not node.getCustomData("selected_cell") |
---|
185 | CKEDITOR.dom.element.setMarker database, node, "selected_cell", true |
---|
186 | retval.push node |
---|
187 | return |
---|
188 | |
---|
189 | for range in ranges |
---|
190 | if range.collapsed |
---|
191 | startNode = range.getCommonAncestor() |
---|
192 | nearestCell = startNode.getAscendant("td", true) or startNode.getAscendant("th", true) |
---|
193 | retval.push nearestCell if nearestCell |
---|
194 | else |
---|
195 | walker = new CKEDITOR.dom.walker(range) |
---|
196 | node = undefined |
---|
197 | walker.guard = moveOutOfCellGuard |
---|
198 | while (node = walker.next()) |
---|
199 | parent = node.getAscendant("td") or node.getAscendant("th") |
---|
200 | if parent and not parent.getCustomData("selected_cell") |
---|
201 | CKEDITOR.dom.element.setMarker database, parent, "selected_cell", true |
---|
202 | retval.push parent |
---|
203 | |
---|
204 | CKEDITOR.dom.element.clearAllMarkers database |
---|
205 | selection.selectBookmarks bookmarks |
---|
206 | return retval |
---|
207 | |
---|
208 | getColumnsIndices = (cells, isStart) -> |
---|
209 | retval = (if isStart then Infinity else 0) |
---|
210 | for cell in cells |
---|
211 | colIndex = getCellColIndex(cell, isStart) |
---|
212 | if isStart |
---|
213 | retval = colIndex if colIndex < retval |
---|
214 | else |
---|
215 | retval = colIndex if colIndex > retval |
---|
216 | return retval |
---|
217 | |
---|
218 | getCellColIndex = (cell, isStart) -> |
---|
219 | row = cell.getParent() |
---|
220 | rowCells = row.$.cells |
---|
221 | colIndex = 0 |
---|
222 | |
---|
223 | for mapCell in rowCells |
---|
224 | colIndex += (if isStart then 1 else mapCell.colSpan) |
---|
225 | break if mapCell is cell.$ |
---|
226 | return colIndex - 1 |
---|