Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript: Add together literal HTML results in loop [closed]

New to JS. All of the questions I could find with similar titles to mine were a bit too complicated for me to understand.

Simply put, I am trying to loop through an array and return one result at the end that essentially adds/concatenates all of the values of the array together.

However, I can't seem to get it to work, as the items in the array are blocks of HTML code, rather than simple strings or numbers. Here's a dumbed-down version.

HTML:

<article class="wrapper"><p>Some text 1.</p></article>
<article>No class.</article>
<article class="wrapper"><p>Some text 2.</p></article>
<article>No class.</article>
<article class="wrapper"><p>Some text 3.</p></article>

I am trying to figure out a way to end up with a template literal of this code:

<article class="wrapper"><p>Some text 1.</p></article>
<article class="wrapper"><p>Some text 2.</p></article>
<article class="wrapper"><p>Some text 3.</p></article>

So that I can inject the entire thing as the innerHTML of another element on a different page.

Started with this JS:

articleArray = document.querySelectorAll('.wrapper').outerHTML;
console.log(articleArray)
// This will return an array with the full HTML of the 3 "wrapper" articles as each item

Then tried to create a loop that will take the full HTML of item 1 on first loop and set it as something like an accumulator value. Then on second loop, it would take the full HTML of item 2 and concatenate it directly to item 1, and that would be the new accumulator value. And so on.

I have far more than 3 items for what I'm applying this to in real life, otherwise I could just do something like articleArray[0] + articleArray[1] + articleArray[2].

I tried a million things, but here were the closest attempts:

  1. Logging
var articleArray = document.querySelectorAll('.wrapper').outerHTML;
for (i = 0; i < searchWrappers.length; i++) {
  searchWrapper = articleArray[i];
  console.log(searchWrapper);
}
// Console log brought back 3 objects, but I need to combine them
  1. Concatenating
var articleArray = document.querySelectorAll('.wrapper').outerHTML;
var searchStr = ''
for (i = 0; i < articleArray.length; i++) {
  itemHTML = articleArray[i];
  fullString = searchStr += itemHTML;
  console.log(fullString);
}
// This did concatenate the 3 items, but only as:
// [object HTMLElement][object HTMLElement][object HTMLElement]
// and not the actual HTML
  1. Concatenating and logging
const articleArray = document.querySelectorAll('.wrapper').outerHTML;
const sum = articleArray.reduce((accumulator, value) => 
  $(accumulator).concat($(value)));
console.log(sum);
// This brought back a normal array of the 3 items again

Any help appreciated!

Edit: Thanks for all your responses! I am going to go through them now and testing your solutions on my real code to see what works best.

like image 519
Katie Reynolds Avatar asked Apr 20 '21 23:04

Katie Reynolds


People also ask

Can you put an if statement inside a template literal?

You can't write anything that's not a simple expression inside of a template literal, so no if statements or loops. You can use ternary expressions, however, if you need to make a choice: var quantity = 14; var cart = `You have ordered ${quantity} ${quantity > 1 ? "wheels" : "wheel"} of cheese.

What is `` in JS?

Backticks ( ` ) are used to define template literals. Template literals are a new feature in ECMAScript 6 to make working with strings easier. Features: we can interpolate any kind of expression in the template literals. They can be multi-line.

What is ${} in HTML?

The ${} syntax allows us to put an expression in it and it will produce the value, which in our case above is just a variable that holds a string! There is something to note here: if you wanted to add in values, like above, you do not need to use a Template Literal for the name variable.

Can We embed a loop inside a string literal?

we can't embed loop inside a string literal but yes we can call a function. Thanks for contributing an answer to Stack Overflow! Please be sure to answer the question.

What is array literals in JavaScript?

JavaScript : Array literals. In Javascript, an array literal is a list of expressions, each of which represents an array element, enclosed in a pair of square brackets ' [ ] ' . When an array is created using an array literal, it is initialized with the specified values as its elements, and its length is set to the number of arguments specified.

What are number literals in JavaScript?

Number literals can be written with or without decimal places. Number literals can be either positive numbers or negative numbers. If you do not specify a sign, then a positive number is assumed. Here are some examples of valid number literals: In JavaScript, you can declare a variable named counter and give it the numeric value of 15.

What are the different kinds of loops in JavaScript?

JavaScript supports different kinds of loops: for - loops through a block of code a number of times for/in - loops through the properties of an object while - loops through a block of code while a specified condition is true do/while - also loops through a block of code while a specified condition is true


Video Answer


4 Answers

This should help you:

function contains(selector, text) {
    var elements = document.querySelectorAll(selector);
    return [].filter.call(elements, function (element) {
        return RegExp(text).test(element.textContent);
    });
}

