using a variable in document.queryselector - javascript

I am trying to access all the strong tags of a certain paragraph, therefore i looped over all the paragraphs in the document and the code explains the rest
let paragraphs = document.getElementsByTagName("p");
for(let i = 0; i < paragraphs.length; i++) {
var element = document.querySelector(`${paragraphs[i]} > strong`)
console.log(element)
if( element == null) {
continue;
}
else{
var element = document.querySelector('p > strong')
element.style = "";
break;
}
}
when i try to do this i get an error because of this line of code
var element = document.querySelector(`${paragraphs[i]} > strong`)
this is the error: Uncaught DOMException: Failed to execute 'querySelector' on 'Document': '[object HTMLParagraphElement] > strong' is not a valid selector.
any help is much appreciated, thank you..

You need to pass a selector string such a p, .class or #id in the place of that variable, not an HTML element.
I suppose you're actually looking to execute the querySelector method on the paragraph element instead of the document object:
var element = paragraphs[i].querySelector(':scope > strong')
(See here for what :scope does.)

Here's what I came up with to solve your problem:
Grab all the strong elements inside the p tags present on the page
and now you can use .forEach() method on the node list to manipulate elements.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>select strong</title>
</head>
<body>
<p><strong>strong 0</strong>something <strong>strong1</strong></p>
<p>something <strong>strong2</strong></p>
<p>something <strong>strong3</strong></p>
<div>
<div>
<p>strong inside <strong>div</strong></p>
</div>
</div>
<script>
// this is a node list with all `strong` tags inside `p`
const strongStuff = document.querySelectorAll("p > strong");
// you can use .forEach() method on a node list
strongStuff.forEach((strongEl) => console.log(strongEl.innerText));
</script>
</body>
</html>
Or, as an executable snippet:
// this is a node list with all `strong` tags inside `p`
const strongStuff = document.querySelectorAll("p > strong");
// you can use .forEach() method on a node list
strongStuff.forEach((strongEl) => console.log(strongEl.innerText));
<p><strong>strong 0</strong>something <strong>strong1</strong></p>
<p>something <strong>strong2</strong></p>
<p>something <strong>strong3</strong></p>
<div>
<div>
<p>strong inside <strong>div</strong></p>
</div>
</div>
If you need more clarification let me know.

Related

Keep Getting an error in javascript about a node

so im trying to make a list of the input from the user and i keep getting this error
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ToDo</title>
</head>
<body>
<h1>To Do List</h1>
<label>Enter What You Have To Do:</label>
<br>
<br>
<input type="text" id="toDo">
<br>
<br>
<button type="button" id="myButton">Submit</button><br>
<ul id="list"></ul>
<script src="todojs.js"></script>
</body>
</html>
javascript
document.getElementById('myButton').onclick = function () {
const doIt = document.getElementById('toDo').value;
const li ='<li>' + doIt + '</li>';
document.getElementById('list').appendChild(li);
document.getElementById('toDo').value = '';
}
Error
Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
at document.getElementById.onclick
appendChild expects a Node Element. You are passing a string.
If you want to append a string, you can use the insertAdjacentHTML function.
https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML
document.getElementById('myButton').onclick = function () {
const doIt = document.getElementById('toDo').value;
const li ='<li>' + doIt + '</li>';
document.getElementById('list').insertAdjacentHTML('beforeend', li);
document.getElementById('toDo').value = '';
}
const li = document.createElement("li");
li.innerHTML(doIt);
should do the trick instead of the one liner
if you pass a string, that string isn't a node or a real element present in the DOM, it wouldn't work.
so simply just programmatically create one element! using document.createElement()
change the text inside it, using document.textContent
try to not use innerHTML because is DANGEROUS, someone can insert in the input some malicious code scripts. textContent is more safe
one more thing, use .addEventListener()
instead of .onclick,
because if you have more event listener in one time, .onclick sometimes don't work, with .addEventListener() you can make 2 or more events work in one time.
for inserting before you can use this: https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore , just read the documentation I linked to you, and you are done!
I hope this help you!
one more thing:
if you want more custom UI,
you can write a copy of all your elements inside a <div>,
and then insert it inside a <template> tag manually...
the result is: now you have a reusable component with just regular HTML, JS
so the previus document.createElement(); it will become Node.cloneNode()
more details here: https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode
let btn = document.getElementById('myButton');
let list = document.getElementById('list');
let inputEl = document.getElementById('toDo');
btn.addEventListener('click', () => {
const getliValue = inputEl.value;
const newLi = document.createElement('li');
newLi.textContent = getliValue;
list.appendChild(newLi);
inputEl.value = '';
});
<h1>To Do List</h1>
<label>Enter What You Have To Do:</label>
<br><br>
<input type="text" id="toDo">
<br><br>
<button type="button" id="myButton">Submit</button>
<br>
<ul id="list"></ul>
<script src="script.js"></script>

