I have this typewriter effect, I also have a website in 3 languages. When changing the language, I want the script to be re-executed with the new language. For this, I added an onclick event. Everything works, but there is a bug, if we change the language during the execution of the script, the new one will be executed on top of the old one. So, how, in my case, can I stop the old script and execute the new one?
I tried to use return as posted in other answers, tried to use clearTimeout but still doesn't work.
The snippet does not work. I am using localStorage and here it looks like it is locked.
UPD. The snippet is already working.
var isTag, text, langText, i = 0;
langText = "Hi!<br>Text,<br>Text ";
(function e() {
if ((text = langText.slice(0, ++i)) !== langText) {
document.querySelector(".index-title-main h1").innerHTML = text;
var t = text.slice(-1);
if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
setTimeout(e, 100);
}
}());
document.querySelector('.en').onclick = function() {
var isTag, text, langText, i = 0;
langText = "Hi!<br>Text,<br>Text ";
(function e() {
if ((text = langText.slice(0, ++i)) !== langText) {
document.querySelector(".index-title-main h1").innerHTML = text;
var t = text.slice(-1);
if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
setTimeout(e, 100);
}
}());
};
document.querySelector('.de').onclick = function() {
var isTag, text, langText, i = 0;
langText = "Hallo!<br>Text,<br>Text ";
(function e() {
if ((text = langText.slice(0, ++i)) !== langText) {
document.querySelector(".index-title-main h1").innerHTML = text;
var t = text.slice(-1);
if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
setTimeout(e, 100);
}
}());
};
document.querySelector('.ru').onclick = function() {
var isTag, text, langText, i = 0;
langText = "Привет!<br>Текст,<br>Текст ";
(function e() {
if ((text = langText.slice(0, ++i)) !== langText) {
document.querySelector(".index-title-main h1").innerHTML = text;
var t = text.slice(-1);
if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return e();
setTimeout(e, 100);
}
}());
};
.lang{
display: flex;
}
.lang a{
color: #000;
width: 100px;
display: block;
transition: .5s;
font-weight: bold;
text-align: center;
text-decoration: none;
border: 1px solid #000;
}
.lang a:not(:last-child){
margin-right: 10px;
}
.lang a:hover{
color: #fff;
transition: .5s;
background-color: #000;
}
.index-title-main{
padding-left: 50px;
}
<div class="lang">
<a class="en" href="#">English</a>
<a class="de" href="#">Deutsche</a>
<a class="ru" href="#">Русский</a>
</div>
<div class="index-title-main">
<h1></h1>
</div>
I have refactored your code and moved the common function outside the click event handler.
We need to clear the interval at the start of the function as we can be sure that as the execution has reached here we no longer need any previous running instance of other language click handlers.
var langText, i = 0, timeout;
langText = "Hi!<br>Text,<br>Text ";
function animateText() {
var isTag, text;
timeout && clearTimeout(timeout);
if ((text = langText.slice(0, ++i)) !== langText) {
document.querySelector(".index-title-main h1").innerHTML = text;
var t = text.slice(-1);
if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return animateText();
timeout = setTimeout(animateText, 100);
}
};
animateText();
document.querySelector('.en').onclick = function() {
i = 0, langText = "Hi!<br>Text,<br>Text ";
animateText();
};
document.querySelector('.de').onclick = function() {
i = 0, langText = "Hallo!<br>Text,<br>Text ";
animateText();
};
document.querySelector('.ru').onclick = function() {
i = 0, langText = "Привет!<br>Текст,<br>Текст ";
animateText();
};
.lang{
display: flex;
}
.lang a{
color: #000;
width: 100px;
display: block;
transition: .5s;
font-weight: bold;
text-align: center;
text-decoration: none;
border: 1px solid #000;
}
.lang a:not(:last-child){
margin-right: 10px;
}
.lang a:hover{
color: #fff;
transition: .5s;
background-color: #000;
}
.index-title-main{
padding-left: 50px;
}
<div class="lang">
<a class="en" href="#">English</a>
<a class="de" href="#">Deutsche</a>
<a class="ru" href="#">Русский</a>
</div>
<div class="index-title-main">
<h1></h1>
</div>
Here is a DRY version
const langTexts = {
en: "Hi!<br>Text,<br>Text ",
de: "Hallo!<br>Text,<br>Text ",
ru: "Привет!<br>Текст,<br>Текст "
}
let langText = langTexts["en"]; // langText[languageFromLocalStorage || "en"]
let tId, isTag, cnt = 0;
const h1 = document.querySelector(".index-title-main h1");
const typer = () => {
if ((text = langText.slice(0, ++cnt)) !== langText) {
h1.innerHTML = text;
const t = text.slice(-1);
if ("<" === t && (isTag = !0), ">" === t && (isTag = !1), isTag) return typer();
tId = setTimeout(typer, 100);
}
}
document.getElementById("nav").addEventListener("click", e => {
e.preventDefault();
const tgt = e.target;
console.log(tgt.getAttribute("lang"))
cnt = 0;
langText = langTexts[tgt.getAttribute("lang")];
clearTimeout(tId)
tId = setTimeout(typer, 100);
})
typer()
.lang {
display: flex;
}
.lang a {
color: #000;
width: 100px;
display: block;
transition: .5s;
font-weight: bold;
text-align: center;
text-decoration: none;
border: 1px solid #000;
}
.lang a:not(:last-child) {
margin-right: 10px;
}
.lang a:hover {
color: #fff;
transition: .5s;
background-color: #000;
}
.index-title-main {
padding-left: 50px;
}
<div id="nav">
<a class="langLink" href="#" lang="en">English</a>
<a class="langLink" href="#" lang="de">Deutsch</a>
<a class="langLink" href="#" lang="ru">Русский</a>
</div>
<div class="index-title-main">
<h1></h1>
</div>
Related
Just wanted to know easiest way to achieve this
Perhaps something like this:
(()=>
{
const formEls = document.querySelectorAll(".input-tags");
for(let i = 0; i < formEls.length; i++)
{
const formEl = formEls[i],
inputEl = document.createElement("input"),
tagsEl = document.createElement("span"),
listEl = document.createElement("datalist");
formEl.tags = [];
Object.defineProperties(formEl, {
list: {
get(){return getData(this, "list")},
set(val){this.dataset.list = val}
},
tags: {
get(){return getData(this, "tags")},
set(val){this.dataset.tags = val}
},
value:
{
get(){return this.dataset.value || ""},
set(val){this.dataset.value = val}
}
});
const list = formEl.list;
listEl.id = "input-tags-datalist" + i;
inputEl.setAttribute("list", listEl.id);
inputEl.type = "text";
tagsEl.className = "tags";
for(let i = 0, optionEl = document.createElement("option"); i < list.length; i++)
{
optionEl = optionEl.cloneNode(false);
optionEl.value = list[i];
listEl.appendChild(optionEl);
}
formEl.appendChild(tagsEl);
formEl.appendChild(inputEl);
formEl.appendChild(listEl);
inputEl._isClicked = true;
inputEl.addEventListener("keydown", e => inputEl._isClicked = !e.keyCode || e.keyCode==13);
inputEl.addEventListener("keyup", e => inputEl._isClicked = true);
inputEl.addEventListener("input", e =>
{
formEl.value = inputEl.value;
if (!inputEl._isClicked && !inputEl.value.match(/(^[^"']+ $)|(^(["']).+\3$)/))
{
dispatchEvent(formEl, "input");
return inputWidth(formEl);
}
const val = inputEl.value.replace(/^\s*((["'])([^"']+)\2|([^"']+)\s+)$/, "$4$3").replace(/[^\w -_]+/g, "").replace(/[ ]{2,}/g, " ");
if (formEl.dataset.autotags !== undefined || formEl.list.indexOf(val) != -1)
{
inputEl.value = val;
addTag(inputEl);
}
formEl.value = inputEl.value;
dispatchEvent(formEl, "input");
inputWidth(formEl);
});//inputEl.oninput()
tagsEl.addEventListener("click", e =>
{
if (!e.target.parentNode.classList.contains("tag"))
return;
const tag = e.target.parentNode.textContent,
list = formEl.list,
tags = formEl.tags,
index = list.indexOf(tag),
optionEl = listEl.children[index];
if (optionEl.classList.contains("new"))
{
list.splice(index, 1);
optionEl.parentNode.removeChild(optionEl);
}
else
optionEl.disabled = false;
tags.splice(tags.indexOf(tag), 1);
formEl.tags = tags;
formEl.list = list;
e.target.parentNode.parentNode.removeChild(e.target.parentNode);
inputWidth(formEl);
e.stopPropagation();
formEl.click();
dispatchEvent(formEl, "input");
});//tagsEl.onclick()
formEl.addEventListener("click", e => inputEl.focus());
inputWidth(formEl);
}
function dispatchEvent(el, type, opts)
{
return el.dispatchEvent(new Event(type, opts));
}
function inputWidth(formEl)
{
const inputEl = formEl.querySelector("input");
inputEl.style.width = "1em"; //min width
const inputStyle = window.getComputedStyle(inputEl),
formStyle = window.getComputedStyle(inputEl.parentNode),
inputRect = inputEl.getBoundingClientRect(),
formRect = inputEl.parentNode.getBoundingClientRect(),
canvas = document.createElement('canvas'),
ctx = canvas.getContext("2d");
ctx.font = inputStyle.font;
const widthText = (ctx.measureText(inputEl.value).width
+ parseFloat(inputStyle.paddingLeft)
+ parseFloat(inputStyle.paddingRight)
+ parseFloat(inputStyle.textIndent)
+ parseFloat(inputStyle.borderLeftWidth)
+ parseFloat(inputStyle.borderRightWidth)
+ 1
),
widthBox = formRect.right - inputRect.left - parseFloat(formStyle.paddingLeft) - parseFloat(formStyle.paddingRight) - 1;
inputEl.style.width = Math.max(widthText, widthBox) + "px";
}
function getData(el, key)
{
return el.dataset[key] ? el.dataset[key].split(",") : [];
}
function addTag(input)
{
const formEl = input.parentNode,
tag = input.value.trim(),
list = formEl.list,
tags = formEl.tags;
if (tag === "" || tags.indexOf(tag) != -1)
return;
const tagsEl = formEl.querySelector(".tags"),
tagEl = document.createElement("span"),
datalistEl = formEl.querySelector("datalist");
if (formEl.dataset.autotags !== undefined && list.indexOf(tag) == -1)
{
const option = document.createElement("option");
option.value = tag;
option.className = "new";
datalistEl.appendChild(option);
list[list.length] = tag;
}
tags[tags.length] = tag;
formEl.list = list;
formEl.tags = tags;
const index = list.indexOf(tag);
datalistEl.children[index].disabled = true;
tagEl.className = "tag";
tagEl.textContent = tag;
tagEl.appendChild(document.createElement("span"));
tagsEl.appendChild(tagEl);
input.value = "";
}
})();
//example:
const test = document.getElementById("test");
test.addEventListener("input", e =>
{
if (e.target !== test)
return;
console.log('value:', test.value);
console.log("tags:", JSON.stringify(test.tags));
console.log("list:", JSON.stringify(test.list));
}, false);
.input-tags
{
display: inline-block;
border: 1px solid black;
font-size: 0.8em;
padding: 0.1em 0.1em 0.1em 0.05em;
width: 100%;
line-height: 1em;
}
.input-tags > input,
.input-tags > input:focus,
.input-tags > input:active
{
outline: none;
border: none;
margin: 0.15em 0;
vertical-align: middle;
max-width: 100%;
box-sizing: border-box;
}
.input-tags > input::-webkit-calendar-picker-indicator
{
display: none !important;
}
.input-tags > .tags
{
vertical-align: middle;
}
.input-tags .tags .tag
{
display: inline-block;
background-color: lightblue;
border: 1px solid blue;
border-radius: 2px;
font-family: "Segoe UI","Liberation Sans",sans-serif;
margin: 0.1em;
padding: 0 0.2em;
line-height: 1.3em;
}
.input-tags .tags .tag > span
{
margin: -0.05em -0.2em 0 0.05em;
cursor: pointer;
display: inline-block;
font-size: 1.3em;
transform: rotate(45deg);
border-radius: 2em;
line-height: 0.7em;
float: right;
}
.input-tags .tags .tag > span:before
{
content: "+";
position: relative;
top: -0.1em;
}
.input-tags .tags .tag > span:hover
{
background-color: #60B3CE;
}
<div style="display: grid; grid-template-columns: auto auto">
<span>Auto-add new tags, suggestions:</span>
<div style="display: inline-block; width: 50vw;">
<div id="test" class="input-tags" data-autotags data-list="test,sometag,SOMETAG,another tag,another tag2,another tag3,another,tag"></div>
</div>
<span>Auto-add new tags, no suggestions:</span>
<div style="display: inline-block; width: 50vw;">
<span class="input-tags" data-autotags></span>
</div>
<span>No new tags, suggestions:</span>
<div style="display: inline-block; min-width: 10em;">
<div class="input-tags" data-list="test,some tag,very long tag,blah"></div>
</div>
<div>
I'm working on a tictactoe Person vs Person game. As a bonus, we can try to implement a minimax algorithm to play against the computer. After numerous trials and errors, I think I have the function so far, that it goes through the calculation without an error. However, the return value for best Score is always -10, assuming the player and not the computer would win.
I have two problems in the code:
the minimax-function always returns the value -10, assuming the person would win.
I cant play the last turn. In the debugger I can see that my gameData array, that keeps track of the visible field, works normally like so: [0,"X","X","O","X","O","O",7,"X"]. But the arrays player.person and player.computer have already stored the 0 and the 7. This should not happen.
At this point I am stuck. And I would tell you what I have been trying so far, but the last couple hours were just poking in the dark pretty much. Therefore the least I can do is write down the steps the code takes till the end:
Important variables etc:
Computer is represented by "O", person by "X"
Array gameData: Starts as [0,1,2,...,8] and replaces the numbers with "X" or "O". It tries to prevent that the tictactoe fields can be selected more than once.
Object player with .person-Array and .computer-Array both start as empty. I use these to check if either of them won the game.
isWinner(PLAYER) iterates through the winning conditions and checks if person or computer match it. The function returns the object ({win:true}) if so.
isTie() checks if there is a tie. It returns the object ({tie:true]), if the conditions isWinner(player.computer) = false, isWinner(player.person) = false and emptySpaces(gameData).length = 0 are met.
the function bestMove() searches for the bestMove of computer. Here's where minimax gets executed.
Code Logic overall:
the code starts at line 140 with function vsComputerGame()
next step is function personMove() in line 301
the player's choice "X" gets stored in the gameData Array. EG gameData = [0,"X",2,...,8]. And the position of "X" (in the exp 1`) gets pushed into player.person.
next it checks, if the person won the game or the game is a tie.
next the function bestMove() gets executed. It chooses a tictactoe-field for the computer.
next player.person and player.computer get updated. Without this step, minimax keeps pushing numbers in those arrays.
Code logic bestMove() and minimax():
bestMove() starts at line 190
the initial player.person and player.computer are saved, to restore them, right after the minimax() function returns a value. Same problem as above: Otherwise, isWinner() returns true on the second click of the player.
for loop gets executed. It selects the first available spot in gameData and replaces it with an "O". player.computer gets updated with this possible move from the computer.
then minimax gets executed, which basically has the same code for both player.computer and player.person, as described in this for loop.
when minimax() returns a value, it get stored in the variable score.
now the gameData Array, player.person and player.computer are reset, so the next iteration of the for loop does not flood them.
at last the if (score.eval > bestScore) checks for the highest score. If highest, the index of the current iteration gets stored in the move variable and is then used to place the "O" on the visible field and inside gameData.
"use strict"
// this function stores the chosen players (condition: player1, player2, computer). The start-game is in another module
let menupage = (function() {
let playerSelection = document.querySelectorAll(".player-selection");
let modalContainer = document.querySelector(".modal-bg");
let submitName = document.querySelector("#submit");
let btnColorPlayerTwo = document.querySelector("#player-two");
let btnColorComputer = document.querySelector("#computer");
let btnColorplayerOne = document.querySelector("#player-one");
let modalClose = document.querySelector(".modal-close");
let inputField = document.querySelector("#name");
let isplayerOne;
let gameModeData = {
playerOne : "",
playerTwo : "",
computer : false,
}
function closeModal() {
inputField.value = "";
modalContainer.classList.remove("bg-active");
}
function submitPlayer() {
if (isplayerOne === true) {
if (inputField.value === "") {
alert("Please enter your battle-tag");
} else if (inputField.value !== "") {
btnColorplayerOne.style.backgroundColor = "#4CAF50";
gameModeData.playerOne = inputField.value;
inputField.value = "";
modalContainer.classList.remove("bg-active");
}
}
if (isplayerOne === false) {
if (inputField.value === "") {
alert("Please enter your battle-tag");
} else if (inputField.value !== "") {
gameModeData.playerTwo = inputField.value;
btnColorPlayerTwo.style.backgroundColor = "#f44336";
gameModeData.computer = false;
btnColorComputer.style.backgroundColor = "#e7e7e7";
inputField.value = "";
modalContainer.classList.remove("bg-active");
}
}
}
function definePlayer(id, color) {
modalClose.addEventListener("click", closeModal);
if (id === "player-one") {
if (color.backgroundColor === "" || color.backgroundColor === "rgb(231, 231, 231)") {
isplayerOne = true;
modalContainer.classList.add("bg-active");
submitName.addEventListener("click", submitPlayer);
} else if (color.backgroundColor === "rgb(76, 175, 80)") {
color.backgroundColor = "#e7e7e7";
gameModeData.playerOne = "";
}
}
if (id === "player-two") {
if (color.backgroundColor === "" || color.backgroundColor === "rgb(231, 231, 231)") {
isplayerOne = false;
modalContainer.classList.add("bg-active");
submitName.addEventListener("click", submitPlayer);
}
}
}
function defineOponent(target) {
if (target.backgroundColor === "rgb(0, 140, 186)") {
return;
} else if (target.backgroundColor === "rgb(231, 231, 231)" || target.backgroundColor === "") {
target.backgroundColor = "#008CBA";
btnColorPlayerTwo.style.backgroundColor = "#e7e7e7";
gameModeData.playerTwo = "";
gameModeData.computer = true;
}
}
let setupPlayers = function setupPlayers() {
if (this.id === "player-one" || this.id === "player-two") {
definePlayer(this.id, this.style);
} else if (this.id === "computer") {
defineOponent(this.style);
}
}
playerSelection.forEach(button => button.addEventListener("click", setupPlayers))
return gameModeData;
}())
let startRound = (function startRound() {
let startGameBtn = document.querySelector("#start-game");
let startScreen = document.querySelector(".start-screen");
let gameboard = document.querySelector(".gameboard");
let selectionMenu = document.querySelector(".window-container");
let frame = document.querySelector(".frame");
let scoreboardPlayer = document.querySelector(".scoreboard-left");
let scoreboardOponent = document.querySelector(".scoreboard-right");
let scorePlayer = document.querySelector(".scoreboard-player");
let scoreOponent = document.querySelector(".scoreboard-oponent");
function displayScore() {
scorePlayer.innerText = menupage.playerOne;
menupage.computer === false ? scoreOponent.innerText = menupage.playerTwo : scoreOponent.innerText = "Computer";
}
function startGame() {
if (menupage.playerOne === "") {
alert("Please choose your profile.");
} else if (menupage.playerTwo === "" && menupage.computer === false) {
alert("Please choose an opponent.")
} else {
startScreen.style.display = "none";
gameboard.style.display = "grid";
scoreboardPlayer.style.display = "grid";
scoreboardOponent.style.display = "grid";
frame.style.display = "none";
selectionMenu.style.gridTemplateAreas = '"header header header" "scoreboard-left gameboard scoreboard-right" "frame frame frame"';
displayScore();
game();
}
}
startGameBtn.addEventListener("click", startGame);
}())
/* ***************************** GAME VS COMPUTER FUNCTION STARTS HERE ************************* */
let vsComputerGame = (function vsComputerGame() {
let player = {
person : [],
computer : [],
}
let gameData = [0, 1, 2, 3, 4, 5, 6, 7, 8]
let isWinner = function isWinner(PLAYER) {
let check = PLAYER.join();
let condition = {
1 : ["0","1","2"],
2 : ["3","4","5"],
3 : ["6","7","8"],
4 : ["0","4","8"],
5 : ["2","4","6"],
6 : ["0","3","6"],
7 : ["1","4","7"],
9 : ["2","5","8"]
}
for (const property in condition) {
if (condition[property].every(v => check.includes(v)) === true) {
return ({win : true});
}
}
return ({win : false });
};
let isTie = function isTie() {
if (emptySpaces(gameData).length === 0 && isWinner(player.computer).win === false && isWinner(player.person).win === false) {
return ({tie: true});
} else {
return ({tie : false});
}
}
function emptySpaces(gameData) {
let updatedBoard = [];
for (let i = 0; i < gameData.length; i++) {
if (gameData[i] !== "X") {
if (gameData[i] !== "O") {
updatedBoard.push(gameData[i]);
}
}
}
return updatedBoard;
}
function bestMove() {
let bestScore = -Infinity;
let move;
// the object player with the values {player:[], computer:[]} is used in isWinner to check who won,
// storedComputer and storedPlayer is needed, to reset both arrays after they go through minimax,
// without, the two object-arrays get fludded
let storedComputer = player.computer.map(x => x);
let storedPlayer = player.person.map(x => x);
// first round of the for loop sets a field for the computer,
// first execution of minimax jumps to player.person
for (let i = 0; i < 9; i++) {
// gameData is the Array, that stores the players' moves. Example: [0, 1, 2, "X", 4, 5, "O", 7, 8]
if (gameData[i] !== "X") {
if (gameData[i] !== "O") {
gameData[i] = "O";
player.computer.push(i);
let score = minimax(gameData, player.person);
gameData[i] = i;
player.person = storedPlayer;
player.computer = storedComputer;
if (score.eval > bestScore) {
bestScore = score.eval;
move = i;
console.log(bestScore);
}
}
}
}
// after a move is found for the computer, O gets logged in the gameData Array and on the visible gameboard
let positionO = document.getElementsByName(move);
gameData[move] = "O";
positionO[0].innerText = "O";
}
function minimax(gameData, PLAYER) {
// the BASE of minimax.
// ************ console.log shows, that it always returns -10 ***************
if (isWinner(player.person).win === true) { return ({eval:-10});}
if (isWinner(player.computer).win === true) { return ({eval:10});}
if (isTie().tie === true) {return ({eval:0});};
/*
PLAYER.push pushes the index-number into either player.computer or player.person
This is needed to check the isWinner function
After that, these Arrays get stored in storedComputer and storedPlayer
*/
if (PLAYER === player.computer) {
let bestScore = -Infinity;
for (let i = 0; i < 9; i++) {
if (gameData[i] !== "X") {
if (gameData[i] !== "O") {
PLAYER.push(i);
//let storedComputer = player.computer.map(x => x);
//let storedPlayer = player.person.map(x => x);
gameData[i] = "O";
let score = minimax(gameData, player.person);
//player.person, player.computer and gameData are resetted, after minimax returns a value
gameData[i] = i;
//player.person = storedPlayer;
//player.computer = storedComputer;
if (score.eval > bestScore) {
bestScore = score.eval;
}
}
}
}
return bestScore;
} else {
let bestScore = Infinity;
for (let i = 0; i < 9; i++) {
if (gameData[i] !== "X") {
if (gameData[i] !== "O") {
PLAYER.push(i);
//let storedComputer = player.computer.map(x => x);
//let storedPlayer = player.person.map(x => x);
gameData[i] = "X";
let score = minimax(gameData, player.computer);
//player.person = storedPlayer;
//player.computer = storedComputer;
gameData[i] = i;
if (score.eval < bestScore) {
bestScore = score.eval;
}
}
}
}
return bestScore;
}
}
let cells = document.querySelectorAll(".cell");
cells.forEach(cell => cell.addEventListener("click", personMove));
function personMove() {
if (this.innerText === "X" || this.innerText === "O") {
return;
} else {
let playersChoice = this.getAttribute("data-parent");
player.person.push(Number(this.getAttribute("data-parent")));
this.innerText = "X";
gameData[playersChoice] = "X";
if (isWinner(player.person).win === true) {
console.log("Win");
};
isTie();
bestMove();
player.computer = [];
player.person = [];
for (let i = 0; i < 9; i++) {
if (gameData[i] === "X") {
player.person.push(i);
} else if (gameData[i] === "O") {
player.computer.push(i);
}
}
}
}
})
/* ***************************** GAME VS COMPUTER FUNCTION ENDS HERE ************************* */
let vsPersonGame = (function vsPersonGame() {
let i = 1;
let player = [];
let oponent = [];
let buttons = document.querySelectorAll(".cell");
buttons.forEach(button => button.addEventListener("click", selection));
function selection() {
let newLocal = this
storeSelection(newLocal);
checkWinner();
}
function storeSelection(input) {
if (i >= 10 || input.innerText !== "") {
return;
} else if (i % 2 === 0) {
return input.innerText = "O", oponent.push(input.dataset.parent),
i++;
} else if (i % 2 !== 0) {
return input.innerText = "X", player.push(input.dataset.parent),
i++;
}
}
function checkWinner() {
let condition = {
1 : ["0","1","2"],
2 : ["3","4","5"],
3 : ["6","7","8"],
4 : ["0","4","8"],
5 : ["2","4","6"],
6 : ["0","3","6"],
7 : ["1","4","7"],
9 : ["2","5","8"]
}
for (const property in condition) {
let toStringplayer = player.join();
let toStringoponent = oponent.join();
if (condition[property].every(v => toStringplayer.includes(v)) === true) {
return alert(menupage.playerOne + " won");
} else if (condition[property].every(v => toStringoponent.includes(v)) === true) {
return alert(menupage.playerTwo + " won");
} else if (i === 10) {
if (condition[property].every(v => toStringplayer.includes(v)) === true) {
return alert(menupage.playerOne + " won");
} else if (condition[property].every(v => toStringoponent.includes(v)) === true) {
return alert(menupage.playerTwo + " won");
} else {
return alert("You tied");
}
}
}
}
})
let game = (function() {
if (menupage.computer === true) {
vsComputerGame();
} else {
vsPersonGame();
}
});
html, body {
display: grid;
height: 100%;
margin: 0;
padding: 0;
}
.window-container {
display: grid;
height: 100%;
grid-template-rows: 10% 80% 10%;
grid-template-areas:
"header header header"
". start-screen ."
"frame frame frame";
}
.header {
grid-area: header;
margin-top: 50px;
font-size: 30px;
text-align: center;
color: red;
font-weight: bolder;
}
.start-screen {
grid-area: start-screen;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 30%;
}
.selection-menu {
flex: 1;
display: grid;
grid-template-rows: 40% 20% 40%;
grid-template-areas:
". . player-two"
"player-one vs ."
". . computer"
}
#player-one {
grid-area: player-one;
background-color: #e7e7e7;
}
#player-two {
grid-area: player-two;
background-color: #e7e7e7;
}
#computer {
grid-area: computer;
background-color: #e7e7e7;
}
#start-game {
display: flex;
cursor: pointer;
border: none;
color: white;
background-color: rgb(37, 36, 36);
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}
#vs {
grid-area: vs;
text-align: center;
font-size: 30px;
font-weight: bold;
color: #4CAF50;
}
.player-selection {
cursor: pointer;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}
.gameboard {
grid-area: gameboard;
margin-top: 10%;
display: none;
justify-content: center;
grid-template-rows: 150px 150px 150px;
grid-template-columns: 150px 150px 150px;
grid-template-areas:
"tL tM tR"
"mL mM mR"
"bL bM bR";
}
.frame {
grid-area: frame;
display: flex;
position: fixed;
height: 250px;
bottom: 0px;
left: 0px;
right: 0px;
margin-bottom: 0px;
justify-content: center;
align-items: center;
}
.cell {
display: flex;
justify-content: center;
align-items: center;
font-size: 40px;
cursor: pointer;
}
.unselectable {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#tL {
grid-area: tL;
border-bottom: 2px solid black;
border-right: 2px solid black;
}
#tM {
grid-area: tM;
border-bottom: 2px solid black;
border-right: 2px solid black;
}
#tR {
grid-area: tR;
border-bottom: 2px solid black;
}
#mL {
grid-area: mL;
border-bottom: 2px solid black;
border-right: 2px solid black;
}
#mM {
grid-area: mM;
border-bottom: 2px solid black;
border-right: 2px solid black;
}
#mR {
grid-area: mR;
border-bottom: 2px solid black;
}
#bL {
grid-area: bL;
border-right: 2px solid black;
}
#bM {
grid-area: bM;
border-right: 2px solid black;
}
#bR {
grid-area: bR;
}
.modal-bg {
position: fixed;
width: 100%;
height: 100vh;
top: 0;
left: 0;
background-color: rgba(0,0,0,0.5);
display: flex;
justify-content: center;
align-items: center;
visibility: hidden;
opacity: 0;
transition: visibility 0s, opacity 0.5s;
}
.bg-active {
visibility: visible;
opacity: 1;
}
.modal {
position: relative;
background-color: white;
border-radius: 5px 5px 5px 5px;
width: 30%;
height: 20%;
display: flex;
justify-content: space-around;
align-items: center;
flex-direction: column;
}
.modal button {
padding: 10px 50px;
background-color: #2980b9;
color: white;
border: none;
cursor: pointer;
}
.modal-close {
position: absolute;
top: 10px;
right: 10px;
font-weight: bold;
cursor: pointer;
}
#modal-headline {
font-size: 20px;
}
#submit {
margin-top: 5px;
}
.scoreboard-left {
display: none;
}
.scoreboard-player {
grid-area: scoreboard-player;
display: flex;
}
.scoreboard-right {
display: none;
}
.scoreboard-oponent {
grid-area: scoreboard-oponent;
display: flex;
}
<!DOCTYPE html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="UTF-8">
<link href="styles.css" rel="stylesheet" type="text/css" />
<script src="script.js" defer></script>
<title>Tic Tac Toe</title>
</head>
<body>
<div class="window-container">
<div class="header">Tic Tac Toe</div>
<div class="start-screen">
<div class="selection-menu">
<button class="player-selection" id="player-one">Player One</button>
<button class="player-selection" id="player-two">Player Two</button>
<div id="vs">vs</div>
<button class="player-selection" id="computer">Computer</button>
</div>
</div>
<div class="gameboard">
<div class="cell unselectable" id="tL" data-parent="0" name="0"></div>
<div class="cell unselectable" id="tM" data-parent="1" name="1"></div>
<div class="cell unselectable" id="tR" data-parent="2" name="2"></div>
<div class="cell unselectable" id="mL" data-parent="3" name="3"></div>
<div class="cell unselectable" id="mM" data-parent="4" name="4"></div>
<div class="cell unselectable" id="mR" data-parent="5" name="5"></div>
<div class="cell unselectable" id="bL" data-parent="6" name="6"></div>
<div class="cell unselectable" id="bM" data-parent="7" name="7"></div>
<div class="cell unselectable" id="bR" data-parent="8" name="8"></div>
</div>
<div class="modal-bg">
<div class="modal">
<h2 id="modal-headline">Choose a Name:</h2>
<input type="text" id="name">
<button id="submit" class="submit">Submit</button>
<span class="modal-close">X</span>
</div>
</div>
<div class="frame">
<button id="start-game">Start Game</button>
</div>
<div class="scoreboard-left">
<div class="display-player">
<div class="scoreboard-player"></div>
<div class="p-win">Wins: </div><div class="player-win">0</div>
<div class="p-loss">Losses: </div><div class="player-loss">0</div>
<div class="p-tie">Ties: </div><div class="player-tie">0</div>
</div>
</div>
<div class="scoreboard-right">
<div class="display-oponent">
<div class="scoreboard-oponent"></div>
<div class="o-win">Wins: </div><div class="oponent-win">0</div>
<div class="o-loss">Losses: </div><div class="oponent-loss">0</div>
<div class="o-tie">Ties: </div><div class="oponent-tie">0</div>
</div>
</div>
</div>
</body>
</html>
I appreciate any feedback and hints to solve the problem.
Im creating a floating label , i manage to make a floating label on textbox but
in my dropdown it doesn't work. hope you can help me.
/** GLOBAL OBJECT **/
var $ = {
addClass: function(elem, name) {
var classes = elem.className.split(' '),
cIndex = classes.indexOf(name);
if (cIndex === -1) {
classes.push(name);
}
elem.className = classes.join(' ');
return this;
}, // END addClass
removeClass: function(elem, name) {
var classes = elem.className.split(' '),
cIndex = undefined;
function recursive() {
// use a recursive function to remove all instances
// of the class name
cIndex = classes.indexOf(name);
if (cIndex >= 0) {
classes.splice(cIndex, 1);
recursive();
}
}
recursive();
elem.className = classes.join(' ');
return this;
}, // END removeClass
hasClass: function(elem, name) {
var classes = elem.className.split(' '),
cIndex = classes.indexOf(name);
if (cIndex >= 0) {
return true;
} else {
return false;
}
}, // END hasClass
selectCreate: function(select, label) {
var _this = this;
id = '_' + select.id,
input = document.createElement('input'),
div = document.createElement('div'),
ul = document.createElement('ul'),
val = {
value: select.value,
text: select.options[select.selectedIndex].text
};
select.style.display = 'none';
ul.id = 'ul' + id;
ul.className = 'ddown-list';
ul.setAttribute('aria-live', 'polite');
input.setAttribute('type', 'text');
input.setAttribute('aria-autocomplete', 'list');
input.setAttribute('aria-haspopup', 'true');
input.setAttribute('aria-owns', ul.id);
input.className = 'dynamic-dropdown';
input.id = id;
if (select.getAttribute('data-required') === 'true') {
input.setAttribute('required', 'true');
}
label.setAttribute('for', id);
div.className = 'selectRegion';
div.appendChild(label);
div.appendChild(input);
div.appendChild(ul);
select.parentNode.insertBefore(div, select);
input.value = val.text;
if (input.value !== '') {
this.addClass(label, 'active');
} else {
this.addClass(label, 'inactive');
}
input.addEventListener('focus', function() {
_this.addClass(label, 'active')
.addClass(label, 'transition')
.removeClass(label, 'inactive');
if (this.setSelectionRange) {
this.setSelectionRange(0, this.value.length);
}
populateList(this, select, document.getElementById('ul' + this.id), -1, true);
}); // END focus
input.addEventListener('blur', function() {
var input = this;
setTimeout(function() {
if (input.value === '') {
_this.addClass(label, 'inactive')
.addClass(label, 'transition')
.removeClass(label, 'active');
} else {
var list = getList(input.value, select, false);
select.value = list.value[0];
input.value = list.text[0];
}
document.getElementById('ul' + input.id).innerHTML = '';
}, 250);
}); // END blur
input.addEventListener('keyup', function(e) {
var list = document.getElementById('ul' + this.id).getElementsByTagName('li'),
index = -1,
kC = e.keyCode;
for (var i = 0, x = list.length; i < x; i++) {
if (_this.hasClass(list[i], 'active')) {
index = i;
break;
}
}
if (kC !== 9 && kC !== 16) { // SHIFT && TAB
if (kC === 13) { // ENTER
var list = getList(this.value, select, false);
select.value = list.value[index];
this.value = list.text[index];
document.getElementById('ul' + this.id).innerHTML = '';
} else {
switch (kC) {
case 38: // ARROW UP
index--;
if (index < 0) {
index = 0;
}
break;
case 40: // ARROW DOWN
index++;
if (index >= list.length) {
index = list.length - 1;
}
break;
default:
index = -1;
break;
}
populateList(this, select, document.getElementById('ul' + this.id), index, false);
}
}
}); // END keyup
function populateList(input, select, target, index, focus) {
var list = getList(input.value, select, focus),
counter = 0,
output;
if (focus) {
index = select.selectedIndex - 1;
}
target.innerHTML = '';
for (var i = 0, x = list.value.length; i < x; i++) {
output = document.createElement('li');
if (counter === index) {
output.className = 'active';
}
output.appendChild(document.createTextNode(list.text[i]));
output.addEventListener('click', function() {
console.log('test');
input.value = this.innerHTML;
});
target.appendChild(output);
counter++;
}
if (index >= 0) {
var lis = target.getElementsByTagName('li'),
sTop = 0;
for (var i = 0, x = lis.length; i < x; i++) {
if (i >= index) {
break;
}
sTop += lis[i].clientHeight;
}
target.scrollTop = sTop;
}
} // END populateList
function getList(val, list, focus) {
var value = [],
text = [],
vLength = val.length;
if (focus) {
vLength = 0;
val = '';
}
for (var i = 0, x = list.length; i < x; i++) {
if (list[i].text !== '' &&
(list[i].text.toUpperCase().substring(0, vLength) === val.toUpperCase() ||
list[i].value.toUpperCase().substring(0, vLength) === val.toUpperCase())) {
value.push(list[i].value);
text.push(list[i].text);
}
}
return {
value: value,
text: text
};
} // END function getList
}, // END selectCreate()
}; // END $
window.onload = function() {
var labels = document.getElementsByTagName('label'),
id = '',
label = undefined,
input = undefined,
type = undefined;
for (var i = 0, x = labels.length; i < x; i++) {
label = labels[i];
id = label.getAttribute('for') || '';
input = document.getElementById(id);
if (input) {
type = input.getAttribute('type') || input.tagName;
type = type.toLowerCase();
if (input && (type === 'select')) {
$.selectCreate(input, label);
} // END if( input && select )
}
} // END for( labels )
}();
var demo = function() {
setTimeout(function() {
document.getElementById('_s').focus();
setTimeout(function() {
document.getElementById('_s').blur();
}, 750);
}, 500);
}();
body {
background-color: #F7F7F7;
font-family: Arial;
padding-top: 10%;
}
input,
label,
select {
width: 280px;
padding: 10px;
font-size: 16px;
}
input {
border: solid 1px #CCCCCC;
border: none;
overflow: visible;
outline: none;
background-color: transparent;
border-bottom: solid 1px #999;
}
label {
position: absolute;
}
label.active {
color: #3784BB;
margin-top: -20px;
font-size: 12px;
}
label.inactive {
color: #999999;
}
li.active {
background-color: rgba( 255, 0, 0, 0.1);
}
.transition {
transition: all linear 0.1s;
}
.input {
width: 300px;
margin: auto;
}
.input:first-child {
margin-bottom: 5%
}
.selectRegion {
width: 100%;
}
.selectRegion ul {
margin: 0;
padding: 0;
position: absolute;
width: 300px;
max-height: 200px;
overflow: auto;
box-shadow: 0 2px 3px rgba( 0, 0, 0, 0.1);
background-color: #FFFFFF;
z-index: 2;
}
.selectRegion ul li {
padding: 10px;
}
.selectRegion ul li:hover {
cursor: pointer;
}
.inputbox {
position: relative;
background: none;
margin-right: 50px;
}
.inputbox input {
width: 120%;
padding: 10px 0;
font-size: 19px;
color: #21a1e;
margin-bottom: 50px;
overflow: visible;
outline: none;
background-color: transparent;
border: none;
border-bottom: solid 1px #999;
margin-left: -10px;
margin-top: -15px;
}
.inputbox label {
display: block;
position: absolute;
top: 0;
left: 0;
padding: 10px 0;
font-size: 16px;
color: #999;
pointer-events: none;
transition: top 0.7s ease, opacity 0.7s ease;
border-radius: .25rem;
margin-left: -10px;
margin-top: -10px;
}
.inputbox input:focus+label,
.inputbox input:valid+label {
top: -18px;
left: 0;
color: #4285f4;
font-size: 12px;
cursor: pointer;
}
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="col-sm-5">
<button type="button" class="button2 " data-toggle="modal" data-target="#exampleModal1">Login</button>
</div>
<div class="modal fade" id="exampleModal1" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg " role="document">
<div class="modal-content">
<div class="modal-header ">
<h5 class="modal-title" id="exampleModalLabel" style=" color: #404E67;">Form</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form>
<div class="form-row ">
<div class="inputbox">
<input type="text" required>
<label>First Name </label>
</div>
<div class="inputbox">
<input type="text" required>
<label>Last Name</label>
</div>
</div>
<div class="form-row">
<div class="input">
<label for="s">Sample 1:</label>
<select id="s">
<option value=""></option>
<option value="1">Assignment</option>
<option value="2">Reading</option>
</select>
</div>
</div>
<div class="clear"></div>
<div class="input">
<label for="state">Sample 2</label>
<select id="state">
<option value=""></option>
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
</select>
</div>
</form>
</div>
</div>
</body>
</html>
here is my current output:
As you can see on my output the two dropdown is not working any idea how ca i make it a floating label like at my textbox?
I would like to toggle between degree's and fahrenheit when the temperature is clicked.
I have managed to do this when it is clicked on degree's it is changed to fahrenheit, but now how do i change it back to degree's when clicked on fahrenheit?
temp.addEventListener('click', degreeToF);
function degreeToF() {
const f = manchester.current.temp_c * 1.8 + 32;
temp.innerHTML = f.toFixed(0) + '<span class="degrees"> f </span>';
}
Here is my codepen: https://codepen.io/o-sewell/pen/mRyEyW
var showing = 'F';
temp.addEventListener('click', degreeToF);
function degreeToF() {
if(showing === 'F'){
// convert to C
showing = 'C';
const f = (manchester.current.temp_c - 32 ) * 5/9;
temp.innerHTML = f.toFixed(0) + '<span class="degrees"> c </span>';
} else {
// convert to
showing = 'F';
const f = manchester.current.temp_c * 1.8 + 32;
temp.innerHTML = f.toFixed(0) + '<span class="degrees"> f </span>';
}
}
Here you go. Used simple boolean value to tell the function which part of code to execute.
CodePen link
const weather = 'https://api.apixu.com/v1/current.json?key=cd93499e97644fcc873154715163112&q=Manchester';
const baseColors = ["#C2272D", "#F8931F", "#FFFF01", "#009245", "#0193D9", "#0C04ED", "#612F90"];
const tintColors = ["#F8DDDE", "#FEDBB4", "white", "#0193D9", "#009245", "#E7E6F9"];
let manchester = [];
fetch(weather)
.then((blob) => blob.json())
.then((data) => manchester = data)
.then((data) => displayWeather(data));
let iconWeather = document.querySelector('#weather');
let temp = document.querySelector('#temp');
let textLocation = document.querySelector('#text-location');
let textWeather = document.querySelector('#text-weather');
function displayWeather() {
iconWeather.src = manchester.current.condition.icon;
temp.innerHTML = manchester.current.temp_c + '<span class="degrees"> c </span>';
textLocation.innerHTML = manchester.location.name;
textWeather.innerHTML = manchester.current.condition.text;
};
const background = document.querySelector('.weather');
window.addEventListener('load', changeBackground);
function changeBackground() {
let random = Math.floor(Math.random() * baseColors.length);
let randomBaseColor = baseColors[random];
let randomTintColor = tintColors[random];
background.style.background = 'linear-gradient(0deg,' + randomBaseColor + ',' + randomTintColor + ')';
background.style.transition = 'background , 2s, ease';
}
setInterval(changeBackground, 2500);
temp.addEventListener('click', degreeToF);
var x = true;
function degreeToF() {
if (x) {
const f = manchester.current.temp_c * 1.8 + 32;
temp.innerHTML = f.toFixed(0) + '<span class="degrees"> f </span>';
x = !x;
} else {
const f = manchester.current.temp_c;
temp.innerHTML = f.toFixed(0) + '<span class="degrees"> c </span>';
x = !x;
}
}
* {
box-sizing: border-box;
}
.wrapper {
margin: 50px;
}
.weather {
max-width: 90%;
margin: 0 auto;
background: pink;
padding: 20px;
box-shadow: 0 5px rgba(0, 0, 0, 0.1);
border-radius: 6px;
}
#media (min-width: 800px) {
.weather {
max-width: 40%;
}
}
.weather__temperature {
margin-top: 50px;
text-align: center;
}
.weather__temperature--temp {
font-size: 80px;
cursor: pointer;
}
.weather__text {
text-align: center;
}
.weather__text--description {
color: black;
font-size: 18px;
}
.weather__icon {
margin-top: 5px;
}
.weather__icon--image {
display: block;
margin: 0 auto;
padding: 5px 0;
width: 150px;
height: auto;
}
.weather__location {
text-align: center;
}
.weather__location--text {
letter-spacing: 5px;
font-size: 22px;
margin-bottom: 50px;
}
.degrees {
color: red;
font-size: 20px;
}
<div class="wrapper">
<div class="weather">
<div class="weather__temperature" />
<p class="weather__temperature weather__temperature--temp" id="temp"></p>
</div>
<div class="weather__text">
<p class="weather__text weather__text--description" id="text-weather"></p>
</div>
<div class="weather__icon">
<img class="weather__icon weather__icon--image" id="weather" src="" />
</div>
<div class="weather__location">
<p class="weather__location--text" id="text-location"></p>
</div>
</div>
</div>
I need to make a Javascript To Do list (checklist), which I have already completed, but I cannot figure out how to make an edit and delete button also appear with each of the items the are entered. Here is what I have so far
<!doctype html>
<html>
<head>
<title>To Do List</title>
<link rel="stylesheet" type="text/css" href="ToDoList.css">
</head>
<body>
<h1> To Do List</h1>
<div id = "listBox">
<input type="text" id="inItemText"><button id = "btnAdd">Add</button>
</div>
<div class="tasks-parent">
<h4>Tasks:</h4>
<ul id = "todolist">
</ul>
</div>
<script src ="ToDoList.js"></script>
</body>
</html>
#btnAdd {
text-transform: uppercase;
background: #22B473;
border: none;
border-radius: 3px;
font-weight: bold;
color: #FFF;
padding: 3px 10px;
cursor: pointer;
width: auto;
}
.tasks-parent {
border: 2px solid #777;
margin-top: 5px;
width: 17%;
}
html {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
ul {
list-style: none;
padding: 0;
margin: 0;
width: 400px;
}
li {
padding: 5px 10px;
color: #000;
}
li span {
padding-left: 17px;
}
function updateItemStatus() {
var cbId = this.id.replace("cb_", "");
var itemText = document.getElementById("item_" + cbId);
if (this.checked) {
itemText.style.textDecoration = "line-through";
} else {
itemText.style.textDecoration = "none";
}
}
function addNewItem(list, itemText) {
var date = new Date();
var id = "" + date.getMinutes(); + date.getSeconds() +
date.getMilliseconds() + "";
var listItem = document.createElement("li");
listItem.id = "li_" + id;
var checkBox = document.createElement("input");
checkBox.type = "checkbox";
checkBox.id = "cb_" + id;
checkBox.onclick = updateItemStatus;
var span = document.createElement("span");
span.id = "item_" + id;
span.innerText = itemText;
listItem.appendChild(checkBox);
listItem.appendChild(span);
list.appendChild(listItem);
}
var inItemText = document.getElementById("inItemText");
inItemText.focus();
var btnNew = document.getElementById("btnAdd");
btnNew.onclick = function() {
var inItemText = document.getElementById("inItemText");
var itemText = inItemText.value;
if (!itemText || itemText === "" || itemText === " ") {
return false;
}
addNewItem(document.getElementById("todolist"), itemText);
};
inItemText.onkeyup = function(event) {
if (event.which == 13) {
var itemText = inItemText.value;
if (!itemText || itemText === "" || itemText === " ") {
return false;
}
addNewItem(document.getElementById("todolist"), itemText);
inItemText.focus();
inItemText.select();
}
};
You need to create additional two elements(one for edit and one for delete) and append them like you did with other elements:
function updateItemStatus() {
var cbId = this.id.replace("cb_", "");
var itemText = document.getElementById("item_" + cbId);
if (this.checked) {
itemText.style.textDecoration = "line-through";
} else {
itemText.style.textDecoration = "none";
}
}
function addNewItem(list, itemText) {
var date = new Date();
var id = "" + date.getMinutes(); + date.getSeconds() +
date.getMilliseconds() + "";
var listItem = document.createElement("li");
listItem.id = "li_" + id;
var checkBox = document.createElement("input");
checkBox.type = "checkbox";
checkBox.id = "cb_" + id;
checkBox.onclick = updateItemStatus;
var span = document.createElement("span");
span.id = "item_" + id;
span.innerText = itemText;
//create edit
var edit = document.createElement("a");
edit.href = "#";
edit.innerText = "edit";
//create delete
var deleteBtn = document.createElement("a");
deleteBtn.href = "#";
deleteBtn.innerText = "delete";
listItem.appendChild(checkBox);
listItem.appendChild(span);
//and append them in li
listItem.appendChild(edit);
listItem.appendChild(deleteBtn);
list.appendChild(listItem);
}
var inItemText = document.getElementById("inItemText");
inItemText.focus();
var btnNew = document.getElementById("btnAdd");
btnNew.onclick = function() {
var inItemText = document.getElementById("inItemText");
var itemText = inItemText.value;
if (!itemText || itemText === "" || itemText === " ") {
return false;
}
addNewItem(document.getElementById("todolist"), itemText);
};
inItemText.onkeyup = function(event) {
if (event.which == 13) {
var itemText = inItemText.value;
if (!itemText || itemText === "" || itemText === " ") {
return false;
}
addNewItem(document.getElementById("todolist"), itemText);
inItemText.focus();
inItemText.select();
}
};
#btnAdd {
text-transform: uppercase;
background: #22B473;
border: none;
border-radius: 3px;
font-weight: bold;
color: #FFF;
padding: 3px 10px;
cursor: pointer;
width: auto;
}
.tasks-parent {
border: 2px solid #777;
margin-top: 5px;
width: 35%;
}
html {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
ul {
list-style: none;
padding: 0;
margin: 0;
width: 400px;
}
li {
padding: 5px 10px;
color: #000;
}
li span {
padding-left: 17px;
}
li a {
padding: 0 5px 0 5px;
}
<h1> To Do List</h1>
<div id="listBox">
<input type="text" id="inItemText">
<button id="btnAdd">Add</button>
</div>
<div class="tasks-parent">
<h4>Tasks:</h4>
<ul id="todolist">
</ul>
</div>
You need to include the buttons inside your appended span. Also need to change .innerText to .innerHTML
span.innerHTML = itemText + "<button>Edit</button><button>Delete</button>";
add classes to the inserted buttons to style