JS - QuerySelector null on element that does exist [duplicate] - javascript

This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 5 years ago.
I've searched for about a good 1 hour and found nothing. I've attempted the 'fixes' I've come across and they do not work on my code. Albeit that the code provided works on its own file, it does not work within mine.
Html:
<div class="result">Pizza</div>
<div class="choices">
<button id="rock">Rock</button>
<button id="paper">Paper</button>
<button id="scissors">Scissors</button>
</div>
</body>
</html>
JS:
let buttons = document.getElementById("#rock").addEventListener("click");
let rock = document.querySelector('#rock');
//check if id exists
let str,
element = document.getElementById('.choices #rock');
if(element != null){
str = elemen.value;
console.log(str);
}else{
str = null;
console.log(str);
}
if it need be, I'll post my entire code. Hopefully, this is enough to replicate the error on your end.
Thanks in advance!

getElementById takes only an id as argument, not a query.
Either use
element = document.querySelector('.choices #rock');
or
element = document.getElementById('rock');
The second form is much cleaner as only one element can have a given id. Keep composite query finished by an id to the very rare cases you want to apply it to the case the element may be or not be inside an another one.

You have some typos, but you are also missing a load or DOMContentLoaded listener. You are likely querying for the element before it exists on the page:
document.addEventListener('DOMContentLoaded', function() {
var rock = document.querySelector('#rock');
var str;
if (rock) {
str = rock.value;
console.log(str);
} else {
str = null;
console.log(str);
}
});
<div class="choices">
<button id="rock" value="rock">Rock</button>
<button id="paper" value="paper">Paper</button>
<button id="scissors" value="scissors">Scissors</button>
</div>

I don't understand the logic of your code, but you need to change the way you're getting the elements.
You're trying to get element by id, however, what you really want is get the element using querySelector.
Check on the changes I did on your code.
let buttons = document.getElementById("rock").addEventListener("click", function() {});
let rock = document.querySelector('#rock');
//check if id exists
let str;
let element = document.querySelector('.choices #rock');
if (element != null) {
str = element.value;
console.log(str);
} else {
str = null;
console.log(str);
}
<div class="choices">
<button id="rock" value="rock">Rock</button>
<button id="paper" value="paper">Paper</button>
<button id="scissors" value="scissors">Scissors</button>
</div>

Related

How would one reference document in a chrome background js script? [duplicate]

This question already has answers here:
How to access the webpage DOM/HTML from an extension popup or background script?
(2 answers)
Closed 1 year ago.
I've been trying to make an extension with chrome, but it seems like when I try to run this simple code:
function reddenPage() {
var bar = document.getElementsByClassName('nav rbx-navbar hidden-xs hidden-sm col-md-5 col-lg-4');
//console.log(bar[0].appendChild(bar[0].childNodes[2].cloneNode(true)));
if(bar[0]==null){
return false;
}else{
return true;
}
}
It returns :
Any help would be lovely, thank you so much!
As I understand You should do with :
document.querySelectorAll()
Example :
var x = document.querySelectorAll("h1, div");
You can't use .getElementByClassName() because getElementByClassName() only applies to single elements.
Different from querySelectorAll() which is flexible to select all variants of elements.
You will always find undefined if you use getElementsByClassName() for your case.
Example getElementsByClassName():
HTML:
<button class="btn btn-lg" onclick="reddenPage()">Click me</button>
<div class="same"></div>
<div class="same"></div>
<div class="same"></div>
Javascript:
function reddenPage(){
var x = document.getElementsByClassName('same');
console.log(x[0]);
if(x[0]==null){
alert("element found "+x.length);
}else{
alert("element found "+x.length);
}
}
Example queryselectorAll():
<button class="btn btn-lg" onclick="reddenPage_()">Click me</button>
<div class="diffrent-1"></div>
<div class="diffrent-2"></div>
<div class="diffrent-3"></div>
<div class="diffrent-4"></div>
Javascript:
function reddenPage_(){
var x = document.querySelectorAll('.diffrent-1, .diffrent-2, .diffrent-3, .diffrent-4');
console.log(x[0]);
if(x[0]==null){
alert("element found "+x.length);
}else{
alert("element found "+x.length);
}
}
Example getElementsByClassName() will return undefined:
function reddenPage_(){
var x = document.getElementsByClassName('diffrent-1 diffrent-2 diffrent-3 diffrent-4');
console.log(x[0]);
if(x[0]==null){
alert("element found "+x.length);
}else{
alert("element found "+x.length);
}
}
//Response undefined