How to reduce javascript code that use JQuery and .each()

I have tried to reduce following code
var wgDialog
= jQuery(".ui-dialog.ui-overlay-visible",window.parent.document)
.each
(function(nIndex)
{
var sWidgetName = $(this).attr('data-widgetvar');
var wgDialog = window.parent.PF(sWidgetName);
});
to this code
var jqDialog
= jQuery(".ui-dialog.ui-overlay-visible",window.parent.document)
.children(":first-child");
var sWidgetName = jqDialog.attr('data-widgetvar');
var wgDialog = window.parent.PF(sWidgetName);
but this doesn't work !
The sWidgetName variable is always undefined in last code.
What is my mistake ?
With help of comments, I have found a solution.
I must use get(0) to obtain first element in list returner by JQuery().
And I must use $(jqDialog) instead of jqDialog to get 'data-widgetvar' attribute.
Here is my new code
var jqDialog
= jQuery(".ui-dialog.ui-overlay-visible",window.parent.document)
.get(0);
var sWidgetName = $(jqDialog).attr('data-widgetvar');
var wgDialog = window.parent.PF(sWidgetName);
Assuming you want to access an element with attribute data-widgetvar nested in an element having css classes ui-dialog and ui-overlay-visible you could do the following with plain javascript:
var myElement = document.querySelector('.ui-dialog.ui-overlay-visible [data-widgetvar]');
querySelector allows a CSS like selector combining class together with attribute selector.
Update:
Here is a working example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Test</title>
<script type="text/javascript">
function main() {
var myElement = document.querySelector('.ui-dialog.ui-overlay-visible [data-widgetvar]');
console.log("Attribute value", myElement.getAttribute('data-widgetvar'));
}
document.addEventListener("DOMContentLoaded", main);
</script>
</head>
<body>
<div class="ui-dialog ui-overlay-visible">
<div>some element</div>
<div data-widgetvar="someValue">some text content</div>
</div>
</body>
</html>

Javascript display all (elements, tags) from method elementsbyTagName

Im learning JavaScript and i have problem with DOM methods.
HTML
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="DOM_Ponovno.js"></script>
</head>
<body>
<div>
<p id="demo" >
this is the first paragraph</p>
<p> boooooooooooommmmmmmmmmmm</p>
<p> third paragraph </p>
<button onclick="changeText()">click me</button>
</div>
</body>
function changeText() {
var tmpTag = document.getElementsByTagName("p");
for(var i = 0;i< tmpTag.length;i++) {
document.write(tmpTag[i].textContent);
}
}
If i follow the tutorial its ok, but i wanted to display all elements by tag name p. I want to display all paragraphs stored in tmpTag.
Someone please explain:
How can ( why cant) display all elements with tag name p ?
How can (why cant) display 3x p tag from variable tmpTag ?
Tried to change to Array with prototype.slice.call method but no success.
You know like Java stuff loop through display/change at index etc..
Thank you :)
Hi and thanx for fast answers.. Sory about the function name it was for testing... I just want to display all elements by tag name p. This code displays only first element and i counter in for loop stops at 1. Why cant i get other 2 paragraph elements ?
Im using document.write like system.out.print in Java to see whats in array. I know if i wanna change i need innerHTML.
If you are wanting to update each paragraph, do not use document write. Try the following:
function changeText() {
var tmpTag = document.getElementsByTagName("p");
for(var i = 0;i< tmpTag.length;i++) {
tmpTag[i].innerHTML = "Your new updated text to change it to for tag index " + i + "...";
}
}
As #Juhana mentioned, the moment you start your loop you overwrite the document using document.write, so all your p tags get removed from the document and replaced by the text in the first paragraph and then your function fails, as the now-empty objects don't have any textContent property. You could concatenate all the contents and write it once:
function changeText() {
var tmpTag = document.getElementsByTagName("p");
var print = '';
for(var i = 0;i< tmpTag.length;i++) {
print += tmpTag[i].textContent;
}
document.write(print)
}
But actually, just don't use document.write - SO snippets don't even allow it anymore! Here a way with a div as output:
var output = document.getElementById('output');
function changeText() {
var tmpTag = document.getElementsByTagName("p");
for(var i = 0;i< tmpTag.length;i++) {
output.textContent += tmpTag[i].textContent;
}
}
<div>
<p id="demo" >this is the first paragraph</p>
<p> boooooooooooommmmmmmmmmmm</p>
<p> third paragraph </p>
<button onclick="changeText()">click me</button>
</div>
<div id="output"></div>
I'm not sure what you're trying to do but you can add another div for result with id='result' and append result you want to it, check following example.
Hope this will help.
function changeText() {
var tmpTag = document.getElementsByTagName("p");
var result = document.getElementById('result');
for(var i = 0;i< tmpTag.length;i++) {
result.innerHTML += tmpTag[i].textContent+'<br>';
}
}
<div>
<p id="demo" >
this is the first paragraph</p>
<p> boooooooooooommmmmmmmmmmm</p>
<p> third paragraph </p>
<button onclick="changeText()">click me</button>
<br>
<div id="result" ></div>
</div>

