最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - jQuery: focusout triggering before onclick for Ajax suggestion - Stack Overflow

programmeradmin0浏览0评论

I have a webpage I'm building where I need to be able to select 1-9 members via a dropdown, which then provides that many input fields to enter their name. Each name field has a "suggestion" div below it where an ajax-fed member list is populated. Each item in that list has an "onclick='setMember(a, b, c)'" field associated with it. Once the input field loses focus we then validate (using ajax) that the input username returns exactly 1 database entry and set the field to that entry's text and an associated hidden memberId field to that one entry's id.

The problem is: when I click on the member name in the suggestion box the lose focus triggers and it attempts to validate a name which has multiple matches, thereby clearing it out. I do want it to clear on invalid, but I don't want it to clear before the onclick of the suggestion box name.

Example:

In the example above Paul Smith would populate fine if there was only one name in the suggestion list when it lost focus, but if I tried clicking on Raphael's name in the suggestion area (that is: clicking the grey div) it would wipe out the input field first.

Here is the javascript, trimmed for brevity:

function memberList() {
    var count = document.getElementById('numMembers').value;
    var current = document.getElementById('listMembers').childNodes.length;
    if(count >= current) {
  for(var i=current; i<=count; i++) {
    var memberForm = document.createElement('div');
    memberForm.setAttribute('id', 'member'+i);
    var memberInput = document.createElement('input');
    memberInput.setAttribute('name', 'memberName'+i);
    memberInput.setAttribute('id', 'memberName'+i);
    memberInput.setAttribute('type', 'text');
    memberInput.setAttribute('class', 'ajax-member-load');
    memberInput.setAttribute('value', '');
    memberForm.appendChild(memberInput);
    // two other fields (the ones next to the member name) removed for brevity

    document.getElementById('listMembers').appendChild(memberForm);

  }
}
else if(count < current) {
   for(var i=(current-1); i>count; i--) {
       document.getElementById('listMembers').removeChild(document.getElementById('listMembers').lastChild);
   }
}

jQuery('.ajax-member-load').each(function() {
var num = this.id.replace( /^\D+/g, '');

// Update suggestion list on key release
jQuery(this).keyup(function(event) {
    update(num);
});

// Check for only one suggestion and either populate it or clear it
jQuery(this).focusout(function(event) {
  var number = this.id.replace( /^\D+/g, '');
  memberCheck(number);
  jQuery('#member'+number+'suggestions').html("");
});
  });

}

    // Looks up suggestions according to the partially input member name
function update(memberNumber) {

  // AJAX code here, removed for brevity

  self.xmlHttpReq.onreadystatechange = function() {
    if (self.xmlHttpReq.readyState == 4) {
              document.getElementById('member'+memberNumber+'suggestions').innerHTML = self.xmlHttpReq.responseText;
    }
  }
} 

// Looks up the member by name, via ajax
// if exactly 1 match, it fills in the name and id
// otherwise the name es back blank and the id is 0
function memberCheck(number) {

   // AJAX code here, removed for brevity

    if (self.xmlHttpReq.readyState == 4) {
          var jsonResponse = JSON.parse(self.xmlHttpReq.responseText);
          jQuery("#member"+number+"id").val(jsonResponse.id);
          jQuery('#memberName'+number).val(jsonResponse.name);
    }
  }
}
function setMember(memberId, name, listNumber) {
   jQuery("#memberName"+listNumber).val(name);
   jQuery("#member"+listNumber+"id").val(memberId);
   jQuery("#member"+listNumber+"suggestions").html("");
}

// Generate members form
memberList();

The suggestion divs (which are now being deleted before their onclicks and trigger) simply look like this:

<div onclick='setMember(123, "Raphael Jordan", 2)'>Raphael Jordan</div>
<div onclick='setMember(450, "Chris Raptson", 2)'>Chris Raptson</div>

Does anyone have any clue how I can solve this priority problem? I'm sure I can't be the first one with this issue, but I can't figure out what to search for to find similar questions.

Thank you!

I have a webpage I'm building where I need to be able to select 1-9 members via a dropdown, which then provides that many input fields to enter their name. Each name field has a "suggestion" div below it where an ajax-fed member list is populated. Each item in that list has an "onclick='setMember(a, b, c)'" field associated with it. Once the input field loses focus we then validate (using ajax) that the input username returns exactly 1 database entry and set the field to that entry's text and an associated hidden memberId field to that one entry's id.

