I am making a tic tac toe game with HTMl CSS (SCSS) and JS, and I am running into some trouble. I have a function to add an X or O to each grid space, but it is adding them automatically before it even has the right parameters to do ir, but it is doing it right(ish). Can someone help?
I also have it here.
My HTML:
<div class="wrap">
<div class="piece one"></div>
<div class="piece two"></div>
<div class="piece three"></div>
<div class="piece four"></div>
<div class="piece five"></div>
<div class="piece six"></div>
<div class="piece seven"></div>
<div class="piece eight"></div>
<div class="piece nine"></div>
</div>
My CSS:
body {
margin: 0;
overflow: hidden;
}
.wrap {
position: absolute;
height: 500px;
width: 510px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-wrap: wrap;
align-content: flex-start;
}
.piece {
width: calc(500px / 3);
height: calc(500px / 3);
background: white;
cursor: pointer;
}
.five, .two, .eight {
border-left: 5px solid black;
border-right: 5px solid black;
}
.one, .two, .three {
border-bottom: 5px solid black;
}
.seven, .eight, .nine {
border-top: 5px solid black;
}
.x {
margin-left: 30px;
margin-top: 20px;
display: flex;
.line {
height: calc(400px / 3);
width: 5px;
background: black;
&Two {
transform: rotate(-45deg);
margin-left: -5px;
}
&One {
transform: rotate(45deg);
margin-left: 50px;
}
}
}
.o {
margin-left: 30px;
margin-top: 20px;
height: 100px;
width: 100px;
border-radius: 100%;
border: 5px solid black;
}
And my JS:
let x = true,
o = false,
AI = false,
easy = true,
med = false,
hard = false;
const one = document.querySelector(".one"),
two = document.querySelector(".two"),
three = document.querySelector(".three"),
four = document.querySelector(".four"),
five = document.querySelector(".five"),
six = document.querySelector(".six"),
seven = document.querySelector(".seven"),
eight = document.querySelector(".eight"),
nine = document.querySelector(".nine"),
X /* The diference between this X and the other x is that this one is capitalized, same w/ the O and o */ = "<div class='x'><div class='lineOne line'></div><div class='lineTwo line'></div></div>",
O = "<div class='o'></div>";
one.addEventListener("click", function() {
console.log("goodness happened")
})
const tic = function(square) {
console.log("test 1 success");
if (x === true) {
square.innerHTML = X;
x = false;
o = true;
}
else {
square.innerHTML = O;
x = true;
o = false;
}
}
one.addEventListener("click", tic(one), false)
two.addEventListener("click", tic(two), false)
three.addEventListener("click", tic(three), false)
four.addEventListener("click", tic(four), false)
five.addEventListener("click", tic(five), false)
six.addEventListener("click", tic(six), false)
seven.addEventListener("click", tic(seven), false)
eight.addEventListener("click", tic(eight), false)
nine.addEventListener("click", tic(nine), false)
Sorry it is a lot. I just want to give you the full picture. Thanks in advance!
You're calling the function instead of referencing it, change all the event handlers to use an anonymous function instead
one.addEventListener("click", function() {
tic(one)
}, false);
Related
I created a slideshow with 3 slides but for some reason, it keeps adding an additional slide
const slideshow = document.getElementById("slideshow");
const slides = slideshow.children;
let currentSlide = 0;
function goToSlide(n) {
slides[currentSlide].classList.remove("active");
currentSlide = (n + slides.length) % slides.length;
slides[currentSlide].classList.add("active");
updateSlideshowCounter();
}
function nextSlide() {
goToSlide(currentSlide + 1);
}
function prevSlide() {
goToSlide(currentSlide - 1);
}
function updateSlideshowCounter() {
const slideshowCounter = document.getElementById("slideshow-counter");
slideshowCounter.textContent = `${currentSlide + 1} / ${slides.length}`;
}
const prevButton = document.getElementById("prev-button");
prevButton.addEventListener("click", prevSlide);
const nextButton = document.getElementById("next-button");
nextButton.addEventListener("click", nextSlide);
updateSlideshowCounter();
#slideshow {
position: relative;
text-align: center;
width: 400px;
height: 300px;
border: 1px black solid;
}
.slide {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 1s;
}
.slide.active {
opacity: 1;
}
#slideshow-controls {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
}
#prev-button,
#next-button {
padding: 10px 20px;
border: none;
background-color: #333;
color: #fff;
cursor: pointer;
}
#prev-button {
margin-right: 20px;
}
#next-button {
margin-left: 20px;
}
#slideshow-counter {
margin: 0 20px;
}
<div id="slideshow">
<div class="slide">Slide 1</div>
<div class="slide">Slide 2</div>
<div class="slide">Slide 3</div>
<div id="slideshow-controls">
<button id="prev-button">Prev</button>
<span id="slideshow-counter"></span>
<button id="next-button">Next</button>
</div>
</div>
Can someone tell me what my mistake is and how I can get 3 slides in the output instead of 4.
You're defining your slides with the statement const slides = slideshow.children;. Your slideshow has a total of 4 direct children, so the counter is technically correct (see slide 1, slide 2, slide 3, and slideshow-controls).
One approach to get just the slides you want is to use const slides = document.getElementsByClassName("slide"). I hope this helps!
The problem is your slides variable is not assigned to the correct list of elements, as the previous answer said, you should replace slideshow.children with either document.getElementsByClassName('slide') or document.querySelectorAll('.slide'), use any of the two.
By using slideshow.children, you're not getting .slide classes, you're getting all children of #slideshow.
So, your variable in line 67, should be as the following:
const slides = document.querySelectorAll('.slide');
or
const slides = document.getElementsByClassName('.slide');
You should keep slideshow controls out of your slideshow div. I am attaching Code Below. Run it and check.
const slideshow = document.getElementById("slideshow");
const slides = slideshow.children;
let currentSlide = 0;
function goToSlide(n) {
slides[currentSlide].classList.remove("active");
currentSlide = (n + slides.length) % slides.length;
slides[currentSlide].classList.add("active");
updateSlideshowCounter();
}
function nextSlide() {
goToSlide(currentSlide + 1);
}
function prevSlide() {
goToSlide(currentSlide - 1);
}
function updateSlideshowCounter() {
const slideshowCounter = document.getElementById("slideshow-counter");
slideshowCounter.textContent = `${currentSlide + 1} / ${slides.length}`;
}
const prevButton = document.getElementById("prev-button");
prevButton.addEventListener("click", prevSlide);
const nextButton = document.getElementById("next-button");
nextButton.addEventListener("click", nextSlide);
updateSlideshowCounter();
#slideshowbox {
position: relative;
width: 400px;
height: 300px;
}
#slideshow {
position: relative;
text-align: center;
width: 400px;
height: 300px;
border: 1px black solid;
}
.slide {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 1s;
}
.slide.active {
opacity: 1;
}
#slideshow-controls {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
}
#prev-button,
#next-button {
padding: 10px 20px;
border: none;
background-color: #333;
color: #fff;
cursor: pointer;
}
#prev-button {
margin-right: 20px;
}
#next-button {
margin-left: 20px;
}
#slideshow-counter {
margin: 0 20px;
}
<div id="slideshowbox">
<div id="slideshow">
<div class="slide">Slide 1</div>
<div class="slide">Slide 2</div>
<div class="slide">Slide 3</div>
</div>
<div id="slideshow-controls">
<button id="prev-button">Prev</button>
<span id="slideshow-counter"></span>
<button id="next-button">Next</button>
</div>
</div>
Your slideshow div childs is throwing 4 because your 4th div is slideshow-controls. You may want to add -1 to the counter or redifine the way you make your div. Best of luck!
I am working on a WordPress site and I have a snippet of html that iterates with repeating classes.
I am attempting to create a click function but only affect the element that is clicked. All in JavaScript.
As of right now my function is affecting all elements with the class name. Test code can be found at my CodePen or below.
I can accomplish this without nested loops as seen here. So my assumption is the problem lies within the second forEach loop. I would appreciate any light on the matter.
Thank you in advance.
/**
*Constructors
**/
const carousel = document.getElementsByClassName("carousel");
const btns = document.getElementsByClassName("btns");
/**
*Execute
**/
Array.from(btns).forEach((i) => {
i.addEventListener("click", (e) => {
Array.from(carousel).forEach((n) => {
if (i.classList.contains("slide-left")) {
n.scrollLeft -= 20;
} else if (i.classList.contains("slide-right")) {
n.scrollLeft += 20;
} else {
alert("ut oh");
}
});
});
});
/*
**Utilities
*/
/*containers*/
.feed-container {
position: absolute;
height: 200px;
width: 100%;
display: grid;
grid-template-columns: 1;
grid-template-rows: 1;
}
.carousel {
grid-row: 1;
grid-column: 1/5;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: 1;
grid-gap: 15px;
align-self: center;
border: 1px solid #ccc;
overflow-x: scroll;
overflow-y: hidden;
}
/*div-buttons*/
div[class*="slide-"] {
/*opacity: 0;*/
position: sticky;
grid-row: 1;
z-index: 5;
place-self: center;
transition: 0.5s;
padding: 15px;
}
.slide-left {
grid-column: 1;
}
.slide-right {
grid-column: 4;
}
/*items*/
div[class*="item-"] {
grid-row: 1;
width: 400px;
height: 200px;
}
.item-1 {
background: blue;
}
.item-2 {
background: red;
}
.item-3 {
background: grey;
}
.item-4 {
background: yellow;
}
/*scrollbar*/
::-webkit-scrollbar {
display: none;
}
/*chevrons*/
[class*="chevron-"] {
box-sizing: border-box;
position: relative;
display: block;
transform: scale(var(--ggs, 1));
width: 22px;
height: 22px;
border: 2px solid transparent;
border-radius: 25px;
}
[class*="chevron-"]::after {
content: "";
display: block;
box-sizing: border-box;
position: absolute;
width: 40px;
height: 40px;
border-bottom: 8px solid;
border-left: 8px solid;
bottom: 0;
}
.chevron-left::after {
transform: rotate(45deg);
left: 15px;
}
.chevron-right::after {
transform: rotate(-135deg);
right: 15px;
}
/*
**Exceptions
*/
.btns:hover {
cursor: pointer;
}
.opaque {
opacity: 1 !important;
}
.show {
display: block;
}
<div id="wrapper" style="display:grid; grid-template-rows:repeat(2, auto); grid-gap: 100px;">
<div>
<h1>Header</h1>
<div class="feed-container">
<div class="carousel">
<div class="item-1"></div>
<div class="item-2"></div>
<div class="item-3"></div>
<div class="item-4"></div>
</div>
<div class="slide-left btns">
<div class="chevron-left"></div>
</div>
<div class="slide-right btns">
<div class="chevron-right"></div>
</div>
</div>
</div>
<br>
<div>
<h1>Header</h1>
<div class="feed-container">
<div class="carousel">
<div class="item-1"></div>
<div class="item-2"></div>
<div class="item-3"></div>
<div class="item-4"></div>
</div>
<div class="slide-left btns">
<div class="chevron-left"></div>
</div>
<div class="slide-right btns">
<div class="chevron-right"></div>
</div>
</div>
</div>
</div>
It's because you're getting all the elements with class name carousel and then looping through them with each click.
const carousel = document.getElementsByClassName("carousel");
Instead what you need to do is get the carousels only under the button's parent when you trigger the click event
eg something like this:
Array.from(btns).forEach((i) => {
i.addEventListener("click", (e) => {
const targetElement = e?.target || e?.srcElement;
const parent = targetElement.parentElement();
const carousel = Array.from(parent.getElementsByClassName("carousel"));
carousel.forEach((n) => {
if (i.classList.contains("slide-left")) {
n.scrollLeft -= 20;
} else if (i.classList.contains("slide-right")) {
n.scrollLeft += 20;
} else {
alert("ut oh");
}
});
});
});
I took a look at the following as recommend and it seems to do the trick.
I created a variable that calls the parentNode "forEach()" button clicked. Oppose to looping through each element.
Working example, codePen
const carousel = document.querySelectorAll(".carousel");
const btns = document.querySelectorAll(".btns");
btns.forEach((i) => {
i.addEventListener("click", () => {
var x = i.parentNode;
var y = Array.from(x.querySelectorAll(".carousel"));
y.forEach((n) => {
if (i.classList.contains("slide-left")) {
n.scrollLeft -= 20;
} else {
n.scrollLeft += 20;
}
});
});
});
I have 10 links and each of them is different from the others.I want when user hovers on them background image of the div changes and a tooltip text be shown on top of the links with a fade-in animation .
i have tried to make several functions using JS and it works but it's a lot of code and mostly repetitive.I want a good shortcut through all of that useless coding.
document.getElementById("d1").onmouseover = function() {
mouseOver1()
};
document.getElementById("d2").onmouseover = function() {
mouseOver2()
};
document.getElementById("d3").onmouseover = function() {
mouseOver3()
};
document.getElementById("d1").onmouseout = function() {
mouseOut1()
};
document.getElementById("d2").onmouseout = function() {
mouseOut2()
};
document.getElementById("d3").onmouseout = function() {
mouseOut3()
};
function mouseOver1() {
document.getElementById("dogs").style.background = "blue";
document.getElementById("tooltiptext1").style.visibility = "visible";
}
function mouseOut1() {
document.getElementById("dogs").style.background = "black";
document.getElementById("tooltiptext1").style.visibility = "hidden";
}
function mouseOver2() {
document.getElementById("dogs").style.background = "green";
document.getElementById("tooltiptext2").style.visibility = "visible";
}
function mouseOut2() {
document.getElementById("dogs").style.background = "black";
document.getElementById("tooltiptext2").style.visibility = "hidden";
}
function mouseOver3() {
document.getElementById("dogs").style.background = "red";
document.getElementById("tooltiptext3").style.visibility = "visible";
}
function mouseOut3() {
document.getElementById("dogs").style.background = "black";
document.getElementById("tooltiptext3").style.visibility = "hidden";
}
#dogs {
float: right;
margin-top: 5%;
background: black;
width: 150px;
height: 150px;
}
#d-list {
color: white;
direction: ltr;
float: right;
width: 60%;
height: 60%;
}
#tooltiptext1,
#tooltiptext2,
#tooltiptext3 {
color: black;
background-color: gray;
width: 120px;
height: 30px;
border-radius: 6px;
text-align: center;
padding-top: 5px;
visibility: hidden;
}
<div id="animals">
<div id="dogs"></div>
<div id="d-list">
<pre style="font-size:22px; color:darkorange">dogs</pre><br />
<pre>white Husky</pre>
<p id="tooltiptext1">Tooltip text1</p>
<pre>black Bull</pre>
<p id="tooltiptext2">Tooltip text2</p>
<pre>brown Rex</pre>
<p id="tooltiptext3">Tooltip text3</p>
</div>
</div>
Please have in mind that all of links will change same outer div object and the idea is to change the background image of that div and the tooltip shoud appear on the top of the links....so,
any ideas?
edit: added animation requested.
CSS is almost always better done in script by using classes when multiple elements are being manipulated with similar functions so I used that here. Rather than put some complex set of logic in place I simply added data attributes for the colors - now it works for any new elements you wish to add as well.
I did find your markup to be somewhat strangely chosen and would have done it differently but that was not part of the question as stated.
I took the liberty of removing the style attribute from your dogs element and put it in the CSS also as it seemed to belong there and mixing markup and css will probably make it harder to maintain over time and puts all the style in one place.
Since you DID tag this with jQuery here is an example of that.
$(function() {
$('#d-list').on('mouseenter', 'a', function(event) {
$('#dogs').css('backgroundColor', $(this).data('colorin'));
$(this).parent().next('.tooltip').animate({
opacity: 1
});
}).on('mouseleave', 'a', function(event) {
$('#dogs').css('backgroundColor', $(this).data('colorout'));
$(this).parent().next('.tooltip').animate({
opacity: 0
});
});
});
#dogs {
float: right;
margin-top: 5%;
background: black;
width: 150px;
height: 150px;
}
#d-list {
color: white;
direction: ltr;
float: right;
width: 60%;
height: 60%;
}
.dog-header {
font-size: 22px;
color: darkorange;
margin-bottom: 2em;
}
.tooltip {
color: black;
background-color: gray;
width: 120px;
height: 30px;
border-radius: 6px;
text-align: center;
padding-top: 5px;
opacity: 0;
position:relative;
top:-4.5em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div id="animals">
<div id="dogs"></div>
<div id="d-list">
<pre class="dog-header">dogs</pre>
<pre>white Husky</pre>
<p id="tooltiptext1" class="tooltip">Tooltip text1</p>
<pre>black Bull</pre>
<p id="tooltiptext2" class="tooltip">Tooltip text2</p>
<pre>brown Rex</pre>
<p id="tooltiptext3" class="tooltip">Tooltip text3</p>
</div>
</div>
Updated
This answer was written before the question was edited to show the intended markup/styling and before all the details were included. The code has been updated to work with that structure.
I think the simplest thing is just to create a configuration object to detail the varying bits, and then use common code for the rest. Here's one approach:
const configs = [
['d1', 'tooltiptext1', 'blue'],
['d2', 'tooltiptext2', 'green'],
['d3', 'tooltiptext3', 'red'],
];
configs.forEach(([id, tt, color]) => {
const dogs = document.getElementById('dogs');
const el = document.getElementById(id);
const tip = document.getElementById(tt);
el.onmouseover = (evt) => {
dogs.style.background = color
tip.style.visibility = "visible";
}
el.onmouseout = (evt) => {
dogs.style.background = "black";
tip.style.visibility = "hidden";
}
})
#dogs{float:right;margin-top:5%;background:#000;width:150px;height:150px}#d-list{color:#fff;direction:ltr;float:right;width:60%;height:60%}#tooltiptext1,#tooltiptext2,#tooltiptext3{color:#000;background-color:gray;width:120px;height:30px;border-radius:6px;text-align:center;padding-top:5px;visibility:hidden}
<div id="animals"> <div id="dogs"></div><div id="d-list"> <pre style="font-size:22px; color:darkorange">dogs</pre><br/> <pre>white Husky</pre> <p id="tooltiptext1">Tooltip text1</p><pre>black Bull</pre> <p id="tooltiptext2">Tooltip text2</p><pre>brown Rex</pre> <p id="tooltiptext3">Tooltip text3</p></div></div>
Obviously you can extend this with new rows really easily. And if you want to add more varying properties, you can simply make the rows longer. If you need to add too many properties to each list, an array might become hard to read, and it might become better to switch to {id: 'demo', tt: 'dem', color: 'blue'} with the corresponding change to the parameters in the forEach callback. (That is, replacing configs.forEach(([id, tt, color]) => { with configs.forEach(({id, tt, color}) => {.) But with only three parameters, a short array seems cleaner.
Older code snippet based on my made-up markup.
const configs = [
['demo', 'dem', 'blue'],
['dd', 'dem1', 'green']
];
configs.forEach(([id1, id2, color]) => {
const a = document.getElementById(id1)
const b = document.getElementById(id2)
a.onmouseover = (evt) => {
a.style.background = color
b.style.visibility = "visible";
}
a.onmouseout = (evt) => {
a.style.background = "black";
b.style.visibility = "hidden";
}
})
div {width: 50px; height: 50px; float: left; margin: 10px; background: black; border: 1px solid #666; color: red; padding: 10px; text-align: center}
#dem , #dem1{visibility:hidden;}
<div id="demo">demo</div>
<div id="dem">dem</div>
<div id="dd">dd</div>
<div id="dem1">dem1</div>
my way of seeing that => zero Javascript:
div[data-info] {
display: inline-block;
margin:80px 20px 0 0;
border:1px solid red;
padding: 10px 20px;
position: relative;
}
div[data-bg=blue]:hover {
background-color: blue;
color: red;
}
div[data-bg=green]:hover {
background-color: green;
color: red;
}
div[data-info]:hover:after {
background: #333;
background: rgba(0, 0, 0, .8);
border-radius: 5px;
bottom: 46px;
color: #fff;
content: attr(data-info);
left: 20%;
padding: 5px 15px;
position: absolute;
z-index: 98;
min-width: 120px;
max-width: 220px;
}
div[data-info]:hover:before {
border: solid;
border-color: #333 transparent;
border-width: 6px 6px 0px 6px;
bottom: 40px;
content: "";
left: 50%;
position: absolute;
z-index: 99;
}
<div data-info="Tooltip for A Tooltip for A" data-bg="blue">with Tooltip CSS3 A</div>
<div data-info="Tooltip for B" data-bg="green" >with Tooltip CSS3 B</div>
I have created a short exercise that involves 3 boxes that are attributed to certain shapes. I have it set now that if someone drags the shape to the correct box it is places in the box. However, currently if someone drags a shape to the wrong shape it only resets. I would like to add some effects such as, if the person drags to the wrong one it resets and a red flash appears on in the box, and if correct a green one appears. If possible it would be nice to be able to also have the red flash appear even if the person adds it to the correct box, but after the specified number such as a third triangle in the triangle box. How would this be done ? This is my current code
var circ = document.getElementById("c1");
var tria = document.getElementById("t1");
var squa = document.getElementById("s1");
var circ2 = document.getElementById("c2");
var tria2 = document.getElementById("t2");
var squa2 = document.getElementById("s2");
var dropt = document.getElementById("dzt");
var dropc = document.getElementById("dzc");
var drops = document.getElementById("dzs");
circ.ondragstart = function(evt) {
evt.dataTransfer.setData('key1', evt.target.id);
console.log("dragging circle");
}
tria.ondragstart = function(evt) {
evt.dataTransfer.setData('key2', evt.target.id);
console.log("dragging triangle");
}
squa.ondragstart = function(evt) {
evt.dataTransfer.setData('key3', evt.target.id);
console.log("dragging square");
}
/*circ2.ondragstart = function(){
evt.dataTransfer.setData('key4','c2');
console.log("yesh");
}
tria2.ondragstart=function(){
evt.dataTransfer.setData('key5','t2');
console.log("nani");
}
squa2.ondragstart=function(){
evt.dataTransfer.setData('key6','s1');
console.log("omae wa");
}
*/
dropt.ondragover = function(evt) {
evt.preventDefault();
console.log("over t");
}
dropc.ondragover = function(evt) {
evt.preventDefault();
console.log("over c");
}
drops.ondragover = function(evt) {
evt.preventDefault();
console.log("over s");
}
dropt.ondrop = function(evt) {
evt.preventDefault();
var icont = evt.dataTransfer.getData('key2');
console.log("drop t");
console.log(icont);
var current = document.getElementById(icont);
console.log(current);
var newcurrent = document.createElement('img');
newcurrent.src = current.src;
dropt.appendChild(newcurrent);
}
dropc.ondrop = function(evt) {
evt.preventDefault();
var iconc = evt.dataTransfer.getData('key1');
console.log("drop c");
console.log(iconc);
var current = document.getElementById(iconc);
console.log(current);
var newcurrent = document.createElement('img');
newcurrent.src = current.src;
dropc.appendChild(newcurrent);
}
drops.ondrop = function(evt) {
evt.preventDefault();
var icons = evt.dataTransfer.getData('key3');
console.log("drop s");
console.log(icons);
var current = document.getElementById(icons);
console.log(current);
var newcurrent = document.createElement('img');
newcurrent.src = current.src;
drops.appendChild(newcurrent);
}
#body {
width: 100%;
height: 100%;
}
.container {
display: flex;
}
.column {
flex: 1;
background: #ffffff;
border: 1px solid #ffffff;
box-sizing: border-box;
}
.column-one {
order: 3;
}
.column-two {
order: 1;
}
.column-three {
order: 4;
}
.column-four {
order: 2;
}
.column-five {
order: 5;
}
.drop-zone1 {
align-content: center;
<!--border-radius: 50%;
-->width: 150px;
height: 150px;
border: 2px;
border-style: solid;
border-color: #535f6b;
}
.drop-zone2 {
align-content: center;
<!--border-radius: 50%;
-->width: 150px;
height: 150px;
border: 2px;
border-style: solid;
border-color: #535f6b;
}
.drop-zone3 {
align-content: center;
<!--border-radius: 50%;
-->width: 150px;
height: 150px;
border: 2px;
border-style: solid;
border-color: #535f6b;
}
.icon1 {
width: 50px;
height: 50px;
margin-left: 45px;
}
.icon2 {
width: 50px;
height: 50px;
margin-left: 56px;
align-content: center;
}
.icon3 {
width: 50px;
height: 50px;
margin-left: 58px;
}
.question {
text-align: center;
color: #535f6b;
font-family: sans-serif;
font-style: italic;
}
<p class="question"><b>Drag and drop the elements to their corresponding set to achieve: <br>a. 3 circles in the circle set<br>b. 2 triangles in the triangle set<br>c. 5 squares in the square set</b></p>
<div class="container">
<div class="column column-one"><img src="circle.png" id="c1" style="margin-left: 55px"></div>
<div class="column column-two"></div>
<div class="column column-three"><img src="square.png" id="s1" style="margin-left: 58px"></div>
<div class="column column-four"><img src="triang.png" id="t1" style="margin-left: 45px"></div>
<div class="column column-five"></div>
</div>
<br>
<div class="container">
<div class="column column-one">
<div class="drop-zone1" id="dzt"></div>
</div>
<div class="column column-two"></div>
<div class="column column-three">
<div class="drop-zone2" id="dzc"></div>
</div>
<div class="column column-four">
<div class="drop-zone3" id="dzs"></div>
</div>
<div class="column column-five"></div>
</div>
<div class="container">
<div class="column column-one">
<div class="icon1"><img src="triang.png"></div>
</div>
<div class="column column-two"></div>
<div class="column column-three">
<div class="icon2"><img src="circle.png"></div>
</div>
<div class="column column-four">
<div class="icon3"><img src="square.png"></div>
</div>
<div class="column column-five"></div>
</div>
This is what it looks like with the images
Thanks in advance and best regards
In the below snippet I've added some condition to check if the object was dragged in its area, if so , I added the class that has an animation background ( annimation created at bottom ) otherwise it will check if the drag area has child ( do not trigger error annimation , else trigger the error annimation )
you can set your own annimation and colors by changing the both css annimations and the css class .green and .red
see below snippet
var circ = document.getElementById("c1");
var tria = document.getElementById("t1");
var squa = document.getElementById("s1");
var circ2 = document.getElementById("c2");
var tria2 = document.getElementById("t2");
var squa2 = document.getElementById("s2");
var dropt = document.getElementById("dzt");
var dropc = document.getElementById("dzc");
var drops = document.getElementById("dzs");
tria.ondragstart = function(evt) {
evt.dataTransfer.setData('key2', evt.target.id);
console.log("dragging triangle");
}
circ.ondragstart = function(evt) {
evt.dataTransfer.setData('key1', evt.target.id);
console.log("dragging circle");
}
squa.ondragstart = function(evt) {
evt.dataTransfer.setData('key3', evt.target.id);
console.log("dragging square");
}
/*circ2.ondragstart = function(){
evt.dataTransfer.setData('key4','c2');
console.log("yesh");
}
tria2.ondragstart=function(){
evt.dataTransfer.setData('key5','t2');
console.log("nani");
}
squa2.ondragstart=function(){
evt.dataTransfer.setData('key6','s1');
console.log("omae wa");
}
*/
dropt.ondragover = function(evt) {
evt.preventDefault();
//console.log("over t");
}
dropc.ondragover = function(evt) {
evt.preventDefault();
//console.log("over c");
}
drops.ondragover = function(evt) {
evt.preventDefault();
//console.log("over s");
}
dropt.ondrop = function(evt) {
evt.preventDefault();
var icont = evt.dataTransfer.getData('key2');
console.log("drop t");
console.log(icont);
var current = document.getElementById(icont);
console.log(current);
if(current != null) {
if(this.hasChildNodes()) return;
var newcurrent = document.createElement('img');
newcurrent.src = current.src;
this.appendChild(newcurrent);
setBackground("green",this);
}
else {
if(!this.hasChildNodes())
setBackground("red",this);
}
}
dropc.ondrop = function(evt) {
evt.preventDefault();
var iconc = evt.dataTransfer.getData('key1');
console.log("drop c");
console.log("dd",iconc);
var current = document.getElementById(iconc);
console.log(current);
if(current != null) {
if(this.hasChildNodes()) return;
var newcurrent = document.createElement('img');
newcurrent.src = current.src;
this.appendChild(newcurrent);
setBackground("green",this);
}
else {
if(!this.hasChildNodes())
setBackground("red",this);
}
}
drops.ondrop = function(evt) {
evt.preventDefault();
var icons = evt.dataTransfer.getData('key3');
console.log("drop s");
console.log(icons);
var current = document.getElementById(icons);
console.log(current);
if(current != null) {
if(this.hasChildNodes()) return;
var newcurrent = document.createElement('img');
newcurrent.src = current.src;
this.appendChild(newcurrent);
setBackground("green",this);
}
else {
if(!this.hasChildNodes())
setBackground("red",this);
}
}
function setBackground (className,node) {
node.classList.remove("green");
node.classList.remove("red");
node.classList.add(className);
}
#body {
width: 100%;
height: 100%;
}
.container {
display: flex;
}
.column {
flex: 1;
background: #ffffff;
border: 1px solid #ffffff;
box-sizing: border-box;
}
.column-one {
order: 3;
}
.column-two {
order: 1;
}
.column-three {
order: 4;
}
.column-four {
order: 2;
}
.column-five {
order: 5;
}
.drop-zone1 {
align-content: center;
<!--border-radius: 50%;
-->width: 150px;
height: 150px;
border: 2px;
border-style: solid;
border-color: #535f6b;
}
.drop-zone2 {
align-content: center;
<!--border-radius: 50%;
-->width: 150px;
height: 150px;
border: 2px;
border-style: solid;
border-color: #535f6b;
}
.drop-zone3 {
align-content: center;
<!--border-radius: 50%;
-->width: 150px;
height: 150px;
border: 2px;
border-style: solid;
border-color: #535f6b;
}
.icon1 {
width: 50px;
height: 50px;
margin-left: 45px;
}
.icon2 {
width: 50px;
height: 50px;
margin-left: 56px;
align-content: center;
}
.icon3 {
width: 50px;
height: 50px;
margin-left: 58px;
}
.question {
text-align: center;
color: #535f6b;
font-family: sans-serif;
font-style: italic;
}
.green {
animation-name: backgroundGreen;
animation-duration: 1.5s;
animation-iteration-count: 3;
background-color:#0f0;
}
.red {
animation-name: backgroundRed;
animation-duration: 1s;
animation-iteration-count: 3;
background-color:#f00;
}
/* The animation code */
#keyframes backgroundGreen {
0% {background-color:#fff;}
50% {background-color:#00ffbb;}
100% {background-color:#00ff00;}
}
#keyframes backgroundRed {
0% {background-color:#fff;}
50% {background-color:#ff0055;}
100% {background-color:#ff0000;}
}
<p class="question"><b>Drag and drop the elements to their corresponding set to achieve: <br>a. 3 circles in the circle set<br>b. 2 triangles in the triangle set<br>c. 5 squares in the square set</b></p>
<div class="container">
<div class="column column-one"><img src="https://cdn1.iconfinder.com/data/icons/material-core/20/check-circle-outline-blank-128.png" id="c1" style="margin-left: 55px"></div>
<div class="column column-two"></div>
<div class="column column-three"><img src="https://cdn1.iconfinder.com/data/icons/feather-2/24/square-128.png" id="s1" style="margin-left: 58px"></div>
<div class="column column-four"><img src="https://cdn1.iconfinder.com/data/icons/feather-2/24/triangle-128.png" id="t1" style="margin-left: 45px"></div>
<div class="column column-five"></div>
</div>
<br>
<div class="container">
<div class="column column-one">
<div class="drop-zone1" id="dzt"></div>
</div>
<div class="column column-two"></div>
<div class="column column-three">
<div class="drop-zone2" id="dzc"></div>
</div>
<div class="column column-four">
<div class="drop-zone3" id="dzs"></div>
</div>
<div class="column column-five"></div>
</div>
<div class="container">
<div class="column column-one">
<div class="icon1"><img src="https://cdn1.iconfinder.com/data/icons/feather-2/24/triangle-64.png"></div>
</div>
<div class="column column-two"></div>
<div class="column column-three">
<div class="icon2"><img src="https://cdn1.iconfinder.com/data/icons/material-core/20/check-circle-outline-blank-64.png"></div>
</div>
<div class="column column-four">
<div class="icon3"><img src="https://cdn1.iconfinder.com/data/icons/feather-2/24/square-64.png"></div>
</div>
<div class="column column-five"></div>
</div>
Hello I'm stuck on how to add category for my to do list. When you click on Button of category need change class name. I don't understand how to correctly write if/else statement when button is clicked.
plan how it need to work
Write task name
Choose Category
Add new task
May be somebody can help me out ore give some advice how to solve this problem!
Sorry for my english and if my question is to badly explained!
var toDoList = function() {
var addNewTask = function() {
var input = document.getElementById("taks-input").value,
itemTexts = input,
colA = document.getElementById('task-col-a').children.length,
colB = document.getElementById('task-col-b').children.length,
taskBoks = document.createElement("div"),
work = document.getElementById("work"),
Category = "color-2",
taskCount = 1;
if (work.onclick === true) {
var Category = "color";
}
taskBoks.className = "min-box";
taskBoks.innerHTML = '<div class="col-3 chack" id="task_' + (taskCount++) + '"><i class="fa fa-star"></i></div><div class="col-8 task-text" id="taskContent"><p>' + itemTexts + '</p><span id="time-now"></span></div><div class="col-1 ' + (Category) + '"></div>'
if (colB < colA) {
var todolist = document.getElementById("task-col-b");
} else {
var todolist = document.getElementById("task-col-a");
}
//todolist.appendChild(taskBoks);
todolist.insertBefore(taskBoks, todolist.childNodes[0]);
},
addButton = function() {
var btn2 = document.getElementById("add-task-box");
btn2.onclick = addNewTask;
};
addButton()
}
toDoList();
p {
padding: 20px 20px 20px 45px;
}
.chack {
background-color: #4c4b62;
height: 100%;
width: 40px;
}
.task-text {
background-color: #55566e;
height: 100%;
width: 255px;
}
.color {
width: 5px;
height: 100%;
background-color: #fdcd63;
float: right;
}
.color-2 {
width: 5px;
height: 100%;
background-color: red;
float: right;
}
.color-3 {
width: 5px;
height: 100%;
background-color: purple;
float: right;
}
.task {
height: 100px;
width: 300px;
border: 1px solid #fff;
float: left;
}
.chack,
.task-text {
float: left;
}
.add-new-task {
margin-bottom: 50px;
height: 80px;
width: 588px;
background-color: rgb(85, 86, 110);
padding-top: 30px;
padding-left: 15px;
}
.min-box {
height: 100px;
border-bottom: 1px solid #fff;
}
.center {
padding-top: 20px;
padding-left: 50px;
}
.fa-star {
padding-left: 14px;
padding-top: 100%;
}
#add-task-box {
float: right;
margin-right: 10px;
margin-top: -7px;
border: none;
background-color: rgb(255, 198, 94);
padding: 10px;
}
#taks-input {
height: 30px;
width: 350px;
margin-top: -7px;
}
.category {
margin-top: 10px;
}
<div class="container">
<div class="add-new-task">
<input type="text" id="taks-input">
<button id="add-task-box">Add New Task box</button>
<div class="category">
<button class="catBtn" id="work">Work</button>
<button class="catBtn" id="home">Home</button>
<button class="catBtn" id="other">Other</button>
</div>
</div>
<div class="lg-task" id="bigTask"></div>
<div class="task" id="task-col-a"></div>
<div class="task" id="task-col-b"></div>
</div>
you need to bind click event to your buttons and store that value in Category, so in you js add this
var toDoList = function() {
// set to default
var Category = "color-3";
// attach event to buttons
var catButtons = document.getElementsByClassName("catBtn");
// assign value based on event
var myCatEventFunc = function() {
var attribute = this.getAttribute("id");
if (attribute === 'work') {
Category = 'color';
} else if (attribute === 'home') {
Category = 'color-2';
}
};
for (var i = 0; i < catButtons.length; i++) {
catButtons[i].addEventListener('click', myCatEventFunc, false);
}
Demo: Fiddle
and remove this code from addNewTask function
if (work.onclick === true) {
var Category = "color";
}
It is a bit hard to understand what you are doing, what you are going for (a module of some kind?). You were not that far away from a working state.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Task</title>
<style>
p {
padding: 20px 20px 20px 45px;
}
.chack {
background-color: #4c4b62;
height: 100%;
width: 40px;
}
.task-text {
background-color: #55566e;
height: 100%;
width: 255px;
}
.color {
width: 5px;
height: 100%;
background-color: #fdcd63;
float: right;
}
.color-2 {
width: 5px;
height: 100%;
background-color: red;
float: right;
}
.color-3 {
width: 5px;
height: 100%;
background-color: purple;
float: right;
}
.task {
height: 100px;
width: 300px;
border: 1px solid #fff;
float: left;
}
.chack,
.task-text {
float: left;
}
.add-new-task {
margin-bottom: 50px;
height: 80px;
width: 588px;
background-color: rgb(85, 86, 110);
padding-top: 30px;
padding-left: 15px;
}
.min-box {
height: 100px;
border-bottom: 1px solid #fff;
}
.center {
padding-top: 20px;
padding-left: 50px;
}
.fa-star {
padding-left: 14px;
padding-top: 100%;
}
#add-task-box {
float: right;
margin-right: 10px;
margin-top: -7px;
border: none;
background-color: rgb(255, 198, 94);
padding: 10px;
}
#taks-input {
height: 30px;
width: 350px;
margin-top: -7px;
}
.category {
margin-top: 10px;
}
</style>
<script>
var toDoList = function() {
var addNewTask = function() {
var input = document.getElementById("taks-input").value,
itemTexts = input,
colA = document.getElementById('task-col-a').children.length,
colB = document.getElementById('task-col-b').children.length,
taskBoks = document.createElement("div"),
work = document.getElementById("work"),
Category = "color-2",
taskCount = 1;
if (work.onclick === true) {
Category = "color";
}
taskBoks.className = "min-box";
taskBoks.innerHTML = '<div class="col-3 chack" id="task_'
+ (taskCount++) +
'"><i class="fa fa-star"></i></div><div class="col-8 task-text" id="taskContent"><p>'
+ itemTexts +
'</p><span id="time-now"></span></div><div class="col-1 '
+ (Category) + '"></div>'
if (colB < colA) {
var todolist = document.getElementById("task-col-b");
} else {
var todolist = document.getElementById("task-col-a");
}
//todolist.appendChild(taskBoks);
todolist.insertBefore(taskBoks, todolist.childNodes[0]);
},
// I don't know what to do with that?
addButton = function() {
var btn2 = document.getElementById("add-task-box");
btn2.onclick = addNewTask();
};
// return the stuff you want to have public
return {
addNewTask:addNewTask
};
}
var f;
// wait until all HTML is loaded and put the stuff from above into the variable `f`
// you can call it with f.someFunction() in your case f.addNewTask()
window.onload = function(){
f = toDoList();
}
</script>
</head>
<body>
<div class="container">
<div class="add-new-task">
<input type="text" id="taks-input">
<button id="add-task-box" onclick="f.addNewTask()">Add New Task box</button>
<div class="category">
<button class="catBtn" id="work" >Work</button>
<button class="catBtn" id="home">Home</button>
<button class="catBtn" id="other">Other</button>
</div>
</div>
<div class="lg-task" id="bigTask"></div>
<div class="task" id="task-col-a"></div>
<div class="task" id="task-col-b"></div>
</div>
</body>
</html
I hope you understood what I did?