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

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.

Related

change properties of two divs with one onclick and querySelectorAll()

I have multiple elements that are seperatet in two divs. The first div contains a Text and the second div a color.
When I click on one element the text and color should change and if I click it again it should change back.
The problem is that no matter which one I click, its always the last one which changes.
The HTML part:
<style>
.colorGreen {
background-color: green;
}
.colorRed {
background-color: red;
}
</style>
<div class="box2">Text1</div>
<div class="box1 colorGreen">O</div>
<div class="box2">Text1</div>
<div class="box1 colorGreen">O</div>
<div class="box2">Text1</div>
<div class="box1 colorGreen">O</div>
The JavaScript part:
<script type='text/javascript'>
var box1Temp = document.querySelectorAll(".box1");
var box2Temp = document.querySelectorAll(".box2");
for (var i = 0; i < box1Temp.length; i++) {
var box1 = box1Temp[i];
var box2 = box2Temp[i];
box2.onclick = box1.onclick = function() {
if (box1.classList.contains("colorGreen")) {
box1.classList.add("colorRed");
box1.classList.remove("colorGreen");
box2.innerHTML = "Text2";
} else {
box1.classList.add("colorGreen");
box1.classList.remove("colorRed");
box2.innerHTML = "Text1";
}
}
}
</script>
It works, when I use only one div.
Then I can use 'this', instead of the 'box1' variable, to addres the right element.
But if I replace 'box1' with 'this' its still the text div that changes.
(I know it's obvious that this is happening, but I'm lost)
With a few small tweaks, this can be written a lot more cleanly:
// Capture click event for parent container, .toggle-set
for (const ele of document.querySelectorAll(".toggle-set")) {
ele.addEventListener("click", function() {
// Grab text and color elements
const textToggle = ele.querySelector(".toggle-text");
const colorToggle = ele.querySelector(".toggle-color");
// Toggle text
// NOTE: This could use further refinement with regex or something similar to strip whitespace before comparison
textToggle.textContent = textToggle.textContent == "Text1" ? "Text2" : "Text1";
// Toggle css classes
colorToggle.classList.toggle("colorGreen");
colorToggle.classList.toggle("colorRed");
});
}
.colorGreen { background-color: green; }
.colorRed { background-color: red; }
<div class="toggle-set">
<div class="toggle-text">Text1</div>
<div class="toggle-color colorGreen">
O
</div>
</div>
<div class="toggle-set">
<div class="toggle-text">Text1</div>
<div class="toggle-color colorGreen">
O
</div>
</div>
Your code is so confused
You were right for the this option.
you can do with simple onclick function :
function change(el){
box1 = el.querySelector('.box1');
box2 = el.querySelector('.box2');
if (box1.classList.contains("colorGreen")) {
box1.classList.add("colorRed");
box1.classList.remove("colorGreen");
box2.innerHTML = "Text2";
} else {
box1.classList.add("colorGreen");
box1.classList.remove("colorRed");
box2.innerHTML = "Text1";
}
}
<style>
.colorGreen {
background-color: green;
}
.colorRed {
background-color: red;
}
</style>
<div onclick="change(this)">
<div class="box2">Text1</div>
<div class="box1 colorGreen">O</div>
</div>
<div onclick="change(this)">
<div class="box2">Text1</div>
<div class="box1 colorGreen">O</div>
</div>
<div onclick="change(this)">
<div class="box2">Text1</div>
<div class="box1 colorGreen">O</div>
</div>
I think following code snippet would help you to get your desired result
let box1 = document.querySelectorAll(".box1");
let box2 = document.querySelectorAll(".box2");
box1.forEach((b1,i) => {
b1.addEventListener("click",(ev) => {
ev.target.classList.toggle("colorGreen");
ev.target.classList.toggle("colorRed");
console.log(box2[i]);
if(ev.target.classList.contains("colorGreen")){
box2[i].textContent = "Text1";
}else{
box2[i].textContent = "Text2"
}
})
})

JavaScript loop throught and hide all divs except one

