Редактор Rich Text не работает корректно

Я пытаюсь создать текстовый редактор в текстовом поле. В попытке сделать это я использую Summernote. У меня есть редактор, инициализирующийся рядом с тем, как я хочу. Мне бы очень хотелось, чтобы airmode вел себя при наведении, а не на клик. Тем не менее, есть странное поведение, которое является моей реальной проблемой.

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

  var optionEditors = $('.option-editor');
  for (var i=0; i<optionEditors.length; i++) {
    $(optionEditors[i]).summernote({
      airMode: true,
      popover: {
        air: [
          ['font', ['bold', 'underline', 'clear']]
        ]
      }
    });
  }

Что мне не хватает? Все выглядит правильно. Просто, что поведение кажется неправильным. Спасибо.

Ответ 1

Другое решение - скрыть входы с помощью CSS и сделать summernote похожим на элемент управления формой:

for (var i=0; i<optionEditors.length; i++) {
    $(optionEditors[i]).summernote({
      airMode: true,
      popover: {
        air: [
          ['font', ['bold', 'underline', 'clear']]
        ]
      },
      callbacks: {
        onInit: function() {
               // make the editor like a "form-control"
               $('.note-editor').addClass('form-control');
               // Force editor height adding one space 
               $(this).summernote('code', ' ');
            }
        }      
    });

}

@see рабочий пример https://jsfiddle.net/v8zhvsmo/

Ответ 2

Плагины Bootstrap зависят от jQuery; они не сработают, если сначала не загрузится:

Зависимости плагинов

     

Некоторые плагины и компоненты CSS зависят от других плагинов. Если вы включаете плагины в отдельности, обязательно проверьте эти зависимости в документах. Также обратите внимание, что все плагины зависят от jQuery (это означает, что jQuery должен быть включен перед файлами плагина). Обратитесь к нашему bower.json, чтобы узнать, какие версии jQuery поддерживаются.

Атрибут defer в тэге загрузки jQuery script вызывает его загрузку после вызова addAllElements в вашем onload событие.

  

defer

  
  

Этот атрибут Boolean установлен для указания браузеру, что script предназначен для выполнения после того, как документ был проанализирован. Поскольку эта функция еще не реализована всеми другими основными браузерами, авторы не должны предполагать, что выполнение script будет отложено. Атрибут defer не должен использоваться для скриптов, не имеющих атрибута src. Начиная с Gecko 1.9.2, атрибут defer игнорируется в сценариях, которые не имеют атрибута src. Однако в Gecko 1.9.1 даже встроенные скрипты откладываются, если установлен атрибут defer.

Ответ 3

Причина, по которой это происходит, похоже, не связана с jQuery, похоже, она связана с тем, как summernote инициализирует редактор. Атрибут optional-editor, который вы захватываете, является элементом div и инициализируется, а не элементом input.

Что происходит дальше, тогда summernote берет этот div и создает внутри него несколько других элементов div с такими классами, как note-editor, note-dropzone, note-editing-area и т.д. Внутренний div имеет класс под названием note-editable и внутри этого div будет ваш входной элемент. Разделитель note-editable - это то, что summernote считает фактическим редактором богатого текста, а не элементом ввода. Тем не менее, вы все равно можете щелкнуть элемент ввода и ввести все, что захотите.

Summernote помещает некоторые прослушиватели событий в событие onkeydown (см. документы здесь), и поскольку это текстовый редактор, похоже, проверяя символ пробела (среди прочих, например, enter, который становится новым абзацем), чтобы он мог избежать его в HTML (пробел становится &nbsp;). Поскольку вы печатаете внутри div note-editable, даже если вы технически печатаете внутри своего элемента input, это нажатие клавиши будет зацепиться с помощью summernote и, кажется, помещает символ escaped space внутри div, а не внутри вход. Это приводит к тому, что текст помещается над вашим элементом ввода. Вы заметите, что вы можете использовать ctrl+A, когда ваш курсор находится над элементом ввода, чтобы выделить все внутри этого редактируемого div, и вы даже можете удалить свой элемент ввода.

Мое предложение состояло бы в том, чтобы удалить элемент ввода вообще и просто использовать содержащий div, поскольку это, по-видимому, самый распространенный сценарий использования. Вы также можете попробовать переопределить прослушиватель событий onkeydown и добавить пространство внутри ввода, но это похоже на очень крутой способ решить что-то, что действительно не нужно решать.

Изменить: Похоже, что summernote клонирует node, который обозначается как редактор богатого текста, который в конечном итоге удалит прослушиватели событий на указанном элементе, включая его дочерние элементы, поэтому вы не можете переопределить событие keydown для элемента ввода текста перед инициализацией summernote. Попытка предоставить обратный вызов переопределения для события keyDown через конфигурацию init summernote возможна, но очень уродлива и имеет причуды из-за предварительно сконфигурированных обработчиков событий, заданных с помощью summernote.

В скрипке я использовал только один ввод текста и дал ему id richTextInput. Кроме того, я удалил onchange="onAnswerChoiceChange(this);", поскольку это вызывало ошибку.

Чтобы обеспечить переопределение в конфигурации, используйте это:

$(optionEditors[i]).summernote({
  airMode: true,
  popover: {
    air: [
      ['font', ['bold', 'underline', 'clear']]
    ]
  },
  callbacks: {
    onKeydown: function(e) {
      if (e.keyCode === 32) { // catch "space"
        e.preventDefault();
        $('.note-editable>#richTextInput').val($('.note-editable>#richTextInput').val() + " ");
      }
    }
  }
});

Класс note-editable - это контейнер div, созданный summernote после инициализации. Нам нужно указать это, потому что summernote автоматически копирует все содержимое "богатого текстового редактора" до инициализации, затем скрывает их с помощью display:none, поэтому просто попытка ссылки на вход с помощью $('#richTextInput') не будет работать, потому что вы 'будет захватывать скрытый ввод.

Quirks:. Вы заметите, что если вы попытаетесь использовать этот код, то summernote попытается автоматически предоставить фокус фактическому div-расширителю текстового редактора, что связано с поведением, представленным в прослушивателе событий, зарегистрированным by summernote. Вы можете обойти это, предоставив такой тайм-аут:

setTimeout(function() {
    $('.note-editable>#richTextInput').focus();
}, 1); 

Как я уже говорил, это действительно нехорошее решение, и хотя это может сделать трюк, я думаю, что лучшим маршрутом было бы полное удаление текста и просто инициализация div или textarea без каких-либо вложений внутри библиотеки надеется. Было бы легче сделать это, а затем соответствующим образом подстроить их. Использование стилей/компонентов дизайна материалов, вероятно, будет плохо работать вместе, так как материал требует ввода или элементы textarea, а summernote преобразует текстовое поле в div, но это другая проблема.

Ответ 4

Возможно, решение было простым. Создается родительский элемент <div contenteditable="true"> (и, возможно, вам не нужен <input>), где на самом деле происходит RICH-EDITING.

1) airmode ON: https://jsfiddle.net/hwd5efe0/13/
2) воздушный режим ВЫКЛ: https://jsfiddle.net/hwd5efe0/18/

(p.s только изменил JS)