How to synchronize two scroll bars based on percentage?

5

I have a <DIV> with overflow and a <TEXTAREA> , the problem is that the element that will be synchronized ends up rolling over than expected, instead of following a percentage basis .

What I've done so far:

function syncScroll(from, to)
{
    var sf = from.scrollHeight - from.clientHeight,
        st = to.scrollHeight - to.clientHeight;

    if (sf < 1) {
        return;
    }

    var p = (sf / 100) * from.scrollTop;

    to.scrollTop = (st / 100) * p;
}


window.onload = function() {
    var currentScrollEvt, timer;

    var editor  = document.querySelector(".editor");
    var preview = document.querySelector(".preview");

    preview.innerHTML = editor.value;

    editor.onscroll = function() {
        if (currentScrollEvt === "preview") {
             return;
        }

        clearTimeout(timer);

        currentScrollEvt = "editor";

        syncScroll(editor, preview);

        timer = setTimeout(function() {
            currentScrollEvt = null;
        }, 200);
    };

    preview.onscroll = function() {
        if (currentScrollEvt === "editor") {
             return;
        }

        clearTimeout(timer);

        currentScrollEvt = "preview";

        syncScroll(preview, editor);

        timer = setTimeout(function() {
            currentScrollEvt = null;
        }, 200);
    };
};
html, body {
    padding: 0;
    margin: 0;
    height: 100%;
}

* {
    box-sizing: content-box;
}

body {
    display: flex;
}

.editor, .preview {
    flex: 1;
}

.preview {
    background-color: #f00;
    overflow: auto;
    float: right;
}
<textarea class="editor">
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
</textarea>

<div class="preview"></div>
    
asked by anonymous 13.08.2016 / 22:18

1 answer

7

It was just a mathematical fit:

From

 var p = (sf / 100) * from.scrollTop;
 to.scrollTop = (st / 100) * p;

To

var p = from.scrollTop / sf;
to.scrollTop = st * p;

function syncScroll(from, to)
{
    var sf = from.scrollHeight - from.clientHeight,
        st = to.scrollHeight - to.clientHeight;

    if (sf < 1) {
        return;
    }

    var p = from.scrollTop / sf;
    to.scrollTop = st * p;
}


window.onload = function() {
    var currentScrollEvt, timer;

    var editor  = document.querySelector(".editor");
    var preview = document.querySelector(".preview");

    preview.innerHTML = editor.value;

    editor.onscroll = function() {
        if (currentScrollEvt === "preview") {
             return;
        }

        clearTimeout(timer);

        currentScrollEvt = "editor";

        syncScroll(editor, preview);

        timer = setTimeout(function() {
            currentScrollEvt = null;
        }, 200);
    };

    preview.onscroll = function() {
        if (currentScrollEvt === "editor") {
             return;
        }

        clearTimeout(timer);

        currentScrollEvt = "preview";

        syncScroll(preview, editor);

        timer = setTimeout(function() {
            currentScrollEvt = null;
        }, 200);
    };
};
html, body {
    padding: 0;
    margin: 0;
    height: 100%;
}

* {
    box-sizing: content-box;
}

body {
    display: flex;
}

.editor, .preview {
    flex: 1;
}

.preview {
    background-color: #f00;
    overflow: auto;
    float: right;
}
<textarea class="editor">
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
a <br>
</textarea>

<div class="preview"></div>
    
13.08.2016 / 22:27