jQuery target data element in nested list - javascript

I have a list which is structured something like this:
<ul data-Id="2" class="listElement">
<li></li>
<li></li>
<li>
<ul data-Id="3" class="listElement" style="display: none">
<li></li>
<li>
<ul data-Id="4" class="listElement" style="display: none">
<li></li>
</ul>
</li>
</ul>
</li>
I need to be able target the ul element which is currently hidden, and do a slidetoggle() on it. This I have tried to do in jQuery, but it doesn't work so well:
var test = 3; //i need to declare it as a var, because i get this from another item
$('.listElement').find('[data-Id="' + test + '"]').slideToggle("fast");
Nothing really happens and I can't seem to find what I'm missing here

Your code is correct, but please make sure dom elements has been already placed(ready) when your javascript code is run.
Or your javascript should be run on ready event of document hired.
$(document).ready(function(){
var test = 3; //i need to declare it as a var, because i get this from another item
$('.listElement').find('[data-Id="' + test + '"]').slideToggle("slow");
});

Related

How to use javascript to add #new after all links

I have the following code and I want all the links in the ul to be added #new by javascript , Can you help me?
<ul id="ul-data">
<li class="data">
data 3
</li>
<li class="data">
data 2
</li>
<li class="data">
data 1
</li>
<li class="data">
data 0
</li>
</ul>
I haven't found a solution yet
You can select the elements using the same syntax as css selectors, then you can loop over each selected element and replace the href attribute. The final result would look something like this:
document.querySelectorAll('#ul-data .data a').forEach((el) => {
el.href = el.href + "#new";
});
note that the space is needed in the selector to select the elements inside another element

Jquery - Looping through sibling elements one at at time

