I want to randomize the children elements of any <div>, <ul> on load with javascript. I am searching for the best approach to do it. Can some one help?
Suppose i have a <ul> with 5 <li> elements. On load i want the <li> elements to appear in random order.
Quicky out of my head:
Remove all the items in the <ul> with detach
Store them in an array.
Shuffle that array
Insert elements in <ul> again.
Also take a look at this question: randomize div elements
Here's how I did it (JSFiddle example here: http://jsfiddle.net/LNvqr/2/)
If you use jQuery and have HTML similar to this:
<div>
<ul id="rndList">
<li id="itemOne">one</li>
<li id="itemTwo">two</li>
<li id="itemThree">three</li>
<li id="itemFour">four</li>
<li id="itemFive">five</li>
</ul>
</div>
Then you could simply use .detach to remove and store the array of the <li> elements.
Next, with a copy of the array, use Math.random() to generate a (pseudo)random integer between 0 and one less than the size of the array. Use this as the random index to be copied from the original (ordered) list in to the new (randomly-ordered) one.
Remove the randomly-chosen element from the original array on each iteration and choose a new random one until all elements have been re-inserted:
function shuffleList() {
var origList = $("#rndList li").detach();
var newList = origList.clone();
for (var i = 0; i < newList.length; i++) {
//select a random index; the number range will decrease by 1 on each iteration
var randomIndex = randomInt(newList.length - i);
//place the randomly-chosen element into our copy and remove from the original:
newList[i] = origList.splice(randomIndex, 1);
//place the element back into into the HTML
$("#rndList").append(newList[i]);
}
}
function randomInt(maxNum) { //returns a random integer from 0 to maxNum-1
return Math.floor(Math.random() * maxNum);
}
You can achieve this with below code:
$(function () {
var parent = $("#parent-container");
var divs = parent.children();
while (divs.length) {
parent.append(divs.splice(Math.floor(Math.random() * divs.length), 1)[0]);
}
});
Related
I am doing one loop where I am matching with some value and assigning class="hidden" to list. But When I run again the loop I want all my list should be without class, so I can assign for other value.
Here is my code.
for (i = list.children.length; i--;) {
li = list.children[i];
match = li.textContent.toLowerCase().indexOf(value.toLowerCase()) > -1;
li.classList.toggle('hidden', !match)
}
But before I run this loop I want all the list without any class so hete in the list I want to remove Class="hidden"
<li class="hidden">
Albania
</li>
Can anyone help me to achieve this
You want to do this before your existing loop? Try this:
var list = document.getElementById("list");
for (i = list.children.length; i--;) {
li = list.children[i];
li.classList.remove("hidden");
}
<ul id="list">
<li class="hidden">foo</li>
<li>bar</li>
<li class="hidden">baz</li>
</ul>
Though it does look like you could do this in the beginning of your existing loop. No need for another loop before that one.
Why not use a combo of Element.classList.contains(), ..remove(), ..add() etc. Lots of info on the MDN page.
For example:
for(i=list.children.length; i--;) {
li = list.children[i];
if (li.textContent.toLowerCase().indexOf(value.toLowerCase()) > -1) {
li.classList.add('hidden');
// or is it li.classList.remove('hidden'); here?
}
}
It is safe to ..add() even if the element has the class already. The class will not be added twice.
I have the following code in my HTML:
<li class="strange">1</li>
<li class="strange">2</li>
<li class="strange">3</li>
<li class="strange">4</li>
I want to choose the exact <li> which contains number '3' as a Text.
Is there any method to choose the exact element?
Can we choose by using some OO-JS methods?
try using jQuery selector :contains
Description: Select all elements that contain the specified text.
$('li:contains("3")')
DEMO
Match exact text
As per #Raoulito mention in his comment here updated answer which match exact text using jQuery filter().
Description: Reduce the set of matched elements to those that match
the selector or pass the function's test.
$(document).ready(function(){
$("li").filter(function() {
return $(this).text() === "3";
}).css("color", "red");
});
DEMO
Try with jQuery contains
$('li:contains("3")');
Demo
Using JavaScript you can do like:
var list = document.getElementsByClassName("strange");
for (i = 0; i < list.length; i++) {
if(list[i].innerHTML ==3)
{
list[i].style.color = "blue";
list[i].style.backgroundColor = "red";
}
}
Check Fiddle.
If you want to use just javascript you can do something like that:
HTML
<ul id="ul">
<li class="strange">1</li>
<li class="strange">2</li>
<li class="strange">3</li>
<li class="strange">4</li>
</ul>
Javascript
var nums = document.getElementById("ul"); // get the ul element
var listItem = nums.getElementsByClassName("strange"); //fetch all elements inside the ul that have a class of strange
var element;
// loop through the list elements
for (var i=0; i < listItem.length; i++) {
// check whether list's inner html is equal to 3
if (parseInt( listItem[i].innerHTML) == 3) {
// set the value of element equal to the list element
element = listItem[i];
break;
}
}
console.log(element); // logs out the element that has the required value, you can use element.innerHTML to check
This only select the element which has exactly '3' as text:
$('li.strange').each(function() {
if ( $(this).text() == '3' ) {
$(this).css('color','red');
}
});
http://jsfiddle.net/dremztou/1/
$('li.strange:contains("3")').addClass('selected'); would select all the elements containing 3, including 13, 23, 33, etc.
I am pushing list items into an array which have a data-sort value on them. When calling them back from the array I need to output them in their data-sort order where 1 would come first, 2 second, and so on. However if the data-sort is equal to 0, I need to do something completely different with the item.
JS
var arr = [];
$('ul li').each(function() {
arr.push($(this));
});
$('ul.main').html('');
$.each(arr, function (i) {
var item = arr[i];
var content = $(item).html();
var itemSort = $(item).data('sort'); //Need to sort by this value
if(itemSort != '0') {
$('ul.main').append('<li>' + content + '</li>')
} else {
$('.another-list').append('<li>' + content + '</li>'); // Sort order of 0's doesn't matter
}
});
HTML
<ul class="main">
<li data-sort="3">Item 1</li>
<li data-sort="2">Item 2</li>
<li data-sort="1">Item 3</li>
<li data-sort="0">Item 4</li>
</ul>
<ul class="another-list"></ul>
The need to create an array from the selected elements is redundant as a jQuery object is an array of the selected elements.
Also, the need to take the html() of an li and then create that in an entirely new li is redundant as you can move elements from one list to another by just using append().
With that in mind you can massively simplify your code by using a combination of sort() and filter():
$('li').sort(function(a, b) {
return $(a).data('sort') > $(b).data('sort');
}).appendTo('.main').filter(function() {
return $(this).data('sort') == 0;
}).appendTo('.another-list');
Example fiddle
In this scenario, I have a series of list items each of which has a corresponding content area. When clicking a list item, a corresponding content area is manipulated (i.e., if the first list item is clicked, then the first content section would be manipulated).
<ul>
<li>List item</li>
<li>List item</li>
<li>List item</li>
</ul>
<div>
<section>Content section</section>
<section>Content section</section>
<section>Content section</section>
</div>
My old-school way of doing this was giving each list item and section an id, such as "li1", "li2", etc. and "section1", "section2", etc. I would then parse the integer off the id of the element that was clicked and manipulate the corresponding section.
Is there a way to determine this without needing extra id attributes? E.g., if I click the 3rd list item and know that is the 3rd, I can use document.querySelector('div:nth-child(3)') to manipulate the third content section. My question is how to know it was the 3rd element in a series that was clicked to begin with.
My first-thought solution was something like this:
var target = e.target;
var parent = e.target.parentNode;
for (var i in parent.childNodes) {
if (parent.childNodes[i].nodeType == 1 && parent.childNodes[i] == target) {
// found it... i+1
}
}
This seems like a rather expensive operation compared to just using IDs, especially if there were many more list items and content sections. I'm hoping there is some node attribute that will give me the correct DOM position that I haven't yet found.
Modern browser-only solutions welcomed.
So i have no ide what you are doing here but there must be a more data oriented approach to this.
Like both the li and the section is referring to the same Product or Person or something so you can find it by that reference.
otherwise you can use the previousElementSibling method to count your location like this
var position = function(el) {
var count = 1;
for(var cur = el.previousElementSibling;
cur !== null; cur = cur.previousElementSibling) {
count++;
}
return count;
};
gl
I’d use something like:
var target = e.target,
i = 0;
while(target = target.previousSibling) {
i += target.nodeType == 1;
}
alert('you clicked on '+i);
Fiddle: http://jsfiddle.net/K5Qg9/1/
You can also try using a data lib or assign stuff to the element expano onload:
var elems = document.getElementsByTagName('li'),
i=0;
for(; elems[i]; i++) {
elems[i].rel = i;
}
Then just fetch e.target.rel onclick. Fiddle: http://jsfiddle.net/UnrCt/
If you can use jQuery: $(elem).index()
Update 2016
Well I've run into this issue again nearly 5 years later only this time I used a much simpler solution using a built-in Array method:
var index = Array.prototype.indexOf.call(event.target.parent.children, event.target);
Ok so I have columns I want added together if there is any information in them. So say I have
Accounts
1
2
3
.
There are 4 account spaces but only 3 accounts.
How do I create java script to add this up.
Live Example
HTML:
<ul>
<li id="accounts">
<p> Accounts </p>
<ul>
<li> 1 </li>
<li> 2 </li>
<li> 3 </li>
<li> . </li>
</ul>
</li>
</ul>
JavaScript:
// Get accounts, ul and set sum to 0
var acc = document.getElementById("accounts"),
ul = acc.getElementsByTagName("ul")[0],
sum = 0;
// Filter out text nodes. Returning an array of <LI> elements
var lis = Array.prototype.filter.call(ul.childNodes, function(li) {
if (li.tagName === "LI") {
return true;
}
});
// Loop through LIs adding up the sum
for (var i = 0, ii = lis.length; i < ii; i++) {
// If it's the last LI element then set the textContent.
if (i === ii - 1) {
lis[i].textContent = sum;
} else {
sum += +lis[i].textContent;
}
}
Disclaimer: Requires Modern Browser or Modernizr.
If your real markup is a list like that, you could do something like this:
// using jquery syntax for brevity; consider it pseudocode
var jList = $('#accounts');
function addColumns() {
var iSum = 0;
jList.find('li').each(function() {
var jLI = $(this);
if(parseFloat(jLI.text()) != 'NaN')
iSum += parseFloat(jLI.text());
});
return iSum;
}
This isn't super-great code. If you give us a little more info about what you're working with, something a little more robust should suggest itself. But the basic idea is that you check a set of elements-of-interest to see if they have summable content (i.e. if their text content can be interpreted as a number); then you add the summable items together.
The requirements of an algorithm like that will impose constraints on the way your "columns" can be marked-up. But there's a near-infinite set of possibilities.