manipulating tag using java script

I am fairy new in learning JavaScript , I am practising to manipulate a tag,
here is my code
I know that I am making a silly mistake here but I am not sure which part has went wrong ?
could any one please give me some hint ?
<html lang='en'>
<head>
<meta charset="UTF-8" />
<title>
HTML Hyperlinks
</title>
</head>
<body>
<h1>
HTML Hyperlinks
</h1>
<p>
Here is a link to <a name = "hyper" href="http://yahoo.com/">page</a>.
The text around the link is not part of the link.
</p>
<script>
var element = document.getElementsByTagName("a");
var attribute = element.getAttribute("href");
element.setAttribute("href","Http://google.com");
element.setAttribute("target","_blank");
</script>
</body>
</html>
getElementsByTagName says elements. Plural.
It returns a NodeList, which is like an Array, not a single Element.
You need to loop over its return value (e.g. with for) or access it by index ([0])
You are requesting a collection of a tags, but then treating them like a single entity.
<script>
var element = document.getElementsByTagName("a");
var attribute = element.getAttribute("href");
element.setAttribute("href","Http://google.com");
element.setAttribute("target","_blank");
</script>
try this
<script>
var element = document.getElementsByTagName("a")[0];
var attribute = element.getAttribute("href");
element.setAttribute("href","Http://google.com");
element.setAttribute("target","_blank");
</script>
or
<script>
var elements = document.getElementsByTagName("a");
for(var i = 0; i < elements.length; i++)
{
var element = elemenets[i];
var attribute = element.getAttribute("href");
element.setAttribute("href","Http://google.com");
element.setAttribute("target","_blank");
}
</script>
Change this line
var attribute = element.getAttribute("href");
to this
var attribute = element[0].getAttribute("href");

Can the mouseover event be used on any element, or only on images?

<html >
<head>
<title>JavaScript Example</title>
<script type="text/javascript">
function greet {
var greet = document.getElementById("greeting");
greet.value="this is dynamic";
</script>
</head>
<body>
<p onmouseover="greet()"> Hello! Welcome to My Page </p>
</html>
What is the problem in this code?
Firstly, you haven't closed your greet function (missing the closing } character). Secondly, you're missing the parentheses after the name of the function:
function greet() {
//Function body
}
Secondly, you're using getElementById to try and obtain a reference to the p element, but the p element doesn't have an id.
Thirdly, the greet variable will contain a reference to a p element, which doesn't have a value property (like, for example, input elements do). You may have meant innerHTML if you are trying to change the contents of the element.
Finally, you haven't closed your <body> element. Edit (see comments) - This isn't a problem, but personally I prefer closing it for consistency.
You could pass a reference to the element into the function when it's called, to save you having to get it by id:
<p onmouseover="greet(this);">Example</p>
And JavaScript:
function greet(elem) {
elem.innerHTML = "Something new";
}
the p element should have an ID of greet, as in:
<p onmouseover="greet()" id="greeting"> Hello! Welcome to My Page </p>
, so that when you select the element's ID at:
document.getElementById("greeting");
the document can find the tag you are trying to select from the HTML document.
Additionally, instead of editing the node's "value" attribute, I think you need to use the "innerHTML" instead. So that gives:
<html >
<head>
<title>JavaScript Example</title>
<script type="text/javascript">
function greet {
var greet = document.getElementById("greeting");
greet.innerHTML="this is dynamic";
}
</script>
</head>
</body>
<p onmouseover="greet()" id="greeting"> Hello! Welcome to My Page </p>
</html>
I am not exactly familiar with JavaScript, but I believe that should work.
You can try:
greet = function(elem) {
elem.innerHTML = "Something new";
}
or
greet = function() {
var greet = document.getElementById("greeting");
greet.innerHTML="this is dynamic";
}
Along with the other tips of course(like id attribute for the relevant <p> element and well-forming your HTML).

Categories