]> scripts.mit.edu Git - autoinstallsdev/wordpress.git/blobdiff - wp-includes/js/tinymce/plugins/lists/plugin.js
Wordpress 4.6
[autoinstallsdev/wordpress.git] / wp-includes / js / tinymce / plugins / lists / plugin.js
index a13c8ec54b31113837e78509048ec031d96512a3..4a778ff05b98ba2a415973ca23ba47bf11957ada 100644 (file)
@@ -1,8 +1,8 @@
 /**
  * plugin.js
  *
- * Copyright, Moxiecode Systems AB
  * Released under LGPL License.
+ * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
  *
  * License: http://www.tinymce.com/license
  * Contributing: http://www.tinymce.com/contributing
 tinymce.PluginManager.add('lists', function(editor) {
        var self = this;
 
+       function isChildOfBody(elm) {
+               return editor.$.contains(editor.getBody(), elm);
+       }
+
+       function isBr(node) {
+               return node && node.nodeName == 'BR';
+       }
+
        function isListNode(node) {
-               return node && (/^(OL|UL|DL)$/).test(node.nodeName);
+               return node && (/^(OL|UL|DL)$/).test(node.nodeName) && isChildOfBody(node);
        }
 
        function isFirstChild(node) {
@@ -30,9 +38,23 @@ tinymce.PluginManager.add('lists', function(editor) {
                return node && !!editor.schema.getTextBlockElements()[node.nodeName];
        }
 
+       function isEditorBody(elm) {
+               return elm === editor.getBody();
+       }
+
        editor.on('init', function() {
                var dom = editor.dom, selection = editor.selection;
 
+               function isEmpty(elm, keepBookmarks) {
+                       var empty = dom.isEmpty(elm);
+
+                       if (keepBookmarks && dom.select('span[data-mce-type=bookmark]').length > 0) {
+                               return false;
+                       }
+
+                       return empty;
+               }
+
                /**
                 * Returns a range bookmark. This will convert indexed bookmarks into temporary span elements with
                 * index 0 so that they can be restored properly after the DOM has been modified. Text bookmarks will not have spans
@@ -237,22 +259,28 @@ tinymce.PluginManager.add('lists', function(editor) {
 
                        dom.insertAfter(newBlock, ul);
 
-                       if (dom.isEmpty(li.parentNode)) {
+                       if (isEmpty(li.parentNode)) {
                                removeAndKeepBookmarks(li.parentNode);
                        }
 
                        dom.remove(li);
 
-                       if (dom.isEmpty(ul)) {
+                       if (isEmpty(ul)) {
                                dom.remove(ul);
                        }
                }
 
+               var shouldMerge = function (listBlock, sibling) {
+                       var targetStyle = editor.dom.getStyle(listBlock, 'list-style-type', true);
+                       var style = editor.dom.getStyle(sibling, 'list-style-type', true);
+                       return targetStyle === style;
+               };
+
                function mergeWithAdjacentLists(listBlock) {
                        var sibling, node;
 
                        sibling = listBlock.nextSibling;
-                       if (sibling && isListNode(sibling) && sibling.nodeName == listBlock.nodeName) {
+                       if (sibling && isListNode(sibling) && sibling.nodeName == listBlock.nodeName && shouldMerge(listBlock, sibling)) {
                                while ((node = sibling.firstChild)) {
                                        listBlock.appendChild(node);
                                }
@@ -261,7 +289,7 @@ tinymce.PluginManager.add('lists', function(editor) {
                        }
 
                        sibling = listBlock.previousSibling;
-                       if (sibling && isListNode(sibling) && sibling.nodeName == listBlock.nodeName) {
+                       if (sibling && isListNode(sibling) && sibling.nodeName == listBlock.nodeName && shouldMerge(listBlock, sibling)) {
                                while ((node = sibling.firstChild)) {
                                        listBlock.insertBefore(node, listBlock.firstChild);
                                }
@@ -283,7 +311,7 @@ tinymce.PluginManager.add('lists', function(editor) {
                                        if (sibling && sibling.nodeName == 'LI') {
                                                sibling.appendChild(ul);
 
-                                               if (dom.isEmpty(parentNode)) {
+                                               if (isEmpty(parentNode)) {
                                                        dom.remove(parentNode);
                                                }
                                        }
@@ -303,11 +331,15 @@ tinymce.PluginManager.add('lists', function(editor) {
                        var ul = li.parentNode, ulParent = ul.parentNode, newBlock;
 
                        function removeEmptyLi(li) {
-                               if (dom.isEmpty(li)) {
+                               if (isEmpty(li)) {
                                        dom.remove(li);
                                }
                        }
 
+                       if (isEditorBody(ul)) {
+                               return true;
+                       }
+
                        if (li.nodeName == 'DD') {
                                dom.rename(li, 'DT');
                                return true;
@@ -350,27 +382,25 @@ tinymce.PluginManager.add('lists', function(editor) {
                                }
 
                                return true;
-                       } else {
-                               if (ulParent.nodeName == 'LI') {
-                                       ul = ulParent;
-                                       newBlock = createNewTextBlock(li, 'LI');
-                               } else if (isListNode(ulParent)) {
-                                       newBlock = createNewTextBlock(li, 'LI');
-                               } else {
-                                       newBlock = createNewTextBlock(li);
-                               }
-
-                               splitList(ul, li, newBlock);
-                               normalizeList(ul.parentNode);
+                       }
 
-                               return true;
+                       if (ulParent.nodeName == 'LI') {
+                               ul = ulParent;
+                               newBlock = createNewTextBlock(li, 'LI');
+                       } else if (isListNode(ulParent)) {
+                               newBlock = createNewTextBlock(li, 'LI');
+                       } else {
+                               newBlock = createNewTextBlock(li);
                        }
 
-                       return false;
+                       splitList(ul, li, newBlock);
+                       normalizeList(ul.parentNode);
+
+                       return true;
                }
 
                function indent(li) {
-                       var sibling, newList;
+                       var sibling, newList, listStyle;
 
                        function mergeLists(from, to) {
                                var node;
@@ -409,13 +439,17 @@ tinymce.PluginManager.add('lists', function(editor) {
                                return true;
                        }
 
-                       if (sibling && sibling.nodeName == 'LI' && isListNode(li.lastChild)) {
+                       /*if (sibling && sibling.nodeName == 'LI' && isListNode(li.lastChild)) {
                                return false;
-                       }
+                       }*/
 
                        sibling = li.previousSibling;
                        if (sibling && sibling.nodeName == 'LI') {
                                newList = dom.create(li.parentNode.nodeName);
+                               listStyle = dom.getStyle(li.parentNode, 'listStyleType');
+                               if (listStyle) {
+                                       dom.setStyle(newList, 'listStyleType', listStyle);
+                               }
                                sibling.appendChild(newList);
                                newList.appendChild(li);
                                mergeLists(li.lastChild, newList);
@@ -481,8 +515,12 @@ tinymce.PluginManager.add('lists', function(editor) {
                        }
                }
 
-               function applyList(listName) {
-                       var rng = selection.getRng(true), bookmark = createBookmark(rng), listItemName = 'LI';
+               function applyList(listName, detail) {
+                       var rng = selection.getRng(true), bookmark, listItemName = 'LI';
+
+                       if (dom.getContentEditable(selection.getNode()) === "false") {
+                               return;
+                       }
 
                        listName = listName.toUpperCase();
 
@@ -538,8 +576,8 @@ tinymce.PluginManager.add('lists', function(editor) {
                                                return;
                                        }
 
-                                       if (dom.isBlock(node) || node.nodeName == 'BR') {
-                                               if (node.nodeName == 'BR') {
+                                       if (dom.isBlock(node) || isBr(node)) {
+                                               if (isBr(node)) {
                                                        dom.remove(node);
                                                }
 
@@ -567,11 +605,22 @@ tinymce.PluginManager.add('lists', function(editor) {
                                return textBlocks;
                        }
 
+                       bookmark = createBookmark(rng);
+
                        tinymce.each(getSelectedTextBlocks(), function(block) {
                                var listBlock, sibling;
 
+                               var hasCompatibleStyle = function (sib) {
+                                       var sibStyle = dom.getStyle(sib, 'list-style-type');
+                                       var detailStyle = detail ? detail['list-style-type'] : '';
+
+                                       detailStyle = detailStyle === null ? '' : detailStyle;
+
+                                       return sibStyle === detailStyle;
+                               };
+
                                sibling = block.previousSibling;
-                               if (sibling && isListNode(sibling) && sibling.nodeName == listName) {
+                               if (sibling && isListNode(sibling) && sibling.nodeName == listName && hasCompatibleStyle(sibling)) {
                                        listBlock = sibling;
                                        block = dom.rename(block, listItemName);
                                        sibling.appendChild(block);
@@ -582,19 +631,28 @@ tinymce.PluginManager.add('lists', function(editor) {
                                        block = dom.rename(block, listItemName);
                                }
 
+                               updateListStyle(listBlock, detail);
                                mergeWithAdjacentLists(listBlock);
                        });
 
                        moveToBookmark(bookmark);
                }
 
+               var updateListStyle = function (el, detail) {
+                       dom.setStyle(el, 'list-style-type', detail ? detail['list-style-type'] : null);
+               };
+
                function removeList() {
                        var bookmark = createBookmark(selection.getRng(true)), root = editor.getBody();
 
                        tinymce.each(getSelectedListItems(), function(li) {
                                var node, rootList;
 
-                               if (dom.isEmpty(li)) {
+                               if (isEditorBody(li.parentNode)) {
+                                       return;
+                               }
+
+                               if (isEmpty(li)) {
                                        outdent(li);
                                        return;
                                }
@@ -611,19 +669,25 @@ tinymce.PluginManager.add('lists', function(editor) {
                        moveToBookmark(bookmark);
                }
 
-               function toggleList(listName) {
+               function toggleList(listName, detail) {
                        var parentList = dom.getParent(selection.getStart(), 'OL,UL,DL');
 
+                       if (isEditorBody(parentList)) {
+                               return;
+                       }
+
                        if (parentList) {
                                if (parentList.nodeName == listName) {
                                        removeList(listName);
                                } else {
                                        var bookmark = createBookmark(selection.getRng(true));
+                                       updateListStyle(parentList, detail);
                                        mergeWithAdjacentLists(dom.rename(parentList, listName));
+
                                        moveToBookmark(bookmark);
                                }
                        } else {
-                               applyList(listName);
+                               applyList(listName, detail);
                        }
                }
 
@@ -635,6 +699,18 @@ tinymce.PluginManager.add('lists', function(editor) {
                        };
                }
 
+               function isBogusBr(node) {
+                       if (!isBr(node)) {
+                               return false;
+                       }
+
+                       if (dom.isBlock(node.nextSibling) && !isBr(node.previousSibling)) {
+                               return true;
+                       }
+
+                       return false;
+               }
+
                self.backspaceDelete = function(isForward) {
                        function findNextCaretContainer(rng, isForward) {
                                var node = rng.startContainer, offset = rng.startOffset;
@@ -645,9 +721,20 @@ tinymce.PluginManager.add('lists', function(editor) {
                                }
 
                                nonEmptyBlocks = editor.schema.getNonEmptyElements();
-                               walker = new tinymce.dom.TreeWalker(rng.startContainer);
+                               if (node.nodeType == 1) {
+                                       node = tinymce.dom.RangeUtils.getNode(node, offset);
+                               }
+
+                               walker = new tinymce.dom.TreeWalker(node, editor.getBody());
 
-                               while ((node = walker[isForward ? 'next' : 'prev']())) {
+                               // Delete at <li>|<br></li> then jump over the bogus br
+                               if (isForward) {
+                                       if (isBogusBr(node)) {
+                                               walker.next();
+                                       }
+                               }
+
+                               while ((node = walker[isForward ? 'next' : 'prev2']())) {
                                        if (node.nodeName == 'LI' && !node.hasChildNodes()) {
                                                return node;
                                        }
@@ -665,20 +752,30 @@ tinymce.PluginManager.add('lists', function(editor) {
                        function mergeLiElements(fromElm, toElm) {
                                var node, listNode, ul = fromElm.parentNode;
 
+                               if (!isChildOfBody(fromElm) || !isChildOfBody(toElm)) {
+                                       return;
+                               }
+
                                if (isListNode(toElm.lastChild)) {
                                        listNode = toElm.lastChild;
                                }
 
+                               if (ul == toElm.lastChild) {
+                                       if (isBr(ul.previousSibling)) {
+                                               dom.remove(ul.previousSibling);
+                                       }
+                               }
+
                                node = toElm.lastChild;
-                               if (node && node.nodeName == 'BR' && fromElm.hasChildNodes()) {
+                               if (node && isBr(node) && fromElm.hasChildNodes()) {
                                        dom.remove(node);
                                }
 
-                               if (dom.isEmpty(toElm)) {
+                               if (isEmpty(toElm, true)) {
                                        dom.$(toElm).empty();
                                }
 
-                               if (!dom.isEmpty(fromElm)) {
+                               if (!isEmpty(fromElm, true)) {
                                        while ((node = fromElm.firstChild)) {
                                                toElm.appendChild(node);
                                        }
@@ -690,17 +787,22 @@ tinymce.PluginManager.add('lists', function(editor) {
 
                                dom.remove(fromElm);
 
-                               if (dom.isEmpty(ul)) {
+                               if (isEmpty(ul) && !isEditorBody(ul)) {
                                        dom.remove(ul);
                                }
                        }
 
                        if (selection.isCollapsed()) {
-                               var li = dom.getParent(selection.getStart(), 'LI');
+                               var li = dom.getParent(selection.getStart(), 'LI'), ul, rng, otherLi;
 
                                if (li) {
-                                       var rng = selection.getRng(true);
-                                       var otherLi = dom.getParent(findNextCaretContainer(rng, isForward), 'LI');
+                                       ul = li.parentNode;
+                                       if (isEditorBody(ul) && dom.isEmpty(ul)) {
+                                               return true;
+                                       }
+
+                                       rng = selection.getRng(true);
+                                       otherLi = dom.getParent(findNextCaretContainer(rng, isForward), 'LI');
 
                                        if (otherLi && otherLi != li) {
                                                var bookmark = createBookmark(rng);
@@ -715,7 +817,7 @@ tinymce.PluginManager.add('lists', function(editor) {
 
                                                return true;
                                        } else if (!otherLi) {
-                                               if (!isForward && removeList(li.parentNode.nodeName)) {
+                                               if (!isForward && removeList(ul.nodeName)) {
                                                        return true;
                                                }
                                        }
@@ -743,16 +845,16 @@ tinymce.PluginManager.add('lists', function(editor) {
                        }
                });
 
-               editor.addCommand('InsertUnorderedList', function() {
-                       toggleList('UL');
+               editor.addCommand('InsertUnorderedList', function(ui, detail) {
+                       toggleList('UL', detail);
                });
 
-               editor.addCommand('InsertOrderedList', function() {
-                       toggleList('OL');
+               editor.addCommand('InsertOrderedList', function(ui, detail) {
+                       toggleList('OL', detail);
                });
 
-               editor.addCommand('InsertDefinitionList', function() {
-                       toggleList('DL');
+               editor.addCommand('InsertDefinitionList', function(ui, detail) {
+                       toggleList('DL', detail);
                });
 
                editor.addQueryStateHandler('InsertUnorderedList', queryListCommandState('UL'));