javascripthtmlcsssocket.ioace-editor

ACE Editor's cursor position resetting to beginning of line


It's simple. When I type something in the editor, whatever I type is getting reversed because the cursor keeps resetting to the beginning of the line.

Say I type in this, it shows up like this:

:siht ekil pu swohs ti ,siht epyt yaS

and when I press enter, that becomes this:

siht semoceb taht ,retne sserp I nehw dna

:siht ekil pu swohs ti ,siht epyt yaS

Here's the code for my client side:

const editor = ace.edit("editor");
editor.setTheme("ace/theme/cobalt");
editor.getSession().setMode("ace/mode/javascript");

document.addEventListener("DOMContentLoaded", () => {
    const socket = io();
    const codingSpace = document.getElementById("codingSpace");
    const roomName = window.location.pathname.slice(1);
    let editorChangeInProgress = false;

    socket.emit("joinRoom", roomName);

    // Initialize ACE Editor
    const editor = ace.edit("editor");
    editor.setTheme("ace/theme/cobalt");
    editor.getSession().setMode("ace/mode/javascript");

    const codeRef = ref(db, "code");

    const fetchAndDisplayInitialData = async () => {
        try {
            const dataSnapshot = await get(child(codeRef, roomName));
            if (dataSnapshot.exists()) {
                const initialCode = dataSnapshot.val();
                codingSpace.value = initialCode;
                editor.setValue(initialCode, -1);
            }
        } catch (error) {
            console.error("Error fetching initial data:", error);
        }
    };
    fetchAndDisplayInitialData();

    const updateCode = (newCode) => {
        editorChangeInProgress = true;
        codingSpace.value = newCode;
        editor.setValue(newCode, -1);
        editorChangeInProgress = false;
        ace.edit("editor").moveCursorTo(-1, -1);
    };

    const onEditorChange = (event) => {
        if (!editorChangeInProgress) {
            const newCode = editor.getValue();
            updateCode(newCode);
            socket.emit("codeChange", { roomName, newCode });
            update(codeRef, { [roomName]: newCode });
        }
    };

    editor.getSession().on("change", onEditorChange);

    socket.on("codeChange", (newCode) => {
        if (!editorChangeInProgress) {
            updateCode(newCode);
        }
    });

    codingSpace.addEventListener("input", () => {
        const newCode = codingSpace.value;
        socket.emit("codeChange", { roomName, newCode });
        update(codeRef, { [roomName]: newCode });
    });
});

I've been trying to fix this from half an hour :(


Solution

  • editor.setValue() resets selection (and thus caret position) by default, so you'll need to account for that:

    var code = editor.getValue();
    var selection = editor.selection.toJSON();
    editor.setValue(code + "\nYeah");
    editor.selection.fromJSON(selection);
    

    May also have to save-restore session.getScrollLeft() / session.getScrollTop() and folds (session.getAllFolds()).

    And for collaborative programming you'll probably want to work with deltas (editor.commands.on("afterExec", handler)) rather than just syncing the editor contents - perhaps have a look around to see how other people usually do this?