Converting some text within an element to an element itself using JavaScript

Is this possible using JavaScript or JQuery, or anything else?
Say I have an HTML file like this
<div>
<p>Hello World</p>
</div>
And I want to turn "World" into a span element itself, like so (so that I can style just "World")
<div>
<p>Hello <span>World</span></p>
</div>
Since there are a lot of unknowns in your question, so I am assuming that you already know the string/word around which you want to add the html tag.
So keeping that in mind, following solution should work:
HTML:
<div>
<p id="my-text">Hello World, Again!</p>
</div>
JavaScript:
const stringToBeReplaced = "World"; // what you want to replace
const innerText = document.getElementById("my-text").innerText; //grab the text
const beginIndex = innerText.indexOf(stringToBeReplaced); // get text where string begins
// if string exists
if (beginIndex >= 0) {
const textWithTag =
"<span style='color: red'>" + stringToBeReplaced + "</span>";
const newString = innerText.replace(stringToBeReplaced, textWithTag);
// replace the text with new string
document.getElementById("my-text").innerHTML = newString;
}
Hope this is what you were asking and looking for.
https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_replace3
str.replace solves the job. The comment of #Umer Hassan is correct.

How do I change more than one element?

EDIT: I changed the var to class but I might have some error in here.
Here it goes, I want to have this paragraph in which the user can change the name on the following paragraph. The code I'm using only changes one name but the rest remains the same.
<script type="text/javascript">
function changey(){
var userInput = document.getElementById('userInput').value;
var list = document.getElementByClassName('kiddo');
for (let item of list) {
item.innerHTML = userInput;
}
}
</script>
<input id="userInput" type="text" value="Name of kid" />
<input onclick="changey()" type="button" value="Change Name" /><br>
Welcome to the site <b class="kiddo">dude</b> This is how you create a document that changes the name of the <b class="kiddo">dude</b>. If you want to say <b class="kiddo">dude</b> more times, you can!
No error messages, the code only changes one name instead of all three.
Use class="kiddo" instead of id in the html.
You can then use var kiddos = document.getElementsByClassName('kiddo') which will return an array of all the elements of that class name stored in kiddos.
Then you just need to loop through the values and change what you want.
Example of loop below:
for (var i = 0; i < kiddos.length; i++) {
kiddos[i].innerHTML = userInput;
}
id should be unique on the page. Javascript assumes that there is only one element with any given id. Instead, you should use a class. Then you can use getElementsByClassName() which returns an entire array of elements that you can iterate over and change. See Select ALL getElementsByClassName on a page without specifying [0] etc for an example.
Hello You should not use id, instead use class.
Welcome to the site <b class="kiddo">dude</b> This is how you create a document that changes the name of the <b class="kiddo">dude</b>. If you want to say <b class="kiddo">dude</b> more times, you can!
After That on Js part :
<script type="text/javascript">
function changey(){
var userInput = document.getElementById('userInput').value;
var list = document.getElementByClassName('kiddo');
for (let item of list) {
item.innerHTML = userInput;
}
}
</script>
you should use class instated of id. if you use id then the id [kiddo] must be unique
In short, document.querySelectorAll('.kiddo') OR
document.getElementsByClassName('kiddo') will get you a list of elements to loop through. Take note of querySelectorAll, though - it uses a CSS selector (note the dot) and doesn't technically return an array (you can still loop through it, though).
See the code below for some full working examples (const and arrow functions are similar to var and function, so I'll put up a version using old JavaScript, too):
const formEl = document.querySelector('.js-name-change-form')
const getNameEls = () => document.querySelectorAll('.js-name')
const useNameFromForm = (formEl) => {
const formData = new FormData(formEl)
const nameValue = formData.get('name')
const nameEls = getNameEls()
// Set the text of each name element
// NOTE: use .textContent instead of .innerHTML - it doesn't get parsed, so it's faster and less work
nameEls.forEach(el => el.textContent = nameValue)
}
// Handle form submit
formEl.addEventListener('submit', (e) => {
useNameFromForm(e.target)
e.preventDefault() // Prevent the default HTTP request
})
// Run at the start, too
useNameFromForm(formEl)
.name {
font-weight: bold;
}
<!-- Using a <form> + <button> (submit) here instead -->
<form class="js-name-change-form">
<input name="name" value="dude" placeholder="Name of kid" />
<button>Change Name</button>
<form>
<!-- NOTE: Updated to use js- for js hooks -->
<!-- NOTE: Changed kiddo/js-name to spans + name class to remove design details from the HTML -->
<p>
Welcome to the site, <span class="js-name name"></span>! This is how you create a document that changes the name of the <span class="js-name name"></span>. If you want to say <span class="js-name name"></span> more times, you can!
</p>
var formEl = document.querySelector('.js-name-change-form');
var getNameEls = function getNameEls() {
return document.querySelectorAll('.js-name');
};
var useNameFromForm = function useNameFromForm(formEl) {
var formData = new FormData(formEl);
var nameValue = formData.get('name');
var nameEls = getNameEls(); // Set the text of each name element
// NOTE: use .textContent instead of .innerHTML - it doesn't get parsed, so it's faster and less work
nameEls.forEach(function (el) {
return el.textContent = nameValue;
});
};
// Handle form submit
formEl.addEventListener('submit', function (e) {
useNameFromForm(e.target);
e.preventDefault(); // Prevent the default HTTP request
});
// Run at the start, too
useNameFromForm(formEl);
<button class="js-get-quote-btn">Get Quote</button>
<div class="js-selected-quote"><!-- Initially Empty --></div>
<!-- Template to clone -->
<template class="js-quote-template">
<div class="js-quote-root quote">
<h2 class="js-quote"></h2>
<h3 class="js-author"></h3>
</div>
</template>
You have done almost everything right except you caught only first tag with class="kiddo".Looking at your question, as you need to update all the values inside tags which have class="kiddo" you need to catch all those tags which have class="kiddo" using document.getElementsByClassName("kiddo") and looping over the list while setting the innerHTML of each loop element to the userInput.
See this link for examples:https://www.w3schools.com/jsref/met_document_getelementsbyclassname.asp
try:
document.querySelectorAll('.kiddo')
with
<b class="kiddo">dude</b>

Get the last occurrence of an element [duplicate]

This question already has answers here:
Get multiple elements by Id
(14 answers)
Closed 5 years ago.
getElementById(id) returns the element with the matching ID attribute. How can I get the last occurrence of this element, as opposed to the first?
<!DOCTYPE html>
<html>
<body>
<button onclick="getLast()">Click me</button>
<div id="username">Lisa</div>
<div id="username">Chris</div>
<script>
function getLast() {
alert(document.getElementById("username").innerHTML);
}
</script>
</body>
</html>
id is always unique. No two DOM elements can have the same id. In your case use the class attribute. Use getElementsByClassName which will return a collection. Get its length and use that value to get the last element.
function getLast() {
var getLastElemIndex = document.getElementsByClassName("username").length - 1;
console.log(getLastElemIndex)
alert(document.getElementsByClassName("username")[getLastElemIndex].innerHTML);
}
<div class="username">Lisa</div>
<div class="username">Chris</div>
<button onclick="getLast()">Click me</button>
id should be unique. But we don't have control on how people write their code and I also meet this case sometimes: "I need to parse the page and they are using same id"
You can treat id as an attribute and use querySelectorAll:
<button onclick="getLast()">Click me</button>
<div id="username">Lisa</div>
<div id="username">Chris</div>
<script>
function getLast() {
tags = document.querySelectorAll('[id="username"]');
alert(tags[tags.length - 1].innerHTML);
}
</script>
And the best practice should be using class.
The id of a HTML element is meant to be unique. You should specify the class instead:
<div class="username">Lisa</div>
<div class="username">Chris</div>
Then use Document.getElementsByClassName() to get all elements of that class:
var usernames = document.getElementsByClassName("username");
Alternatively, you can use Document.querySelectorAll():
var usernames = document.querySelectorAll(".username");
And then you can get the last one:
var lastUsername = usernames[usernames.length - 1];
Even you can do it by tag name div, as #brk said id must be unique.
function getLast(){
var divs = document.querySelectorAll("div");
console.log(divs[divs.length - 1].textContent);
}
getLast();
<button onclick="getLast()">Click me</button>
<div>Lisa</div>
<div>Chris</div>

Printing all the id names for a class in javascript [duplicate]

This question already has answers here:
for loop works fine with console.log but not innerHTML?
(2 answers)
Closed 6 years ago.
I want print the Id of every element that has the class name "test". Right now nothing is printing. I would like this to print
myAnchor
SecondId
I left my comments in there to show how an Id can be printed by accessing the Id name
This is my script
<!DOCTYPE html>
<html>
<body>
<p><a id="myAnchor" class="test" href="http://www.w3schools.com/">W3Schools</a></p>
<p><a id="SecondId" class="test" href="http://www.w3schools.com/">Second</a></p>
<p>Click the button to display the value of the id attribute of the link above.</p>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>
<script>
function myFunction() {
//var x = document.getElementById("myAnchor");
//document.getElementById("demo").innerHTML = x.id;
var x = document.getElementByClassName("test");
for(count = 0; count < x.length; count++){
document.getElementById("demo").innerHTML = x.id;
}
}
</script>
</body>
</html>
You've just got a couple of basic typos:
document.getElementByClassName("test") should be document.getElementsByClassName("test')
document.getElementById("demo").innerHTML = x.id should be document.getElementById("demo").innerHTML += x[count].id
This is because the getElementsByClassName function returns an array of elements, so you need to get each element from the array, not the array itself.
Also, you were overwriting demo every time. Using the += operator rather than the = operator concats an string to the end of the original, rather than setting the original to the new string.
A few changes here:
Use getElementsByClassName() (instead of getElementByClassName, which isn't a function - unless you are defining it somewhere).
In order to access the id attribute of the element in the for loop, use x[count].id, since x is a NodeList and we need to access the element at index count. But for a simpler approach, use Array.forEach() (along with function.call, since the list of elements is a NodeList instead of a native Array instance) to iterate over the list of elements. That way the id attribute can be obtained via element.id instead of indexing into the array of elements manually. Also, you don't have to worry about incrementing the loop variable.
var testElements = document.getElementsByClassName("test");
Array.prototype.forEach.call(testElements, function(element) {
//access elements via callback argument element
});
As it is written with the for loop, you would need to access x[count].id in order to obtain the value of the id attribute.
Get a reference to the element with id demo outside the loop, then refer to that when adding to the innerHTML property.
var demo = document.getElementById("demo");
//in loop - refer to demo - e.g. demo.innerHTML
That way it won't be obtaining a reference to the DOM element each time it adds the id attribute value.
Add (append) to the innerHTML (string) property using the plus-equal operator (i.e. +=).
demo.innerHTML += element.id;
And you might likely want to separate those values (e.g. with a space, break tag (i.e. <br />), etc.
demo.innerHTML += element.id + '<br />';
See the changes implemented below:
function myFunction() {
var demo = document.getElementById("demo");
var testElements = document.getElementsByClassName("test");
Array.prototype.forEach.call(testElements, function(element) {
demo.innerHTML += element.id+'<br />';
});
}
<p><a id="myAnchor" class="test" href="http://www.w3schools.com/">W3Schools</a>
</p>
<p><a id="SecondId" class="test" href="http://www.w3schools.com/">Second</a>
</p>
<p>Click the button to display the value of the id attribute of the link above.</p>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>

Categories

Resources