我正在尝试在summernote中实施handsontable富文本编辑器。要求就像用户按下/ F2 /双击单元格然后打开富文本编辑器,光标应移动到编辑器中有单元格文本的编辑器(如果单元格保留任何数据),用户可以输入/修改数据。用户可以在编辑器工具栏的帮助下修改数据(可以制作粗体/斜体/上传图像等)。在输入或修改数据之后,它应该按照handontable的默认行为返回到handsontable单元格中。
我尝试使用summernote在handsontable中实现上述行为。我可以在单元格中按Enter键后打开编辑器,但是summernote编辑器会冻结一段时间,编辑器中的焦点不会输入任何数据。
请建议/帮助将summernote整合到handontable中。
这是完整的html页面:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handsontable/0.22.0/handsontable.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/handsontable/0.22.0/handsontable.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.0/summernote.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.0/summernote.css" rel="stylesheet" />
<style type="text/css">
body {
background: white;
margin: 20px;
}
h2 {
margin: 20px 0;
}
</style>
</head>
<body>
<div id="example_handsontable" class="handsontable"></div>
<!--Selected Id: <span id="selectedId"></span>-->
<div class="summernote"></div>
</body>
<script type="text/javascript">
$(document).ready(function () {
var mydata = [{ num: 1, num2: 2, num3: 3 }
, { num: 1, num2: 2, num3: 3 }
, { num: 1, num2: 2, num3: 3 }
, { num: 1, num2: 2, num3: 3 }
, { num: 1, num2: 2, num3: 3 }
, { num: 1, num2: 2, num3: 3 }];
var columnsList =
[{
data: 'num',
editor: 'summernote',
renderer: summerNoteRenderer,
width: '200px'
},
{
data: 'num',
editor: 'summernote',
renderer: summerNoteRenderer,
width: '200px'
},
{
data: 'num',
editor: 'summernote',
renderer: summerNoteRenderer,
width: '200px'
}
],
$container = $('#example_handsontable');
$container.handsontable({
data: mydata,
minSpareRows: 0,
colHeaders: true,
columns: columnsList
});
});
function summerNoteRenderer(instance, td, row, col, prop, value, cellProperties) {
Handsontable.TextCell.renderer.apply(this, arguments);
}
// SummerNote plugin
(function (Handsontable) {
"use strict";
var SummerNoteEditor = Handsontable.editors.TextEditor.prototype.extend();
SummerNoteEditor.prototype.prepare = function (row, col, prop, td, originalValue, cellProperties) {
Handsontable.editors.TextEditor.prototype.prepare.apply(this, arguments);
};
SummerNoteEditor.prototype.createElements = function () {
this.$body = $(document.body);
this.TEXTAREA = document.createElement('input');
this.TEXTAREA.setAttribute('type', 'text');
this.$textarea = $(this.TEXTAREA);
Handsontable.Dom.addClass(this.TEXTAREA, 'handsontableInput');
this.textareaStyle = this.TEXTAREA.style;
this.textareaStyle.width = 0;
this.textareaStyle.height = 0;
this.TEXTAREA_PARENT = document.createElement('DIV');
Handsontable.Dom.addClass(this.TEXTAREA_PARENT, 'handsontableInputHolder');
this.textareaParentStyle = this.TEXTAREA_PARENT.style;
this.textareaParentStyle.top = 0;
this.textareaParentStyle.left = 0;
this.textareaParentStyle.display = 'none';
this.TEXTAREA_PARENT.appendChild(this.TEXTAREA);
this.instance.rootElement.appendChild(this.TEXTAREA_PARENT);
var that = this;
this.instance._registerTimeout(setTimeout(function () {
that.refreshDimensions();
}, 0));
};
var onSummerNoteInit = function () {
console.log('Summmer initialized');
// this.close();
// this.finishEditing();
};
var onSummerNoteEnter = function () {
console.log('Summmer Enter');
//this.close();
//this.finishEditing();
};
var onBeforeKeyDown = function (event) {
var instance = this;
var that = instance.getActiveEditor();
var keyCodes = Handsontable.helper.keyCode;
var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey; //catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)
//Process only events that have been fired in the editor
if (!$(event.target).hasClass('summernote') || event.isImmediatePropagationStopped()) {
return;
}
if (event.keyCode === 17 || event.keyCode === 224 || event.keyCode === 91 || event.keyCode === 93) {
//when CTRL or its equivalent is pressed and cell is edited, don't prepare selectable text in textarea
event.stopImmediatePropagation();
return;
}
var target = event.target;
switch (event.keyCode) {
case keyCodes.ARROW_RIGHT:
if (Handsontable.Dom.getCaretPosition(target) !== target.value.length) {
event.stopImmediatePropagation();
} else {
that.$textarea.summernote('destroy');
}
break;
case keyCodes.ARROW_LEFT:
if (Handsontable.Dom.getCaretPosition(target) !== 0) {
event.stopImmediatePropagation();
} else {
that.$textarea.summernote('destroy');
}
break;
case keyCodes.ENTER:
var selected = that.instance.getSelected();
var isMultipleSelection = !(selected[0] === selected[2] && selected[1] === selected[3]);
if ((ctrlDown && !isMultipleSelection) || event.altKey) { //if ctrl+enter or alt+enter, add new line
if (that.isOpened()) {
that.val(that.val() + '\n');
that.focus();
} else {
that.beginEditing(that.originalValue + '\n')
}
event.stopImmediatePropagation();
}
event.preventDefault(); //don't add newline to field
break;
case keyCodes.A:
case keyCodes.X:
case keyCodes.C:
case keyCodes.V:
if (ctrlDown) {
event.stopImmediatePropagation(); //CTRL+A, CTRL+C, CTRL+V, CTRL+X should only work locally when cell is edited (not in table context)
}
break;
case keyCodes.BACKSPACE:
case keyCodes.DELETE:
case keyCodes.HOME:
case keyCodes.END:
event.stopImmediatePropagation(); //backspace, delete, home, end should only work locally when cell is edited (not in table context)
break;
}
};
SummerNoteEditor.prototype.open = function (keyboardEvent) {
this.refreshDimensions();
this.textareaParentStyle.display = 'block';
this.instance.addHook('beforeKeyDown', onBeforeKeyDown);
this.$textarea.css({
height: $(this.TD).height() + 4,
'min-width': $(this.TD).outerWidth() - 4
});
var self = this;
this.$textarea.summernote({ focus: true });
// setTimeout(function () { $('.summernote').find('.note-editable').focus(); }, 200);
};
SummerNoteEditor.prototype.init = function () {
Handsontable.editors.TextEditor.prototype.init.apply(this, arguments);
};
SummerNoteEditor.prototype.close = function () {
this.instance.listen();
this.instance.removeHook('beforeKeyDown', onBeforeKeyDown);
this.$textarea.off();
this.$textarea.hide();
Handsontable.editors.TextEditor.prototype.close.apply(this, arguments);
};
SummerNoteEditor.prototype.val = function (value) {
if (typeof value == 'undefined') {
return this.$textarea.val();
} else {
this.$textarea.val(value);
}
};
SummerNoteEditor.prototype.focus = function () {
this.instance.listen();
// DO NOT CALL THE BASE TEXTEDITOR FOCUS METHOD HERE, IT CAN MAKE THIS EDITOR BEHAVE POORLY AND HAS NO PURPOSE WITHIN THE CONTEXT OF THIS EDITOR
//Handsontable.editors.TextEditor.prototype.focus.apply(this, arguments);
};
SummerNoteEditor.prototype.beginEditing = function (initialValue) {
var onBeginEditing = this.instance.getSettings().onBeginEditing;
if (onBeginEditing && onBeginEditing() === false) {
return;
}
Handsontable.editors.TextEditor.prototype.beginEditing.apply(this, arguments);
};
SummerNoteEditor.prototype.finishEditing = function (isCancelled, ctrlDown) {
this.instance.listen();
return Handsontable.editors.TextEditor.prototype.finishEditing.apply(this, arguments);
};
Handsontable.editors.SummerNoteEditor = SummerNoteEditor;
Handsontable.editors.registerEditor('summernote', SummerNoteEditor);
})(Handsontable);
</script>
</html>