How to clone -> reverse -> and prependTo? - javascript

I have a list of element e.g.: .title, I'm cloning them out and append them to a container, but the order is reversed from prependTo`.
How do I put these cloned element to an array and reverse it before prepending them?
For example, for each .title clone it, and prependTo .container, and wrap it with li:
$('.title').each(function() {
$this.clone()
.prependTo('.container')
.wrap('<li></li>')
});

Given this html:
<ul>
<li class="title">A</li>
<li class="title">B</li>
<li class="title">C</li>
<li class="title">D</li>
<li class="title">E</li>
</ul>
<ul class="container">
</ul>
Use this jQuery to add them to the .container element:
$('.title').each(function() {
$('.container')
.append($(this).clone());
});
If you want to reverse the order, then use .prepend instead of .append.
Check out http://jsfiddle.net/y8Aub/ if you want to see it in action.

Related

Get <li> value based on class

I have the following example code:
<ul class="name_of_class" id="TEST">
<li class="foo">1</li>
<li class="boo">2</li>
<li class="goo">3</li>
<ul>
When a specific <li> is selected, the class changes to whatever the name is, plus sortUp or sortDown.
Example:
<ul class="name_of_class" id="TEST">
<li class="foo">111</li>
<li class="boo sortDown">222</li>
<li class="goo">333</li>
<ul>
I am trying to get the value of the actual text inside the <li>, but I keep getting undefined.
var li = document.getElementById('TEST');
alert($('#TEST').filter('.sort').html());
I tried using different ways but no matter what I do I can't get the actual value, which in this case should be 222.
Any idea what I am doing wrong?
You can select the li with either sortUp or sortDown by using the [attribute*="value"] selector,
The [attribute*="value"] selector is used to select elements whose
attribute value contains a specified value.
const li = document.querySelector('[class*="sort"]');
console.log(li.textContent);
li.style.background = "red";
<ul class="name_of_class" id="TEST">
<li class="foo">111</li>
<li class="boo sortDown">222</li>
<li class="goo">333</li>
<ul>
See css attribute selectors
I'm not sure what the classes have to do with your requirement to get the text of the clicked li element. Just set up a click event handler on the ul and then in the handler, check the event target to ensure it was an li, then just get the text of the event target.
document.getElementById("TEST").addEventListener("click", function(evt){
if(evt.target.nodeName==="LI"){
alert(evt.target.textContent);
}
});
<ul class="name_of_class" id="TEST">
<li class="foo">1</li>
<li class="boo">2</li>
<li class="goo">3</li>
<ul>
Maybe you can try this:
alert($('#TEST').find('li[class^='sort']').html());
You will find a li element that has a class that starts with "sort".
You can see more of this selector here.

Using jQuery .nextUntil() on split lists

