javascript - Move cursor past span on content editable
问题描述
I am creating a tag entering system for a template builder. Right now I am trying to help my editor "know" the difference between regular text and formatted text because right now I am making it so it is similar to WordPress shortcodes where a templated element would be something like [shortcode]
But the issue I am running into right now is that my div's cursor includes any text typed after an inserted shortcode into the styled div as well.
$(function() {
/**
* Position tracking.
*/
class PositionTracker {
constructor(start, end) {
this.start = start;
this.end = end;
}
}
/**
* Variable insert selector
* @type {jQuery|HTMLElement}
*/
const $selector = $("#variableSelector");
/**
* Message content editor
* @type {jQuery|HTMLElement}
*/
const $body = $("#bodyContent");
/**
* Message Recorder
* @type {jQuery|HTMLElement}
*/
const $recorder = $('#bodyRecorder');
/**
* Position of cursor
* @type {PositionTracker}
*/
const position = new PositionTracker(0, 0);
$selector.on('change', function() {
let content = $body.html();
let tag = $('<span>', {
class: 'text-tag',
text: $(this).val().toString()
});
$body.append(tag);
});
$body.on('input mousedown mouseup mouseout', function() {
$recorder.val($(this).html);
let selection = window.getSelection();
position.start = selection.anchorOffset;
position.end = selection.focusOffset;
});
});
.text-editor {
background: #fff;
margin: 1rem 0;
padding: 10px 8px;
font: inherit;
font-size: 1.15em;
line-height: 1.35;
color: #000;
border: solid 1px rgba(6, 26, 45, 0.65);
box-shadow: inset 2px 2px 6px rgba(4, 24, 39, 0.35);
}
.text-editor:focus {
outline: none;
}
.text-editor[contenteditable=true]:empty:before {
color: darkgray;
content: attr(placeholder);
pointer-events: none;
display: block;
/* For Firefox */
}
.text-editor.body {
min-height: 170px;
}
.text-tag {
background: rgba(0, 195, 255, 0.1);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<input name="content" type="hidden" id="contentRecoreder" required="required">
<div id="bodyContent" contenteditable="true" class="content-body text-editor" placeholder="Hi [customer-name], this is [my-name] with [my-company]. We can do that job for just [quote-price]. If you have any questions, call or text us at [my-phone]"></div>
<label>Variables</label>
<select name="variables" id="variableSelector">
<option value="empty">(choose one)</option>
<option value="[customer-name]">Customer Name</option>
<option value="[my-name]">My Name</option>
<option value="[my-company]">My Company</option>
<option value="[my-price" ]>Quote Price</option>
<option value="[my-phone]">My Phone</option>
</select>
<button type="submit">Save</button>
</form>
解决方案
可能有其他方法可以实现这一点 - 但一种简单的方法是将contenteditable
属性添加到您的 span 元素并将其值设置为false
- 注意这必须在您使用您的shortcode
值填充它之后完成。
请注意,虽然这不会“移动光标”,但它确实会阻止在插入的短代码进入样式跨度之后键入的任何文本。当您考虑它时,这可能是您真正想要的 - 否则您的shotcode
标签只需点击输入即可编辑。
例如
$(function() {
/**
* Position tracking.
*/
class PositionTracker {
constructor(start, end) {
this.start = start;
this.end = end;
}
}
/**
* Variable insert selector
* @type {jQuery|HTMLElement}
*/
const $selector = $("#variableSelector");
/**
* Message content editor
* @type {jQuery|HTMLElement}
*/
const $body = $("#bodyContent");
/**
* Message Recorder
* @type {jQuery|HTMLElement}
*/
const $recorder = $('#bodyRecorder');
/**
* Position of cursor
* @type {PositionTracker}
*/
const position = new PositionTracker(0, 0);
$selector.on('change', function() {
let content = $body.html();
let tag = $('<span>', {
class: 'text-tag',
text: $(this).val().toString()
});
// prevent editing of the span content
tag.attr('contenteditable', false);
$body.append(tag);
});
$body.on('input mousedown mouseup mouseout', function() {
$recorder.val($(this).html);
let selection = window.getSelection();
position.start = selection.anchorOffset;
position.end = selection.focusOffset;
});
});
.text-editor {
background: #fff;
margin: 1rem 0;
padding: 10px 8px;
font: inherit;
font-size: 1.15em;
line-height: 1.35;
color: #000;
border: solid 1px rgba(6, 26, 45, 0.65);
box-shadow: inset 2px 2px 6px rgba(4, 24, 39, 0.35);
}
.text-editor:focus {
outline: none;
}
.text-editor[contenteditable=true]:empty:before {
color: darkgray;
content: attr(placeholder);
pointer-events: none;
display: block;
/* For Firefox */
}
.text-editor.body {
min-height: 170px;
}
.text-tag {
background: rgba(0, 195, 255, 0.1);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<input name="content" type="hidden" id="contentRecoreder" required="required">
<div id="bodyContent" contenteditable="true" class="content-body text-editor" placeholder="Hi [customer-name], this is [my-name] with [my-company]. We can do that job for just [quote-price]. If you have any questions, call or text us at [my-phone]"></div>
<label>Variables</label>
<select name="variables" id="variableSelector">
<option value="empty">(choose one)</option>
<option value="[customer-name]">Customer Name</option>
<option value="[my-name]">My Name</option>
<option value="[my-company]">My Company</option>
<option value="[my-price" ]>Quote Price</option>
<option value="[my-phone]">My Phone</option>
</select>
<button type="submit">Save</button>
</form>
编辑(见评论):
推荐阅读
- scala - Scala 中具有通用返回类型的模式匹配
- javascript - 如何将 javascript 代码与 html 表单合并,当我们执行“提交”之类的操作并给出输出时触发?
- dns - 除了 INTERNET,是否有其他 DNS 类有用的用例?
- angular6 - Angular 多组件页面设计
- java - 关于程序中实例数的模糊问题
- angularjs - 使用 angularjs 登录后,Django request.user 变为空
- c++ - 转换运算符不适用于 sleep_until
- python - 我正在尝试使用 tkinter 制作一个简单的线条绘图程序,但它不起作用
- x11 - X11:使用 xcb 获取主窗口列表
- python - 在python3中使用带有beautifulsoup的子字符串查找html标签