JSFiddle - React, Tailwind, and code Playground

by petroveg

HTML

<div class="content" data-target="insert" contenteditable="true">Здравствуйте! Обычно для ввода/изменения текста используются textarea и input.
<p>В моём случае я использую див с contentEditable="true". Поэтому здесь не подходят функции для определения позиции курсора в textarea и input.</p>
<p><b>Сама</b> задача: мне нужно узнать позицию курсора в этом диве, после чего получить эту позицию, и вставить туда кусок текста, который будет добавляться при клике на другой див.</p>
<p>Для начала хочу узнать, как определить и получить позицию курсора в div'e с contentEditable="true"?</p></div>

<div class="container">
	<div class="inner">
		<textarea placeholder="Текст для вставки" class="source" data-source="insert"><strong>Просто</strong> <em>Текст</em></textarea>
	</div>
	<button type="button" class="action" data-action="insert">Вставить</button>
</div>

CSS

.content,
.container{
	display:inline-block;
	vertical-align:top;
}
.content,
.source{
	border:4px solid #ccc;
	border-radius:6px;
}
.content:focus,
.source:focus{
	border-color:#69c;
}
.content{
	overflow:auto;
	width:400px;
	height:300px;
}
.source{
	width:200px;
	height:100px;
}
.inner{
	margin:0 0 30px;
}
.action{
	height:40px;
	line-height:40px;
	margin:0;
	padding:0 20px;
	border:0;
	line-height:40px;
	border-radius:5px;
	font:inherit;
	color:#fff;
	background:#777;
}
.action:hover,
.action:focus{
	background:#69c;
}
.action:active{
	background:#c30;
}

JavaScript

$(function () {
	var $content = $('[data-target="insert"]'),
		$source = $('[data-source="insert"]');

	$(document).on('click', '[data-action="insert"]', function() {
		$content.trigger('focus');
		insertHTML($source.val());
	});
});

function insertHTML(html) {
	try {
		var selection = window.getSelection(),
			range = selection.getRangeAt(0),
			temp = document.createElement('div'),
			insertion = document.createDocumentFragment();

		temp.innerHTML = html;

		while (temp.firstChild) {
			insertion.appendChild(temp.firstChild);
		}

		range.deleteContents();
		range.insertNode(insertion);
	} catch (z) {
		try {
			document.selection.createRange().pasteHTML(html);
		} catch (z) {}
	}
}