Skip to content

Commit

Permalink
ww: enhance hr control resolved #425, resolved #426
Browse files Browse the repository at this point in the history
  • Loading branch information
shiren authored and seonim-ryu committed Jan 6, 2020
1 parent 2fe18ba commit 2915b56
Show file tree
Hide file tree
Showing 9 changed files with 300 additions and 138 deletions.
23 changes: 7 additions & 16 deletions apps/editor/src/js/domUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,6 @@ var isElemNode = function(node) {
return node && node.nodeType === Node.ELEMENT_NODE;
};

/**
* getChildNodeAt
* Get child node in given parent and index
* @param {HTMLElement} elem parent element
* @param {number} index node index
* @return {Node} child
*/
var getChildNodeAt = function(elem, index) {
if (elem.childNodes.length && index >= 0) {
return elem.childNodes[index];
}
};

/**
* getNodeName
* Get node name of node
Expand Down Expand Up @@ -117,7 +104,7 @@ var getChildNodeByOffset = function(node, index) {

if (isTextNode(node)) {
currentNode = node;
} else {
} else if (node.childNodes.length && index >= 0) {
currentNode = node.childNodes[index];
}

Expand Down Expand Up @@ -249,8 +236,11 @@ var getNextTopBlockNode = function(node) {
return getNodeWithDirectionUnderParent('next', node, 'BODY');
};

var getTopBlockNode = function(node) {
return getParentUntil(node, 'BODY');
};

module.exports = {
getChildNodeAt: getChildNodeAt,
getNodeName: getNodeName,
isTextNode: isTextNode,
isElemNode: isElemNode,
Expand All @@ -261,5 +251,6 @@ module.exports = {
getChildNodeByOffset: getChildNodeByOffset,
getPrevTopBlockNode: getPrevTopBlockNode,
getNextTopBlockNode: getNextTopBlockNode,
getParentUntil: getParentUntil
getParentUntil: getParentUntil,
getTopBlockNode: getTopBlockNode
};
102 changes: 76 additions & 26 deletions apps/editor/src/js/wwHrManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,16 @@ WwHrManager.prototype._initEvent = function() {
WwHrManager.prototype._initKeyHandler = function() {
var self = this;

this.wwe.addKeyEventHandler('ENTER', function(event, range) {
if (self._isInHr(range) || self._isNearHr(range)) {
return self._removeHrIfNeed(range, event);
}
this.wwe.addKeyEventHandler(function(ev, range, keyMap) {
return self._onTypedInHr(range, keyMap);
});

this.wwe.addKeyEventHandler('ENTER', function(ev, range) {
return self._removeHrOnEnter(range, ev);
});

this.wwe.addKeyEventHandler('BACK_SPACE', function(event, range) {
return self._removeHrIfNeed(range, event);
this.wwe.addKeyEventHandler('BACK_SPACE', function(ev, range) {
return self._removeHrOnBackspace(range, ev);
});
};

Expand All @@ -79,42 +81,90 @@ WwHrManager.prototype._isInHr = function(range) {
* @returns {boolean} result
*/
WwHrManager.prototype._isNearHr = function(range) {
var prevNode = domUtils.getChildNodeAt(range.startContainer, range.startOffset - 1);
var prevNode = domUtils.getChildNodeByOffset(range.startContainer, range.startOffset - 1);
return domUtils.getNodeName(prevNode) === 'HR';
};

WwHrManager.prototype._onTypedInHr = function(range, keyMap) {
//HR위에서 테스트 컨텐츠 입력을 시도한경우
if ((this._isInHr(range) || this._isNearHr(range))
&& (!keyMap.length || /^[A-Z0-9]$/.test(keyMap))
) {
this.wwe.breakToNewDefaultBlock(range, 'before');
return false;
}
};

