Can someone please explain my function deleteButton(this)? - javascript

Here is the link to my codepen to see all my code: http://codepen.io/stevengangano/full/LGvRdq/
My question has to do with my deleteButton function. I have trouble grasping this concept.
I created a function for the delete button called deleteButton(item). I just want to know what does "item" and "parentNode" represent in the variable remove? Which one is the <ul> and which one is the <li>?
An explanation would be appreciated. Thanks!

deleteButton(item) is attached to the removeButton. this represents the current node which is button itself.
item.parentNode will be nothing but parent of the button which is li element. remove variable holds this li element.
Again remove.parentNode will return parent node of the li element which is ul element.
paretNode.removeChild removes a child node from the DOM
So in this case, UL_ELEMENT.removeChild(LI_ELEMENT);

function deleteButton(item) {
var remove = item.parentNode;
remove.parentNode.removeChild(remove);
}
in your code (posted offsite) is long for
function deleteButton(item) {
item.parentNode.parentNode.removeChild(item.parentNode);
}
which removes the parent node of the clicked item from its grandparent node's list of children. The parent node of the delete button is listItem in code, which means an LI item will be deleted.
Elsewhere in code posted offsite (bad practice™) the delete function is defined as
removeButton.setAttribute('onclick', 'deleteButton(this);');
which is seriously really very, interesting. It suggests that setting an onclick attribute with text, after HTML parsing has been completed, causes the text to be parsed as source for a javascript function which becomes the attribute value. Okay, so a setter can do this - but onEvent setters doing this is news to me. And testing indicates it being true.
So an answer is that setting the onclick attribute of a node with text compiles the text to a function object, attaches the function object as the onclick attribute value, which when called by clicking supplies the node being clicked on as the this object for the onclick handler. If the function called removes the parent node of the clicked object, in this case an LI element gets removed.

Related

How to set up remove item buttons in vanilla-typescript todo app

I am creating a basic todo list app using vanilla typescript. After appending buttons to each list item, I want the items to delete when the user clicks the button on a specific list item. To execute this, I tried adding a 2nd addEventListener method in index.ts to listen for remove button clicks, then remove the child of the parent element. My addEventListener method looks like this:
listItemBtn.addEventListener("click", (e: Event) => {
const element = e.target as HTMLUListElement;
element.removeChild(element);
});
However, I keep getting an error in the console that says "Uncaught TypeError: Cannot read property 'addEventListener' of null". I am not sure why I can't append .addEventListener to listItemBtn without errors. Any idea how to fix this?
Here is a link to the project in CodeSandBox: https://codesandbox.io/s/vanilla-typescript-forked-xnnf4
You are looking for the listItemBtn before it exists. If you add this line
document.querySelectorAll("#listItemBtn").forEach(console.log);
at the end of your form.addEventListener then you'll start to see it populating with elements.
There's a lot that needs to change in this code. Be cautious with using as because it prevents Typescript from seeing potential runtime errors, like that an element might be null.
Your question is how to set up the remove buttons, so I don't actually think that querySelectorAll is the correct way. I would add the listener where you create btn. At that point you already have the button element as a variable.
Your listener function itself has problems. Again you have a troublesome as in const element = e.target as HTMLUListElement; because the target is the button, not the li.
element.removeChild(element) is wrong because you need to be calling removeChild on the parent, like parent.removeChild(child). You can look as element.parentElement (which might be null). Since we are moving this function into ListTemplate then we have access to the parent li variable. The element that we want to remove is the li from the ul. So actually our e.target which is btn isn't very useful.
Inside the render method of ListTemplate, do this:
btn.addEventListener("click", () => {
this.container.removeChild(li);
});
As mentioned in the comments, you should not set an id which is not unique. You could use className instead:
btn.className = "listItemBtn";
But you only need that for styling. We no longer query this element anywhere.
You can clean up your form submit listener. There is no reason to create a variable and then assign it. Just assign it directly. This also removes the need to manually specify types because the type is known from the value that you set to the variable.
form.addEventListener("submit", (e) => {
e.preventDefault();
const value = listItem.value;
const doc = new ListItem(value);
list.render(doc, value, "start");
});

Does element.appendChild(node) applies properties of parent node to child node?

I am new to HTML and JS.
Need to create dynamic expand-collapse list.
var parentId = document.getElementById("ABCD")
parentId.setAttribute("data-toggle","collapse")
parentId.setAttribute("data-target","#collapse1")
var tag = document.createElement("ul");
tag.setAttribute("id","collapse1")
tag.appendChild(document.createTextNode("PQR"))
parentId.appendChild(tag)
Trying for list as-
ABCD
PQR
So in this case, when i am clicking on ABCD, PQR gets expanded/collapsed.
But the problem is on clicking on PQR, it gets collapsed again.
So does the properties of parent gets applied to child node also?
it's not that it gets properties of it's parent, this has to do with how events handled, specifically event bubbling. When you click a child element, a click event if fired for all parent elements of what you clicked on
to cancel the event from bubbling when you click the appended elements you need to event.stopPropagation() inside of a click handler for the new elements
after you append them do the following
// tag.appendchild code goes here, then do the following
document.querySelector("#collapse1").onclick=function(event){
event.stopPropagation();
}
also, i should mention all this would be 10 times easier with jQuery

