setAttribute "value" returns undefined - javascript

I am dynamically (but not async) building html elements with js and encounter an error upon setting the "value" attribute.
Simplified code:
let tag = document.createElement("div");
tag.innerHTML = `${item}`;
tag.setAttribute("value", `${item}`);
tag.classList.add("newtags", "lot of css classes")
tagslist.appendChild(tag)
newtags = Array.from(document.querySelectorAll('.newtags'))
newtags.forEach(item => {
item.addEventListener("click", e =>{
console.log(e.target.value)
})
})
Upon clicking on the created tags I get "undefined" yet if I do console.log(e.target) without adding value I can see it is working and the value is there. Am I setting something that isn't really the value of the element?
Thanks

Div elements don't have value attributes. Only form controls (like input and button elements) do.
You could use a data attribute for this but div elements aren't designed to be interactive.
You are adding a click event handler but screen readers won't tell the user they can click on them, and people navigating with a keyboard will skip right past them since you haven't done anything to allow them to be focused.
Use a button instead of a div. Apply CSS as desired.

div element doesn't have value property. only few elements such as input, textarea have value
https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes

I think you want to add attribute data-value to the div as div element doesn't have a value attribute.
tag.setAttribute("data-value", `${item}`);
Then when you try to get the div data value.
console.log(e.target.dataset.value)

Related

How to grab the h3 text within a div

My website HTML has the following:
To grab the H3 text (SOME TEXT) as a variable in Tag Manager - when a user clicks on the div class "c-card c-card--primary c-parkcard " I think I need to use a DOM Element variable
But it's not returning the text.
Should the Element Selector be:
.c-card.c-card--primary.c-card__body.u-h6.c-card__title
However, it returns a null value in Tag Manager
The solution was to create a custom JS variable that when the image was clicked on would find the "c-card c-card--primary c-parkcard " div (9 parents up) and then go back down to find the h3 element by class and then return the text:
function(){
var z = {{Click Element}}.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode
.getElementsByClassName('u-h6 c-card__title')[0].innerText;
return z;
}
use of getElementsByClass is as simple as:
$dom = new DOMDocument('1.0', 'utf-8');
$dom->loadHTML($html);
$content_node=$dom->getElementByClass("c-card__body");
$div_a_class_nodes=getElementsByClass($content_node, 'h3', 'u-h6 c-card__title');
You have set "h3" as "attribute name. "h3" is not an attribute (but the name of the tag). You do not want to set an attribute name at all, because you do not want to return the value of an attribute, but the innerText of the tag, and that is the default behaviour anyway.
If you use a DOM variable this will return the first instance on the page. If your selector matches several DOM nodes, you will still just get the first one, regardless if what the user clicks. If you expect this to update depending on the clicked element, you should rather use the {{Click Text}} variable (a built-in variable that you might have to enable first).
Chances are that the actual click element is not the h3, but the nested link inside, but that does not really change things for you (as in both cases the innerText will be the contained texted nodes, which in this case is the same).

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");
});

How to find the top parent element of a text selection?

I have many contenteditable div.
When I select a text by hightlighting inside a contenteditable div, I want to retrieve the contenteditable div element.
For exemple :
<div contenteditable="true">
Hello World,
<i>this is <b>a dog</b> in the garden</i>
Thank you very much
</div>
So when I select the text "dog" by highlighting, I want to retrieve the contenteditable div element in order to know which contenteditable div I have used.
An idea ?
Edit :
I made this code, but it's not perfect :
var selection = window.getSelection();
var node = selection.anchorNode;
for(var i = 0; i < 50; i++)
{
node = node.parentNode;
if(node.getAttribute("contenteditable") == "true")
{
console.log("found");
break;
}
}
I think previous answers are over-complicating matters.
This is the same whether you select text or just click on an element.
You need to be able to identify the current element that you have clicked on or pressed a key on (otherwise I don't see how you can make contenteditable work sensibly).
Assuming you can do this, all you need to do is go back from CurrentElm to the parent that has the contenteditable attribute with a while loop -
while (Elm.contenteditable != true) {Elm=Elm.parent}
I confess to not providing full programming details, but I can if you need them.
The first issue is to be able to identify the CurrentElm on mouseclick or keypress.
If you can't do this, then get back to me and I'll explain - the rest then becomes easy.
You need an event to fire after the text is highlighted. Unfortunatley, there isn't a onhighlight event so you must use something like onmouseup.
Next, you need a way to add event listeners to all your contenteditable divs. One way to use this is document.querySelectorAll(). But you may find it easer to add one event listener to the "parent" of these divs and continue on with the directions below.
The event listener for mouseup will provide an event object. See https://developer.mozilla.org/en-US/docs/Web/Events/mouseup. This object has the value currentTarget which will give you the element where the mouseup event occured, which in turn is the element where the highlighting took place.
This question seems to have already been asked:
javascript to get paragraph of selected text in web page
Here is another example:
http://www.codetoad.com/javascript_get_selected_text.html

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);
});

Categories

Resources