How to disable a dynamically created <li> element? - javascript

i have created <ul> containing three <li>.i want to make disable one of my <li> on certain condition and insert some text in other <li> but failed.!
code
var d = document.createElement('div');
d.className = "dataTables_paginate paging_bootstrap pagination";
var UL = document.createElement('ul');
var L1 = document.createElement('li');
L1.className = 'prev';
var A1 = document.createElement('a');
A1.appendChild(document.createTextNode('← Previous'));
A1.id = 'B1';
L1.appendChild(A1);
UL.appendChild(L1);
var L3 = document.createElement('li');
L3.className = 'active';
var A3 = document.createElement('a');
A3.appendChild(document.createTextNode('1'));
L3.appendChild(A3);
UL.appendChild(L3);
d.appendChild(UL);
var L2 = document.createElement('li');
L2.className = 'next';
var A2 = document.createElement('a');
A2.appendChild(document.createTextNode('Next →'));
L2.appendChild(A2);
A2.id = 'B2';
UL.appendChild(L2);
var root = document.getElementById('rose');
root.appendChild(d);
i want to B1 disable. i have tried following code:
script
$('#B1').attr("disabled", true);

try with .off():
$('#B1').off("click");
FYI:
Only form input elems are having property to get disabled, whether that is type text, select checkbox buttons etc.

While there is no disabled state for a li element, you can simulate the desired behavior like this:
$('#B1').css("color","gray").css("text-decoration","none");
Which will make it appear as if disabled (it will not be underlined and will appear grayed-out).
If in addition you need to disable the event listeners attached to it, you will have to use off():
$('#B1').off("click");
Furthermore, if the element is a link, you will have to prevent it from being clickable, in the following way:
$('#B1').click(function() {
$(this).preventDefault(); // prevent the default action
$(this).stopPropagation(); // prevent event from bubbling up
return false; // just to be sure
}

Related

my list function doesn't work in javascript

so i wrote this code that would create a list and then append an input to it on click. really simple. but the problem is it doesn't work and i have no idea why
here is the code:
function pushing() {
var li = document.createElement("li");
var inputValue = document.getElementById("inp").value;
var pushchild = document.createTextNode(inputValue);
li.appendChild(pushchild);
}
sub.addEventListener("click", pushing);
the id inp is an input id. thank you
Add this to the last line of your function. Append your newly created li element to the ul.
document.querySelectorAll(‘ul’).appendChild(newCreatedLi);
Your list item is never appended to a list element.
// Cache the elements,
// add the button listener,
// & focus on the input
const list = document.querySelector('ul');
const input = document.querySelector('#inp');
const sub = document.querySelector('#sub');
sub.addEventListener('click', pushing);
input.focus();
function pushing() {
const li = document.createElement('li');
const text = document.createTextNode(input.value);
li.appendChild(text);
// Adding the list item to the list element
list.appendChild(li);
}
<input id="inp" />
<button id="sub">Click</button>
<ul></ul>

Why does deleting this element with a non-unique ID delete the one I want?

Pardon the bad title, it's hard to explain. If you know how to phrase it better, please comment and I will update as soon as I can.
So, I was messing around with a random generator site (perchance.org) and writing my own HTML/Javascript to make my generator work. It has a behavior that is what I want, but that shouldn't be happening according to my knowledge of HTML.
Let me explain with a minimal example.
The example code here is to produce a simple page that has a button.
This button should generate <input>s with <button>s next to them, attached with similar ID's.
The button, when clicked, deletes the <input> and <button>.
Here is a snippet to show you the code/let you reproduce the results:
<html>
<head>
<script>
var current_id = 0;
function add_input () {
var list = document.getElementById("list");
var input = document.createElement("input");
var delete_button = document.createElement("button");
var br = document.createElement("br");
input.id = "input_" + current_id;
delete_button.id = "button_" + current_id;
br.id = "br_" + current_id;
input.value = input.id;
delete_button.textContent = "Delete";
delete_button.onclick = function () {
delete_input(this.id.slice(7)) //To get the numerical ID
}
list.appendChild(input);
list.appendChild(delete_button);
list.appendChild(br);
current_id++;
}
function delete_input (id) {
var input = document.getElementById("input_"+id);
var button = document.getElementById("button_"+id);
var br = document.getElementById("br_"+id);
input.remove();
button.remove();
br.remove();
current_id--;
}
</script>
</head>
<body>
<div id="list">
</div>
<button onclick="add_input()">Add</button>
</body>
</html>
When you add two inputs, then delete the first, and add one more, it leaves you with two inputs using the same ID. It also leaves you with two buttons with the same ID. And yet, both buttons delete their intended target.
Why?
You really should delegate - here I wrap in a div that can be removed in one go
You can rename each input to have incremented IDs but just letting the cnt run, gives you unique IDs
let cnt = 0;
function add_input() {
var list = document.getElementById("list");
var div = document.createElement("div");
var input = document.createElement("input");
var delete_button = document.createElement("button");
var br = document.createElement("br");
input.id = "input_" + (cnt++)// list.querySelectorAll("div").length
input.value = input.id;
delete_button.textContent = "Delete";
delete_button.classList.add("delete")
div.appendChild(input);
div.appendChild(delete_button);
div.appendChild(br);
list.appendChild(div);
}
window.addEventListener("load", function() {
document.getElementById("list").addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains("delete")) tgt.closest("div").remove();
})
})
<div id="list">
</div>
<button onclick="add_input()">Add</button>
I changed your code to be more effective.
I'm not using IDs as they aren't adding any benefit instead making it more complex.
Instead I target the element via the event handler and an argument.
I also wrap each set of inputs/buttons in a div so I can just remove that div and it will remove all of the children.
function add_input() {
var list = document.getElementById("list");
var input = document.createElement("input");
var delete_button = document.createElement("button");
var br = document.createElement("br");
delete_button.textContent = "Delete";
delete_button.onclick = function(e) {
e.target.parentNode.remove();
}
var div = document.createElement("div");
div.appendChild(input);
div.appendChild(delete_button);
div.appendChild(br);
list.appendChild(div)
}
<div id="list">
</div>
<button onclick="add_input()">Add</button>

