Jquery Blur работает дважды - почему? - PullRequest
4 голосов
/ 14 мая 2011

Я работаю над созданием своего собственного журнала успеваемости, который работает как AJAX.В его основе таблица с редактируемыми ячейками.Пользователь щелкает ячейку, чтобы ввести оценку, а когда он щелкает ячейку, оценка отправляется в БД через AJAX.Пока все работает нормально, за исключением того, что я добавил возможность для пользователя нажимать Enter и заставить его действовать так, как будто пользователь щелкнул где-то еще, чтобы закрыть форму редактирования.

ПРОБЛЕМА заключается в том, что когда пользователь нажимает клавишу возврата вместо ввода, часть размытия запускается дважды, о чем свидетельствует всплывающее предупреждение дважды.Если они просто щелкают куда-то, это нормально.Мое понимание jbuery .blur () заключается в том, что если вы вызываете его без обратного вызова или аргументов, он действует как исполнитель и обрабатывает его так, как если бы выбранный элемент потерял фокус.

Бывает на IE8, Chrome и FF 4.0.1.Живая версия работает на мой тестовый сайт

Может кто-нибудь объяснить, почему он запускается дважды, когда я пытаюсь установить размытие, когда пользователь нажимает ввод?

ОБНОВЛЕНИЕ: Не могуопубликовать HTML, потому что на самом деле это просто таблица, а набор табличных тегов отсутствует в белом списке stackOverflow.(Я новичок здесь, так что, возможно, есть способ сделать это, но я не знаю этого.)

Кроме того, я решил немедленную проблему, изменив

                if(event.keyCode=='13')
            {
                $('#gradeUpdate').blur();
            }

на

                if(event.keyCode=='13')
            {
                $("#gradeUpdate").parent().focus();
                //$('#gradeUpdate').blur();
            }

но я все же хотел бы знать, почему оригинальная линия не просто заставляет #gradeUpdate размыться так, как я думал.

Все происходит внутри этой функции:

function clickableCell(){
$("td.assignmentCell").click(function(){  //if a td with an assignment class is clicked,
    if( clicked == 0)
    {
        clicked = 1;
        currentValue = $(this).text();//get the current value of the entered grade
        var passable = this;
alert("Test:  passable is: "+$(passable).text());
    //change content to be an editable input form element
        $(this).html("<input name='gradeUpdate' id='gradeUpdate' size=3 value='"+currentValue+"' type='text' />");
    //move the cursor to the new input and highlight the value for easy deletion    
        $('#gradeUpdate').focus().select();  
    //watch for keystrokes somewhere else and act appropriately 
        $(document).keyup(function(event){
        //if they hit Enter, treat it like they clicked somewhere else
            if(event.keyCode=='13')
            {
                $('#gradeUpdate').blur();
            }
        });

        $('#gradeUpdate').blur(function(passable){
        //reset the clicked counter
            clicked = 0;
        //check to see if the value is blank or hasn't changed
            var inputValue = $('#gradeUpdate').val();
        //////////////////////////////////////////////////////////////////////////////////////////
        //  Here we need to insert a REGEX check for the "exception" values created by the GDST
        //  and check for those values; anything else that's not a number will be disallowed
        //  and reset to "" so that it's caught in a later step.  For now I'm just checking for digits
        //////////////////////////////////////////////////////////////////////////////////////////
        if(!inputValue.match(/^\d+$/)) 
        { 
            alert ("we don't have a match!");
            inputValue = "";
        }
        ///////////////////////////////////////////////////////////////////////////////////////////
            if(currentValue == inputValue || inputValue =="")//hasn't changed or is blank
            {
                //DON'T run AJAX call
alert("Not a good value, reverting to old value!");
            //assign the original, unchanged value to the table
                $('#gradeUpdate').parent().text(currentValue) 
                $("#gradeUpdate").remove();//close out the input block
            //make it like they actually clicked on the element they did click on to lose focus
                $(this).click();
            }
            else //it's valid, send the ajax
            {
                //send AJAX call here
                //on success update the td
alert("We're all good--entering value!");
                $("#gradeUpdate").parent().text(inputValue);
                $("#gradeUpdate").remove();
            }
        });
    }//close of if clicked ==0
});

}

и вот полный HTML-код исходной страницы;на самом деле это просто таблица с некоторыми предварительно введенными значениями для тестирования.Следующим моим шагом будет создание таблицы на лету с использованием XML, возвращенного из запроса AJAX.

Ответы [ 4 ]

8 голосов
/ 16 марта 2012

Я думаю, вам нужно перейти с $('#gradeUpdate').blur() на $('#gradeUpdate')[0].blur(). Браузер примет размытие jQuery отличным от обычного размытия. Так что это будет срабатывать дважды.

1 голос
/ 14 августа 2012

Со мной происходило то же самое, строка $('input')[0].blur(); как-то исправила это, но я не понимаю, как это работает. Мой код:

$('h1 input').live('blur', function(){
    var text = $('h1 input').val();
    if(text == ''){
        alert('!');
        $('h1').html('<p>' + originalProjectName + '</p><span></span>');
        text = originalProjectName;
    }
    var id = document.location.hash.split('-')[1];
    $('h1').html('<p>' + text + '</p><span></span>');
    $.getJSON('json-project.php', { method: 'rename', id: id, name: text }, function(data) {
        var type = document.location.hash.split('-')[0];
        if(type == '#shoot'){
            $('#scroller-shoots ul li[data-id=' + id + ']').html(text); 
        }
        if(type =='#project'){
            $('#scroller-projects ul li[data-id=' + id + ']').html(text);
        }
    });
});
$('h1 input').live('keydown', function(event) {
    originalProjectName = $(this).val();      
    if ( event.which == 13 ) {
        $(this)[0].blur();
    }
});

Это не имеет смысла, поскольку $(this) должно относиться только к одному селектору, а не к нескольким. Кто-нибудь знает, почему это работает?

0 голосов
/ 10 марта 2014

Мне не удалось решить эту проблему с помощью предложенного решения, поскольку событие размытия на входе происходило до события размытия в окне (почему, я пока не совсем уверен). При этом я смог подписаться на этот пост и настроить его так, чтобы он определял, когда мышь пользователя покидает область окна, чтобы игнорировать событие размытия.

Пример кода:

var isTargetWindow = false;

function addEvent(obj, evt, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(evt, fn, false);
    }
    else if (obj.attachEvent) {
        obj.attachEvent("on" + evt, fn);
    }
}

var isTargetWindow = false;

addEvent(window,"load",function(e) {
    addEvent(window, "mouseout", function(e) {
        e = e ? e : window.event;
        var from = e.relatedTarget || e.toElement;
        if (!from || from.nodeName == "HTML") {
            // stop your drag event here
            // for now we can just use an alert
            isTargetWindow = true;
        }
        else {
            isTargetWindow = false;
        }
    });
});

$(document).on( 'blur', 'input', function( e ) {

    if( isTargetWindow ) {
        return false;
    }

    // ... do something here
}
0 голосов
/ 14 мая 2011

Каждый раз, когда вы нажимаете td.assignmentCell, вы привязываете события blur и keyup. Попробуйте связать их только один раз, если это имеет смысл, или используйте live или delegate для #gradeUpdate.

Обновите ваши вопросы с вашим HTML, и я смогу лучше понять, что вы делаете.

...