Как сбросить постоянную позицию полосы прокрутки после обновления div в FF3? - PullRequest
9 голосов
/ 23 апреля 2010

У меня странная проблема с полосой прокрутки. Я строю страницу, которая использует jQuery и PHP для динамической загрузки изображений в DIV последовательно. Этот DIV является фиксированной высотой, но использует полосу прокрутки для своей переменной ширины. Проблема в том, что полоса прокрутки не сбрасывается после динамического обновления DIV. Поэтому, когда пользователь прокручивает, а затем обновляет новое содержимое, положение полосы прокрутки остается постоянным, а не сбрасывается обратно влево.

Это, кажется, происходит только в FF3. Полоса прокрутки прекрасно сбрасывается в Chrome, Safari и IE8.

Для каждого обновления DIV скрывается, очищается, измеряется с помощью CSS, а затем последовательно добавляется с изображениями.

Я пытался сбросить white-space: normal до nowrap, играя с overflow, а также с scrollLeft в jQuery безрезультатно. Он по-прежнему ведет себя странно в FF3 и только в FF3.

Нажмите на миниатюру, переместите полосу прокрутки, затем щелкните другой большой палец.

Спасибо за любую помощь!

Ответы [ 5 ]

5 голосов
/ 27 апреля 2010

Хорошо, после размышления над предложениями Дэвида М. я понял это.Поскольку #interiors является потомком #content, оно также скрывалось.Поэтому мне сначала пришлось show установить scrollLeft, а затем hide снова.Немного клёвый, но что бы ни работало ...

$('#landing, #interiors, #caption').empty();
$('#content').show()
$('#interiors').scrollLeft(0);
$('#interiors, #caption').hide();

Что касается кэшированных данных в FF3, я до сих пор не уверен в этом.Сохрани это на черный день ...

Спасибо

3 голосов
/ 16 января 2015

Только для справки, вот соответствующая ошибка Firefox:

https://bugzilla.mozilla.org/show_bug.cgi?id=706792

0 голосов
/ 23 сентября 2016

Только что столкнулся с той же проблемой и решил ее, установив тайм-аут ПОСЛЕ #interiors стало видимым на странице.

$("#interiors").show(function(){
    setTimeout(function(){$(this).scrollLeft(0);},10);});
});
0 голосов
/ 27 апреля 2010

Я отредактировал JavaScript, чтобы сбросить значения scrollLeft / scrollTop, прежде чем скрывать / очищать / настраивать HTML. Я поместил все эти операции в одну функцию, чтобы попытаться выяснить, что происходит.

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

Кажется, я был прав в своем другом ответе, что вам нужно сбросить значения scrollLeft и scrollTop в Firefox, в то время как элемент с переполнением auto отображается с отображением block, хотя, как кажется, что он восстанавливает старые значения при отображении независимо от того, изменились ли значения прокрутки, когда они скрыты:

function setInteriors(html, hide) {
    var i = $('#interiors');

    // Reset the scrollbar positions BEFORE clearing/setting the HTML
    i.scrollLeft(0);
    i.scrollTop(0);

    // Set the HTML if provided, otherwise empty
    if (html) i.html(html);
    else i.empty();

    // Hide the element if hide is `true`
    if (hide) i.hide();
}

function showContent(nav) {
    if($.browser.safari) // webkit browsers
    { 
        bodyelement = $("body")
    }
    else
    { 
        bodyelement = $("html, body")
    }
    bodyelement.animate({ scrollTop: 0 }, 300);

    setInteriors(null, true);
    $('#caption').hide();
    $('#caption').empty();
    $('#landing').empty();

    // Detect document window size and use appropriate image heigh images

    if ($(window).height() < 832 ) // size of the document window, not browser window
    {                              // threshold for 600px images + 5 caption lines
        var imageHeight = 500;
    }
    else
    {
        var imageHeight = 600;
    }

    // Show #content so we can show/hide #interiors and #caption individually

    $('#content').show();
    if ((nav == "about") || (nav == "contact"))
    {
        setInteriors(null); // for fast back/forward button mashing

        switch(nav)
        {
            case "about":
                setInteriors($('#hidden-about').html()); // Load from hidden div
                break;
            case "contact":
                setInteriors($('#hidden-contact').html());
                break;
        }
        $('#interiors').css('height', '100%');  // Dimensions for "about" and "contact"
        $('#interiors').css('width', '645px');
        $('#interiors').css('white-space', 'normal');
        $('#interiors').fadeIn(200);
    }
    // TO DO: Maybe separate #interiors to two classes for dynamic changes?
    else
    {
        switch(imageHeight)
        {
            case 500:
                $('#interiors').css('height', '520px');  // Dimensions for gallery
                                                         // Extra 20px for scrollbar
                break;
            case 600:
                $('#interiors').css('height', '620px');
                break;
        }
        $('#interiors').css('width', '100%');
        setInteriors(null); // for fast back/forward button mashing
        $('#interiors').show();
        nav = (location.hash).substring(1); // for fast back/forward button mashing
        $('#caption').html('<P class="caption">' + $('#hidden-' + nav).html() + '</P>'); // load hidden captions
        $('#caption').fadeIn(300);  // show caption before images

        getImages = "http://www.shadowshapes.com/uttwerk/getImages.php?id=" + nav + "&height=" + imageHeight;
        $.getJSON(getImages, function(json) {
            var max = json.length;
            if(max > 0)
            {
                loadImage(0, max, nav);
            }

            function loadImage(index, max, nav) {
                if ((location.hash).substring(1) == nav) // until hash changes, load current nav
                {
                    if(index < max)
                    {
                        var newimg = new Image();
                        $(newimg).load(function () {
                            if ((location.hash).substring(1) == nav) // after current image loads
                            {                                        // continue if no hashchange
                                $('#interiors').append(this);
                                $('#interiors').css('white-space', 'nowrap');
                                $(this).hide();
                                if (max - index > 1)  // add space after each image except last one
                                {
                                    $(this).css('margin-right', '20px');
                                }
                                $(this).css('vertical-align', 'top');
                                $(this).fadeIn(200, function() {
                                        loadImage(index + 1, max, nav);
                                });
                            }
                        }).attr('src', json[index]);
                    }
                }
            }
        });
    }
}

