Вопрос

Я пытаюсь создать навигационное меню, которое использует некоторый jQuery.Я хотел, чтобы пользователи клавиатуры могли иметь тот же опыт, что и пользователи мыши, поэтому я дублирую функциональность, найденную в моем hover() обработчик событий в моем focus() и blur() обработчики событий.По какой-то причине это вызывает заметную задержку в Firefox и IE, когда пользователь нажимает на ссылку, чего не происходит, когда focus() и blur() код удален.Как я могу ускорить это?Я провел столько оптимизации, сколько позволяли мои ограниченные знания javascript, но я не видел никакого "ускорения", поэтому я думаю, что это может быть связано с тем, как эти браузеры обрабатывают события.

Есть ли что-то важное, что я упускаю из виду?Или есть какие-либо альтернативные способы сохранить доступность для пользователей клавиатуры, не используя эти события?

        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);
            }
        );  
    });

Вы можете это проверить здесь

Это было полезно?

Решение 2

Я решил это совершенно случайно, вроде. Я понял, что моя проблема на самом деле не была задержкой, это был только симптом & Конфликта событий &.

Насколько я могу судить, проблема в том, что focus() вызывается либо переходом по ссылке, либо mousedown() на элементе, который может получить фокус. Таким образом, каждый раз, когда на ссылку нажимают, она получает фокус. Но событие click() не завершено, пока мышь не будет отпущена. Таким образом, эффект, который я видел в Firefox и IE, был результатом небольшой задержки между mouseup() и .click(). Я попытался просто поменять местами обработку событий <=> в моем коде на <=>, и, поскольку это только одно событие, которое я ожидал, я решил интегрировать это в свою функцию hoverState (). Я закончил с этим:

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);

Однако это вызвало странное поведение, приводившее к порче переменной statePad. Я вернулся к коду, который предоставил Расс Кэм, и начал переосмысливать вещи. Я попробовал это в Опере, что я еще не сделал, и это работало отлично. Я попробовал это в Safari и Chrome, и они работали нормально, как обычно. Я попробовал это в Firefox, просто пытаясь понять, что отличает его, и ... это работало!

Я оглянулся на свой код, и оказалось, что я все еще связывал функцию hoverState с событием <=>. Я не совсем уверен, почему это работает, но это работает. Это исправляет проблему и в IE. Задушить, это вызывает новую проблему в Chrome, это настолько незначительно, что я даже не собираюсь беспокоиться.

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

Другие советы

Там много ненужного удлинение цепочки прицелов в вашем коде и более длинная цепочка областей видимости будут разрешаться дольше.Его можно было бы сократить до следующего

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

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

Редактировать:

В ответ на ваш комментарий вы могли бы получить индекс в функции, используя переданный в event объект target свойство, которое будет элементом, на котором было вызвано событие.Итак, чтобы получить индекс <a> элемент во всех <a> элементы в <ul> с идентификатором панель навигации, мы можем использовать тот факт , что каждый <a> содержится в <li>, следовательно, индекс в каждом конкретном случае будет одинаковым.С этим и есть разум, event.target будет самым <a> элемент, на котором вызывается событие click, event.target.parentNode будет родительским элементом <a> который является <li>

Чтобы получить индекс, вы могли бы использовать

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;
} 

Это устранит необходимость в анонимных обработчиках событий функций, обертывающих hoverState.

Вот несколько переработанных кодов

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);  
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top