How to get data attributes of the clicked element on focusout - javascript

As the title says, I'd like to know if there is a way to get the data attributes of the element being clicked on during a focusout event.
My page produces search results in a small div on the side when the user types into the search input.
The problem is that when the focus is lost from the input, I want the search results to disappear.
I wrote the following code to accomplish this.
$('#chat-search').focusout(function(){
$('#chat-search').val(""); //Search input is cleared
$('.search-results').hide(); //The search results div is hidden
$('.people').show(); // Shows the previous div that was taken up by the search results
});
The problem is, I need to get information from the clicked div contained within the search-results class. The div that contains the data has the search-person class and there are many of them within the search-results div.
$('body').on('click', '.search-person', function(){
var userId = $(this).attr("data-id");
console.log(userId);
$('#chat-search').addClass('center-text');
$('#chat-search').val("");
$('.search-results').hide();
$('.people').show();
});
The search-person click function does not fire because the focusout event has hidden the element that was clicked. Focusout always appears to trigger before the on click event.
I tried to fire a normal on click event so that when the user clicks on anything that is not the search results or the input, the same code is executed as in the method above. This workaround is not perfect though, as it does not trigger if the search input loses focus because the user pressed tab.
$('body').on('click', function(e){
if ($(e.target).is($('#chat-search'))){ // If the search input is selected
$('#chat-search').removeClass('center-text');
$('.search-results').val("");
$('.people').hide();
$('search-results').show();
}
else if (!($(e.target).is($('.search-person')))){
// If the selected element is neither the search input nor the search result
$('#chat-search').addClass('center-text');
$('#chat-search').val("");
$('.search-results').hide();
$('.people').show();
}
});
Is there any way to find out the data attributes of the clicked element on focusout when the elements are going to be hidden when the input loses focus?
The HTML looks like this
<div class="search-container">
<input id="chat-search" class="chat-search center-text" placeholder="Search Users">
</div>
<div class="user-container scrollbar">
<ul class="people">
</ul>
<ul class="search-results">
</ul>
</div>
And within the search results ul, results with this HTML are generated through an ajax request.
<li class="search-person" data-id="someId">
<div class="search-left">
<img class="search-image" src="someurl">
</div>
<div class="search-right">
<div class="search-name">
Text here
</div>
</div>
</li>

I managed to solve the problem by setting a timeout for the focusout event, so that the click event could fire before the search results disappeared.
If anyone has this issue in the future, here is how I solved it.
$('#chat-search').focusout(function(){
setTimeout(function(){
console.log("focus out!");
$('#chat-search').addClass('center-text');
$('#chat-search').val("");
$('.search-results').hide();
$('.people').show();
}, 300)
});

Related

Uncaught TypeError: document.querySelector(...).click is not a function on automated process

Expected Behaviour: I am adding the value from a select element to a 3rd party API input element using the select element's onchange event. Once the text value has been added to the input element, the search button must be clicked to fully automate the process.
Returned Behaviour: Although the text value can be seen in the input, once it gets focus, it clears the text. When the text is visible and the search button is clicked, nothing happens. When I add the text value manually to the input and then click search it works fine. Not too sure what to do to make sure the text remains in the input.
Code for my select and the input as follow -
function vehicle_vin() {
var use_vehicle_vin = document.getElementById('get_vehicle_make');
use_vehicle_vin = use_vehicle_vin.options[use_vehicle_vin.selectedIndex].value;
var add_vehicle_vin = document.getElementById('id-vin-frame-search');
add_vehicle_vin.value = use_vehicle_vin;
alert(add_vehicle_vin.value);
//This works fine, but please see my notes above, when I put focus on the input, my value dissapears...
//I have tried, as per various search results the following QuerySelector, no luck in the search button being clicked.
//document.querySelector('.CLOYw6ixbVCoWy9pu904a ._2DcnCzqTJKrTWusHYHyHEf').click();
//I then changed to the svg element, the same error was returned...
var x_vin = document.querySelector('._15YY4Hl-2b6wr1smId9ZlA').click();
//I also tried to do a setTimeout, also did not work, then added the below, this returns nothing -.
if (x_vin && x_vin.length) {
alert("All true, click...");
setTimeout(() => { x_vin[0].click(); }, 750);
alert("clicked");
} else {
alert("not clicked");
}
}
<select id="get_vehicle_make" name="get_vehicle_make" title="Select a vehicle from your current car park. This V.I.N. will be added to the Search Input and will automatically load your search." onchange="vehicle_vin();">
<option value="" selected >Select Saved Vehicle</option>
<option value = "123456asdfgh09876" >Kia, Sportage, 2. CRDi</option>
</select>
<!--3rd party Api input and search button-->
<input type="text" id="id-vin-frame-search" name="vin-frame-search" placeholder="VIN or FRAME" class="_2UbmnxPVuhV1aqBHdE1oDO">
<button type="button" class="CLOYw6ixbVCoWy9pu904a _2DcnCzqTJKrTWusHYHyHEf">
<span class="_24-MeE_aY0KDledQMmmJAn">
<svg width="16" class="_15YY4Hl-2b6wr1smId9ZlA">
<use xlink:href="#search"></use>
</svg>
</span>
</button>
As above, I have tried many things with no success and will really appreciate any help available, javascript is not my strong point...
querySelector returns single element, to get multiple elements use
querySelectorAll
As you are trying to access single and first element, then you can use querySelector.
So the x_vin will contain element directly (not nodelist)
So you are trying to click element programmatically (From Javascript), Then you have .click() function
Just wrapped the click function in timeout (e.g., below)
setTimeout(() => {
console.log(document.querySelector('._15YY4Hl-2b6wr1smId9ZlA'));
document.querySelector('._15YY4Hl-2b6wr1smId9ZlA').click();
}, 1000) //1 second delay
Update
Hey I just found that svg does not have click function (I thought
every element does). Solution is to click parent element
programmatically, In your case either click span or button

