Как перейти к элементу в переполненном Div?

У меня есть 20 элементов списка внутри div, которые могут показывать только 5 за раз. Каков хороший способ прокрутки к элементу № 10, а затем к элементу № 20? Я знаю высоту всех предметов.

Плагин scrollTo делает это, но его источник не очень легко понять, не вникая в него. Я не хочу использовать этот плагин.

Скажем, у меня есть функция, которая принимает 2 элемента $parentDiv, $innerListItem, ни $innerListItem.offset().top, ни $innerListItem.positon().top не дает мне правильный scrollTop для $parentDiv.

Ответ 1

$innerListItem.position().top фактически относится к .scrollTop() его первого позиционированного предка. Таким образом, способ вычисления правильного значения $parentDiv.scrollTop() заключается в том, чтобы убедиться, что $parentDiv позиционируется. Если он еще не имеет явного position, используйте position: relative. Элементы $innerListItem и все его предки до $parentDiv не должны иметь явной позиции. Теперь вы можете перейти к $innerListItem с помощью:

// Scroll to the top
$parentDiv.scrollTop($parentDiv.scrollTop() + $innerListItem.position().top);

// Scroll to the center
$parentDiv.scrollTop($parentDiv.scrollTop() + $innerListItem.position().top
    - $parentDiv.height()/2 + $innerListItem.height()/2);

Ответ 2

Это мой собственный плагин (позиционирует элемент в верхней части списка. Специально для overflow-y : auto. Может не работать с overflow-x!):

ПРИМЕЧАНИЕ: elem - это селектор HTML элемента, к которому будет прокручиваться страница. Все, что поддерживается jQuery, например: #myid, div.myclass, $(jquery object), [dom object] и т.д.

jQuery.fn.scrollTo = function(elem, speed) { 
    $(this).animate({
        scrollTop:  $(this).scrollTop() - $(this).offset().top + $(elem).offset().top 
    }, speed == undefined ? 1000 : speed); 
    return this; 
};

Если вам не нужна анимация, используйте:

jQuery.fn.scrollTo = function(elem) { 
    $(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem).offset().top); 
    return this; 
};

Как использовать:

$("#overflow_div").scrollTo("#innerItem");
$("#overflow_div").scrollTo("#innerItem", 2000); //custom animation speed 

Примечание: #innerItem может находиться где угодно внутри #overflow_div. Это действительно не должно быть прямым ребенком.

Протестировано в Firefox (23) и Chrome (28).

Если вы хотите прокрутить всю страницу, отметьте этот вопрос.

Ответ 3

Я скорректировал ответ Гленна Мосса, чтобы учесть тот факт, что div overflow не может быть в верхней части страницы.

parentDiv.scrollTop(parentDiv.scrollTop() + (innerListItem.position().top - parentDiv.position().top) - (parentDiv.height()/2) + (innerListItem.height()/2)  )

Я использовал это в приложении Google Maps с помощью адаптивного шаблона. При разрешении > 800 пикселей список находился в левой части карты. По разрешению < 800 этот список был ниже карты.

Ответ 4

Вышеуказанные ответы будут позиционировать внутренний элемент в верхней части элемента переполнения, даже если он отображается внутри элемента переполнения. Я не хотел этого, поэтому я изменил его, чтобы не изменять позицию прокрутки, если элемент находится в поле зрения.

jQuery.fn.scrollTo = function(elem, speed) {
    var $this = jQuery(this);
    var $this_top = $this.offset().top;
    var $this_bottom = $this_top + $this.height();
    var $elem = jQuery(elem);
    var $elem_top = $elem.offset().top;
    var $elem_bottom = $elem_top + $elem.height();

    if ($elem_top > $this_top && $elem_bottom < $this_bottom) {
        // in view so don't do anything
        return;
    }
    var new_scroll_top;
    if ($elem_top < $this_top) {
        new_scroll_top = {scrollTop: $this.scrollTop() - $this_top + $elem_top};
    } else {
        new_scroll_top = {scrollTop: $elem_bottom - $this_bottom + $this.scrollTop()};
    }
    $this.animate(new_scroll_top, speed === undefined ? 100 : speed);
    return this;
};

Ответ 5

Играя с ним в течение очень долгого времени, это то, что я придумал:

    jQuery.fn.scrollTo = function (elem) {
        var b = $(elem);
        this.scrollTop(b.position().top + b.height() - this.height());
    };

и я называю это так

$("#basketListGridHolder").scrollTo('tr[data-uid="' + basketID + '"]');