]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/debian/missing-sources/framework/Web/Javascripts/source/tinymce-405/plugins/table/classes/Quirks.js
baculum: Add missing-sources directory in debian metadata structure
[bacula/bacula] / gui / baculum / debian / missing-sources / framework / Web / Javascripts / source / tinymce-405 / plugins / table / classes / Quirks.js
1 /**
2  * Quirks.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 includes fixes for various browser quirks.
13  *
14  * @class tinymce.tableplugin.Quirks
15  * @private
16  */
17 define("tinymce/tableplugin/Quirks", [
18         "tinymce/util/VK",
19         "tinymce/Env",
20         "tinymce/util/Tools"
21 ], function(VK, Env, Tools) {
22         var each = Tools.each;
23
24         function getSpanVal(td, name) {
25                 return parseInt(td.getAttribute(name) || 1, 10);
26         }
27
28         return function(editor) {
29                 /**
30                  * Fixed caret movement around tables on WebKit.
31                  */
32                 function moveWebKitSelection() {
33                         function eventHandler(e) {
34                                 var key = e.keyCode;
35
36                                 function handle(upBool, sourceNode) {
37                                         var siblingDirection = upBool ? 'previousSibling' : 'nextSibling';
38                                         var currentRow = editor.dom.getParent(sourceNode, 'tr');
39                                         var siblingRow = currentRow[siblingDirection];
40
41                                         if (siblingRow) {
42                                                 moveCursorToRow(editor, sourceNode, siblingRow, upBool);
43                                                 e.preventDefault();
44                                                 return true;
45                                         } else {
46                                                 var tableNode = editor.dom.getParent(currentRow, 'table');
47                                                 var middleNode = currentRow.parentNode;
48                                                 var parentNodeName = middleNode.nodeName.toLowerCase();
49                                                 if (parentNodeName === 'tbody' || parentNodeName === (upBool ? 'tfoot' : 'thead')) {
50                                                         var targetParent = getTargetParent(upBool, tableNode, middleNode, 'tbody');
51                                                         if (targetParent !== null) {
52                                                                 return moveToRowInTarget(upBool, targetParent, sourceNode);
53                                                         }
54                                                 }
55                                                 return escapeTable(upBool, currentRow, siblingDirection, tableNode);
56                                         }
57                                 }
58
59                                 function getTargetParent(upBool, topNode, secondNode, nodeName) {
60                                         var tbodies = editor.dom.select('>' + nodeName, topNode);
61                                         var position = tbodies.indexOf(secondNode);
62                                         if (upBool && position === 0 || !upBool && position === tbodies.length - 1) {
63                                                 return getFirstHeadOrFoot(upBool, topNode);
64                                         } else if (position === -1) {
65                                                 var topOrBottom = secondNode.tagName.toLowerCase() === 'thead' ? 0 : tbodies.length - 1;
66                                                 return tbodies[topOrBottom];
67                                         } else {
68                                                 return tbodies[position + (upBool ? -1 : 1)];
69                                         }
70                                 }
71
72                                 function getFirstHeadOrFoot(upBool, parent) {
73                                         var tagName = upBool ? 'thead' : 'tfoot';
74                                         var headOrFoot = editor.dom.select('>' + tagName, parent);
75                                         return headOrFoot.length !== 0 ? headOrFoot[0] : null;
76                                 }
77
78                                 function moveToRowInTarget(upBool, targetParent, sourceNode) {
79                                         var targetRow = getChildForDirection(targetParent, upBool);
80
81                                         if (targetRow) {
82                                                 moveCursorToRow(editor, sourceNode, targetRow, upBool);
83                                         }
84
85                                         e.preventDefault();
86                                         return true;
87                                 }
88
89                                 function escapeTable(upBool, currentRow, siblingDirection, table) {
90                                         var tableSibling = table[siblingDirection];
91
92                                         if (tableSibling) {
93                                                 moveCursorToStartOfElement(tableSibling);
94                                                 return true;
95                                         } else {
96                                                 var parentCell = editor.dom.getParent(table, 'td,th');
97                                                 if (parentCell) {
98                                                         return handle(upBool, parentCell, e);
99                                                 } else {
100                                                         var backUpSibling = getChildForDirection(currentRow, !upBool);
101                                                         moveCursorToStartOfElement(backUpSibling);
102                                                         e.preventDefault();
103                                                         return false;
104                                                 }
105                                         }
106                                 }
107
108                                 function getChildForDirection(parent, up) {
109                                         var child =  parent && parent[up ? 'lastChild' : 'firstChild'];
110                                         // BR is not a valid table child to return in this case we return the table cell
111                                         return child && child.nodeName === 'BR' ? editor.dom.getParent(child, 'td,th') : child;
112                                 }
113
114                                 function moveCursorToStartOfElement(n) {
115                                         editor.selection.setCursorLocation(n, 0);
116                                 }
117
118                                 function isVerticalMovement() {
119                                         return key == VK.UP || key == VK.DOWN;
120                                 }
121
122                                 function isInTable(editor) {
123                                         var node = editor.selection.getNode();
124                                         var currentRow = editor.dom.getParent(node, 'tr');
125                                         return currentRow !== null;
126                                 }
127
128                                 function columnIndex(column) {
129                                         var colIndex = 0;
130                                         var c = column;
131                                         while (c.previousSibling) {
132                                                 c = c.previousSibling;
133                                                 colIndex = colIndex + getSpanVal(c, "colspan");
134                                         }
135                                         return colIndex;
136                                 }
137
138                                 function findColumn(rowElement, columnIndex) {
139                                         var c = 0, r = 0;
140
141                                         each(rowElement.children, function(cell, i) {
142                                                 c = c + getSpanVal(cell, "colspan");
143                                                 r = i;
144                                                 if (c > columnIndex) {
145                                                         return false;
146                                                 }
147                                         });
148                                         return r;
149                                 }
150
151                                 function moveCursorToRow(ed, node, row, upBool) {
152                                         var srcColumnIndex = columnIndex(editor.dom.getParent(node, 'td,th'));
153                                         var tgtColumnIndex = findColumn(row, srcColumnIndex);
154                                         var tgtNode = row.childNodes[tgtColumnIndex];
155                                         var rowCellTarget = getChildForDirection(tgtNode, upBool);
156                                         moveCursorToStartOfElement(rowCellTarget || tgtNode);
157                                 }
158
159                                 function shouldFixCaret(preBrowserNode) {
160                                         var newNode = editor.selection.getNode();
161                                         var newParent = editor.dom.getParent(newNode, 'td,th');
162                                         var oldParent = editor.dom.getParent(preBrowserNode, 'td,th');
163
164                                         return newParent && newParent !== oldParent && checkSameParentTable(newParent, oldParent);
165                                 }
166
167                                 function checkSameParentTable(nodeOne, NodeTwo) {
168                                         return editor.dom.getParent(nodeOne, 'TABLE') === editor.dom.getParent(NodeTwo, 'TABLE');
169                                 }
170
171                                 if (isVerticalMovement() && isInTable(editor)) {
172                                         var preBrowserNode = editor.selection.getNode();
173                                         setTimeout(function() {
174                                                 if (shouldFixCaret(preBrowserNode)) {
175                                                         handle(!e.shiftKey && key === VK.UP, preBrowserNode, e);
176                                                 }
177                                         }, 0);
178                                 }
179                         }
180
181                         editor.on('KeyDown', function(e) {
182                                 eventHandler(e);
183                         });
184                 }
185
186                 function fixBeforeTableCaretBug() {
187                         // Checks if the selection/caret is at the start of the specified block element
188                         function isAtStart(rng, par) {
189                                 var doc = par.ownerDocument, rng2 = doc.createRange(), elm;
190
191                                 rng2.setStartBefore(par);
192                                 rng2.setEnd(rng.endContainer, rng.endOffset);
193
194                                 elm = doc.createElement('body');
195                                 elm.appendChild(rng2.cloneContents());
196
197                                 // Check for text characters of other elements that should be treated as content
198                                 return elm.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi, '-').replace(/<[^>]+>/g, '').length === 0;
199                         }
200
201                         // Fixes an bug where it's impossible to place the caret before a table in Gecko
202                         // this fix solves it by detecting when the caret is at the beginning of such a table
203                         // and then manually moves the caret infront of the table
204                         editor.on('KeyDown', function(e) {
205                                 var rng, table, dom = editor.dom;
206
207                                 // On gecko it's not possible to place the caret before a table
208                                 if (e.keyCode == 37 || e.keyCode == 38) {
209                                         rng = editor.selection.getRng();
210                                         table = dom.getParent(rng.startContainer, 'table');
211
212                                         if (table && editor.getBody().firstChild == table) {
213                                                 if (isAtStart(rng, table)) {
214                                                         rng = dom.createRng();
215
216                                                         rng.setStartBefore(table);
217                                                         rng.setEndBefore(table);
218
219                                                         editor.selection.setRng(rng);
220
221                                                         e.preventDefault();
222                                                 }
223                                         }
224                                 }
225                         });
226                 }
227
228                 // Fixes an issue on Gecko where it's impossible to place the caret behind a table
229                 // This fix will force a paragraph element after the table but only when the forced_root_block setting is enabled
230                 function fixTableCaretPos() {
231                         editor.on('KeyDown SetContent VisualAid', function() {
232                                 var last;
233
234                                 // Skip empty text nodes from the end
235                                 for (last = editor.getBody().lastChild; last; last = last.previousSibling) {
236                                         if (last.nodeType == 3) {
237                                                 if (last.nodeValue.length > 0) {
238                                                         break;
239                                                 }
240                                         } else if (last.nodeType == 1 && !last.getAttribute('data-mce-bogus')) {
241                                                 break;
242                                         }
243                                 }
244
245                                 if (last && last.nodeName == 'TABLE') {
246                                         if (editor.settings.forced_root_block) {
247                                                 editor.dom.add(
248                                                         editor.getBody(),
249                                                         editor.settings.forced_root_block,
250                                                         null,
251                                                         Env.ie ? '&nbsp;' : '<br data-mce-bogus="1" />'
252                                                 );
253                                         } else {
254                                                 editor.dom.add(editor.getBody(), 'br', {'data-mce-bogus': '1'});
255                                         }
256                                 }
257                         });
258
259                         editor.on('PreProcess', function(o) {
260                                 var last = o.node.lastChild;
261
262                                 if (last && (last.nodeName == "BR" || (last.childNodes.length == 1 &&
263                                         (last.firstChild.nodeName == 'BR' || last.firstChild.nodeValue == '\u00a0'))) &&
264                                         last.previousSibling && last.previousSibling.nodeName == "TABLE") {
265                                         editor.dom.remove(last);
266                                 }
267                         });
268                 }
269
270                 // this nasty hack is here to work around some WebKit selection bugs.
271                 function fixTableCellSelection() {
272                         function tableCellSelected(ed, rng, n, currentCell) {
273                                 // The decision of when a table cell is selected is somewhat involved.  The fact that this code is
274                                 // required is actually a pointer to the root cause of this bug. A cell is selected when the start
275                                 // and end offsets are 0, the start container is a text, and the selection node is either a TR (most cases)
276                                 // or the parent of the table (in the case of the selection containing the last cell of a table).
277                                 var TEXT_NODE = 3, table = ed.dom.getParent(rng.startContainer, 'TABLE');
278                                 var tableParent, allOfCellSelected, tableCellSelection;
279
280                                 if (table) {
281                                         tableParent = table.parentNode;
282                                 }
283
284                                 allOfCellSelected =rng.startContainer.nodeType == TEXT_NODE &&
285                                         rng.startOffset === 0 &&
286                                         rng.endOffset === 0 &&
287                                         currentCell &&
288                                         (n.nodeName == "TR" || n == tableParent);
289
290                                 tableCellSelection = (n.nodeName == "TD" || n.nodeName == "TH") && !currentCell;
291
292                                 return allOfCellSelected || tableCellSelection;
293                         }
294
295                         function fixSelection() {
296                                 var rng = editor.selection.getRng();
297                                 var n = editor.selection.getNode();
298                                 var currentCell = editor.dom.getParent(rng.startContainer, 'TD,TH');
299
300                                 if (!tableCellSelected(editor, rng, n, currentCell)) {
301                                         return;
302                                 }
303
304                                 if (!currentCell) {
305                                         currentCell=n;
306                                 }
307
308                                 // Get the very last node inside the table cell
309                                 var end = currentCell.lastChild;
310                                 while (end.lastChild) {
311                                         end = end.lastChild;
312                                 }
313
314                                 // Select the entire table cell. Nothing outside of the table cell should be selected.
315                                 rng.setEnd(end, end.nodeValue.length);
316                                 editor.selection.setRng(rng);
317                         }
318
319                         editor.on('KeyDown', function() {
320                                 fixSelection();
321                         });
322
323                         editor.on('MouseDown', function(e) {
324                                 if (e.button != 2) {
325                                         fixSelection();
326                                 }
327                         });
328                 }
329
330                 if (Env.webkit) {
331                         moveWebKitSelection();
332                         fixTableCellSelection();
333                 }
334
335                 if (Env.gecko) {
336                         fixBeforeTableCaretBug();
337                         fixTableCaretPos();
338                 }
339         };
340 });