The problem is: when I click on the member name in the suggestion box the lose focus triggers and it attempts to validate a name which has multiple matches, thereby clearing it out. I do want it to clear on invalid, but I don't want it to clear before the onclick of the suggestion box name.

Example:

In the example above Paul Smith would populate fine if there was only one name in the suggestion list when it lost focus, but if I tried clicking on Raphael's name in the suggestion area (that is: clicking the grey div) it would wipe out the input field first.

Here is the javascript, trimmed for brevity:

function memberList() {
    var count = document.getElementById('numMembers').value;
    var current = document.getElementById('listMembers').childNodes.length;
    if(count >= current) {
  for(var i=current; i<=count; i++) {
    var memberForm = document.createElement('div');
    memberForm.setAttribute('id', 'member'+i);
    var memberInput = document.createElement('input');
    memberInput.setAttribute('name', 'memberName'+i);
    memberInput.setAttribute('id', 'memberName'+i);
    memberInput.setAttribute('type', 'text');
    memberInput.setAttribute('class', 'ajax-member-load');
    memberInput.setAttribute('value', '');
    memberForm.appendChild(memberInput);
    // two other fields (the ones next to the member name) removed for brevity

    document.getElementById('listMembers').appendChild(memberForm);

  }
}
else if(count < current) {
   for(var i=(current-1); i>count; i--) {
       document.getElementById('listMembers').removeChild(document.getElementById('listMembers').lastChild);
   }
}

jQuery('.ajax-member-load').each(function() {
var num = this.id.replace( /^\D+/g, '');

// Update suggestion list on key release
jQuery(this).keyup(function(event) {
    update(num);
});

// Check for only one suggestion and either populate it or clear it
jQuery(this).focusout(function(event) {
  var number = this.id.replace( /^\D+/g, '');
  memberCheck(number);
  jQuery('#member'+number+'suggestions').html("");
});
  });

}

    // Looks up suggestions according to the partially input member name
function update(memberNumber) {

  // AJAX code here, removed for brevity

  self.xmlHttpReq.onreadystatechange = function() {
    if (self.xmlHttpReq.readyState == 4) {
              document.getElementById('member'+memberNumber+'suggestions').innerHTML = self.xmlHttpReq.responseText;
    }
  }
} 

// Looks up the member by name, via ajax
// if exactly 1 match, it fills in the name and id
// otherwise the name es back blank and the id is 0
function memberCheck(number) {

   // AJAX code here, removed for brevity

    if (self.xmlHttpReq.readyState == 4) {
          var jsonResponse = JSON.parse(self.xmlHttpReq.responseText);
          jQuery("#member"+number+"id").val(jsonResponse.id);
          jQuery('#memberName'+number).val(jsonResponse.name);
    }
  }
}
function setMember(memberId, name, listNumber) {
   jQuery("#memberName"+listNumber).val(name);
   jQuery("#member"+listNumber+"id").val(memberId);
   jQuery("#member"+listNumber+"suggestions").html("");
}

// Generate members form
memberList();

The suggestion divs (which are now being deleted before their onclicks and trigger) simply look like this:

<div onclick='setMember(123, "Raphael Jordan", 2)'>Raphael Jordan</div>
<div onclick='setMember(450, "Chris Raptson", 2)'>Chris Raptson</div>

Does anyone have any clue how I can solve this priority problem? I'm sure I can't be the first one with this issue, but I can't figure out what to search for to find similar questions.

Thank you!

Share Improve this question asked Nov 18, 2013 at 17:32 BingBing 3,1837 gold badges49 silver badges85 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 8

If you use mousedown instead of click on the suggestions binding, it will occur before the blur of the input. JSFiddle.

<input type="text" />
<a href="#">Click</a>

$('input').on('blur', function(e) {
   console.log(e);
});

$('a').on('mousedown', function(e) {
   console.log(e); 
});

Or more specifically to your case:

<div onmousedown='setMember(123, "Raphael Jordan", 2)'>Raphael Jordan</div>

using onmousedown instead of onclick will call focusout event but in onmousedown event handler you can use event.preventDefault() to avoid loosing focus. This will be useful for password fields where you dont want to loose focus on input field on click of Eye icon to show/hide password

发布评论

评论列表(0)

  1. 暂无评论