Select using "this" keyword using document.on(..) - Jquery

My html code ( which is fetched from a json file after the page is loaded ):
<div class="fooditem">
<select class="quan">
<option value="0">0</option>
</select>
</div>
My javascript/jquery code :
$(document).on("click", ".fooditem", function() {
$(this).find('.quan').click();
});
I want to to click the select option tag when i click the div.
I found that the this keyword, here, is representing the document not the particular class.
So how should I go about doing it?
Here is the link
First Problem:
You are getting an infinite loop by listening to click but then generating a click on a descendant element...
The only solution to that is:
Move the child element outside of the element catching the click.
Note: You cannot block the click handler of the select or it will stop working.
As an alternative you can however do one of the following:
Set focus on the select element
Change the value of the select element
Generate a change event on the select element (as if the element was chosen)
but you cannot get the select to simply pop open and select the item.
Examples below:
1) Set focus
$(document).on("click", ".fooditem", function(e) {
$(this).find('.quan').focus();
});
2) Change the selected value
$(document).on("click", ".fooditem", function(e) {
$(this).find('.quan').val(0); // or whatever value
});
3) Generate a change event on the select element
$(document).on("click", ".fooditem", function(e) {
$(this).find('.quan').trigger('change');
});
note: This can be done with or without a prior value change.
Note: You have said in comment "i just want the drop down to open and select the value when i click on div", but this will not happen. A click event will not trigger opening of a select. See this example which has the recursion avoided (the elements are not nested): jsfiddle.net/TrueBlueAussie/zgub3838/7
You are binding your onclick event to the document. Try changing your jQuery snippet to this:
$(".fooditem").on("click", function(e) {
e.preventDefault();
$(this).find('.quan').click();
});

jQuery click event does not update ':last' when i add a new element that should become the new ":last"

