How to add popover to dynamically created list items - javascript

I have the following code. Clicking on the existing list item shows the popover.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Test</title>
<script src="https://cdn.jsdelivr.net/npm/jquery#3.5.1/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.5.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
$(function () {
$('[data-toggle="popover"]').popover()
})
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.0/dist/css/bootstrap.min.css"/>
</head>
<body>
<div class="container">
<div class="card" style="width: 18rem;">
<div class="card-header">
Featured
</div>
<ul id="card-list" class="list-group list-group-flush">
<li id="card-item" class="list-group-item" data-toggle="popover" title="Rule Details" data-placement="top" data-html="true" data-content="<h3>Popover Content</h3>">Cras justo odio</li>
</ul>
</div></br>
<button id="test" type="button" class="btn btn-outline-dark btn-sm">Test</button>
</div>
</body>
</html>
The above code has a Test button to add items to the current list. I use the code below to define new items during which I set popover attributes. New list items can be added but clicking on them doesn't bring up popovers. Please help!
let listItem = document.createElement('li');
listItem.innerHTML = "Test";
listItem.className = "list-group-item";
listItem.setAttribute("data-toggle", "popover");
listItem.setAttribute("title", "Rule Details");
listItem.setAttribute("data-placement", "top");
listItem.setAttribute("data-html", "true");
listItem.setAttribute("data-content", "<strong>test Hello World</strong>");
document.getElementById("card-list").appendChild(listItem);

You have to initialize popover on the newly created elements. Since popover is a jQuery plugin convert your element to jQuery object and apply popoper before appending like:
let listItem = document.createElement('li');
listItem.innerHTML = "Test";
listItem.className = "list-group-item";
listItem.setAttribute("data-toggle", "popover");
listItem.setAttribute("title", "Rule Details");
listItem.setAttribute("data-placement", "top");
listItem.setAttribute("data-html", "true");
listItem.setAttribute("data-content", "<strong>test Hello World</strong>");
listItem = $(listItem);
listItem.popover();
$("#card-list").append(listItem);

Related

jQuery load executes but callback is not executed

I am kinda new to website development, so I am asking for some help on the matter. I have the following snippet of html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!--CSS Styles -->
<link rel="stylesheet" href="../assets/css/styles.css"/>
</head>
<body>
<!--Navigation bar-->
<div id="nav-placeholder"></div>
<!--end of Navigation bar-->
</body>
<script src="../assets/js/navigation_bar.js" type="text/javascript", locator="about"></script>
</html>
It calls the navigation_bar.js script provided here
locator = document.currentScript.getAttribute('locator');
function changeActiveElement(element_id){
console.log("Called");
nav_element = document.getElementById("navigation");
for (i = 0; i < nav_element.length; i++) {
console.log(nav_element[i].id)
if(nav_element[i].id == element_id) document.getElementById(element_id).className = "active-nav-link";
else document.getElementById(element_id).className = "nav-link";
}
}
$(function()
{$("#nav-placeholder").load("/assets/html/nav.html", function(){
changeActiveElement(locator);
});}
);
whereas the nav.html file is here:
<nav>
<h1>Some name</h1>
<ul id="navigation" class="navigation">
<li><a id="about" href="/pages/about.html" class="nav-link">About</a></li>
<li><a id="compt" href="#compt" class="nav-link">Competences</a></li>
<li><a id="projects" href="#projects" class="nav-link">Projects</a></li>
<li><a id="contact" href="#contact" class="nav-link">Contact</a></li>
</ul>
<button class="burger-menu" id="burger-menu">
<ion-icon class="bars" name="menu-outline"></ion-icon>
</button>
</nav>
The scope of the snippet is to change the class of the a tags listed in the navigation element. The navigation bar is correctly loaded via $("#nav-placeholder").load("/assets/html/nav.html"), yet changeActiveElement function is never executed via the callback.
Can someone explain me this behaviour?
I tested your code and everything is working except that nav_element is not a list and therefore nav_element.length throws an error. You could use document.querySelectorAll("#navigation"); instead, which returns a node list of all selected elements. Although, I would not recommend doing a for loop on elements by id. Use classes to select the elements. Id is only for one element.