Getting String Value Of JavaScript Button

I have a list of buttons that is created by the DOM which references an array. When a button in the list is clicked, I want to retrieve the String that is displayed on the Button.
I have tried the following code to reference the string value, but get undefined:
this.String; inside the function when the button is clicked to retreive the string.
How can I properly retrieve the string.
The click handling function is:
$('.timeButtons').click(function() {
confirmation.push(this.textContent);
})
This is how the list of buttons is created:
var populateList=function(array){
var list = document.createElement('ul');
list.className="delete";
for(var i = 0; i < array.length;- i++) {
var item = document.createElement('li');
var itemButton=document.createElement('button');
itemButton.style.cssText='background:#f85a5a; border:none; width:200px; height:50px; margin-bottom:50px; align:center; border-radius:25px; color:#ffffff;'
itemButton.appendChild(document.createTextNode(array[i]));
item.appendChild(itemButton);
list.appendChild(item);
}
return list;
}
Assuming that this is a reference to the button element in question, you can use this.textContent to get the button's text. (Or .innerHTML.)
Demo: http://jsfiddle.net/w0ntsrLx/
Or since in your edited question you seem to be using jQuery, use the .text() method. In a comment you say that the containing div has the "timeButtons" class, so bind a delegated handler to that div as follows:
$(".timeButtons").on("click", "button", function(e) {
confirmation.push($(this).text());
});
Demo: http://jsfiddle.net/w0ntsrLx/1/
That way the function will only be called if the click is on a button element within the .timeButtons div, and this will be the clicked button. The click handler that you show in your question with $(".timeButtons").click(...) is bound to the div and doesn't in any way test for the buttons, so within the handler this will be the div, not the clicked button.
Check this out
Assuming you want pure javascript code,
Whenever an event is triggered, an object is passed back in callback (generally being named as 'event'). this object has many properties including source element, position of click and many more.
get the element using event.srcElement
You can use element.innerHTML or element.innerText to find out the content of the Button.
There is a difference between using innerText and innerHTML, but in your case, both can be used.
Also, you can use jquery too to easily append child, create elements and binding events.

Using focus on elements inside contenteditable div?

I am trying to use the following code to reference anything focused inside my contenteditable div, which has an id of rt:
var lastfocused;
$("#rt *").focus(function () {
lastfocused = $(this);
});
For some reason, lastfocused always equals $("#rt");, but never anything else which may be inside the contenteditable div. How do I make it so that anything focused inside the contenteditable div will be stored in the lastfocused variable?
Looks like your problem is elsewhere. The above code perfectly works for me:
http://jsfiddle.net/8hZWq/
EDIT
If the children elements aren't inputs as you said, but divs - the focus() method is not applicable to them, as it works only for input, textareas, select etc.
You can also use .click() instead of focus() to store the reference to the last clicked element. Bear in mind though, it also depends to the structure of your elements.
For example if you have multiple levels of containers within children divs, the #ID * selector will actually trigger multiple times each level of children starting from the #ID.
If you like to store reference to only the first level of children of the #ID, you should use #ID > * selector to refer only direct children.
If you like to store the reference to only the very element that was clicked upon regardless of it's level in relation to the container, you should use click event target reference instead:
var clicked;
$('#ID').click(function(event){
clicked = $(event.target);
});
Indeed your problem is because of variable declaration out of the function. Setting it in, in each focus event the 'lastfocused' variable will be re-assigned.
I came later, but if i arrive here someone else can.
Do this:
$("#rt *").focus(function () {
var lastfocused = $(this);
});

jQuery appending li to ul unclickable

i have the following code that adds data to unordered lists. The troublesome code is as follows:
$('li:not(:first-child)').click(function() {
var clickedLi = this;
$(this).parent().prepend(clickedLi);
var selectedLi = $(this).text();
alert(selectedLi);
$(this).parent().parent().nextAll().children('ul').children().replaceWith('<li>Please select</li>');
//ajax call
var returnedData = "<li>Dataset1</li><li>Dataset2</li><li>Dataset3</li>";
//populate next with returned data
$(this).parent().parent().next().children('ul').append(returnedData);
});​
If you click on one of the options in the first ul, data gets added to the second ul. However, the list items under this ul are not clickable, and I need them to be so, so that 'chain' can be continued.
Where is the bug? Any help would be much appreciated. Thanks in advance.
Try with: (if you use jQuery greater than 1.6.8. )
$(document).on('click','li:not(:first-child)',function() {
http://api.jquery.com/on/
I can suppose, judging by your code, that you expect the freshly added li to inherit the behaviour you append to the existing ones. Unfortunately it cannot work with the code written that way.
You need to attach the click event in an "observable" way so newly added elements to the dom will get the event handler attached.
To do this, you must use the .on method. You can check its reference here

Categories

Resources