@itlogunov

Как заставить правильно работать каретку?

Добрый день!

html:
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>caret</title>
</head>

<body>
   <button class="input">Вставить радио кнопки</button>
   <div class="edit" contenteditable>
    
   </div>
</body>
</html>


$(document).on('keyup', '.edit', function(e){
   var caret = ''; // положение каретки
   var insertCurrentPlace = ''; // текущий тег, от которого считается каретка
   caret = window.getSelection().anchorOffset;

   if (window.getSelection().anchorNode.nodeName == '#text') {
       insertCurrentPlace = window.getSelection().anchorNode.parentNode;
   } else {
       insertCurrentPlace = window.getSelection().anchorNode;
   }

   console.log(caret);
});


function insertAtCaret(obj, caret, html){
        txt = obj.innerHTML;
        caret += (txt.split('&nbsp;').length-1)*5;
        txt = txt.substring(0, caret) + html + txt.substring(caret);
        obj.innerHTML = txt;
        obj.focus();
};

$('.input').click(function(){
    var html = '<input type="radio" name="radio" value="да"/>Да<input type="radio" name="radio" value="нет"/>Нет';
    insertAtCaret(insertCurrentPlace, caret, html);
});


Конкретно для firefox.
Каретка при нажатии правильно считается, но мы нажимаем ENTER, переходим на новую строку, каретка обнуляется и начинает считать с нуля. Все в принципе логично и я не против. Тег добавляется "br".

Далее я печатаю пару символов и нажимаю ENTER, печатаю еще пару символов и нажимаю "Вставить радио кнопки". Так вставляется относительно главного тега div class="edit", а не относительно новой строки. Причем каретка-то правильно считает с новой строки. Вот в хроме все отлично, там добавляется div при нажатии enter и отсчет каретки идет относительно этого вновь созданного div, а ff победить никак не могу. Подскажите пожалуйста в какую сторону смотреть.
  • Вопрос задан
  • 4026 просмотров
Решения вопроса 1
@itlogunov Автор вопроса
Решил так:
$.extend( {
		    saveSelection: function() {
		        SelectionProvider = new Object();
		 
		        if (window.getSelection) {
		            sel = window.getSelection();
		            if (sel.getRangeAt && sel.rangeCount) {
		                SelectionProvider.storedSelection = sel.getRangeAt(0);
		            }
		        } else if (document.selection && document.selection.createRange) {
		            SelectionProvider.storedSelection = document.selection.createRange();
		        }
		        // SelectionProvider.storedSelection = null;
		         
		    }
		});

		$.extend( {
		    restoreSelection: function() {
		         
		        var range = SelectionProvider.storedSelection;
		        if (range) {
		            if (window.getSelection) {
		                sel = window.getSelection();
		                sel.removeAllRanges();
		                sel.addRange(range);
		            } else if (document.selection && range.select) {
		                range.select();
		            }
		        }
		         
		    }
		});

		$.extend( {
		    pasteHtmlAtCursor: function(html) {
		        var sel, range;
		        if (window.getSelection) {
		            sel = window.getSelection();
		            if (sel.getRangeAt && sel.rangeCount) {
		                range = sel.getRangeAt(0);
		                range.deleteContents();
		 
		                var el = document.createElement("div");
		                el.innerHTML = html;
		                var frag = document.createDocumentFragment(), node, lastNode;
		                while ((node = el.firstChild)) {
		                    lastNode = frag.appendChild(node);
		                }
		                range.insertNode(frag);
		 
		                if (lastNode) {
		                    range = range.cloneRange();
		                    range.setStartAfter(lastNode);
		                    range.collapse(true);
		                    sel.removeAllRanges();
		                    sel.addRange(range);
		                }
		            }
		        } else if (document.selection && document.selection.type != "Control") {
		            document.selection.createRange().pasteHTML(html);
		        }      
		    }
		});


затем когда нужно сохранить курсор ставим
$.saveSelection(); //сохраняем позицию курсора

и вставляем
$.restoreSelection(); //загружаем позицию курсора
$.pasteHtmlAtCursor(html); //вставляем код
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Нашел странице на какой-то гугла

function pasteHtmlAtCaret(html) {
    var sel, range;
    if (window.getSelection) {
        // IE9 and non-IE
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.deleteContents();

            // Range.createContextualFragment() would be useful here but is
            // non-standard and not supported in all browsers (IE9, for one)
            var el = document.createElement("div");
            el.innerHTML = html;
            var frag = document.createDocumentFragment(), node, lastNode;
            while ((node = el.firstChild)) {
                lastNode = frag.appendChild(node);
            }
            range.insertNode(frag);

            // Preserve the selection
            if (lastNode) {
                range = range.cloneRange();
                range.setStartAfter(lastNode);
                range.collapse(true);
                sel.removeAllRanges();
                sel.addRange(range);
            }
        }
    } else if (document.selection && document.selection.type != "Control") {
        // IE < 9
        document.selection.createRange().pasteHTML(html);
    }
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы