Jquery get text of unorder list line items - javascript

I'm trying to get the text value of a list item in an unordered list when the items is clicked on.
I've added an event listener and am logging the results to the console before I go any further.
When I selected by class I received only one line item, but it didn't matter which link you clicked it showed the same link text. I've tried using .eq(), this, and a few other methods but either way I either return all 4 elements or no elements
Here is my fiddle.
HTML:
<div id="mapSelections">
<ul>
<li>Jump to State : </li>
<li id="Conn" >Connecticut |</li>
<li id="Maine">Maine |</li>
<li id="Mass">Massachusetts |</li>
<li id="Rh">Rhode Island |</li>
<li id="Home">Home</li>
</ul>
And here is the listener:
var link = document.getElementById('mapSelections');
link.addEventListener('click', function () {
var text = $("li:eq()", this).text();
console.log(text);
});

Brief
What you are trying to do is called event delegation. You want to listen to the event from the parent <div> for events bubbling up from the child <a> tags.
You can delegate the event by using jQuery's .on() function:
var link = document.getElementById('mapSelections');
$(link).on('click', 'a', function () {
var text = $(this).text();
//console.log(text);
alert(text);
});
Here is updated fiddle.
Explanation
Basically there are two options for what you want:
Multiple Listeners
$("#mapSelections a").on('click', function () {
var text = $(this).text();
alert(text);
});
This works fine but you are binding event listeners to several elements (one listener to each <a> tag). There is a bit of overhead for each one so it's not the most performant option available to you.
Event Delegation
$("#mapSelections").on('click', 'a', function () {
var text = $(this).text();
alert(text);
});
The reason (IMO) this is best is because you are saving your application some resources. You are binding only one listener to the parent $("#mapSelections"), and that element is then waiting for events that bubble up only from child <a> tags.

Like this? http://jsfiddle.net/q8nzR/1/
I just edited a few lines of your jQuery:
$('#mapSelections a').on('click', function () {
var text = $(this).text();
console.log(text);
//alert(text);
});
Your problem was, that THIS was not reffering to a single a, but the whole div#mapSelections instead.

You should bind the handler to the LI, not the whole DIV.
$("#mapSelections li").click(function() {
var text = $(this).find("a").text();
console.log(text);
});

Related

Change title of fa-icon using jquery [duplicate]

