Skip to content
Permalink
Browse files

android virtualkey with corrector/completion

  • Loading branch information...
Gorash committed Mar 21, 2019
1 parent ed4a457 commit 41cf7d82889c45ec29927b900efab5d0f4fbd8cf
@@ -13,15 +13,11 @@ dom.isAnchor = function (node) {
var KeyboardPlugin = AbstractPlugin.extend({
events: {
'summernote.keydown': '_onKeydown',
'summernote.keyup': '_onKeyup',
'DOMNodeInserted .note-editable': '_removeGarbageSpans',
'textInput .note-editable': '_onAndroidVirtualKeyboardTextInput',
},

//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------



//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
@@ -998,7 +994,47 @@ var KeyboardPlugin = AbstractPlugin.extend({
}
return range;
},
/**
* create a container to focus and who receive the accented char or the
* auto-completion string.
*
* @private
* @param {function} callback
*/
_onAccentedAndVirtualKey: function (callback) {
var self = this;
if (this._onAccentedAndVirtualKeyCallback) {
return;
}

this.editable.normalize();
var baseRange = this.context.invoke('editor.createRange');

var $parent = $(baseRange.sc.parentNode);
var parentContenteditable = $parent.attr('contenteditable');
$parent.attr('contenteditable', false);

var accentPlaceholder = this.document.createElement('span');
accentPlaceholder.style.position = 'absolute';
accentPlaceholder.style.zIndex = '-100';
$(baseRange.sc).after(accentPlaceholder);
$(accentPlaceholder).attr('contenteditable', true);

this.context.invoke('editor.setRange', accentPlaceholder, 0).select();

this._onAccentedAndVirtualKeyCallback = function () {
var text = accentPlaceholder.textContent;
if (parentContenteditable) {
$parent.attr('contenteditable', parentContenteditable);
} else {
$parent.removeAttr('contenteditable');
}
$(accentPlaceholder).remove();
callback(text, baseRange);
this._onAccentedAndVirtualKeyCallback = null;
};
this._onAccentedAndVirtualKeyTimer = setTimeout(this._onAccentedAndVirtualKeyCallback.bind(this));
},

//--------------------------------------------------------------------------
// Handle
@@ -1022,7 +1058,9 @@ var KeyboardPlugin = AbstractPlugin.extend({
return;
}

if (e.key &&
if (e.keyCode === 229) {
this._onAndroidVirtualKeyboard(e);
} else if (e.key &&
(e.key.length === 1 || e.key === "Dead" || e.key === "Unidentified") &&
!e.ctrlKey && !e.altKey && !e.metaKey) {

@@ -1056,34 +1094,19 @@ var KeyboardPlugin = AbstractPlugin.extend({
}
} else {
this.lastCharIsVisible = false;
this.context.invoke('editor.clearTarget');
this.context.invoke('MediaPlugin.hidePopovers');
this.context.invoke('editor.beforeCommand');
switch (e.keyCode) {
case 8: // BACKSPACE
handled = this._onBackspace(e);
break;
case 9: // TAB
handled = this._onTab(e);
break;
case 13: // ENTER
handled = this._onEnter(e);
break;
case 46: // DELETE
handled = this._onDelete(e);
break;
}
if (handled) {
this._preventTextInEditableDiv();
this.context.invoke('editor.saveRange');
if (this._onMiscKeydown(e)) {
e.preventDefault();
this.context.invoke('editor.afterCommand');
}
}
if (e.key !== "Dead") {
this._accented = false;
}
},
_onKeyup: function (se, e) {
if (e.key && e.key === "Dead" || e.key === "Unidentified") {
this._accented = true;
};
},
/**
* Handle BACKSPACE keydown event.
*
@@ -1173,6 +1196,45 @@ var KeyboardPlugin = AbstractPlugin.extend({
}
return true;
},
/**
* Used for BACKSPACE, TAB, ENTER and DELETE
*
* @private
* @param {string} action
*/
_onMiscKeydown: function (e) {
var action = ({
'8': 'BACKSPACE',
'9': 'TAB',
'13': 'ENTER',
'46': 'DELETE',
})[e.keyCode];

this.context.invoke('editor.clearTarget');
this.context.invoke('MediaPlugin.hidePopovers');
this.context.invoke('editor.beforeCommand');
var handled;
switch (action) {
case 'BACKSPACE':
handled = this._onBackspace(e);
break;
case 'TAB':
handled = this._onTab(e);
break;
case 'ENTER':
handled = this._onEnter(e);
break;
case 'DELETE':
handled = this._onDelete(e);
break;
}
if (handled) {
this._preventTextInEditableDiv();
this.context.invoke('editor.saveRange');
this.context.invoke('editor.afterCommand');
}
return handled;
},
/**
* Handle TAB keydown event.
*
@@ -1230,38 +1292,86 @@ var KeyboardPlugin = AbstractPlugin.extend({
*/
_onVisibleChar: function (e, accented) {
var self = this;
e.preventDefault();
if (accented) {
this.editable.normalize();
var baseRange = this.context.invoke('editor.createRange');

var $parent = $(baseRange.sc.parentNode);
var parentContenteditable = $parent.attr('contenteditable');
$parent.attr('contenteditable', false);

var accentPlaceholder = this.document.createElement('span');
$(baseRange.sc).after(accentPlaceholder);
$(accentPlaceholder).attr('contenteditable', true);

var range = this.context.invoke('editor.setRange', accentPlaceholder, 0);
range.select();

setTimeout(function () {
var accentedChar = accentPlaceholder.innerHTML;
$(accentPlaceholder).remove();
if (parentContenteditable) {
$parent.attr('contenteditable', parentContenteditable);
} else {
$parent.removeAttr('contenteditable');
}
baseRange.select();
self.context.invoke('HelperPlugin.insertTextInline', accentedChar);
this._onAccentedAndVirtualKey(function (text, range) {
range.select();
self.context.invoke('HelperPlugin.insertTextInline', text);
});
} else {
e.preventDefault();
this.context.invoke('HelperPlugin.insertTextInline', e.key);
}
return true;
},
_onAndroidVirtualKeyboardTextInput: function (e) {
this.context.invoke('HelperPlugin.insertTextInline', e.originalEvent.data);
e.preventDefault();
},
/**
* Handle keydown event from android virtual keyboard.
*
* @private
* @param {jQueryEvent} e
* @returns {Boolean} true if case is handled and event default must be prevented
*/
_onAndroidVirtualKeyboard: function (e) {
var self = this;
e.preventDefault();

if (!e.originalEvent.isComposing) {
return;
}

this._onAccentedAndVirtualKey(function (text, range) {
// get the previous word to complete or correct
var previousText = '';
var point = dom.nextPoint(dom.prevPointUntil(range.getStartPoint(), function (point) {
if (dom.isBlock(point.node.childNodes[point.offset] || point.node)) {
return true;
}
if (dom.isText(point.node)) {
var char = point.node.textContent.slice(point.offset, point.offset+1);
if (char === ' ' || char === '\u00A0') {
return true;
}
previousText = char + previousText;
}
}));

// complete the word
if (!text.indexOf(previousText)) {
text = text.slice(previousText.length);
} else {
// autocorrect the word (change only the updated char, and keep the format for previous chars)
var length = previousText.length;
var remove = false;
while (point && point.node && length) {
if (dom.isText(point.node)) {
var char = point.node.textContent.slice(point.offset, point.offset + 1);
if (char.length) {
length--;
if (!remove && text[0] === char) {
text = text.slice(1);
} else {
point.node.textContent = point.node.textContent.slice(0, point.offset) + point.node.textContent.slice(point.offset + 1);
remove = true;
continue;
}
}
}
point = dom.nextPoint(point);
}
range.sc = range.ec = point.node;
range.so = range.eo = point.offset;
range.select();
}
if (text.length) {
range.select();
self.context.invoke('HelperPlugin.insertTextInline', text);
}
});
return true;
},
});

registry.add('KeyboardPlugin', KeyboardPlugin);
Oops, something went wrong.

0 comments on commit 41cf7d8

Please sign in to comment.
You can’t perform that action at this time.