Pass element as argument when creating event via DOM - JS Javascript - javascript

I'm trying to create HTML elements usingn DOM. I need to pass the <li> element to the toogle method as follows:
<ul>
<li onclick="toogle(this)"><a>Some text</a></li>
</ul>
How can I do it?
Current code that doesn't work:
var li = document.createElement("li");
li.onclick = toogle(this);

var li = document.createElement("li");
li.onclick = function () { toogle(this); };

This:
li.onclick = toogle(this);
actually EXECUTES that toogle function, and assigns its return value to the onclick. If you want your function to be called AS the click handler, then it should be
li.onclick = toogle;

The Snippet below demonstrates how to pass an element that was clicked by using event.target. Details are commented in source.
SNIPPET
var li = document.createElement("li");
// Needs to be in DOM before you can click it
document.querySelector('ul').appendChild(li);
// Assigning class for testing
li.className = 'klass';
// Add click event for li
li.addEventListener('click', function(e) {
// event.target is always the element that was clicked
var tgt = e.target;
// Verifying that the li was passed
console.log(tgt.className);
// klass
}, false);
li {
background: #000;
}
<ul></ul>

You can do:
var li = document.createElement("li");
li.addEventListener('click', toogle);
Which will call toogle on click. This is the better way to do it.
and then you can get the element with:
function toogle(e) {
// "e.target" will represent the element
}
Or if you want it your way then you can do:
var li = document.createElement("li");
li.onclick = toogle;
and then you get the element with:
function toogle() {
// "this" will represent the element
}

Related

JQuery removing <li> using onclick event

I have a ul in which I'll add elements using JQuery, I have this
function addElement(e) {
let text = $('#itemToAdd').val();
let newItem = $('<li>' + text + '</li>');
let removeBtn = $('<button onclick = "removeElement">X</button>');
newItem.append(removeBtn);
$('#shoppingList').append(newItem);
$('#itemToAdd').val('');
e.preventDefault();
}
$(document).ready(function() {
$("#addBtn").on('click', addElement);
});
For removing the elements I have this:
function removeElement() {
$(this).parent().remove();
}
The adding function works awesome, but the removing one doesn't.
If you are using onclick then you have to invoke the function with the reference since this won't refer to clicked element(refers to window object most commonly) and based on that remove that element.
Element creation:
let removeBtn = $('<button onclick = "removeElement(this)">X</button>');
Function :
function removeElement(ele) {
$(ele).parent().remove();
}
Or alternately you can use the existing function but bind event handler using jQuery after element creation.
let removeBtn = $('<button>X</button>');
removeElement.click(removeElement);
An another option would be event delegation which helps to handle events on dynamically created elements.

why this addEventListener not working for the li element I create?

I try to implement an aotocomplete input. I want when user clicked new added li element, the input value will be the value of the li element. However, this addEventListener seems not work in this function. May I know why? I think every new li element did create before I add event listener to them.
function displayMatches(matchesArr) {
var newLi;
for (let j of matchesArr) {
newLi = document.createElement('li');
newLi.innerHTML = `<li id="${j.replace(/\s/g,'')}">${j}</li>`;
autoResults.innerHTML += newLi.innerHTML;
document.getElementById(j.replace(/\s/g, '')).addEventListener("click",
function(e) {
alert("Hello World!");
})
}
}
If I use NewLi it also doesn't work.
newLi.addEventListener("click",
function(e) {
alert("Hello World!");
})
The li that you're adding to the DOM is not the same one as newLi. You're creating a brand new element when you assign to .innerHTML. You're also destroying and recreating all the old elements in autoResults. When you assign to .innerHTML it parses the HTML text from scratch, creating all new elements; any properties that were set on the old elements, such as event listeners, are lost.
Instead of assigning to .innerHTML, append the element itself.
function displayMatches(matchesArr) {
var newLi;
for (let j of matchesArr) {
newLi = document.createElement('li');
newLi.id = j.replace(/\s/g, '');
newLi.innerHTML = j;
newLi.addEventListener("click",
function(e) {
alert("Hello World!");
});
autoResults.appendChild(newLi);
}
}

