Change li class in jquery - javascript

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

Related

javascript jquery accessing the element being clicked

I've got the following list of semibuttons loaded using javascript:
var html ='<ul class="nav well-tabs well-tabs-inverse mb10" id="users">';
html +='<li class="active"><a id="'+this.my.user+'" data-toggle="tab_'+self.my.id+'" class="pestaña">'+this.my.user+'</a></li>';
var users = this.my.community_users;
for (i=0;i<users.length;i++) {
if (users[i].user != this.my.user)
html +='<li><a id="'+users[i].user+'" data-toggle="tab_'+self.my.id+'" class="pestana">'+users[i].user+'</a></li>';
};
html +='</ul>';
$(html).appendTo("#Dashboard");
Note, that the first item in the list is active. I am getting something like this:
Ok, now i code he onclick event to do something when a button is clicked:
$(document).on('click', 'a[data-toggle=tab_'+self.my.id+']', function(e){
// whatever here
});
What I need now is to set active the tab being clicked and set inactive the tab that was active. How can I access both elements to addclass and removeclass active?
You could use following logic:
$(document).on('click', '#users li:not(.active)', function () {
$('#users').find('li.active').add(this).toggleClass('active');
});
Something like this might work. Basically remove the .active class from everything but the element you clicked on. The add the .active class to the element clicked on.
$(document).on('click', 'a[data-toggle=tab_'+self.my.id+']', function (e) {
$('a[data-toggle=tab_'+self.my.id+']').not(this).removeClass('active');
$(this).addClass('active');
});
I would remove the 'active' class from all the list items first, then add it back to just the only that was clicked.
$(document).on('click', 'a[data-toggle=tab_'+self.my.id+']', function (e) {
$('#users .active').removeClass('active');
$(this).addClass('active');
});

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

Jquery get text of unorder list line items

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);
});

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

Prototype event handler

I've defined the following HTML elements
<span class="toggle-arrow">▼</span>
<span class="toggle-arrow" style="display:none;">▶</span>
When I click on one of the elements the visibility of both should be toggled. I tried the following Prototype code:
$$('.toggle-arrow').each(function(element) {
element.observe('click', function() {
$(element).toggle();
});
});
but it doesn't work. I know everything would be much simpler if I used jQuery, but unfortunately this is not an option:
Instead of iterating through all arrows in the collection, you can use the invoke method, to bind the event handlers, as well as toggling them. Here's an example:
var arrows = $$('.toggle-arrow');
arrows.invoke("observe", "click", function () {
arrows.invoke("toggle");
});
DEMO: http://jsfiddle.net/ddMn4/
I realize this is not quite what you're asking for, but consider something like this:
<div class="toggle-arrow-container">
<span class="toggle-arrow" style="color: pink;">▶</span>
<span class="toggle-arrow" style="display:none; color: orange;">▶</span>
</div>
document.on('click', '.toggle-arrow-container .toggle-arrow', function(event, el) {
var buddies = el.up('.toggle-arrow-container').select('.toggle-arrow');
buddies.invoke('toggle');
});
This will allow you to have multiple "toggle sets" on the page. Check out the fiddle: http://jsfiddle.net/nDppd/
Hope this helps on your Prototype adventure.
Off the cuff:
function toggleArrows(e) {
e.stop();
// first discover clicked arow
var clickedArrow = e.findElement();
// second hide all arrows
$$('.toggle-arrow').invoke('hide');
// third find arrow that wasn't clicked
var arw = $$('.toggle-arrow').find(function(a) {
return a.identify() != clickedArrow.identify();
});
// fourth complete the toggle
if(arw)
arw.show();
}
Wire the toggle arrow function in document loaded event like this
document.on('click','.toggle-arrow', toggleArrows.bindAsEventListener());
That's it, however you would have more success if you took advantage of two css classes of: arrow and arrow-selected. Then you could easily write your selector using these class names to invoke your hide/show "toggle" with something like:
function toggleArrows(e) {
e.stop();
$$('.toggle-arrow').invoke('hide');
var arw = $$('.toggle-arrow').reject(function(r) {
r.hasClassName('arrow-selected'); });
$$('.arrow-selected').invoke('removeClassName', 'arrow-selected');
arw.show();
arw.addClassName('arrow-selected');
}

Categories