I want to make a todo list but I am stuck at the start, where am I going wrong in this code?

I want to add li to the ul element with the value entered by user in the input area.
This is the error I am getting in console:
[Error] TypeError: document.getElementsByClassName("list-group").appendChild is not a function. (In 'document.getElementsByClassName("list-group").appendChild("li")', 'document.getElementsByClassName("list-group").appendChild' is undefined)
additem (script.js:7)
//this is my javascript code-->
function additem() {
var task = document.getElementsByClassName("input-group-text").value;
var li = document.createElement("li");
li.classList.add("list-group-item");
li = "task";
document.getElementsByClassName("list-group").appendChild("li");
}
document.getElementById("button").addEventListener("click",additem);
//<--!this is my html code-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>LearnCodeOnline</title>
<link rel="stylesheet" href="./style.css" />
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
/>
</head>
<body class="bg-dark">
<div class="container bg-warning p-4">
<h1 class="text-center">LearnCodeOnline</h1>
<div class="input-group">
<span class="input-group-text">todo</span>
<textarea class="form-control" aria-label="With textarea"></textarea>
</div>
<button id="button" class="float-right">Add</button>
<ul class="list-group">
<li class="list-group-item">An item</li>
</ul>
<!-- <button
type="button"
class="btn btn-success btn-lg mt-4 mx-auto d-block sort-btn"
>
Sort courses
</button> -->
</div>
</body>
</html>
JS:-
function additem() {
var task = document.getElementsByClassName("form-control")[0].value;
var li = document.createElement("li");
li.classList.add("list-group-item");
li.innerText = task;
document.getElementsByClassName("list-group")[0].appendChild(li);
}
document.getElementById("button").addEventListener("click",additem);
Instead of doing .appendChild("li"), we'll give it an element and not string as it takes the element and not string
getElementsByClassName() returns an array so we will take the item at 0th index of the array in both the functions where it is there
also instead of setting li = "task" like this, we'll have to set its text by li.innerText = task

todos list with a saved array and then retrieve it stuck?

i started an app todoslist , after creating first code simply of adding new todos in DOM
now my task is this :
addtodo :
// grab todo value
// pu tit in the array
// tell the draw method to redraw the todos
drawtodo :
grab the array
for each text add a todo entry in the documen
the array
my html code
<!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="stylesheet" type="text/css" href="style.css">
<title>TodoList</title>
</head>
<body>
<div class="todolist_box">
<h3> To Do List </h3>
<div class="input">
<input type="text" id ="inp" placeholder="Add new Task">
<button onclick="newTodo()" ><i> enter </i></button>
<button onclick="newTodo()" ><i> save </i></button>
<button onclick="drawtodo()" ><i> load </i></button>
</div>
<ul id="myUL">
</ul>
</div>
<script src="script.js" type="application/javascript"></script>
</body>
</html>
and this is my javascript code
function newElement() {
// this code doesn't work, but it gives you an idea
const li = document.createElement("li")
const newEntry = document.getElementById("inp").value
const u = document.createTextNode(newEntry)
li.appendChild(u)
document.getElementById("myUL").appendChild(li)
document.getElementById("inp").value = "Nothing"
// something like thi
let todos = []
function newTodo() {
let inpvalue = document.getElementById('inp').value
todos.push(inpvalue)
// trigger draw event
}
function drawtodo() {
for (var i = todos.length - 1; i >= 0; i--) {
let li = document.createElement('li')
let newlist = li.appendChild(document.createTextNode(todos[i]))
inpvalue.appendChild(newlist)
}
}
document.onload = function() {
// this will excute when the document loads
}
}
Try using Javascript event listener instead of onclick attribute in html.
HTML:
<button id="load" ><i> load </i></button> // Removed onclick attribute
JS:
document.getElementById("load").addEventListener("click", drawtodo, false);
same with enter and save buttons, when click triggers the newTodo function.

How to get my text to appear under tasks after I click "add task"?

