Insert node as string but keep the instance of the node - javascript

I want to insert a node, that is converted to a string, on a specific position.
the problem is that i want to keep or regain the instance of the node, but dont know how.
I hope some of you have a solution
Note: I have to insert the element as string!
HTML:
<div class="div">
Here are <span class="span"></span> some text
</div>
CSS:
.div, .span {
display: inline-block;
border: 1px solid #333333;
width: 200px;
height: 100px;
}
.span {
min-width: 10px;
max-width: 50px;
height: 50px;
}
JS:
var div = document.querySelector('.div');
var span = document.querySelector('.span');
// element to insert
var newElement = document.createElement('div');
newElement.innerHTML = 'Hallo!';
// convert to string
var converter = document.createElement('div');
converter.appendChild(newElement);
// insert element at the end of span
span.innerHTML = span.innerHTML + converter.innerHTML;
// get the instance of the node? to interact with it
newElement.style.color = '#00ff00';
Example: CODEPEN

I wrote small function for test:
function makeNode(innerHTML){
var node = document.createElement('div');
node.id = 'unique_id';
node.innerHTML = innerHTML;
document.body.innerHTML += node.outerHTML;
return document.getElementById('unique_id');
}
Create element, insert in body, and return it
var elm = makeNode('test div');
Apply some style
elm.style = 'color:red;';
Try it: https://jsfiddle.net/nv6gyLve/

You need to set styles before insert element to dom. Other way -getElementById or same functions

Related

How do I place span elements before and after a paragraph with JavaScript?

I have some text in HTML that changes frequently and I'm trying to place a span tag before and after it, but when I try to create a span element and add it before the text element it instead displays "[object HTMLSpanElement]"
What should I do so I can have a text element that has a separate span element on both sides of the text?
Desired output: <span></span> <p id = "mytext"> <span></span>
function myFunction() {
myText = document.getElementById("myText");
var mySpan = document.createElement('span');
mySpan.textContent = 'example';
myText.textContent = mySpan;
}
<p id="myText"> Example </p>
<button onclick="myFunction()"> Click Here </button>
So if you want to inject a DOM element before another and after, you could use before() and after() methods. Here's documentation for after() and for before().
function myFunction() {
myText = document.getElementById("myText");
var mySpanLeft = document.createElement('span');
var mySpanRight = document.createElement('span');
myText.before(mySpanLeft)
myText.after(mySpanRight)
}
<p id = "myText"> Example </p>
<button onclick = "myFunction()"> Click Here </button>
Here's a step-by-step approach that's fairly readable. I would also refactor to use an event listener instead of inline JavaScript, and to pass in an element to make the function reusable (always a worthy goal).
function flankTextWithSpans(el) {
const mySpan = document.createElement('span');
const myText = el.textContent;
el.replaceChildren(); // clear the element contents
el.appendChild(mySpan); // append the empty span
el.innerHTML += myText; // append the text
el.appendChild(mySpan); // append the empty span again
}
document.querySelector('#myButton').addEventListener('click', () => {
flankTextWithSpans(document.querySelector('#myText'));
});
span {
background: pink;
display: inline-block;
width: 10px;
height: 10px;
}
<p id="myText"> Example </p>
<button id="myButton"> Click Here </button>
This is not a "perfect" example but you can either replace all or just wrap a word (or words) this will have challenges if the element contains HTML already in some situations.
I was a bit confused initially by the question so I added a wrapper and a flanker example;
function wrapper(word, element) {
const rgxp = new RegExp(word, 'g');
const repl = '<span class="my-class">' + word + '</span>';
element.innerHTML = element.innerHTML.replace(rgxp, repl);
}
function flanker(word, element) {
const rgxp = new RegExp(word, 'g');
const repl = '<span class="my-class"></span>' + word + '<span class="my-class"></span>';
element.innerHTML = element.innerHTML.replace(rgxp, repl);
}
function callWrapper() {
const myText = document.getElementById("myText");
wrapper("Example", myText);
flanker("guys", myText);
}
.my-class {
background-color: yellow;
border: solid green 2px;
padding: 0.5rem;
}
<p id="myText"> Example fun guys </p>
<button onclick="callWrapper()"> Click Here </button>

Re: How to target child nodes in HTML collection