function arrangeStars() {
    $('img.star').each(function () {
        thumbposition = $(this).siblings('a.nav').children('img').position();
        $(this).css("top", (thumbposition.top - 9));
        $(this).css("left", (thumbposition.left - 9));
    });
}

function placeStar(nav) {
    // clear all stars on hash change

    if ($('div.thumb').children('img').hasClass("visiblestar")) {
        $('div.thumb').children('img').removeClass("visiblestar").addClass("hiddenstar");
    }
    // attach star to selected thumbnail

    var test = $('div#_' + nav);
    if ($(test).children('img').hasClass("hiddenstar")) {
        $(test).children('img').removeClass("hiddenstar").addClass("visiblestar");
    }
}

$(document).ready(function() {

    //$.imgpreload(['', ''], {each: null, all:null});  

    // bind hover event for empty/contact/about hash only

    $(arrangeStars());  // positions stars in the corner of each thumbnail

    $('img.thumb, img.thumbwithborder').hover(
        function () {  
            var nav = (location.hash).substring(1);
            if ((nav == '') || (nav == "about") || (nav =="contact")) {
                nav = $(this).parent().parent().attr("id");
                $('div.thumb#' + nav).children('img').removeClass('hiddenstar').addClass('visiblestar');
            }
        },
        function () {  
            var nav = (location.hash).substring(1);
            if ((nav == '') || (nav == "about") || (nav =="contact")) {
                nav = $(this).parent().parent().attr("id");
                $('div.thumb#' + nav).children('img').removeClass('visiblestar').addClass('hiddenstar');
            }
        }
    );

    // hash change event triggers all the navigation and content switching

    jQuery.hashchangeDelay = 50;

    $(function() { 
        $(window).bind('hashchange', function() {
            var nav = (location.hash).substring(1);
            if (nav != '')
            {
                placeStar(nav);
                $('#content').fadeOut(200, function() {
                    showContent(nav);
                });
            }
        });
    })

    if (location.hash != '')
    {
        $(window).trigger('hashchange');
    }

    // load landing content

    $(function() {
        $('#content').hide(function() {
            var landingdiv = $(document.createElement('div')).attr({id: 'landing'});
            landingdiv.html($('#hidden-landing').html());
            landingdiv.clone().appendTo('#interiors');
            $(this).fadeIn(200);
            });
    });
});
0 голосов
/ 25 апреля 2010

Когда я набираю это в интерактивной консоли firebug:

var e = $('#interiors')[0]
e.scrollLeft = 0
e.scrollTop = 0

, кажется, правильно сбрасываются полосы прокрутки.Элемент также может потребоваться показать с display из block перед установкой scrollLeft, но я не уверен - я думаю, что когда я пытался это сделать, Firefox восстановил последние значения, когда элементы с overflow: auto изменено со скрытого на показанное.

РЕДАКТИРОВАТЬ: Есть несколько вещей, которые вы можете попытаться заставить Firefox сбросить значения.Во-первых, вы можете удалить, а затем повторно добавить элемент «content» при изменении хэша:

var e = $('#interiors')[0]
var p = e.parentNode
p.removeChild(e)
p.insertBefore(e, p.firstChild) // insert again before the caption

Во-вторых, вы можете сбросить значения scrollLeft / scrollTop до 0 доиспользуя $('#interiors').empty() или $('#interiors').hide(), чтобы не сохранять значения.

...