Jquery change colors with recursion - javascript

Here is jsfiddle of raw code and the result should be like this
<div class="wrapper">
<div class="row">
<div class="col red">R</div>
<div class="col blue">B</div>
<div class="col green">G</div>
<div class="col orange">O</div>
</div>
</div>
The mission is: Last color of previous row should be the first in next row and first color from previuos row should be the second in next row.
I think that I have to use loop and recursion but I don't have enough knowledge to do this.
Thanks in advance :)

You can run through the for loop and do something like this
check this snippet
//last color of previous row should be first in next row
//first color from previous row should be second in next row
var colors = ['red', 'blue', 'green', 'orange'];
$(document).ready(function() {
var rows = $('.row');
rows.each(function(row) {
var index = $(this).index();
var prevRow;
if (index > 0)
prevRow = $(this).prev();
colorColumns($(this).find('.col'), prevRow);
});
});
function colorColumns(cols, prevRow) {
var index = 0;
// alert("hi");
cols.each(function(col) {
var colIndex = $(this).index();
if (prevRow) {
var cols = prevRow.find('.col').length;
var totalCols = cols - 1;
var currentIndex = ((colIndex + totalCols) % cols);
var prevRowColor = $(prevRow).find('.col').eq(currentIndex);
var classes = prevRowColor.attr('class');
var classArr = classes.split(" ");
$(this).addClass(classArr[1]);
} else {
$(this).addClass(colors[colIndex]);
}
});
}
.row {
display: flex;
}
.row .col {
width: 20px;
height: 20px;
border-radius: 100%;
text-align: center;
}
.red {
background: red;
}
.orange {
background: orange;
}
.blue {
background: blue;
}
.green {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="row">
<div class="col">R</div>
<div class="col">B</div>
<div class="col">G</div>
<div class="col">O</div>
</div>
<div class="row">
<div class="col">R</div>
<div class="col">B</div>
<div class="col">G</div>
<div class="col">О</div>
</div>
<div class="row">
<div class="col">R</div>
<div class="col">B</div>
<div class="col">G</div>
<div class="col">O</div>
</div>
Hope it helps

Related

Swap 3 divs and make the selection div go to the center

I have three divs and I want that every single time I click on any div, it will be swapped with a second div which is meant to be at the center.
I have tried like this and it doesn't work:
function swapDiv(event, elem) {
elem.parentNode.insertBefore(elem, elem.parentNode.secondChild);
}
<div class="all-div-container">
<div class="div1" onclick="swapDiv(event,this);">
1
</div>
<div class="div2" onclick="swapDiv(event,this);">
2
</div>
<div class="div3" onclick="swapDiv(event,this);">
3
</div>
</div>
1 2 3 and when I click 3 the result must be 1 3 2 from this result and I click on 1 it's must be 3 1 2
function swapDiv(event, elem) {
// get all elements in .all-div-container
const allElements = [...elem.parentElement.children];
// get index of target elem
const targetIndex = allElements.indexOf(elem);
// get center element
const centerElem = allElements[1];
// exit from function if we clicked at center elem
if (elem === centerElem) return;
// move center element
if (targetIndex === 0) {
elem.parentElement.prepend(centerElem)
} else {
elem.parentElement.append(centerElem)
}
}
<div class="all-div-container">
<div class="div1" onclick="swapDiv(event,this);">
1
</div>
<div class="div2" onclick="swapDiv(event,this);">
2
</div>
<div class="div3" onclick="swapDiv(event,this);">
3
</div>
</div>
Consider the following.
$(function() {
$(".all-div-container > div").click(function(event) {
if ($(this).index() == 0) {
return false;
}
var $prev = $(this).prev();
var $self = $(this).detach();
$prev.before($self);
});
});
.all-div-container>div {
height: 2em;
width: 100%;
border: 1px solid #ccc;
border-radius: 3px;
margin-bottom: 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="all-div-container">
<div class="div1">1</div>
<div class="div2">2</div>
<div class="div3">3</div>
</div>
You did not clarify what should happen if the first item is clicked. This code will swap the clicked element and the previous element.

How to change background color conditionally?

I am trying to change the color of background.
I am changing every odd results to light green(#f0f5f5) so when the result ends in even number,
I get big white space.
I would like to change background color of pagination section to light green when the result ends in even number.
Sear
search results displays only 5 results so it could be 2th and 4th.
search.addWidgets([
instantsearch.widgets.searchBox({
container: '#searchbox',
}),
instantsearch.widgets.hits({
container: '#Algolia_Result',
transformItems: function (items) {
return items.map(function (item) {
if (item.objectType === 'Startup') {
item._isDescription = isNotNull(item.description);
} else if (item.objectType === 'NEWS') {
item._isSource = isNotNull(item.source);
} else if (item.objectType === 'Comment') {
item._isComment = isNotNull(item.comment);
return item;
});
},
templates: {
empty: '<div id="empty">No results have been found for {{ query }}.</div><br>',
item: `
<a href="{{linkUrl}}" target="_blank">
<div class="algolia_container">
<div class="item1">
<div id="images"><img src="{{logoUrl}}" alt="{{hits-image}}" id="hits-image"></div>
<div id="objTyeps"><span class="objectType {{objectCss}}">{{objectType}}</span></div>
</div>
<div class="item2">
<div id="objectTitle">
<span id="titleForDisplay">{{#helpers.highlight}}{ "attribute": "titleForDisplay" }{{/helpers.highlight}}</span>
</div>
</div>
<div class="item3">
{{#_isLocation}}
<div id="location">{{#helpers.highlight}}{ "attribute": "location" }{{/helpers.highlight}}</div>
{{/_isLocation}}
</div>
</div></a>
`,
},
}),
instantsearch.widgets.pagination({
container: '#pagination',
}),
]);
#Algolia_Result > div > div > ol > li:nth-child(odd){background-color: #f0f5f5;}
.ais-Pagination-item {
display:inline;
padding: 5px;
margin: 0 5px;
border: 1px solid #E8E8E8;
border-radius:5px;
font-size:18px;
}
.ais-Pagination-list {
text-align: center;
height:45px;
padding-top: 10px;
}
.ais-Pagination-item:hover {
background-color: #DCDCDC;
transition: background-color .2s;
}
.ais-Pagination-item--selected{
background-color: #E8E8E8;
}
<div id="searchbox"></div>
<div id="results">
<div id="Algolia_Result"></div>
<div id="pagination"></div>
</div>
This is ok
This need be fixed as if the background color of pagination area is the same as the last result, it must be green
This is what I get in the console.
You can color background of the pagination row by using JavaScript to count the number of results and apply color if the number of results is even.
Check out the example below.
Example 1 is with an odd number of result rows and the CSS works fine, same as your working example.
Example 2 is with an even number of result rows and uses the JS code to style the pagination background.
// Count the rows
let numRows = document.querySelectorAll('#example-2 .row').length
// If the number of rows is even
if (numRows % 2 == 0) {
// Apply the background color to the pagination row
document.querySelector('#example-2 .pagination').style.backgroundColor = '#eee'
}
.container {
border: 1px solid #000;
margin-bottom: 5px;
}
.row:nth-child(odd) {
background-color: #eee;
}
Example 1
<div id="example-1" class="container">
<div>
<div class="row">Row 1</div>
<div class="row">Row 2</div>
<div class="row">Row 3</div>
</div>
<div>
<div class="pageination">Pagination Row</div>
</div>
</div>
Example 2
<div id="example-2" class="container">
<div>
<div class="row">Row 1</div>
<div class="row">Row 2</div>
<div>
<div>
<div class="pagination">Pagination Row</div>
</div>
</div>
EDIT: So in your example, you would add the following JavaScript.
<script>
let numRows = document.querySelectorAll('.ais-Hits-item').length
if (numRows % 2 == 0) {
document.querySelector('.ais-Pagination-list').style.backgroundColor = '#eee'
}
</script>
EDIT 2: Looking at your code sandbox I can see that the issue is that the JS that counts the number of rows is being run before the rows have been rendered by Algolia.
To solve this issue we need to place our row counting JS into an Algolia callback that is ran after the rows have been rendered. We can use the algolia search.on('render', ...) event callback.
Try this:
search.on('render', () => {
let numRows = document.querySelectorAll('.algolia_container').length;
if (numRows % 2 === 0) {
document.querySelector('#pagination').style.backgroundColor = 'red';
} else {
document.querySelector('#pagination').style.backgroundColor = 'transparent';
}
});

Only allow the user to select a maximum of three blocks

I have a piece of code that adds an event listener to a number of buttons, when the user clicks a button a class is applied to the button container. How can I restrict this so the user can only select a maximum of three buttons. The code below is working to a point, when you get to three you cannot deselect. Can anyone help me achieve
var blocks = document.querySelectorAll(".block");
var btn = document.querySelectorAll("button");
var total = 0;
for (let i = 0; i < btn.length; i++) {
btn[i].addEventListener("click", function() {
if (total < 3 && blocks[i].classList.contains("active")) {
blocks[i].classList.remove("active");
total--;
} else if (total < 3 && !blocks[i].classList.contains("active")) {
blocks[i].classList.add("active");
total++;
}
});
}
.container{
display:flex;
}
.block{
padding: 50px;
border:1px solid;
max-width:
}
.block.active{
background:grey;
}
<div class="container">
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
</div>
this.
You simply need to remove this condition total < 3 && from your first if. The number of selected items is irrelevant if the element is already selected. You just want to de-select it.
var blocks = document.querySelectorAll(".block");
var btn = document.querySelectorAll("button");
var total = 0;
for (let i = 0; i < btn.length; i++) {
btn[i].addEventListener("click", function() {
if (blocks[i].classList.contains("active")) {
blocks[i].classList.remove("active");
total--;
} else if (total < 3 && !blocks[i].classList.contains("active")) {
blocks[i].classList.add("active");
total++;
}
});
}
.container{
display:flex;
}
.block{
padding: 50px;
border:1px solid;
max-width:
}
.block.active{
background:grey;
}
<div class="container">
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
</div>

Create multiple divs with different content

The problem is when duplicate multiple div but with different data-type, it still running a same content, i want correct all div will have the different content following the different data-type.
Is there a way to do this?
$(function() {
// document
'use strict';
var cp = $('div.box');
// unique id
var idCp = 0;
for (var i = 0; i < cp.length; i++) {
idCp++;
cp[i].id = "cp_" + idCp;
}
// diffrent type
if (cp.data('type') == "c1") {
cp.addClass('red').css({
"background: 'red',
"padding": "20px",
"display": "table"
});
$('.box').append('<div class="cp-title">' + 'c1-title' + '</div>');
} else if (cp.data('type') == "c2") {
cp.addClass('green').css({
"background": 'green',
"padding": "20px",
"display": "table"
});
$('.box').append('<div class="cp-title">' + 'c2-title' + '</div>');
} else {
return false;
}
}); //end
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<! it should be like this>
<div class="box" data-type="c1" id="cp_1">
<div class="cp-title">c1 title</div>
</div>
<div class="box" data-type="c2" id="cp_2">
<div class="cp-title">c2 title</div>
</div>
<! currently wrong output>
<div class="box" data-type="c1" id="cp_1">
<div class="cp-title">c1 title</div>
</div>
<div class="box" data-type="c2" id="cp_2">
<div class="cp-title">c1 title</div>
</div>
The problem in your code is that you are not looping inside the div's. You have to use the .each() function while looping inside all the elements
$(function() {
var cp = $('div.box');
cp.each(function() {
var _cp = $(this);
var text = _cp.attr("data-type") + "-title"; //Generate the text dynamically
var cls = _cp.attr("data-class"); //Get the class dynamically
_cp.addClass(cls).append('<div class="cp-title">' + text + '</div>'); //Add the class and append the text to the parent div
});
}); //end
.box{
padding: 20px;
display: table;
}
.red{
background: red;
}
.green{
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box" data-type="c1" data-class="red"></div>
<div class="box" data-type="c2" data-class="green"></div>
Probably you're searching for something like this.
// document.ready
$(function() {
'use strict';
$('.box').each(function(i,elem){
var ref = +$(elem).attr("data-type").match(/\d/)[0], addClass = 'default';
switch(true) {
case ref === 1:
addClass = 'red';
break;
case ref === 2:
addClass = 'green';
break;
}
$(this)
.addClass(addClass)
.append('<div class="cp-title">c'+ref+' title</div>');
});
}); //end
.red{
background: red;
padding: 20px;
display: table;
}.green{
background: green;
padding: 20px;
display: table;
}.default {
background: #2d2d2d;
color: #f6f6f6;
padding: 20px;
display: table;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box" data-type="c1"></div><div class="box" data-type="c2"></div>

how to check if it was the last element

how can I check if it was the last div? If it was I need to remove all classes "ready"
html:
<div class="green"></div>
<div class="orange"></div>
<div class="red"></div>
<div class="green"></div>
<div class="orange"></div>
js:
$(function() {
setInterval(showBlock, 1000);
function showBlock() {
var x = $("div:first").addClass("ready");
var c = $("div");
$(".ready").css("display", "block");
if (c.hasClass("ready")) {
$(".ready:last").next().addClass("ready");
}
}
})
;
Looking at your code what I understand is you want display one div after each second. For that I'll suggest following approach.
First add hidden class to all divs and then remove it from first hidden div at each second.
$(function() {
$('div').addClass('hidden');
var i = setInterval(showBlock, 1000);
function showBlock() {
var x = $("div.hidden:first").removeClass("hidden");
if($("div.hidden").length == 0) {
clearInterval(i);
}
}
});
.hidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="green">Green</div>
<div class="orange">Orange</div>
<div class="red">Red</div>
<div class="green">Green</div>
<div class="orange">Orange</div>
As far as I understand your problem, following solution must work in your case:
$(function() {
setInterval(showBlock, 1000);
function showBlock() {
var ready_divs = $("div.ready").length;
var total_divs = $("div").length;
if(ready_divs!=total_divs){
if(ready_divs==0){
$("div:first").addClass('ready');
}else{
$("div.ready:last").next('div').addClass('ready');
}
}else{
$("div").removeClass('ready')
}
}
});
div{
width: 20px;
height: 20px;
border:1px solid red;
}
div.ready{
border:3px solid blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="green"></div>
<div class="orange"></div>
<div class="red"></div>
<div class="green"></div>
<div class="orange"></div>

Categories

Resources