Skip to content

Instantly share code, notes, and snippets.

@netj
Forked from alisey/scrollSelectionIntoView.js
Last active September 14, 2016 19:59
Show Gist options
  • Select an option

  • Save netj/ce30c8ad560b5554d296b1c29e50f16a to your computer and use it in GitHub Desktop.

Select an option

Save netj/ce30c8ad560b5554d296b1c29e50f16a to your computer and use it in GitHub Desktop.

Revisions

  1. netj revised this gist Sep 14, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion scrollSelectionIntoView.js
    Original file line number Diff line number Diff line change
    @@ -31,7 +31,7 @@ function scrollSelectionIntoView() {
    range = document.createRange();
    range.setStart(sel.focusNode, sel.focusOffset);

    if ($.browser.opera && range.startContainer.nodeType == 1) {
    if ($.browser && $.browser.opera && range.startContainer.nodeType == 1) {
    return false;
    }

  2. @alisey alisey created this gist Sep 18, 2012.
    79 changes: 79 additions & 0 deletions scrollSelectionIntoView.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,79 @@
    // Scroll to selection focus, but only if it's out of view. Align selection
    // focus with the top or bottom edge of its scroll-container. Return true
    // on success.
    // * there might be several nested scroll-containers, including window
    // * must not try to scroll overflow:hidden and overflow:visible elements
    // * no scrolling should happen if selection focus is visible
    // * selection is not necessarily collapsed
    // * range.getBoundingClientRect doesn't work for collapsed ranges
    // * Opera reports incorrect startOffset and endOffset for collapsed ranges
    // outside of text nodes (e.g. between 2 <br> elements), range.insertNode
    // doesn't work correctly in that case too.
    // * horizontal scroll is ignored

    function scrollSelectionIntoView() {
    var sel, range, marker, container, rect, top, bottom,
    containerTop, containerBottom, scroll;

    // IE8, IE9
    if (document.selection) {
    // scrolls only if needed
    document.selection.createRange().scrollIntoView();
    return true;
    }

    sel = window.getSelection();
    if (!sel.focusNode) {
    return false;
    }

    // collapse to focus point
    range = document.createRange();
    range.setStart(sel.focusNode, sel.focusOffset);

    if ($.browser.opera && range.startContainer.nodeType == 1) {
    return false;
    }

    // zero-width space
    marker = $('<span style="visibility: hidden">\u200B</span>')[0];
    range.insertNode(marker);
    container = marker;

    if (marker.scrollIntoViewIfNeeded) {
    marker.scrollIntoViewIfNeeded(true); // WebKit
    } else while (container != window) {
    container = container.parentNode || window;

    if (container === window) {
    containerTop = 0;
    containerBottom = $(container).height();
    } else if (
    container.scrollHeight > container.clientHeight &&
    /scroll|auto/.test($(container).css('overflow'))
    ) {
    rect = container.getBoundingClientRect();
    containerTop = rect.top;
    containerBottom = rect.bottom;
    } else {
    continue;
    }

    rect = marker.getBoundingClientRect();
    top = rect.top;
    bottom = rect.bottom;
    scroll = $(container).scrollTop();

    if (top < containerTop) {
    $(container).scrollTop(scroll + top - containerTop - 20);
    } else if (bottom > containerBottom) {
    $(container).scrollTop(scroll + bottom - containerBottom + 20);
    }
    }

    container = marker.parentNode;
    container.removeChild(marker);
    container.normalize();

    return true;
    }