Ace: O evento 'change' é acionado ao definir o Ace programaticamente

Criado em 14 nov. 2011  ·  12Comentários  ·  Fonte: ajaxorg/ace

Para código como este:

editor.getSession().on('change', function() {
// Faça alguma coisa
});

Eu esperaria que esse evento fosse acionado apenas quando houver uma interação do usuário. No entanto, descobri que ele é acionado quando defino o valor do editor programaticamente, o que não é consistente com algo como, digamos, o DOM. (Se você adicionar um ouvinte de evento 'change' para um campo de entrada, ele não será acionado se definirmos o valor com JavaScript.)

Isso pode ser corrigido e existe uma solução alternativa ou um evento diferente que é acionado quando o valor do editor é atualizado, mas não programaticamente?
@gissues :{"order":33.540372670807756,"status":"backlog"}

Comentários muito úteis

use o método descrito em https://github.com/ajaxorg/ace/issues/1547#issuecomment -22257510 ou

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

Todos 12 comentários

Mesma razão pela qual eu larguei o CodeMirror para o ACE. Mas o código do ACE é muito mais fácil de ler. Eu fiz um patch para corrigir um pouco isso. O evento change ainda é acionado, mas adicionei uma propriedade booleana ao objeto de dados: userTyped. Será verdadeiro se o usuário digitar ou colar texto no editor. False se tiver sido inserido programaticamente. Isso funciona para o meu caso de uso específico no Chrome.

Isso é para o arquivo ace-uncompressed.js da versão 0.2.0: http://dl.dropbox.com/u/310281/ace-patch.txt

não acho que haja uma boa maneira de separar as alterações 'programáticas' e do usuário (por exemplo, a qual tipo pertence o texto inserido pelo widget de preenchimento automático?)
e adicionar userTyped adiciona muita contabilidade em todo o lugar

se você quiser apenas eventos de entrada de texto, você pode adicionar o ouvinte de eventos dom "input" ao editor.container
ou se você quiser filtrar apenas sua própria chamada setValue, adicione um sinalizador (semelhante a $blockScrolling no editor.js)
funcionará desde que o evento 'change' seja síncrono

use o método descrito em https://github.com/ajaxorg/ace/issues/1547#issuecomment -22257510 ou

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

O snippet postado por nightwing não funciona como deveria enquanto copiar e colar é aplicado. Outra solução que pode resolver o problema é algo assim, por exemplo, com 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");
    }
})

Nós vamos

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

não funciona se você tem dois editor divs e ambos são focus() ed, você está usando applyDeltas e está tentando sincronizá-los. Se eu estiver usando isso de forma errada, me avise. Mas tenho certeza que preciso de uma solução diferente.

O bug da pasta não ter comando foi resolvido há algum tempo.
A verificação de activeElement não funcionará e geralmente é uma má ideia acessar o dom a partir do ouvinte de eventos de mudança, pois isso prejudicará o desempenho do editor.

Use https://github.com/ajaxorg/ace/issues/1547#issuecomment -22257510
ou https://github.com/ajaxorg/ace/issues/503#issuecomment -44525640

Posso usar # 1547 com applyDeltas? e com #503, o groubis estava correto ao falar sobre copiar/colar (porque eu preciso disso também?)

Eu definitivamente poderia estar fazendo essa sincronização da maneira errada também - então não descarte isso ainda haha ​​:)

acabei de tentar

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

literalmente e quando colei, disse "outra mudança". Estou no Safari 9.0.1. Essa é uma plataforma suportada?

Talvez você esteja usando a versão antiga?
A abordagem descrita em #1547 funciona com applyDeltas.

Sim, então eu pensei que você quis dizer adicionar o objeto {silent:true} a applyDeltas(delta, {silent:true}) . Estou atualizado para a versão mais recente agora e acho que meu problema é que, embora o evento de alteração seja síncrono - parece que estou enfrentando um problema de simultaneidade em que o bloqueio "silencioso" bloqueará deltas remotos enquanto o usuário local está digitando .

Desculpe, houve um erro no exemplo.
Deve dizer

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

e em mudança de ouvinte

if (silent) return

tão silencioso é uma variável em seu módulo, não algo que você passa para ace.

Observe que o uso de applyDeltas não é suficiente para a sincronização, pois você precisará alterar os deltas para levar em conta que o documento ao qual você está aplicando é provavelmente diferente do documento para o qual eles foram criados.

Sim, o bug que eu estava enfrentando não estava relacionado à API real do ace. Ace is ace - eu estava enfrentando um problema de simultaneidade com vários editores (colaborativos) no mesmo documento, coordenados por um servidor central.

Esse problema não é trivial, exigindo algo chamado transformação operacional; em si muito além do escopo de Ace. Para os interessados: https://en.wikipedia.org/wiki/Operational_transformation.

Desculpe por qualquer inconveniente que causei em seu grande projeto :/ haha!

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

dimroc picture dimroc  ·  6Comentários

aslushnikov picture aslushnikov  ·  4Comentários

mafar picture mafar  ·  4Comentários

akosyakov picture akosyakov  ·  3Comentários

christianbs picture christianbs  ·  3Comentários