Pregunta

Estoy intentando crear un menú de navegación que utiliza jQuery.Yo quería teclado que los usuarios puedan tener la misma experiencia que los usuarios de ratón, así que estoy duplicar la funcionalidad que se encuentra en mi hover() controlador de eventos en mi focus() y blur() los controladores de eventos.Por alguna razón, esto está causando notable retraso en el Firefox y el IE cuando el usuario hace clic en un enlace, lo cual no ocurre cuando el focus() y blur() el código es llevado a cabo.Cómo se puede ir sobre la aceleración de este proceso?He hecho tanto la optimización como mis limitados conocimientos de javascript permite, pero no he visto ninguna "speedup", así que estoy pensando que podría estar relacionado con cómo estos navegadores controlar los eventos.

Hay algo importante que me estoy vistas?O hay formas alternativas para conservar la accesibilidad para los usuarios de teclados mientras que el no uso de estos eventos?

        var statePad=0;

            function stateChanger(ourStatePad) {
                //the purpose of this function is to translate the current state of the menu into a different graphical representation of the menu state.
                var tempVar=ouStatePad;
                var tempArray = new Array;
                tempArray[5]=0;
                for (var x=0;x < 5;x++) {
                    tempArray[x]=tempVar % 10;
                    tempVar=(tempVar-tempArray[x])/10;
                }
                for (var arrayIndex=4;arrayIndex>=0;arrayIndex--) {
                   //Calculate the proper position in our CSS sprite, based on the each link's state, as well as it's neighbors'.
                    $(".block").eq(4 - arrayIndex)
                    .css(
                        "background-position",
                        //x-position
                        ((4 - arrayIndex) * -100) + "px " + 
                        //y-position
                        (tempArray[arrayIndex] + ((3 * tempArray[(arrayIndex) + 1]) * -30))) + "px";
                }
            }


        function hoverState(index,sign) {
            var placeholder=Math.pow(10,4-index);

            if (statePad != placeholder*2)
                statePad += (placeholder * sign);
            stateChanger(statePad);
}

        .click(function() {
            var index=$("#navbar a").index(this);
            statePad=Math.pow(10,(4-index))*2;
            stateChanger(statePad);
            $(".active").removeClass("active");
            $(this).addClass("active");
        })


        .hover(
            function () {
                hoverState($("#navbar a").index(this),1);
            },
            function () {
                hoverState($("#navbar a").index(this),-1);
            });

        $("#navbar a").focus( 
            function() {
                hoverState($("#navbar a").index(this),1);
            }
        );

        $("#navbar a").blur( 
            function() {
                hoverState($("#navbar a").index(this),-1);
            }
        );  
    });

Usted puede comprobar a cabo aquí

¿Fue útil?

Solución 2

Lo resuelto por accidente completa, tipo de.Me di cuenta de que mi problema no era realmente el gal, que era sólo un síntoma de un "conflicto de eventos".

El problema como lo que puedo decir es que focus() se desencadena por la tabulación a través de un enlace o un mousedown() en un elemento que puede recibir el foco.Por lo tanto, cada vez que un vínculo se hace clic en, se está poniendo el foco.Pero, una click() evento no está completa hasta que se suelta el ratón.Para el efecto de que estaba viendo en Firefox y IE fue resultado de un ligero retraso entre mousedown() y mouseup().He intentado simplemente cambiando el .click() manejo de eventos en mi código mousedown(), y ya que es tan solo un evento que estaba mirando hacia fuera para que me decidí a integrar eso en mi hoverState() función.Terminé con esto:

function hoverState(e) {
    var index = $(e.target.parentNode).prevAll().length;
    if (e.type == 'mousedown') {
        statePad=Math.pow(10,(4-index))*2;
        $(".active").removeClass('active');
        $("#"+ e.target.id).addClass('active');
}
else {
   var sign = (e.type === 'mouseenter' || 
                 e.type === 'focus')? 1 : -1;
 var placeholder=Math.pow(10,4-index);
    if (statePad != placeholder*2)
        statePad += (placeholder * sign);
 $('h1').text(statePad + " " + e.type);
    }
    stateChanger(statePad);
}

