Создание помощника по контенту (ctrl + пробел) с использованием Javascript и редактируемого документа - PullRequest
3 голосов
/ 06 ноября 2011

Я создал работающий пример помощника по содержимому в редактируемой области HTML-документа. Поэтому, если пользователь нажимает Ctrl и пробел на клавиатуре, появляется контекстное меню. В настоящее время (см. Демонстрацию ниже) контекстное меню находится в правой позиции y (ниже текста). Но это идет не вместе с осью X (если текст станет длиннее, поле будет посеяно в начале строки).

Можете ли вы помочь мне решить эту проблему?

Привет, mythbu

Пример кода:

<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Test</title>
<script type="text/javascript">

var iframe = null, iwindow = null, iDocument = null;

function setUpInput() {
        iframe = document.createElement( 'iframe' );
        iframe.setAttribute( 'id', 'iframe-test' );
        iframe.setAttribute( 'frameborder', 0 );
        iframe.setAttribute( 'style', 'width:100%; height:100%;border: solid 1px red;' );

        document.getElementById( "input" ).appendChild( iframe );

        iwindow   = iframe.contentWindow;
        idocument = iwindow.document;

        idocument.open();
        idocument.write("<p></p>");
        idocument.close();

        idocument.body.setAttribute( 'spellcheck', false );
        idocument.body.setAttribute( 'style', 'font-family: Consolas,serif;font-size: 0.8em;' );
        idocument.body.contentEditable = true;

        iwindow.onkeydown = function(e) {
            if (e.ctrlKey && e.keyCode == 32) {
                createSuggestObject();
                return false;
            }
            if (e.ctrlKey) return false;
        };

        iwindow.onkeypress = function(e) {if (e.ctrlKey) return false;};
}

function createSuggestObject() {
suggest = new Object();
suggest.box = document.createElement( 'div' );
suggest.box.style.position = 'absolute';
suggest.box.style.width = '120px';
suggest.box.style.overflow = 'auto';
suggest.box.style.border = '1px solid #BEC7E4';
suggest.box.style.display = 'block';
suggest.box.style.marginTop = '16px';
suggest.box.innerHTML = "Example 1";
document.body.appendChild( suggest.box )

var position = iframe.getBoundingClientRect();

var selObj = iwindow.getSelection();
var selRange = selObj.getRangeAt(0);
var p2 = selObj.anchorNode.parentNode.getBoundingClientRect();  

suggest.box.style.top = Math.round( window.scrollY + position.top + p2.top) + 'px';
suggest.box.style.left = Math.round( window.scrollX + position.left + p2.left) + 'px';

}

window.onload = function() {
    setUpInput();
};
</script>

</head>
<body>
<div id="input"></div>
</body>
</html>

1 Ответ

0 голосов
/ 08 ноября 2011

Основная проблема вашего решения заключалась в том, что вы использовали ограничивающий прямоугольник элемента p (который, как вы предполагали, содержали текст, введенный пользователем) в качестве ссылки на место размещения объекта подсказки.

Прежде всего, вы не учли ограничивающую ширину прямоугольника в позиции объекта подсказки, поэтому поле для подсказок оставалось слева независимо от длины текста.

Однако такой подход в конечном итоге потерпит неудачу, потому что если текст будет иметь более одной строки (где вторая строка будет короче первой), ширина ограничительного прямоугольника будет равна длине первой строки (больше или меньше) ). Следовательно, объект предложения будет расположен неправильно.

Моей первой идеей о том, как исправить ваш код, было добавление некоторого встроенного элемента к тексту ( маяк , если хотите), измерение его позиции, удаление его из DOM и использование этой вычисленной позиции для правильно установить объект предложения.

Оказалось, почти работать. Почти, потому что, как оказалось, разные браузеры используют разные методы , имеющие дело с окончаниями строки contentEditable . Например, Firefox вставляет <br _moz_dirty=""/> в конце строки, а Chrome - нет. Поэтому, когда я попытался добавить свой элемент beacon после текста, к которому он был добавлен после этого, <br/> снова вызвал неправильную позицию.

Решение состояло в том, чтобы изменить способ получения текстового узла, с которым мы имеем дело, и вставить маяк прямо перед следующим сообщением.

Вот рабочий пример http://jsfiddle.net/MmKXS/10/

Примечание 1. Я удалил добавление пустого элемента <p></p> в документ iframe, поскольку в Chrome текст, введенный пользователем, не был вставлен в него, что вызвало еще одну проблему с позиционированием объекта предлагаем.

Примечание 2: На данный момент мое решение работает только для позиционирования объекта предложения в конце текста, , а не в позиции курсора, так как это будет связано с разделением textNodes, вставкой маяка, проверкой его положение и слияние текстовых узлов снова. В зависимости от варианта использования, который у вас есть для этого кода, это может привести к снижению производительности и / или может потребовать изменения всего подхода к позиционированию объекта предложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...