mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 06:42:42 +01:00
Update client logic for inline comment "Save" and "Cancel" actions
Summary: Ref T13559. Substantially correct the client logic for "Save" and "Cancel" actions to handle unusual cases. Test Plan: Quoting behavior: - Quoted a comment. - Cancelled the quoted comment without modifying anything. - Reloaded page. - Before changes: quoted comment still exists. - After changes: quoted comment is deleted. - Looked at comment count in header, saw consistent behavior (before: weird behavior). Empty suggestion behavior: - Created a new comment on a suggestable file. - Clicked "Suggest Edit" to enable suggestions. - Without making any text or suggestion changes, clicked "Save". - Before changes: comment saves, but is empty. - After changes: comment deletes itself without undo. General behavior: - Created and saved an empty comment (deletes itself). - Created and saved a nonempty comment (saves as draft). - Created and saved an empty comment with an edit suggestion (saves). - Created and saved an empty comment with a suggestion to entirely delete lines -- that is, no suggestion text (saves). - Edited a comment, saved without changes (save). - Edited a comment, save deleting all text (saves -- note that this is intentionally without undo, since this is a lot of steps to do by accident). - Cancel editing an unchanged comment (cancels without undo). - Cancel editing a changed comment (cancels with undo). - Undo'd, got text back. - Cancel new comment with no text (deletes without undo). - Cancel new comment with text (deletes with undo). - Undo'd, got text back. - Saved a quoted comment with no changes (saves -- note that this is intentionally not a "delete", since just quoting someone seems fine if you click "Save" -- maybe you want to come back to it later). Maniphest Tasks: T13559 Differential Revision: https://secure.phabricator.com/D21654
This commit is contained in:
parent
6fd55d692f
commit
1308a5555f
4 changed files with 179 additions and 104 deletions
|
@ -13,7 +13,7 @@ return array(
|
||||||
'core.pkg.js' => '68f29322',
|
'core.pkg.js' => '68f29322',
|
||||||
'dark-console.pkg.js' => '187792c2',
|
'dark-console.pkg.js' => '187792c2',
|
||||||
'differential.pkg.css' => 'ffb69e3d',
|
'differential.pkg.css' => 'ffb69e3d',
|
||||||
'differential.pkg.js' => '59453886',
|
'differential.pkg.js' => '8deec4cd',
|
||||||
'diffusion.pkg.css' => '42c75c37',
|
'diffusion.pkg.css' => '42c75c37',
|
||||||
'diffusion.pkg.js' => '78c9885d',
|
'diffusion.pkg.js' => '78c9885d',
|
||||||
'maniphest.pkg.css' => '35995d6d',
|
'maniphest.pkg.css' => '35995d6d',
|
||||||
|
@ -385,8 +385,8 @@ return array(
|
||||||
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '0116d3e8',
|
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '0116d3e8',
|
||||||
'rsrc/js/application/diff/DiffChangeset.js' => 'd7d3ba75',
|
'rsrc/js/application/diff/DiffChangeset.js' => 'd7d3ba75',
|
||||||
'rsrc/js/application/diff/DiffChangesetList.js' => 'cc2c5de5',
|
'rsrc/js/application/diff/DiffChangesetList.js' => 'cc2c5de5',
|
||||||
'rsrc/js/application/diff/DiffInline.js' => '26664c24',
|
'rsrc/js/application/diff/DiffInline.js' => '9c775532',
|
||||||
'rsrc/js/application/diff/DiffInlineContentState.js' => '68e6339d',
|
'rsrc/js/application/diff/DiffInlineContentState.js' => 'aa51efb4',
|
||||||
'rsrc/js/application/diff/DiffPathView.js' => '8207abf9',
|
'rsrc/js/application/diff/DiffPathView.js' => '8207abf9',
|
||||||
'rsrc/js/application/diff/DiffTreeView.js' => '5d83623b',
|
'rsrc/js/application/diff/DiffTreeView.js' => '5d83623b',
|
||||||
'rsrc/js/application/differential/behavior-diff-radios.js' => '925fe8cd',
|
'rsrc/js/application/differential/behavior-diff-radios.js' => '925fe8cd',
|
||||||
|
@ -788,8 +788,8 @@ return array(
|
||||||
'phabricator-dashboard-css' => '5a205b9d',
|
'phabricator-dashboard-css' => '5a205b9d',
|
||||||
'phabricator-diff-changeset' => 'd7d3ba75',
|
'phabricator-diff-changeset' => 'd7d3ba75',
|
||||||
'phabricator-diff-changeset-list' => 'cc2c5de5',
|
'phabricator-diff-changeset-list' => 'cc2c5de5',
|
||||||
'phabricator-diff-inline' => '26664c24',
|
'phabricator-diff-inline' => '9c775532',
|
||||||
'phabricator-diff-inline-content-state' => '68e6339d',
|
'phabricator-diff-inline-content-state' => 'aa51efb4',
|
||||||
'phabricator-diff-path-view' => '8207abf9',
|
'phabricator-diff-path-view' => '8207abf9',
|
||||||
'phabricator-diff-tree-view' => '5d83623b',
|
'phabricator-diff-tree-view' => '5d83623b',
|
||||||
'phabricator-drag-and-drop-file-upload' => '4370900d',
|
'phabricator-drag-and-drop-file-upload' => '4370900d',
|
||||||
|
@ -1162,10 +1162,6 @@ return array(
|
||||||
'javelin-json',
|
'javelin-json',
|
||||||
'phabricator-prefab',
|
'phabricator-prefab',
|
||||||
),
|
),
|
||||||
'26664c24' => array(
|
|
||||||
'javelin-dom',
|
|
||||||
'phabricator-diff-inline-content-state',
|
|
||||||
),
|
|
||||||
'289bf236' => array(
|
'289bf236' => array(
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
'javelin-util',
|
'javelin-util',
|
||||||
|
@ -1549,9 +1545,6 @@ return array(
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
),
|
),
|
||||||
'68e6339d' => array(
|
|
||||||
'javelin-dom',
|
|
||||||
),
|
|
||||||
'6a1583a8' => array(
|
'6a1583a8' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-history',
|
'javelin-history',
|
||||||
|
@ -1823,6 +1816,10 @@ return array(
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
'javelin-workflow',
|
'javelin-workflow',
|
||||||
),
|
),
|
||||||
|
'9c775532' => array(
|
||||||
|
'javelin-dom',
|
||||||
|
'phabricator-diff-inline-content-state',
|
||||||
|
),
|
||||||
'9cec214e' => array(
|
'9cec214e' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-stratcom',
|
'javelin-stratcom',
|
||||||
|
@ -1913,6 +1910,9 @@ return array(
|
||||||
'javelin-typeahead-ondemand-source',
|
'javelin-typeahead-ondemand-source',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
),
|
),
|
||||||
|
'aa51efb4' => array(
|
||||||
|
'javelin-dom',
|
||||||
|
),
|
||||||
'aa6d2308' => array(
|
'aa6d2308' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
|
|
|
@ -172,7 +172,9 @@ abstract class PhabricatorInlineCommentController
|
||||||
$inline = $this->loadCommentByIDForEdit($this->getCommentID());
|
$inline = $this->loadCommentByIDForEdit($this->getCommentID());
|
||||||
|
|
||||||
if ($is_delete) {
|
if ($is_delete) {
|
||||||
$inline->setIsDeleted(1);
|
$inline
|
||||||
|
->setIsEditing(false)
|
||||||
|
->setIsDeleted(1);
|
||||||
} else {
|
} else {
|
||||||
$inline->setIsDeleted(0);
|
$inline->setIsDeleted(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,6 @@ JX.install('DiffInline', {
|
||||||
_undoRow: null,
|
_undoRow: null,
|
||||||
_undoType: null,
|
_undoType: null,
|
||||||
_undoState: null,
|
_undoState: null,
|
||||||
_preventUndo: false,
|
|
||||||
|
|
||||||
_draftRequest: null,
|
_draftRequest: null,
|
||||||
_skipFocus: false,
|
_skipFocus: false,
|
||||||
|
@ -161,14 +160,6 @@ JX.install('DiffInline', {
|
||||||
return this._endOffset;
|
return this._endOffset;
|
||||||
},
|
},
|
||||||
|
|
||||||
_setPreventUndo: function(prevent_undo) {
|
|
||||||
this._preventUndo = prevent_undo;
|
|
||||||
},
|
|
||||||
|
|
||||||
_getPreventUndo: function() {
|
|
||||||
return this._preventUndo;
|
|
||||||
},
|
|
||||||
|
|
||||||
setIsSelected: function(is_selected) {
|
setIsSelected: function(is_selected) {
|
||||||
this._isSelected = is_selected;
|
this._isSelected = is_selected;
|
||||||
|
|
||||||
|
@ -452,21 +443,12 @@ JX.install('DiffInline', {
|
||||||
this._undoText = null;
|
this._undoText = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var uri = this._getInlineURI();
|
this._applyEdit(content_state);
|
||||||
var handler = JX.bind(this, this._oneditresponse);
|
|
||||||
|
|
||||||
var data = this._newRequestData('edit', content_state);
|
|
||||||
|
|
||||||
this.setLoading(true);
|
|
||||||
|
|
||||||
new JX.Request(uri, handler)
|
|
||||||
.setData(data)
|
|
||||||
.send();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
delete: function(is_ref) {
|
delete: function(is_ref) {
|
||||||
var uri = this._getInlineURI();
|
var uri = this._getInlineURI();
|
||||||
var handler = JX.bind(this, this._ondeleteresponse);
|
var handler = JX.bind(this, this._ondeleteresponse, false);
|
||||||
|
|
||||||
// NOTE: This may be a direct delete (the user clicked on the inline
|
// NOTE: This may be a direct delete (the user clicked on the inline
|
||||||
// itself) or a "refdelete" (the user clicked somewhere else, like the
|
// itself) or a "refdelete" (the user clicked somewhere else, like the
|
||||||
|
@ -586,7 +568,6 @@ JX.install('DiffInline', {
|
||||||
this._readInlineState(response.inline);
|
this._readInlineState(response.inline);
|
||||||
this._drawEditRows(rows);
|
this._drawEditRows(rows);
|
||||||
|
|
||||||
this.setLoading(false);
|
|
||||||
this.setInvisible(true);
|
this.setInvisible(true);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -617,7 +598,8 @@ JX.install('DiffInline', {
|
||||||
return new JX.DiffInlineContentState().readWireFormat(map);
|
return new JX.DiffInlineContentState().readWireFormat(map);
|
||||||
},
|
},
|
||||||
|
|
||||||
_ondeleteresponse: function() {
|
_ondeleteresponse: function(prevent_undo) {
|
||||||
|
if (!prevent_undo) {
|
||||||
// If there's an existing "unedit" undo element, remove it.
|
// If there's an existing "unedit" undo element, remove it.
|
||||||
if (this._undoRow) {
|
if (this._undoRow) {
|
||||||
JX.DOM.remove(this._undoRow);
|
JX.DOM.remove(this._undoRow);
|
||||||
|
@ -634,7 +616,6 @@ JX.install('DiffInline', {
|
||||||
this._editRow = null;
|
this._editRow = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._getPreventUndo()) {
|
|
||||||
this._drawUndeleteRows(state);
|
this._drawUndeleteRows(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,7 +674,6 @@ JX.install('DiffInline', {
|
||||||
var anchor = cursor || this._row;
|
var anchor = cursor || this._row;
|
||||||
cursor = cursor || this._row.nextSibling;
|
cursor = cursor || this._row.nextSibling;
|
||||||
|
|
||||||
|
|
||||||
var result_row;
|
var result_row;
|
||||||
var next_row;
|
var next_row;
|
||||||
while (row) {
|
while (row) {
|
||||||
|
@ -837,8 +817,10 @@ JX.install('DiffInline', {
|
||||||
|
|
||||||
save: function() {
|
save: function() {
|
||||||
if (this._shouldDeleteOnSave()) {
|
if (this._shouldDeleteOnSave()) {
|
||||||
this._setPreventUndo(true);
|
JX.DOM.remove(this._editRow);
|
||||||
this._applyDelete();
|
this._editRow = null;
|
||||||
|
|
||||||
|
this._applyDelete(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -846,35 +828,56 @@ JX.install('DiffInline', {
|
||||||
},
|
},
|
||||||
|
|
||||||
_shouldDeleteOnSave: function() {
|
_shouldDeleteOnSave: function() {
|
||||||
var state = this._getActiveContentState();
|
var active = this._getActiveContentState();
|
||||||
|
var initial = this._getInitialContentState();
|
||||||
|
|
||||||
// TODO: This is greatly simplified because we don't track all the
|
// When a user clicks "Save", it counts as a "delete" if the content
|
||||||
// state we need yet.
|
// of the comment is functionally empty.
|
||||||
|
|
||||||
return !state.getText().length;
|
// This isn't a delete if there's any text. Even if the text is a
|
||||||
},
|
// quote (so the state is the same as the initial state), we preserve
|
||||||
|
// it when the user clicks "Save".
|
||||||
|
if (!active.isTextEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
_shouldDeleteOnCancel: function() {
|
// This isn't a delete if there's a suggestion and that suggestion is
|
||||||
var state = this._getActiveContentState();
|
// different from the initial state. (This means that an inline which
|
||||||
|
// purely suggests a block of code should be deleted is non-empty.)
|
||||||
|
if (active.getHasSuggestion()) {
|
||||||
|
if (!active.isSuggestionSimilar(initial)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: This is greatly simplified, too.
|
// Otherwise, this comment is functionally empty, so we can just treat
|
||||||
|
// a "Save" as a "delete".
|
||||||
return !state.getText().length;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
_shouldUndoOnCancel: function() {
|
_shouldUndoOnCancel: function() {
|
||||||
var new_state = this._getActiveContentState().getWireFormat();
|
var committed = this._getCommittedContentState();
|
||||||
var old_state = this._getCommittedContentState().getWireFormat();
|
var active = this._getActiveContentState();
|
||||||
|
var initial = this._getInitialContentState();
|
||||||
|
|
||||||
// TODO: This is also simplified.
|
// When a user clicks "Cancel", we only offer to let them "Undo" the
|
||||||
|
// action if the undo would be substantive.
|
||||||
|
|
||||||
var is_empty = this._isVoidContentState(new_state);
|
// The undo is substantive if the text is nonempty, and not similar to
|
||||||
var is_same = this._isSameContentState(new_state, old_state);
|
// the last state.
|
||||||
|
var versus = committed || initial;
|
||||||
if (!is_empty && !is_same) {
|
if (!active.isTextEmpty() && !active.isTextSimilar(versus)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The undo is substantive if there's a suggestion, and the suggestion
|
||||||
|
// is not similar to the last state.
|
||||||
|
if (active.getHasSuggestion()) {
|
||||||
|
if (!active.isSuggestionSimilar(versus)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -887,8 +890,8 @@ JX.install('DiffInline', {
|
||||||
this._applyCall(handler, data);
|
this._applyCall(handler, data);
|
||||||
},
|
},
|
||||||
|
|
||||||
_applyDelete: function() {
|
_applyDelete: function(prevent_undo) {
|
||||||
var handler = JX.bind(this, this._ondeleteresponse);
|
var handler = JX.bind(this, this._ondeleteresponse, prevent_undo);
|
||||||
|
|
||||||
var data = this._newRequestData('delete');
|
var data = this._newRequestData('delete');
|
||||||
|
|
||||||
|
@ -903,6 +906,14 @@ JX.install('DiffInline', {
|
||||||
this._applyCall(handler, data);
|
this._applyCall(handler, data);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_applyEdit: function(state) {
|
||||||
|
var handler = JX.bind(this, this._oneditresponse);
|
||||||
|
|
||||||
|
var data = this._newRequestData('edit', state);
|
||||||
|
|
||||||
|
this._applyCall(handler, data);
|
||||||
|
},
|
||||||
|
|
||||||
_applyCall: function(handler, data) {
|
_applyCall: function(handler, data) {
|
||||||
var uri = this._getInlineURI();
|
var uri = this._getInlineURI();
|
||||||
|
|
||||||
|
@ -946,24 +957,33 @@ JX.install('DiffInline', {
|
||||||
},
|
},
|
||||||
|
|
||||||
cancel: function() {
|
cancel: function() {
|
||||||
|
// NOTE: Read the state before we remove the editor. Otherwise, we might
|
||||||
|
// miss text the user has entered into the textarea.
|
||||||
|
var state = this._getActiveContentState().getWireFormat();
|
||||||
|
|
||||||
JX.DOM.remove(this._editRow);
|
JX.DOM.remove(this._editRow);
|
||||||
this._editRow = null;
|
this._editRow = null;
|
||||||
|
|
||||||
if (this._shouldDeleteOnCancel()) {
|
// When a user clicks "Cancel", we delete the comment if it has never
|
||||||
this._setPreventUndo(true);
|
// been saved: we don't have a non-empty display state to revert to.
|
||||||
this._applyDelete();
|
var is_delete = (this._getCommittedContentState() === null);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._shouldUndoOnCancel()) {
|
var is_undo = this._shouldUndoOnCancel();
|
||||||
var state = this._getActiveContentState().getWireFormat();
|
|
||||||
this._drawUneditRows(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If you "undo" to restore text ("AB") and then "Cancel", we put you
|
// If you "undo" to restore text ("AB") and then "Cancel", we put you
|
||||||
// back in the original text state ("A"). We also send the original
|
// back in the original text state ("A"). We also send the original
|
||||||
// text ("A") to the server as the current persistent state.
|
// text ("A") to the server as the current persistent state.
|
||||||
|
|
||||||
|
if (is_undo) {
|
||||||
|
this._drawUneditRows(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_delete) {
|
||||||
|
// NOTE: We're always suppressing the undo from "delete". We want to
|
||||||
|
// use the "undo" we just added above instead, which will get us
|
||||||
|
// back to the ephemeral, client-side editor state.
|
||||||
|
this._applyDelete(true);
|
||||||
|
} else {
|
||||||
this.setEditing(false);
|
this.setEditing(false);
|
||||||
this.setInvisible(false);
|
this.setInvisible(false);
|
||||||
|
|
||||||
|
@ -971,6 +991,7 @@ JX.install('DiffInline', {
|
||||||
this._applyCancel(old_state.getWireFormat());
|
this._applyCancel(old_state.getWireFormat());
|
||||||
|
|
||||||
this._didUpdate(true);
|
this._didUpdate(true);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_onCancelResponse: function(response) {
|
_onCancelResponse: function(response) {
|
||||||
|
@ -1067,8 +1088,8 @@ JX.install('DiffInline', {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var state = this._getActiveContentState().getWireFormat();
|
var state = this._getActiveContentState();
|
||||||
if (this._isVoidContentState(state)) {
|
if (state.isStateEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,7 +1098,7 @@ JX.install('DiffInline', {
|
||||||
id: this.getID(),
|
id: this.getID(),
|
||||||
};
|
};
|
||||||
|
|
||||||
JX.copy(draft_data, state);
|
JX.copy(draft_data, state.getWireFormat());
|
||||||
|
|
||||||
return draft_data;
|
return draft_data;
|
||||||
},
|
},
|
||||||
|
@ -1193,22 +1214,8 @@ JX.install('DiffInline', {
|
||||||
suggestionText: '',
|
suggestionText: '',
|
||||||
hasSuggestion: false
|
hasSuggestion: false
|
||||||
};
|
};
|
||||||
},
|
|
||||||
|
|
||||||
_isVoidContentState: function(state) {
|
|
||||||
if (!state.text) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return (!state.text.length && !state.suggestionText.length);
|
|
||||||
},
|
|
||||||
|
|
||||||
_isSameContentState: function(u, v) {
|
|
||||||
return (
|
|
||||||
((u === null) === (v === null)) &&
|
|
||||||
(u.text === v.text) &&
|
|
||||||
(u.suggestionText === v.suggestionText) &&
|
|
||||||
(u.hasSuggestion === v.hasSuggestion));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -59,6 +59,72 @@ JX.install('DiffInlineContentState', {
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isStateEmpty: function() {
|
||||||
|
return (this.isTextEmpty() && this.isSuggestionEmpty());
|
||||||
|
},
|
||||||
|
|
||||||
|
isTextEmpty: function() {
|
||||||
|
var text = this.getText();
|
||||||
|
if (text === null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._isStringSimilar(text, '')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
isSuggestionEmpty: function() {
|
||||||
|
if (!this.getHasSuggestion()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var suggestion = this.getSuggestionText();
|
||||||
|
if (suggestion === null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._isStringSimilar(suggestion, '')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
isTextSimilar: function(v) {
|
||||||
|
if (!v) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var us = this.getText();
|
||||||
|
var vs = v.getText();
|
||||||
|
|
||||||
|
return this._isStringSimilar(us, vs);
|
||||||
|
},
|
||||||
|
|
||||||
|
isSuggestionSimilar: function(v) {
|
||||||
|
// If we don't have a comparison state, treat them as dissimilar. This
|
||||||
|
// is expected to occur in old inline comments that did not save an
|
||||||
|
// initial state.
|
||||||
|
|
||||||
|
if (!v) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var us = this.getSuggestionText();
|
||||||
|
var vs = v.getSuggestionText();
|
||||||
|
|
||||||
|
return this._isStringSimilar(us, vs);
|
||||||
|
},
|
||||||
|
|
||||||
|
_isStringSimilar: function(u, v) {
|
||||||
|
u = u || '';
|
||||||
|
v = v || '';
|
||||||
|
return (u === v);
|
||||||
|
},
|
||||||
|
|
||||||
_getSuggestionNode: function(row) {
|
_getSuggestionNode: function(row) {
|
||||||
try {
|
try {
|
||||||
return JX.DOM.find(row, 'textarea', 'inline-content-suggestion');
|
return JX.DOM.find(row, 'textarea', 'inline-content-suggestion');
|
||||||
|
|
Loading…
Reference in a new issue