Подтвердить что ты не робот

Как сохранить постоянную строку textarea внутри области просмотра?

У меня есть страница с очень длинным текстовым полем, используемым для редактирования большого количества текстов. Обычно, когда вы набираете, когда каретка приближается к нижней части текстового поля, страница автоматически прокручивается, чтобы сохранить курсор всегда в пределах области просмотра (Firefox будет прокручиваться по одной строке за раз, Chrome будет прокручивать каретку в центр в окне просмотра).

Моя проблема связана с тем, что я программно меняю содержимое текстовой области на основе того, что пользователь набирает. В некоторых случаях это связано с добавлением дополнительного контента, тем самым выталкивая каретку вне поля зрения.

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

Единственное решение, которое я вижу сейчас, это попытаться получить координаты XY каретки:

  • Поиск позиции символа каретки.
  • Построение div, отражающего содержимое текстового поля маркером в позиции каретки.
  • Измерение положения маркера.

Есть ли более простой способ сделать это?

4b9b3361

Ответ 1

Я ненавижу предлагать добавить целую библиотеку для одной проблемы, но подумайте над CodeMirror. Он обрабатывает все такие вещи для вас и довольно прост в использовании.

http://codemirror.net/

Ответ 2

[Предыдущее решение не совместимо с Chrome (WebKit?)]

IF, BIG, если дополнительный контент добавляется к концу ввода, упражнение ниже может предложить решение:

<html>
  <head>
    <script>
      function btnGoOnClick(ctrl)
      {
        //-- For this POC the text content is reset to 160 lines of dummy text -
        //----------------------------------------------------------------------

        ctrl.value = "";

        for (var i = 0; i < 160; ++i)
        {
          ctrl.value += "dummy!\n";
        }

        //-- Then the carret is set to the last position -----------------------
        //----------------------------------------------------------------------

        if (ctrl.createTextRange)
        {
          //-- IE specific methods to move the carret to the last position

          var textRange = ctrl.createTextRange();
          textRange.moveStart("character", ctrl.value.length);
          textRange.moveEnd("character", 0);
          textRange.select();
        }
        else
        {
          //-- Mozilla and WebKit methods to move the carret

          ctrl.setSelectionRange(ctrl.value.length, ctrl.value.length);
        }

        //-- For WebKit, the scroll bar has to be explicitly set ---------------
        //----------------------------------------------------------------------

        ctrl.scrollTop = ctrl.scrollHeight;

        //-- Almost there: make sure the control has fucos and is into view ----
        //----------------------------------------------------------------------

        ctrl.focus();
        ctrl.scrollIntoView(false);
      }
    </script>
  </head>
  <body>
    <form name="form">
      <input type="button" name="btnGo" value="Go!" onClick="btnGoOnClick(document.form.text);" />
      <div style="height: 1000px"></div>
      <textarea name="text" rows="80"></textarea>
    </form>
  </body>
</html>

Ответ 3

Поскольку вы уже находитесь на пути javascript и предположите, что высота динамической textarea создаст проблему с дизайном, вы можете попробовать выполнить автореализацию своего текстового поля по контенту:

function resizeTextarea(textarea) {
  var lines = textarea.value.split('\n');
  var width = textarea.cols;
  var height = 1;
  for (var i = 0; i < lines.length; i++) {
    var linelength = lines[i].length;
    if (linelength >= width) {
      height += Math.ceil(linelength / width);
    }
  }
  height += lines.length;
  textarea.rows = height;
}

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

Я лично ненавижу слишком маленькие области текста и зависит от этого случая, предпочла бы их автосоздание.