Jquery blur running twice--why?
I'm working on creating my own gradebook that works as AJAX. At its base a table with editable cells. User clicks on a cell to enter the grade, and when they click off the cell the grade is sent to the DB via AJAX. So far it's working fine, except that I've added in the ability for the user to hit Enter and have it act as if the user clicked somewhere else to close the edit form.
THE PROBLEM IS that when the user hits return instead of enter, the blur portion runs twice as evidenced by the alert popping up twice. If they just click somewhere, it's fine. My understanding of jQuery's .blur() is that if you call it without a callback or arguments it acts as a doer and treats it as if the selected element lost focus.
Happens on IE8, Chrome, and FF 4.0.1. Live version running at my test site
Can someone please explain why it's running twice when I try to set the blur when user hits enter?
UPDATE: Can't post the HTML, because it's really just a table and the table tag set isn't on the stackOverflow white list. (I'm new here, so maybe there's a way to do it, but I don't know it.)
Also, I solved the immediate issue by changing
if(event.keyCode=='13')
{
$('#gradeUpdate').blur();
}
to
if(event.keyCode=='13')
{
$("#gradeUpdate").parent().focus();
//$('#gradeUpdate').blur();
}
but I'd still like to know why the original line isn't just making #gradeUpdate to blur like I thought it would.
Everything happens inside this function:
function clickableCell(){
$("td.assignmentCell").click(function(){ //if a td with an assignment class is clicked,
if( cli开发者_StackOverflowcked == 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
});
}
and here's the full HTML of the original page; it's really just a table with some pre-entered values to use for testing. My next step is to build the table on the fly with XML returned from an AJAX request.
I think you need to change from $('#gradeUpdate').blur()
to $('#gradeUpdate')[0].blur()
. The browser will take the jQuery blur different from the normal blur. So it will be triggered twice.
I had the same thing happening to me, the $('input')[0].blur();
line somehow fixed it, but i do not understand how this works. My code is:
$('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();
}
});
It doesnt make sense, as $(this)
should only refer to one selector, not multiple. Does anyone know why this works?
Everytime you click on td.assignmentCell
you're rebinding the blur
and keyup
events. Try bind them only once if it makes sense or using live
or delegate
for #gradeUpdate
.
Update your questions with your HTML and I can get a better idea what you're doing.
I was not able to get this resolved with the proposed solution as the blur event on the input was occurring before the blur event on the window (why, I'm not quite sure yet). That being said, I was able to follow this post, and adjusted it to detect when the user's mouse leaves the window area to ignore the blur event.
Example code:
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
}
精彩评论