I have elements which have nested li elements and i made a click function to get the value. Every time i click i am getting the same value again and again.
<script type="text/javascript">
$('.cat-select').on('click',function(){
$('.cat-list').css('display','block');
$('.sub-list').css('display','block');
});
$(document).on('click','.cat-list>li',function(){
var selectedVal = $(this).clone() //clone the element
.children() //select all the children
.remove() //remove all the children
.end() //again go back to selected element
.text(); //get the text of elemen
console.log(selectedVal);
$('.cat-select').text(selectedVal);
});
</script>
<div class="form-group">
<label for="input-placeholder" class="col-sm-2 control-label"></label>
<div class="col-sm-10">
<style type="text/css">
.cat-list, .sub-list{ display: none; }
</style>
<div class="cat-group">
<button class="cat-select" type="button">Select Category</button>
<ul class="cat-list">
<li class="have-child">Electronics
<ul class="sub-list">
<li class="have-child"> Mobiles & Tablets
<ul class="sub-list">
<li>Mobiles</li>
<li>Tablets</li>
<li class="have-child">Accessories</li>
<ul>
<li>Power Bank</li>
<li>Phone Cases</li>
</ul>
</ul>
</li>
<li class="have-child">Cameras
<ul class="sub-list">
<li>DSLRs</li>
<li>Drones</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
Every time i click i am getting the same value
The issue you see is because you only attach the event handler to the child of the .cat-list
through your use of the >
operator.
To solve this, remove that from the selector and call stopPropagation()
on the event to stop it bubbling up the DOM. Try this:
$(document).on('click', '.cat-list li', function(e) {
e.stopPropagation();
var selectedVal = $(this).clone().children().remove().end().text();
$('.cat-select').text(selectedVal);
})
$('.cat-select').on('click', function() { $('.cat-list, .sub-list').toggle(); }); $(document).on('click', '.cat-list li', function(e) { e.stopPropagation(); var selectedVal = $(this).clone().children().remove().end().text(); $('.cat-select').text(selectedVal); })
.cat-list, .sub-list { display: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script> <div class="form-group"> <label for="input-placeholder" class="col-sm-2 control-label"></label> <div class="col-sm-10"> <div class="cat-group"> <button class="cat-select" type="button">Select Category</button> <ul class="cat-list"> <li class="have-child">Electronics <ul class="sub-list"> <li class="have-child"> Mobiles & Tablets <ul class="sub-list"> <li>Mobiles</li> <li>Tablets</li> <li class="have-child">Accessories <ul> <li>Power Bank</li> <li>Phone Cases</li> </ul> </li> </ul> </li> <li class="have-child"> Cameras <ul class="sub-list"> <li>DSLRs</li> <li>Drones</li> </ul> </li> </ul> </li> </ul> </div> </div> </div>
Also note that I fixed the HTML in your 'Accessories' ul
as it was outside of the parent li
.
Event.stopPropagation()
The worst thing you can do (as suggested by answers here and around the web) is to use Event.stopPropagation()
.
Don't use Event.stopPropagation()
, well, unless you really know what you're doing .
An Application should be always aware of every event happening in it's context.
Imagine you build a popup, modal, or a custom select-box that needs to close if you click anywhere else in the page. Well, congratulations, a LI element just stopped you from doing so.
Event.target
insteadfunction myClickHandler(ev) {
if (ev.target !== this) return; // Ignore if non-this called the event
console.log( this.textContent );
}
Here's an example with your specific use-case:
const $cat = $('.cat-select'); $cat.on('click', function() { $('.cat-list, .sub-list').toggle(); }); $(document).on('click', '.cat-list li', function(ev) { if (ev.target !== this) return; // Ignore if non-this called the event const value = $(this).contents().filter((i, el) => el.nodeType == 3)[0].nodeValue; $cat.text(value); }); // Than, 3000 lines later... THANK YOU BECAUSE: $('body').on('click', function() { // Close a popup or something console.clear(); console.log(`YEY I registered an event! Thank you for not using Event.preventDefault()`); });
.cat-list, .sub-list { display: none; }
<div class="form-group"> <label for="input-placeholder" class="col-sm-2 control-label"></label> <div class="col-sm-10"> <div class="cat-group"> <button class="cat-select" type="button">Select Category</button> <ul class="cat-list"> <li class="have-child">Electronics <ul class="sub-list"> <li class="have-child"> Mobiles & Tablets <ul class="sub-list"> <li>Mobiles</li> <li>Tablets</li> <li class="have-child">Accessories</li> <ul> <li>Power Bank</li> <li>Phone Cases</li> </ul> </ul> </li> <li class="have-child">Cameras <ul class="sub-list"> <li>DSLRs</li> <li>Drones</li> </ul> </li> </ul> </li> </ul> </div> </div> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Get the clicked element based the event.target
property. Although you can avoid the clone by contents()
and filter()
methods which help to filter out text nodes.
$(document).on('click', 'li', function(e) {
// if target element is not `li` tag then get closest li tag
var selectedVal = (e.target.nodeType == 'LI' ? $(e.target) : $(e.target).closest('li'))
.contents() // get all children nodes
.filter(function() { // filter out text nodes
return this.nodeType === 3;
}).text(); // get text content
$('.cat-select').text(selectedVal);
})
$(document).on('click', 'li', function(e) { // if target element is not `li` tag then get closest li tag var selectedVal = (e.target.nodeType == 'LI' ? $(e.target) : $(e.target).closest('li')) .contents() // get all children nodes .filter(function() { // filter out text nodes return this.nodeType === 3; }).text(); // get text content $('.cat-select').text(selectedVal); })
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="form-group"> <label for="input-placeholder" class="col-sm-2 control-label"></label> <div class="col-sm-10"> <div class="cat-group"> <button class="cat-select" type="button"> Select Category</button> <ul class="cat-list"> <li class="have-child">Electronics <ul class="sub-list"> <li class="have-child">Mobiles & Tablets <ul class="sub-list"> <li>Mobiles</li> <li>Tablets</li> <li class="have-child">Accessories</li> <ul> <li>Power Bank</li> <li>Phone Cases</li> </ul> </ul> </li> <li class="have-child">Cameras <ul class="sub-list"> <li>DSLRs</li> <li>Drones</li> </ul> </li> </ul> </li> </ul> </div> </div>
i hope this one is helping u
$('.cat-select').each(function() {
$(this).on('click', function() {
$('.cat-list').css('display', 'block');
$('.sub-list').css('display', 'block');
});
});
$(document).on('click', function() {
$(this).each('.cat-list li', function() {
var selectedVal = $(this).clone() //clone the element
.children() //select all the children
.remove() //remove all the children
.end() //again go back to selected element
.text(); //get the text of elemen
console.log(selectedVal);
$('.cat-select').text(selectedVal);
});
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.