Im trying to rearrange a list. I've got for example a list with categories:
<ul class="category">
<li class="cat1 active">cat1</li>
<li class="cat2 active">cat2</li>
<li class="cat3">cat3</li>
<li class="cat4">cat4</li>
</ul>
and a list with subjects
<ul class="subjects">
<li class="sub1">sub1</li>
<li class="sub2">sub2</li>
<li class="sub3">sub3</li>
<li class="sub4">sub4</li>
<li class="sub5">sub5</li>
<li class="sub6">sub7</li>
<li class="sub7">sub7</li>
<li class="sub8">sub8</li>
</ul>
What I want to do is when a certain category has the class active, some subjects will go to the top of the list. for example like this:
<ul class="subjects">
<li class="sub3">sub3</li>
<li class="sub5">sub5</li>
<li class="sub8">sub8</li>
<li class="sub1">sub1</li>
<li class="sub2">sub2</li>
<li class="sub4">sub4</li>
<li class="sub6">sub6</li>
<li class="sub7">sub7</li>
</ul>
I can do this with this code:
if($('li.cat1').hasClass('active')){
$('.sub3, .sub5, .sub8').insertBefore($('.subjects li:first-child'));
}
But then the real problem starts when multiple categories is active. I have done it like so:
if($('li.cat1').hasClass('active')){
$('.sub3, .sub5, .sub8').insertBefore($('.subjects li:first-child'));
}
if($('li.cat2').hasClass('active')){
$('.sub3, .sub4, .sub7').insertBefore($('.subjects li:first-child'));
}
The result is this:
<ul class="subjects">
<li class="sub4">sub4</li>
<li class="sub7">sub7</li>
<li class="sub3">sub3</li>
<li class="sub5">sub5</li>
<li class="sub8">sub8</li>
<li class="sub1">sub1</li>
<li class="sub2">sub2</li>
<li class="sub6">sub6</li>
</ul>
the order is now 4,7,3,5,8. Those are the numbers that have been selected but how do I rearrange them into: 3,4,5,7,8,1,2,6? Could someone help me with this? Here is the JsFiddle http://jsfiddle.net/NTPd4/2/
You could do 2 things to make it ALL good. First, make an sort method to suit your needs (i went by alpha of inner html, pik your poison). Second, make a variable for a jQuery object you can simply add elements too.
Next, use the variable in your if statements to gather the elements you want. Then before inserting, sort them!
Example
function sortAlpha(a,b){
return a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase() ? 1 : -1;
};
var activeSubjects = $();
if ($('li.cat1').hasClass('active')) {
activeSubjects = activeSubjects.add($('.sub5, .sub3, .sub8'))
}
if ($('li.cat2').hasClass('active')) {
activeSubjects = activeSubjects.add($('.sub3, .sub4, .sub7'))
}
activeSubjects.sort(sortAlpha).insertBefore($('.subjects li:first-child'));
I think the .add will sort them automigikally, but keep in mind, you could also use the sort function straightforward, like:
$('.sub5, .sub3, .sub8').sort(sortAlpha);
Also, for your current setup (where all text is same except for number) you could use a sort function like:
function sortNum(a,b) {
return parseInt($(a).text().substring(3)) - parseInt($(b).text().substring(3));
}
However, the sortAlpha will probably better suite your needs in the long run. As I mentioned before, you can arrange your sort function how you like.
If you want all five elements in their original order, you need to move them at the same time. Use .add() to combine them:
$('.sub3, .sub5, .sub8').add('.sub3, .sub4, .sub7').prependTo($('.subjects'));
Or, integrating it into your code:
var $selector = $();
if ($('li.cat1').hasClass('active')) {
$selector = $selector.add('.sub3, .sub5, .sub8');
}
if ($('li.cat2').hasClass('active')) {
$selector = $selector.add('.sub3, .sub4, .sub7');
}
$selector.prependTo('.subjects');
http://jsfiddle.net/mblase75/GYfpv/
Related
I have a list and I want to count only the items in that list that have an id attribute. For example, this is my code:
<ul class="members-list">
<li id="newmember1"></li>
<li id="newmember2"></li>
<li data-empty-index="3"></li>
<li data-empty-index="4"></li>
</ul>
The list counts how many members are associated with an account and a user can add and delete members themselves. When they add a member, they are given an id. I want to count the number of unused accounts they have, i.e. the list items here that aren't associated with an id (the bottom 2).
I have the following code already to count how many list items altogether:
var listOfMembers = $(".members-list").children();
var numberOfMembers = listOfMembers.length;
However I don't know how to get the ones that don't have an id, and separate them from the group? I'm not even sure if this is possible, but would really grateful for any pointers please :)
this should work for you.
var listOfMembers = $(".members-list").find("li[id]")
You can use querySelectorAll():
let count = document.querySelectorAll('ul li[id]').length;
You can use .find() with :not()
var listOfMembers = $(".members-list").find(":not(li[id])");
var numberOfMembers = listOfMembers.length;
console.log(numberOfMembers);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="members-list">
<li id="newmember1"></li>
<li id="newmember2"></li>
<li data-empty-index="3"></li>
<li data-empty-index="4"></li>
</ul>
OR: You can use .filter() to filter out the elements not having an id attribute.
var listOfMembers = $(".members-list li").filter((_, el) => !$(el).attr('id'));
var numberOfMembers = listOfMembers.length;
console.log(numberOfMembers);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="members-list">
<li id="newmember1"></li>
<li id="newmember2"></li>
<li data-empty-index="3"></li>
<li data-empty-index="4"></li>
</ul>
Simple. This can be done using the :not selector combined with targeting all li's with an id attribute.
$(function() {
var listItems = $('li:not([id])');
console.log(listItems.get(), 'Number of elements: ' + listItems.length)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="members-list">
<li id="newmember1"></li>
<li id="newmember2"></li>
<li data-empty-index="3"></li>
<li data-empty-index="4"></li>
</ul>
Let's say that I have a nested <ul> that looks like this:
<ul>
<ul class="pizzatype">
<h1>Margherita</h1>
<li class="ingredient">Tomato sauce</li>
<li class="ingredient">Mozzarella</li>
<li class="ingredient">Origano</li>
</ul>
<ul class="pizzatype">
<h1>Spicy salamino</h1>
<li class="ingredient">Tomato sauce</li>
<li class="ingredient">Mozzarella</li>
<li class="ingredient">Salamino</li>
</ul>
<ul class="pizzatype">
<h1>Onion n' Tuna</h1>
<li class="ingredient">Tomato sauce</li>
<li class="ingredient">Mozzarella</li>
<li class="ingredient">Tuna</li>
<li class="ingredient">Onion</li>
</ul>
</ul>
And a script that console.log the childrens of class "pizzatype":
var pizzatype = document.querySelectorAll('.pizzatype');
console.log(pizzatype[1].children[3]);
The console.log at children[3] returns: <li class="ingredient">Salamino</li>
But I'm looking for a parameter that returns just Salamino
Anyone can help?
Also, is there any reference site that I can consult to find out which parameters can be asked, starting from the children function? Like children.text, children.value etc
Use textContent to get the text of an element
console.log(pizzatype[1].children[3].textContent);
What you're currently doing is pointing to the li element it's self. You need to target the text of this element.
You can do this by using .innerText. You can also use .innerHTML, which will return the text in raw format and won't automatically encode/decode text.
console.log(pizzatype[1].children[3].innerHTML);
I have done coding the first part HTML then JavaScript/JQuery. Now I want to surround the final common list with a UL need to be done using JavaScript/JQuery. So the final common list will be surrounded by two UL instead of one. Eg
Final Outcome
<ul id="CommonLister">
<ul> <!--Need to add this-->
<li class="columnItem">John</li>
<li class="columnItem">Mark</li>
</ul><!--Need to add this-->
</ul>
Current Code
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<ul id="listOne">
<li class="columnItem">John</li><!--will be removed and put under CommonLister-->
<li class="columnItem">James</li>
<li class="columnItem">Mary</li><!--will be removed and put under CommonLister-->
</ul>
<ul id="listTwo">
<li class="columnItem">John</li><!--will be removed and put under CommonLister-->
<li class="columnItem">Mark</li>
<li class="columnItem">Mary</li><!--will be removed and put under CommonLister-->
</ul>
<ul id="CommonLister">
<li class="columnItem">John</li>
<li class="columnItem">Mark</li>
</ul>
</div>
$(function() {
$('#run-code').on('click', function(e) {
e.preventDefault();
//What were you doing? nope.
var currentItems = {}; //Blank object
var $mergeColumn = $('#CommonLister'); //Common list reference
$('.columnItem').each(function(i, el) {
var $el = $(el); //Notation I use to differentiate between the regular HTML Element and jQuery element
if (!currentItems.hasOwnProperty($el.html())) {
//Has this name come up before? if not, create it.
currentItems[$el.html()] = []; //Make it equal to a brand spanking new array
}
currentItems[$el.html()].push(el);
//Add the item to the array
});
$.each(currentItems, function(name, data) {
//Loop through each name. We don't actually use the name variable because we don't care what someone's name is
if (data.length > 1) {
//Do we have more than 1 element in our array? time to move some stuff
$.each(data, function(i, el) {
var $el = $(el); //See note above
if (i == 0) {
//If this is the first element, let's just go ahead and move it to the merge column ul
$el.appendTo($mergeColumn);
} else {
$el.remove(); //Otherwise, we've already got this element so delete this one.
} //end if/else
}); //end $.each(data)
} //end if data.length >1
}); //end $.each(currentItems)
}); //end $.on()
}); //end $(
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="run-code" class="btn btn-success">Click Me</button>
<h4>List 1</h4>
<ul id="listOne">
<li class="columnItem">John</li>
<!--will be removed and put under CommonLister-->
<li class="columnItem">James</li>
<li class="columnItem">Mary</li>
<!--will be removed and put under CommonLister-->
</ul>
<h4>List 2</h4>
<ul id="listTwo">
<li class="columnItem">John</li>
<!--will be removed and put under CommonLister-->
<li class="columnItem">Mark</li>
<li class="columnItem">Mary</li>
<!--will be removed and put under CommonLister-->
</ul>
<h4>Common List</h4>
<ul id="CommonLister">
<!--Extra ul will be added here-->
</ul>
It's invalid nesting a ul directly in a ul like this but if you have to, you could use jquery wrapAll:
$( "li" ).wrapAll( "<ul></ul>" );
See fiddle: https://jsfiddle.net/9xLt6d9f/
I agree with charlietfl that it seems strange to do it this way. However, to answer your question, the best way to force this improperly formatted HTML code would be hardcode it into your original file. Try the following code for the end of your file:
<h4>Common List</h4>
<ul id="CommonLister">
<ul id="CommonListerSub">
<!--Extra ul will be added here-->
</ul>
</ul>
Then, simply change one line of your code:
var $mergeColumn = $('#CommonListerSub'); //Common list reference
This will force it to list the list items under the nested ul tags.
I hope this is an acceptable solution. If for some reason it doesn't work, please comment as to what additional limitations you have, and perhaps share the link of the page that is giving you the required template or format specifications.
I have an array in javascript called menuElm that has <ul> elements in it:
<ul id="1"></ul>
<ul id="2"></ul>
<ul id="3"></ul>
I have a page in HTML that has the following:
<ul id="menu">
<li class="menu-item"></li>
<li class="menu-item"></li>
<li class="menu-item"></li>
</ul>
I want to add the elements of menuElm to the HTML page so it would look like this:
<ul id="menu">
<li class="menu-item">
<ul id="1"></ul>
</li>
<li class="menu-item">
<ul id="2"></ul>
</li>
<li class="menu-item">
<ul id="3"></ul>
</li>
</ul>
I have tried the following, but the <ul> elements just wont show up in the page nor in the code:
function CreateMenu() {
var menuElm;
var k = 0;
menuElm = createElm("ul");
menuElm.id = ++k;
for (var i = 0; i < menuElm.length; ++i) {
document.getElementsByClassName("menu-item")[i].appendChild(menuElm[i]);
}
}
I am new with JavaScript, what am I doing wrong?
menuElm.length
The ul element doesn't have a length, so you are looping from 0 to 0, which is 0 iterations.
menuElm = createElm("ul");
This function isn't defined. You need document.createElement('ul');
menuElm = createElm("ul");
menuElm.id = ++k;
You appear to be creating one list item, and then changing its ID and appending it multiple times.
You need a new list item each time you go around the loop.
appendChild(menuElm[i]);
You've been treating menuElm as an element previously. It isn't an array, [i] makes no sense here.
$("#menu").find('li').each(function(i){
$(this).append(menuElm[i]);
});
/* if you want to use jquery here is the code to append */
First of all I am sorry that I cannot explain the scenario as for my poor english.This is what actually I need to do.
I have a list as follows,
<ul id="sortable" class="sortable">
<li id="1">1</li>
<li id="2">2</li>
<li id="3">3</li>
<li id="4">4</li>
</ul>
list IDs and their values are same.Normally,if I move list ID 4 to top using jquery sortable then I get the new list as,
<ul id="sortable" class="sortable">
<li id="4">4</li>
<li id="1">1</li>
<li id="2">2</li>
<li id="3">3</li>
</ul>
But What I need to do is rename/reorder the IDs to Ascending as for current order of list.
which means
ID 4 => ID 1
ID 1 => ID 2
ID 2 => ID 3
ID 3 => ID 4
Is this possible using jQuery .sortable(). If so how would I overcome this problem?
Thanks a lot.
Yes, you can do it with any of a number of supported events. For this example I'll use stop:
$(".sortable").sortable({
stop: function(e, ui) {
$(this).children("li").each(function(idx, elt) {
$(elt).attr("id", idx);
});
}
});
However note that this (changing id-s) is generally considered bad practice, there should be a way for you to achieve your results without it. Also, if you're concerned with backward compatibility remember that id-s starting with a number are not part of the standard in HTML4.
You can sort like this
function sort_by_id(a, b) {
var sa = a.id, sb = b.id;
return sb>sa ? -1 : sb<sa ? 1 : 0;
}
function sortList(){
var list = $("#sortable > li").get();
list.sort(sort_by_id);
for (var i = 0; i < list.length; i++) {
list[i].parentNode.appendChild(list[i]);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
Sort list
<ul id="sortable" class="sortable">
<li id="4">4</li>
<li id="1">1</li>
<li id="2">2</li>
<li id="3">3</li>
</ul>