Creating a to do list using (Bootstrap) HTML and pure Javascript

I'm getting started with Javascript and need a little help with creating a simple to do list. I have seen a few questions about this kind of thing on Stack Overflow, but most of them use JQuery or a very different approach than I have taken.
The code successfully takes the input value and dynamically creates content from it, and it also toggles a 'complete' CSS class on-click.
The issue I'm having is that instead of creating a new li for each input task, it will create a new li the first time and then add the new tasks to that li.
(function() { //IIFE
// DOM queries
var item = document.getElementById("input").value; //list item input
var ul = document.getElementById("task-list"); //task list container
var li = document.createElement('li');
li.className = "list-group-item"; //list item created and assigned class
var button = document.getElementById("button") //add item button
// event listeners
// add task on button click
button.addEventListener('click', function(){ //create new list item
li.appendChild(document.createTextNode(input.value)); //get input from form
ul.appendChild(li); //attach task to list
console.log('clicked');
}, false);
// toggle task complete on item click
li.onclick = function(){
console.log('toggle task completion');
li.classList.toggle('complete');
}
}()); //IIFE ENDS
How can I create a new li each time instead of just appending new tasks to the first li created? I'm sure it's a simple fix, I just can't seem to figure it out. Thanks in advance!
You need to create the li and the event listener for each li inside the button click listener:
// DOM queries
var item = document.getElementById("input").value; //list item input
var ul = document.getElementById("task-list"); //task list container
var button = document.getElementById("button") //add item button
// event listeners
// add task on button click
button.addEventListener('click', function() { //create new list item
var li = document.createElement('li');
li.className = "list-group-item"; //list item created and assigned class
li.textContent = input.value;
ul.appendChild(li); //attach task to list
// toggle task complete on item click
li.onclick = function() {
console.log('toggle task completion');
li.classList.toggle('complete');
}
}, false);
.complete { color: green }
<input id="input">
<div id="button">add</div>
<ul id="task-list"></ul>
Though it might be nicer to have only a single listener on the ul, using event delegation, rather than adding another listener each time an item is added:
// DOM queries
var item = document.getElementById("input").value; //list item input
var ul = document.getElementById("task-list"); //task list container
var button = document.getElementById("button") //add item button
// event listeners
// add task on button click
button.addEventListener('click', function() { //create new list item
var li = document.createElement('li');
li.className = "list-group-item"; //list item created and assigned class
li.textContent = input.value;
ul.appendChild(li); //attach task to list
}, false);
ul.onclick = (e) => {
if (e.target.tagName !== 'LI') return;
// toggle task complete on item click
console.log('toggle task completion');
e.target.classList.toggle('complete');
};
.complete { color: green }
<input id="input">
<div id="button">add</div>
<ul id="task-list"></ul>
Just put everything that creates the li into the onclick handler:
(function() { //IIFE
// DOM queries
var item = document.getElementById("input").value; //list item input
var ul = document.getElementById("task-list"); //task list container
var button = document.getElementById("button") //add item button
// event listeners
// add task on button click
button.addEventListener('click', function(){ //create new list item
var li = document.createElement('li');
li.className = "list-group-item"; //list item created and assigned class
li.appendChild(document.createTextNode(input.value)); //get input from form
li.onclick = function(){
console.log('toggle task completion');
li.classList.toggle('complete');
}
ul.appendChild(li); //attach task to list
console.log('clicked');
}, false);
// toggle task complete on item click
}()); //IIFE ENDS
This will make sure that it creates a new li-element every time instead of only once
DOM elements are unique once created. You cannot use the same li created to append new li. You must create a new li every time like this:
(function() { //IIFE
// DOM queries
var item = document.getElementById("input").value; //list item input
var ul = document.getElementById("task-list"); //task list container
//Remove line creating li here
li.className = "list-group-item"; //list item created and assigned class
var button = document.getElementById("button") //add item button
// event listeners
// add task on button click
button.addEventListener('click', function(){ //create new list item
//Placed line here
var li = document.createElement('li');
li.appendChild(document.createTextNode(input.value)); //get input from form
ul.appendChild(li); //attach task to list
console.log('clicked');
}, false);
// toggle task complete on item click
li.onclick = function(){
console.log('toggle task completion');
li.classList.toggle('complete');
}
}()); //IIFE ENDS

