: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
// Chrome(v31.0), FF(v25.0.1) use DIV for paragraph
return node && /^DIV|^P|^LI|^H[1-7]/.test(node.nodeName.toUpperCase());
var isHeading = function (node) {
return node && /^H[1-7]/.test(node.nodeName.toUpperCase());
var isPre = makePredByNodeName('PRE');
var isLi = makePredByNodeName('LI');
var isPurePara = function (node) {
return isPara(node) && !isLi(node);
var isTable = makePredByNodeName('TABLE');
var isInline = function (node) {
return !isBodyContainer(node) &&
var isList = function (node) {
return node && /^UL|^OL/.test(node.nodeName.toUpperCase());
var isHr = makePredByNodeName('HR');
var isCell = function (node) {
return node && /^TD|^TH/.test(node.nodeName.toUpperCase());
var isBlockquote = makePredByNodeName('BLOCKQUOTE');
var isBodyContainer = function (node) {
return isCell(node) || isBlockquote(node) || isEditable(node);
var isAnchor = makePredByNodeName('A');
var isParaInline = function (node) {
return isInline(node) && !!ancestor(node, isPara);
var isBodyInline = function (node) {
return isInline(node) && !ancestor(node, isPara);
var isBody = makePredByNodeName('BODY');
* returns whether nodeB is closest sibling of nodeA
var isClosestSibling = function (nodeA, nodeB) {
return nodeA.nextSibling === nodeB ||
nodeA.previousSibling === nodeB;
* returns array of closest siblings with node
* @param {function} [pred] - predicate function
var withClosestSiblings = function (node, pred) {
if (node.previousSibling && pred(node.previousSibling)) {
siblings.push(node.previousSibling);
if (node.nextSibling && pred(node.nextSibling)) {
siblings.push(node.nextSibling);
* blank HTML for cursor position
* - [workaround] old IE only works with
* - [workaround] IE11 and other browser works with bogus br
var blankHTML = agent.isMSIE && agent.browserVersion < 11 ? ' ' : '<br>';
* returns #text's text size or element's childNodes size
var nodeLength = function (node) {
return node.nodeValue.length;
return node.childNodes.length;
* returns whether node is empty or not.
var isEmpty = function (node) {
var len = nodeLength(node);
} else if (!isText(node) && len === 1 && node.innerHTML === blankHTML) {
// ex) <p><br></p>, <span><br></span>
} else if (list.all(node.childNodes, isText) && node.innerHTML === '') {
// ex) <p></p>, <span></span>
* padding blankHTML if node is empty (for cursor position)
var paddingBlankHTML = function (node) {
if (!isVoid(node) && !nodeLength(node)) {
node.innerHTML = blankHTML;
* find nearest ancestor predicate hit
* @param {Function} pred - predicate function
var ancestor = function (node, pred) {
if (pred(node)) { return node; }
if (isEditable(node)) { break; }
* find nearest ancestor only single child blood line and predicate hit
* @param {Function} pred - predicate function
var singleChildAncestor = function (node, pred) {
if (nodeLength(node) !== 1) { break; }
if (pred(node)) { return node; }
if (isEditable(node)) { break; }
* returns new array of ancestor nodes (until predicate hit).
* @param {Function} [optional] pred - predicate function
var listAncestor = function (node, pred) {
pred = pred || func.fail;
ancestor(node, function (el) {
* find farthest ancestor predicate hit
var lastAncestor = function (node, pred) {
var ancestors = listAncestor(node);
return list.last(ancestors.filter(pred));
* returns common ancestor node between two nodes.
var commonAncestor = function (nodeA, nodeB) {
var ancestors = listAncestor(nodeA);
for (var n = nodeB; n; n = n.parentNode) {
if ($.inArray(n, ancestors) > -1) { return n; }
return null; // difference document area
* listing all previous siblings (until predicate hit).
* @param {Function} [optional] pred - predicate function
var listPrev = function (node, pred) {
pred = pred || func.fail;
if (pred(node)) { break; }
node = node.previousSibling;
* listing next siblings (until predicate hit).
* @param {Function} [pred] - predicate function
var listNext = function (node, pred) {
pred = pred || func.fail;
if (pred(node)) { break; }
* listing descendant nodes
* @param {Function} [pred] - predicate function
var listDescendant = function (node, pred) {
// start DFS(depth first search) with node
(function fnWalk(current) {
if (node !== current && pred(current)) {
descendents.push(current);
for (var idx = 0, len = current.childNodes.length; idx < len; idx++) {
fnWalk(current.childNodes[idx]);
* wrap node with new tag.
* @param {Node} tagName of wrapper
* @return {Node} - wrapper
var wrap = function (node, wrapperName) {
var parent = node.parentNode;
var wrapper = $('<' + wrapperName + '>')[0];
parent.insertBefore(wrapper, node);
wrapper.appendChild(node);
* insert node after preceding
* @param {Node} preceding - predicate function
var insertAfter = function (node, preceding) {
var next = preceding.nextSibling, parent = preceding.parentNode;
parent.insertBefore(node, next);
parent.appendChild(node);
* @param {Collection} aChild
var appendChildNodes = function (node, aChild) {
$.each(aChild, function (idx, child) {
* returns whether boundaryPoint is left edge or not.
* @param {BoundaryPoint} point
var isLeftEdgePoint = function (point) {
return point.offset === 0;
* returns whether boundaryPoint is right edge or not.
* @param {BoundaryPoint} point
var isRightEdgePoint = function (point) {
return point.offset === nodeLength(point.node);
* returns whether boundaryPoint is edge or not.
* @param {BoundaryPoint} point
var isEdgePoint = function (point) {
return isLeftEdgePoint(point) || isRightEdgePoint(point);
* returns wheter node is left edge of ancestor or not.
var isLeftEdgeOf = function (node, ancestor) {
while (node && node !== ancestor) {
if (position(node) !== 0) {
* returns whether node is right edge of ancestor or not.
var isRightEdgeOf = function (node, ancestor) {
while (node && node !== ancestor) {
if (position(node) !== nodeLength(node.parentNode) - 1) {
* returns whether point is left edge of ancestor or not.
* @param {BoundaryPoint} point
var isLeftEdgePointOf = function (point, ancestor) {
return isLeftEdgePoint(point) && isLeftEdgeOf(point.node, ancestor);
* returns whether point is right edge of ancestor or not.
* @param {BoundaryPoint} point
var isRightEdgePointOf = function (point, ancestor) {
return isRightEdgePoint(point) && isRightEdgeOf(point.node, ancestor);
* returns offset from parent.
var position = function (node) {
while ((node = node.previousSibling)) {
var hasChildren = function (node) {
return !!(node && node.childNodes && node.childNodes.length);
* returns previous boundaryPoint
* @param {BoundaryPoint} point
* @param {Boolean} isSkipInnerOffset
* @return {BoundaryPoint}
var prevPoint = function (point, isSkipInnerOffset) {
if (point.offset === 0) {
if (isEditable(point.node)) {
node = point.node.parentNode;
offset = position(point.node);
} else if (hasChildren(point.node)) {
node = point.node.childNodes[point.offset - 1];
offset = nodeLength(node);
offset = isSkipInnerOffset ? 0 : point.offset - 1;
* returns next boundaryPoint
* @param {BoundaryPoint} point
* @param {Boolean} isSkipInnerOffset
* @return {BoundaryPoint}
var nextPoint = function (point, isSkipInnerOffset) {
if (nodeLength(point.node) === point.offset) {
if (isEditable(point.node)) {
node = point.node.parentNode;
offset = position(point.node) + 1;
} else if (hasChildren(point.node)) {
node = point.node.childNodes[point.offset];
offset = isSkipInnerOffset ? nodeLength(point.node) : point.offset + 1;
* returns whether pointA and pointB is same or not.
* @param {BoundaryPoint} pointA
* @param {BoundaryPoint} pointB
var isSamePoint = function (pointA, pointB) {
return pointA.node === pointB.node && pointA.offset === pointB.offset;