What I want to do is when I click the task it will have a line through the text means that I'm done with the task. but the add event listener function for this is not working, I'm working with the javascript toggle and that's all I can think of right now to achieve this functionality.
Is there another way to do this? I searched on the internet and it seems complicated when I'm trying to figure it out.
const addBtn = document.querySelector("#push");
const taskInput = document.querySelector("#taskInput");
const taskOutput = document.querySelector("#tasks");
addBtn.addEventListener("click", function() {
let newTasks = taskInput.value;
if (newTasks.length == 0) {
alert("Please enter a task");
} else {
taskOutput.innerHTML += `<div class="task">
<span id="taskname">${newTasks} </span>
<button class="delete" id="deleteButton"><i class="fa-solid fa-trash"></i> </button>
</div>
`;
//delete
let deleteBtn = document.querySelector("#deleteButton");
deleteBtn.addEventListener("click", function() {
this.parentNode.remove();
});
//line through
let theTask = document.querySelectorAll(".task");
theTask.addEventListener("click", function() {
this.classList.toggle("completed");
});
}
});
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
height: 100vh;
background: linear-gradient( 90deg, rgba(241, 206, 221, 1) 0%, rgba(124, 184, 254, 1) 100%);
display: flex;
justify-content: center;
align-items: center;
font-family: 'Kumbh Sans', sans-serif;
}
.container {
border: 2px solid white;
width: 50%;
min-width: 450px;
margin: auto;
padding: 30px 40px;
}
#new-task {
position: relative;
background-color: white;
padding: 30px 20px;
border-radius: 1em;
}
#new-task input {
width: 70%;
height: 45px;
font-family: 'Manrope', sans-seif;
font-size: 1.2em;
border: 2px solid #d1d3d4;
padding: 12px;
color: #111111;
font-weight: 500;
position: relative;
border-radius: 5px;
}
#new-task input:focus {
outline: none;
border-color: violet;
}
#new-task button {
font-family: 'Manrope', sans-seif;
position: relative;
float: right;
width: 25%;
height: 45px;
border-radius: 5px;
font-weight: bold;
font-size: 16px;
border: none;
background-color: violet;
color: white;
cursor: pointer;
}
#tasks {
background-color: white;
padding: 30px 20px;
margin-top: 50px;
border-radius: 10px;
width: 100%;
}
.task {
background-color: white;
height: 50px;
padding: 5px 10px;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 2px solid violet;
cursor: pointer;
}
.task span {
font-size: 18px;
font-weight: 400;
}
.task button {
background-color: violet;
color: white;
height: 100%;
width: 40px;
border: none;
border-radius: 5px;
outline: none;
cursor: pointer;
}
.task button:hover {
background-color: red;
}
.completed {
text-decoration: line-through;
}
<body>
<div class="container">
<div id="new-task">
<input type="text" name="" id="taskInput" placeholder="Task to be done" />
<button id="push">ADD</button>
</div>
<div id="tasks"></div>
</div>
<script src="/script.js"></script>
</body>
querySelectorAll will return the list of nodes matching the selector tasks. So you have to iterate through each of those nodes and add your listener. See the below code snippet
let theTasks = document.querySelectorAll(".task");
theTasks.forEach((task) => {
task.addEventListener("click", function() {
this.classList.toggle("completed");
});
});
theTask is a list of nodes. Trying to attach event listener on this list is causing issues.
Also, you will be inserting lots of buttons with same id deleteButton and spans with same id taskname which is incorrect and can cause undefined behavior.
For theTask fix, you may want to do something like:
let theTasks = [...document.querySelectorAll(".task")];
theTasks.forEach(task => {
task.addEventListener("click", function() {
this.classList.toggle("completed");
})
});
Using innerHTML to create manipulate the DOM for an application like a todo list is probably not a good idea. The answers to Advantages of createElement over innerHTML? give good explanations why.
It is worth noting that in the innerHTML code, the span and the button are created with an id and so all of these elements will have the same id. It is also probably not a good idea to have duplicate ids on one page. Why are duplicate ID values not allowed in HTML? explains why.
Also, adding event listeners to every new task is also probably not a good idea. What is DOM Event delegation? gives a good explanation why.
Finally, the Difference between HTMLCollection, NodeLists, and arrays of objects and Document.querySelectorAll() explain how to get lists of elements that can be manipulated.
So, I have rewritten the task creation code in the addBtn.addEventListener to show one way how this could be done with document.createElement().
And I have created a separate event listener on the Tasks container div, which handles both task deletion and task completion.
I also added the following CSS so that clicking on a trash can icon is handled by the parent button. Without this CSS, clicking on an icon would not delete the task.
div#tasks i {
pointer-events: none;
}
To make the todo list more visible in the code snippet below, I reduced the heights, margins, and paddings of some of the elements in the CSS.
I also added a link to the font awesome icon library.
const addBtn = document.querySelector("#push");
const taskInput = document.querySelector("#taskInput");
const taskOutput = document.querySelector("#tasks");
taskOutput.addEventListener("click", function(event) {
if (event.target && event.target.nodeName === "SPAN") {
event.target.classList.toggle("completed");
}
if (event.target && event.target.nodeName === "BUTTON") {
event.target.parentNode.remove();
}
});
addBtn.addEventListener("click", function() {
let newTasks = taskInput.value;
if (newTasks.length == 0) {
alert("Please enter a task");
} else {
// Create a task DIV
const newTaskElement = document.createElement("div");
newTaskElement.classList.add("task");
// Create a SPAN with the task name
const newTaskNameElement = document.createElement("span");
const taskTextnode = document.createTextNode(newTasks);
newTaskNameElement.appendChild(taskTextnode);
// Create a BUTTON with a TRASH CAN ICON
const newTaskDeleteButton = document.createElement("button");
const deleteImageElement = document.createElement("i");
deleteImageElement.classList.add("fa-solid", "fa-trash");
newTaskDeleteButton.appendChild(deleteImageElement);
// Append the SPAN and the BUTTON to the task DIV
newTaskElement.appendChild(newTaskNameElement);
newTaskElement.appendChild(newTaskDeleteButton);
// Append the task DIV to the TASK LIST DIV
taskOutput.appendChild(newTaskElement);
}
});
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
height: 100vh;
background: linear-gradient( 90deg, rgba(241, 206, 221, 1) 0%, rgba(124, 184, 254, 1) 100%);
font-family: 'Kumbh Sans', sans-serif;
}
/* ADDED TO MAKE SURE THAT THE TRASH ICON DOES NOT PROCESS CLICKS */
div#tasks i {
pointer-events: none;
}
.container {
border: 2px solid white;
width: 50%;
min-width: 450px;
margin: auto;
padding: 3px 4px;
}
#new-task {
position: relative;
background-color: white;
padding: 6px 4px;
border-radius: 1em;
}
#new-task input {
width: 70%;
height: 45px;
font-family: 'Manrope', sans-seif;
font-size: 1.2em;
border: 2px solid #d1d3d4;
padding: 12px;
color: #111111;
font-weight: 500;
position: relative;
border-radius: 5px;
}
#new-task input:focus {
outline: none;
border-color: violet;
}
#new-task button {
font-family: 'Manrope', sans-seif;
position: relative;
float: right;
width: 25%;
height: 45px;
border-radius: 5px;
font-weight: bold;
font-size: 16px;
border: none;
background-color: violet;
color: white;
cursor: pointer;
}
#tasks {
background-color: white;
padding: 6px 4px;
margin-top: 5px;
border-radius: 10px;
width: 100%;
min-height: 50px;
}
.task {
background-color: white;
height: 50px;
padding: 5px 10px;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 2px solid violet;
cursor: pointer;
}
.task span {
font-size: 18px;
font-weight: 400;
}
.task button {
background-color: violet;
color: white;
height: 100%;
width: 40px;
border: none;
border-radius: 5px;
outline: none;
cursor: pointer;
}
.task button:hover {
background-color: red;
}
.completed {
text-decoration: line-through;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css" rel="stylesheet" />
<div class="container">
<div id="new-task">
<input type="text" name="" id="taskInput" placeholder="Task to be done" />
<button id="push">ADD</button>
</div>
<div id="tasks"></div>
</div>
How can I add icons before the form fields?
This is how looks now:
And here how I want:
Here is css code (front.css):
body .qb-form {
width: auto;
height: auto;
}
#media (max-width: 660px) {
body .qb-form {
width: 100%;
}
}
body .qb-form h2 {
background: #3482C3;
padding: 15px 25px;
margin-bottom: 0;
color: white;
margin-top: 0;
}
body .qb-form .moreinfo {
background: #3482C3;
color: white;
padding: 0 25px 15px 25px;
margin-bottom: 15px;
}
body .qb-form label {
text-align: left;
font-size: 14px;
display: block;
padding-bottom: 0;
}
body .qb-form .qb-gdpr-label {
padding-bottom: 0;
}
body .qb-form .quickbuy_input {
height: 31px;
width: 190px;
border: 1px solid #ABADB3;
padding: 5px;
}
body .qb-form textarea {
width: 100%;
height: 60px;
border: 1px solid #abadb3;
}
body .qb-form .crow {
padding: 0 25px 25px 25px;
}
body .qb-form .buttons_wrp {
padding: 10px 25px 25px 25px;
}
body .qb-form .buttons_wrp .button {
padding: 10px 20px;
border: none;
border-radius: 4px;
text-transform: uppercase;
color: white;
background: #3482C3;
overflow: hidden;
}
body .qb-form .buttons_wrp .qb-btn-submit {
padding: 10px 20px 10px 62px;
background: #3482C3 url('../img/cart-icon.png') no-repeat 15px center;
}
body .qb-form .buttons_wrp .button:hover {
background-color: #388bd1;
}
body .qb-wrp .qb-btn span {
border-bottom: 1px dashed;
}
.product-simple .qb-btn {
background: none;
color: #1F679B;
font-size: 13px;
border-bottom: 1px dashed #1F679B;
padding: 0 0 1px 0;
}
body .qb-form sup {
color: red;
font-weight: bold;
}
body .qb-form .quickbuy_errors,
body .qb-form .quickbuy_success {
margin: 0 15px;
display: none;
padding: 10px;
line-height: 1.5;
}
body .qb-form .qb-product-name {
padding: 5px;
border: 1px dashed white;
font-weight: bold;
display: inline-block;
}
body .qb-form body .qb-form_loader {
position: relative;
top: -3px;
}
body .qb-form .qb-loader {
visibility: hidden;
}
body .qb-form .qb-loader.visible {
visibility: visible;
}
.qb-form .qb-gdpr-label .qb_gdpr_wrp {
float: left;
position: relative;
top: 3px;
margin-right: 10px;
}
.qb-form .qb-btn-close {
display: none;
}
.qb-form .qb-btn-close span {
font-size: 2rem;
line-height: 0;
display: inline-block;
vertical-align: middle;
margin-right: 0.5rem;
position: relative;
top: -1px;
border: none;
}
.qb-gdpr-label p:last-child {
margin-bottom: 0;
}
#media (max-width: 767px) {
.qb-wrap,
#product .qb-wrap {
flex-wrap: wrap;
}
}
And here is the hook.tpl:
<div class="crow">
<label for="quickbuy_name">{l s='Your name' mod='quickbuy'}:</label>
<input type="text" class="qb_name qb-input-field form-control" id="quickbuy_name" name="qb_customer_name" value="{$qb_name|escape:'html':'UTF-8'}" />
</div>
<div class="crow">
<label for="quickbuy_address">{l s='Your address' mod='quickbuy'}:</label>
<input type="text" class="qb_address qb-input-field form-control" id="quickbuy_address" name="qb_address" value="{$qb_address|escape:'html':'UTF-8'}" />
</div>
<div class="crow">
<label for="quickbuy_phone">{l s='Your phone number' mod='quickbuy'}: <sup>*</sup></label>
<input type="text" class="qb_phone qb-input-field form-control" id="quickbuy_phone" name="qb_phone" value="{$qb_phone|escape:'html':'UTF-8'}" />
</div>
{if $qb_gdpr}
<div class="crow">
<label class="qb-gdpr-label">
<span class="qb_gdpr_wrp">
<input type="checkbox" class="qb_gdpr" name="qb_gdpr">
</span>
{if $qb_gdpr_text}
{$qb_gdpr_text nofilter}{* HTML *}
{else}
{l s='I agree to processing of my personal data' mod='quickbuy'}
{if $qb_gdpr_link}(<a target="_blank" href="{$qb_gdpr_link|escape:'html':'UTF-8'}">{l s='read' mod='quickbuy'}</a>){/if}
{/if}
</label>
</div>
{/if}
<div class="crow quickbuy_errors error"></div>
<div class="crow quickbuy_success success"></div>
<div class="buttons_wrp">
<input type="hidden" name="qb_id_product" value="{$qb_product->id|intval}" />
<input type="hidden" name="qb_id_product_attribute" value="{$qb_product->id_product_attribute|intval}" />
<input type="hidden" name="qb_token" value="{$qb_token|escape:'html':'UTF-8'}" />
<input type="hidden" name="qb_action" value="submitQB" />
<input type="submit" class="qb-btn-submit btn btn-default button button-small" value="{l s='Buy' mod='quickbuy'}" />
<button class="qb-btn-close btn btn-default button button-small"><span>×</span> {l s='Close' mod='quickbuy'}</button>
<img class="qb-loader" src="/img/loader.gif" alt="{l s='Loading...' mod='quickbuy'}" />
</div>
</div>
</div>
</div>
I will be happy if anyone can help.
Thank you in advance.
Best regards
You can select the input fields from your HTML template by using their id's.
You you use icons8 to find the correct icons.
There you can get the Link (CDN) for each item by clicking on the download button and copy HTML.
You can paste the copied code in your HTML (just before the respective input field).
Afterwards you can style the respective item in your CSS file.
So that it has the same border and height as your input field.
I have the following code:
Type some text in place of the [Header] and press enter.
As you can see on clicking enter in the h2 element the cursor shifts to span element.
However, it adds an extra line in the beginning.
I don't know how to remove a line from the end.
function enter() {
if (event.key == "Enter") {
$("div#text span").focus();
}
}
var h = $('h2').offset();
$('div#text span').click(function() {
});
div#text {
padding: 5px;
margin: 0;
width: 99.3%;
height: 99%;
resize: none;
font-family: 'Callibri';
font-size: 25px;
text-align: left;
z-index: 99;
line-height: 30px;
background-color: white;
overflow-y: scroll;
cursor: text;
}
h2 {
text-align: center;
font-size: 40px !important;
}
h2:focus,
div#text span:focus {
outline: none;
border: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="text" spellcheck="false">
<h2 contenteditable="true" onkeydown="enter()">[Header]</h2><span contenteditable="true">[Body]</span>
</div>
Use event.preventDefault to override default behaviour on pressing enter key.
function enter() {
if (event.key == "Enter") {
event.preventDefault();
$("div#text span").focus();
}
}
var h = $('h2').offset();
$('div#text span').click(function() {
});
div#text {
padding: 5px;
margin: 0;
width: 99.3%;
height: 99%;
resize: none;
font-family: 'Callibri';
font-size: 25px;
text-align: left;
z-index: 99;
line-height: 30px;
background-color: white;
overflow-y: scroll;
cursor: text;
}
h2 {
text-align: center;
font-size: 40px !important;
}
h2:focus,
div#text span:focus {
outline: none;
border: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="text" spellcheck="false">
<h2 contenteditable="true" onkeydown="enter()">[Header]</h2><span contenteditable="true">[Body]</span>
</div>
If click on button some boxes are append. next you will click on that boxes gradient box will append but gradient boxes are not appending.its append only first box if click on another box gradient box doesn't append
My Fiddle
<script src="https://cdn.office24by7.com/add-templates/gradX.js"></script>
<button class="clbtn" name="button" value="button">button</button>
<div class="appenddiv">
</div>
<script>
$(document).ready(function(){
var i = 0;
$(".clbtn").click(function(el){
$.fn.myFunction = function(){
gradX("#clrpik", {
targets: [".target"]
});
}
$(".appenddiv").append('<div class="target"><div class="target_text">Click Here for gradient</div></div>');
$(".target").click(function(){
$(".appenddiv").append('<div id="clrpik"></div>').myFunction();
});
});
});
</script>
Gradient box appending on other div click but it's stick to first div
use this to set:
$(this).append('<div id="clrpik"></div>').myFunction();
});
$(document).ready(function(){
var f = 0;
$(".clbtn").click(function(el){
$.fn.myFunction = function(){
gradX("#clrpik", {
targets: [".target"]
});
//f++;
}
$(".appenddiv").append('<div class="target"><div class="target_text">Click Here for gradient</div></div>');
$(".target").one('click', function(){
$(this).append('<div id="clrpik"></div>').myFunction();
});
});
});
.targets {
margin:0 auto;
text-align: center;
border: 1px solid #ccc;
background: #f8f8f8;
margin: 0 auto;
border-radius: 4px;
width:auto;
padding:10px;
}
.target_text {
margin: 0px auto;
margin-top: 40%;
background: #f8f8f8;
width: 70px;
border: 1px solid #ddd;
padding: 2px;
border-radius: 2px;
color: #111;
}
.target {
border: 1px solid;
margin: 0px 10%;
width: 150px;
height: 150px;
display:inline-block;
}
#target {
border-radius: 150px;
}
.result {
text-align: center;
text-transform: uppercase;
font-weight: bold;
padding:12px;
padding-left: 15px;
margin: 10px 0px;
border: 1px solid #ddd;
background: #f8f8f8;
}
.clrpik {
height: 200px;
margin: 100px 34%;
}
<link href="https://cdn.office24by7.com/add-templates/colorpicker.css" rel="stylesheet"/>
<link href="https://cdn.office24by7.com/add-templates/gradX.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://codologic.com/page/sites/all/files/gradx/dom-drag.js"></script>
<script src="https://codologic.com/page/sites/all/files/gradx/colorpicker/js/colorpicker.js"></script>
<script src="https://cdn.office24by7.com/add-templates/gradX.js"></script>
<button class="clbtn" name="button" value="button">button</button>
<div class="appenddiv">
</div>
This is my code
<script src="https://code.jquery.com/jquery-1.8.0.min.js"></script>
<script>
function skinchange(link){
document.getElementById('inputtest').value = link;
}
</script>
<script type="text/javascript">
$(function() {
$('.imgstyles').click(function() {
$('.imgstyles').removeClass('selected');
$(this).addClass('selected')
});
});
</script>
.selected {
border: 10px solid #7EBEFC;
}
a:hover img.imgstyles {
border: 3px solid #7EBEFC;
opacity:0.15;
}
a:hover div.textcss {
display: block;
}
a img.imgstyles {
border: 2px solid #ffffff;
}
.textcss {
display: none;
margin-top: -147px;
font-size: 50px;
font-weight: bold;
margin-right: 20px;
color: #7EBEFC;
text-align: center;
}
<input type="text" name="inputtest" id="inputtest"/>
<a onclick="skinchange('https://wp-test-hoangxanh.c9.io/wp-content/plugins/hEmbed/skins/gred.xml')"><img class="imgstyles" src="https://wp-test-hoangxanh.c9.io/wp-content/plugins/hEmbed/skins/images/gred.jpg" width="95%" height="60%"><div class="textcss">Gred</div></a>
Function set value work, hover work but my selected css didn't, someone help me!
The problem is the css specificity.
The border rule set by .selected is overwritten by the more specific rule a img.selected.
So the solution is to create a more specific rule like img.imgstyles.selected
function skinchange(link) {
document.getElementById('inputtest').value = link;
}
$(function() {
$('.imgstyles').click(function() {
$('.imgstyles').removeClass('selected');
$(this).addClass('selected')
});
});
.selected, img.imgstyles.selected {
border: 10px solid #7EBEFC;
}
a:hover img.imgstyles {
border: 3px solid #7EBEFC;
opacity: 0.15;
}
a:hover div.textcss {
display: block;
}
a img.imgstyles {
border: 2px solid #ffffff;
}
.textcss {
display: none;
margin-top: -147px;
font-size: 50px;
font-weight: bold;
margin-right: 20px;
color: #7EBEFC;
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<input type="text" name="inputtest" id="inputtest" />
<a onclick="skinchange('https://wp-test-hoangxanh.c9.io/wp-content/plugins/hEmbed/skins/gred.xml')">
<img class="imgstyles" src="https://wp-test-hoangxanh.c9.io/wp-content/plugins/hEmbed/skins/images/gred.jpg" width="95%" height="60%">
<div class="textcss">Gred</div>
</a>