-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exercises-1 pull req Dan Menahem #6
base: main
Are you sure you want to change the base?
Conversation
… is deleted it alert
</div> | ||
<div id="info"> | ||
<span id="peding-task-text">You have 0 pending tasks</span> | ||
<button class="btn" id="clearAllBtn" disabled>Clear All</button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job on reusing the btn class!
* { | ||
font-family: Alef, Arial, Helvetica, sans-serif; | ||
font-size: 20px; | ||
margin: 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in general, it's usually a bad practice to use the wildcard selector *, as it applies to all elements, rather than inheriting the style from a parent element (it still could be html or body) which are much easier to override when needed.
You can read more on CSS precedence here - https://jenkov.com/tutorials/css/precedence.html
You also have this cool library that normalizes the base/default styles across different browsers - https://necolas.github.io/normalize.css/
.btn[disabled] { | ||
opacity: 0.3; | ||
box-shadow: none; | ||
border: none; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
duplicate? isn't it already in .btn?
|
||
.btn[disabled]:hover { | ||
cursor: not-allowed; | ||
box-shadow: none; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
duplicate? isn't it already in .btn[disabled]? (move below .btn:hover)
box-shadow: none; | ||
} | ||
|
||
.btn { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's a good practice to put all the different variants of a style after the base is defined so the variants will get a priority and could override the base class with ease and without the need for !important
} | ||
|
||
|
||
#taskList li { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using "li" here instead of a class makes it coupled to this specific solution. If you'll need to change li to a different element (ex: div) you'll have to make many changes in the code
overflow: hidden; | ||
} | ||
|
||
#taskList li span { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same goes for the span here better to use a class name. Also for readability, a descriptive classname will tell me on which element this style is targeting
const addBtn = document.querySelector(" #addBtn "); | ||
const clearAllBtn = document.querySelector(" #clearAllBtn "); | ||
const sortAllBtn = document.querySelector(" #sortAllBtn "); | ||
const taskList = document.querySelector(" #taskList "); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
having all the elements outside here requires all the dom elements exist when this file is loaded, which might not be the case in complex web apps that dynamically change the dom depending on the view
const placeHolder = document.querySelector(" .placeHolder ") | ||
const pedingTaskText = document.querySelector(" #peding-task-text ") | ||
|
||
const taskArr = JSON.parse(localStorage.getItem("tasks")) || []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice!
consider moving this to a function that handles the initial loading of the tasks
|
||
|
||
//waiting for user input before enable the add button | ||
taskInput.addEventListener('keyup', () => addBtn.disabled = !taskInput.value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extract the validation into a function as multiple sources need to use it :)
|
||
//sort the tasks list add them to html list element and save them to the LocalStorage | ||
sortAllBtn.addEventListener("click", () => { | ||
taskArr.sort(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the sort method mutates the original array, therefore it's better to copy it beforehand ex: taskArr = [...taskArr.sort()];
As mutating the state directly (and complex data structures in general) is considered a bad practice as other parts of the code might be using it, not expecting it to suddenly change.
Read more on pure functions and the immutability approach in coding https://css-tricks.com/understanding-immutability-in-javascript/
|
||
//Clear the tasks list | ||
clearAllBtn.addEventListener("click", () => { | ||
taskArr.length = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not a common usage, I would change it to taskArr = [];
Also it mutates taskArr directly which is a bad practice due to the comment above
//if there are some task in the localStorage insert them | ||
function init() { | ||
if (taskArr.length != 0) insertAllTasks(); | ||
else placeHolder.classList.remove("hidden"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code duplication, this could have been instead a call to showEmptyState()/ showEmptyStateIfNeeded()/toggleEmptyState() or something similar
} | ||
|
||
//Function to create the li element and its childs and assign a click event to them | ||
function createLi(taskValue) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as the css point, let's decouple this by changing to something more general like createTaskElement/createTaskNode
} | ||
|
||
//if there are some task in the localStorage insert them | ||
function init() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice use of init, I would add the loading of the localStorage and initializing the tasksList here as well
i.classList.add("fa", "fa-trash-o"); | ||
span.appendChild(i); | ||
li.appendChild(span); | ||
span.onclick = (e) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prefer using the addEventListener instead of onclick directly
} | ||
|
||
//update the button and the placeHolder if necessary | ||
function updateForm() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider renaming the function to make it more descriptive or even separate into 2 different functions as you always know what you actually need to do beforehand. 1 for hiding the empty state and other for showing it
|
||
// function to remove task that have been clicked | ||
function removeTask(li, taskValue) { | ||
taskArr.splice(taskArr.indexOf(taskValue), 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As task holds only the text value it is not unique, therefore you might be removing the wrong task from the list. Consider an alternative approach. hint: find a way to uniquely identify tasks
<title>Exercise 1</title> | ||
<meta charset="UTF-8"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice
<i class="fa fa-plus"></i> | ||
<p>Time to add your first task</p> | ||
</div> | ||
<div id="info"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good dom modeling, gj!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see comments
feat: add fourth exercise
No description provided.