$("#navbar a").bind("mouseenter mouseleave focus blur mousedown", hoverState);

Sin embargo, esto causó algunos comportamientos extraños que la pata de la statePad variable.He vuelto a el código que Russ Cam proporciona mí, y comenzó a repensar las cosas.He probado en Opera, que yo no había hecho todavía, y funcionó bien.Lo he probado en Safari y Chrome, y se trabajó muy bien como de costumbre.Lo he probado en Firefox, tratando de conseguir una manija en lo que lo hace diferente, y...se fue a trabajar!

Miré hacia mi código, y resulta que yo todavía era la unión de la hoverState función a la mousedown() evento.No estoy exactamente seguro de por qué esto funciona, pero lo hace.Se corrige el problema en IE, así.Estrangular, hace un tema nuevo en Chrome, es tan pequeño que ni siquiera voy a preocuparse.

No creo que hubiera sido capaz de resolver esto sin Russ' ayuda, así que quiero darle las gracias de nuevo por toda su ayuda en esto.

Otros consejos

Hay un montón de alargamiento innecesario la cadena de alcance en su código, y una cadena de alcance más larga tardará más en resolverse. Podría acortarse a lo siguiente

$("navbar a").click(blah) 
             .hover(foo,bar)
             .focus(foo)
             .blur(bar);

Esperemos que esto resulte en un retraso menor. Si aún ve un retraso notable después de realizar este cambio, publique el código para las funciones del controlador de eventos, ya que también se pueden realizar mejoras en ese código.

EDIT:

En respuesta a su comentario, puede obtener el índice en la función utilizando la propiedad event del objeto target, que será el elemento sobre el que se generó el evento. Entonces, para obtener el índice de un elemento <a> en todos los elementos <ul> en el <li> con id barra de navegación , podemos usar el hecho de que cada event.target está contenido dentro de un < =>, por lo tanto, el índice en cada caso será el mismo. Con esto en mente, event.target.parentNode será el elemento <=> en el que se genera el evento click, <=> será el elemento padre de <=> que es el <=>

Para obtener el índice, puede usar

function hoverState(e) { 
    // get the index of the <a> element, which will be the same
    // as the index of the <li> that contains it in the <ul>
    //
    var index = $(e.target.parentNode).prevAll().length; 
    //
    // get the sign
    var sign = (e.type === 'mouseenter' || e.type === 'focus')? 1 : -1;
} 

Esto eliminará la necesidad de controladores de eventos de función anónimos que envuelvan hoverState.

Aquí hay un código revisado

var statePad=0;

// the purpose of this function is to translate 
// the current state of the menu into a different 
// graphical representation of the menu state.
//
function stateChanger(ourStatePad) {

    var tempVar=ourStatePad;
    var tempArray = [0,0,0,0,0];
    for (var x=0;x < 5;x++) {
        tempArray[x]=tempVar % 10;
        tempVar=(tempVar-tempArray[x])/10;
    }
    // Calculate the proper position in our CSS sprite, 
    // based on the each link's state, as well as it's neighbors'
    //
    var arrayIndex=4;
    while (arrayIndex--) {

        $("#rightpostheader div.block").eq(4 - arrayIndex)
            .css(
                "backgroundPosition",
                //x-position
                ((4 - arrayIndex) * -100) + "px " + 
                //y-position
                (tempArray[arrayIndex] + ((3 * tempArray[(arrayIndex) + 1]) * -30))) + "px";
    }

}


function hoverState(e) {
    var index = $(e.target.parentNode).prevAll().length;
    var sign = (e.type === 'mouseenter' || 
                e.type === 'focus')? 1 : -1;
    var placeholder=Math.pow(10,4-index);

    if (statePad != placeholder*2)
        statePad += (placeholder * sign);
    stateChanger(statePad);
}

$("#navbar a")
    .click(function(e) {
        // might be able to rework this into using hoverState too
        var $this = $(e.target);

        // get the index of the parent <li>
        var index= $this.parent().prevAll().length;

        statePad=Math.pow(10,(4-index))*2;

        stateChanger(statePad);

        $("#navbar a").removeClass('active');
        $this.addClass('active');
    })
    .bind("mouseenter mouseleave focus blur", hoverState);  
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top