Eventlisteners not being added in the following js code

I am building a todo app where I am dynamically generating tasks using javascript.[]
I generate following equivalent html from js whenever I click on the add button:
<div class="row datasection">
<div class="todo">
<div class="databox col s6 offset-s1 waves-effect">
<p class="checkglyph1 checkglyph2">Task no 1</p>
<a>
<i class="material-icons checkglyph checkglyph1 checkglyph2 glyphcolor">check</i>
</a>
</div>
</div>
</div>
Now what I want is whenever I click event on the task created it should become yellow in colour.I have written the code to this. below.However it works fine only when there is one task created.If there is multiple then the last task works well but actionlistener on the first one does not seem to be working.I am not able to figure out where the code is breaking.
var glyph= document.querySelectorAll(".glyphcolor");
for (var i = 0; i < glyph.length; i++) {
glyph[i].addEventListener('click', function(event) {
this.classList.toggle("checkglyph1");
});
}
The actual snippet
//declaration
var calendardata = document.getElementById('date1');
var addbutton = document.querySelector('.addbutton');
var todo = document.querySelector('.todo');
addbutton.addEventListener('click', function() {
/* body to return the html */
if (data.value) {
var newdiv = document.createElement("div"); // Create a <button> element
newdiv.classList.add("databox", "col", "s6", "waves-effect");
//console.log(newdiv);
todo.appendChild(newdiv);
//console.log(newdiv.parentNode);
var newpar = document.createElement("p");
newpar.classList.add("checkglyph1", "checkglyph2");
var node = document.createTextNode(data.value + "." + " " +
calendardata.value);
var newa = document.createElement("a");
newdiv.appendChild(newa)
var newglyph = document.createElement("i");
newglyph.classList.add("material-icons", "checkglyph", "checkglyph1",
"checkglyph2", "glyphcolor");
var node1 = document.createTextNode("check");
newa.appendChild(newglyph);
newglyph.append(node1);
newpar.appendChild(node);
newdiv.appendChild(newpar);
data.value = "";
calendardata.value = "";
created = true;
// console.log("before glyh created");
//code to perform action on the click of the tick symbol
var glyph = document.querySelectorAll(".glyphcolor");
var par = document.getElementsByClassName('checkglyph2');
for (var i = 0; i < glyph.length; i++) {
//console.log("Inside the loop");
glyph[i].addEventListener('click', function.bind(event) {
this.classList.toggle("checkglyph1");
//console.log('Inside the click');
//console.log(i);
});
}
}
})
What's happening that when they other tasks are created they aren't being collected in the Node Collection, thus they have no event listener. What you can do is instead add the event listener to the container and change whichever item that was clicked in:
document.querySelector('ul').addEventListener('click', changeClass);
document.querySelector('#button').addEventListener('click', addLi);
function changeClass(e){
e.target.closest('li').classList.toggle('checkglyph1');
}
function addLi(e){
const new_li = document.createElement('li');
new_li.textContent = document.querySelectorAll('li').length + 1;
new_li.classList.add('checkglyph1');
document.querySelector('ul').appendChild(new_li);
}
li:not(.checkglyph1) {
background: #f00;
}
<button id="button">Add li</button>
<ul>
<li class="checkglyph1">1</li>
<li class="checkglyph1">2</li>
<li class="checkglyph1 red">3</li>
<li class="checkglyph1">4</li>
<li class="checkglyph1">5</li>
<li class="checkglyph1">6</li>
<li class="checkglyph1">7</li>
<li class="checkglyph1">8</li>
<li class="checkglyph1">9</li>
<li class="checkglyph1">10</li>
</ul>
The problem with your code is that everytime you click on ".addbutton", you're going through all of the ".glyphcolor"s element's in your DOM and adding a new onclick event listener. The last one created will work, but the others will have multiple event listeners repeated (yes, this is possible). So, when you click on an element that has two events telling it to toggle the "checkglyph1" class, it will do it twice. And of course, it will not change at all. You can easily see this happening, because all the odd elements in your page must work (they will toggle the class by odd times), while the even ones must not.
This can be corrected by adding the event listener directly on the element when you create it on the page. The code below must work fine:
//declaration
var calendardata = document.getElementById('date1');
var addbutton = document.querySelector('.addbutton');
var todo = document.querySelector('.todo');
addbutton.addEventListener('click', function() {
if (data.value) {
var newdiv = document.createElement("div"); // Create a <button> element
newdiv.classList.add("databox", "col", "s6", "waves-effect");
//console.log(newdiv);
todo.appendChild(newdiv);
//console.log(newdiv.parentNode);
var newpar = document.createElement("p");
newpar.classList.add("checkglyph1", "checkglyph2");
var node = document.createTextNode(data.value + "." + " " +
calendardata.value);
var newa = document.createElement("a");
newdiv.appendChild(newa)
var newglyph = document.createElement("i");
newglyph.classList.add("material-icons", "checkglyph", "checkglyph1",
"checkglyph2", "glyphcolor");
var node1 = document.createTextNode("check");
newa.appendChild(newglyph);
newglyph.append(node1);
newpar.appendChild(node);
newdiv.appendChild(newpar);
data.value = "";
calendardata.value = "";
created = true;
newglyph.addEventListener('click', function(event) {
event.preventDefault(); // Just to prevent non desired effects of click
newglyph.classList.toggle('checkglyph1');
}
}
}
And just small clarifications: you don't need the "bind" in your actual code.
glyph[i].addEventListener('click', function.bind(event) { // just type function(event)
this.classList.toggle('checkglyph1');...

Javascript- Creating To Do list not working

I deleted the button part in my script but not even the first part of my function is working where I type in input box and suppose to be added to the ...I don't understand why. When I run the code without the buttons code which is titled " //BUTTON creation " I get no error but no item is being added to the list. So I have two problems Items aren't being added to my list and aren't displaying and also if I include the button part its saying an error "list.appendChild is not a function"
<input type="text" placeholder="Enter an Activity" id="textItem">
<img src="images/add-button.png" id="addButton">
<div id="container">
<ul class="ToDo">
<!--
<li>
This is an item
<div id="buttons">
<button ></button>
<img src="images/remove-icon.png"id="remove">
<button id="complete"></button>
<img src="images/complete-icon.jpg" id="complete">
</div>
</li>
!-->
</ul>
</div>
<script type="text/javascript">
//Remove and complete icons
var remove = document.createElement('img').src =
"images/remove-icon.png";
var complete = document.createElement('img').src = "images/complete-icon.jpg";
//user clicks add button
//if there is text in the item field we grab the item into var text
document.getElementById("addButton").onclick = function()
{
//value item is the text entered by user
var value = document.getElementById("textItem").value;
//checks if there is a value typed
if(value)
{
addItem(value);
}
//adds a new item to the ToDo list
function addItem(text)
{
var list = document.getElementsByClassName("ToDo");
//created a varibale called item that will create a list item everytime this function is called
var item = document.createElement("li");
//this will add to the innerText of the <li> text
item.innerText = text;
//BUTTON creation
var buttons = document.createElement('div');
buttons.classList.add('buttons');
var remove = document.createElement('buttons');
buttons.classList.add('remove');
remove.innerHTML = remove;
var complete = document.createElement('buttons');
buttons.classList.add('complete');
complete.innerHTML = complete;
buttons.appendChild(remove);
buttons.appendChild(complete);
list.appendChild(buttons);
list.appendChild(item);
}
}
</script>
The problem is in the line:
var list = document.getElementsByClassName("ToDo");
list.appendChild(item);
The line var list = document.getElementsByClassName("ToDo"); will provide a collection, notice the plural name in the api.
You need to access it using :
list[0].appendChild(item);
There are other problems too in the code but hopefully this gets you going!
There are a couple of issues in your code that need to be addressed to get it to work properly.
1) You are creating your image elements and then setting the variables to the src name of that image and not the image object itself. When you use that reference later on, you are only getting the image url and not the element itself. Change var remove = document.createElement('img').src = "images/remove-icon.png" to this:
var removeImg = document.createElement('img')
removeImg.src = "images/remove-icon.png";
2) As #Pankaj Shukla noted, inside the onclick function, getElementsByClassName returns an array, you will need to address the first item of this array to add your elements. Change var list = document.getElementsByClassName("ToDo") to this:
var list = document.getElementsByClassName("ToDo")[0];
3) For your buttons, you are trying to creating them using: var remove = document.createElement('buttons'). This is invalid, buttons is an not the correct element name, its button. Additionally, you are re-declaring the variables remove and complete as button objects, so within the onclick function it reference these buttons, not the images you defined earlier. So when you assign the innerHTML to remove and complete, you are assigning the buttons innerHTML to itself. The solution is to change the image variables to something different.
4) Finally, also relating to the buttons, you are assigning the innnerHTML to an image object, that's incorrect. You can either insert the html text of the img directly, or append the image object as a child of the button, similar to how the button is a child of the div.
The updated code with all these changes looks like this:
//Remove and complete icons
var removeImg = document.createElement('img');
removeImg.src = "images/remove-icon.png";
var completeImg = document.createElement('img');
completeImg.src = "images/complete-icon.jpg";
//user clicks add button
//if there is text in the item field we grab the item into var text
document.getElementById("addButton").onclick = function() {
//value item is the text entered by user
var value = document.getElementById("textItem").value;
//checks if there is a value typed
if (value) {
addItem(value);
}
//adds a new item to the ToDo list
function addItem(text) {
var list = document.getElementsByClassName("ToDo")[0];
//created a varibale called item that will create a list item everytime this function is called
var item = document.createElement("li");
//this will add to the innerText of the <li> text
item.innerText = text;
//BUTTON creation
var buttons = document.createElement('div');
buttons.classList.add('buttons');
var remove = document.createElement('button');
remove.classList.add('remove');
remove.appendChild(removeImg);
var complete = document.createElement('button');
complete.classList.add('complete');
complete.appendChild(completeImg);
buttons.appendChild(remove);
buttons.appendChild(complete);
list.appendChild(buttons);
list.appendChild(item);
}
}

