For code like this:
editor.getSession().on('change', function() {
// Do something
});
I would expect this event to only fire when there's a user interaction. However, I've found that it fires when I set the value of the editor programmatically, which is not consistent with something like, say, the DOM. (If you add a 'change' event listener for an input field, it will not fire if we set the value with JavaScript.)
Can this be fixed, and is there a workaround or a different event that fires when the value of the editor has updated, but not programmatically?
@gissues:{"order":33.540372670807756,"status":"backlog"}
Same reason why I dropped CodeMirror for ACE. But ACE's code is a lot easier to read. I made a patch to somewhat fix this. The change event is still fired, but I added a boolean property to the data object: userTyped. Will be true if the user typed or pasted text into the editor. False if it was programmatically entered. This works for my specific use case in Chrome.
This is for the ace-uncompressed.js file from 0.2.0: http://dl.dropbox.com/u/310281/ace-patch.txt
i don't think there is a good way of separating 'programmatical' and user changes (e.g. to which type belongs text entered by autocomplete widget?)
and adding userTyped
adds lot's of bookkeeping all over the place
if you want only text input events you can add dom "input" event listener to editor.container
or if you want to filter out only you your own setValue call add a flag (similar to $blockScrolling in editor.js)
it will work since 'change' event is synchronous
either use method described in https://github.com/ajaxorg/ace/issues/1547#issuecomment-22257510 or
editor.on("change", function(e) {
if (editor.curOp && editor.curOp.command.name) console.log("user change");
else console.log("other change")
})
The snippet posted by nightwing does not work as it should while copy-paste is applied. Another solution that may solve the issue is something like that e.g with 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");
}
})
Well
$(document.activeElement).closest("div").attr("id") == "editordiv"
doesn't work if you have two editor divs and they are both focus()
ed, you're using applyDeltas and you're trying to sync them. If I'm using this wrongly, let me know. But I'm pretty sure I need a different solution.
The bug with paste not having a command have been solved some time ago.
Checking for activeElement won't work, and it's generally a bad idea to access dom from change event listener, since it will degrade editor performance.
Use either https://github.com/ajaxorg/ace/issues/1547#issuecomment-22257510
or https://github.com/ajaxorg/ace/issues/503#issuecomment-44525640
Can I use #1547 with applyDeltas though? and with #503, was groubis correct when talking about copy/paste (because I need that too?)
I could definitely be going about this syncing thing the wrong way, as well - so don't rule that out yet haha :)
I just tried
editor.on("change", function(e) {
if (editor.curOp && editor.curOp.command.name) console.log("user change");
else console.log("other change")
});
verbatim and when I pasted, it said "other change". I'm on Safari 9.0.1. Is that a supported platform?
Maybe you are using old version?
Approach described in #1547 works with applyDeltas.
Yep so I though you meant adding the {silent:true}
object to applyDeltas(delta, {silent:true})
. I am updated to the latest version now, and I guess my problem is that even though the change event is synchronous - I seem to be running into a concurrency issue where the "silent" lock will lock out remote deltas while the local user is typing.
Sorry there was an error in the example.
It should say
silent = true
editor.session.setValue("some text");
silent = false
and in change listener
if (silent) return
so silent is a variable in your module, not something you pass to ace.
Note that using applyDeltas is not enough for syncing, as you'll need to change deltas to take account that document to which you applying is most likely different from the document for which they were created.
Yes, the bug I was experiencing was unrelated to the actual API of ace. Ace is ace - I was experiencing a concurrency issue with multiple (collaborative) editors in the same document, coordinated by a central server.
That problem is non-trivial, requiring something called operational transformation; itself well beyond the scope of Ace. For those interested: https://en.wikipedia.org/wiki/Operational_transformation.
Sorry for any inconvenience I've caused on your great project :/ haha!
Most helpful comment
either use method described in https://github.com/ajaxorg/ace/issues/1547#issuecomment-22257510 or