I have created a todo-list following watchandcode.com course and I tried to add more functionality to it. So I want to make the COMPLETED button which toggles the non-completed list items ad completed,DISAPPEAR after I click on it and after it turns the list item into completed. I hope I expressed my self properly of what I'd like to achieve. Here's the code down below, thanks in advance!
I copied the whole code down below, but if you only need to see the parts that I might be referring (I am not sure, as I am really new into JS), here they are:
var view = {
displayTodos: function(){
var todosUl = document.querySelector("ul");
todosUl.innerHTML = '';
for (var i = 0; i < todoList.todos.length; i++){
var todoLi = document.createElement("li");
var todo = todoList.todos[i];
var todoTextForCompleted = "";
if (todo.completed === true){
todoTextForCompleted = todo.todoText;
todoLi.classList.toggle("checked");
} else {
todoTextForCompleted = todo.todoText;
todoLi.classList.toggle("notCompleted");
}
todoLi.id = i;
todoLi.textContent = todoTextForCompleted;
todoLi.appendChild(this.createDeleteButton());
todoLi.appendChild(this.createToggleButton());
todosUl.appendChild(todoLi);
}
},
createToggleButton: function(){
var toggleButton = document.createElement("button");
toggleButton.textContent = "Completed";
toggleButton.id= "toggleBtn";
return toggleButton;
},
Here's the whole code if its necessary:
//The object that holds the todo list:
var todoList = {
todos: [],
//Method for ADDING a TODO items
addTodo: function(todoText){
this.todos.push({
todoText: todoText,
completed: false,
});
},
//Method for changing the made TODO items
changeTodo: function(position, newValue){
this.todos[position].todoText = newValue;
},
//Method for deleting TODO items:
deleteTodo: function(position){
this.todos.splice(position, 1);
},
//Method for toggling a todo item as COMPLETED:
toggleCompleted: function(position){
var todo = this.todos[position];
todo.completed = !todo.completed;
},
//Method for toggling ALL todo items:
toggleAll: function(){
var totalTodos = this.todos.length;
//Counting the ones that are completed
var completedTodos = 0;
//Getting the number of the completed todos:
for(var i = 0; i < totalTodos; i++){
if(this.todos[i].completed === true) {
//For every todo item that is completed, increase completedTodos by 1;
completedTodos++;
}
}
//Case 1: If everything is true, the turn it into FALSE;
if(completedTodos === totalTodos){
for(var i = 0; i < totalTodos; i++){
this.todos[i].completed = false
}
//Case 2: Otherwise, make everything TRUE;
} else {
for (var i = 0; i < totalTodos; i++){
this.todos[i].completed = true;
};
};
}
}
//Object for the BUTTON HANDLERS:
var handlers = {
addTodo: function(){
var addTodoText = document.getElementById("addTodoTextInput");
todoList.addTodo(addTodoTextInput.value);
//Clear the input
addTodoText.value = "";
view.displayTodos();
},
//Change todo
changeTodo: function(){
var changeTodoText = document.getElementById("changeTodoText");
var changeTodoPosition = document.getElementById("changeTodoPosition");
//Get the CHANGE TODO method in the object TODOLIST and set these parameters
todoList.changeTodo(changeTodoPosition.valueAsNumber, changeTodoText.value);
//Clear the inputs
changeTodoText.value = "";
changeTodoPosition.value = "";
//Call upon VIEW object and trigger displayTodos() method/function;
view.displayTodos();
},
deleteTodo: function(position){
todoList.deleteTodo(position);
view.displayTodos();
},
deleteAll:function(position){
todoList.todos.splice(position);
view.displayTodos();
},
toggleCompleted: function(){
var toggleCompletedInput = document.getElementById("toggleBtn");
todoList.toggleCompleted(toggleCompletedInput.valueAsNumber);
toggleCompletedInput.value = "";
view.displayTodos();
},
toggleAll: function(){
todoList.toggleAll();
view.displayTodos();
}
};
//Object that is used only to DISPLAY the items:
var view = {
displayTodos: function(){
var todosUl = document.querySelector("ul");
todosUl.innerHTML = '';
for (var i = 0; i < todoList.todos.length; i++){
var todoLi = document.createElement("li");
var todo = todoList.todos[i];
var todoTextForCompleted = "";
if (todo.completed === true){
todoTextForCompleted = todo.todoText;
todoLi.classList.toggle("checked");
} else {
todoTextForCompleted = todo.todoText;
todoLi.classList.toggle("notCompleted");
}
todoLi.id = i;
todoLi.textContent = todoTextForCompleted;
todoLi.appendChild(this.createDeleteButton());
todoLi.appendChild(this.createToggleButton());
todosUl.appendChild(todoLi);
}
},
createDeleteButton: function(){
var deleteButton = document.createElement("button");
deleteButton.textContent = "DELETE";
deleteButton.className = "deleteBtn";
return deleteButton;
},
createToggleButton: function(){
var toggleButton = document.createElement("button");
toggleButton.textContent = "Completed";
toggleButton.id= "toggleBtn";
return toggleButton;
},
//
setUpEventListeners: function(){
var todosUl = document.querySelector("ul");
todosUl.addEventListener("click", function(event){
var elementClicked = event.target;
if(elementClicked.className === "deleteBtn"){
handlers.deleteTodo(parseInt(elementClicked.parentNode.id));
}
if (elementClicked.id === "toggleBtn"){
todoList.toggleCompleted(parseInt(elementClicked.parentNode.id));
var toggleCompletedInput = document.getElementById("toggleBtn");
toggleCompletedInput.value = "";
view.displayTodos();
view.removeTodoButton();
}
});
}
}
view.setUpEventListeners();
The code was a bit messy... the main problem I saw is that you were using multiple elements with same id (toggleBtn). I changed it to use a className. Here you have a working version following the design pattern (view-model-handlers).
The changes are:
toggleCompleted: function(position) {
var toggleCompletedInput = document.querySelector("#" + position + " toggleBtn");
var todoLi = document.createElement("li");
var todo = todoList.todos[i];
todoLi.id = i;
todoLi.textContent = todo.todoText;
if (todo.completed === true) {
todoLi.classList.toggle("checked");
} else {
todoLi.classList.toggle("notCompleted");
todoLi.appendChild(this.createToggleButton());
}
todoLi.appendChild(this.createDeleteButton());
todosUl.appendChild(todoLi);
toggleButton.className = "toggleBtn";
if (elementClicked.className === "toggleBtn") {
todoList.toggleCompleted(parseInt(elementClicked.parentNode.id));
view.displayTodos();
}
And in CSS:
.toggleBtn {
background-color: #eee;
color: #e84118;
cursor: pointer;
position: absolute;
right: 70px;
bottom: 3px;
animation: delete 0.5s ease-out 1 forwards;
}
.toggleBtn:hover {
background-color: #4cd137;
color: #eee;
}
.toggleBtn.removed {
display: none;
}
//The object that holds the todo list:
var todoList = {
todos: [],
//Method for ADDING a TODO items
addTodo: function(todoText) {
this.todos.push({
todoText: todoText,
completed: false,
});
},
//Method for changing the made TODO items
changeTodo: function(position, newValue) {
this.todos[position].todoText = newValue;
},
//Method for deleting TODO items:
deleteTodo: function(position) {
this.todos.splice(position, 1);
},
//Method for toggling a todo item as COMPLETED:
toggleCompleted: function(position) {
var todo = this.todos[position];
todo.completed = !todo.completed;
},
//Method for toggling ALL todo items:
toggleAll: function() {
var totalTodos = this.todos.length;
//Counting the ones that are completed
var completedTodos = 0;
//Getting the number of the completed todos:
for (var i = 0; i < totalTodos; i++) {
if (this.todos[i].completed === true) {
//For every todo item that is completed, increase completedTodos by 1;
completedTodos++;
}
}
//Case 1: If everything is true, the turn it into FALSE;
if (completedTodos === totalTodos) {
for (var i = 0; i < totalTodos; i++) {
this.todos[i].completed = false
}
//Case 2: Otherwise, make everything TRUE;
} else {
for (var i = 0; i < totalTodos; i++) {
this.todos[i].completed = true;
};
};
}
}
//Object for the BUTTON HANDLERS:
var handlers = {
addTodo: function() {
var addTodoText = document.getElementById("addTodoTextInput");
todoList.addTodo(addTodoTextInput.value);
//Clear the input
addTodoText.value = "";
view.displayTodos();
},
//Change todo
changeTodo: function() {
var changeTodoText = document.getElementById("changeTodoText");
var changeTodoPosition = document.getElementById("changeTodoPosition");
//Get the CHANGE TODO method in the object TODOLIST and set these parameters
todoList.changeTodo(changeTodoPosition.valueAsNumber, changeTodoText.value);
//Clear the inputs
changeTodoText.value = "";
changeTodoPosition.value = "";
//Call upon VIEW object and trigger displayTodos() method/function;
view.displayTodos();
},
deleteTodo: function(position) {
todoList.deleteTodo(position);
view.displayTodos();
},
deleteAll: function(position) {
todoList.todos.splice(position);
view.displayTodos();
},
toggleCompleted: function(position) {
var toggleCompletedInput = document.querySelector("#" + position + " toggleBtn");
todoList.toggleCompleted(toggleCompletedInput.valueAsNumber);
toggleCompletedInput.value = "";
view.displayTodos();
},
toggleAll: function() {
todoList.toggleAll();
view.displayTodos();
}
};
//Object that is used only to DISPLAY the items:
var view = {
displayTodos: function() {
var todosUl = document.querySelector("ul");
todosUl.innerHTML = '';
for (var i = 0; i < todoList.todos.length; i++) {
var todoLi = document.createElement("li");
var todo = todoList.todos[i];
todoLi.id = i;
todoLi.textContent = todo.todoText;
if (todo.completed === true) {
todoLi.classList.toggle("checked");
} else {
todoLi.classList.toggle("notCompleted");
todoLi.appendChild(this.createToggleButton());
}
todoLi.appendChild(this.createDeleteButton());
todosUl.appendChild(todoLi);
}
},
createDeleteButton: function() {
var deleteButton = document.createElement("button");
deleteButton.textContent = "DELETE";
deleteButton.className = "deleteBtn";
return deleteButton;
},
createToggleButton: function() {
var toggleButton = document.createElement("button");
toggleButton.textContent = "Completed";
toggleButton.className = "toggleBtn";
return toggleButton;
},
//
setUpEventListeners: function() {
var todosUl = document.querySelector("ul");
todosUl.addEventListener("click", function(event) {
var elementClicked = event.target;
if (elementClicked.className === "deleteBtn") {
handlers.deleteTodo(parseInt(elementClicked.parentNode.id));
}
if (elementClicked.className === "toggleBtn") {
todoList.toggleCompleted(parseInt(elementClicked.parentNode.id));
view.displayTodos();
}
});
}
}
view.setUpEventListeners();
* {
margin: 0;
padding: 0;
}
body {
background-color: #dcdde1;
font-family: 'Poppins', sans-serif;
}
li {
color: #eee;
margin: 5px 0;
list-style-type: none;
padding: 10px;
background-color: grey;
display: flex;
justify-content: flex-start;
align-items: center;
user-select: none;
width: 100%;
animation: listitem 1s 1 forwards;
position: relative;
border-radius: 5px;
}
li.deleted {
animation: listItem 1s 1;
}
#keyframes listItem {
from {
opacity: 0
}
to {
opacity: 1
}
;
}
li.checked {
background-color: #4cd137;
color: #eee;
}
li.checked:before {
color: #eee;
margin: 0 10px;
content: "\2714";
animation: checkmark 1s 1 forwards;
}
#keyframes checkmark {
0% {
transform: scale(0);
}
60% {
transform: scale(1.3);
}
100% {
transform: scale(1);
}
}
li.notCompleted {
background-color: #e84118;
color: #eee;
}
li.notCompleted:before {
content: "\2716";
animation: check 1s 1 forwards;
margin: 0 10px;
}
#keyframes check {
0% {
transform: scale(0);
}
60% {
transform: scale(1.3);
}
100% {
transform: scale(1);
}
}
ul li .deleteBtn {
background-color: #eee;
color: #e84118;
cursor: pointer;
position: absolute;
right: 10px;
bottom: 3px;
animation: delete 0.5s ease-out 1 forwards;
}
.deleteBtn:hover {
background-color: #353b48;
color: #eee;
}
.toggleBtn {
background-color: #eee;
color: #e84118;
cursor: pointer;
position: absolute;
right: 70px;
bottom: 3px;
animation: delete 0.5s ease-out 1 forwards;
}
.toggleBtn:hover {
background-color: #4cd137;
color: #eee;
}
.toggleBtn.removed {
display: none;
}
#keyframes delete {
0% {
transform: scale(0);
}
50% {
transform: scale(1.05);
}
80% {
transform: scale(0.95);
}
100% {
transform: scale(1);
}
}
.wrapper {
max-width: 1200px;
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
padding: 10px;
}
h1 {
color: #e84118;
font-size: 35px;
font-weight: 700;
text-transform: uppercase;
}
h1 span {
color: #0097e6;
font-size: 65px;
font-weight: 800;
opacity: 0;
letter-spacing: -50px;
animation: headerSpan 2s 0.5s 1 forwards;
}
#keyframes headerSpan {
0% {
opacity: 0;
letter-spacing: -50px;
transform: scale(0);
}
50% {
letter-spacing: 10px;
}
100% {
opacity: 1;
transform: scale(1);
letter-spacing: 0px;
}
}
input {
padding: 5px;
border: none;
background-color: #f5f6fa;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
border-radius: 3px;
color: #e84118;
font-family: 'Poppins';
width: 100%;
margin: 2px 0;
}
input:focus {
outline: none !important;
}
input::placeholder {
color: #e84118;
font-family: "Poppins";
font-style: italic;
font-size: 12px;
padding-left: 5px;
}
button {
margin: 5px 0;
padding: 3px;
border: none;
border-radius: 3px;
font-family: 'Poppins';
text-transform: uppercase;
color: #eee;
background-color: #00a8ff;
font-weight: bold;
font-size: 14px;
transition: 0.2s ease-out;
}
button:focus {
outline: none!important;
}
button:hover {
background-color: #e84118;
color: #eee;
}
.container_todo {
border-radius: 5px;
padding: 35px;
display: flex;
flex-direction: column;
background-color: #f4f4f4;
box-shadow: 0 2px 25px rgba(0, 0, 0, 0.25);
animation: container 1s 1 forwards;
}
.toggleAllButtons {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.all.active {
background-color: red;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>The Todo List</title>
<link rel="stylesheet" type="text/css" href="styles.css">
<link href="https://fonts.googleapis.com/css?family=Gaegu|Indie+Flower|Pacifico|Raleway" rel="stylesheet">
</head>
<body>
<div class="wrapper">
<!-- Title -->
<h1>The <span>Todo</span> List !</h1>
<!-- TODO LIST container -->
<div class="container_todo">
<!-- BUTTONS -->
<!-- Add Todo item -->
<div class="add">
<button onclick="handlers.addTodo()">Add todo</button>
<input type="text" id="addTodoTextInput" placeholder="Add a Todo item">
</div>
<!-- Change Todo Item-->
<div class="change">
<button onclick="handlers.changeTodo()">Change Todo</button>
<input type="text" id="changeTodoText" placeholder="Change a Todo item">
<input type="number" id="changeTodoPosition" placeholder="Choose which Item to change">
</div>
<!-- Toggle completed Todo item -->
<div class="toggleAllButtons">
<!-- Toggle All items button -->
<div class="all">
<button onclick="handlers.toggleAll()">Toggle All</button>
<button onclick="handlers.deleteAll()">Delete All</button>
</div>
</div>
<ul></ul>
</div>
</div>
<!-- /////////////////////////////////////// -->
<!-- JS link -->
<script src="script.js"></script>
</body>
</html>
Related
I'm working on a javascript to-do list where you can view all the elements on the list or you can view just the active items or the completed items.
Each of the views has its own array which I sorted out using the index of each element
but when I reorder the list on one of the views, the change is not implemented in the other views.
How do I rectify this?
const dragArea1 = document.querySelector('#task1');
const dragArea2 = document.querySelector('#task2');
const dragArea3 = document.querySelector('#task3');
const addnew = document.querySelector('[name="addnew"]')
const add = document.querySelector('[name="new"]')
const countIt = document.querySelector('#count')
var all = [];
var active = [];
var complete = [];
var lists = document.querySelectorAll('ul');
var views = document.querySelectorAll('.action .views a');
var mobileViews = document.querySelectorAll('#views a');
var list = document.querySelector('.list');
countIt.innerHTML = active.length;
addnew.addEventListener('click', () => {
var newItem
if (addnew.checked == true) {
newItem = {
val: add.value,
checked: false
}
all.push(newItem);
active.push(newItem);
window.setTimeout(() => {
addnew.checked = false;
add.value = '';
}, 300);
displayAll();
count();
}
})
list.addEventListener('click', (ev) => {
if (ev.target.tagName === 'LABEL' || ev.target.tagName === 'P' || ev.target.tagName === 'LI') {
ev.target.classList.toggle('checked');
sortAllList();
if (lists[1].style.display == 'block') {
activeToComplete();
}
if (lists[2].style.display == 'block') {
completeToActive();
}
sortActive();
sortComplete();
}
if (all.length == 0) {
var htmlCode = `<em style="text-align: center; width: 100%; padding: 20px;">add a todo item</em>`;
lists[0].innerHTML = htmlCode;
}
if (active.length == 0) {
var htmlCode = `<em style="text-align: center; width: 100%; padding: 20px;">add a todo item</em>`;
lists[1].innerHTML = htmlCode;
}
if (complete.length == 0) {
var htmlCode = `<em style="text-align: center; width: 100%; padding: 20px;">complete a todo item</em>`;
lists[2].innerHTML = htmlCode;
}
// console.log(ev.target.tagName);
})
function count() {
// to keep count of active items
countIt.innerHTML = active.length;
}
views[0].classList.add('view')
mobileViews[0].classList.add('view')
function displayAll() {
sortActive();
sortComplete();
var htmlCode = "";
if (all.length !== 0) {
for (let i = 0; i < all.length; i++) {
htmlCode += `
<li draggable="true">
<div class="check">
<input type="checkbox" name="listItem" id="item${i}">
<label for="item${i}"></label>
</div>
<p class="itemdesc">${all[i].val}</p>
<span onclick="del(${i})">╳</span>
</li>
`
}
lists[0].innerHTML = htmlCode;
}
lists[0].style.display = 'block';
lists[1].style.display = 'none';
lists[2].style.display = 'none';
views[0].classList.add('view')
views[1].classList.remove('view')
views[2].classList.remove('view')
mobileViews[0].classList.add('view')
mobileViews[1].classList.remove('view')
mobileViews[2].classList.remove('view')
count()
keepChecked();
}
function sortActive() {
// to add active items to the active array
var fit
fit = all.filter(el => el.checked == false)
active = fit
count();
}
function sortComplete() {
//to add completed items to the complete array
var com
com = all.filter(el => el.checked == true)
complete = com
// console.log('complete', complete);
}
function sortAllList() {
// to sort the items into active and completed
const items = document.querySelectorAll('#task1 li');
for (let i = 0; i < all.length; i++) {
if (items[i].classList.contains('checked') == true) {
all[i].checked = true
} else {
all[i].checked = false
}
}
}
function activeToComplete() {
let newA
const items = document.querySelectorAll('#task2 li')
for (let i = 0; i < active.length; i++) {
if (items[i].classList.contains('checked') == true) {
active[i].checked = true;
// active.splice(i,1);
// console.log(active.splice());
} else {
active[i].checked = false
}
}
newA = active.filter(el => el.checked !== true)
console.log(newA);
active = newA;
}
function keepChecked() {
// to keep the completed items checked afetr changing views
const allItems = document.querySelectorAll('#task1 li');
for (let i = 0; i < all.length; i++) {
if (all[i].checked == true) {
allItems[i].classList.add('checked')
}
}
}
function completeToActive() {
const items = document.querySelectorAll('#task3 li')
for (let i = 0; i < complete.length; i++) {
if (items[i].classList.contains('checked') == true) {
complete[i].checked = true;
} else {
complete[i].checked = false
complete.splice(i, 1);
console.log(complete.splice());
}
}
}
function displayActive() {
sortAllList();
sortActive();
var htmlCode = "";
if (active.length !== 0) {
for (let i = 0; i < active.length; i++) {
htmlCode += `
<li draggable="true">
<div class="check">
<input type="checkbox" name="listItem" id="item${i}">
<label for="item${i}"></label>
</div>
<p class="itemdesc">${active[i].val}</p>
<span onclick="del(${i})">╳</span>
</li>
`
}
lists[1].innerHTML = htmlCode;
}
lists[1].style.display = 'block';
lists[0].style.display = 'none';
lists[2].style.display = 'none';
views[1].classList.add('view')
views[0].classList.remove('view')
views[2].classList.remove('view')
mobileViews[1].classList.add('view')
mobileViews[0].classList.remove('view')
mobileViews[2].classList.remove('view')
count()
}
function displayCompleted() {
let unique = [...new Set(complete)]
// console.log(unique[0].val);
var htmlCode = "";
if (unique.length !== 0) {
for (let i = 0; i < unique.length; i++) {
htmlCode += `
<li draggable="true" class="checked">
<div class="check">
<input type="checkbox" name="listItem" id="item${i}">
<label for="item${i}"></label>
</div>
<p class="itemdesc">${unique[i].val}</p>
<span onclick="del(${i})">╳</span>
</li>
`
}
lists[2].innerHTML = htmlCode;
}
lists[2].style.display = 'block';
lists[1].style.display = 'none';
lists[0].style.display = 'none';
views[2].classList.add('view')
views[0].classList.remove('view')
views[1].classList.remove('view')
mobileViews[2].classList.add('view')
mobileViews[1].classList.remove('view')
mobileViews[0].classList.remove('view')
count()
}
function clearComplete() {
var htmlCode = `<em style="text-align: center; width: 100%; padding: 20px;">complete a todo item</em>`;
complete = [];
lists[2].innerHTML = htmlCode;
}
function del(theIndex) {
let i = theIndex;
if (lists[0].style.display == 'block') {
all.splice(i, 1);
displayAll();
}
if (lists[1].style.display == 'block') {
active.splice(i, 1);
let removeFromAll = all.find(el => {
el == active.splice()
})
all.splice(removeFromAll, 1);
displayActive();
}
if (lists[2].style.display == 'block') {
complete.splice(i, 1);
let removeFromAll = all.find(el => {
el == complete.splice()
})
all.splice(removeFromAll, 1);
displayCompleted();
}
sortActive();
sortComplete();
}
new Sortable(dragArea1, {
animation: 350
})
new Sortable(dragArea2, {
animation: 350
})
new Sortable(dragArea3, {
animation: 350
})
:root {
--blue: hsl(220, 98%, 61%);
/* vd -> Very Drak */
--vdblue: hsl(235, 21%, 11%);
--vdDesaturatedblue: hsl(235, 24%, 19%);
--lightgrayblue: hsl(234, 39%, 85%);
--lightgrayblueh: hsl(236, 33%, 92%);
--darkgrayblue: hsl(234, 11%, 52%);
--vdGrayishblueh: hsl(233, 14%, 35%);
--vdGrayishblue: hsl(237, 14%, 26%);
--checkbg: linear-gradient(rgba(87, 221, 255, .7), rgba(192, 88, 243, .7));
--font: 'Josefin Sans', sans-serif;
font-size: 18px;
}
* {
padding: 0;
margin: 0;
font-family: var(--font);
/* font-weight: 700; */
}
*,
*::after,
*::before {
box-sizing: border-box;
}
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
textarea:-webkit-autofill,
textarea:-webkit-autofill:hover,
textarea:-webkit-autofill:focus,
select:-webkit-autofill,
select:-webkit-autofill:hover,
select:-webkit-autofill:focus {
border: none;
-webkit-text-fill-color: white;
background-color: transparent !important;
-webkit-box-shadow: 0 0 0px 1000px #00000000 inset;
transition: background-color 5000s ease-in-out 0s;
}
input:focus, input:active, input:visited, textarea:focus, textarea:active, textarea:visited{
background-color: transparent;
border: none;
outline: none;
}
a, em, span{
display: inline-block;
cursor: pointer;
}
a{
text-decoration: none;
display: inline-block;
}
header, main, footer{
width: 100%;
max-width: 30rem;
padding: 10px;
}
main {
display: flex;
flex-direction: column;
gap: 30px;
align-items: center;
}
main #new,
li {
display: flex;
align-items: center;
gap: 20px;
padding: 1rem;
width: 100%;
}
main section,
main #views {
width: 100%;
}
main section,
main #new,
main #views {
border-radius: 5px;
}
main .list {
min-height: 2.5rem;
max-height: 20rem;
/* height: 10rem; */
position: relative;
overflow-y: auto;
}
main .list ul {
/* position: absolute; */
/* top: 20px; */
width: 100%;
display: none;
}
main .list ul:nth-child(1) {
display: block;
}
main #new input[name="new"] {
padding: 10px;
height: inherit;
}
input {
background-color: transparent;
width: calc(100% - 70px);
border: none;
font-size: 1rem;
}
li {
justify-content: flex-start;
}
li .check {
position: relative;
}
main #new .check input,
li .check input {
display: none;
}
main #new .check label,
li .check label {
width: 30px;
height: 30px;
border-radius: 30px;
display: inline-block;
}
main #new .check input:checked~label,
li.checked .check label {
background-image: var(--checkbg), url(images/icon-check.svg);
background-position: center center;
background-repeat: no-repeat;
}
li p {
width: 85%;
}
li.checked label {
background-color: #66666696;
}
li.checked p {
text-decoration: line-through;
}
li span {
/* justify-self: flex-end; */
display: none;
}
li:hover span {
display: flex;
}
main .action {
display: flex;
justify-content: space-between;
/* gap: 2rem; */
padding: 1.1rem;
font-size: .8rem;
}
.views a,
#views a {
font-weight: 700;
}
.action a.view {
color: var(--blue);
}
main #views {
padding: .8rem;
text-align: center;
font-size: .8rem;
display: none;
}
#views a.view {
color: var(--blue);
}
main #views+p {
font-size: .7rem;
}
li,
em {
border-bottom: 1px solid var(--darkgrayblue);
}
li,
li p,
main .action a:hover {
color: var(--lightgrayblue);
}
a,
em,
li.checked p,
p,
span,
input,
li span {
color: var(--darkgrayblue);
}
header img {
content: url("images/icon-sun.svg");
}
main #new {
background-color: var(--vdDesaturatedblue);
}
main #new .check label,
li .check label {
border: 1px solid var(--vdGrayishblue);
}
main #new .check label:hover,
li .check label:hover {
border: 1px solid var(--vdGrayishblue);
}
main section,
main #views {
background-color: var(--vdDesaturatedblue);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.15.0/Sortable.min.js"></script>
<main role="main">
<div id="new">
<div class="check">
<input type="checkbox" name="addnew" id="addnew">
<label for="addnew"></label>
</div>
<input type="text" name="new" placeholder="Create a new todo...">
</div>
<section>
<div class="list">
<ul id="task1">
<em style="text-align: center; width: 100%; padding: 20px;">add a todo item</em>
</ul>
<ul id="task2">
<em style="text-align: center; width: 100%; padding: 20px;">add a todo item</em>
</ul>
<ul id="task3">
<em draggable="true" style="text-align: center; width: 100%; padding: 20px;">complete a todo item</em>
</ul>
</div>
<div class="action">
<p>
<span id="count"></span> items left
</p>
<div class="views">
All
Active
Completed
</div>
Clear Completed
</div>
</section>
<div id="views">
All
Active
Completed
</div>
<p>Drag and drop to reorder list</p>
</main>
Clicking on the Home button at the end of this project brings it to the beginning, but no function is reset. Level buttons are not also being enabled anew. If I enable those level buttons by writing some extra code for enabling, then the number of buttons given for each level will be doubled after selecting the level. In other words, for the first time due to selecting the basic level, there were 4 options, But when I click on the last home button and then select the medium level to play the game from the beginning, it becomes 16 options instead of 8.
//VARIABLE DECLARATION PART
let frontpage = document.querySelector(".front-page");
let playbutton = document.querySelector(".play");
let levelpage = document.querySelector(".levelpg");
let startbtn = document.querySelector(".startbtn");
let maingame = document.querySelector(".maingame");
let easybtn = document.querySelector(".easy");
let mediumbtn = document.querySelector(".medium");
let hardbtn = document.querySelector(".hard");
let nextbtn = document.querySelector(".nextbtn");
let pagecount = document.querySelector('.gamepagecount');
let getnumberdiv = document.querySelector('.numberbtn').children;
let resultpg = document.querySelector('.resultpage');
let backhome = document.querySelector('.backhome');
let finalscore = document.querySelector('.score');
let resulttext = resultpg.children[1];
let changeimg = document.querySelector('.resultpage img');
// PLAYBUTTON CLICK
playbutton.addEventListener("click", () => {
frontpage.classList.add("hidden");
levelpage.classList.remove("hidden");
levelpage.classList.add("visibility");
});
//GAME START FUNCTION
function startGame(level) {
if (level == "easy") {
mediumbtn.disabled = true;
hardbtn.disabled = true;
easybtn.disabled = true;
easybtn.classList.add('levelcolor');
startbtn.addEventListener("click", () => {
pagecount.innerHTML = `1 of 10`;
nextbtn.disabled = true
levelChange(4);
gameInterfaceChange()
mainGame(10);
//NEXTBUTTON FUNCTION
nextbtn.addEventListener('click', () => {
enableBtn(4)
pageCount(10);
mainGame(10);
})
});
}
else if (level == "medium") {
mediumbtn.disabled = true;
hardbtn.disabled = true;
easybtn.disabled = true;
mediumbtn.classList.add('levelcolor');
startbtn.addEventListener("click", () => {
pagecount.innerHTML = `1 of 15`;
nextbtn.disabled = true
levelChange(8);
gameInterfaceChange();
maingame.style.top = "20%";
mainGame(20);
//NEXTBUTTON FUNCTION
nextbtn.addEventListener('click', () => {
enableBtn(8)
pageCount(15)
mainGame(20);
})
});
}
else if (level == "hard") {
mediumbtn.disabled = true;
hardbtn.disabled = true;
easybtn.disabled = true;
hardbtn.classList.add('levelcolor');
startbtn.addEventListener("click", () => {
pagecount.innerHTML = `1 of 20`;
nextbtn.disabled = true
levelChange(12);
gameInterfaceChange();
maingame.style.top = "12%";
mainGame(30);
//NEXTBUTTON FUNCTION
nextbtn.addEventListener('click', () => {
enableBtn(12)
pageCount(20)
mainGame(30);
})
});
}
}
//PAGE SLIDING FUNCTION
function gameInterfaceChange() {
levelpage.classList.remove("hidden");
levelpage.classList.add("hidden");
maingame.classList.remove("hidden");
maingame.style.top = "25%";
maingame.classList.add("visibility");
}
// FUNCTION OF RANDOM INPUTING NUMBER IN DIV
function mainGame(maxnum) {
let numboxlen = getnumberdiv.length;
let wrongnum = Math.floor(Math.random() * maxnum) + 1;
let getnumber = [];
//DUPLICATE RANDOM NUMBER CHECKING
for (let i = 0; i < numboxlen; i++) {
let check = getnumber.includes(wrongnum);
if (check === false) {
getnumber.push(wrongnum);
}
else {
while (check === true) {
wrongnum = Math.floor(Math.random() * maxnum) + 1;
check = getnumber.includes(wrongnum);
if (check === false) {
getnumber.push(wrongnum);
}
}
}
}
// NUMBER PUTTING IN InnerHtml
for (var j = 0; j < numboxlen; j++) {
if (getnumber[j] < 10) {
getnumberdiv[j].innerHTML = '0' + getnumber[j];
}
else {
getnumberdiv[j].innerHTML = getnumber[j];
}
}
}
// BUTTON ADDING ACCORDING TO THE LEVEL
function levelChange(divnum) {
for (let index = 0; index < divnum; index++) {
let newBtn = document.createElement('button');
let newbtnNode = document.createTextNode('');
newBtn.appendChild(newbtnNode);
let gamebtn = document.getElementById('numbrbtn');
gamebtn.appendChild(newBtn);
newBtn.setAttribute("onclick", `numberClick(${index},${divnum})`);
}
}
//RIGHT - WRONG CHECKING FUNTION
var right = 0;
var wrong = 0;
function numberClick(index, divnum) {
let rightnumberindex = Math.floor(Math.random() * divnum);
if (index == rightnumberindex) {
nextbtn.disabled = false
right++;
//RIGHT AND WRONG BACKGROUND ADDING AND BUTTON DISABLE
getnumberdiv[index].classList.add("rightans");
for (let i = 0; i < divnum; i++) {
getnumberdiv[i].disabled = true;
}
}
else {
nextbtn.disabled = false
wrong++;
//RIGHT AND WRONG BACKGROUND ADDING AND BUTTON DISABLE
getnumberdiv[rightnumberindex].classList.add("rightans");
getnumberdiv[index].classList.add("wrongans");
for (let i = 0; i < divnum; i++) {
getnumberdiv[i].disabled = true;
}
}
}
// BUTTON ENABLE ON NEXT BUTTION CLICK
function enableBtn(divnum) {
for (let i = 0; i < divnum; i++) {
nextbtn.disabled = true
getnumberdiv[i].disabled = false;
getnumberdiv[i].classList.remove("wrongans");
getnumberdiv[i].classList.remove("rightans");
}
}
//PAGE COUNTING ACCORDING TO THE LEVEL
let currentpg = 1;
function pageCount(levelPg) {
currentpg++;
if (currentpg <= levelPg) {
if (currentpg == levelPg) {
nextbtn.innerHTML = 'Result'
pagecount.innerHTML = `${currentpg} of ${levelPg}`;
}
else {
pagecount.innerHTML = `${currentpg} of ${levelPg}`;
}
}
else {
result();
}
}
//FINAL RESULT FUNTION
function result() {
maingame.classList.remove("visibility");
maingame.classList.add("hidden");
resultpg.classList.remove('hidden')
resultpg.classList.add('visibility')
if (right > wrong) {
changeimg.setAttribute('src', 'trophy.png')
resulttext.innerHTML = `You Win`;
finalscore.innerHTML = `Your Right Score is : ${right} out of ${right + wrong}`;
}
else if (right == wrong) {
changeimg.setAttribute('src', 'draw.png')
resulttext.innerHTML = `It's Draw`;
finalscore.innerHTML = `Your Right Score is : ${right} out of ${right + wrong}`;
}
else if (right < wrong) {
changeimg.setAttribute('src', 'lose.png')
resulttext.innerHTML = `You Lose`;
finalscore.innerHTML = `Your Right Score is : ${right} out of ${right + wrong}`;
}
}
//BACK TO THE HOME FUNCTION
backhome.addEventListener('click', () => {
frontpage.classList.add("visibility");
frontpage.classList.remove("hidden");
resultpg.classList.add('hidden')
resultpg.classList.remove('visibility')
// enable level button
mediumbtn.disabled = false;
hardbtn.disabled = false;
easybtn.disabled = false;
})
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
body {
margin-top: 50px;
}
.guessing-game {
position: relative;
color: white;
text-align: center;
margin: auto;
width: 350px;
height: 600px;
border-radius: 25px;
padding: 50px 30px;
background: linear-gradient(to right, #bd3f32, #cb356b);
}
.guessing-game .front-page .front-img {
height: 160px;
text-align: center;
}
.guessing-game .front-page img {
max-height: 100%;
}
.guessing-game .front-page .front-text h1 {
margin-top: 50px;
font-size: 1.8em;
}
.guessing-game .front-page .front-text p {
margin-top: 10px;
font-size: 1em;
}
.guessing-game .front-page .front-text button,
.resultpage button ,
.levelpg .easy,
.levelpg .medium,
.levelpg .hard,
.maingame .nextbtn {
margin-top: 30px;
width: 100%;
color: white;
padding: 15px;
outline: 0;
border: 0;
border-radius: 50px;
font-size: 0.9em;
background-color: #d64d5d;
box-shadow: rgba(17, 17, 26, 0.1) 0px 1px 0px,
rgba(17, 17, 26, 0.144) 0px 8px 24px, rgba(17, 17, 26, 0.1) 0px 16px 48px;
}
.guessing-game .front-page .front-text button:hover,
.maingame .nextbtn:hover,
.resultpage button:hover {
transition: 0.5s;
background-color: #c22f40;
}
/* Level page */
.visiblepg {
position: absolute;
top: 12%;
width: 290px;
}
.levelpg h1 {
margin: 45px 0 40px 0;
font-weight: 600;
font-size: 2.4em;
border: 1px solid white;
}
.levelpg .easy,
.levelpg .medium,
.levelpg .hard {
display: block;
margin-top: 15px;
padding: 12px;
background: white;
font-size: 1em;
border-radius: 10px;
font-weight: 400;
color: #c22f40;
}
.startbtn {
background: transparent;
border: 0;
outline: 0;
}
.levelpg i {
color: white;
margin-top: 50px;
font-size: 70px;
border-radius: 50%;
border: 2px solid transparent;
}
.levelpg i:hover {
background-color: white;
border: 2px solid white;
color: #c22f40;
transition: 0.5s;
}
/* GAME PART */
.maingame .gamepagecount {
background-color: #d64d5d;
color: white;
padding: 4px;
border-radius: 6px;
font-size: 0.8em;
font-weight: 600;
}
.maingame .gametext {
margin-top: 15px;
font-size: 1.2em;
}
.maingame .numberbtn {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
}
.maingame .numberbtn button {
margin-top: 40px;
width: 50px;
height: 50px;
background-color: white;
display: flex;
align-content: space-around;
justify-content: center;
align-items: center;
flex-wrap: wrap;
flex: 1 0 21%;
margin-left: 10px;
border: 0;
outline: 0;
border-radius: 10px;
font-size: 1em;
color: #c22f40;
font-weight: 600;
}
.maingame .numberbtn button:nth-child(1),
.maingame .numberbtn button:nth-child(5),
.maingame .numberbtn button:nth-child(9) {
margin-left: 0;
}
.resultpage h1 {
margin: 0px 0 40px 0;
}
.resultpage img {
margin-top: 45px;
width: 50%;
}
/* PRE DEFINE CSS */
.visibility {
visibility: visiible;
opacity: 2s;
transition: 0.5s;
transform: translateX(0px);
}
.hidden {
visibility: hidden;
opacity: 0;
transition: 0.5s;
transform: translateX(-30px);
}
.levelcolor {
transition: 0.5s;
color: white !important;
background-color: #c22f40 !important;
}
.rightans {
background-color: #27ae60 !important;
color: white !important;
transition: 0.5s;
}
.wrongans {
background-color: #fd4631 !important;
color: white !important;
transition: 0.5s;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght#0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
rel="stylesheet" />
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css"
integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous" />
<title>Guessing Game</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="guessing-game">
<div class="front-page">
<div class="front-img">
<img src="./question.png" alt="" />
</div>
<div class="front-text">
<h1>Guessing Game</h1>
<p>
You just need to chose the right number from the option. If your
guess is right more than wrong , you will win otherwise you will
fail! Let's see how good your sixth sense is!!!
</p>
<button class="play">Let's play</button>
</div>
</div>
<div class="levelpg hidden visiblepg">
<h1>Game level</h1>
<button class="easy" onclick="startGame('easy')">Easy</button>
<button class="medium" onclick="startGame('medium')">Medium</button>
<button class="hard" onclick="startGame('hard')">Hard</button>
<button class="startbtn"><i class="fas fa-play-circle"></i></button>
</div>
<div class="maingame visiblepg hidden">
<p class="gamepagecount">1</p>
<p class="gametext">Guess the number you think is right</p>
<div class="numberbtn" id="numbrbtn"></div>
<button class="nextbtn">Next</button>
</div>
<div class="resultpage levelpg hidden visiblepg">
<img src="" alt="" />
<h1></h1>
<div class="score"></div>
<button class="backhome">Home</button>
</div>
</div>
<script src="./main.js"></script>
</body>
</html>
In short, as soon as I click on the home button, I want the game to start anew, all the functions will be reset anew, and the HTML will be reset anew also. I hope my problem is enough clear to understand.
I have solved the problem.
I just add a reload function to solve this problem.
backhome.addEventListener('click', () => {
frontpage.classList.add("visibility");
frontpage.classList.remove("hidden");
resultpg.classList.add('hidden')
resultpg.classList.remove('visibility')
//reload function
window.location.reload();
})
I am unable to add text into slideshow li element. Its not my slideshow i downloaded it from codepen https://codepen.io/team/moderndeveloper/pen/MKgqzq?q=imageslider&limit=team&team_name=moderndeveloper . When i add some text into li element entire slideshow disappear. I tried to add div into li element but nothing help. So, is there any solution for this?
HTML
<div class="ImageSlider">
<div class="ImageSlider-scroller">
<ul class="ImageSlider-items">
<li class="ImageSlider-item" style="background-image: url(https://farm6.staticflickr.com/5076/14164379250_71c3a5b32a_b.jpg);"></li>
<li class="ImageSlider-item" style="background-image: url(https://farm3.staticflickr.com/2937/14371160993_186df4a083_b.jpg);"></li>
<li class="ImageSlider-item" style="background-image: url(https://farm3.staticflickr.com/2914/14185397280_e51c40b1df_b.jpg);"></li>
</ul>
<nav class="ImageSlider-indicators">
</nav>
</div>
</div>
CSS
body {
margin: 0;
}
.ImageSlider {
display: flex;
align-items: stretch;
}
.ImageSlider-button {
width: 40px;
border: none;
background: transparent;
color: #000000;
font-size: 40px;
text-align: center;
outline: none;
opacity: 0.5;
transition: opacity 300ms ease-out;
}
.ImageSlider-button:hover {
opacity: 1;
}
.ImageSlider-scroller {
flex: 1;
overflow: hidden;
position: relative;
}
.ImageSlider-items {
margin: 0;
padding: 0;
list-style: none;
white-space: nowrap;
font-size: 0;
line-height: 0;
transition: transform 0.6s cubic-bezier(1, 0, 0, 1);
}
.ImageSlider-item {
display: inline-block;
padding-bottom: 31.25%;
width: 100%;
height: 100%;
background-size: cover;
background-position: 50% 50%;
}
.ImageSlider-indicators {
list-style: none;
padding: 0;
position: absolute;
bottom: 0;
left: 0;
right: 0;
display: block;
text-align: right;
padding: 40px 140px;
font-size: 0;
}
.ImageSlider-indicator {
display: inline-block;
text-decoration: none;
color: #FFFFFF;
font-weight: bold;
border: 2px solid #FFFFFF;
width: 14px;
height: 14px;
border-radius: 16px;
margin: 0 4px;
background-color: rgba(255, 255, 255, 0);
transition: background-color 0.4s ease-in-out;
}
.ImageSlider-indicator:hover,
.ImageSlider-indicator--is-active {
background-color: #FFFFFF;
}
JS
/* global Modernizr */
if (!Object.assign) {
Object.defineProperty(Object, 'assign', {
enumerable: false,
configurable: true,
writable: true,
value: function(target) {
'use strict';
if (target === undefined || target === null) {
throw new TypeError('Cannot convert first argument to object');
}
var to = Object(target);
for (var i = 1; i < arguments.length; i++) {
var nextSource = arguments[i];
if (nextSource === undefined || nextSource === null) {
continue;
}
nextSource = Object(nextSource);
var keysArray = Object.keys(nextSource);
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
var nextKey = keysArray[nextIndex];
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
if (desc !== undefined && desc.enumerable) {
to[nextKey] = nextSource[nextKey];
}
}
}
return to;
}
});
}
(function(window, document, Modernizr) {
"use strict";
var d = document;
var transform = Modernizr.prefixed('transform');
function ImageSliderIndicators(imageSlider, options) {
this.imageSlider = imageSlider;
this.options = Object.assign({}, ImageSliderIndicators.DEFAULTS, options || {});
this.el = d.querySelector('.' + this.options.indicatorsClass);
this.indicators = [].slice.call(d.querySelectorAll('.' + this.options.indicatorClass));
this.imageSlider.el.addEventListener('positionChanged', this.onPositionChanged.bind(this));
this.el.addEventListener('click', this.onIndicatorClick.bind(this), false);
this.onPositionChanged();
}
ImageSliderIndicators.DEFAULTS = {
indicatorsClass: 'ImageSlider-indicators',
indicatorClass: 'ImageSlider-indicator',
indicatorActiveClass: 'ImageSlider-indicator--is-active'
};
ImageSliderIndicators.prototype.onIndicatorClick = function onIndicatorClick(event) {
var position = this.indicators.indexOf(event.target);
if (position !== -1) {
this.imageSlider.goto(position);
}
};
ImageSliderIndicators.prototype.onPositionChanged = function onPositionChanged() {
var self = this;
this.indicators.forEach(function(element, index) {
var action = index === self.imageSlider.position ? 'add' : 'remove';
element.classList[action](self.options.indicatorActiveClass);
});
};
function ImageSlider(options) {
this.options = Object.assign({}, ImageSlider.DEFAULTS, options || {});
this.position = 0;
this.el = d.querySelector('.' + this.options.imageSliderClass);
this.items = d.querySelector('.' + this.options.itemsClass);
this.itemCount = d.querySelectorAll('.' + this.options.itemClass).length;
this.scroller = d.querySelector('.' + this.options.scrollerClass);
this.previousButton = d.querySelector('.' + this.options.previousButtonClass);
this.nextButton = d.querySelector('.' + this.options.nextButtonClass);
this.indicators = new ImageSliderIndicators(this, this.options.indicators);
window.addEventListener('resize', this.render.bind(this));
this.nextButton && this.nextButton.addEventListener('click', this.next.bind(this));
this.previousButton && this.previousButton.addEventListener('click', this.previous.bind(this));
}
ImageSlider.DEFAULTS = {
imageSliderClass: 'ImageSlider',
itemsClass: 'ImageSlider-items',
itemClass: 'ImageSlider-item',
scrollerClass: 'ImageSlider-scroller',
previousButtonClass: 'js-ImageSlider-button--previous',
nextButtonClass: 'js-ImageSlider-button--next'
};
ImageSlider.prototype.render = function render() {
this.items.style[transform] = 'translate3d(' + (-this.position * this.items.offsetWidth) + 'px,0,0)';
};
ImageSlider.prototype.goto = function goto(position) {
var event = d.createEvent('Event');
event.initEvent('positionChanged', true, true);
this.position = position;
this.el.dispatchEvent(event);
this.render();
};
ImageSlider.prototype.previous = function previous() {
this.goto((this.position + (this.itemCount - 1)) % this.itemCount);
};
ImageSlider.prototype.next = function next() {
this.goto((this.position + 1) % this.itemCount);
};
window.ImageSlider = ImageSlider;
}).call(this, window, window.document, Modernizr);
new ImageSlider();
Durinko.
The slideshow doesn't disappear. The content is pushed down.
The secret is in the CSS code.
Try this:
HTML
<li class="ImageSlider-item" style="background-image: url(https://farm6.staticflickr.com/5076/14164379250_71c3a5b32a_b.jpg);"><p>Some Text</p></li>
CSS:
p {
position: absolute;
font-size: 30px;
}
My problem is that when i open index.html in browser(offline) image slider works great. But when i try to open it on server (it takes actually long time to load images are over 5mb) it wont slide. You can try to click on that white dots in right corner and nothing happen. Thanks for any advice.
Code is
<!-- BEGIN - SlideShow -->
<div class="ImageSlider">
<div class="ImageSlider-scroller">
<ul class="ImageSlider-items">
<li class="ImageSlider-item" style="background-image: url(http://vitas.sk/OnlineTv/images/1.jpg);"></li>
<li class="ImageSlider-item" style="background-image: url(http://vitas.sk/OnlineTv/images/2.jpg);"></li>
<li class="ImageSlider-item" style="background-image: url(http://vitas.sk/OnlineTv/images/3.jpg);"></li>
</ul>
<nav class="ImageSlider-indicators">
</nav>
</div>
</div>
<!-- END - SlideShow -->
/* Image Slider */
.ImageSlider {
display: flex;
align-items: stretch;
height: 50%;
}
.ImageSlider-button {
width: 40px;
border: none;
background: transparent;
color: #000000;
font-size: 40px;
text-align: center;
outline: none;
opacity: 0.5;
transition: opacity 300ms ease-out;
}
.ImageSlider-button:hover {
opacity: 1;
}
.ImageSlider-scroller {
flex: 1;
overflow: hidden;
position: relative;
}
.ImageSlider-items {
margin: 0;
padding: 0;
list-style: none;
white-space: nowrap;
font-size: 0;
line-height: 0;
transition: transform 0.6s cubic-bezier(1, 0, 0, 1);
}
.ImageSlider-item {
display: inline-block;
padding-bottom: 31.25%;
width: 100%;
height: 100%;
background-size: cover;
background-position: 50% 50%;
}
.ImageSlider-indicators {
list-style: none;
padding: 0;
position: absolute;
bottom: 0;
left: 0;
right: 0;
display: block;
text-align: right;
padding: 40px 140px;
font-size: 0;
}
.ImageSlider-indicator {
display: inline-block;
text-decoration: none;
color: #FFFFFF;
font-weight: bold;
border: 2px solid #FFFFFF;
width: 14px;
height: 14px;
border-radius: 16px;
margin: 0 4px;
background-color: rgba(255, 255, 255, 0);
transition: background-color 0.4s ease-in-out;
}
.ImageSlider-indicator:hover,
.ImageSlider-indicator--is-active {
background-color: #FFFFFF;
}
And Js
/* global Modernizr */
if (!Object.assign) {
Object.defineProperty(Object, 'assign', {
enumerable: false,
configurable: true,
writable: true,
value: function(target) {
'use strict';
if (target === undefined || target === null) {
throw new TypeError('Cannot convert first argument to object');
}
var to = Object(target);
for (var i = 1; i < arguments.length; i++) {
var nextSource = arguments[i];
if (nextSource === undefined || nextSource === null) {
continue;
}
nextSource = Object(nextSource);
var keysArray = Object.keys(nextSource);
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
var nextKey = keysArray[nextIndex];
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
if (desc !== undefined && desc.enumerable) {
to[nextKey] = nextSource[nextKey];
}
}
}
return to;
}
});
}
(function(window, document, Modernizr) {
"use strict";
var d = document;
var transform = Modernizr.prefixed('transform');
function ImageSliderIndicators(imageSlider, options) {
this.imageSlider = imageSlider;
this.options = Object.assign({}, ImageSliderIndicators.DEFAULTS, options || {});
this.el = d.querySelector('.' + this.options.indicatorsClass);
this.indicators = [].slice.call(d.querySelectorAll('.' + this.options.indicatorClass));
this.imageSlider.el.addEventListener('positionChanged', this.onPositionChanged.bind(this));
this.el.addEventListener('click', this.onIndicatorClick.bind(this), false);
this.onPositionChanged();
}
ImageSliderIndicators.DEFAULTS = {
indicatorsClass: 'ImageSlider-indicators',
indicatorClass: 'ImageSlider-indicator',
indicatorActiveClass: 'ImageSlider-indicator--is-active'
};
ImageSliderIndicators.prototype.onIndicatorClick = function onIndicatorClick(event) {
var position = this.indicators.indexOf(event.target);
if (position !== -1) {
this.imageSlider.goto(position);
}
};
ImageSliderIndicators.prototype.onPositionChanged = function onPositionChanged() {
var self = this;
this.indicators.forEach(function(element, index) {
var action = index === self.imageSlider.position ? 'add' : 'remove';
element.classList[action](self.options.indicatorActiveClass);
});
};
function ImageSlider(options) {
this.options = Object.assign({}, ImageSlider.DEFAULTS, options || {});
this.position = 0;
this.el = d.querySelector('.' + this.options.imageSliderClass);
this.items = d.querySelector('.' + this.options.itemsClass);
this.itemCount = d.querySelectorAll('.' + this.options.itemClass).length;
this.scroller = d.querySelector('.' + this.options.scrollerClass);
this.previousButton = d.querySelector('.' + this.options.previousButtonClass);
this.nextButton = d.querySelector('.' + this.options.nextButtonClass);
this.indicators = new ImageSliderIndicators(this, this.options.indicators);
window.addEventListener('resize', this.render.bind(this));
this.nextButton && this.nextButton.addEventListener('click', this.next.bind(this));
this.previousButton && this.previousButton.addEventListener('click', this.previous.bind(this));
}
ImageSlider.DEFAULTS = {
imageSliderClass: 'ImageSlider',
itemsClass: 'ImageSlider-items',
itemClass: 'ImageSlider-item',
scrollerClass: 'ImageSlider-scroller',
previousButtonClass: 'js-ImageSlider-button--previous',
nextButtonClass: 'js-ImageSlider-button--next'
};
ImageSlider.prototype.render = function render() {
this.items.style[transform] = 'translate3d(' + (-this.position * this.items.offsetWidth) + 'px,0,0)';
};
ImageSlider.prototype.goto = function goto(position) {
var event = d.createEvent('Event');
event.initEvent('positionChanged', true, true);
this.position = position;
this.el.dispatchEvent(event);
this.render();
};
ImageSlider.prototype.previous = function previous() {
this.goto((this.position + (this.itemCount - 1)) % this.itemCount);
};
ImageSlider.prototype.next = function next() {
this.goto((this.position + 1) % this.itemCount);
};
window.ImageSlider = ImageSlider;
}).call(this, window, window.document, Modernizr);
new ImageSlider();
There is an JavaScript error in your code before the slider initialization.
Uncaught ReferenceError: Modernizr is not defined
You should fix this dependency issue and I guess your slider will work.
(maybe change http to https in Modernizr url)
For me my browser are blocking Modernizr script and a bunch of other thing to be loaded
const todoList = {
todos: [],
addTodo: function(todoText) {
this.todos.push({
todoText: todoText,
completed: false
});
view.displayTodos();
},
changeTodo: function(position, newTodoText) {
this.todos[position].todoText = newTodoText;
view.displayTodos();
},
deleteTodo: function(position) {
this.todos.splice(position, 1);
view.displayTodos();
},
toggleCompleted: function(position) {
let todo = this.todos[position];
todo.completed = !todo.completed;
},
toggleAll: function() {
const allTodos = this.todos.length;
let completedTodos = 0;
for (let i = 0; i < allTodos; i++) {
if (this.todos[i].completed === true) {
completedTodos++;
}
}
if (completedTodos === allTodos) {
for (let i = 0; i < allTodos; i++) {
this.todos[i].completed = false;
}
} else {
for (let i = 0; i < allTodos; i++) {
this.todos[i].completed = true;
}
}
view.displayTodos();
}
};
const handlers = {
toggleAll: function() {
todoList.toggleAll();
},
addTodo: function(e) {
if (e.keyCode === 13) {
e.preventDefault(); // Ensure it is only this code that rusn
let todoTextInput = document.getElementById('todoTextInput');
todoList.addTodo(todoTextInput.value);
todoTextInput.value = '';
}
},
deleteTodo: function(position) {
todoList.deleteTodo(position);
}
};
const view = {
displayTodos: function() {
let todosUl = document.getElementById('todoList');
todosUl.innerHTML = '';
for (let i = 0; i < todoList.todos.length; i++) {
let todoLi = document.createElement('li');
let todoLiText = document.createElement('input');
todoLiText.type = "text";
todoLiText.disabled = true;
todoLiText.id = 'textInput';
let todoTextWithCompletion = todoList.todos[i].todoText;;
let check = document.createElement('input');
check.type = "checkbox";
check.id = "checkbox";
check.className = "checkbox";
check.checked = '';
todoLi.id = i;
todoLiText.value = todoTextWithCompletion;
todoLi.appendChild(check);
todoLi.appendChild(todoLiText);
todoLi.appendChild(this.createDeleteButton());
todoLi.appendChild(this.createEditButton());
todosUl.appendChild(todoLi);
if (document.getElementById('checkbox').checked === true) {
todoList.toggleCompleted(i);
};
if (todoList.todos[i].completed === true) {
todoLiText.style.textDecoration = "line-through";
};
}
},
createDeleteButton: function() {
let deleteButton = document.createElement('a');
deleteButton.href = "#";
deleteButton.textContent = "Delete";
deleteButton.className = 'x';
return deleteButton;
},
createEditButton: function() {
let editButton = document.createElement('a');
editButton.href = "#";
editButton.textContent = "edit";
editButton.className = 'edit';
return editButton;
},
setUpEventListeners: function() {
let todosUl = document.getElementById('todoList');
todosUl.addEventListener('click', (event) => {
let elementClicked = event.target;
if (elementClicked.className === 'x') {
handlers.deleteTodo(parseInt(elementClicked.parentNode.id));
};
});
// Edit List Item
todosUl.addEventListener('click', (event) => {
let elementClicked = event.target;
let position = elementClicked.parentNode.id;
if (elementClicked.className === 'edit') {
let input = document.getElementById('textInput');
input.disabled = false;
input.className += " activeTextInput ";
input.focus();
input.select();
input.addEventListener('keyup', (event) => {
let elementClicked = event.target;
if (event.keyCode === 13) {
let textInput = input.value;
input.disabled = true;
input.classList.remove("activeTextInput");
todoList.changeTodo(position, textInput);
};
});
};
});
// Line through on check
todosUl.addEventListener('click', (event) => {
let elementClicked = event.target;
let position = elementClicked.parentNode.id;
let check = document.getElementById('checkbox');
if (elementClicked.className === 'checkbox') {
todoList.toggleCompleted(position);
check.checked = true;
};
});
//Delete All
let clearAll = document.getElementById('clearAll');
clearAll.addEventListener('click', (event) => {
todoList.todos.splice(0, todoList.todos.length);
view.displayTodos();
});
// TODO Delete Selected
}
};
view.setUpEventListeners();
html,
body {
margin: 0;
height: 100%;
}
body {
background-color: #eeeeee !important;
}
h1 {
color: #282845 !important;
}
p {
opacity: .3;
}
.container {
min-height: 70%;
display: flex;
justify-content: center;
flex-direction: column;
width: 50% !important;
}
#todoTextInput {
background-color: white;
opacity: .7;
box-shadow: 1px 1px 10px rgba(5, 5, 5, 0.2);
height: 50px;
padding: 10px;
border: none;
font-style: italic;
}
ul {
display: flex;
flex-direction: column;
padding: 0;
margin: 0;
}
li {
list-style-type: none !important;
border-bottom: 1px solid rgba(5, 5, 5, 0.1);
padding: 10px;
background-color: white;
box-shadow: 1px 1px 10px rgba(5, 5, 5, 0.2);
min-width: inherit;
}
li a {
float: right;
padding-right: 10px;
opacity: .3 !important;
transition: .2s;
}
li a:hover {
opacity: 1 !important;
}
input {
border: none;
border-bottom: 1px solid rgba(5, 5, 5, 0..01);
background-color: inherit;
}
li input[type="text"] {
padding: none;
border: none;
width: 80%;
margin-left: 10px;
transition: .5s;
}
.activeTextInput {
box-shadow: 1px 1px 10px rgba(5, 5, 5, 0.1);
padding: 10px !important;
}
input[type="text"] {
background-color: inherit;
border: none;
border-bottom: 1px solid rgba(5, 5, 5, 0.01);
padding: 0;
}
input:focus {
outline: none;
}
input:checked+input[type="text"] {
text-decoration: line-through;
opacity: .5;
}
.btn {
background-color: white !important;
border-radius: 0 !important;
padding: 0;
box-shadow: 1px 1px 10px rgba(5, 5, 5, 0.2);
margin-top: -2px !important;
font-style: italic;
opacity: 0.5;
}
#clearAll {
margin-top: -21px !important;
}
.hidden {
display: none !important;
background-color: red !important;
}
<link href="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/css/bootstrap.css" rel="stylesheet" />
<body>
<div class="container">
<h1 class="text-center">List+</h1>
<div class="row list-head">
<div class="col-md-12">
<input type="text" placeholder="Enter a List Item" style="width: 100%" id="todoTextInput" onkeyup="handlers.addTodo(event)">
</div>
</div>
<div class="row list-container">
<div class="col-md-12">
<ul id="todoList">
</ul>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button class="btn" style="width: 100%" id="clearAll">Clear All</button>
<button class="btn" style="width: 100%">Clear Selected</button>
</div>
</div>
<div class="row">
<div class="col-md-12">
<p class="text-center"><i>Created by Connor Beam</i></p>
</div>
</div>
</div>
<script src="js/main.js"></script>
</body>
I'm building a todo list in vanilla JavaScript. I'm trying to get the 'edit' option to function properly. When I click the 'edit' button, the corresponding text input should be enabled, and auto-selected, then the user should be able to press 'enter' to submit changes.
However, no matter which 'edit' button is clicked, he first text input is always selected, while still changing the correct item when submitted.
Here's a working link to the most recent version: http://vanillajstodo.surge.sh/
I believe the problem is that all 'todoLiText' inputs are being created with the same id; however, I'm not sure how to fix that.
Let me know if more info is needed.
Thanks
Take a look at this solution:
https://codepen.io/anon/pen/YQQovp?editors=1010
let input = document.getElementById(position).childNodes[1];
Your mistake is that you should never have multiple elements with the same id on the same page. Instead you should use the same class in that situation.