Is it possible to get the .nextUntil() to work on split lists, or get the same functionality?
So I am trying to implement the ever so popular shift select for my items, and since they are ordered in a list in my application I want to be able to select across <ul> borders.
I have the following set of DOM elements:
<ul class="current">
<li class="item">first</li>
<li class="item clicked">second</li>
<li class="item">third</li>
<li class="item">fourth</li>
</ul>
<ul class="later">
<li class="item">fifth</li>
<li class="item selected">sixth</li>
<li class="item">seventh</li>
</ul>
And using something like this:
$('li.clicked').nextUntil('li.selected');
I'd like a list containing the following elements
[ <li class="item">third</li>,
<li class="item">fourth</li>,
<li class="item">fifth</li> ]
However all I get is the elements leading up to the split </ul>. Is there any way of doing this? I have also tried to first selecting all items with $('.item')and then using .nextUntil() on them without any luck.
Is this what you are looking for?
$('li').slice($('li').index($('.clicked'))+1,$('li').index($('.selected')));
For reference
Jquery.Index
Jquery.Slice
Edit
So if you do
$('li')
you will get an array of all elements 'li' getting:
[<li class=​"item">​first​</li>​,
<li class=​"item clicked">​second​</li>​,
<li class=​"item">​third​</li>​,
<li class=​"item">​fourth​</li>​,
<li class=​"item">​fifth​</li>​,
<li class=​"item selected">​sixth​</li>​,
<li class=​"item">​seventh​</li>​]
Since it is an array you can slice him to get an sub array you just need two positions, where to start and here to finish.
//start
$('li').index($('.clicked'))+1 // +1 because you dont want to select him self
//end
$('li').index($('.selected'))
For better preformance you should before create an array with all li so it will not search all dom 3 times for the array of 'li'
var array = $('li');
var subarray = array.slice(array.index($('.clicked'))+1,array.index($('.selected')));
Assuming these lists cannot be merged into one, it is impossible using the nextUntil method. This is because of how jQuery performs traversing. According to the documentation,
Get all following siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object passed.
fifth is not a sibling of the clicked element, but rather it is a child of the sibling of the element's parents.
I came up with two possible solutions.
Solution 1: Combine NEXT and PREV traversals
Assuming that .clicked is always in the first list and .selected is always in the second list, combining prevAll() with nextAll() should do the trick. This assumes that the order is the same.
var siblings = $("li.clicked").nextAll()
Get all siblings of the current element AFTER the element itself.
var distantSiblings = $("li.selected").prevAll();
Get all distant siblings after the first element, but before the second one.
siblings.push(distantSiblings);
Combine them into two and then iterate over each element.
var siblings = $("li.clicked").nextAll()
var distantSiblings = $("li.selected").prevAll();
siblings.push(distantSiblings);
siblings.each(function() {
$(this).addClass("blue");
});
.blue { color: blue; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="current">
<li class="item">first</li>
<li class="item clicked">second</li>
<li class="item">third</li>
<li class="item">fourth</li>
</ul>
<ul class="later">
<li class="item">fifth</li>
<li class="item selected">sixth</li>
<li class="item">seventh</li>
</ul>
http://jsfiddle.net/r15z10o4/
Note:
You will notice that the above code works, however it might not be the optimal solution. This is only confirmed to work for your example above. There may also be a less verbose solution.
Solution 2 (Find index of all list items)
Another idea is to find the index of all items, and collect the elements that are sandwiched between those two indices. You will then want to use the 'slice' selector to get the range in between.
var items = $(".item");
var clicked = $(".clicked");
var selected = $(".selected");
var clickIndex = items.index(clicked);
var selectIndex = items.index(selected);
$("li").slice(clickIndex + 1, selectIndex).addClass("blue");
var clicked = $(".clicked");
var selected = $(".selected");
var clickIndex = $("li").index(clicked);
var selectIndex = $("li").index(selected);
$("li").slice(clickIndex+1, selectIndex).addClass("blue");
.blue { color: blue; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="current">
<li class="item">first</li>
<li class="item clicked">second</li>
<li class="item">third</li>
<li class="item">fourth</li>
</ul>
<ul class="later">
<li class="item">fifth</li>
<li class="item selected">sixth</li>
<li class="item">seventh</li>
</ul>
You can do it manually by selecting all these items at once, and using loops.
Consider the parent element, let's say "container":
<div id="container">
<ul class="current">
<li class="item">first</li>
<li class="item clicked">second</li>
<li class="item">third</li>
<li class="item">fourth</li>
</ul>
<ul class="later">
<li class="item">fifth</li>
<li class="item selected">sixth</li>
<li class="item">seventh</li>
</ul>
</div>
Now, you can select all these items:
var $items = $("#container > ul > li.item"); // or simply $("#container .item");
And iterate through them:
var $items = $(".item"), $result = $(), found = false;
for (var i = 0; i < $items.length; i++)
{
$currentItem = $items.eq(i);
if ($currentItem.is('.clicked')) {
found = true;
continue;
}
if ($currentItem.is('.selected'))
break;
if (found)
$result = $result.add($currentItem);
}
console.log($result);
Here is the working JSFiddle demo.
In any case it feels like you will need to define groups of li.
I think the easiest is to create a function getting a list of lis that you can request any way you want then to filter the el you are interested in.
function elRange(elList, start, end){
// we do not use indexOf directly as elList is likely to be a node list
// and not an array.
var startI = [].indexOf.call(elList, start);
var endI = [].indexOf.call(elList, end);
return [].slice.call(elList, startI, endI + 1);
}
// request the group of *ordered* elements that can be selected
var liList = document.querySelectorAll('ul.current > li, ul.later > li');
var selectionEnd = document.querySelector('.selected');
[].forEach.call(liList, function(li){
li.addEventListener('click', function(){
var selected = elRange(liList, li, selectionEnd);
selected.forEach(function(el){
el.classList.add('red');
})
});
});
.selected {
color: blue;
}
.red {
color: red;
}
<ul class="current">
<li class="item">first</li>
<li class="item">second</li>
<li class="item">third</li>
<li class="item">fourth</li>
</ul>
<ul class="later">
<li class="item">fifth</li>
<li class="item selected">sixth</li>
<li class="item">seventh</li>
</ul>

Determine what number li element a div is in

Say I have:
<ul>
<li></li>
<li>
<div id="test"></div>
</li>
<li></li>
</ul>
Is there a way to tell from the div tag what number li tag it's in?
I.e. in the div there is a javascript function that returns 2 since it's inside the second li element.
I realise I could go:
get parent ul
check each li child until the div is found.
Is there a more elegant way to do this?
You can use different variations of jQuery index()
$('li').index( $('li:has(div)') );
or
$('li:has(div)').index();
demo
You could use jQuery .find(); something like :
<ul class="level-1">
<li class="item-i">I</li>
<li class="item-ii">II
<div class="text">this is the div</div>
</li>
<li class="item-c">C</li>
<li class="item-iii">III</li>
</ul>
$("ul.level-1").find( "div" ).css( "background-color", "yellow" );
Depends what you need ...
You can use .index() to get the index of the li, since index is zero based add 1 to it to get 2
var $div = $('#test')
var index = $div.parent().index() + 1

Find all next elements with specific class

I have html like this:
<ul>
<li class="foo">One</li>
<li class="bar">Two</li>
<li class="bar">Tree</li>
<li class="bar">Four</li>
<li class="foo">Five</li>
<li class="bar">Six</li>
<li class="bar">Seven</li>
</ul>
and I have JS code like this:
$('.foo').click(function() {
$(this).allNext('.bar');
});
How can I select all elements that are after .foo and have class bar.
You can use nextAll:
$('.foo').click(function() {
$(this).nextAll('.bar');
});
beside nextAll may be you want to know about nextUntil() .. it will select all .bar until the next .foo
$('.foo').click(function() {
$(this).nextUntil('.foo').css('background','red');
});
DEMO

How to know the exact children number of Ul element?

I am a newbie in web development. Not sure if it is a dumb question.
<nav class="navigation">
<ul class="navigation-items-container">
<li class="navigation-items">Home</li>
<li class="navigation-items">about</li>
<li class="navigation-items">blog</li>
<li class="navigation-items">contacts</li>
</ul>
/nav>
On hover of each li I want to know its in which children Number of ul.
i.e
On hovering "Home" it should give as children Number 0 and on hovering "blog" it should give children number 2.
As you've included the jQuery tag I'll post a jQuery based answer - if you want a non-jQuery answer let me know:
$(".navigation-items-container li").hover(function(e) {
var index = $(this).index();
});
And FYI your markup is wrong, the anchors should be inside the li tags
The version for your current code (though it should be changed):
$(".navigation-items-container a").hover(function(e) {
var index = $(this).index();
});
Due to the fact that your li elements are within a elements, you should use this:
$(".navigation li").hover(function(){
var index = $(".navigation li").index(this);
alert(index);
});
Here is a working example
Of course, it would be better to have your a elements with the li elements like so:
<li class="navigation-items">Home</li>
That way the li elements will be direct children of the ul element, then you could do this:
$(".navigation li").hover(function(){
var index = $(this).index();
alert(index);
});
Here is a better example
Alternatively, and I am not saying this is better, but you could also use data-* attributes to store the value you want:
<li class="navigation-items" data-myindex="0">Home</li>
with this:
$(".navigation li").hover(function(){
var index = $(this).data("myindex");
alert(index);
});
This has the benefit that you could specify different values if required, such as record IDs for example.
Here is an example
Try this.
$('li').on('mouseover', function(){
console.log($('ul li').index($(this)));
})
Try index()
http://api.jquery.com/index/
$(".navigation ul li").hover(function(e) {
alert($(this).index());
});
More possiblities
this help you
Working Demo http://jsfiddle.net/cse_tushar/7SmfR/
$(".navigation ul li").hover(function() {
alert($(this).index('li'));
});
Correct your markup anchor(a) tag should be enclosed within li tags
<nav class="navigation">
<ul class="navigation-items-container">
<li class="navigation-items">
Home
</li>
<li class="navigation-items">
about
</li>
<li class="navigation-items">
blog
</li>
<li class="navigation-items">
contacts
</li>
</nav>

Categories