remove element javascript with classename - javascript

when I remove this with id it works but when I tried with className it didn't work
const remov= document.createElement('a');
remov.classList='clsx';
remov.textContent='X';
remov.setAttribute("id", "Div1");
remov.onclick = function (){
document.getElementById('Div1').remove(); }
this is my code im trying to remove the element that i've created with id 'Div1' emphasized text
const lista = document.getElementById('list');
eventlisteners();
function eventlisteners(){
document.querySelector('#form').addEventListener('submit', yrlist);
}
//function
function yrlist(e){
e.preventDefault();
var textare =document.getElementById('textar').value;
const li= document.createElement('li');
li.textContent=textare;
li.classList='clsli';
li.setAttribute("id", "Div1");
const remov= document.createElement('a');
remov.classList='clsx';
remov.textContent='X';
remov.setAttribute("id", "Div1");
remov.onclick = function (){
document.getElementById('Div1').remove();
}
li.appendChild(remov);
lista.appendChild(li);
}

Note that getElementById returns single element while getElementsByClassName returns list of elements. So you need to iterate through this list. And remove each element.
For example you can do this using loop:
const elements = document.getElementsByClassName("clsx");
for(var x=0; x < elements.length; x++) {
elements[x].remove();
}

remov.classList = 'clasx'; is just wrong. The classList member is actually a DOMTokenList, not a string. As such, it has functions of it's own. Rather than trying to set this member, you need to use the add function it contains.
I.e
remov.classList.add('clsx');
It seems that clicking on the element will have the effect of removing it. This is functionality you've given it at creation time. There's a better way to go about this. Rather than trying to find the element, (which must be identifiable in some manner) why not just have the element remove itself? If you connect the action and the event using AddEventListener, rather than by overwriting a member of the element yourself, a neat thing happens - the function that gets called behaves as though it was a part of the element that triggered it, and so the this keyword refers to itself. It's a huge help, but for the uninitiated, can be a real headache.
const removeMe = document.createElement('a');
removeMe.classList.add('clsx');
removeMe.textContent = 'X';
removeMe.addEventListener('click', function(evt){ this.remove(); }, false);
li.appendChild(removeMe);

Related

Alter unappened element's html tag type with javascript

