Ticket #7969: TableTools.coffee

File TableTools.coffee, 7.5 KB (added by Audrey Tang, 10 years ago)

CoffeeScript Source for Move Row/Column context menu implementation

Line 
1CKEDITOR.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
© 2003 – 2022, CKSource sp. z o.o. sp.k. All rights reserved. | Terms of use | Privacy policy