How to shuffle list items randomly in JavaScript - javascript

I was trying to make a word fill quiz but got stuck in between:
looking to shuffle randomly the list items
If the guess is right then how to get to the next blank
Jsfiddle
$(".btn-container li").click(function () {
let val = $(this).text();
$(".blank:empty:first").html(val);
var optionIndex = $(this).index();
if (optionIndex === blankIndex) {
$(this).prop("disabled", true).addClass('disable');
console.log('right');
} else {
console.log('wrong');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content-container">
<p>The bluebird <span class="blank"></span> the <span class="blank"></span> on his <span class="blank"></span></p>
</div>
<div class="btn-container">
<ul id="my_div">
<li>carries</li>
<li>sky</li>
<li>back</li>
</ul>
</div>

here I found easy logic https://stackoverflow.com/a/11972692/6631280
var ul = document.querySelector('#my_div');
for (var i = ul.children.length; i >= 0; i--) {
ul.appendChild(ul.children[Math.random() * i | 0]);
}
<div class="content-container">
<p>The bluebird <span class="blank"></span> the <span class="blank"></span> on his <span class="blank"></span></p>
</div>
<div class="btn-container">
<ul id="my_div">
<li>carries</li>
<li>sky</li>
<li>back</li>
</ul>
</div>

Related

Trying to add a class for clicked elements but if statement doesn't work

<div>
<div class=category> Birthdays </div>
<div class=category> Anniversaries </div>
<div class=category> Newborns </div>
<div class=category> Weddings </div>
</div>
<ul>
<li class="product-filter-items">Birthdays</li>
<li class="product-filter-items">Weddings</li>
<li class="product-filter-items">Newborns</li>
<li class="product-filter-items">Anniversaries</li>
</ul>
<script>
let proCatList = document.querySelectorAll(".category")
let proFilterItems = document.querySelectorAll(".product-filter-items")
for(let i = 0; i < proFilterItems.length; i++){
proFilterItems[i].addEventListener("click" , function(){
if (proCatList[i].textContent.toUpperCase().replace(/[\n\r]+|[\s]{2,}/g, ' ').trim() == proFilterItems[i].textContent.toUpperCase().replace(/[\n\r]+|[\s]{2,}/g, ' ').trim() ){
proFilterItems[i].classList.add("active-filter")
console.log("Class Added")
}
})
}
</script>
I am trying to add a class based on a click event. What I am trying to do is if classname, category and product-filter-items are equal then it should add a classname called active-filter on click. Can anyone point out why this statement does not recognise the textContent of proCatList?
The iteration param i can't be used in the event handler. Therefor you could use the index of the clicked element, which you can call with this.
For getting the index, you can use the following small function:
const getIndex = elem => [...elem.parentNode.children].indexOf(elem);
Working example:
let proCatList = document.querySelectorAll(".category");
let proFilterItems = document.querySelectorAll(".product-filter-items");
/* small function for getting the index */
const getIndex = elem => [...elem.parentNode.children].indexOf(elem);
for (let i = 0; i < proFilterItems.length; i++) {
proFilterItems[i].addEventListener("click", function() {
const elem_index = getIndex(this);
if (proCatList[elem_index].textContent.toUpperCase().replace(/[\n\r]+|[\s]{2,}/g, ' ').trim() == this.textContent.toUpperCase().replace(/[\n\r]+|[\s]{2,}/g, ' ').trim()) {
this.classList.add("active-filter");
console.log("Class Added");
}
})
}
<div>
<div class=category> Birthdays </div>
<div class=category> Anniversaries </div>
<div class=category> Newborns </div>
<div class=category> Weddings </div>
</div>
<ul>
<li class="product-filter-items">Birthdays</li>
<li class="product-filter-items">Weddings</li>
<li class="product-filter-items">Newborns</li>
<li class="product-filter-items">Anniversaries</li>
</ul>

pure JS handling if content text length < 0 then hide

I tried to handling,
if content text length < 0
then set class match-name & divider style to display none.
it seem like not working with below code.
var newsMatchName = document.querySelectorAll(".match-name");
var newsMatchNameDivider = document.querySelectorAll(".divider");
for (var i = 0; i < newsMatchName.length; i++) {
if (newsMatchName[i].length < 0) {
console.log(newsMatchName[i].length)
for (var i = 0; i < elem.length; i++) {
newsMatchName[i].style.display = "none";
newsMatchNameDivider[i].style.display = "none"
}
}
}
<div class="news-content">
<div class="match-name"></div>
<div class="divider"></div>
<div class="title">Title Text</div>
<div class="footer">
<span class="author">Author</span>
<span class="spacer"></span>
<div class="timeline">
<span class="date">2021-04-01</span>
<span class="time">12:15</span>
</div>
</div>
</div>
I have corrected the code for you:
var newsMatchName = document.querySelectorAll(".match-name");
var newsMatchNameDivider = document.querySelectorAll(".divider");
for (var i = 0; i < newsMatchName.length; i++) {
if (newsMatchName[i].innerText.length <= 0) {
newsMatchName[i].style.display = "none";
newsMatchNameDivider[i].style.display = "none"
}
}
<div class="news-content">
<div class="match-name"></div>
<div class="divider"></div>
<div class="title">Title Text</div>
<div class="footer">
<span class="author">Author</span>
<span class="spacer"></span>
<div class="timeline">
<span class="date">2021-04-01</span>
<span class="time">12:15</span>
</div>
</div>
</div>
I test the length of the text in match-name
Length can be 0 or more, not <0, so use
newsMatchName[i].textContent.length === 0
but I suggest this:
var newsMatchName = document.querySelectorAll(".match-name");
var newsMatchNameDivider = document.querySelectorAll(".divider");
newsMatchName.forEach((name, i) => {
const textLen = name.textContent.trim().length;
name.classList.toggle("hide", textLen === 0);
newsMatchNameDivider[i].classList.toggle("hide", textLen === 0);
})
.hide {
display: none;
}
<div class="news-content">
<div class="match-name"></div>
<div class="divider">This will be hidden</div>
<div class="title">Title Text</div>
<div class="footer">
<span class="author">Author</span>
<span class="spacer"></span>
<div class="timeline">
<span class="date">2021-04-01</span>
<span class="time">12:15</span>
</div>
</div>
</div>

How to search for value in all descendant textNodes(Javascript)?

So basically I am making a Chrome extension which sorts the search results on Ebay by their popularity(number of times sold). To do this I need to find all li elements which have a descendant text node containing the text ...+ Sold where ... is a number.
Basically, search results on Ebay look like this:
<li class="s-item">
<div class="s-item__wrapper clearfix">
<div class="s-item__image-section">
<!-- other stuff -->
</div>
<div class="s-item__info clearfix">
<!-- other stuff -->
<div class="s-item__details clearfix">
<!-- other stuff -->
<div><span><span>62+ Sold</span></span></div>
</div>
</div>
</div>
</li>
In every li element I have to search for the text Sold and extract the number out of that text node to process it further. How can I do that?
You cannot do that only by using childNodes or children properties because they return only the children and not all descendants of the current node. So you will have to write your own function for that, something like:
function getDescendants(node, arr) {
var i;
arr = arr || [];
for (i = 0; i < node.childNodes.length; i++) {
arr.push(node.childNodes[i])
getDescendants(node.childNodes[i], arr);
}
return arr;
}
Using this function, you just simply iterate over all descendants and check if they are text nodes ( nodeType == 3 ) and after that search for the word Sold in them. Extracting the number is pretty easy after that.
Something like:
var searchValue = "Sold";
var descendants = getDescendants(listItem);
for(var j = 0; j < descendants.length; j++) {
if(descendants[j].nodeType == 3){
if(descendants[j].nodeValue.indexOf(searchValue) > -1){
var text = descendants[j].nodeValue.trim();
//"37+ Sold" for example
var soldNr = text.substring(0, text.indexOf(searchValue)-2);
//you process your number(soldNr) further
}
}
}
Use a selector string: select li.s-item span to select all spans which descend from an li with a class of s-item, check to see if the span's only child is a text node with "Sold" in it, and if so, do whatever you need to do with it.
If you're sure that any <li> will do, and not just those with a class of s-item, then use 'li span' instead:
document.querySelectorAll('li span').forEach(({ childNodes, textContent }) => {
if (childNodes.length !== 1 || childNodes[0].nodeType !== 3 || !textContent.includes('Sold')) return;
const count = textContent.match(/\d+/);
console.log('Processing span with sold number ' + count);
});
<ul>
<li class="s-item">
<div class="s-item__wrapper clearfix">
<div class="s-item__image-section">
<!-- other stuff -->
</div>
<div class="s-item__info clearfix">
<!-- other stuff -->
<div class="s-item__details clearfix">
<!-- other stuff -->
<div><span><span>62+ Sold</span></span>
</div>
</div>
</div>
</div>
</li>
<li class="s-item">
<div class="s-item__wrapper clearfix">
<div class="s-item__image-section">
<!-- other stuff -->
</div>
<div class="s-item__info clearfix">
<!-- other stuff -->
<div class="s-item__details clearfix">
<!-- other stuff -->
<div><span><span>333+ Sold</span></span>
</div>
</div>
</div>
</div>
</li>
</ul>

How to show images when hovered a single list element of ngfor ulist in angular2?

showfavstar(val)
{
this.favstar = true;
}
<ul class="listboxtickets">
<li class="selectlistticket" *ngFor="let fav of favlist" (mouseover)="showfavstar(fav.req_id)" (mouseleave)="hidefavstar()">
<div class="atickname" (click)="timetracker(fav.req_id,fav.ticket_summary,fav.time_logged*60*1000)"> {{fav.ticket_summary.substring(0,20)}} </div>
<div> {{fav.time_logged} </div>
<div class="atickstat" [hidden]="!favstar"> <img class="staraimg" src="assets/images/star_icon.png" (click)="removefav(fav.req_id)"/> </div>
<div class="namelinet"> <img src="assets/images/text_bottomline.png"/> </div>
</li>
</ul>
I want to show star image for only hovered list?Now i get all the star images
This cannot be achived using single variable which you took here i.e favstar.
Try your code like this
<ul class="listboxtickets">
<li class="selectlistticket" *ngFor="let fav of favlist" (mouseover)="showfavstar(fav)" (mouseleave)="hidefavstar(fav)">
<div class="atickname" (click)="timetracker(fav.req_id,fav.ticket_summary,fav.time_logged*60*1000)">
{{fav.ticket_summary.substring(0,20)}}
</div>
<div> {{fav.time_logged} </div>
<div class="atickstat" [hidden]="!fav?.Show">
<img class="staraimg" src="assets/images/star_icon.png" (click)="removefav(fav.req_id)"/>
</div>
<div class="namelinet"> <img src="assets/images/text_bottomline.png"/> </div>
</li>
</ul>
showfavstar(fav){
fav.Show = true;
for(let i = 0; i < this.favlist.length; i++){
this.favlist[i].Show = false;
}
}
hidefavstar(val){
fav.Show = true;
for(let i = 0; i < this.favlist.length; i++){
this.favlist[i].Show = true;
}
}

Sorting of divs in Jquery

My code have divs of movies which are used to display movie with poster, now i want jquery to sort divs for me on basis of title,
<!-- Movie -->
<div class="movie" title="Reservoir Dogs">
<div class="movie-image">
<span class="play"><span class="name">Reservoir Dogs |
Reservoir Dogs</span></span><img src="http://ia.media-imdb.com/images/M/MV5BMTQxMTAwMDQ3Nl5BMl5BanBnXkFtZTcwODMwNTgzMQ##._V1_SX300.jpg" alt="movie">
</div>
<div class="rating">
<p>RATING</p>
<div class="stars">
<div class="stars-in4">
</div>
</div>
<span class="comments"></span>
</div>
</div>
<!-- end Movie -->
<!-- Movie -->
<div class="movie" title="Saw">
<div class="movie-image">
<span class="play"><span class="name">Saw |
Saw</span></span><img src="http://ia.media-imdb.com/images/M/MV5BMjAyNTcxNzYwMV5BMl5BanBnXkFtZTgwMzQzNzM5MjE#._V1_SX300.jpg" alt="movie">
</div>
<div class="rating">
<p>RATING</p>
<div class="stars">
<div class="stars-in4">
</div>
</div>
<span class="comments"></span>
</div>
</div>
<!-- end Movie -->
<!-- Movie -->
<div class="movie" title="Scarface">
<div class="movie-image">
<span class="play"><span class="name">Scarface |
Scarface</span></span><img src="http://ia.media-imdb.com/images/M/MV5BMjAzOTM4MzEwNl5BMl5BanBnXkFtZTgwMzU1OTc1MDE#._V1_SX300.jpg" alt="movie">
</div>
<div class="rating">
<p>RATING</p>
<div class="stars">
<div class="stars-in4">
</div>
</div>
<span class="comments"></span>
</div>
</div>
<!-- end Movie -->
<!-- Movie -->
<div class="movie" title="Signs">
<div class="movie-image">
<span class="play"><span class="name">Signs |
Signs</span></span><img src="http://ia.media-imdb.com/images/M/MV5BNDUwMDUyMDAyNF5BMl5BanBnXkFtZTYwMDQ3NzM3._V1_SX300.jpg" alt="movie">
</div>
<div class="rating">
<p>RATING</p>
<div class="stars">
<div class="stars-in3">
</div>
</div>
<span class="comments"></span>
</div>
</div>
<!-- end Movie -->
<!-- Movie -->
<div class="movie" title="Stir of Echoes">
<div class="movie-image">
<span class="play"><span class="name">Stir of Echoes |
Stir of Echoes</span></span><img src="http://ia.media-imdb.com/images/M/MV5BMTU0OTAyMDQzNV5BMl5BanBnXkFtZTcwNTg1NjYyMQ##._V1_SX300.jpg" alt="movie">
</div>
<div class="rating">
<p>RATING</p>
<div class="stars">
<div class="stars-in4">
</div>
</div>
<span class="comments"></span>
</div>
</div>
<!-- end Movie -->
Now here is my current code
$(document).ready(function () {
var desc = false;
document.getElementById("sort").onclick = function () {
sortUnorderedList("movie", desc);
desc = !desc;
return false;
}
});
function sortUnorderedList(ul, sortDescending) {
if (typeof ul == "string")
var lis = document.getElementsByClassName("movie");
var vals = [];
for (var i = 0, l = lis.length; i < l; i++)
vals.push(lis[i]);
debugger;
vals.sort(function (a, b) { return a.title - b.title });
//vals[].title.sort();
if (sortDescending)
vals.reverse();
for (var i = 0, l = lis.length; i < l; i++)
lis[i].innerHTML = vals[i].innerHTML;
}
above code is not giving desired result
can u suggest better way to do it
You can significantly simplify your code if you use more jQuery, anyway you are using it. Entire code in this case will be:
$(document).ready(function () {
var desc = false;
$("#sort").click(function () {
sortUnorderedList("movie", desc);
desc = !desc;
});
});
function sortUnorderedList(ul, sortDescending) {
$('.' + ul).sort(function(a, b) {
return sortDescending ? a.title.localeCompare(b.title) : b.title.localeCompare(a.title);
}).appendTo('body');
}
Just note that instead of appendTo('body'), you should append to appropriate container that holds .movie elements. I'm appending to body because this is a container for movie divs in my demo.
Demo: http://jsfiddle.net/212oc0kw/

Categories

Resources