reorder list elements - jQuery? [duplicate] - javascript

This question already has answers here:
How may I sort a list alphabetically using jQuery?
(10 answers)
Closed 5 years ago.
Is it possible to reorder <li> elements with JavaScript or pure jQuery. So if I have a silly list like the following:
<ul>
<li>Foo</li>
<li>Bar</li>
<li>Cheese</li>
</ul>
How would I move the list elements around? Like put the list element with Cheese before the list element with Foo or move Foo to after Bar.
Is it possible? If so, how?

var ul = $("ul");
var li = ul.children("li");
li.detach().sort();
ul.append(li);
This is a simple example where <li> nodes are sorted by in some default order. I'm calling detach to avoid removing any data/events associated with the li nodes.
You can pass a function to sort, and use a custom comparator to do the sorting as well.
li.detach().sort(function(a, b) {
// use whatever comparison you want between DOM nodes a and b
});

If someone is looking to reorder elements by moving them up/down some list one step at a time...
//element to move
var $el = $(selector);
//move element down one step
if ($el.not(':last-child'))
$el.next().after($el);
//move element up one step
if ($el.not(':first-child'))
$el.prev().before($el);
//move element to top
$el.parent().prepend($el);
//move element to end
$el.parent().append($el);

One of my favorite things about jQuery is how easy it is to write tiny little add-ons so quickly.
Here, we've created a small add-on which takes an array of selectors, and uses it to order the children of the target elements.
// Create the add-on
$.fn.orderChildren = function(order) {
this.each(function() {
var el = $(this);
for(var i = order.length - 1; i >= 0; i--) {
el.prepend(el.children(order[i]));
}
});
return this;
};
// Call the add-on
$(".user").orderChildren([
".phone",
".email",
".website",
".name",
".address"
]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="user">
<li class="name">Sandy</li>
<li class="phone">(234) 567-7890</li>
<li class="address">123 Hello World Street</li>
<li class="email">someone#email.com</li>
<li class="website">https://google.com</li>
</ul>
<ul class="user">
<li class="name">Jon</li>
<li class="phone">(574) 555-8777</li>
<li class="address">123 Foobar Street</li>
<li class="email">jon#email.com</li>
<li class="website">https://apple.com</li>
</ul>
<ul class="user">
<li class="name">Sarah</li>
<li class="phone">(432) 555-5477</li>
<li class="address">123 Javascript Street</li>
<li class="email">sarah#email.com</li>
<li class="website">https://microsoft.com</li>
</ul>
The function loops backwards through the array and uses .prepend so that any unselected elements are pushed to the end.

Here is a jQuery plugin to aid with this functionality: http://tinysort.sjeiti.com/

something like this?
​var li = $('ul li').map(function(){
return this;
})​.get();
$('ul').html(li.sort());
demo
I was somewhat lost you may be wanting something like this...
$('ul#list li:first').appendTo('ul#list'); // make the first to be last...
$('ul#list li:first').after('ul#list li:eq(1)'); // make first as 2nd...
$('ul#list li:contains(Foo)').appendTo('ul#list'); // make the li that has Foo to be last...
more of it here1 and here2

Have a look at jquery ui sortable
http://jqueryui.com/demos/sortable/

Related

How to find the class of element in a each loop

I am trying to create a menu system where I can change the style of the active page item in the menu. I am using a separate body class on each page, then I want to cycle through the li in the menu and find a match to the body class. At that match I will add the new styling to that menu item.
Here is my code so far.
HTML
<body class="home-state">
...
<div class="menu-left">
<ul>
<li class="home-state">
Home
</li>
<li class="work-state">
Work
</li>
<li class="services-state">
Services
</li>
<li class="about-state">
About
</li>
<li class="blog-state">
Blog
</li>
<li class="shop-state">
Shop
</li>
<li class="contact-state">
<a data-toggle="modal" href="#modal-coworking">Contact</a>
</li>
<li class="project-state">
Project brief
</li>
</ul>
</div>
...
</body>
JS
var bodyClass = $("body").attr('class');
$('.menu-left ul li').each(function(){
First: I want to find the element's class here I have used $(this).attr("class"); which didn't work
var element = $(this);
Second: I want to use a if statement to check to see if the class matches the bodyClass
console.log(element);
Last: If there is a match I want to add the class .active to the element li.
});
Given that elements can have multiple classes, I'd suggesting changing your body element to use a data- attribute rather than a class to specify what the current page is:
<body data-current="home-state">
Then the JS needed to add the active class to the relevant menu item is simple:
$("li." + $("body").attr("data-current")).addClass("active")
You don't need to loop over the menu items comparing classes as mentioned in the question, because you can just directly select the required li element based on its class.
In the event that the body element doesn't have a data-current attribute then $("body").attr("data-current") would return undefined, which would mean the code above tries to select an element with $("li.undefined") and add a class to it. Probably you have no elements with such a class so that would be harmless, but if you wanted to explicitly test that the data-current attribute exists:
var current = $("body").attr("data-current")
if (current) {
$("li." + current).addClass("active")
}
You can do this in couple ways, here is the simple way to do this;
var bodyClass = $("body").attr('class');
$("li." + bodyClass).addClass("active")
You can also use a loop for this one;
var bodyClass = $("body").attr('class');
$(".menu-left li").each(function(i, classes) {
if (bodyClass === $(this).attr("class")) {
$(this).addClass("active")
}
})
both will do the job.
enter image description here
enter image description here
as the comment said,the element can have more than one class ,so you should check it one by one
You missed to bind the click event for the menu item. Follow like below
var bodyClass = $("body").attr('class');
$('.menu-left ul li').on( "click", function() {
var myClass = $(this).attr("class");
alert(myClass);
});
Tested: https://codepen.io/anon/pen/XzYjGY

Put Duplicates under Common Element JavaScript/Jquery

I have the following code.Now I am building the list using Jquery. How do I do this using Javascript/JQuery?
Html(raw)after completion should look like this
<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>
Jquery/JavaScrpit
function myFunctioner(){
$(() => {
let names = [];
let nameSet = new Set();
$("li.columnItemer").each((idx, ele) => {
nameSet.add($(ele).html())
});
var $common = $("<ul>").addClass("commmonLister");
nameSet.forEach((name) => {
if ($("li:contains(" + name + ")").length > 1) {
$("li:contains(" + name + ")").remove();
$("<li>").addClass("columnItemer").html(name).appendTo($common);
}
});
$common.appendTo($(".CommonLister"));
});
}
The above code only works if the list already exists on HTML not when dynamically creating the list. I will be building the list by Ajax query. really appreciate in if you guys can show me how to implement the above code dynamically as the list is built on click event.
Here is what I've got. I don't use the new Javascript notation (not really a fan of it), though I'm sure you could transcribe what I've written into ES if you want to keep it consistent in your project.
I took a very similar approach to you, however I did not dynamically create the element. If you know this element will exist on the page anyway, my personal philosophy is just let it exist there and be empty so that you don't have to create it on your own.
If these lists are being loaded dynamically (something I couldn't really test out while using codepen) then put this into a function called after the list elements have been created. Preferably you would simply go through the data when it is loaded and make the applicable DOM changes only once, but sometimes we do what we must
$(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">
</ul>

Accessing a specific li within a ul

After looking at past examples and source code I have made, I can't seem to work out accessing a specific <li><a>the value in this</a></li> based on a parameter sent in.
Mockup:
<ul class="selectBox-dropdown-menu selectBox-options size-dropdown mediumSelect footwear" style="top: 309px; left: 34px; display: none;">
<li class="" style="display: none;"><a rel=""></a></li>
<li class="size-not-in-stock"><a rel="3096786:6"> 6</a></li>
<li class="size-not-in-stock"><a rel="3096787:6.5"> 6.5</a></li>
<li class=""><a rel="3096788:7"> 7</a></li>
<li class="selectBox-selected"><a rel="3096789:7.5"> 7.5</a></li>
<li class=""><a rel="3096790:8"> 8</a></li>
<li class=""><a rel="3096791:8.5"> 8.5</a></li><li><a rel="3096792:9"> 9</a></li>
<li><a rel="3096793:9.5"> 9.5</a></li><li><a rel="3096794:10"> 10</a></li>
<li><a rel="3096795:10.5"> 10.5</a></li><li><a rel="3096796:11"> 11</a></li>
<li><a rel="3096797:11.5"> 11.5</a></li><li><a rel="3096798:12"> 12</a></li>
<li><a rel="3096799:12.5"> 12.5</a></li><li><a rel="3096800:13"> 13</a></li>
<li><a rel="3096801:14"> 14</a></li><li><a rel="3096802:15"> 15</a></li></ul>
</ul>
Here is what I am trying to get. Let us say that a user puts in a value of 7, well than it should find the corresponding <li><a></a></li> that contains the number 7 and click it.
My troubles are with finding that value inside this, I know I need to use find within the <ul> but what stumps me is based on a value.
UPDATE:
I just want to make clear that, this is something that is going to be an auto process so I am trying to make it so I don't have to do anything except load the page.
You need something like
var test = "the content to seek";
$('ul.footwear').find('a').filter(function(idx, el){
return $.trim($(this).text()) == $.trim(test);
}).closest('li').trigger('click')
Demo: Fiddle
There is no need to loop through and read the innerHTML of every element like all of the other solutions appear to be doing. You can just do it with a selector.
Since the rel attribute seems to have the data you are after at the end :size, you can use use :has() and ends with $= selectors to get the lis you are after.
var num = 7;
var elems = $(".footwear li:has(a[rel$=':" + num + "'])");
console.log(elems.length);
And if you want to click it, than you call .click() or .trigger("click")
function findAndClick (size) {
var elem = $(".footwear li:has(a[rel$=':" + size + "'])");
elem.trigger("click");
}
And to trigger it on the page load it would be something like
$(window).on("load", function() { findAndClick(7); } );
or document ready
$( function() { findAndClick(7); } );
Sad thing is, this solution appears to be great with a simple selector, but the performance can be subpar. If there is only going to be one element with the size, the best performance would be an each() loop and breaking out of it when you find the one element. No need to look at the other elements.
The best performing would be an each()
function findAndClick (size) {
var elem;
size = size.toString();
$('.footwear').find('a').each(function () {
if ($.trim($(this).text()) == size) { //compare the text
elem = $(this).parent(); //set the element that contains the link
return false; //exit each loop
}
});
if (elem) {
elem.trigger("click"); //fire click
}
}
For even better performance, eliminate the need to read the text of the element or use a ends with selector. Add a data attribute to the element.
<li data-size="7">
and than you would just use a selector
function findAndClick (size) {
$('.footwear li[data-size="' + size + '"]').trigger("click");
}
I would optimize this by making your structure better suited for these types of queries
<li id="10"><a rel="3096793:9.5"> 9.5</a></li><li><a rel="3096794:10"> 10</a></li>
Put an id on the li that corresponds to the value of the a tags.
Then you can do a simple $("#10") selector
While it's possible to make complex selectors based on filters etc, keep in mind that performance will not be great in general for non browser backed selectors (pseudo selectors)
Since you have an attribute rel that finish with the content, you can use this:
$('a[rel$="\:'+valueToMatch+'"]').parent()

find an element by style with jquery

How could I find an element in an HTML document using it's style properties?
here is an example:
HTML:
<ul>
<li style='z-index=1;'>e1</li>
<div style='z-index=8;'>div</div>
<li style='z-index=2;'>e2</li>
<li style='z-index=3;'>e3</li>
<li style='z-index=4;'>e4</li>
<li style='z-index=5;'>e5</li>
<ul>
The question is how do i select, for example..: the element <li> with z-index=4.
and how to select all div's with z-index=8 ...
If the style is set inline, you can use an attribute selector:
$('li[style*="z-index:4"]') //returns any li's with z-index = 4
see here. The advantage to this method is that it is very fast.
If the style is set via a stylesheet, you can access it this way:
var elem;
var elems = $("li");
for(var i=0; i<elems.length; i++) {
if($(elems[i]).css('z-index') == '4') {
elem = elems[i]; //assign elem we found
break; //exit loop early
}
}
Note Webkit browsers, (Safari, Chrome, etc), will not return a z-index value unless it is positioned as well. See this example
Also, for loop is still faster than .filter()
There isn't a style selector (how would it work, the style is a combination of inherited and explicitly stated rules), but you can filter (demo):
var things = $("li").filter(function() {
return $(this).css('z-index') == '4';
});
Now if you are using z-index to attach a piece of data to an HTML element you might have more luck using data attributes (cleaner, and searchable by Sizzle). One interpretation might look like this: (demo)
<div data-id='8'>div</div>
<ul>
<li data-id='1'>e1</li>
<li data-id='2'>e2</li>
<li data-id='3'>e3</li>
<li data-id='4'>e4</li>
<li data-id='5'>e5</li>
<ul>
<script>
alert($('[data-id=4]').text())
alert($('[data-id=8]').text())
</script>

Use jQuery to sort List Items alphabetically - then sort special items Numerically [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How may I sort a list alphabetically using jQuery?
I'm using jQuery to come to the rescue for a limited CMS setup.
I need to sort an ordered list alphabetically, but then I also need to be able to place "special" list items at the top of the list and sort again only those special items descending by their "optional" numerical value.
For example if this was my original markup:
<ul>
<li class=" ">C</li>
<li class=" ">A</li>
<li class=" ">B</li>
<li class=" ">E</li>
<li class=" ">D</li>
<li class="3">Z</li>
<li class="6">Y</li>
<li class="14">X</li>
</ul>
... I would want jQuery to sort it so this would be the resulting DOM content:
<ul>
<li class="14">X</li>
<li class="6">Y</li>
<li class="3">Z</li>
<li class=" ">A</li>
<li class=" ">B</li>
<li class=" ">C</li>
<li class=" ">D</li>
<li class=" ">E</li>
</ul>
If sorting by a class value is not possible or is overly convoluted, perhaps I could use the following markup structure instead:
<ul>
<li><span class="numerical">3</span><span class="alphabetical">B</span></li>
</ul>
Does anyone know what jQuery code would allow me to do this? Would I need to run a series of nested "each" actions and "insertAfter" and "insertBefore" functions that somehow compare values? I would think there is a better way, but I'm not sure where to begin my research.
I'm open to any and all suggestions. I'll also be trying to figure this out on my own in the meantime, but I'm still a jQuery rookie so I doubt I'll find the right code on my own :)
Thanks!!
You need a comparator function, and a way to rearrange the elements. Plugins are available which given the former will do the latter for you, although if the elements are the sole children of a single parent it's pretty easy (see below).
For your comparator, you'll need something which can be given a pair of your <li> elements, and tell you which comes first:
function myCompare(a, b) {
var cls_a = parseInt(a.classList, 10);
var cls_b = parseInt(b.classList, 10);
cls_a = cls_a || -1 ; // make blank class == -1
cls_b = cls_b || -1 ; // ditto
if (cls_a === cls_b) {
var str_a = a.innerText || a.textContent;
var str_b = b.innerText || b.textContent;
return str_a.localeCompare(str_b);
} else {
return cls_a - cls_b; // numeric descending sort
}
}
and for rearranging:
var $el = $('li');
var $ul = $('ul');
$el.sort(myCompare); // from above
$el.each(function() {
$ul.append(this);
});
The .each loop works by just taking each sorted item, and adding it to the end of the <ul> - when there's none left, it's done.
Shorter versions of the above are possible, e.g.:
$('li').sort(myCompare).appendTo($('ul'));
See this jsfiddle

Categories

Resources