|
1 /** |
|
2 * CellSelection.js |
|
3 * |
|
4 * Copyright, Moxiecode Systems AB |
|
5 * Released under LGPL License. |
|
6 * |
|
7 * License: http://www.tinymce.com/license |
|
8 * Contributing: http://www.tinymce.com/contributing |
|
9 */ |
|
10 |
|
11 /** |
|
12 * This class handles table cell selection by faking it using a css class that gets applied |
|
13 * to cells when dragging the mouse from one cell to another. |
|
14 * |
|
15 * @class tinymce.tableplugin.CellSelection |
|
16 * @private |
|
17 */ |
|
18 define("tinymce/tableplugin/CellSelection", [ |
|
19 "tinymce/tableplugin/TableGrid", |
|
20 "tinymce/dom/TreeWalker", |
|
21 "tinymce/util/Tools" |
|
22 ], function(TableGrid, TreeWalker, Tools) { |
|
23 return function(editor) { |
|
24 var dom = editor.dom, tableGrid, startCell, startTable, hasCellSelection = true, resizing; |
|
25 |
|
26 function clear(force) { |
|
27 // Restore selection possibilities |
|
28 editor.getBody().style.webkitUserSelect = ''; |
|
29 |
|
30 if (force || hasCellSelection) { |
|
31 editor.dom.removeClass( |
|
32 editor.dom.select('td.mce-item-selected,th.mce-item-selected'), |
|
33 'mce-item-selected' |
|
34 ); |
|
35 |
|
36 hasCellSelection = false; |
|
37 } |
|
38 } |
|
39 |
|
40 function cellSelectionHandler(e) { |
|
41 var sel, table, target = e.target; |
|
42 |
|
43 if (resizing) { |
|
44 return; |
|
45 } |
|
46 |
|
47 if (startCell && (tableGrid || target != startCell) && (target.nodeName == 'TD' || target.nodeName == 'TH')) { |
|
48 table = dom.getParent(target, 'table'); |
|
49 if (table == startTable) { |
|
50 if (!tableGrid) { |
|
51 tableGrid = new TableGrid(editor, table); |
|
52 tableGrid.setStartCell(startCell); |
|
53 |
|
54 editor.getBody().style.webkitUserSelect = 'none'; |
|
55 } |
|
56 |
|
57 tableGrid.setEndCell(target); |
|
58 hasCellSelection = true; |
|
59 } |
|
60 |
|
61 // Remove current selection |
|
62 sel = editor.selection.getSel(); |
|
63 |
|
64 try { |
|
65 if (sel.removeAllRanges) { |
|
66 sel.removeAllRanges(); |
|
67 } else { |
|
68 sel.empty(); |
|
69 } |
|
70 } catch (ex) { |
|
71 // IE9 might throw errors here |
|
72 } |
|
73 |
|
74 e.preventDefault(); |
|
75 } |
|
76 } |
|
77 |
|
78 // Add cell selection logic |
|
79 editor.on('MouseDown', function(e) { |
|
80 if (e.button != 2 && !resizing) { |
|
81 clear(); |
|
82 |
|
83 startCell = dom.getParent(e.target, 'td,th'); |
|
84 startTable = dom.getParent(startCell, 'table'); |
|
85 } |
|
86 }); |
|
87 |
|
88 editor.on('mouseover', cellSelectionHandler); |
|
89 |
|
90 editor.on('remove', function() { |
|
91 dom.unbind(editor.getDoc(), 'mouseover', cellSelectionHandler); |
|
92 }); |
|
93 |
|
94 editor.on('MouseUp', function() { |
|
95 var rng, sel = editor.selection, selectedCells, walker, node, lastNode; |
|
96 |
|
97 function setPoint(node, start) { |
|
98 var walker = new TreeWalker(node, node); |
|
99 |
|
100 do { |
|
101 // Text node |
|
102 if (node.nodeType == 3 && Tools.trim(node.nodeValue).length !== 0) { |
|
103 if (start) { |
|
104 rng.setStart(node, 0); |
|
105 } else { |
|
106 rng.setEnd(node, node.nodeValue.length); |
|
107 } |
|
108 |
|
109 return; |
|
110 } |
|
111 |
|
112 // BR element |
|
113 if (node.nodeName == 'BR') { |
|
114 if (start) { |
|
115 rng.setStartBefore(node); |
|
116 } else { |
|
117 rng.setEndBefore(node); |
|
118 } |
|
119 |
|
120 return; |
|
121 } |
|
122 } while ((node = (start ? walker.next() : walker.prev()))); |
|
123 } |
|
124 |
|
125 // Move selection to startCell |
|
126 if (startCell) { |
|
127 if (tableGrid) { |
|
128 editor.getBody().style.webkitUserSelect = ''; |
|
129 } |
|
130 |
|
131 // Try to expand text selection as much as we can only Gecko supports cell selection |
|
132 selectedCells = dom.select('td.mce-item-selected,th.mce-item-selected'); |
|
133 if (selectedCells.length > 0) { |
|
134 rng = dom.createRng(); |
|
135 node = selectedCells[0]; |
|
136 rng.setStartBefore(node); |
|
137 rng.setEndAfter(node); |
|
138 |
|
139 setPoint(node, 1); |
|
140 walker = new TreeWalker(node, dom.getParent(selectedCells[0], 'table')); |
|
141 |
|
142 do { |
|
143 if (node.nodeName == 'TD' || node.nodeName == 'TH') { |
|
144 if (!dom.hasClass(node, 'mce-item-selected')) { |
|
145 break; |
|
146 } |
|
147 |
|
148 lastNode = node; |
|
149 } |
|
150 } while ((node = walker.next())); |
|
151 |
|
152 setPoint(lastNode); |
|
153 |
|
154 sel.setRng(rng); |
|
155 } |
|
156 |
|
157 editor.nodeChanged(); |
|
158 startCell = tableGrid = startTable = null; |
|
159 } |
|
160 }); |
|
161 |
|
162 editor.on('KeyUp Drop SetContent', function(e) { |
|
163 clear(e.type == 'setcontent'); |
|
164 startCell = tableGrid = startTable = null; |
|
165 resizing = false; |
|
166 }); |
|
167 |
|
168 editor.on('ObjectResizeStart ObjectResized', function(e) { |
|
169 resizing = e.type != 'objectresized'; |
|
170 }); |
|
171 |
|
172 return { |
|
173 clear: clear |
|
174 }; |
|
175 }; |
|
176 }); |