I am currently developing a tag input system for a template builder. My main focus right now is on assisting the editor in distinguishing between regular text and formatted text. I am structuring it similar to WordPress shortcodes, where a templated element would be enclosed in square brackets like [shortcode]
. However, I am facing an issue where the cursor in my div 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>