Change InnerHTML based on anchor click

I'm a little new to Web Development so I was hoping someone could answer this for me.
I'm building a prototype for a "Web Messenger" similar to Facebook messenger. I have a sidebar that I populate with a UL of anchor tags when the window loads and it looks like this. Here is the code for it
var toAdd = document.createDocumentFragment();
var newUL = document.createElement('ul');
newUL.id = 'menu-content';
newUL.className = 'menu-content collapse out';
for(var i = 0; i < 5; i++){
var newLI = document.createElement('li');
var newA = document.createElement('a');
newA.id = 'chat' + i;
newA.setAttribute('href', "#");
newA.innerHTML = "Chat" + (i + 1);
newLI.appendChild(newA);
newUL.appendChild(newLI);
}
toAdd.appendChild(newUL)
document.getElementById("menu-list").appendChild(toAdd);
I also have a Div at the top of the page which will display some details about the current chat, but for the time being will simply display the name of the chat, same as on the anchor tags.
Now based on another StackOverflow post the correct way to call a JS function from an anchor tag is
var c0 = document.getElementById("chat0");
//Set code to run when the link is clicked
// by assigning a function to "onclick"
c0.onclick = function(id) {
//Change Title Name here
//Do other stuff in the future
return false;
}
However I could have 20+ chats on the sidebar at any one time, so this seems like a lot of repetitive code to write.
Is there a better way to do this?
Give your chats a general class instead example chat then attach the click event to all the chat's in the same time using .getElementsByClassName().
So you could add className just after newA.id :
newA.id = 'chat' + i;
newA.className = 'chat';
Then attach the click event :
var chats = document.getElementsByClassName('chat');
for (var i=0; i < chats.length; i++) {
chats[i].addEventListener('click', chatClick, false);
}
function chatClick(){
//chat is clicked
//The 'this' object here refer to clicked element
}
You could use .addEventListener() instead of onclick.
NOTE : You can attach the click event directly after node creation :
for(var i = 0; i < 5; i++){
var newLI = document.createElement('li');
var newA = document.createElement('a');
newA.id = 'chat' + i;
newA.setAttribute('href', "#");
newA.innerHTML = "Chat" + (i + 1);
newA.addEventListener('click', chatClick, false); //Attach click event HERE
newLI.appendChild(newA);
newUL.appendChild(newLI);
}
Hope this help.
Yap sure. You can give them all a class and after load just use a simple jQuery code to bind onclick for all of them:
$('a.className').click(function() {
// Your code here
});
Now if the a tags are added after execution of the code you just simply need to call this again or bind to those elements manually.

Categories

Resources