In my JSP page I added some links:
<a class="applicationdata" href="#" id="1">Organization Data</a>
<a class="applicationdata" href="#" id="2">Business Units</a>
<a class="applicationdata" href="#" id="6">Applications</a>
<a class="applicationdata" href="#" id="15">Data Entity</a>
It has a jQuery function registered for the click event:
$("a.applicationdata").click(function() {
var appid = $(this).attr("id");
$('#gentab a').addClass("tabclick");
$('#gentab a').attr('href', '#datacollector');
});
It will add a class, tabclick to <a> which is inside <li> with id="gentab". It is working fine. Here is my code for the <li>:
<li id="applndata"><a class="tabclick" href="#appdata" target="main">Application Data</a></li>
<li id="gentab">General</li>
Now I have a jQuery click handler for these links
$("a.tabclick").click(function() {
var liId = $(this).parent("li").attr("id");
alert(liId);
});
For the first link it is working fine. It is alerting the <li> id. But for the second <li>, where the class="tabclick" is been added by first jQuery is not working.
I tried $("a.tabclick").live("click", function(), but then the first link click event was also not working.
Since the class is added dynamically, you need to use event delegation to register the event handler
$(document).on('click', "a.tabclick", function() {
var liId = $(this).parent("li").attr("id");
alert(liId);
});
You should use the following:
$('#gentab').on('click', 'a.tabclick', function(event) {
event.preventDefault();
var liId = $(this).closest("li").attr("id");
alert(liId);
});
This will attach your event to any anchors within the #gentab element,
reducing the scope of having to check the whole document element tree and increasing efficiency.
.live() is deprecated.When you want to use for delegated elements then use .on() wiht the following syntax
$(document).on('click', "a.tabclick", function() {
This syntax will work for delegated events
.on()
Based on #Arun P Johny this is how you do it for an input:
<input type="button" class="btEdit" id="myButton1">
This is how I got it in jQuery:
$(document).on('click', "input.btEdit", function () {
var id = this.id;
console.log(id);
});
This will log on the console: myButton1.
As #Arun said you need to add the event dinamically, but in my case you don't need to call the parent first.
UPDATE
Though it would be better to say:
$(document).on('click', "input.btEdit", function () {
var id = $(this).id;
console.log(id);
});
Since this is JQuery's syntax, even though both will work.
on document ready event there is no a tag with class tabclick. so you have to bind click event dynamically when you are adding tabclick class. please this code:
$("a.applicationdata").click(function() {
var appid = $(this).attr("id");
$('#gentab a').addClass("tabclick")
.click(function() {
var liId = $(this).parent("li").attr("id");
alert(liId);
});
$('#gentab a').attr('href', '#datacollector');
});
Here is the another solution as well, the bind method.
$(document).bind('click', ".intro", function() {
var liId = $(this).parent("li").attr("id");
alert(liId);
});
Cheers :)
I Know this is an old topic...but none of the above helped me.
And after searching a lot and trying everything...I came up with this.
First remove the click code out of the $(document).ready part and put it in a separate section.
then put your click code in an $(function(){......}); code.
Like this:
<script>
$(function(){
//your click code
$("a.tabclick").on('click',function() {
//do something
});
});
</script>

Get data-val on a programatically added <li>

I'm trying to get an programatically added li data-val on click, as below:
$(function () {
$("#bpadd").click(function () {
var bpinput = document.getElementById("bpinput").value;
$('#bpitem').append('<li data-val="' + bpinput + ' clicked">' + bpinput + '</li>');
});
$('#bpitem li').click(function () {
alert($(this).attr('data-val'));
});
This is the html sample:
<input type="text" id="bpinput">
<input type="button" id="bpadd" value="+">
<ul id="bpitem">
<li data-val="Test 1 clicked">Test 1</li>
</ul>
If I click in Test 1, it works, but nothing happens when I click in a new item, why is that so?
You need to use the .ondoc function on some selector that'll work for every newly added element, like this:
$('#bpitem').on('click', 'li', function () {
alert($(this).attr('data-val'));
});
As you can see on the docs, the function will bind the events on newly-added elements that match the selector rather than just binding it to existing ones like the .click function does.
Try this:
$('#bpitem').on('click', 'li', function () {
alert($(this).attr('data-val'));
});
The .click() method binds the click handler only to elements that exist at the time that line of code runs. If you use .on(), you bind the handler to your parent #bpitem element (which exists initially) but when a click occurs jQuery checks if the clicked child element matches the selector in the second parameter and thus it works on children of #bpitem that were added dynamically.
try:
$('#bpitem').on('click', 'li', function() {
alert('clicked');
);
This will dynamically add event listeners to ALL bpitem li elements instead of the ones that are there when this is first ran

Styled Select Fields with jquery and HTML Listelements

i have a little problem with my styled Selectfield. I used for this unordered list elemnts (UL / LI) and a H3.
The problem is to close the "Selectfield" by clicking anywhere on the page.
When i bind a click event to the "document", then don't open the SelectField with the current jQuery code.
I have hidden the UL Element by using CSS (display:none).
To open the Select Fields is not the problem. But only without the $(document).bind('click') [...] code.
I hope anyone have a resolution for my.
Thanks.
And here my HTML Code:
<div class="select_container">
<h3 class="reset">Select Items</h3>
<ul class="select_elements">
<li>Select Item 01</li>
<li>Select Item 02</li>
<li>Select Item 03</li>
</ul>
</div>
And here the jQuery Code:
$(document).ready(function(){
var selectFields = {
init: function(){
$('.select_container').on('click',function(){
$(this).find('ul.select_elements').toggle();
$(this).find('ul.select_elements').toggleClass('active');
});
$(document).bind('click',function(){
if( $('.select_elements').is(':visible')){
$('.select_elements.active').hide();
}
else if( $('.select_elements').is(':hidden')){
console.log('visible false ...');
}
});
}
};
$(selectFields.init);
});
You need to use .stopPropagation in $('.select_container').on('click') function to prevent triggiring $(document).on('click')
You need to use toggleClass in $(document).on('click') too
$('.select_container').on('click',function(e){
$(this).find('ul.select_elements').toggle();
$(this).find('ul.select_elements').toggleClass('active');
e.stopPropagation();
});
$(document).on('click',function(){
if( $('.select_elements').is(':visible')){
$('.active').hide();
$('.select_elements').toggleClass('active');
}
else {
console.log('visible false ...');
}
});
FIDDLE
In jquery and javascript an event bubbles up so you have to use e.stopPropagation() on your container click.
check theese pages linki1 or link2 and a possible solution to your problem could be
<script type="text/javascript">
$(document).ready(function(){
var selectFields = {
init: function(){
$(document).bind('click',function(e){
if( !$('ul').hasClass('active')){
$('ul').hide()
$(this).find('ul.select_elements').toggleClass('active');
}
});
$('.select_container').on('click',function(e){
e.stopPropagation()
if( $('ul').hasClass('active')){
$('ul').show()
}else{ $('ul').hide() }
$(this).find('ul.select_elements').toggleClass('active');
});
}
};
$(selectFields.init);
})
</script>
With stopPropagation prevent the event from bubbling and being caught by the document when you click on the list
in some cases you can also use stopImmediatePropagation, for understand differences between stopPropagation and stopImmediatePropagation check this post Post
The only drawback to similar code and to and Batu Zet code, is that If you want the items in the list can be clicked without disappearing, you have to add another stopPropagation on ul tag
Tis is the final Fiddle

Change li class in jquery

I want to change the class of the current li(list) which is selected
$('li.doBlokkeer').click(function(e) {
$(this).addClass('doDEBlokkeer').removeClass('doBlokkeer');
});
$('li.doDEBlokkeer').click(function(e) {
$(this).addClass('doBlokkeer').removeClass('doDEBlokkeer');
});
so if a current li is selected its class need to be changed (it needs to have doDEBlokkeer). The above code works..
The problem is that this only works once for each LI item..
when I click on li.doBlokkeer the class changes which is good, but when I press the same current li again, it calls the same function li.doBlokkeer instead of li.doDEBlokkeer function (despite the css class) . I tried so much stuff but i really can't find any solution. can you guys help me out? I have been searching for a solution for more then 14 hours, so frustrated right now...
Issue is that you are binding the event on the class selector (for the element existed in DOM at that time ) which gets changed dynamically so your binding is lost. You can consider using event delegation syntax or bind it to a different class/selector which doesn't change.
Using Event delegation (jq >=1.7) you can try:
$('ul').on('click', 'li.doBlokkeer', function(e) {
$(this).addClass('doDEBlokkeer').removeClass('doBlokkeer');
});
$('ul').on('click', 'li.doDEBlokkeer', function(e) {
$(this).addClass('doBlokkeer').removeClass('doDEBlokkeer');
});
Another shortcut:
$('.cls').click(function (e) { // add a common class to all lis and bind the click event to that.
var flg = $(this).is('.doBlokkeer'); //check if it is a specific class
$(this).addClass(function () {
return flg ? 'doDEBlokkeer' : 'doBlokkeer'; //based on flag return the other class
}).removeClass(function () {
return flg ? 'doBlokkeer' : 'doDEBlokkeer'; //based on flag return the other class
});
});
or just:
$('.cls').click(function (e) {
$(this).toggleClass('doDEBlokkeer').toggleClass('doBlokkeer');
});
Fiddle
Fiddle
Also, please consider this:
$('li').click(function()
{
var $this = $(this),
one = 'doBlokkeer',
two = 'doDEBlokkeer';
if ( $this.hasClass(one) ) {
$this.removeClass(one).addClass(two);
} else {
$this.removeClass(two).addClass(one);
}
});
Use .toggleClass
$('li.doBlokkeer').click(function(e) {
$(this).toggleClass('doDEBlokkeer');
});
There is no need for the second click event
The issue is as explained earlier, that you bind the event to an element with the given class name, then, on click you change the class name, so the handler doesn't listen to it any more...
I would recommend to stick with event delegation because it's lighter and you can also nest elements in your lis (like a link or a div etc.):
First add the class 'cls'to your <ul>, so <ul class="cls">. Your HTML could the look like:
<ul class="cls">
<li class="doBlokkeer"><div>Click on me</div></li>
<li class="doDEBlokkeer">Click on me</li>
<li class="doBlokkeer">Click on me</li>
<li class="doBlokkeer">Click on me</li>
</ul>
All you need for your javaScript is now:
$('.cls').on('click', '.doDEBlokkeer, .doBlokkeer', function (e) {
$(this).toggleClass('doDEBlokkeer doBlokkeer');
});
...which requires jQuery 1.7. If you have only jQuery 1.4.2 and up you can use '.delegate()`
$('.cls').delegate('.doDEBlokkeer, .doBlokkeer', 'click', function (e) {
$(this).toggleClass('doDEBlokkeer doBlokkeer');
});
The event (and only one) is now on the ul and the .on() pickes out the right elements defined by the class names you passed through.
I updated the fiddle from PSL

More confusing behavior with stopPropagation()

I have the following code It takes a <ul> and it drops down the contents when clicked. That works great. The problem was that it would also close other menus of the same type when a child <li> was clicked.
I 'fixed' this problem by using the if clause to determine if the item being clicked was also the item that was currently open, but I want to take it a step further and make it so that if the parent ul is clicked again, it will close the menu. I am having a great deal of misunderstanding as to how to approach this. I attempted to stop the propagation of the children elements, but it yields the same results. Can anyone assist?
wiring (document load)
$(document).ready(function () {
$('[data-role="sidebar-dropdown"]').drawer({
open: 'sidebar-dropdown-open',
css: '.sidebar-dropdown-open'
});
});
html
<ul>
<li class=" dropdown" data-role="sidebar-dropdown">
Link Text
<ul class="sub-menu light sidebar-dropdown-menu">
<li><a class="remote" href="pages/...">Link Text</a></li>
<li><a class="remote" href="pages/...">Link Text</a></li>
<li><a class="remote" href="pages/...">Link Text</a></li>
</ul>
</li>
</ul>
JavaScript
(function ($) {
$.fn.drawer = function (options) {
// Create some defaults, extending them with any options that were provided
var settings = $.extend({
open: 'open',
css: '.open'
}, options);
return this.each(function () {
$(this).on('click', function (e) {
// slide up all open dropdown menus
$(settings.css).not($(this)).each(function () {
$(this).removeClass(settings.open);
// retrieve the appropriate menu item
var $menu = $(this).children(".dropdown-menu, .sidebar-dropdown-menu");
// slide down the one clicked on.
$menu.slideUp('fast');
$menu.removeClass('active');
});
// mark this menu as open
$(this).addClass(settings.open);
// retrieve the appropriate menu item
var $menu = $(this).children(".dropdown-menu, .sidebar-dropdown-menu");
// slide down the one clicked on.
$menu.slideDown(100);
$menu.addClass('active');
e.preventDefault();
e.stopPropagation();
}).on("mouseleave", function () {
$(this).children(".dropdown-menu").hide().delay(300);
});
})
};
})(jQuery);
In jQuery events you can read the node which initiated the event by referencing e.target.
if ($(e.target).is("li")) { // do something only if the clicked element was a li }
Regarding closing elements which are not children, instead of doing a global selector $(selector) you should instead do a selector relative to your initiating dom node. It's a common practice to pass this and stashing it inside your jQuery plugin.
return this.each(function(this)) { var $node = $(this); }
Then all lookups would be done like
$node.find(selector).doStuff()

Categories