I am trying to loop through some sibling elements one at a time, and I am having trouble separating the process from just running through all matching elements at once. This has to be dynamic, as the list of items will vary and will not always be the same size. Examples below:
<div class="class">
<ul>
<li class="active"></li>
<li></li>
<li></li>
</ul>
</div>
<div class="class">
<ul>
<li class="active"></li>
<li></li>
<li></li>
</ul>
</div>
<div class="class">
<ul>
<li class="active"></li>
<li></li>
<li></li>
</ul>
</div>
The goal is to limit the number of active elements in each list to 1. However, when I loop through the elements using a normal .each() loop, it runs through all of the lists at the same time and limits the total amount to 1 rather then 1 per list. The code is rather simple so far, as I don't have a solution to this problem.
$('.class').find('li').each(function() {
// do something
});
I am curious of the basic task of looping through each of these lists individually and completing the tasks rather then looping through all lists at once. I would rather not create a separate jQuery call for each possible list, and would prefer a single call to handle the task. Any help or ideas would be appreciated, I might be looking past a simple solution.
Use nested loops, one for each list, then loop through the items in that list.
$(".class ul").each(function() {
var active_count = 0;
$(this).find("li").each(function() {
// do something
});
});
Loop your .class than:
$('.class').each(function() {
var $li = $(this).find('li');
// $li is now a collection of n LI elements inside the current .class
$li.each(function () {
// you can use $(this) at this point
});
});
That's how jQuery's .find works, first you searched for elements matching .class, then in all of these you searched for li. You'd have to do something like this:
$('.class').each(function () {
$(this).find('li')...
});
Your code is saying "find all the elements named class. Then loop through the <li>s present".
Try something like:
$('.class').each(function(){
$(this).find(li).each ...
}
Since each div with class ".class" contains a ul with li elements in which you want to have only one set as active, you would need to .each() on your divs and have an inner .each() on your li elements for each div.
$('.class').each(function(i, ele){
$(ele).find('li').each( function(i, ele) {} ); });
This snippet treats each list individually, and stores the first active item. Removes active from every li, then sets the original first active element to active. It also sets the first list item active if no item was active in this list.
$('.class').find('ul').each(function() {
let firstActiveLink = $(this).children('li.active:first');
$(this).children('li').removeClass('active');
if (firstActiveLink.length) {
firstActiveLink.addClass('active');
} else {
$(this).children('li:first-child()').addClass('active');
}
});
.active {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="class">
<ul>
<li class="active"></li>
<li class="active"></li>
<li class="active"></li>
</ul>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
<ul>
<li></li>
<li class="active"></li>
<li class="active"></li>
<li></li>
</ul>
<ul>
<li class="active"></li>
<li></li>
<li class="active"></li>
<li></li>
</ul>
</div>
Thank you for all the help! I ended up solving my problem by adding in a data- field and incrementing that field. Using a simple less than if statement to see if the element had more then the correct amount of li's associated with it. If anyone is having a similar situation, let me know if you want to see the code.

jQuery prepend on clone inserting at unexpected location

I'm trying to copy the contents of a DIV and insert a heading before the copy. However, the heading gets inserted at the wrong point.
var reference = $('#reference').clone().contents();
reference.prepend('<h1>Heading</h1>');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="reference">
<ul>
<li></li>
</ul>
</div>
I want the heading to go before the <ul> but instead it gets inserted after before the first li.
So it looks like this:
<div id="copy">
<ul>
<h1>Heading</h1>
<li></li>
</ul>
</div>
Instead of this (what I want):
<div id="copy">
<h1>Heading</h1>
<ul>
<li></li>
</ul>
</div>
This is probably a really basic question but a few hours of trying prependTo(), before(), insertBefore() and searching online have not gotten me any closer. Thanks :)
Firstly remove contents() as you want to clone the whole element, not its children. Secondly, create the h1 tag, then use prependTo() to place it at the desired location in the cloned element.
Also note that your current code results in duplicate id attributes in the DOM, which is invalid. I'd suggest making the #reference id in to a class instead. Try this:
var reference = $('.reference:first').clone();
$('<h1>Heading</h1>').prependTo(reference);
$('body').append(reference);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="reference">
<ul>
<li>Foo</li>
</ul>
</div>
Use it like this I have tried and It is working fine.
$('#reference').clone().contents().parent().prepend('<h1>Hea‌​ding</h1>')

javascript getElementById and InnerHTML only running once against html

I am trying to create a simple title spacer for my html code so that I don't have to type "&nbsp" a lot and so the code looks more eat. However I have created this:
$(function() {
var subSpace = document.getElementById("subSpace");
var titleName = document.getElementById("subSpace").value;
subSpace.innerHTML = " " + titleName;
return false;
});
but it only runs against this code once:
<li><a href="#" id="subSpace" value="Start Menu" ></a></li>
<li><a href="#" id="subSpace" value="Tiles" ></a></li>
<li><a href="#" id="subSpace" value="Action Center" ></a></li>
<li><a href="#" id="subSpace" value="Settings" ></a></li>
<li></li>
<li></li>
<li></li>
So it runs Start Menu and properly spaces it the way I want but doesn't run tiles, action center, etc. Is there a way to fix this? Am I missing something? I could be way off as I am still learning.
Thank you in advance!
You should use a class instead of an ID as IDs are supposed to be unique. Other than that, you could be using CSS to add padding to the left:
.subspace {
padding-left:10px;
}
<li>Start Menu</li>
<li>Tiles</li>
<li>Action Center</li>
<li>Settings</li>
<li>Customizations</li>
<li>Windows Search</li>
<li>Microsoft Edge</li>
That's because you have multiple elements with an id of subSpace. You should use an id only once. If you have multiple elements with the same id, the first element will only be matched.
Also, on a side-note, you should really use CSS to style your page (i.e adding spacers/margins/paddings).
You have duplicates ids. Use class if you need to select multiple elements. You can select them using JQuery
<a href="#" id="subSpace" value="Start Menu" class="subSpace">
In your js:
$('.subSpace').html(' ');
I see another answer here which suggests a better way to do this only using CSS. You should consider that too.

Convert 4 lines of Jquery to Mootools

The following lines of code do two things. The first two lines add classes to the siblings immediately before and after an element with a given id (in this case a UL with id "nav")
The last two lines add the classes first and last to the first and last sibling elements whose parent has the id "nav".
This is jquery. How would I achieve the same with Mootools 1.11. Any help appreciated.
$('#nav .active').prev().addClass('prevtab');
$('#nav .active').next().addClass('nexttab');
$('#nav').children(":first").addClass('first');
$('#nav').children(":last").addClass('last');
formatting doesn't work in comments so repeating for zombat:
Using mootools 1.1
There is no edit button available to me, and I can't comment as I don't have enough rep.
Your solution is doing something, but not targeting the correct element.
This is the result I want and am getting with jquery:
<ul id="nav">
<li class="first"></li>
<li></li>
<li class="prevtab"></li>
<li class="active"></li>
<li class="nexttab"></li>
<li class="last"></li>
</ul>
This is the result of your js:
<div class="prevtab"></div>
<ul id="nav">
<li></li>
<li></li>
<li></li>
<li class="active"></li>
<li></li>
<li></li>
</ul>
<div class="nexttab"><div>
Give this a shot.
$('nav').getNext().addClass('nexttab');
$('nav').getPrevious().addClass('prevtab');
var c = $('nav').getChildren();
c[0].addClass('first');
c[c.length-1].addClass('last');
Edit: Working now.
Second/Third edits:
Ok, I misunderstood the way you're using the .active class. Try this:
var n = $('nav').getElement('.active').getNext();
if (n) n.addClass('nexttab');
var p = $('nav').getElement('.active').getPrevious();
if (p) p.addClass('prevtab');
var c = $('nav').getChildren();
c[0].addClass('first');
c[c.length-1].addClass('last');
$each($$('#nav .active'),function(item){
item.getPrevious().classname='prevtab';
}
);
This is the first line.
Second you can use getNext
Third you can use $('#nav').getFirst //make sure it has children....
Fourth you can use getLast

Categories