So i am having a small issue,
I am working on a small effect on jquery that works this way.
The user is provided with one input button.
as soon as he types something into the input field, a new input is added below it.
Here is the HTML
<div class="container">
<div class="row">
<div class="col-md-4 data">
<input type="text" class="form-control" placehoder="some text"/>
</div>
</div>
<span><i class="fa fa-plus"></i></span>
</div>
Here is the jquery code
$(document).ready(function()
{
var input_button = '<div class="col-md-4 data"><input type="text" class="form-control" placeholder="some text"/></div>';
var last = 'div.data input[type="text"]';
$('div.data input[type="text"]:last').on("keyup",function(e)
{
value = $(this).val().trim();
if(value.length != 0)
{
$('.row').append(input_button);
}
});
});
Therefore, i use the $(div.data input[type="text"]:last) selector and the keyup event.
However, in my own thinking, when i Add a new input button, it should automatically become the ":last" input field. right?
But this is not the case. The last input field is, according to how the code is working, the first input field that originally existed?
Basically the first original input button is considered the "last" button even when more are added by the keyup event.
So my question is, how do i make the newly added input field (added using jquery) the last input field on the next keyup event?
The problem is that you bind to elements that are searched only once, not to a dynamic selector.
You should use
$('div.data').on("keyup", 'input[type="text"]:last', function(e)
so that the 'input[type="text"]:last' selector is checked each time there's a keyup event in a descendant of an element of $('div.data').
As your question isn't clear, in case you also dynamically add the div.data element, then you should do
$('.container').on("keyup", 'div.data input[type="text"]:last', function(e)
To read more about event delegation in jQuery, you can check this page.
When you dynamically create an element you have to select a parent element that is not being dynamically created then use the on function to trigger a function on an event.
So in your case you have to select a parent that is not being dynamically created which is .row and use the on function as follows:
$('.row').on("keyup", 'input[type="text"]:last', function (e)
http://jsfiddle.net/55SNt/
As the content are dynamically added on the fly , the event handler defined in your question points to the static field generated on page load. Instead you should do :
$(document).on("keyup", 'div.data input[type="text"]:last', function(e)
{
value = $(this).val().trim();
if(value.length != 0)
{
$('.row').append(input_button);
}
});
here is the example.
See More about Event Delegation.
To understand what's going on, you have to consider what jQuery is doing:
//Your code:
$('div.data input[type="text"]:last').on("keyup", function(e) {
//...
});
It looks like one thing is happening there, but there are actually two:
First you wrap the last element that matches div.data input[type="text"] in a jQuery object,
Then you add a handler to it.
Once $('div.data input[type="text"]:last') runs, the element it contains isn't going to change. It's already been found. The event handler is operating on that specific element, not the position it occupies.
To fix this, you have to tell jQuery to bind the handler dynamically every time the event fires. Fortunately, the on method is clever about that, and gives you the option to do it differently:
$(document).on("keyup", 'div.data input[type="text"]:last', function(e) {
//...
});
This will search the entire document for 'div.data input[type="text"]:last' before firing the event handler.

get Attribute of Hovered element that displayed menu

I have a menu that is displayed when a user hovers over an anchor tag with a certain class. The same menu is always displayed, but the anchor tags have a different "accNum" attribute. I want to get the value of the accNum attribute from the "parent" element that displayed the menu and append it to the click event of one of the menu items. Something like;
Actions
Actions
Actions
<div id="ActionsMenu" style="display:none;">
Show Account
</div>
Whichever 'ActionLink' is the one hovered over to display the menu, i want to take that AccNum value and create the onClick event of "ShowAccountValues" something like
onClick="showAccountValues('AccNum value of parent');"
any help would be great. Also, I assume I have to bind this to the document.ready() function for 'ActionLink' which makes sense, but i figured if i could get any of it through this that would be great.
Thank you
Firstly use jQuery to hook up your events, secondly accnum isn't a valid attribute, so use a data-* attribute like this:
Actions
Actions
Actions
<div id="ActionsMenu" style="display:none;">
Show Account
</div>
Then you can update the data attribute of the #showAccountValues link on hover of each a element:
$('.actionLink').on({
click: function(e) {
e.preventDefault();
$('#ActionsMenu').show();
},
mouseover: function() {
$('#showAccountValues').data('accnum', $(this).data('accnum'));
}
});
Then on the click of the a element in #ActionsMenu you can get the accnum:
$('#showAccountValues').click(function(e) {
e.preventDefault();
showAccountValues($(this).data('accnum'));
});
Example fiddle

Issue with jQuery :not selector

I have a search icon that when hovered over reveals an input text search box. I'm using jQuery to add a class to the input to reveal the text box when the search icon is hovered over. That is working fine.
The next function is that if the user decides not to click in the search box and elsewhere on the page, the search box goes away. That's working fine too.
The only remaining issue is that if the user clicks in the search box, it also goes away which I don't want.
My HTML:
<input type="text" class="form-text text-hidden" title="Enter the terms you wish to search for." value="" size="15" id="edit-search-block-form-1" name="search_block_form" maxlength="128">
<input type="image" src="http://d3j5vwomefv46c.cloudfront.net/photos/large/802431483.png?1377197793" class="form-submit search-hover" alt="Search" id="edit-submit">
My jQuery:
$(".search-hover").hover(function () {
$('.text-hidden').addClass('hover');
});
// Now remove the class in case of a false start or the user decides to do something else.
$("body:not(.text-hidden)").click(function(){
//alert('The body click is working!!!');
$('.form-text.text-hidden').removeClass('hover');
});
Note that I'm attempting to use the :not selector to indicate to only remove the hover class if clicked anywhere but the search box but it's not working.
I've got a fiddle here
Try
jQuery(function(){
$(".search-hover").hover(function () {
$('.text-hidden').addClass('hover');
});
// Now remove the class in case of a false start or the user decides to do something else.
$("body").click(function(e){
//alert('The body click is working!!!');
if($(e.target).closest('.text-hidden').length == 0)
$('.form-text.text-hidden').removeClass('hover');
});
})
Demo: Fiddle
The problem is that when you click the input, the body's click event still arises.
There's a simple solution. Just stop the event's propagation when the input's being clicked.
jsFiddle Demo
$(".form-text.text-hidden").click(function(e) {
e.stopPropagation();
});
P.S - Notice that I've removed the :not selector from the JS. It has become unnecessary.

Categories

Resources