var articleArray = contains(".wrapper", 'menu');
// var articleArray = contains(".wrapper", /menu/i); // for case-insensitive
let templateLiteral = ``;
articleArray.forEach(function (article) {
    templateLiteral += article.outerHTML + '\n';
})
console.log(templateLiteral);
article {
    display: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<article class="wrapper"><p>Some text 1. menu</p></article>
<article>No class.</article>
<article class="wrapper"><p>Some text 2. menu</p></article>
<article>No class.</article>
<article class="wrapper"><p>Some text 3.</p></article>


</body>
</html>

The basic idea is to loop through each HTML element and get add the outerHTML of the element to the template literal.

Edit: Thanks to this answer, it helps me achieve the desired effect of finding a vanilla js replacement for :contains in jQuery.

like image 109
Parzival Avatar answered Nov 10 '22 00:11

Parzival


You could map the elements to their outer HTML and then join the results.

const htmlString = [...document.querySelectorAll('.wrapper')]
  .map(({ outerHTML }) => outerHTML.trim())
  .join('\n');

console.log(htmlString);
.as-console-wrapper { top: 0; max-height: 100% !important; }

.wrapper { display: none; }
<article class="wrapper">
  <p>Some text 1.</p>
</article>
<article>No class.</article>
<article class="wrapper">
  <p>Some text 2.</p>
</article>
<article>No class.</article>
<article class="wrapper">
  <p>Some text 3.</p>
</article>
like image 27
Mr. Polywhirl Avatar answered Nov 10 '22 00:11

Mr. Polywhirl


You can also fetch only wrappers and push them in new element to make a template:

let result = document.createElement("div")
document.querySelectorAll('.wrapper').forEach(e =>
  result.insertAdjacentElement("beforeend", e))

console.log(result.innerHTML)
<article class="wrapper">
  <p>Some text 1.</p>
</article>
<article>No class.</article>
<article class="wrapper">
  <p>Some text 2.</p>
</article>
<article>No class.</article>
<article class="wrapper">
  <p>Some text 3.</p>
</article>

Then you can use result.innerHTML to transfer all.

Also see: Element.insertAdjacentElement()

EDIT: You will actuality need to use cloning so wrappers does not get removed from DOM:

let result = document.createElement("div")

document.querySelectorAll('.wrapper').forEach(e => {
  let cln = e.cloneNode(true)
  result.insertAdjacentElement("beforeend", cln)
})

console.log(result.innerHTML)
<article class="wrapper">
  <p>Some text 1.</p>
</article>
<article>No class.</article>
<article class="wrapper">
  <p>Some text 2.</p>
</article>
<article>No class.</article>
<article class="wrapper">
  <p>Some text 3.</p>
</article>
like image 32
ikiK Avatar answered Nov 10 '22 00:11

ikiK


DOMParser is the right tool if you really have:

"the items in the array are blocks of HTML code"

// I have an array of elements as HTML strings:
const elArray = [
  `<article class="wrapper"><p>Some text 1.</p></article>`,
  `<article>No class.</article>`,
  `<article class="wrapper"><p>Some text 2.</p></article>`,
  `<article>No class.</article>`,
  `<article class="wrapper"><p>Some text 3.</p></article>`,
];

// DOMParser is the right tool for the job!
const DOC = new DOMParser().parseFromString(elArray.join(""), "text/html");

// Use selectors as normal!
const ELs = DOC.querySelectorAll(".wrapper");

// DEMO TIME: retrieve elements and finally
// place them somewhere in the app
document.querySelector("#test").append(...ELs);
<div id="test"></div>

If instead you actually have a NodeList of Elements:

  • document.querySelectorAll("article.wrapper"); to get your 3 elements as a non-live NodeList
  • Array.prototype.reduce() to reduce the three elements outerHTML to a single string!

// I am trying to figure out a way to end up
// with a template literal!

const ELs = document.querySelectorAll("article.wrapper"); 
const literal = [...ELs].reduce((s, EL) => s + EL.outerHTML, "");
console.log(literal);
<article class="wrapper"><p>Some text 1.</p></article>
<article>No class.</article>
<article class="wrapper"><p>Some text 2.</p></article>
<article>No class.</article>
<article class="wrapper"><p>Some text 3.</p></article>

Depends on what you're actually building, you need to be aware that when taking items from the DOM and converting them to string you might lose any Element Properties or Events (like "click" etc) assigned to those elements.

In such case you might just want to perhaps simply use Element.append(...myNodesList) to move them to your desired new location in the DOM:

// Let's say they have some event listeners already assigned:
document.querySelectorAll(".wrapper").forEach(EL => EL.addEventListener("click", (ev) => {
  console.log(ev.currentTarget.textContent);
}));

// Get your elements
const ELs = document.querySelectorAll("article.wrapper"); 
// And simply move them somewhere else!
document.querySelector("#test").append(...ELs); 
// Click events are preserved!!
#test { padding: 10px; background: #eee; }
<article class="wrapper"><p>CLICK ME! 1.</p></article>
<article>No class.</article>
<article class="wrapper"><p>CLICK ME! 2.</p></article>
<article>No class.</article>
<article class="wrapper"><p>CLICK ME! 3.</p></article>

<div id="test">
  <!-- Let's say you want to insert your .wrapper elements here! -->
</div>
like image 21
Roko C. Buljan Avatar answered Nov 09 '22 23:11

Roko C. Buljan