I have a list of <li> I was wondering how I can click and select them to be pushed onto my array.
For example,
<li class="browser_list">
<ul>
<li id="config_3"> Chrome 29</li>
<li id="config_4"> Chrome 31</li>
<li id="config_5"> Chrome 33</li>
<li id="config_6"> Chrome 35</li>
</ul>
</li>
array:
arr = [];
Can vary from size 0-4 depending on what I click
I want to be able to select or unselect (with highlighting) and add config_3, config_4, config_5, config_6 to an array for later use.
This is the solution in pure Javascript.
Alongside the snippet below, here's the same in a fiddle: http://jsfiddle.net/7qxs6hgj/
var list = document.getElementById('browser_list');
var items = list.getElementsByTagName('li');
var arr = [];
for (var i = 0; i < items.length; i++)
{
items[i].onclick = function(event)
{
if (this.className == 'selected')
{
this.className = 'unselected';
var idx = arr.indexOf(this.id);
if (idx >= 0)
arr.splice(idx, 1);
}
else
{
this.className = 'selected';
arr[arr.length] = this.id;
}
document.getElementById('arr').innerHTML = JSON.stringify(arr);
};
}
#browser_list li { cursor: pointer; }
.selected { background-color: #cccccc; }
.deselected { background-color: transparent; }
<ul id='browser_list'>
<li id="config_3"> Chrome 29</li>
<li id="config_4"> Chrome 31</li>
<li id="config_5"> Chrome 33</li>
<li id="config_6"> Chrome 35</li>
</ul>
<div id='arr'></div>
arr = []
$("#browser_list > ul").click(function(event){
if($(event.target).is("li")){
arr.push(event.target)
}
})
Toggle classes and check arrays:
var arr = [];
$(".browser_list ul li").click(function() {
$(this).toggleClass("active"); //add / remove class active;
var index = arr.indexOf(this.id)
if (index > -1) arr.splice(index, 1);
else arr.push(this.id)
});
And a fiddle: http://jsfiddle.net/2ymwdvrn/
Or if you need to get the list of ID's at a later point and dont want to keep a global array:
var arr = $(".browser_list ul li.active").map(function() {
return this.id;
}).get();
You have to do it this way:
$(function(){
$(".browser_list li").click(function(){
var arr = new Array();
$(this).toggleClass("selected");
$(".browser_list .selected").each(function(){
arr.push(this.id);
})
})
})
.selected
{
background:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<li class="browser_list">
<ul>
<li id="config_3"> Chrome 29</li>
<li id="config_4"> Chrome 31</li>
<li id="config_5"> Chrome 33</li>
<li id="config_6"> Chrome 35</li>
</ul>
</li>
Related
I am trying to write some sorting code. I would like to sort a list like:
banana
cake
egg
doughnut
burger
rice
apple
and turn into:
apple
banana
cake
egg
doughnut
burger
rice
<html>
<head>
<title>Sort list items alphabetically with Javascript</title>
<script type="text/javascript">
function sortUnorderedList(ul, sortDescending) {
if(typeof ul == "string")
ul = document.getElementById(ul);
var lis = ul.getElementsByTagName("LI");
var vals = [];
for(var i = 0, l = lis.length; i < l; i++)
vals.push(lis[i].innerHTML);
vals.sort();
if(sortDescending)
vals.reverse();
for(var i = 0, l = lis.length; i < l; i++)
lis[i].innerHTML = vals[i];
}
window.onload = function() {
var desc = false;
document.getElementById("test").onclick = function() {
sortUnorderedList("list", desc);
desc = !desc;
return false;
}
}
</script>
</head>
<body>
<input type="button" id="test" value="Sort List (click again to reverse)"/>
<ul id="list">
<li>banana</li>
<li>cake</li>
<ul>
<li>egg</li>
<li>doughnut</li>
<li>burger</li>
</ul>
<li>rice</li>
<li>apple</li>
</ul>
</body>
</html>
The main issue with your code is that your HTML is invalid; ul cannot be a child of another ul. Only li or ol can. This invalid HTML causes the li to be rendered differently than you expect so the sorting is affected. To fix this correct the HTML so the nested 'cake' ul is within the li.
As you've tagged the question with jQuery, here's a much simple implementation of what you originally had:
jQuery($ => {
let $ul = $('#list');
$('#test').on('click', function() {
let sort = $(this).data('sortasc');
let dir = sort ? [1, -1] : [-1, 1];
$ul.children('li').sort((a, b) => a.innerText.trim() < b.innerText.trim() ? dir[0] : dir[1]).appendTo($ul);
$(this).data('sortasc', !sort);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="test">Toggle sort</button>
<ul id="list">
<li>banana</li>
<li>
cake
<ul>
<li>egg</li>
<li>doughnut</li>
<li>burger</li>
</ul>
</li>
<li>rice</li>
<li>apple</li>
</ul>
I'm wanting to sort this UL numerically and alphabetically, using each items data-char value.
Note: I'm only wanting to sort the parent UL, not the child UL elements.
<ul>
<li data-char="w">
<span>W</span>
<ul>
<li>WWWWWWWWWWWWWW</li>
</ul>
</li>
<li data-char="5">
<span>5</span>
<ul>
<li>55555555555555</li>
</ul>
</li>
<li data-char="a">
<span>A</span>
<ul>
<li>AAAAAAAAAAAAAA</li>
</ul>
</li>
<li data-char="1">
<span>1</span>
<ul>
<li>11111111111</li>
</ul>
</li>
</ul>
I'm able to accomplish this with jQuery by doing:
function sortCharLi(a, b) {
var va = a.dataset.char.toString().charCodeAt(0),
vb = b.dataset.char.toString().charCodeAt(0);
// add weight if it's a number
if (va < 'a'.charCodeAt(0)) va += 100;
if (vb < 'a'.charCodeAt(0)) vb += 100;
return vb < va ? 1 : -1;
}
$('ul > li').sort(sortCharLi).appendTo('ul');
But I'm needing to remove the jQuery dependency so that's not an option any more.
Any ideas how I may do this without jQuery?
JSBIN
You can get the ul using getElemetsByTagName and children li can be get from the element object using children property.
function order(ul) {
// get html children elements of li
// in case of ul children will be li
// ` Array.from` will hell helps to convert them into array
var elements = Array.from(ul.children);
// sort them with the same code
elements.sort(function(a, b) {
var va = a.getAttribute('data-char').charCodeAt(0),
vb = b.getAttribute('data-char').charCodeAt(0),
charCA = 'a'.charCodeAt(0);
// add weight if it's a number
if (va < charCA) va += 100;
if (vb < charCA) vb += 100;
// just get the difference and return to sort them
return va - vb;
});
// append back to update the order
// forEach can be used to update since it's in array format
elements.forEach(function(ele) {
ul.appendChild(ele)
});
}
// get ul tag from dom and pass as parameter
// although you can use id selector or querySelector, etc
// it depends up on your need, here you just need to pass the dom reference of `ul` to be sorted
order(document.getElementsByTagName('ul')[0]);
<ul>
<li data-char="w">
<span>W</span>
<ul>
<li>WWWWWWWWWWWWWW</li>
</ul>
</li>
<li data-char="5">
<span>5</span>
<ul>
<li>55555555555555</li>
</ul>
</li>
<li data-char="a">
<span>A</span>
<ul>
<li>AAAAAAAAAAAAAA</li>
</ul>
</li>
<li data-char="1">
<span>1</span>
<ul>
<li>11111111111</li>
</ul>
</li>
</ul>
UPDATE :
If you want to use them in chain as in jQuery, then extend the prototype
NodeList.prototype.sortElements = function(custom) {
// if custom sort function passed then sort based on that
if (typeof custom === 'function')
return [].slice.call(this).sort(custom);
// otherwise apply sort method directly
return [].slice.call(this).sort();
// you can also use Array.from(this), which only works in latest browsers
}
Array.prototype.updateOrder = function() {
// iterate over array element
this.forEach(function(ele) {
// append to the parent element
ele.parentNode.appendChild(ele);
})
}
// sort them with the same code
function sortFn(a, b) {
var va = a.getAttribute('data-char').charCodeAt(0),
vb = b.getAttribute('data-char').charCodeAt(0),
charCA = 'a'.charCodeAt(0);
// add weight if it's a number
if (va < charCA) va += 100;
if (vb < charCA) vb += 100;
// just get the difference and return to sort them
return va - vb;
}
// get li elements which have `data-char` attribute
document.querySelectorAll('ul li[data-char]')
.sortElements(sortFn) // call sortElements methods we defined with custom sort function
.updateOrder(); // call updateOrder to update the order of element
<ul>
<li data-char="w">
<span>W</span>
<ul>
<li>WWWWWWWWWWWWWW</li>
</ul>
</li>
<li data-char="5">
<span>5</span>
<ul>
<li>55555555555555</li>
</ul>
</li>
<li data-char="a">
<span>A</span>
<ul>
<li>AAAAAAAAAAAAAA</li>
</ul>
</li>
<li data-char="1">
<span>1</span>
<ul>
<li>11111111111</li>
</ul>
</li>
</ul>
This function preserves your original sorter method. The function expects the ul element to be passed:
function sortThem(ul) {
var nodes = Array.prototype.slice.call(ul.childNodes).filter(function(el) {
// Could use QSA with scope depending on browser support here
return el.tagName === 'LI';
});
nodes.sort(function(a, b) {
var va = a.getAttribute('data-char').charCodeAt(0),
vb = b.getAttribute('data-char').charCodeAt(0);
// add weight if it's a number
if (va < 'a'.charCodeAt(0)) va += 100;
if (vb < 'a'.charCodeAt(0)) vb += 100;
return vb < va ? 1 : -1;
});
nodes.forEach(function(node) {
ul.appendChild(node);
});
}
You may use querySelectorAll for $('ul > li'). Pay attention, the right selector should be $('ul > li[data-char]') because you are inrested only in li tags having the data-char as attribute.
To convert the NodeList returned from querySelectorAll to array you can use Array.from.
To substitute the appendTo you may use forEach.
So the code could be:
function sortCharLi(a, b) {
var va = a.getAttribute('data-char').charCodeAt(0),
vb = b.getAttribute('data-char').charCodeAt(0);
// add weight if it's a number
if (va < 'a'.charCodeAt(0)) va += 100;
if (vb < 'a'.charCodeAt(0)) vb += 100;
return vb < va ? 1 : -1;
}
window.onload = function() {
// $('ul > li').sort(sortCharLi).appendTo('ul');
Array.from(document.querySelectorAll('ul > li[data-char]')).sort(sortCharLi).forEach(function(element, index) {
element.parentNode.appendChild(element);
});
}
<ul>
<li data-char="w">
<span>W</span>
<ul>
<li>WWWWWWWWWWWWWW</li>
</ul>
</li>
<li data-char="5">
<span>5</span>
<ul>
<li>55555555555555</li>
</ul>
</li>
<li data-char="a">
<span>A</span>
<ul>
<li>AAAAAAAAAAAAAA</li>
</ul>
</li>
<li data-char="1">
<span>1</span>
<ul>
<li>11111111111</li>
</ul>
</li>
</ul>
UPDATE
A shorter way to convert:
$('ul > li[data-char]').sort(sortCharLi).appendTo('ul');
to pure javaScript can be:
document.querySelectorAll('ul > li[data-char]').sort(sortCharLi).replaceWith();
In order to achieve this result the following methods have to be added:
NodeList.prototype.sort = function(callBack) {
if (typeof callBack === 'function') {
return [].slice.call(this).sort(callBack);
} else {
return [].slice.call(this).sort();
}
}
Array.prototype.replaceWith = function() {
this.forEach(function(element, index) {
element.parentNode.appendChild(element);
});
return this;
}
In this way there exist the possibility to chain methods like in jQuery:
function sortCharLi(a, b) {
var va = a.getAttribute('data-char').charCodeAt(0),
vb = b.getAttribute('data-char').charCodeAt(0);
// add weight if it's a number
if (va < 'a'.charCodeAt(0)) va += 100;
if (vb < 'a'.charCodeAt(0)) vb += 100;
return vb < va ? 1 : -1;
}
NodeList.prototype.sort = function(callBack) {
if (typeof callBack === 'function') {
return [].slice.call(this).sort(callBack);
} else {
return [].slice.call(this).sort();
}
}
Array.prototype.replaceWith = function() {
this.forEach(function(element, index) {
element.parentNode.appendChild(element);
});
return this;
}
window.onload = function () {
document.querySelectorAll('ul > li[data-char]').sort(sortCharLi).replaceWith();
}
<ul>
<li data-char="w">
<span>W</span>
<ul>
<li>WWWWWWWWWWWWWW</li>
</ul>
</li>
<li data-char="5">
<span>5</span>
<ul>
<li>55555555555555</li>
</ul>
</li>
<li data-char="a">
<span>A</span>
<ul>
<li>AAAAAAAAAAAAAA</li>
</ul>
</li>
<li data-char="1">
<span>1</span>
<ul>
<li>11111111111</li>
</ul>
</li>
</ul>
This is the best answer I can snap off from work, but it might need to be tailored to your html structure.
FUNCTION TO SORT UL WITHOUT JQUERY:
function sortUnorderedList(ul, sortDescending) {
if(typeof ul == "string")
ul = document.getElementById(ul);
// Idiot-proof, remove if you want
if(!ul) {
alert("The UL object is null!");
return;
}
// Get the list items and setup an array for sorting
var lis = ul.getElementsByTagName("LI");
var vals = [];
// Populate the array
for(var i = 0, l = lis.length; i < l; i++)
vals.push(lis[i].innerHTML);
// Sort it
vals.sort();
// Sometimes you gotta DESC
if(sortDescending)
vals.reverse();
// Change the list on the page
for(var i = 0, l = lis.length; i < l; i++)
lis[i].innerHTML = vals[i];
}
USAGE:
sortUnorderedList("ID_OF_LIST");
I want to access all tags with id="BasketProduct..."
HTML
<ul class ="productdetails">
<li id="BasketProduct-60">...</li>
<li id="BasketProduct-133">...</li>
<li id="BasketProduct-195">...</li>
<li id="BasketProduct-202">...</li>
</ul>
Edited:
var ul = document.getElementsByClassName('productdetails')[0],
i, temp;
for (i = 0; i < ul.children.length; i += 1) {
temp = ul.children[i].id;
if (temp.indexOf('BasketProduct-') > -1) {
// do smth
}
}
My HTML looks like:
<ul>
<li data-target="12">1</li>
<li data-target="4">2</li>
<li data-target="9">3</li>
<li data-target="15">4</li>
<li data-target="23">5</li>
<li data-target="32">6</li>
<li data-target="7">7</li>
<li data-target="10">8</li>
<li data-target="5">9</li>
<li data-target="2">10</li>
</ul>
What method should I use to get the maximum value from the data-target attributes? Do vanilla JavaScript or jQuery have some native functions for this or I should just use for loop to iterate through all the items and get the maximum value, shouldn't I?
One way (without bothering with an array);
var max = 0;
$("li[data-target]").each(function() {
max = Math.max(max, parseInt($(this).data("target"), 10));
});
alert(max);
use Math.max.apply() method to get max value from a numeric array.
var arr = $('li[data-target]').map(function(){
return $(this).data('target')
});
console.log(Math.max.apply(Math,arr));
Fiddle Demo
Try this: use .map() along with Math function:
var targets = $("li").map(function() {
return $(this).data("target");
}).get();
var max = Math.max.apply(Math,targets);
Demo
This should work...
var array = [];
$('li').each(function() {
array.push($(this).data('target'));
});
var maxNumber = Math.max.apply(Math, array);
alert(maxNumber);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<li data-target="12">1</li>
<li data-target="4">2</li>
<li data-target="9">3</li>
<li data-target="15">4</li>
<li data-target="23">5</li>
<li data-target="32">6</li>
<li data-target="7">7</li>
<li data-target="10">8</li>
<li data-target="5">9</li>
<li data-target="2">10</li>
var maxVal = 0;
$('[data-target]').each(
function(){
if($(this).attr('data-target') > maxVal){
maxVal = $(this).attr('data-target');
}
});
fiddle
Try with this:
var maxValue = 0;
$("li").each(function(index,val){
var value = $(this).attr('data-target');
if(value > maxValue) maxValue= value;
});
Yes you can get max value using for each loop of jquery. For each value of li get its attribute data-target. e.g
var maxVal=0;
$(this).find('li').each(function(){
// cache jquery var
var current = $(this);
var val=parseInt(current.attr( "data-target" ));
if(val > maxVal){
maxVal=val;
}
});
console.log(maxVal);//Its the max value
Turak Vladyslav
below code will work you can check it once
var Lis = $('#test').find('li');
var dataArray = []
for(var i=0;i<Lis.length;i++){
dataArray.push($(Lis[i]).attr('data-target'))
}
var maxDatatTarget = Math.max.apply(null, dataArray)
alert("max data target value"+maxDatatTarget)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="test">
<li data-target="12">1</li>
<li data-target="4">2</li>
<li data-target="9">3</li>
<li data-target="15">4</li>
<li data-target="23">5</li>
<li data-target="32">6</li>
<li data-target="7">7</li>
<li data-target="10">8</li>
<li data-target="5">9</li>
<li data-target="2">10</li>
</ul>
Try this if it works for you :
function calculateMaxTarget(){
var attr[] = $('li').attr('data-target');
var max = 0;
for (var i=0; i < attr.length; i++) {
if(attr[i]>max){
max = attr[i];
}
};
return max;
}
I got a UL like this:
<ul id='mylist'>
<li id='1'><img src='kids.jpg'>kids.jpg</li>
<li id='2'><img src='apple.jpg'>apple.jpg</li>
<li id='3'><img src='toys.jpg'>toys.jpg</li>
<li id='4'><img src='love.jpg'>love.jpg</li>
</ul>
I want to sort it using jquery/javascript like this:
<ul id='mylist'>
<li id='2'><img src='apple.jpg'>apple.jpg</li>
<li id='1'><img src='kids.jpg'>kids.jpg</li>
<li id='4'><img src='love.jpg'>love.jpg</li>
<li id='3'><img src='toys.jpg'>toys.jpg</li>
</ul>
May I know how do I write the code?
$(document).ready(function() {
var ul = $('ul#mylist'),
li = ul.children('li');
li.detach().sort(function(a,b) {
return alphabetical($(a).children('img').attr('src'), $(b).children('img').attr('src'));
});
ul.append(li);
});
function alphabetical(a, b)
{
var A = a.toLowerCase();
var B = b.toLowerCase();
if (A < B){
return -1;
}else if (A > B){
return 1;
}else{
return 0;
}
}
<ul id='mylist'>
<li id='1'><img src='kids.jpg'>kids.jpg</li>
<li id='2'><img src='apple.jpg'>apple.jpg</li>
<li id='3'><img src='toys.jpg'>toys.jpg</li>
<li id='4'><img src='love.jpg'>love.jpg</li>
</ul>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript">
var starting_array = new Array();
var temp_array = new Array();
for(var i = 1 ; i <= 4 ;i++){
starting_array[i] = $('#'+i).find('img').attr('src');
temp_array[i] = $('#'+i).find('img').attr('src');
}
temp_array.sort();
$('#mylist').html('');
var li_data = '';
for(var j=0; j< temp_array.length-1 ; j++ ){
var id = $.inArray(temp_array[j] ,starting_array);
li_data += '<li id="'+ id +'"><img src="'+ temp_array[j] +'" > '+ temp_array[j]+' </li>';
}
$('#mylist').html(li_data);
</script>
You can try this:
var items = $("#mylist > li").detach().get( );
items.sort( srcSort );
$("#mylist").append( items );
function srcSort( a, b ) {
var _a = $(a).children("img").prop("src").toUpperCase();
var _b = $(b).children("img").prop("src").toUpperCase();
if( _a > _b ) return 1;
if( _a < _b ) return -1;
return 0;
}
fiddle here