]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/debian/missing-sources/framework/Web/Javascripts/source/tinymce-405/plugins/lists/plugin.js
baculum: Add missing-sources directory in debian metadata structure
[bacula/bacula] / gui / baculum / debian / missing-sources / framework / Web / Javascripts / source / tinymce-405 / plugins / lists / plugin.js
1 /**
2  * plugin.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 /*global tinymce:true */
12
13 tinymce.PluginManager.add('lists', function(editor) {
14         var plugin = this;
15
16         editor.on('init', function() {
17                 var dom = editor.dom, selection = editor.selection;
18
19                 /**
20                  * Returns a range bookmark. This will convert indexed bookmarks into temporary span elements with
21                  * index 0 so that they can be restored properly after the DOM has been modified. Text bookmarks will not have spans
22                  * added to them since they can be restored after a dom operation.
23                  *
24                  * So this: <p><b>|</b><b>|</b></p>
25                  * becomes: <p><b><span data-mce-type="bookmark">|</span></b><b data-mce-type="bookmark">|</span></b></p>
26                  *
27                  * @param  {DOMRange} rng DOM Range to get bookmark on.
28                  * @return {Object} Bookmark object.
29                  */
30                 function createBookmark(rng) {
31                         var bookmark = {};
32
33                         function setupEndPoint(start) {
34                                 var offsetNode, container, offset;
35
36                                 container = rng[start ? 'startContainer' : 'endContainer'];
37                                 offset = rng[start ? 'startOffset' : 'endOffset'];
38
39                                 if (container.nodeType == 1) {
40                                         offsetNode = dom.create('span', {'data-mce-type': 'bookmark'});
41
42                                         if (container.hasChildNodes()) {
43                                                 offset = Math.min(offset, container.childNodes.length - 1);
44                                                 container.insertBefore(offsetNode, container.childNodes[offset]);
45                                         } else {
46                                                 container.appendChild(offsetNode);
47                                         }
48
49                                         container = offsetNode;
50                                         offset = 0;
51                                 }
52
53                                 bookmark[start ? 'startContainer' : 'endContainer'] = container;
54                                 bookmark[start ? 'startOffset' : 'endOffset'] = offset;
55                         }
56
57                         setupEndPoint(true);
58
59                         if (!rng.collapsed) {
60                                 setupEndPoint();
61                         }
62
63                         return bookmark;
64                 }
65
66                 /**
67                  * Moves the selection to the current bookmark and removes any selection container wrappers.
68                  *
69                  * @param {Object} bookmark Bookmark object to move selection to.
70                  */
71                 function moveToBookmark(bookmark) {
72                         function restoreEndPoint(start) {
73                                 var container, offset, node;
74
75                                 function nodeIndex(container) {
76                                         var node = container.parentNode.firstChild, idx = 0;
77
78                                         while (node) {
79                                                 if (node == container) {
80                                                         return idx;
81                                                 }
82
83                                                 // Skip data-mce-type=bookmark nodes
84                                                 if (node.nodeType != 1 || node.getAttribute('data-mce-type') != 'bookmark') {
85                                                         idx++;
86                                                 }
87
88                                                 node = node.nextSibling;
89                                         }
90
91                                         return -1;
92                                 }
93
94                                 container = node = bookmark[start ? 'startContainer' : 'endContainer'];
95                                 offset = bookmark[start ? 'startOffset' : 'endOffset'];
96
97                                 if (!container) {
98                                         return;
99                                 }
100
101                                 if (container.nodeType == 1) {
102                                         if (container.parentNode == editor.getBody()) {
103                                                 // TODO: Move the create block or br to some global class possible ForceBlocks.js
104                                                 var block, forcedRootBlock = editor.settings.forced_root_block;
105
106                                                 if (forcedRootBlock) {
107                                                         block = dom.create(forcedRootBlock);
108                                                         if (!tinymce.Env.ie || tinymce.Env.ie > 10) {
109                                                                 block.appendChild(dom.create('br', {'data-mce-bogus': 'true'}));
110                                                         }
111
112                                                         container.parentNode.insertBefore(block, container);
113                                                         container = block;
114                                                         offset = 0;
115                                                 } else {
116                                                         block = dom.create('br');
117                                                         container.parentNode.insertBefore(block, container);
118                                                         container = container.parentNode;
119                                                         offset = nodeIndex(block);
120                                                 }
121                                         } else {
122                                                 if (start) {
123                                                         offset = nodeIndex(container);
124                                                         container = container.parentNode;
125                                                 } else {
126                                                         offset = nodeIndex(container);
127                                                         container = container.parentNode;
128                                                 }
129                                         }
130
131                                         dom.remove(node);
132                                 }
133
134                                 bookmark[start ? 'startContainer' : 'endContainer'] = container;
135                                 bookmark[start ? 'startOffset' : 'endOffset'] = offset;
136                         }
137
138                         restoreEndPoint(true);
139                         restoreEndPoint();
140
141                         var rng = dom.createRng();
142
143                         rng.setStart(bookmark.startContainer, bookmark.startOffset);
144
145                         if (bookmark.endContainer) {
146                                 rng.setEnd(bookmark.endContainer, bookmark.endOffset);
147                         }
148
149                         selection.setRng(rng);
150                 }
151
152                 function isListNode(node) {
153                         return node && (/^(OL|UL)$/).test(node.nodeName);
154                 }
155
156                 function isFirstChild(node) {
157                         return node.parentNode.firstChild == node;
158                 }
159
160                 function isLastChild(node) {
161                         return node.parentNode.lastChild == node;
162                 }
163
164                 function isTextBlock(node) {
165                         return node && !!editor.schema.getTextBlockElements()[node.nodeName];
166                 }
167
168                 function createNewTextBlock(contentNode, blockName) {
169                         var node, textBlock;
170
171                         if (editor.settings.forced_root_block) {
172                                 blockName = blockName || editor.settings.forced_root_block;
173                         }
174
175                         if (blockName) {
176                                 textBlock = dom.create(blockName);
177                         } else {
178                                 textBlock = dom.createFragment();
179                         }
180
181                         if (contentNode) {
182                                 while ((node = contentNode.firstChild)) {
183                                         textBlock.appendChild(node);
184                                 }
185                         }
186
187                         if (!editor.settings.forced_root_block) {
188                                 textBlock.appendChild(dom.create('br'));
189                         }
190
191                         // BR is needed in empty blocks on non IE browsers
192                         if (!textBlock.hasChildNodes() && (!tinymce.Env.ie || tinymce.Env.ie > 10)) {
193                                 textBlock.innerHTML = '<br data-mce-bogus="1">';
194                         }
195
196                         return textBlock;
197                 }
198
199                 function getSelectedListItems() {
200                         return tinymce.grep(selection.getSelectedBlocks(), function(block) {
201                                 return block.nodeName == 'LI';
202                         });
203                 }
204
205                 function getSelectedTextBlocks() {
206                         return tinymce.grep(selection.getSelectedBlocks(), isTextBlock);
207                 }
208
209                 function splitList(ul, li, newBlock) {
210                         var tmpRng, fragment;
211
212                         var bookmarks = dom.select('span[data-mce-type="bookmark"]', ul);
213
214                         newBlock = newBlock || createNewTextBlock(li);
215                         tmpRng = dom.createRng();
216                         tmpRng.setStartAfter(li);
217                         tmpRng.setEndAfter(ul);
218                         fragment = tmpRng.extractContents();
219
220                         if (!dom.isEmpty(fragment)) {
221                                 dom.insertAfter(fragment, ul);
222                         }
223
224                         if (!dom.isEmpty(newBlock)) {
225                                 dom.insertAfter(newBlock, ul);
226                         }
227
228                         if (dom.isEmpty(li.parentNode)) {
229                                 tinymce.each(bookmarks, function(node) {
230                                         li.parentNode.parentNode.insertBefore(node, li.parentNode);
231                                 });
232
233                                 dom.remove(li.parentNode);
234                         }
235
236                         dom.remove(li);
237                 }
238
239                 function mergeWithAdjacentLists(listBlock) {
240                         var sibling, node;
241
242                         sibling = listBlock.nextSibling;
243                         if (sibling && isListNode(sibling) && sibling.nodeName == listBlock.nodeName) {
244                                 while ((node = sibling.firstChild)) {
245                                         listBlock.appendChild(node);
246                                 }
247
248                                 dom.remove(sibling);
249                         }
250
251                         sibling = listBlock.previousSibling;
252                         if (sibling && isListNode(sibling) && sibling.nodeName == listBlock.nodeName) {
253                                 while ((node = sibling.firstChild)) {
254                                         listBlock.insertBefore(node, listBlock.firstChild);
255                                 }
256
257                                 dom.remove(sibling);
258                         }
259                 }
260
261                 /**
262                  * Normalizes the all lists in the specified element.
263                  */
264                 function normalizeList(element) {
265                         tinymce.each(tinymce.grep(dom.select('ol,ul', element)), function(ul) {
266                                 var sibling, parentNode = ul.parentNode;
267
268                                 // Move UL/OL to previous LI if it's the only child of a LI
269                                 if (parentNode.nodeName == 'LI' && parentNode.firstChild == ul) {
270                                         sibling = parentNode.previousSibling;
271                                         if (sibling && sibling.nodeName == 'LI') {
272                                                 sibling.appendChild(ul);
273
274                                                 if (dom.isEmpty(parentNode)) {
275                                                         dom.remove(parentNode);
276                                                 }
277                                         }
278                                 }
279
280                                 // Append OL/UL to previous LI if it's in a parent OL/UL i.e. old HTML4
281                                 if (isListNode(parentNode)) {
282                                         sibling = parentNode.previousSibling;
283                                         if (sibling && sibling.nodeName == 'LI') {
284                                                 sibling.appendChild(ul);
285                                         }
286                                 }
287                         });
288                 }
289
290                 function indent() {
291                         var state, bookmark = createBookmark(selection.getRng(true));
292
293                         tinymce.each(getSelectedListItems(), function(li) {
294                                 var sibling, newList;
295
296                                 sibling = li.previousSibling;
297
298                                 if (sibling && sibling.nodeName == 'UL') {
299                                         sibling.appendChild(li);
300                                         return;
301                                 }
302
303                                 if (sibling && sibling.nodeName == 'LI' && isListNode(sibling.lastChild)) {
304                                         sibling.lastChild.appendChild(li);
305                                         return;
306                                 }
307
308                                 sibling = li.nextSibling;
309
310                                 if (sibling && sibling.nodeName == 'UL') {
311                                         sibling.insertBefore(li, sibling.firstChild);
312                                         return;
313                                 }
314
315                                 if (sibling && sibling.nodeName == 'LI' && isListNode(li.lastChild)) {
316                                         return;
317                                 }
318
319                                 sibling = li.previousSibling;
320                                 if (sibling && sibling.nodeName == 'LI') {
321                                         newList = dom.create(li.parentNode.nodeName);
322                                         sibling.appendChild(newList);
323                                         newList.appendChild(li);
324                                 }
325
326                                 /*sibling = li.nextSibling;
327                                 if (sibling && sibling.nodeName == 'LI') {
328                                         newList = dom.create(li.parentNode.nodeName);
329                                         sibling.insertBefore(newList, sibling.firstChild);
330                                         newList.appendChild(li);
331                                 }*/
332
333                                 state = true;
334                         });
335
336                         moveToBookmark(bookmark);
337
338                         return state;
339                 }
340
341                 function outdent() {
342                         var state, bookmark = createBookmark(selection.getRng(true));
343
344                         function removeEmptyLi(li) {
345                                 if (dom.isEmpty(li)) {
346                                         dom.remove(li);
347                                 }
348                         }
349
350                         tinymce.each(getSelectedListItems(), function(li) {
351                                 var ul = li.parentNode, ulParent = ul.parentNode, newBlock;
352
353                                 if (isFirstChild(li) && isLastChild(li)) {
354                                         if (ulParent.nodeName == "LI") {
355                                                 dom.insertAfter(li, ulParent);
356                                                 removeEmptyLi(ulParent);
357                                         } else if (isListNode(ulParent)) {
358                                                 dom.remove(ul, true);
359                                         } else {
360                                                 return;
361                                         }
362                                 } else if (isFirstChild(li)) {
363                                         if (ulParent.nodeName == "LI") {
364                                                 dom.insertAfter(li, ulParent);
365                                                 newBlock = dom.create("LI");
366                                                 newBlock.appendChild(ul);
367                                                 dom.insertAfter(newBlock, li);
368                                                 removeEmptyLi(ulParent);
369                                         } else if (isListNode(ulParent)) {
370                                                 ulParent.insertBefore(li, ul);
371                                         } else {
372                                                 return;
373                                         }
374                                 } else if (isLastChild(li)) {
375                                         if (ulParent.nodeName == "LI") {
376                                                 dom.insertAfter(li, ulParent);
377                                         } else if (isListNode(ulParent)) {
378                                                 dom.insertAfter(li, ul);
379                                         } else {
380                                                 return;
381                                         }
382                                 } else {
383                                         if (ulParent.nodeName == 'LI') {
384                                                 ul = ulParent;
385                                                 newBlock = createNewTextBlock(li, 'LI');
386                                         } else if (isListNode(ulParent)) {
387                                                 newBlock = createNewTextBlock(li, 'LI');
388                                         } else {
389                                                 return;
390                                         }
391
392                                         splitList(ul, li, newBlock);
393                                         normalizeList(ul.parentNode);
394                                 }
395
396                                 state = true;
397                         });
398
399                         moveToBookmark(bookmark);
400
401                         return state;
402                 }
403
404                 function applyList(listName) {
405                         var rng = selection.getRng(true), bookmark = createBookmark(rng), textBlocks = getSelectedTextBlocks();
406
407                         function convertNonBlockLines() {
408                                 function getEndPointNode(start) {
409                                         var container, offset, root = editor.getBody();
410
411                                         container = rng[start ? 'startContainer' : 'endContainer'];
412                                         offset = rng[start ? 'startOffset' : 'endOffset'];
413
414                                         // Resolve node index
415                                         if (container.nodeType == 1) {
416                                                 container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
417                                         }
418
419                                         while (container.parentNode != root) {
420                                                 if (isTextBlock(container)) {
421                                                         return container;
422                                                 }
423
424                                                 if (/^(TD|TH)$/.test(container.parentNode.nodeName)) {
425                                                         return container;
426                                                 }
427
428                                                 container = container.parentNode;
429                                         }
430
431                                         return container;
432                                 }
433
434                                 function getAllSiblings(node, isForward) {
435                                         var sibling, siblings = [];
436
437                                         if (!isTextBlock(node)) {
438                                                 // Walk to start/end of line
439                                                 while (node) {
440                                                         sibling = node[isForward ? 'previousSibling' : 'nextSibling'];
441                                                         if (dom.isBlock(sibling) || !sibling) {
442                                                                 break;
443                                                         }
444
445                                                         node = sibling;
446                                                 }
447
448                                                 while (node) {
449                                                         siblings.push(node);
450                                                         node = node[isForward ? 'nextSibling' : 'previousSibling'];
451                                                 }
452                                         }
453
454                                         return siblings;
455                                 }
456
457                                 var startNode = getEndPointNode(true);
458                                 var endNode = getEndPointNode();
459                                 var block, siblings;
460
461                                 siblings = getAllSiblings(startNode, true);
462
463                                 if (startNode != endNode) {
464                                         siblings = siblings.concat(getAllSiblings(endNode).reverse());
465                                 }
466
467                                 tinymce.each(siblings, function(node) {
468                                         if (dom.isBlock(node) && node.nodeName != 'BR') {
469                                                 return;
470                                         }
471
472                                         if (!block || node.nodeName == 'BR') {
473                                                 if (node.nodeName == 'BR') {
474                                                         if (!node.nextSibling || (dom.isBlock(node.nextSibling) && node.nextSibling.nodeName != "BR")) {
475                                                                 dom.remove(node);
476                                                                 return false;
477                                                         }
478                                                 }
479
480                                                 block = dom.create('p');
481                                                 textBlocks.push(block);
482                                                 node.parentNode.insertBefore(block, node);
483                                         }
484
485                                         if (node.nodeName != 'BR') {
486                                                 block.appendChild(node);
487                                         } else {
488                                                 dom.remove(node);
489                                         }
490
491                                         if (node == endNode) {
492                                                 return false;
493                                         }
494                                 });
495                         }
496
497                         convertNonBlockLines();
498
499                         tinymce.each(textBlocks, function(block) {
500                                 var listBlock, sibling;
501
502                                 sibling = block.previousSibling;
503                                 if (sibling && isListNode(sibling) && sibling.nodeName == listName) {
504                                         listBlock = sibling;
505                                         block = dom.rename(block, 'LI');
506                                         sibling.appendChild(block);
507                                 } else {
508                                         listBlock = dom.create(listName);
509                                         block.parentNode.insertBefore(listBlock, block);
510                                         listBlock.appendChild(block);
511                                         block = dom.rename(block, 'LI');
512                                 }
513
514                                 mergeWithAdjacentLists(listBlock);
515                         });
516
517                         moveToBookmark(bookmark);
518                 }
519
520                 function removeList() {
521                         var bookmark = createBookmark(selection.getRng(true));
522
523                         tinymce.each(getSelectedListItems(), function(li) {
524                                 var node, rootList;
525
526                                 for (node = li; node; node = node.parentNode) {
527                                         if (isListNode(node)) {
528                                                 rootList = node;
529                                         }
530                                 }
531
532                                 splitList(rootList, li);
533                         });
534
535                         moveToBookmark(bookmark);
536                 }
537
538                 function toggleList(listName) {
539                         var parentList = dom.getParent(selection.getStart(), 'OL,UL');
540
541                         if (parentList) {
542                                 if (parentList.nodeName == listName) {
543                                         removeList(listName);
544                                 } else {
545                                         var bookmark = createBookmark(selection.getRng(true));
546                                         mergeWithAdjacentLists(dom.rename(parentList, listName));
547                                         moveToBookmark(bookmark);
548                                 }
549                         } else {
550                                 applyList(listName);
551                         }
552                 }
553
554                 plugin.backspaceDelete = function(isForward) {
555                         function findNextCaretContainer(rng, isForward) {
556                                 var node = rng.startContainer, offset = rng.startOffset;
557
558                                 if (node.nodeType == 3 && (isForward ? offset < node.data.length : offset > 0)) {
559                                         return node;
560                                 }
561
562                                 var walker = new tinymce.dom.TreeWalker(rng.startContainer);
563                                 while ((node = walker[isForward ? 'next' : 'prev']())) {
564                                         if (node.nodeType == 3 && node.data.length > 0) {
565                                                 return node;
566                                         }
567                                 }
568                         }
569
570                         function mergeLiElements(fromElm, toElm) {
571                                 var node, listNode, ul = fromElm.parentNode;
572
573                                 if (isListNode(toElm.lastChild)) {
574                                         listNode = toElm.lastChild;
575                                 }
576
577                                 node = toElm.lastChild;
578                                 if (node && node.nodeName == 'BR' && fromElm.hasChildNodes()) {
579                                         dom.remove(node);
580                                 }
581
582                                 while ((node = fromElm.firstChild)) {
583                                         toElm.appendChild(node);
584                                 }
585
586                                 if (listNode) {
587                                         toElm.appendChild(listNode);
588                                 }
589
590                                 dom.remove(fromElm);
591
592                                 if (dom.isEmpty(ul)) {
593                                         dom.remove(ul);
594                                 }
595                         }
596
597                         if (selection.isCollapsed()) {
598                                 var li = dom.getParent(selection.getStart(), 'LI');
599
600                                 if (li) {
601                                         var rng = selection.getRng(true);
602                                         var otherLi = dom.getParent(findNextCaretContainer(rng, isForward), 'LI');
603
604                                         if (otherLi && otherLi != li) {
605                                                 var bookmark = createBookmark(rng);
606
607                                                 if (isForward) {
608                                                         mergeLiElements(otherLi, li);
609                                                 } else {
610                                                         mergeLiElements(li, otherLi);
611                                                 }
612
613                                                 moveToBookmark(bookmark);
614
615                                                 return true;
616                                         } else if (!otherLi) {
617                                                 if (!isForward && removeList(li.parentNode.nodeName)) {
618                                                         return true;
619                                                 }
620                                         }
621                                 }
622                         }
623                 };
624
625                 editor.addCommand('Indent', function() {
626                         if (!indent()) {
627                                 return true;
628                         }
629                 });
630
631                 editor.addCommand('Outdent', function() {
632                         if (!outdent()) {
633                                 return true;
634                         }
635                 });
636
637                 editor.addCommand('InsertUnorderedList', function() {
638                         toggleList('UL');
639                 });
640
641                 editor.addCommand('InsertOrderedList', function() {
642                         toggleList('OL');
643                 });
644         });
645
646         editor.on('keydown', function(e) {
647                 if (e.keyCode == tinymce.util.VK.BACKSPACE) {
648                         if (plugin.backspaceDelete()) {
649                                 e.preventDefault();
650                         }
651                 } else if (e.keyCode == tinymce.util.VK.DELETE) {
652                         if (plugin.backspaceDelete(true)) {
653                                 e.preventDefault();
654                         }
655                 }
656         });
657 });