/**
* InsertLi.js
*
* Released under LGPL License.
* Copyright (c) 1999-2017 Ephox Corp. All rights reserved
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
define(
'tinymce.core.newline.InsertLi',
[
'tinymce.core.dom.NodeType',
'tinymce.core.newline.NewLineUtils'
],
function (NodeType, NewLineUtils) {
var hasFirstChild = function (elm, name) {
return elm.firstChild && elm.firstChild.nodeName === name;
};
var hasParent = function (elm, parentName) {
return elm && elm.parentNode && elm.parentNode.nodeName === parentName;
};
var isListBlock = function (elm) {
return elm && /^(OL|UL|LI)$/.test(elm.nodeName);
};
var isNestedList = function (elm) {
return isListBlock(elm) && isListBlock(elm.parentNode);
};
var getContainerBlock = function (containerBlock) {
var containerBlockParent = containerBlock.parentNode;
if (/^(LI|DT|DD)$/.test(containerBlockParent.nodeName)) {
return containerBlockParent;
}
return containerBlock;
};
var isFirstOrLastLi = function (containerBlock, parentBlock, first) {
var node = containerBlock[first ? 'firstChild' : 'lastChild'];
// Find first/last element since there might be whitespace there
while (node) {
if (NodeType.isElement(node)) {
break;
}
node = node[first ? 'nextSibling' : 'previousSibling'];
}
return node === parentBlock;
};
// Inserts a block or br before/after or in the middle of a split list of the LI is empty
var insert = function (editor, createNewBlock, containerBlock, parentBlock, newBlockName) {
var dom = editor.dom;
var rng = editor.selection.getRng();
if (containerBlock === editor.getBody()) {
return;
}
if (isNestedList(containerBlock)) {
newBlockName = 'LI';
}
var newBlock = newBlockName ? createNewBlock(newBlockName) : dom.create('BR');
if (isFirstOrLastLi(containerBlock, parentBlock, true) && isFirstOrLastLi(containerBlock, parentBlock, false)) {
if (hasParent(containerBlock, 'LI')) {
// Nested list is inside a LI
dom.insertAfter(newBlock, getContainerBlock(containerBlock));
} else {
// Is first and last list item then replace the OL/UL with a text block
dom.replace(newBlock, containerBlock);
}
} else if (isFirstOrLastLi(containerBlock, parentBlock, true)) {
if (hasParent(containerBlock, 'LI')) {
// List nested in an LI then move the list to a new sibling LI
dom.insertAfter(newBlock, getContainerBlock(containerBlock));
newBlock.appendChild(dom.doc.createTextNode(' ')); // Needed for IE so the caret can be placed
newBlock.appendChild(containerBlock);
} else {
// First LI in list then remove LI and add text block before list
containerBlock.parentNode.insertBefore(newBlock, containerBlock);
}
} else if (isFirstOrLastLi(containerBlock, parentBlock, false)) {
// Last LI in list then remove LI and add text block after list
dom.insertAfter(newBlock, getContainerBlock(containerBlock));
} else {
// Middle LI in list the split the list and insert a text block in the middle
// Extract after fragment and insert it after the current block
containerBlock = getContainerBlock(containerBlock);
var tmpRng = rng.cloneRange();
tmpRng.setStartAfter(parentBlock);
tmpRng.setEndAfter(containerBlock);
var fragment = tmpRng.extractContents();
if (newBlockName === 'LI' && hasFirstChild(fragment, 'LI')) {
newBlock = fragment.firstChild;
dom.insertAfter(fragment, containerBlock);
} else {
dom.insertAfter(fragment, containerBlock);
dom.insertAfter(newBlock, containerBlock);
}
}
dom.remove(parentBlock);
NewLineUtils.moveToCaretPosition(editor, newBlock);
};
return {
insert: insert
};
}
);
|