I am new to programming and this is my first question. The problem I am having is I am trying to use DOM manipulation on all the child nodes of an html collection. I am expecting the nodes to change background color when they are hovered. Here is what I have tried so far:
let x = 0;
do{
const square = document.createElement("div");
square.className = "squares";
square.setAttribute("id","block");
document.getElementById("container").appendChild(square);
x++;
}
while(x < 16);
var container = document.getElementById("container");
var cells = container.childNodes;
cells.forEach(function(){
cells.onmouseover = function(){
cells.style.backgroundColor = "black";
}
});
console.log(`${cells.length}`);
This doesn't work even though console.log shows 16 child nodes being targeted.
var container = document.getElementById("container");
var cells = container.children[0];
cells.onmouseover = function(){
cells.style.backgroundColor = "black";
}
I have tried this and can use index but of course only that cell will change bg color. I want any cell that is hovered to change also.
I am at a loss for what I am doing wrong here. If anyone can point me in the right direction I would greatly appreciate it.
Welcome to Stack Overflow.
There is an issue in your forEach cycle. Consider the following:
cells.forEach(cell => {
cell.onmouseover = () => {
cell.style.backgroundColor = "black"
}
})
Note that you need to refer to cycle variable instead of the cells array.
Instead of attaching listeners to all the squares you can use event delegation and just have one listener on the container that captures the events from its children as they "bubble up" the DOM.
// Cache the container element, and add a listener to it
const container = document.querySelector('.container');
container.addEventListener('mouseover', handleMouse);
// Create some squares HTML by pushing template
// strings into an array
const html = [];
for (let i = 1; i < 10; i++) {
html.push(`<div class="square">${i}</div>`);
}
// Add that HTML to the container making sure
// we join the array of strings into one string
container.innerHTML = html.join('');
// When a event is fired check that it was
// was from an element with a square class
// and then add an active class to it
function handleMouse(e) {
if (e.target.matches('.square')) {
e.target.classList.add('active');
}
}
.container { display: grid; grid-template-columns: repeat(3, 50px); grid-gap: 0.2em; }
.square { font-size: 1.2em; padding: 0.7em 0.2em; background-color: #565656; color: white; text-align: center; }
.square.active { background-color: thistle; color: black; cursor: pointer; }
<div class="container"></div>
Additional documentation
Template/string literals

How to map JSON Data from an API to a div

I've been working on an app that fetches data from an API and then neatly puts them into card div's. I've written the code for performing the request and getting all the data in JSON (image below), however I can't find a way to keep my code clean and manage the results.
What i want to do is create a div called card for each JSON object (there are 50 in the picture below) and then inside those divs i append span tags with the information.
Here's my current code
xhr.onreadystatechange = () => {
if (xhr.readyState == 4) {
results.style.opacity = 1
let result = xhr.responseText
result = JSON.parse(result)
console.log(result)
Create the function and pass the JSON data to that function and then you need to iterate the loop for the key name results. Then access the each element by using the key name of the array's object. Below is the example code (css not included). More about object
<body>
<div id="container">
</div>
</body>
<script>
xhr.onreadystatechange = () => {
if (xhr.readyState == 4) {
results.style.opacity = 1
let result = xhr.responseText
result = JSON.parse(result)
loadDiv(result);
}
}
function loadDiv(data){
for(var x of data.results){
var div = `<div class="cols">
${x.mal_id}
<img src="${x.url}"/>
</div>
`;
document.getElementById("container").insertAdjacentHTML("beforeend",div);
}
}
You can iterate the object and create divs and spans.
// I expect your results in this variable.
var result = {
results: [{
One: 'div',
Two: 'span'
}]
};
result.results.forEach(data => {
var div = document.createElement('div');
div.id = 'block';
div.className = 'block';
var span = document.createElement('span');
span.className = 'block-2';
div.appendChild(span);
document.getElementsByTagName('body')[0].appendChild(div);
});
.block {
height: 50px;
width: 50px;
border: 1px solid red;
}
.block-2 {
height: 20px;
width: 20px;
border: 1px solid blue;
position: absolute;
}

Trying to append child to all elements with same class name

I am trying to use the appendChild() method to add a document.createElement("div") element to multiple <div> elements with the same class name.
I have tried this way:
const childElement = document.createElement("div");
childElement.className = "second";
const parentObject = document.getElementsByClassName("first");
[...parentObject].map(parent => parent.appendChild(childElement))
Which didnt work, so I tried:
for(let i = 0; i < parentObject.length; i++){
parentObject[i].appendChild(childElement);
}
The only way it worked was if I wrote the html element myself and then added it to the innerHTML of each parent:
[...parentObject].map(parent => parent.innerHTML = "<div class='second'></div>")
But since I am generating all different kind of HTML element tags, like IMG, DIV, SPAN I need the convenience of calling the createElement() method.
Has anyone any experience with this?
An element can only exist in one place in the DOM. What you need to do is create a new element to append to each parent:
const parentObject = document.getElementsByClassName('first');
[...parentObject].forEach((parent, i) => {
const childElement = document.createElement('div');
childElement.className = 'second';
childElement.innerHTML = `second ${i}`;
parent.appendChild(childElement)
});
div { padding: 5px; }
.first { background-color: pink; display: inline-block; }
.second { background-color: lightblue; }
<div class="first">first</div>
<div class="first">first</div>
<div class="first">first</div>
<div class="first">first</div>

Function that adds a div of a particular class

In my CSS I have a particular class for a div
div.videl
{
width: 80%;
margin: 0 auto;
background-color: #39275b;
color: white;
padding: 5px;
}
and then a function to add divs of that class:
this.addVideo = function()
{
var newVidElement = document.createElement("div");
newVidElement.class = "videl";
newVidElement.innerHTML = "<p>(" + ++this.numVids + ") <textarea class='vidtxt'></textarea></p>"
document.getElementById("vidplaydiv").appendChild(newVidElement);
}
However, for some reason, that function is not correctly applying the CSS properties when I test it out. See this page http://jaminweb.com/YoutubePlaylist.html and click the Add Another Video button. Any idea what I'm doing wrong?
className is the name of the attribute you're trying to set.
newVidElement.className = "videl";
When you don't know the property name of the HTML attribute, You can always use setAttribute, for example:
newVidElement.setAttribute('class','videl')
Change the JavaScript code as below -
this.addVideo = function()
{
var newVidElement = document.createElement("div");
newVidElement.className = "videl";
newVidElement.innerHTML = "<p>(" + ++this.numVids + ") <textarea class='vidtxt'></textarea></p>"
document.getElementById("vidplaydiv").appendChild(newVidElement);
}

Categories

Resources