2010-04-22 12 views
8

Sto vivendo un bizzarro problema della barra di scorrimento. Sto costruendo una pagina che usa jQuery e PHP per caricare dinamicamente le immagini in un DIV in sequenza. Questo DIV è un'altezza fissa ma utilizza una barra di scorrimento per la sua larghezza variabile. Il problema è che la barra di scorrimento non si ripristina dopo un aggiornamento dinamico del DIV. Pertanto, quando l'utente scorre e si aggiorna con nuovi contenuti, la posizione della barra di scorrimento rimane persistente invece di reimpostarsi a sinistra.Come resettare la posizione della barra di scorrimento permanente dopo il div refresh in FF3?

Questo sembra accadere solo in FF3. La barra di scorrimento si reimposta perfettamente in Chrome, Safari e IE8.

Per ogni aggiornamento, il DIV è nascosto, svuotato, ridimensionato con CSS, quindi aggiunto in sequenza con le immagini.

Ho provato a resettare white-space: normal prima della nowrap, giocare con overflow, e anche jQuery di scrollLeft inutilmente. Si comporta ancora in modo strano in FF3 e solo in FF3.

Fare clic su una miniatura, spostare la barra di scorrimento quindi fare clic su un altro pollice.

Grazie per qualsiasi aiuto!

+1

Wow, è molto strano. La mia ipotesi migliore sarebbe semplicemente afferrare l'elemento e impostarlo come scrollTop e scrollLeft a zero, in questo modo non ci dovrebbero essere storie. btw, bel sito! Adoro il controllo hash. – Tom

+0

Sì, ho provato a fare ScrollLeft prima. Potrei rivisitarlo di nuovo. Il plugin di hashchange è ottimo, eh ?. Dovrei donare un po 'di soldi per la birra a Ben Alman perché mi ha salvato dal dover scrivere tutto quel materiale elettorale! – rcon

risposta

5

OK, dopo aver contemplato i suggerimenti di David M, ho capito. Dal momento che #interiors è un figlio di #content è stato anche nascosto. Quindi ho dovuto prima impostare show, impostare scrollLeft quindi hide di nuovo. Un po 'sfacciato, ma qualunque cosa funzioni ...

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

Per quanto riguarda i dati memorizzati nella cache in FF3, io non sono ancora chiari su questo. Salvo che uno per un giorno di pioggia ...

Grazie

0

Quando scrivo questo nella console interattiva Firebug:

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

sembra ripristinare correttamente le barre di scorrimento. L'elemento può anche essere mostrato con unblock prima di impostare scrollLeft ma non sono sicuro: penso che quando ho provato a farlo, Firefox ripristinava gli ultimi valori quando gli elementi con overflow: auto venivano modificati da nascosti a mostrati.

MODIFICA: Ci sono un paio di cose che potresti provare a forzare Firefox a ripristinare i valori. Prima di tutto, è possibile rimuovere e quindi aggiungere nuovamente l'elemento "contenuto" quando cambia hash:

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

In secondo luogo, si potrebbe ripristinare i valori scrollLeft/scrollTop a 0 prima di utilizzare $('#interiors').empty() o $('#interiors').hide() in modo che doesn' t salvare i valori.

+0

Ho fatto più analisi in Firebug. Quello che sta succedendo è che con l'aggiornamento DIV, il valore scrollLeft si azzera fino a quando non ha bisogno di una barra di scorrimento. Se la barra di scorrimento è necessaria, ripristina il valore precedente (lo vedrai alternativamente). Se la barra di scorrimento non è necessaria, il valore rimane a zero e gli aggiornamenti successivi utilizzeranno questo nuovo valore memorizzato pari o meno a una barra di scorrimento. Ora voglio capire un modo per azzerare o bloccare il vecchio valore. – rcon

+0

@rcon: Ho aggiunto altri suggerimenti per reimpostare la barra di scorrimento, per favore rispondi se hai ancora problemi – cryo

+0

M: Pensavo che un 'remove()' avrebbe funzionato anche, ma sfortunatamente no. Si potrebbe pensare che la rimozione di un elemento dal DOM cancellerebbe i dati persistenti. È una buona idea, quindi proverò a giocare con 'clone()'. Per quanto riguarda l'altro suggerimento, vedere la mia risposta alla risposta di Már Örlygsson. Grazie per le idee! – rcon

0

Ho modificato il javascript per reimpostare i valori scrollLeft/scrollTop prima di nascondere/cancellare/impostare l'HTML. Ho inserito tutte queste operazioni in una singola funzione per cercare di capire cosa stava succedendo.

Ho provato questo in Firefox e sembra risolvere i problemi di scorrimento, ma non ho testato altri browser. Dovrebbe funzionare comunque.

Sembra che avevo ragione nel mio altra risposta che è necessario ripristinare i valori scrollLeft e scrollTop in Firefox, mentre l'elemento con un overflow di auto è mostrato con un display di block anche se, come sembra ripristinare il vecchio valori quando mostrato indipendentemente dal fatto che i valori di scorrimento modificati mentre nascosto:

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

@Davin M: Sì, hai assolutamente ragione. L'elemento dovrebbe essere 'display: block'. La tua funzione funziona, ma solo finchè '# content' non è nascosta. Vedi la mia risposta. Grazie per l'aiuto! – rcon

0

appena incontrato lo stesso problema e risolto impostando un timeout DOPO lo #interiors è diventato visibile sulla pagina.

$("#interiors").show(function(){ 
    setTimeout(function(){$(this).scrollLeft(0);},10);}); 
}); 
Problemi correlati