/**
* _removeHrIfNeed
* Remove hr if need
* _removeHrOnEnter
* Remove hr if need on enter
* @param {Range} range range
* @param {Event} event event
* @param {Event} ev event
* @returns {boolean} return true if hr was removed
*/
WwHrManager.prototype._removeHrIfNeed = function(range, event) {
var hrSuspect, cursorTarget;
WwHrManager.prototype._removeHrOnEnter = function(range, ev) {
var hrSuspect, blockPosition;

if (!range.collapsed) {
return;
}

if (this._isInHr(range)) {
hrSuspect = domUtils.getChildNodeAt(range.startContainer, range.startOffset);
} else if (range.startOffset === 0) {
hrSuspect = range.startContainer.previousSibling || range.startContainer.parentNode.previousSibling;
hrSuspect = domUtils.getChildNodeByOffset(range.startContainer, range.startOffset);
} else if (this._isNearHr(range)) {
hrSuspect = domUtils.getChildNodeByOffset(range.startContainer, range.startOffset - 1);
blockPosition = 'before';
}

if (domUtils.getNodeName(hrSuspect) !== 'HR') {
hrSuspect = null;
}
return this._changeHrToNewDefaultBlock(hrSuspect, range, ev, blockPosition);
};

/**
* _removeHrOnBackspace
* Remove hr if need on backspace
* @param {Range} range range
* @param {Event} ev event
* @returns {boolean} return true if hr was removed
*/
WwHrManager.prototype._removeHrOnBackspace = function(range, ev) {
var hrSuspect, blockPosition;

if (!range.collapsed) {
return;
}

if (this._isInHr(range)) {
hrSuspect = domUtils.getChildNodeByOffset(range.startContainer, range.startOffset);
} else if (range.startOffset === 0) {
hrSuspect = domUtils.getPrevTopBlockNode(range.startContainer);
blockPosition = 'none';
} else if (this._isNearHr(range)) {
hrSuspect = domUtils.getChildNodeAt(range.startContainer, range.startOffset - 1);
hrSuspect = domUtils.getChildNodeByOffset(range.startContainer, range.startOffset - 1);
blockPosition = 'before';
}

if (hrSuspect) {
event.preventDefault();
return this._changeHrToNewDefaultBlock(hrSuspect, range, ev, blockPosition);
};

/**
* _changeHrToNewDefaultBlock
* Remove hr and add new default block then set range to it
* @param {Node} hrSuspect Node could be hr
* @param {Range} range range
* @param {Event} ev event
* @param {strong} newBlockPosition new default block add position
* @returns {boolean} return true if hr was removed
*/
WwHrManager.prototype._changeHrToNewDefaultBlock = function(hrSuspect, range, ev, newBlockPosition) {
if (hrSuspect && domUtils.getNodeName(hrSuspect) === 'HR') {
ev.preventDefault();

if (newBlockPosition !== 'none') {
this.wwe.breakToNewDefaultBlock(range, newBlockPosition);
}

cursorTarget = hrSuspect.nextSibling;
$(hrSuspect).remove();

range.setStartBefore(cursorTarget);
range.collapse(true);
this.wwe.getEditor().setSelection(range);

return false;
}
};
Expand Down
2 changes: 1 addition & 1 deletion apps/editor/src/js/wwTableManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ WwTableManager.prototype._isInTable = function(range) {
* @returns {boolean} result
*/
WwTableManager.prototype._isBeforeTable = function(range) {
return domUtils.getNodeName(domUtils.getChildNodeAt(range.startContainer, range.startOffset)) === 'TABLE';
return domUtils.getNodeName(domUtils.getChildNodeByOffset(range.startContainer, range.startOffset)) === 'TABLE';
};

/**
Expand Down
6 changes: 3 additions & 3 deletions apps/editor/src/js/wwTaskManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,14 @@ WwTaskManager.prototype._unformatTaskIfNeedOnBackspace = function(range) {
if (domUtils.isElemNode(startContainer)) {
//태스크리스트의 제일 첫 오프셋인경우(인풋박스 바로 위)
if (startOffset === 0) {
prevEl = domUtils.getChildNodeAt(startContainer, startOffset);
prevEl = domUtils.getChildNodeByOffset(startContainer, startOffset);
//inputbox 오른편 어딘가에서 지워지는경우
} else {
prevEl = domUtils.getChildNodeAt(startContainer, startOffset - 1);
prevEl = domUtils.getChildNodeByOffset(startContainer, startOffset - 1);

//지워질위치가 인풋스페이스 텍스트 영역으로 의심되는경우 그다음 엘리먼드로 prevEl을 지정해준다.(그다음이 input이면 지워지도록)
if (domUtils.isTextNode(prevEl) && prevEl.nodeValue.length === 1 && FIND_TASK_SPACES_RX.test(prevEl.nodeValue)) {
prevEl = domUtils.getChildNodeAt(startContainer, startOffset - 2);
prevEl = domUtils.getChildNodeByOffset(startContainer, startOffset - 2);
}
}

Expand Down
30 changes: 17 additions & 13 deletions apps/editor/src/js/wysiwygCommands/hr.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

'use strict';

var CommandManager = require('../commandManager');
var CommandManager = require('../commandManager'),
domUtils = require('../domUtils');

/**
* HR
Expand All @@ -22,29 +23,32 @@ var HR = CommandManager.command('wysiwyg', /** @lends HR */{
* @param {WysiwygEditor} wwe WYsiwygEditor instance
*/
exec: function(wwe) {
var sq = wwe.getEditor();
var sq = wwe.getEditor(),
range = sq.getSelection(),
nextBlockNode;

if (!sq.getSelection().collapsed || sq.hasFormat('TABLE')) {
if (!range.collapsed || sq.hasFormat('TABLE')) {
sq.focus();
return;
}

sq.modifyBlocks(function(frag) {
/*
var block = sq.createElement('DIV');
var newFrag = sq._doc.createDocumentFragment();
nextBlockNode = domUtils.getNextTopBlockNode(domUtils.getChildNodeByOffset(range.startContainer, range.startOffset));

newFrag.appendChild(frag);
newFrag.appendChild(block);
if (!nextBlockNode) {
nextBlockNode = sq.createDefaultBlock();
wwe.get$Body().append(nextBlockNode);
}

block.appendChild(sq.createElement('BR'));
block.appendChild(sq.createElement('HR'));
*/
sq.modifyBlocks(function(frag) {
frag.appendChild(sq.createElement('HR'));

return frag;
});

range.selectNodeContents(nextBlockNode);
range.collapse(true);

sq.setSelection(range);

sq.focus();
}
});
Expand Down
11 changes: 2 additions & 9 deletions apps/editor/src/js/wysiwygEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -390,13 +390,6 @@ WysiwygEditor.prototype._onKeyDown = function(keyboardEvent) {
WysiwygEditor.prototype._initDefaultKeyEventHandler = function() {
var self = this;

this.addKeyEventHandler('ENTER', function(ev, range) {
if (self._isInOrphanText(range)) {
self._wrapDefaultBlockTo(range);
return false;
}
});

this.addKeyEventHandler('BACK_SPACE', function(ev, range) {
if (!range.collapsed) {
self.postProcessForChange();
Expand Down Expand Up @@ -454,7 +447,7 @@ WysiwygEditor.prototype._wrapDefaultBlockTo = function(range) {
block = this.getEditor().createDefaultBlock([range.startContainer]);

//range for insert block
insertTargetNode = domUtils.getChildNodeAt(range.startContainer, range.startOffset);
insertTargetNode = domUtils.getChildNodeByOffset(range.startContainer, range.startOffset);
if (insertTargetNode) {
range.setStartBefore(insertTargetNode);
} else {
Expand Down Expand Up @@ -814,7 +807,7 @@ WysiwygEditor.prototype.hasFormatWithRx = function(rx) {
WysiwygEditor.prototype.breakToNewDefaultBlock = function(range, where) {
var div, pathToBody, appendBefore, currentNode;

currentNode = domUtils.getChildNodeAt(range.startContainer, range.startOffset) || range.startContainer;
currentNode = domUtils.getChildNodeByOffset(range.startContainer, range.startOffset) || domUtils.getChildNodeByOffset(range.startContainer, range.startOffset - 1);

pathToBody = $(currentNode).parentsUntil('body');

Expand Down
Loading

0 comments on commit 2915b56

Please sign in to comment.