what I want to achieve is setting all occurences of a class to their designated data - except the particular occurence clicked, which is to be set to something unique. My code below gives an undefined error on the "y" variable. How would I go about contextualizing the dataset?
<div id="menu">
<ul>
<li id="menu-tos" data-info="TERMS OF SERVICE">TERMS OF SERVICE</li>
<li id="menu-contact" data-info="CONTACT">CONTACT</li>
<li id="menu-signup" data-info="SIGN UP">SIGN UP</li>
<li id="menu-login" data-info="LOG IN">LOGIN</li>
</ul>
</div>
<script>
$('#menu ul li').click(function() {
i = $(this.id);
y = dataset.info;
$('#menu ul li').not(i).html(y);
$(i).html('Something unique');
});
</script>
(to skip the explanation and see a working version, scroll to the bottom)
Your undefined error is because you trying to access dataset as if it is a variable, when it is actually a property of DOM element objects (details here).
Also, if I'm understanding your desired functionality correctly, there are a couple other issues you'll run into with your code:
i = $(this.id); this will resolve to $('menu-tos'). To select via ID, you'd need a #, like this: $('#menu-tos'). In your case, though, there's really no reason to set the current element to a variable anyway, because it is already available via $(this).
As mentioned above, y = dataset.info; won't work because dataset is a property on HTML Element objects, not a variable. Since you're using jQuery, it'd be easier to use $(this).data('info').
$('#menu ul li').not(i).html(y); this will not do what you said you're trying to do. This will set the HTML of all other <li> elements to the value of the one you just clicked. To set each one to its own value, you'll need to loop through them using .each()
$(i).html('Something unique'); assuming i was set correctly as a jQuery object, you don't need the jQuery wrapper here, you can just use i.html('Something unique');
A couple other things that would help your code:
The way you are setting your variables now (without using var), it will set them on the global scope. This may work, but it can cause collisions, and is generally avoided. Use var like var i = $(this);, and it will keep that variable only within the scope of your click() function.
When using jQuery, you should wrap your code in a $(document).ready() callback. This will ensure that the DOM is loaded before jQuery tries to bind any event handlers (such as your click handler).
After fixing the issues mentioned here, the javascript code ends up looking like:
$(document).ready(function() { // ensure document is loaded before running code
$('#menu ul li').click(function() {
// set all other elements to their own data-info attribute value
$('#menu ul li').not(this).each(function() {
var info = $(this).data('info');
$(this).html(info);
});
// set the clicked item to 'Something unique'
$(this).html('Something unique');
});
});
Checkout the working code on this JSFiddle.
Try like this:
$('#menu ul li').click(function() {
$(this).siblings().each(function() {
var info = $(this).data('info');
$(this).html(info);
});
$(this).html('Something unique');
});
Full example here https://jsfiddle.net/_jakob/q49kq3c5/1/
Related
Hi!
My problem is that I'm appending to an UL like that:
$("#tagek").append("<li><a>"+arr[0]+"</a><span class='ex'><a>X</a></span></li>");
So just shortly: I want to make a tag cloud. When someone types a comma, add the tag to the ul list. That works like charm, however I want to add an "X" to the li element so when someone clicks on it, it will be removed.
Something like that:
$(document).on('click','.ex',function(){
var li = $('.ex').closest("li");
li.remove();
});
So when I click on the ".ex" span its' li should disappear. This is working, but EVERY li is removed (logically), because every "X" has the same class.
Any ideas on this?
Maybe with .eq()?
Thank you.
You are experimenting that behaviour because you're removing the closest 'li' of every '.ex' element instead of the one clicked. Use the $(this) selector in the handler instead:
Try:
$(document).on('click','.ex',function(){
$(this).parent().remove();
});
i think u need this if you are using jquery .
$(document).on('click','.ex',function(){
var li = $(this).closest("li");
li.remove();
});
It's because you're re-selecting .ex (which gets all of them) inside the function handler instead of using the one that the event was triggered by.
Fix:
$(document).on('click', '.ex', function() {
$(this).closest('li').remove();
});
Edit: Not enough karma to comment, but alex030293's code should execute faster, but assumes that the element is a direct child as opposed to a descendant. If this is always the case, it's better to use his code. If there might be a situation where the .ex element is encapsulated in another tag, it's better to use mine.
Here's the HTML I'm focusing on:
<nav>
<ul id='nav'>
<li></icon>Home<span> +</span></li>
<li><icon><img src="images/skills-icon.png"></icon>Skillsets</li>
<li><icon><img src="images/gallery-icon.png"></icon>Gallery</li>
<li><icon><img src="images/about-icon.png"></icon>About</li>
<li></icon>Contact</li>
</ul>
</nav>
I want to select the text within the span—preferably only the "+" part of the text within the span (without the space). The way I'm trying to do that right now is with this code:
$(document).ready(function(){
var ul = $('nav > ul'),
li = ul.children('li'),
top = li.find('a').hasClass("top"),
navSpan = $(top).children('span');
$(navSpan).contents().replaceWith(' -');
});
but it isn't selecting the element correctly. With the way I have my javascript set up (there's a lot more of it than this) I need to keep these variables. However, it appears that some of these variables aren't set up correctly, or that my $(navSpan).contents().replaceWith() command isn't set up correctly. Do you guys have any ideas on how to fix it? Thanks!
First of all, lets fix your selectors and your double-wrapping:
$(function(){
var ul = $('#nav'),
li = ul.children('li'),
top = li.find('a.top'), // you can remove the 'a' qualifier if there is never another item with the top class
navSpan = top.children('span');
Second of all ... you can just replace the contents with this:
navSpan.text(' -');
});
Final code:
$(function(){
var ul = $('#nav'),
li = ul.children('li'),
top = li.find('a.top'),
navSpan = top.children('span');
navSpan.text(' -');
});
I cringe a little bit at the volume of unnecessary variables in this example, but you said you need all of them so I won't try to further optimize.
EDIT: Couldn't resist optimizing a little. Even if you need to capture all of those variables, you will have a faster querying with an id than you will using nav > li. If you have multiple menus that this applies to then disregard, but if not then this would be a little faster.
Here is a jsFiddle of the working code.
hasClass returns a boolean value. If you want to filter an element, you can use the filter method: li.find('a').filter(".top")
contents returns the childNodes of an element, you can't call jQuery methods on the returned value.
$('nav > ul').find('a.top span').text(' -');
jQuery newbie here.
If I have this html:
<ul id="floor-selector">
<li id="floor-1">Ground Floor</li>
<li id="floor-2">Second Floor</li>
<li id="floor-3">Third Floor</li>
<li id="floor-4">Premier Floor (Premier Floor)</li>
</ul>
I want to add a click event to each li item, such that I can get the id of the element I am on. Right now I just have an alert with the index I'm on (and it's not working either), but I really want the ID of the item I'm on, not the index of the array returned by my selector.
Here's what I tried, but it doesn't seem to work, I think I might have the wrong understanding of each() or click().
$('#floor-selector li').each( function(index, node) {
node.click( function(){ alert('I am on the '+index+'th element'); } );
// but I really want to get the ID of this element
});
This should work:
$('#floor-selector li').on('click', function() {
alert('I am the '+$(this).attr('id')+' element');
});
Behind the scenes jQuery does a bunch of magic and essentially binds the function you pass to the element. this therefore references the element that you are clicking and passing it to jQuery functio: $(this) gives you back that element wrapped in a jQuery object. Of course you could simply access the id on this directly.
I'm plucking my brain away at this but was hoping someone could help after several failed attempts.
I have an HTML list like this:
<ul>
<li><span class="current"></span></li>
<li><span class="normal"></span></li>
</ul>
I'm trying to figure out a way to find the li element in this list which has the span with the class current with the number it is at in the ul. So, in this case, it would be 1.
I tried using different jquery functions but I seem to be getting nowhere. This is what it looks like right now:
var list = $('ul li');
$.each(list, function(key, value) {
if( $(this).find('.current') ) {
alert(key);
}
});
This just alerts 0, and 1, essentially meaning that it doesn't work. Does anyone have any idea what is wrong with what I'm doing?
It would be 0 not 1 (JavaScript is zero-indexed), but:
$('li:has(span.current)').index();
JS Fiddle demo, and a larger-table example.
Or you could use:
$('span.current').parent().index();
JS Fiddle demo, and a larger-table example.
Or:
$('span.current').closest('li').index();
JS Fiddle demo, and a larger-table example.
References:
closest().
:has() selector.
index().
parent().
jQuery selectors (never) return a falsey value. So something like:
$(this).find('.current')
Will always return true in an if statement. An easy way to check for existence is with the length property, which says how many elements are found from the selector.
if ($(this).find('.current').length > 0) {
Your code loops through each item in the list and shows its key.
What you want is more like:
$('mylist').find('.current').each(function(key, value)
{
alert(key);
}
This will loop only through the items with class 'current'.
I have the following HTML:
<ul actualpage=0>
<li/>
<li/>
....
</ul>
<ul actualpage=0>
<li/>
<li/>
....
</ul>
Im trying to get the value of actualpage of each ul and create a new attribute. Its easy but not in one jquery sentence... Its possible? Until now i have the following line (between ## simbols the missing part that i need.
/*
select all uls with attribute actualpage and create a new attribute on each with the current actualpage value
*/
$('ul[actualpage]').attr('newactualpage',##Current value of actualpage attr of UL##);
Well maybe this isn't as nice as you'd like, but
$('ul[actualpage]').each(function(_, ul) { $(ul).attr('newactualpage', $(ul).attr('actualpage')); });
One might think that
$('ul[actualpage]').attr('newactualpage',$(this).attr('actualpage'))
is the answer.
However, this is evaluated before the call to attr, so it's going to equal whatever this equals in the calling context.
You could use:
$('ul[actualpage]').attr('newactualpage',function(){
return $(this).attr('actualpage');
});
or this:
$('ul[actualpage]').each(function()
{
$(this).attr('newactualpage',$(this).attr('actualpage'));
};
In both, this refers to the element that your selector matched.
You can use function as second argument for .attr(), eliminating the need of .each():
$('ul[actualpage]').attr('newactualpage', function() { return $(this).attr('actualpage') });