So I have an element created by another process, created in a method akin to
var their_element = document.createElement("div");
/* Lots of stuff is done to their_element */
And that object is being passed to me later. It has not been appended anywhere yet. The problem is, I need it to be different html tag type when it finally hits the html, such as:
<form></form>
How do i change it? The solutions I have found involve editing after it's appended, not before.
Edit:
Also, learned nodeName can't be assigned for this.
their_element.nodeName = "FORM"
doesn't work.
Also, this doesn't work either:
their_element.tagName = "FORM"
Also this didn't work either:
var outside = their_element.outerHTML;
outside = outside.replace(/div/g, 'form');
their_element.outerHTML = outside;
All of these still leave it as a DIV when appended.
(And I'm not looking for jQuery)
Check on this for cross-browser compatability, but there are properties and methods on elements that could be of use. Particularly, Element.attributes, Element.hasAttributes(), and Element.setAttribute(). See: https://developer.mozilla.org/en-US/docs/Web/API/Element/attributes
I'm not going to use ES6 here, so we don't have to worry about transpiling. You can update if you want:
var el = document.createElement('div');
el.id="random";
el.style.background="red";
el.style.width="200px";
el.style.padding="10px";
el.style.margin="10px";
el.innerHTML="<input type='submit' value='submit'>";
console.log({"Element 1": el});
var newEl = document.createElement('form');
console.log({"Element 2 Before Transformation": newEl})
if (el.hasAttributes()) {
var attr = el.attributes
for (var i = 0; i < attr.length; i++) {
var name = attr[i].name, val = attr[i].value;
newEl.setAttribute(name, val)
}
}
if (el.innerHTML) { newEl.innerHTML = el.innerHTML }
console.log({"Element 2 After Transformation": newEl})
document.body.append(el);
document.body.append(newEl);
There are certain properties you need to account for like innerHTML, innerText, and textContent that would overwrite one another if multiples are set. You may also have to account for childNodes and what not.

getElementsByClassName isn't returning all elements

I'm creating a button that I should highlight certain words within a specified class, but I am having issues with it returning all elements within the class. It will only work if I specify an index, so I'm assuming there may be something wrong with the existing "for loop". Any help is appreciated!
This will work, but only "highlights" the first element in the class, of course:
var bodyText = document.getElementsByClassName('test')[0].innerHTML;
for (var i = 0; i < searchArray.length; i++) {
bodyText = doHighlight(bodyText, searchArray[i], highlightStartTag,
highlightEndTag);}
document.getElementsByClassName('test')[0].innerHTML = bodyText;
return true;
This will not work at all:
var bodyText = document.getElementsByClassName('test').innerHTML;
for (var i = 0; i < searchArray.length; i++) {
bodyText = doHighlight(bodyText, searchArray[i], highlightStartTag,
highlightEndTag);}
document.getElementsByClassName('test').innerHTML = bodyText;
return true;
If you want to replace multiple words in multiple elements, you need two loops:
const testElements = document.getElementsByClassName('test');
for (const element of testElements) {
for (const search of searchArray) {
element.innerHTML = doHighlight(element.innerHTML, search, highlightStartTag, highlightEndTag);
}
}
As you can see getElementsByClassName is pluralized (Elements). Indeed a same class can be assigned to multiple HTML elements. You won't find any way to ommit the [0] and you shouldn't anyway as it might mean you're getting data from the wrong node. If you need data from a specific element that you can ensure is unique then you need to give it an id and use getElementById instead.
You cannot access innerHTML in something which returns an htmlcollection
document.getElementsByClassName('test').innerHTML
Because it's written in plain english: getElementsByClassName. plural.
"Elements".
with an "s" at the end...
meaning it's a (sort of) Array (an htmlcollection)

JS: I can't get the inner HTML of elements with a specific class name

I'm trying to create a calculator out of javascript to work on my skills. I've added the class num to all of my buttons that have a number.
I'm trying to display to display the innerHTML of those buttons in the console when I click them with this code:
var num = document.getElementsByClassName('num');
num.addEventListener('click', getNum);
function getNum(){
console.log(num.innerHTML);
}
getNum();
However all I get is
num.addEventListener is not a function.
Here is my codepen: https://codepen.io/teenicarus/pen/wrEzwd
what could I be doing wrong?
You need to change the code like below. getElementsByClassName returns collection of elements. Loop through the elements and add click event listener. In getNum, you can use this to get access to the button clicked.
var num = document.getElementsByClassName('num');
for (var i = 0; i < num.length; i++) {
num[i].addEventListener('click', getNum);
}
function getNum(){
console.log(this.innerHTML);
}
You can also use Array forEach like the following:
[].forEach.call(num, function(el){
el.addEventListener('click', getNum);
})
getElementsByClassName returns a collection of elements, not a single element. If you want to get single element assign it an id attribute and use getElementById. This way you can use addEventListener function
Here's a solution you can plug directly in your codepen:
var nums = document.getElementsByClassName('num');
[].forEach.call(nums, num => num.addEventListener('click', numClick));
function numClick(){
// adding + turns the text into an actual number
console.log(+this.innerHTML);
}
getElementsByClassName() returns an HTMLCollection, to iterate over it you can pass it to [].forEach.call() like I showed above.
I also renamed the handler to numClick, since it doesn't "get" the number. And added +, which is a nice shortcut to turn text into a number (otherwise, adding two numbers would yield unexpected results, like "1" + "2" => "12"
The .getElementsByClassName returns not an element, but a collection of them.
You can access elements using .getElementsByClassName(num)[element's sequential number], or better use id's and getElementById method.
Here is the modified code for your desired output.just copy and try:
var num = document.getElementsByClassName('num');
//num.addEventListener('click', getNum);
for (var i = 0; i < num.length; i++) {
num[i].addEventListener('click', getNum);
}
function getNum(){
document.getElementById('result').innerHTML+=this.innerHTML;
console.log('value:'+this.innerHTML);
}
//getNum();
As you tagged Jquery to your question I suppose that you are able to use Jquery as well. You can grab the clicked element's class and referance it with 'this' to get its text.
$('.num').click(function(){
var x = $(this).text();
console.log(x);
});
This is a working example you can check the console.log DEMO

Detect child node number

I'm trying to add a event listener for clicking and I want to know the position of the node that was clicked
function evl(etna) {
document.addEventListener("click", function (el) {
alert("You clicked on " + 'the name of element that was clicked or his array code');
}, false);
};
where etna is:
document.getElementsByTagName("*");
function evl(etna){
document.addEventListener("click",function (el) {
var clickedElement = el.target || el.srcElement;
alert("Link detected a click. Cancellable: "+clickedElement.name);
for(var i = 0; i < etna.length; i++) {
if(etna[i] === clickedElement) {
//i is a position of an element in etna
break;
}
}
},false);
};
You can use this which will point to a clicked element. As to Phil H IE 8 does not work that way. But anyway, there should be used .target or .srcElement. And maybe it will be better to get its id. Name attribute is not valid for divs, spans, etc.
But also you are attaching an event to a document. And this will point to a document.
Instead of that you should use el.target || el.srcElement where .target/.srcElement is a pointer to a node where click actually happened.
Also, I do not think you can get index of an element in array (actually, node list) returned by document.getElementsByTagName("*") (well, you can get that list and iterate through it in loop and check each element if it is eaqual to this). Plus, I have no idea why it could be needed.
Add a loop and set the event listener differently for each item in the etna array:
function evl(etna){
for(var i=0; i < etna.length; ++i) {
(function() {
var thisNode = etna[i];
var localval = i;
etna[i].addEventListener("click",function (el) {
alert("Link detected a click. Cancellable: "+ thisNode.id + " which is id " + localval );
},false);
})();
}
}
Working jsfiddle: http://jsfiddle.net/5xDjE/
The function that is immediately called is merely to force the scoping of thisNode and localval, otherwise all the elements get references to the same variable (javascript scoping is interesting).
I would advise against using the index (scoped via localval) because it requires retaining the original array of nodes. Since nodes change over time and javascript does reference counting for you, you want to avoid these kinds of long arrays of nodes.
Note that this doesn't always have element that was clicked, in IE8 and below this points to the global window object.

Using JavaScript & jQuery in a single function (Nodes & Stuff)

I am currently learning jQuery. I know that jQuery is a custom library for JavaScript.
I am doing some learning examples in a book that is only using JavaScript, and to further my learning experience, I am trying to make use of jQuery for anything that might be more efficient.
So, I have this code:
function addLetter(foo) {
$(foo).unbind('click');
var tileLetter = $(foo).attr('class').split(' ');
var letter = tileLetter[2].charAt(1);
if (document.getElementById('currentWord').childNodes.length > 0) {
$('#currentWord p').append(letter);
} else {
var p = document.createElement('p');
var txt = document.createTextNode(letter);
p.appendChild(txt);
$('#currentWord').append(p);
}
}
Question #1:
If I change document.getElementById('currentWord').childNodes.length to $('#currentWord').childNodes.length it doesn't work. I thought the jQuery selector was the same thing as the JS document.getElementById as that it brought me back the DOM element. If that was the case, it'd make sense to be able to use the .childNodes.length functions on it; but it doesn't work. I guess it's not the same thing?
Question #2:
The code is textbook code. I have added all the jQuery that there is in it. My jQuery knowlede is limited, is there a more efficient way to execute the function?
The function's purpose:
This function is supposed to create a p element and fill it with a Text Node if it's the first time it's run. If the p element has already been created, it simply appends characters into it.
This is a word generating game, so you click on a letter and it gets added to a 'currentWord' div. The tile's letter is embedded in the 3rd css class, hence the attr splitting.
Thanks!
document.getElementById('currentWord')
returns a DOM object whereas $('#currentWord') returns a DOM object wrapped inside a jQuery object.
To get the plain DOM object you can do
$('#currentWord').get(0)
So
$('#currentWord').get(0).childNodes.length
should work.
Question #1:
jQuery returns a jQuery object. To return it to a regular javascript object use $(object)[0] and you can then treat it as a plain javascript (or DOM) object.
Question #2:
The efficiency looks good to me. Although you might want to use spans instead of p elements.
I guess one thing you could do (even though yours looks to run very fast) is cache the dom element:
function addLetter(foo) {
$(foo).unbind('click');
var tileLetter = $(foo).attr('class').split(' ');
var letter = tileLetter[2].charAt(1);
var currentWord = document.getElementById('currentWord');
if (currentWord.childNodes.length > 0) {
$(currentWord).find('p').append(letter);
} else {
var p = document.createElement('p');
p.innerHTML = letter;
currentWord.appendChild(p);
}
}
Calls to the jQuery() function ($()) return a jQuery object containing the matching elements, not the elements themselves.
Calling $('#some-id') will, then, return a jQuery object that contains the element that would be selected by doing document.getElementById('some-id'). In order to access that element directly, you can get it out of that jQuery object, using either the .get() function or an array index syntax: $('#some-id')[0] (it's 0-indexed).
I think you can replace all of this with a call to the text function.
function addLetter(foo) {
$(foo).unbind('click');
var tileLetter = $(foo).attr('class').split(' ');
var letter = tileLetter[2].charAt(1);
var currentWordP = $('#currentWord p');
if (currentWordP.size() > 0) {
currentWordP.text(currentWordP.text() + letter);
} else {
$('#currentWord').append("<p>" + letter + "</p>");
}
}
1: Use $.get(0) or $[0] to get the DOM element. e.x. $('#currentWord')[0].childNodes.length.
2: Try this:
function addLetter(foo) {
$(foo).unbind('click');
var tileLetter = $(foo).attr('class').split(' ');
var letter = tileLetter[2].charAt(1);
if ($('#currentWord p').length > 0) {
$('#currentWord p').append(letter);
} else {
$('#currentWord').append(
$('<p />', { text: letter })
);
}
}
Question #1:
document.getElementById returns DOM object. more
childNodes.length is property of Node object which is returned by document.getElementById.
jQuery selector returns jQuery object more. You can get DOM object from jQuery object using .get
$('#IDselector').get(0) = document.getElementById('IDselector')
Question #2:
function addLetter(foo) {
$(foo).unbind('click');
var tileLetter = $(foo).attr('class').split(' ');
var letter = tileLetter[2].charAt(1);
if ($('currentWord p').length > 0) {
$('#currentWord p').append(letter);
} else {
var p = $('<p />').text(letter);
$('#currentWord').append(p);
}
}

Categories

Resources