Ace: Событие «change» срабатывает при программной настройке Ace

Созданный на 14 нояб. 2011  ·  12Комментарии  ·  Источник: ajaxorg/ace

Для такого кода:

editor.getSession().on('изменить', function() {
// Сделай что-нибудь
});

Я ожидаю, что это событие будет срабатывать только при взаимодействии с пользователем. Однако я обнаружил, что он срабатывает, когда я программно устанавливаю значение редактора, что не соответствует чему-то вроде, скажем, DOM. (Если вы добавите прослушиватель событий «change» для поля ввода, он не сработает, если мы установим значение с помощью JavaScript.)

Можно ли это исправить, и есть ли обходной путь или другое событие, которое срабатывает при обновлении значения редактора, но не программно?
@gissues :{"заказ":33.540372670807756,"статус":"отставание"}

Самый полезный комментарий

либо используйте метод, описанный в https://github.com/ajaxorg/ace/issues/1547#issuecomment -22257510, либо

editor.on("change", function(e) {
  if (editor.curOp && editor.curOp.command.name) console.log("user change");
  else console.log("other change")
})

Все 12 Комментарий

По той же причине, по которой я отказался от CodeMirror в пользу ACE. Но код ACE намного легче читать. Я сделал патч, чтобы немного исправить это. Событие изменения по-прежнему запускается, но я добавил логическое свойство к объекту данных: userTyped. Будет true, если пользователь набрал или вставил текст в редактор. False, если он был введен программно. Это работает для моего конкретного случая использования в Chrome.

Это для файла ace-uncompressed.js из 0.2.0: http://dl.dropbox.com/u/310281/ace-patch.txt

я не думаю, что есть хороший способ разделить «программные» и пользовательские изменения (например, к какому типу принадлежит текст, введенный виджетом автозаполнения?)
и добавление userTyped добавляет много бухгалтерии повсюду

если вам нужны только события ввода текста, вы можете добавить прослушиватель событий dom "input" в editor.container
или если вы хотите отфильтровать только свой собственный вызов setValue, добавьте флаг (аналогично $blockScrolling в editor.js)
это будет работать, поскольку событие «изменение» является синхронным

либо используйте метод, описанный в https://github.com/ajaxorg/ace/issues/1547#issuecomment -22257510, либо

editor.on("change", function(e) {
  if (editor.curOp && editor.curOp.command.name) console.log("user change");
  else console.log("other change")
})

Фрагмент, опубликованный nightwing, не работает должным образом, пока применяется копипаста. Другое решение, которое может решить проблему, похоже на это, например, с jquery:

editor.getSession().on('change', function() {
    if ($(document.activeElement).closest("div").attr("id") == "editordiv") {
        console.log("editor was changed by user typing or copy paste");
    } else {
        console.log("editor was changed programmatically");
    }
})

Что ж

$(document.activeElement).closest("div").attr("id") == "editordiv"

не работает, если у вас есть два редактора div, и они оба отредактированы focus() , вы используете applyDeltas и пытаетесь их синхронизировать. Если я использую это неправильно, дайте мне знать. Но я почти уверен, что мне нужно другое решение.

Некоторое время назад была решена ошибка с отсутствием команды paste.
Проверка на наличие activeElement не сработает, и, как правило, не рекомендуется обращаться к dom из прослушивателя событий изменения, поскольку это снизит производительность редактора.

Используйте либо https://github.com/ajaxorg/ace/issues/1547#issuecomment -22257510
или https://github.com/ajaxorg/ace/issues/503#issuecomment-44525640

Могу ли я использовать # 1547 с applyDeltas? и с # 503, был ли groubis прав, когда говорил о копировании/вставке (потому что мне это тоже нужно?)

Я определенно мог пойти по поводу этой синхронизации неправильно, так что не исключайте этого, ха-ха :)

я только что попробовал

editor.on("change", function(e) {
  if (editor.curOp && editor.curOp.command.name) console.log("user change");
  else console.log("other change")
});

дословно, и когда я вставил, он сказал «другое изменение». У меня Сафари 9.0.1. Это поддерживаемая платформа?

Может быть, вы используете старую версию?
Подход, описанный в #1547, работает с applyDeltas.

Да, я так и думал, что вы имели в виду добавление объекта {silent:true} в applyDeltas(delta, {silent:true}) . Сейчас я обновлен до последней версии, и я предполагаю, что моя проблема в том, что, хотя событие изменения является синхронным, я, кажется, сталкиваюсь с проблемой параллелизма, когда «тихая» блокировка блокирует удаленные дельты, пока локальный пользователь печатает .

Извините, в примере ошибка.
Он должен сказать

silent = true
editor.session.setValue("some text");
silent = false

и в прослушивателе изменений

if (silent) return

так что молчание - это переменная в вашем модуле, а не то, что вы передаете асу.

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

Да, ошибка, с которой я столкнулся, не была связана с реальным API ace. Туз есть туз. Я столкнулся с проблемой параллелизма с несколькими (совместными) редакторами в одном документе, координируемом центральным сервером.

Эта проблема нетривиальна и требует так называемого оперативного преобразования; выходит далеко за рамки Ace. Для интересующихся: https://en.wikipedia.org/wiki/Operational_transformation.

Извините за неудобства, которые я причинил вашему замечательному проекту :/ ха-ха!

Была ли эта страница полезной?
0 / 5 - 0 рейтинги