<div class="card" style>
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#collapseOne" aria-
expanded="true" aria-controls="collapseOne">
Collapsible Group Item #1
</button>
</h5>
</div>
<!-- Add mx-auto -->
<div id="collapseOne" class="collapse show text-center mx-auto" aria-labelledby="headingOne"
style="width:300px;">
<div class="card-body">
<div class="card">
<div class="card-header text-center" id="headingTwo" style="width:300px;">
<h5 class="mb-0">
<button class="btn btn-link collapsed text-center" data- toggle="collapse" data-
target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo" style="width:300px;">
Collapsible Group Item #2
</button>
</h5>
</div>
<div id="collapseTwo" class="collapse show" aria-labelledby="headingTwo">
<div class="card-body">
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus wolf moon put a
craft beer sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings farm-
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-header" id="headingThree">
<h5 class="mb-0">
<button class="btn btn-link collapsed" data-toggle="collapse" data- target="#collapseThree"
aria-expanded="false" aria-controls="collapseThree">
Collapsible Group Item #3
</button>
</h5>
</div>
<div id="collapseThree" class="collapse" aria-labelledby="headingThree">
<div class="card-body">
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry wolf moon
et. Nihil anim keffiyeh helvetica, craft beer labore wes sapiente ea proident. Ad vegan
</div>
</div>
</div>
</div>
Hello I have been copying and pasting this like 10-20 times on my code changing the id the header id and the button. I also had been copying and pasting a bunch of other html code (image tag about 20 images) I was wondering if there was a way to stop repeating code (like a function) with pure html css. If not can you do it with plain vanilla js? if not then what are the other ways?
In short
Most important question (A is most important C is least)
- A) is there a way to prevent repeating code with the collapse code above with just pure HTML/CSS? if yes how?
- B) is there a way to prevent repeating code with the collapse code above with just pure HTML/CSS/vanilla js? if yes how?
- C) is there a way to prevent repeating code with the collapse code above with just pure HTML/CSS/angular/react? if yes how?
<div class="card" style>
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#collapseOne" aria-
expanded="true" aria-controls="collapseOne">
Collapsible Group Item #1
</button>
</h5>
</div>
<!-- Add mx-auto -->
<div id="collapseOne" class="collapse show text-center mx-auto" aria-labelledby="headingOne"
style="width:300px;">
<div class="card-body">
<div class="card">
<div class="card-header text-center" id="headingTwo" style="width:300px;">
<h5 class="mb-0">
<button class="btn btn-link collapsed text-center" data- toggle="collapse" data-
target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo" style="width:300px;">
Collapsible Group Item #2
</button>
</h5>
</div>
<div id="collapseTwo" class="collapse show" aria-labelledby="headingTwo">
<div class="card-body">
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus wolf moon put a
craft beer sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings farm-
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-header" id="headingThree">
<h5 class="mb-0">
<button class="btn btn-link collapsed" data-toggle="collapse" data- target="#collapseThree"
aria-expanded="false" aria-controls="collapseThree">
Collapsible Group Item #3
</button>
</h5>
</div>
<div id="collapseThree" class="collapse" aria-labelledby="headingThree">
<div class="card-body">
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry wolf moon
et. Nihil anim keffiyeh helvetica, craft beer labore wes sapiente ea proident. Ad vegan
</div>
</div>
</div>
</div>
Hello I have been copying and pasting this like 10-20 times on my code changing the id the header id and the button. I also had been copying and pasting a bunch of other html code (image tag about 20 images) I was wondering if there was a way to stop repeating code (like a function) with pure html css. If not can you do it with plain vanilla js? if not then what are the other ways?
In short
Most important question (A is most important C is least)
- A) is there a way to prevent repeating code with the collapse code above with just pure HTML/CSS? if yes how?
- B) is there a way to prevent repeating code with the collapse code above with just pure HTML/CSS/vanilla js? if yes how?
- C) is there a way to prevent repeating code with the collapse code above with just pure HTML/CSS/angular/react? if yes how?
- Templates might be a good friend – B001ᛦ Commented Jun 14, 2020 at 16:30
- 1 it can absolutely be done with vanilla. you will have to select the parent element and do for loop on innerHTML for each thing you need. See this other answer where a table is built. Should get you started. stackoverflow./questions/35617964/… – Goofballtech Commented Jun 14, 2020 at 16:34
- 1 @B001ᛦ Telling someone to use Google is not exactly a helpful answer – pafau k. Commented Jun 14, 2020 at 16:36
- 1 @Goofballtech thanks. So you need js right? there's not way to do it with pure html or css? – dragonn Commented Jun 14, 2020 at 16:37
- 1 i have never found myself not having javascript to use so i honestly don't know. My best answer..... "maybe?". I know vanilla can do ot for sure though... – Goofballtech Commented Jun 14, 2020 at 16:41
5 Answers
Reset to default 3I reckon I have found another answer, it involves the html <template>
tag and json to get the data.
html template
As mdn states it :
The HTML Content Template (
<template>
) element is a mechanism for holding HTML that is not to be rendered immediately when a page is loaded but may be instantiated subsequently during runtime using JavaScript.
Thus it is exactly what you need for this kind of problem.
Solution
First of all, you need to specify the button text and the card-content in a json object. This json can reside in a separate file (and loaded as seen below) or you can place the json content inside a variable as seen in the jsfiddle.
1. Using a Json file
data.json
[
{
"button" : "Button 1",
"body" : "Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt"
},
{
"button" : "Button 2",
"body" : "aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat"
},
{
"button" : "Button 3",
"body" : "craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS."
},
{
"button" : "Button 4",
"body" : "Lorem ipsum dolor sit amet"
}
]
loadDom
function:
function loadDom() {
//Get the data from data.json
var xobj = new XMLHttpRequest();
xobj.overrideMimeType("application/json");
xobj.open('GET', 'data.json', true);
xobj.onreadystatechange = function() {
if (xobj.readyState == 4 && xobj.status == "200") {
//parse the json
let dataToLoad = JSON.parse(xobj.responseText);
//create the cards
dataToLoad.forEach((card, i) => {
createCard(i, card["button"], card["body"]);
});
}
};
xobj.send(null);
}
2. Inline Json
function loadDom() {
//Just specify the data that you want...
var dataToLoad = [{
"button": "Button 1",
"body": "Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt"
},
{
"button": "Button 2",
"body": "aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat"
},
{
"button": "Button 3",
"body": "craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS."
},
{
"button": "Button 4",
"body": "Lorem ipsum dolor sit amet"
}
];
//load the data from json and create the cards
dataToLoad.forEach((card, i) => {
createCard(i, card["button"], card["body"]);
});
}
function createCard(id, buttonText, cardBody) {
var card = document.getElementById("cardTemplate").content;
//clone the card template
var cln = card.cloneNode(true);
//create the custom heading and collapse id
let headingId = "heading-" + id;
let collapseId = "collapse-" + id;
//set all the attributes
cln.querySelectorAll(".card-header")[0].id = headingId;
cln.querySelectorAll(".card-header button")[0].setAttribute("data-target", "#" + collapseId);
cln.querySelectorAll(".card-header button")[0].setAttribute("aria-controls", collapseId);
cln.querySelectorAll(".card-body")[0].parentElement.id = collapseId;
cln.querySelectorAll(".card-body")[0].parentElement.setAttribute("aria-labelledby", headingId);
//set the content
cln.querySelectorAll(".card-header button")[0].innerHTML = buttonText;
cln.querySelectorAll(".card-body")[0].innerHTML = cardBody;
//add the card to the accordion
document.getElementById("accordion").appendChild(cln);
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn./bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<script src="https://code.jquery./jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn./bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
</head>
<body onload="loadDom();">
<div id="accordion">
<template id="cardTemplate">
<!-- Card -->
<div class="card">
<div class="card-header">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" aria-expanded="true" >
</button>
</h5>
</div>
<div class="collapse" data-parent="#accordion">
<div class="card-body">
</div>
</div>
</div>
<!-- /card -->
</template>
</div>
</body>
</html>
Hope this helps! If not, please ment
(For this example I borrowed @Polygnome's <head>
code)
In pure HTML/CSS this isn't possible, unless you employ a server-side rendering with some template language.
As far as doing it with pure HTML/CSS/JS, ECMAScript 262 introduced template literals which can be employed to great effectiveness here:
<script>
function createCard(id, content) {
return `<div class="card">
<div class="card-header" id="heading-${id}">
<h5 class="mb-0">
<button class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapse-${id}" aria-expanded="false" aria-controls="collapse-${id}">Collapsible Group Item #${id}</button>
</h5>
</div>
<div id="collapse-${id}" class="collapse" aria-labelledby="heading-${id}">
<div class="card-body">
${content}
</div>
</div>
</div>`;
}
$(function(){
// create one card
$('#cards').append($(createCard('1', "Lorem ipsum")));
// create nested cards
$('#cards').append($(createCard('2', createCard(3, "Dolor sit amnet"))));
});
</script>
Note that I have employed jQuery here for the ease of selecting the element & inserting and because Bootstrap -- which you are using -- uses jQuery anyways. You can easily do this with pure JS via document.getElementById(...)
as well.
A working demo can be seen here:
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn./bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<h1>Hello, world!</h1>
<div class="container" id="cards">
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery./jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn./bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
<script>
function createCard(id, content) {
return `<div class="card">
<div class="card-header" id="heading-${id}">
<h5 class="mb-0">
<button class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapse-${id}" aria-expanded="false" aria-controls="collapse-${id}">Collapsible Group Item #${id}</button>
</h5>
</div>
<div id="collapse-${id}" class="collapse" aria-labelledby="heading-${id}">
<div class="card-body">
${content}
</div>
</div>
</div>`;
}
$(function(){
$('#cards').append($(createCard('1', "Lorem ipsum")));
$('#cards').append($(createCard('2', createCard(3, "Dolor sit amnet"))));
});
</script>
</body>
</html>
You can use a function to repeat how many times you want to duplicate your element, in the following snippet I created a function that will clone .card
node using .cloneNode()
and iterate a number of times, then modify the ids and attributes using querySelector()
on the cloned node, here is a snippet for option A
:
function duplicateElement(selector, numOfDuplicates) {
let element = document.querySelector(selector);
for(let i = numOfDuplicates; i > 0; i--) {
let newElement = element.cloneNode(true);
newElement.querySelector('#headingOne').id = `headingOne-${i}`;
newElement.querySelector('#collapseOne').id = `collapseOne-${i}`;
newElement.querySelector('#collapseTwo').id = `collapseTwo-${i}`;
newElement.querySelector('#headingTwo').id = `headingTwo-${i}`;
let toggleBtn = newElement.querySelector('[data-target="#collapseOne"]');
toggleBtn.dataset['target'] = `#collapseOne-${i}`;
toggleBtn.setAttribute('aria-controls', `collapseOne-${i}`);
let toggleBtn2 = newElement.querySelector('[data-target="#collapseTwo"]');
toggleBtn2.dataset['target'] = `#collapseTwo-${i}`;
toggleBtn2.setAttribute('aria-controls', `collapseTwo-${i}`);
element.after(newElement);
}
}
duplicateElement('.card', 4);
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn./bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://code.jquery./jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn./bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#collapseOne" aria- expanded="true" aria-controls="collapseOne">
Collapsible Group Item #1
</button>
</h5>
</div>
<!-- Add mx-auto -->
<div id="collapseOne" class="collapse show text-center mx-auto" aria-labelledby="headingOne" style="width: 300px;">
<div class="card-body">
<div class="card">
<div class="card-header text-center" id="headingTwo" style="width: 300px;">
<h5 class="mb-0">
<button class="btn btn-link collapsed text-center" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo" style="width: 300px;">
Collapsible Group Item #2
</button>
</h5>
</div>
<div id="collapseTwo" class="collapse show" aria-labelledby="headingTwo">
<div class="card-body">
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus wolf moon put a craft beer sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings farm-
</div>
</div>
</div>
</div>
</div>
</div>
If you are looking for option C
solution, it will be a bit plicated if your project is not already using React or other client rendering library or front-end framework, you have to use Webpack with Babel to setup the front-end framework and code-base for your project, here is a working codesandbox sample for on how you might implement your bootstrap front-end using React.
In the following snippet, I created a ponent function and used Array.map()
on array [1, 2, 3, 4, 5]
to create 5 ponents:
import React, { useState } from "react";
import { Collapse, Button, Card } from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.min.css";
import "./styles.css";
function Example() {
const [open, setOpen] = useState(false);
const [openLevel, setOpenLevel] = useState(false);
return (
<>
<Card>
<Card.Header>
<Button
onClick={() => setOpen(!open)}
aria-controls="collapseOne"
aria-expanded={open}
>
Collapsible Group Item #1
</Button>
</Card.Header>
<Collapse className="first-coll" in={open}>
<Card.Body id="collapseOne">
<Card>
<Card.Header>
<Button
onClick={() => setOpenLevel(!openLevel)}
aria-controls="collapseTwo"
aria-expanded={openLevel}
>
Collapsible Group Item #2
</Button>
</Card.Header>
<Collapse className="second-coll" in={openLevel}>
<Card.Body id="collapseTwo">
Anim pariatur cliche reprehenderit, enim eiusmod high life
accusamus wolf moon put a craft beer sapiente ea proident. Ad
vegan excepteur butcher vice lomo. Leggings farm-
</Card.Body>
</Collapse>
</Card>
</Card.Body>
</Collapse>
</Card>
</>
);
}
export default function App() {
return (
<div className="App">
{[1, 2, 3, 4, 5].map((el, i) => {
return <Example key={i} />;
})}
</div>
);
}
As an extension of Polygnome's answer,
You can acplish this in vanilla JavaScript using the following:
function appendCard(id, content) {
let el = document.querySelector(".card");
let content = document.createTextNode(`<div class="card">
<div class="card-header" id="heading-${id}">
<h5 class="mb-0">
<button class="btn btn-link collapsed" data-toggle="collapse" data-target="#collapse-${id}" aria-expanded="false" aria-controls="collapse-${id}">Collapsible Group Item #${id}</button>
</h5>
</div>
<div id="collapse-${id}" class="collapse" aria-labelledby="heading-${id}">
<div class="card-body">
${content}
</div>
</div>
</div>`);
el.appendChild(content);
}
Hope this helps!
answer to A- There's no way out with pure HTML and CSS, As HTML is the language where you define the content, that's why you have to repeat the same things 'n' times for 'n' number of results... But if you feel confused while giving each repeated content a new class and Id for its unique CSS, Then it is not required, as you can simply use :nth-child()
property... You can just copy and paste the code in HTML with same classes and still you can define different CSS to each one of them... CHECK :nth-child()
for more info !!
answer to B and C- Well, there is not much left that I can sill tell you now, as I am a bit late to the party and the answers have already been discussed by others, which I feel are absolutely correct and relatable... You can kindly check other answers from different users (like- Chiel, ROOT, Polygnome & Coder100) for desired results with the use of different languages and frameworks outside pure CSS and HTML...
Have a nice day to everyone!!
Regards,
Om Chaudhary
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744189007a4562342.html
评论列表(0条)