javascript click event on dropdown menu

an application I have four dropdwon -menu where one of these is filled by selecting an earlier ... this is filled in automatically ... does not respond to click event
I have searching by answers about creating a dinamic UL LI itens and found this:
function getModelos(response)
{
var obj = JSON.parse(response);
try
{
var ul = document.getElementById("modelo");
var modelos = obj.modelos;
var x = document.getElementById("modelo");
while(x.length > 0)
{
x.remove(0);
}
for(i=0;i<modelos.length;i++)
{
var li = document.createElement("li");
var a = document.createElement("a");
a.appendChild(document.createTextNode(modelos[i].modelo));
a.setAttribute("href","#");
a.setAttribute("data-value",modelos[i].id+",.modelo");
li.appendChild(a);
ul.appendChild(li);
}
}
catch(err)
{
alert("ERRO: "+err);
}
}
also I have found a click event delegating:
$(".dropdown-menu li a").click(function()
{
var selText = $(this).text();
$(this).parents('.dropdown').find('.dropdown-toggle').html(selText+' <span class="caret"></span>');
var valor = $(this).data('value');
var options = valor.split(",");
$(this).parents(".dropdown").find(options[1]).val(options[0]);
if(options[1] == ".marca")
{
pedeModelos(selText);
}
});
all dropdowm-menus previously defined response to click on LI, but this dropdown dinamic created don't
I'm new to javascript/Bootstrap/JQuery, I need a way to follow, I will apreciate any help. thanks
Like this:
$(".dropdown-menu").on("click","li a",function() {blah});
Read about Direct and delegated events
The issue is how you are delegating the click event.
If your delegation is outside the event which is creating the dynamic elements than its not going to work. Your reference to the click event should happen in the same function where you are generating the dynamic html.
For example :
<input type="button" id="btn" value="GenerateHTML"/><br/>
<div>
</div>
$("#btn").click(function()
{
$("div").append("<ul class='dropdown-menu'><li><a href='#'>1</a></li><a href='#'>2</a></ul>");
$(".dropdown-menu").find("li a").click(function()
{
alert();
});
});
http://jsfiddle.net/pkhout3x/

How can I trigger onblur from a ul li?

I am essentially highlighting each li when clicked, and want to "un-highlight" the clicked li when clicking elsewhere or tabbing out (by effecting the background-color property).
This behavior would essentially be emulating <select> in its' highlighting behavior... I'm not using select though, because I want to nest HTML inside the listed items  --  you can't do this with <option>.
I'm attempting to use onblur, which is not working...
Here is the HTML:
<ul id = "list">
<li>asdf</li>
<li>qwerty</li>
<ul>
...here is the CSS:
#list {
list-style-type: none;
}
...and here is the jQuery/Javascript:
function getEventTarget(e) {
e = e || window.event;
return e.target || e.srcElement;
}
function highlightSelection(selection) {
alert("It worked!");
$(selection).css("background-color","#FFFF00");
}
// this function is not being triggered:
function removeHighlight(selection) {
$(selection).css("background-color","none");
}
var ul = document.getElementById("list");
ul.onclick = function(event) {
var target = getEventTarget(event);
highlightSelection(target);
};
// this event is not working:
ul.onblur = function(event) {
var target = getEventTarget(event);
removeHighlight(target);
};
The lis don't blur because they don't focus. Try with mouseout or mouseleave.
Since you're already using JQuery...
<ul id = "list">
<li tabindex="1">asdf</li>
<li tabindex="2">qwerty</li>
<ul>
var ul = $("#list");
ul.on('click focus','li',function(){
$(this)
.css("background-color","#FFFF00")
.siblings().css('background','');
}).on('blur','li',function(){
$(this).css('background','');
});
http://jsfiddle.net/mc4tN/2/
I wasn't sure of what effect you wanted when you tab away from a list item... It seems you would just want to leave it highlighted. You can add focus-ability to your list items by giving them a tabindex attribute.

Categories

Resources