I have a big list of getElementsById that looks like this:
let ahSummerCamps = document.getElementById("aH-summerCamps");
let ahTrekking = document.getElementById("aH-trekking");
let bpLongDistanceHiking = document.getElementById("bp-longDistanceHiking");
let bpThruHiking = document.getElementById("bp-thruHiking");
let cOceanCruising = document.getElementById("c-oceanCruising");
let cRiverCruising = document.getElementById("c-riverCruising");
let eRecreationsEvent = document.getElementById("e-recreationsEvent");
let eSportsEvent = document.getElementById("e-sportsEvents");
let phEscortedTours = document.getElementById("ph-escortedTours");
let phIndependentTours = document.getElementById("ph-independentTours");
let sPhotographicSafari = document.getElementById("s-photographicSafari");
let sCyclingSafari = document.getElementById("s-cyclingSafari");
let sAsBackcountrySkiing = document.getElementById("sAs-backcountrySkiing");
let sAsDownhillSkiing = document.getElementById("sAs-downhillSkiing");
let vChildcare = document.getElementById("v-childcare");
let vConservationAndEnvironment = document.getElementById("v-conservationAndEnvironment");
I won't go into details, is there any way that I can loop throught all of them and for example hide all except bpLongDistanceHiking and bpThruHiking .
I had this function but that is not good way for sure:
function hideAllExceptbP() {
ahSummerCamps.style.display = "none";
ahTrekking.style.display = "none";
/* ... and for all of them like this except bpLongDistanceHiking and bpThruHiking */
}
So on that way I need function for every element like:
function hideAllExceptaH() {
/* ... + 10 lines */
function hideAllExceptC() {
/* ... + 10 lines */
function hideAllExceptE() {
/* ... + 10 lines */
Function
function choice() {
backpacking.addEventListener("click", () => {
hideBackpacking();
hideSafari();
hidePackageHoliday();
showBackpackingOptions();
console.log("Backpacking");
});
So as you can see from html I have 8 divs at start, and when user click on backpacking for example function should hide all divs except bpLongDistanceHiking and bpThruHiking
Full code calling function:
HTML:
<div class="row">
<!--main divs-->
<div style="background-color: #4cc9f0" class="column" id="adventureHolidays"><p>Adventure Holidays</p></div>
<div style="background-color: #4895ef" class="column" id="backpacking"><p>Backpacking</p></div>
<div style="background-color: #4361ee" class="column" id="cruiseHolidays"><p>Cruise Holidays</p></div>
<div style="background-color: #4361ee" class="column" id="eventTravel"><p>Event Travel</p>
</div>
<div style="background-color: #3a0ca3" class="column" id="packageHoliday"><p>Package Holiday</p></div>
<div style="background-color: #480ca8" class="column" id="safari"><p>Safari</p></div>
<div style="background-color: #560bad" class="column" id="skiingAndSnowboarding"><p>Skiing and Snowboarding</p>
</div>
<div style="background-color: #7209b7" class="column" id="volunteering"><p>Volunteering</p></div>
<!--end on main divs-->
<!--sub divs-->
<div style="background-color: #4cc9f0" class="column" id="aH-summerCamps"><p>Summer camps</p></div>
<div style="background-color: #4895ef" class="column" id="aH-trekking"><p>Trekking</p></div>
<div style="background-color: #4361ee" class="column" id="bP-longDistanceHiking"><p>Long Distance Hiking</p></div>
<div style="background-color: #4361ee" class="column" id="bP-thruHiking"><p>Thru Hiking</p></div>
<div style="background-color: #3a0ca3" class="column" id="c-oceanCruising"><p>Ocean Cruising</p></div>
<div style="background-color: #480ca8" class="column" id="c-riverCruising"><p>River Cruising</p></div>
<div style="background-color: #560bad" class="column" id="e-recreationsEvent"><p>Recreations Events</p></div>
<div style="background-color: #7209b7" class="column" id="e-sportsEvents"><p>Sports events</p></div>
<div style="background-color: #4cc9f0" class="column" id="pH-escortedTours"><p>Escorted Tours</p></div>
<div style="background-color: #4895ef" class="column" id="pH-independentTours"><p>Independent Tours</p></div>
<div style="background-color: #4361ee" class="column" id="s-photographicSafari"><p>Photographic Safari</p></div>
<div style="background-color: #4895ef" class="column" id="s-cyclingSafari"><p>Cycling Safari</p></div>
<div style="background-color: #3a0ca3" class="column" id="sAs-backcountrySkiing"><p>Backcountry skiing</p></div>
<div style="background-color: #560bad" class="column" id="sAs-downhillSkiing"><p>Downhill skiing</p></div>
<div style="background-color: #4361ee" class="column" id="v-childcare"><p>Childcare</p></div>
<div style="background-color: #4895ef" class="column" id="v-conservationAndEnvironment"><p>Conservation And
Environment</p></div>
</div>
<script type="text/javascript" th:src="#{/js/index.js}"></script>
js:
let adventureHolidays = document.getElementById("adventureHolidays");
let backpacking = document.getElementById("backpacking");
let cruiseHolidays = document.getElementById("cruiseHolidays");
let eventTravel = document.getElementById("eventTravel");
let packageHoliday = document.getElementById("packageHoliday");
let safari = document.getElementById("safari");
let skiingAndSnowboarding = document.getElementById("skiingAndSnowboarding");
let volunteering = document.getElementById("volunteering");
/*End of inserting main variables*/
/*sub variables*/
let ahSummerCamps = document.getElementById("aH-summerCamps");
let ahTrekking = document.getElementById("aH-trekking");
let bPLongDistanceHiking = document.getElementById("bP-longDistanceHiking");
let bPThruHiking = document.getElementById("bP-thruHiking");
let cOceanCruising = document.getElementById("c-oceanCruising");
let cRiverCruising = document.getElementById("c-riverCruising");
let eRecreationsEvent = document.getElementById("e-recreationsEvent");
let eSportsEvent = document.getElementById("e-sportsEvents");
let phEscortedTours = document.getElementById("ph-escortedTours");
let phIndependentTours = document.getElementById("ph-independentTours");
let sPhotographicSafari = document.getElementById("s-photographicSafari");
let sCyclingSafari = document.getElementById("s-cyclingSafari");
let sAsBackcountrySkiing = document.getElementById("sAs-backcountrySkiing");
let sAsDownhillSkiing = document.getElementById("sAs-downhillSkiing");
let vChildcare = document.getElementById("v-childcare");
let vConservationAndEnvironment = document.getElementById("v-conservationAndEnvironment");
/*end of subs variables*/
const divs = ["adventureHolidays", "backpacking", "cruiseHolidays", "eventTravel", "packageHoliday", "safari", "skiingAndSnowboarding", "volunteering", "aH-summerCamps", "aH-trekking", "bP-longDistanceHiking", "bP-thruHiking", "c-oceanCruising", "c-riverCruising", "e-recreationsEvent", "e-sportsEvents", "ph-escortedTours", "ph-independentTours", "s-photographicSafari", "s-cyclingSafari", "sAs-backcountrySkiing", "v-conservationAndEnvironment", "sAs-downhillSkiing", "v-childcare"]
.map(id => document.getElementById(id)); // gives you an array of those elements
function hideAllDivsExcept(id) {
for (const div of divs) div.hidden = !div.id === id;
}
window.onload = function () {
choice();
};
/* start of function choice for user clicks*/
function choice() {
backpacking.addEventListener("click", () => {
hideAllDivsExcept('adventureHolidays');
console.log("Backpacking");
})
}
CSS:
* {
box-sizing: border-box;
}
/* Create three equal columns that floats next to each other */
.column {
float: left;
width: 33.33%;
padding: 10px;
}
/* Clear floats after the columns */
.row:after {
content: "";
/*
display: table;
*/
clear: both;
}
I'm getting:
index.js:38 Uncaught TypeError: Cannot read properties of null (reading 'id')
at hideAllDivsExcept (index.js:38:47)
at HTMLDivElement.<anonymous> (index.js:51:9)
And that is this
function hideAllDivsExcept(id) {
this > for (const div of divs) div.hidden = !div.id === id;
}
One approach to the problem is as below, with explanatory comments in the code:
// defining a named function to handle clicks on the 'filter' elements, that takes one
// argument, a reference to the Event Object:
const showRelevant = (evt) =>{
// caching a reference to the element to which the function is bound as the
// event-handler:
let source = evt.currentTarget,
// retrieving the attribute-value from the custom data-* attribute, using the
// HTMLElement.dataset API:
category = source.dataset.category;
// retrieving all <div> elements that do not have a "data-category" attribute which
// are the children of a .row element; we iterate over that collection using
// NodeList.prototype.forEach():
document.querySelectorAll('.row > div:not([data-category])').forEach(
// using an Arrow function we pass in a reference to the current
// Node of the NodeList over which we're iterating:
(el) => {
// we split the element's id property-value at the '-' character,
// and retrieve the first element of the resulting Array:
let prefix = el.id.split('-')[0];
// if the chosen category is exactly equal to 'all':
if (category === 'all') {
// we want to show all elements, therefore we set the hidden property
// of every element to false; so every element is shown:
el.hidden = false;
} else {
// otherwise, if the category is not equal to the prefix (above) the
// assessment results in true and so the element is hidden; if the
// category is equal to the prefix (therefore the current element is
// one we wish to see) the assessment results in false, and so the
// element is shown:
el.hidden = category !== prefix;
}
})
};
// here we retrieve all child elements with a "data-category" attribute of a .row element,
// and iterate over that NodeList with NodeList.prototype.forEach():
document.querySelectorAll('.row > [data-category]').forEach(
// using an Arrow function we pass in a reference to the current Node of the NodeList,
// and use EventTarget.addEventListener() to bind the showRelevant() function (note the
// deliberate lack of parentheses) as the event-handler for the 'click' event:
(el) => el.addEventListener('click', showRelevant)
)
:root {
--h-1: 212;
--h-2: 194;
--s: 84%;
--l: 62%;
--c-l: var(--l);
--bgc-l: var(--l);
}
* {
box-sizing: border-box;
}
.row {
/* rather than using float, I've used display: flex: */
display: flex;
/* the default of flex elements is:
flex-direction: row;
flex-wrap: nowrap;
flex-flow is a shorthand to update both those values;
here I've specified:
flex-direction: row;
flex-wrap: wrap;
*/
flex-flow: row wrap;
/* adjust to taste, but this replicates the behaviour of
floating in that elements on an incomplete row will
align to the start of the row: */
justify-content: start;
/* placing a 0.2em margin on the block-axis of the element;
in a language such as English (left-to-right, top-to-bottom)
that aligns to the top (margin-block-start) and bottom
(margin-block-end) margins: */
margin-block: 0.2em;
}
.row > * {
box-shadow: inset 0 0 0 3px currentColor, inset 0 0 0 4px #fff;
/* basing the width of the elements - using the flex-basis
property - to 33%: */
flex-basis: 33%;
padding: 10px;
}
.row > *:nth-child(even) {
/* using CSS custom properties to set color and
background-color: */
color: hsl(var(--h-1) var(--s) var(--c-l));
background-color: hsl(var(--h-2) var(--s) var(--bgc-l));
}
.row > *:nth-child(odd) {
color: hsl(var(--h-2) var(--s) var(--c-l));
background-color: hsl(var(--h-1) var(--s) var(--bgc-l));
}
.row > *:nth-child(even):hover,
.row > *:nth-child(odd):hover {
/* manipulating the CSS custom properties with the
calc function to make the color darker (by decreasing
the lightness) and the background-color lighter (by
increasing the lightness): */
--c-l: calc(var(--l)*0.5);
--bgc-l: calc(var(--l) * 1.2);
}
<div class="row">
<!--main divs-->
<!-- I've added a custom data-* attribute to each of the elements that would
constitute a 'filter' element; the attribute-value is all the initial
letters of the words written as camel-case, so:
'Adventure Holidays' => 'AH' => 'aH' -->
<div id="adventureHolidays" data-category="aH">
<p>Adventure Holidays</p>
</div>
<div id="backpacking" data-category="bP">
<p>Backpacking</p>
</div>
<div id="cruiseHolidays" data-category="cH">
<p>Cruise Holidays</p>
</div>
<div id="eventTravel" data-category="eT">
<p>Event Travel</p>
</div>
<div id="packageHoliday" data-category="pH">
<p>Package Holiday</p>
</div>
<div id="safari" data-category="s">
<p>Safari</p>
</div>
<div id="skiingAndSnowboarding" data-category="sAS">
<p>Skiing and Snowboarding</p>
</div>
<div id="volunteering" data-category="v">
<p>Volunteering</p>
</div>
<div data-category="all">
<p>Show all</p>
</div>
<!--end on main divs-->
</div>
<!-- this isn't essential, but I prefer to separate the 'filters' from the elements to be filtered: -->
<div class="row">
<!--sub divs-->
<!-- I've changed the id prefix of these elements to match the 'data-category' value from the
'filter' <div> elements: -->
<div id="aH-summerCamps">
<p>Summer camps</p>
</div>
<div id="aH-trekking">
<p>Trekking</p>
</div>
<div id="bP-longDistanceHiking">
<p>Long Distance Hiking</p>
</div>
<div id="bP-thruHiking">
<p>Thru Hiking</p>
</div>
<div id="cH-oceanCruising">
<p>Ocean Cruising</p>
</div>
<div id="cH-riverCruising">
<p>River Cruising</p>
</div>
<div id="eT-recreationsEvent">
<p>Recreations Events</p>
</div>
<div id="eT-sportsEvents">
<p>Sports events</p>
</div>
<div id="pH-escortedTours">
<p>Escorted Tours</p>
</div>
<div id="pH-independentTours">
<p>Independent Tours</p>
</div>
<div id="s-photographicSafari">
<p>Photographic Safari</p>
</div>
<div id="s-cyclingSafari">
<p>Cycling Safari</p>
</div>
<div id="sAS-backcountrySkiing">
<p>Backcountry skiing</p>
</div>
<div id="sAS-downhillSkiing">
<p>Downhill skiing</p>
</div>
<div id="v-childcare">
<p>Childcare</p>
</div>
<div id="v-conservationAndEnvironment">
<p>Conservation and Environment</p>
</div>
</div>
JS Fiddle demo.
References:
Arrow functions.
data-* attributes.
document.querySelectorAll().
Event.
EventTarget.addEventListener().
HTMLElement.dataset API.
HTMLElement.hidden property.
NodeList.prototype.forEach().
String.prototype.split().
Add an id to your main div with class 'row', e.x. daDiv then iterate and perform whatever you want checking id attribute of each one
$('#daDiv').children('div').each(function () {
if ($(this).attr('id') !== 'bP-longDistanceHiking' && $(this).attr('id') !== 'bP-thruHiking') {
$(this).hide();
}
});
CodePen
Example
UPDATE
You can even make a function
function hideExcept(arr) {
$('#daDiv').children('div').each(function () {
if (!arr.includes($(this).attr('id')))
$(this).hide();
});
}
hideExcept(['bP-longDistanceHiking', 'bP-thruHiking']); // hide all except bP-longDistanceHiking and bP-thruHiking

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';
}
});

TicTacToe - trouble alternating players

First mouse click gives me the expected 'x' marker but the next mouse click results in the alert ("Player o: tile has already been selected) even though the grid-item is blank. What am I doing wrong?
In the HTML body, I have created a 3x3 grid, 9 gridItems in total.
$(document).ready(function(){
let grid = $("#grid-container")
let gridItem = $(".grid-item")
function select(){
for (i = 0; i < gridItem.length; i++){
gridItem[i].addEventListener("click", function(){
if ($(this).html() == ""){
$(this).html("x");
nextSelect();
} else {alert ("Player X: tile has already been selected"); select()}
})
}
}
function nextSelect(){
for (i = 0; i < gridItem.length; i++){
gridItem[i].addEventListener("click", function(){
if ($(this).html() == ""){
$(this).html("o");
select();
} else {alert ("Player o: tile has already been selected"); nextSelect()}
})
}
}
select()
});
The addEventListener should be executed only once. Your problem is that you're adding multiple event handlers. A possible version in the snippet bellow.
The idea is that you only need one function and attach it to click event only once per cell, which is done with jQuery .click(callback). To manage the turns you can use a boolean variable (isTurnOfPlayerOne).
$(document).ready(function() {
let isTurnOfPlayerOne = true;
$(".grid-item").click(handleClick);
function handleClick() {
if ($(this).html() == " ") {
let symbol = (isTurnOfPlayerOne ? "x" : "o");
$(this).html(symbol);
} else {
alert("Tile has already been selected");
}
isTurnOfPlayerOne = !isTurnOfPlayerOne;
}
});
.grid-item {
width: 40px;
height: 40px;
display: inline-block;
border: solid 1px #000;
text-align: center;
margin-bottom: 3px;
line-height: 30px;
font-size: 30px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="grid-container">
<div class="grid-item"> </div>
<div class="grid-item"> </div>
<div class="grid-item"> </div>
<br/>
<div class="grid-item"> </div>
<div class="grid-item"> </div>
<div class="grid-item"> </div>
<br/>
<div class="grid-item"> </div>
<div class="grid-item"> </div>
<div class="grid-item"> </div>
</div>

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>

Categories

Resources