2010-04-22 13 views
8

Tengo un problema raro con la barra de desplazamiento. Estoy construyendo una página que usa jQuery y PHP para cargar dinámicamente imágenes en un DIV secuencialmente. Este DIV es una altura fija pero usa una barra de desplazamiento para su ancho variable. El problema es que la barra de desplazamiento no se restablece después de una actualización dinámica del DIV. Por lo tanto, cuando el usuario se desplaza y luego actualiza con nuevo contenido, la posición de la barra de desplazamiento permanece constante en lugar de restablecerse a la izquierda.¿Cómo restablecer la posición persistente de la barra de desplazamiento después de la actualización div en FF3?

Esto parece suceder solo en FF3. La barra de desplazamiento se restablece perfectamente en Chrome, Safari e IE8.

Para cada actualización, el DIV está oculto, vaciado, dimensionado con CSS, y luego se adjunta secuencialmente con imágenes.

He intentado reajustar white-space: normal antes de la nowrap, jugando con overflow, y también de jQuery scrollLeft en vano. Todavía se comporta de forma extraña en FF3 y solo en FF3.

Haga clic en una miniatura, mueva la barra de desplazamiento y luego haga clic en otro pulgar.

¡Gracias por cualquier ayuda!

+1

Guau, eso es muy extraño. Mi mejor opción sería simplemente agarrar el elemento y configurarlo scrollTop y scrollLeft a cero, así no debería haber problemas. por cierto, buen sitio! Me encanta el control hash. – Tom

+0

Sí, intenté hacer ScrollLeft antes. Podría volver a visitar eso de nuevo. El plugin de hashchange es genial, ¿eh ?. ¡Debería donar dinero de cerveza a Ben Alman porque me ahorró tener que escribir todo ese material de votación! – rcon

Respuesta

5

bien, después de contemplar las sugerencias de David M, lo he descubierto. Como #interiors es un hijo de #content, también se estaba ocultando. Así que tuve que show primero, configurar scrollLeft luego hide de nuevo. Un poco kludgy, pero lo que sea que funcione ...

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

En cuanto a los datos en caché en FF3, todavía no lo tengo claro. Salvo que uno para un día de lluvia ...

Gracias

0

cuando escribo esto en la consola interactiva Firebug:

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

parece a restablecer las barras de desplazamiento correctamente. El elemento también puede necesitar ser mostrado con un display de block antes de configurar scrollLeft pero no estoy seguro - Creo que cuando traté de hacer esto, Firefox restauró los últimos valores cuando los elementos con overflow: auto cambiaron de oculto a mostrado.

EDITAR: Hay un par de cosas que podría intentar obligar a Firefox a restablecer los valores. En primer lugar, se puede quitar y volver a agregar el elemento de "contenido" cuando los cambios de hash:

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

En segundo lugar, se podría restablecer los valores scrollLeft/scrollTop a 0 antes de usar $('#interiors').empty() o $('#interiors').hide() por lo que doesn' t guardar los valores.

+0

Hice más análisis en Firebug. Lo que está sucediendo es que al actualizar DIV, el valor de scrollLeft se restablece a cero hasta que necesite una barra de desplazamiento. Si se necesita la barra de desplazamiento, restaura el valor anterior (lo verá alternar). Si la barra de desplazamiento no es necesaria, el valor permanece en cero, y las actualizaciones posteriores utilizarán este nuevo valor almacenado de cero, ya sea que se necesite o no una barra de desplazamiento. Ahora quiero encontrar una manera de cero o bloquear el valor anterior. – rcon

+0

@rcon: He agregado algunas sugerencias más para restablecer la barra de desplazamiento, responda si todavía tiene problemas – cryo

+0

M: Pensé que hacer un 'remove()' también funcionaría, pero desafortunadamente no es así. Uno pensaría que eliminar un elemento del DOM borraría los datos persistentes. Es una buena idea, así que voy a tratar de jugar con 'clone()' a continuación. En cuanto a la otra sugerencia, ver mi respuesta a la respuesta de Már Örlygsson. Gracias por las ideas! – rcon

0

He editado el javascript para restablecer los valores scrollLeft/scrollTop antes de ocultar/borrar/configurar el HTML. Puse todas esas operaciones en una sola función para tratar de descubrir qué estaba pasando.

He probado esto en Firefox y parece solucionar los problemas de desplazamiento, pero no he probado otros navegadores. Debería funcionar sin embargo.

Parece que tenía razón en mi otra respuesta que es necesario restablecer los valores scrollLeft y scrollTop en Firefox, mientras que el elemento con un desbordamiento de auto se muestra con una pantalla de block embargo, ya que parece restaurar la vieja valores cuando se muestra independientemente de si los valores de desplazamiento cambiado mientras oculta:

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í, tienes toda la razón. El elemento debe ser 'display: block'. Tu función funciona, pero solo mientras '# content' no esté oculta. Ver mi respuesta ¡Gracias por tu ayuda! – rcon

0

Sólo se encontró con el mismo problema y lo resolvió mediante el establecimiento de una tiempo de espera DESPUÉS el #interiors se ha vuelto visible en la página.

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