How to synchronize two scrollbars based on percentage?

Asked

Viewed 59 times

6

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

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>

  • 1

    @Sergio was kind enough to send a compact version, if he can’t post, I incorporate with the proper credits https://jsfiddle.net/7sczdko7/

1 answer

7


It was just a mathematical adjustment:

Of

 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>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.