I'm trying to add customize text to my "task" and when I click add text button in my "task list" it only appears in the address bar. The objective is to create a list item under "task list" once I click add task. The first block of code is my app.js file and the following block of code is my index.html file.
//Load all event listeners
loadEventListeners();
// Load all event listeners
function loadEventListeners() {
// Add task event
form.addEventListener('submit', addTask);
}
// Add task
function addTask(e) {
if(taskInput.value === '') {
alert('Add a task');
}
// Create li element
const li = document.createElement('li');
// Add class
li.className = 'collection-item';
// Create text node and append to li
li.appendChild(document.createTextNode(taskInput.value));
// Create new link element
const link = document.createElement('a');
// Add class
link.className = 'delete-item secondary-content';
// Add icon html
link.innerHTML = '<i class="fa fa-remove"></i>';
// Append the link to li
li.appendChild(link);
// Append li to ul
taskList.appendChild(li);
// Clear Input
taskInput.value = '';
e.preventDefault();
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<title>Task List</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col s12">
<div id="main" class="card">
<div class="card-content">
<span class="card-title">Task List</span>
<div class="row">
<form id="task-form">
<div class="input-field col s12">
<input type="text" name="task" id="task">
<label for="task">New Task</label>
</div>
<input type="submit" value="Add Task" class="btn">
</form>
</div>
</div>
<div class="card-action">
<h5 id="task-title">Tasks</h5>
<div class="input-field col s12">
<input type="text" name="filter" id="filter">
<label for="filter">Filter Tasks</label>
</div>
<ul class="collection"></ul>
Clear Tasks
</div>
</div>
</div>
</div>
</div>
<script
src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<script type="app.js"></script>
</body>
</html>
Just a few modifications:
const btn = document.querySelector('.btn');
const taskInput = document.getElementById('task');
const taskList = document.querySelector('.container ul');
btn.addEventListener('click', addTask);
// Add task
function addTask(e) {
if(taskInput.value === '') {
alert('Add a task');
}
// Create li element
const li = document.createElement('LI');
// Add class
li.classList.add('collection-item');
// Create text node and append to li
li.appendChild(document.createTextNode(taskInput.value));
// Create new link element
const link = document.createElement('a');
// Add class
link.classList.add('delete-item' , 'secondary-content');
// Add icon html
link.innerHTML = '<i class="fa fa-remove"></i>';
// Append the link to li
li.appendChild(link);
// Append li to ul
taskList.appendChild(li);
e.preventDefault();
}
document.querySelector('.clear-tasks').addEventListener('click',()=> {
// Clear Input
taskInput.value = '';
});

forEach method not setting style property for list items

Here is app.js
const listItems=document.querySelector(".student-list").children;
const numberOfItems=10;
const page=document.querySelector(".page");
displayPage=(list,pageNumber)=> {
const SI=(pageNumber*numberOfItems)-numberOfItems
const EI=pageNumber*numberOfItems
Array.of(list).forEach((item,index)=> {
if (index>= SI && index<EI) {
item.style.display="block";
} else {
item.style.display="none";
}
})
}
addPaginationLinks=(list)=> {
const pages=list.length/10
let html=``
for (let i=0; i<pages; i++) {
html+=`
<li>
<a class="active" href="#">${i+1}</a>
</li>`
return html
}
ul=document.createElement("UL");
ul.innerHTML=html;
div=document.createElement("DIV");
div.className.add("pagination");
div.appendChild(ul);
page.appendChild(div);
}
displayPage(listItems, 1);
addPaginationLinks(listItems);
Here is a sample of index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Students</title>
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/design.css">
</head>
<body>
<div class="page">
<div class="page-header cf">
<h2>Students</h2>
<!-- dynamically insert search form here (optional) -->
</div>
<ul class="student-list">
<li class="student-item cf">
<div class="student-details">
<img class="avatar" src="https://randomuser.me/api/portraits/thumb/women/67.jpg">
<h3>iboya vat</h3>
<span class="email">iboya.vat#example.com</span>
</div>
<div class="joined-details">
<span class="date">Joined 07/15/15</span>
</div>
</li>
</ul>
There's no error in the html, it just continues down with more and more li's, and then closes up with a ul and a closing div tag. Then the script app js appears later.
I'm getting an Uncaught TypeError: Cannot set property 'display' of undefined Array.forEach
Basically, it's not recognizing each item in the list in the for each loop. Why is that? When I console log the items, the HTML collection shows up.

Categories

Resources