I have created a todo-apps with js but I have a problem : when I am clicking on the check button to do someting or on the edit button or the time button all tasks are changed : for example when I click on the check button on « learn js » I want that just this task changed ( underline) but when I do that all my tasks become underline. I know this is a beginner question sorry. This is my HTML code :
<h1>To Do List</h1>
<input type="text" placeholder="Name..." id="Name">
<input type="button" id="addItem" value="Add Item" />
<div class="choices">
<p id="p"></p>
</div>
<button id="btn" type="submit"> Clear Items</button>
This is my JS code :
let clear = document.getElementById("btn");
let add = document.getElementById("addItem");
let choices = [];
let vide = document.getElementById('p');
var choice = document.getElementById("Name").value;
let invalid = document.getElementById("invalid");
function main() {
add.addEventListener('click', function() {
addItems();
})
}
function addItems() {
choice = document.getElementById("Name").value;
vide.innerHTML += choice;
choices.push(choice);
document.getElementById('p').insertAdjacentHTML('beforeend', `<i id="check" class="far fa-check-circle"></i>`);
document.getElementById('p').insertAdjacentHTML( 'beforeend', `<i id="null" class="far fa-times-circle"></i>`);
document.getElementById('p').insertAdjacentHTML( 'beforeend', `<i. id="edit" class="far fa-edit"></i>`);
vide.insertAdjacentHTML('beforeend', `<br/><br/>`);
document.getElementById('p').classList.add('listClass');
document.getElementById('check').onclick = function() {
document.getElementById('p').classList.toggle("done");
document.getElementById('check').classList.toggle('opacity');
};
document.querySelector('#null').onclick = function() {
vide.innerHTML ='';
};
document.getElementById('edit').onclick = function() {
// I have not finished this part
}
}
}
main();
This is a picture of the result :
Depsite the fact that you have many mistakes(especially code redundancy) in your code, the main issue is that your IDs are not unique in the page.
As I said, the code is not that flexible to allow us building on it, so I took sometime to provide you a more modern, readable, performant solution (regarding yours of course !).
The code is commented to allow you understand easily what I'm doing.
// selecting the elements from the DOM
const todoList = document.getElementById("todo-list"),
newTodoForm = document.getElementById("new-todo-form"),
todoInp = document.getElementById("todo"),
clearBtn = document.getElementById("clear"),
choices = [],
/**
* createElement: a function that creates an HTML element with the specified attributes and events
* #param nodeName (string) the HTML element tag name
* #param opts (object) the attributes object which can contain :
* content: (object) an object to specify the element's content and it has two fields :
* html: (boolean) is the content should be inserted as HTML or a simple text. Defaults to false, pass true to treat the content as HTML
* value: (string) the actual content
* classList: (string) specifies a space-separated classes to be assigned to the element
* id: (string) the elemnt's ID
* data: (object) an object for the "data-TOKEN=VAL" attributes where each key (in camelCase) is the "TOKEN" and its value is the "VAL", example: {someDataOne: 'some value one', someDataTwo: 'some value two'} will be transformed into "data-some-data-one="some value one" data-some-data-two="some value two""
* events: (object) the keys are event names and the values are the events callbacks. Example {click: () => alert('clicked !')}
**/
createElement = (nodeName, opts) => {
// create the requested element
const el = document.createElement(nodeName);
// merge the options with the default ones
opts = Object.assign({
content: {
value: "",
html: !1
},
classList: "",
id: "",
data: {},
events: {}
},
opts
);
// apply the classes if the "opts.classList" is not empty
!!opts.classList && (el.classList = opts.classList);
// apply the ID if the "opts.id" is not empty
!!opts.id && (el.id = opts.id);
// apply the content if the "opts.content.value" is not empty and check if we want the content to be treated as HTML
!!opts.content.value &&
(el[opts.content.html === !0 ? "innerHTML" : "textContent"] =
opts.content.value);
// apply the data-* if the "opts.data" is not empty
if (Object.getOwnPropertyNames(opts.data).length) {
for (let p in opts.data)
if (opts.data.hasOwnProperty(p)) el.dataset[p] = opts.data[p];
}
// assign the events if the "opts.events" is not empty
if (Object.getOwnPropertyNames(opts.events).length) {
for (let p in opts.events)
if (opts.events.hasOwnProperty(p))
el.addEventListener(p, opts.events[p]);
}
// return the created element after applying the requested attributes and events
return el;
},
/*
* a function that generates a list-item template (HTML code that contains the todo text, buttons for edit, delete and so on...)
* #param txt (string) the todo text
*/
todoItemTpl = txt => {
// "item" is the list-item wrapper that contains all the buttons and todo text for only one todo item
// as you can see, we're using the "createElement" function so the code doesn't get redundant and also it become more readable and flexible
const item = createElement("div", {
classList: "todo-item row col-12 py-2 px-0 m-0 my-1 align-items-center"
}),
// the "p" element that shows the todo text
txtWrapper = createElement("p", {
content: {
value: txt
},
classList: "todo-text col-auto m-0"
}),
// a wrapper for the options (delete, edit and check) buttons of a todo item
btnsWrapper = createElement("div", {
classList: "todo-btns col-auto"
}),
// an array that holds the 3 option buttons so later we can loop through it and append each button to "btnsWrapper"
// every button here has its click event so the browser won't get confused which todo item should it alter
// !!: the edit functionality is not implemented it simply prints some text to the console when the edit button is clicked
optionBtns = [
createElement("button", {
content: {
value: '<i class="far fa-check-circle"></i>',
html: !0
},
classList: "option-btn check-btn ml-1",
events: {
click: function() {
this.closest('div.todo-item').classList.add('finished');
this.disabled = !0;
}
}
}),
createElement("button", {
content: {
value: '<i class="far fa-edit"></i>',
html: !0
},
classList: "option-btn edit-btn ml-1",
events: {
click: function() {
console.log('Edit functionnality not yet implemented !');
}
}
}),
createElement("button", {
content: {
value: '<i class="fa fa-times"></i>',
html: !0
},
classList: "option-btn del-btn ml-1",
events: {
click: function() {
const todoItem = this.closest('div.todo-item'),
txt = todoItem.querySelector('.todo-text').textContent;
todoItem.remove();
choices.splice(choices.indexOf(txt), 1);
}
}
})
];
// append the option buttons to the buttons wrapper
optionBtns.forEach((b) => btnsWrapper.appendChild(b));
// append the todo text to the todo-item
item.appendChild(txtWrapper);
// append the option buttons wrapper text to the todo-item
item.appendChild(btnsWrapper);
// return the newly created todo-item
return item;
};
// listen for the form submission
newTodoForm.addEventListener("submit", e => {
// store the trimmed input (the todo name) value
const inpVal = todoInp.value.trim();
// prevent form submission to disable page reload
e.preventDefault();
// stop execution if the todo item name is empty
if (!inpVal) return;
// if the todo text is not empty then :
// append the entered value to the "choices" array
choices.push(inpVal);
// append the todo-item to the todo list (that is initially empty) using "todoItemTpl" function and by passing the entered value for the todo name
todoList.appendChild(todoItemTpl(inpVal));
// finnaly, empty up the todo name input field
todoInp.value = "";
});
// listen for the click event of the clear button
// when clicked, remove all the todo-items and empty up the "choices" array
clearBtn.addEventListener('click', () => (todoList.innerHTML = '', choices.length = 0));
// styling for the demo, nothing fancy !
.todo-list * {
transition: all .4s 0s ease;
}
.todo-list {
background-color: #f5f5f5;
}
.todo-list .todo-item {
border-bottom: 1px solid #c5c5c5;
}
.todo-list .todo-item.finished {
background-color: #65d4a8;
}
.todo-list .todo-item.finished .todo-text {
text-decoration: line-through;
}
<!-- importing Bootsrap and Font-Awesome -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/css/all.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet" />
<!-- some transformations to use Bootsrap's classes -->
<div class="todo-form-wrapper">
<form action="#" id="new-todo-form">
<h1>To Do List</h1>
<input type="text" placeholder="Name..." id="todo">
<button type="submit" value="Add Item">Add</button>
</form>
</div>
<!-- the todo list wrapper is initially empty -->
<div id="todo-list" class="todo-list row m-0"></div>
<button id="clear" type="button">Clear Items</button>
Eventhough the code looks good, I don't recommand using it in production as it has some issues, it doesn't support old browsers like IE for example.
I guess you are adding all the contents inside one single - p - tag and when you change the class- i.e: toggling the class of that - p - tag to "done", it is getting applied to all inner texts.
You need separate wrapper for each task assertion to handle this problem.
Related
I want to add html elements to the body of my page as an unordered list. I have used DocumentFragment method to create a fragment of the reply button and comment span. Now I need to add a textbox and a add reply to that ul whenever a user clicks on the reply button and add all the replies as a list next to respective comment. Here is what I've tried:
function comment() {
var my_comment = document.getElementById('comments');
my_comment.innerHTML = "<textarea id='user_comment'> </textarea> <button onclick='addNewItem()'>Post Comment</button>";
}
function addNewItem() {
var thediv = document.getElementById("comments_and_replies");
var listItem = document.createElement("ul");
var replyBox = document.createElement("textbox");
var commentSpan = document.createElement("span");
var user_comment = document.getElementById('user_comment');
var replyButton = document.createElement("button");
listItem.className = "comments-list";
replyButton.innerText = "Reply";
replyButton.className = "reply";
replyButton.addEventListener("click", function() {
var g = document.getElementById('comments_and_replies');
for (var i = 0, len = g.children.length; i < len; i++) {
(function(index) {
g.children[i].onclick = function() {
listItem.insertBefore(replyBox, listItem.children[index]);
}
})(i);
}
})
commentSpan.textContent = user_comment.value;
var documentFragment = document.createDocumentFragment();
documentFragment.appendChild(listItem);
listItem.appendChild(commentSpan);
listItem.appendChild(replyButton);
thediv.appendChild(documentFragment);
}
<section><button onclick="comment()">Leave a comment</button></section>
<div id="comments"></div>
<div id="comments_and_replies"></div>
Event delegation on a single <form> can accommodate an unlimited amount of <button>s even if they are added after the page has loaded.
The example below uses the following:
document.forms
.elements
event.currentTarget
event.target
.matches()
.insertAdjacentHTML()
.previousElementSibling
.parentElement
.remove()
Note: Unless you are submitting data to a server, add type="button" to each <button>
Details are commented in code below
// Refernce <form>
const form = document.forms.commentsReplies;
// Any click on <form> invokes post()
form.onclick = post;
// Pass the event
function post(event) {
/* Reference all <fieldset>
(also <button>, <textarea>, etc) */
const field = event.currentTarget.elements;
// Reference the actual element clicked
const clicked = event.target;
// if element clicked has class postCom
if (clicked.matches('.postCom')) {
/* find <fieldset name="post"> and
insert HTML into it */
field.post.insertAdjacentHTML('beforeEnd', `<fieldset name='commentPost'><textarea></textarea><button class='comTxt' type='button'>Done</button></fieldset>`);
// Otherwise if clicked element has class comTxt
} else if (clicked.matches('.comTxt')) {
/* find the clicked element's element
that is right before it and get it's text */
const text = clicked.previousElementSibling.value;
/* find <fieldset name='comments'> and insert HTML */
field.comments.insertAdjacentHTML('afterBegin', `<fieldset>${text}<button class='postRep' type='button'>Reply</button><ul></ul></fieldset>`);
// Remove <fieldset name='commentPost'>
field.commentPost.remove();
} else if (clicked.matches('.postRep')) {
clicked.insertAdjacentHTML('afterEnd', `<ul><textarea></textarea><button class='repTxt' type='button'>Done</button></ul>`);
} else if (clicked.matches('.repTxt')) {
const text = clicked.previousElementSibling.value;
const list = clicked.parentElement;
list.insertAdjacentHTML('afterBegin', `<li>${text}<button class='postRep' type='button'>Reply</button></li>`);
clicked.previousElementSibling.remove();
clicked.remove();
} else {
return false;
}
}
button {
display: block;
margin-left: 25%;
}
<form id='commentsReplies'>
<fieldset name='post'><button class='postCom' type='button'>Leave a comment</button>
</fieldset>
<fieldset name="comments">
<legend>Comments</legend>
</fieldset>
</form>
I have a low level knowledge of javascript and am trying to create a basic image based quiz that passes data back to a search page for local businesses.
Each image would have it's own "tag" as the image ID that relates to one of the options in the search. Ie. Outdoor, Ballroom, Barn, Garden, etc.
Upon submission, it would send the selected image ID's data to www.sitename/search/?_characteristics=TAG1,TAG2,TAG3
That search page will filter the business listings by the tags. Currently it's search function filters the businesses with the following format: website.com/search/?_characteristics=TAG1%2CTAG2
The HTML would look like this:
<img src="http://website.com/image1" id="TAG1"/>
<br/>
<img src="http://website.com/image2" id="TAG2"/>
<form action="https://website.com/business/?&_characteristics=TAG1, TAG2, TAG3" method="get">
<input type="submit" value="View Selected"/>
What you want is the following
Register a click handler on your images to
Capture ids into a collection (array or Set)
Toggle the "selected" class
Register a submit handler on the form to inject an hidden input element, transforming the tag collection into a CSV and setting it to the input value
const form = document.querySelector("form")
const tags = new Set()
document.querySelectorAll("img[id]").forEach(img => {
img.addEventListener("click", () => {
const selected = img.classList.toggle("selected")
tags[selected ? "add" : "delete"](img.id)
})
})
form.addEventListener("submit", (e) => {
const input = Object.assign(document.createElement("input"), {
name: "_characteristics",
type: "hidden",
value: ([...tags]).join(",")
})
form.append(input)
// this is just for the example, omit the following
e.preventDefault()
console.log(`Submitting to ${form.action}?${new URLSearchParams(new FormData(form))}`)
input.remove()
})
img { border: 2px solid grey; }
img.selected { border-color: red; }
<img src="https://picsum.photos/100" id="TAG1"/>
<br/>
<img src="https://picsum.photos/100" id="TAG2"/>
<form action="https://website.com/business/" method="get">
<input type="submit" value="View Selected"/>
</form>
I'm not sure how you want to get the selected img, but here's a way to do it:
Add the class active to the selected img
When clicking on the button, get the id and push it to the output array
Create the link of the tags (id's)
Read the comments below for the detailed explanation.
// Get the images and the submit button
let images = document.querySelectorAll('img');
let btn = document.getElementById('btn');
// Array to hold the tags
let output = [];
// variable to hold the link
let link = '';
// Add the class active to the selected images
for(let i = 0; i < images.length; i++) {
// For each image onclick:
images[i].addEventListener('click', () => {
// Toggle the `active` class on click
images[i].classList.toggle('active');
});
}
// Button onclick:
btn.addEventListener('click', () => {
for(let i = 0; i < images.length; i++) {
// Get the images with the `active` class and push the id to the output array
images[i].classList.contains('active') ? output.push(images[i].getAttribute('id')) : '';
}
// Remove duplicates if found
let uniq = [...new Set(output)];
// Create the link by adding the tags to the string (output values)
link = `www.sitename/search/?_characteristics=${uniq.join(',')}`;
// Print the link to the console
console.log(link);
});
img.active {
box-shadow: 0 0 1px 1px #121212;
}
5. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="air-conditioned"/>
<br/>
6. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="outdoor"/>
<br/>
7. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="indoor"/>
<br/>
8. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="house"/>
<br/>
<button id="btn">Submit</button>
I have a dynamically generated form with groups of checkboxes representing categories of companies. These eventually get plotted on a dynamic chart (not shown here). Each group of companies has a toggle button to turn all the checkboxes on or off in each category.
I have a jQuery handler for the first toggle button (Tech Giants) using its ID and then checks or unchecks all the boxes in that group accordingly.
My question is this, which refers to the last portion of code in the block below. Instead of manually coding a handler for each toggle button, how can I create one that will apply to all of them on the page? Each button should only check or uncheck all the boxes in its specific category. Note that the first button on the page is separate, and not part of the category selection checkboxes we want to handle.
Here's the code in JSFiddle:
https://jsfiddle.net/gq5tw309/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- This button is different than the other buttons -->
<button class="button-text" id="customize-button">Open User Settings</button>
<!-- Placeholder for dynamic form -->
<div id="company-selection-form"></div>
<script type="text/javascript">
function toMachineString(humanString) {
var machineString = humanString.replace(/\s+/g, '-').toLowerCase();
machineString = machineString.replace('&','');
return machineString;
}
// Setup the form
var categories = new Map([
['Tech Giants',['Alphabet','Amazon','Apple','Facebook','Microsoft']],
['Semiconductors', ['AMD','Intel','Nvidia']],
['Telecoms',['AT&T','Verizon','Sprint','T-Mobile']]
// ...
]);
// Build company selection form inputs
let companySelectionHTML = '';
for (let category of categories) {
categoryName = category[0];
categoryList = category[1];
// Setup a div to differentiate each category of companies.
// Will be used for turning on/off categories en masse
companySelectionHTML += `<div id="${toMachineString(categoryName)}">\n`;
// Category heading
companySelectionHTML += `<h4>${categoryName}</h4><button id="btn-${toMachineString(categoryName)}" data-checked="true">Toggle</button>`;
categoryList.forEach(companyName => {
companySelectionHTML += `
<label class="checkbox-label">
<input id="x-${toMachineString(companyName)}" class="checkbox" type="checkbox" name="company" value="${companyName}" checked>
<label for="x-${toMachineString(companyName)}">${companyName}</label>
</label>`;
});
companySelectionHTML += '</div>\n</div>\n</div>\n';
}
// Append to DOM
const companySelectionId = document.getElementById('company-selection-form');
companySelectionId.insertAdjacentHTML('beforeend', companySelectionHTML);
// Arm the toggle button
// HOW DO I APPLY THIS TO ALL THE TOGGLE BUTTONS INSTEAD OF JUST ONE?
$(document).ready(function(){
$('#tech-giants').click(function() {
// Access the data object of the button
var buttonData = $(this).data();
// Set all checkboxes 'checked' property
$('#tech-giants input[type=checkbox]').prop('checked', !buttonData.checked);
// Set the new 'checked' opposite value to the button's data object
buttonData.checked = !buttonData.checked;
// Update the chart -- code goes here
// dynamically-refresh-chart();
});
});
</script>
Thank you!
First bind your event like so for dynamically generated HTML (the buttons):
$('body').on("click", ".yourClass", function () {
//Your code goes here
});
Then use the class on the button instead of an ID, to apply the event listener to all buttons with the given class.
You could do it like this: bind the click() event to all buttons that have an id starting with "btn" $(document).on("click", "button[id^='btn']", function() {}); or just add a class to all toggle buttons and bind the click() event to them, which I did in the following code.
function toMachineString(humanString) {
var machineString = humanString.replace(/\s+/g, '-').toLowerCase();
machineString = machineString.replace('&', '');
return machineString;
}
// Setup the form
var categories = new Map([
['Tech Giants', ['Alphabet', 'Amazon', 'Apple', 'Facebook', 'Microsoft']],
['Semiconductors', ['AMD', 'Intel', 'Nvidia']],
['Telecoms', ['AT&T', 'Verizon', 'Sprint', 'T-Mobile']]
// ...
]);
// Build company selection form inputs
let companySelectionHTML = '';
for (let category of categories) {
categoryName = category[0];
categoryList = category[1];
// Setup a div to differentiate each category of companies.
// Will be used for turning on/off categories en masse
companySelectionHTML += `<div id="${toMachineString(categoryName)}">\n`;
// Category heading
companySelectionHTML += `<h4>${categoryName}</h4><button id="btn-${toMachineString(categoryName)}" class="category" data-checked="true">Toggle</button>`;
categoryList.forEach(companyName => {
companySelectionHTML += `
<label class="checkbox-label">
<input id="x-${toMachineString(companyName)}" class="checkbox" type="checkbox" name="company" value="${companyName}" checked>
<label for="x-${toMachineString(companyName)}">${companyName}</label>
</label>`;
});
companySelectionHTML += '</div>\n</div>\n</div>\n';
}
// Append to DOM
const companySelectionId = document.getElementById('company-selection-form');
companySelectionId.insertAdjacentHTML('beforeend', companySelectionHTML);
$(document).ready(function() {
$(document).on("click", ".category", function() {
var buttonData = $(this).data();
$(this).closest("div").find('input[type=checkbox]').prop('checked', !buttonData.checked);
buttonData.checked = !buttonData.checked;
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="button-text" id="customize-button">Open User Settings</button>
<div id="company-selection-form"></div>
I am trying to do a web app similar to google calendar. I have done the object and methods within it but now it's time to be able to add what I want as a task. My idea is for the user to add something to the input and that input being console.logged for now.
Any idea?
HTML
<div class="new-task" id="task-input">
<div id="add-new-task">Task: <input type="text"></div>
<div id="add-time">Time: <input type="text"></div>
<button class ="save-task" onclick="">Save task</button>
</div>
Javascript
var idCounter = 0
var tasksManager = {
array: [],
add: function(task){
taskObject = {
title: task,
idVerification: idCounter ++
}
tasksManager.array.push(taskObject)
},
show:function(id){
var i;
for (i = 0; i < tasksManager.array.length; i++) {
if(id === tasksManager.array[i].idVerification){
return tasksManager.array[i]
}
}
},
delete:function(task){
if(this.show){
tasksManager.array.splice(task)
}
}
}
var newTask = document.getElementById("add-new-task")
newTask.addEventListener('click',tasksManager.add())
console.log(tasksManager.array)
As you can see with console.log above the array index [0] is logged as undefined but I wanted the user to write in the input " Go to the gym" and this to be logged within the array.
Thanks
Some issues:
You are not assigning the click handler. Instead you execute it immediately (not on click).
When you call .add() you don't provide an argument: the name of the task
The click handler should be on the button element, not on the div that has the input element. And so it will be useful to give that button an id attribute.
You should retrieve the value from the input element, and so it would be more appropriate to give that element an id and not so much the div that wraps it.
The console.log at the end of your script is executed immediately. It should be done only when the user has clicked the button.
Snippet with some corrections (also in the HTML!):
var idCounter = 0
var tasksManager = {
array: [],
add: function(task){
let taskObject = {
title: task,
idVerification: idCounter ++
}
tasksManager.array.push(taskObject)
},
show:function(id){
var i;
for (i = 0; i < tasksManager.array.length; i++) {
if(id === tasksManager.array[i].idVerification){
return tasksManager.array[i]
}
}
},
delete:function(task){
if(this.show){
tasksManager.array.splice(task)
}
}
}
var button = document.getElementById("save-task"); // <-- the button
var input = document.getElementById("add-new-task"); // <-- the input (move the ID attribute to the input!)
button.addEventListener('click', () => {
tasksManager.add(input.value);
console.log(tasksManager.array)
})
<div class="new-task" id="task-input">
<div >Task: <input id="add-new-task" type="text"></div>
<div id="add-time">Time: <input type="text"></div>
<button class ="save-task" id ="save-task" onclick="">Save task</button>
</div>
I'm trying to use javascript to create a set of elements over and over again once the user enters a text where it would display the text with a button with an image in it to the side of it but I could not find a way to do it efficiently.
The current method I was going to create would require each element to have a id tag to it so that I could call appendChild to join the elements together.
I also need to have a create element be appended into another create element which adds to the issues
This is what I'm trying to achieve in the html code (the div would not be needed to be created as it is in the html code already)
function addToList(input) {
console.log(x);
let task = document.createElement('p');
task.id = x;
task.appendChild(document.createTextNode(input));
document.getElementById('listOfTasks').appendChild(task);
addCheckBox(x);
x++;
}
function addCheckBox(id) {
let checkBox = document.createElement('a');
checkBox.className = 'button is-rounded is-small';
checkBox.id = 'checkBox';
document.getElementById(id).appendChild(checkBox);
let a = document.createElement('span');
a.className = 'icon is-small';
a.id = 'apple';
document.getElementById(id).appendChild(a);
let b = document.createElement('i');
b.className = 'fas fa-check';
document.getElementById(id).appendChild(b);
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css"/>
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
<div class="container">
<div id="listOfTasks"></div>
</div>
<section class="section">
<div class="container">
<div class="field box form-popup" id="addTask">
<div class="control">
<div class="field is-grouped">
<label class="label"><b>Task to add</b></label>
</div>
<input
type="text"
class="input"
placeholder="Enter Task"
id="task"
required
/>
</div>
<button
type="button submit"
class="button is-success"
id="submit"
onclick="closeForm()"
>
Add
</button>
</div>
</div>
</section>
The current output is shown as
Would be grateful if anyone knows a better method to do this
Make a function that reduces boilerplate code when creating element
function create(name, props, children) {
let elem = document.createElement(name); // create it
const parent = props.parent // we use parent prop elsewhere
let keys = Object.keys(props) // collect keys
keys = keys.filter(function(key) { // remove parent prop from keys
return key !== 'parent'
})
keys.forEach(function(key) { // assign props to element
elem.setAttribute(key, props[key])
})
if (children && children.length) { // add children to element
children.forEach(function(child) {
elem.appendChild(child)
})
}
if (parent) { // attach to parent
document.getElementById(id).appendChild(elem);
}
return elem // return it, to customize further
}
And then
function addCheckBox(id) {
create('a', {
id: 'checkBox', // simple prop
parent: id, // parent prop
class: 'button is-rounded is-small' // simple prop
})
var span = create('span', {
parent: id,
id: 'apple',
class: 'icon is-small'
}, [create('i', { // demo of children
class: 'fa fa-check'
}])
span.setAttribute('data-something', 1) // demo of customizing
}