I would like to automate duplicating a class from a parent div to each separate child span based on a word.
As an example: parent div contains the following classes: grid-item tag-street-style tag-slender tag-classic tag-navy tag-grey tag-white is-loaded
I would like to duplicate any classes within the parent div with the precursor "tag-" and place them into each separate child span. In this case, the parent div contains the classes with the initial "tag-" word: tag-street-style tag-slender tag-classic tag-navy tag-grey tag-white
Some other parent divs will contain other classes that contain the initial word "tag-"
The "tag-" classes can be different in other parent divs but there will always be 5 "tag-" classes. As an example, a different parent div may contain the following classes with the initial "tag-" word: tag-smart-style tag-casual tag-modern tag-red tag-black tag-green
I already have a code snippet but this is locked in to 5 specific "tag-" classes. Here is the code:
let classMap = {
"tag-street-style": ".colour-tag-1",
"tag-slender": ".colour-tag-2",
"tag-navy": ".colour-tag-3",
"tag-grey": ".colour-tag-4",
"tag-white": ".colour-tag-5",
};
I would like the first "tag-" class identified within the parent div to be duplicated into "colour-tag-1" within the first child span.
Then I would like the second "tag-" class identified within the parent div to be duplicated into "colour-tag-2" within the second child span.
Then I would like the third "tag-" class identified within the parent div to be duplicated into "colour-tag-3" within the third child span.
Then I would like the fourth "tag-" class identified within the parent div to be duplicated into "colour-tag-4" within the fourth child span.
Then I would like the fifth "tag-" class identified within the parent div to be duplicated into "colour-tag-5" within the fifth child span.
$(document).ready( function() {
$(".grid-item .grid-meta-wrapper").each(function(e){
$(this).append('<div ><span >tag1</span><span >tag2</span><span >tag3</span><span >tag4</span><span >tag5</span></div>');
});
let classMap = {
"tag-street-style": ".colour-tag-1",
"tag-slender": ".colour-tag-2",
"tag-navy": ".colour-tag-3",
"tag-grey": ".colour-tag-4",
"tag-white": ".colour-tag-5",
};
for (let cls in classMap) {
document.querySelector(classMap[cls]).classList.add(cls);
}
});
<style>
.tag-street-style {
background-color: purple;
}
.tag-slender {
background-color: red;
}
.tag-navy {
background-color: blue;
}
.tag-grey {
background-color: grey;
}
.tag-white {
background-color: black;
color: white;
}
.tag-red {
background-color: black;
color: red;
}
.tag-black {
background-color: white;
color: black;
}
.tag-green {
background-color: black;
color: green;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
<section >
<div >
<div > T-Shirt </div>
<div >
<div >
<span>12.99</span>
</div>
</div>
</div>
<div ></div>
</section>
</div>
<br><br><br>
<div >
<section >
<div >
<div > T-Shirt </div>
<div >
<div >
<span>12.99</span>
</div>
</div>
</div>
<div ></div>
</section>
</div>
CodePudding user response:
First, here is a testable solution:
$(document).ready( function() {
$(".grid-item .grid-meta-wrapper").each(function(e){
$(this).append('<div ><span >tag1</span><span >tag2</span><span >tag3</span><span >tag4</span><span >tag5</span></div>');
});
let classes = [...document.getElementById("tag-specifier").classList].filter(item => item.indexOf("tag-") === 0);
for (let index = 0; index < classes.length; index ) {
let currentItem = document.querySelector(".colour-tag-" (index 1));
if (currentItem !== null) {
currentItem.classList.add(classes[index]);
}
}
});
.tag-street-style {
background-color: purple;
}
.tag-slender {
background-color: red;
}
.tag-navy {
background-color: blue;
}
.tag-grey {
background-color: grey;
}
.tag-white {
background-color: black;
color: white;
}
.tag-red {
background-color: black;
color: red;
}
.tag-black {
background-color: white;
color: black;
}
.tag-green {
background-color: black;
color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="tag-specifier" >
<section >
<div >
<div > T-Shirt </div>
<div >
<div >
<span>12.99</span>
</div>
</div>
</div>
<div ></div>
</section>
</div>
Now, let's understand it:
- I have added the
id
oftag-specifier
to the element which has the classes, so the code will have an easy time finding the classes to work with document.getElementById("tag-specifier").classList
is returning an object of key-value pairs where the keys are indexes (starting from 0) and the values are class names- I convert the result of
classList
into an array via[...document.getElementById("tag-specifier").classList]
because I intend to use thefilter()
function of the array, alternatively I could have written a loop with similar effect .filter()
is being called for the newly converted array. This function takes a callback (more on that below) that determines which items we are interested about from the array and returns an array that contains only the items that the callback found interesting- a callback is a function that is scheduled to be executed at some future point of time
- in our case, the callback of
.filter()
is a function which will be executed for each elements of the array and will evaluate them whether they are interesting - our callback is
item => item.indexOf("tag-") === 0
, which is a function (we use the arrow operator=>
to differentiate the parameter, which isitem
and the actual function body, which isitem.indexOf("tag-") === 0
), that is, we are only interested about items whose name starts withtag-
- after the call for
.filter()
, the value assigned toclasses
is an array of class names that only holds valuable class names from our perspective, that is, class names starting withtag-
- we loop
classes
using a variable we create for this purpose, namedindex
- we search for the element that corresponds to the selector of
".colour-tag-" (index 1)
. The reason for theindex 1
is that Javascript arrays are 0-indexed and your tag indexes start from 1 - note that
(index 1)
is enclosed into parantheses. The reason for this is that(index 1)
the result of".colour-tag-" index 1
would be looking like.colour-tag-01
instead of.colour-tag-2
- we check whether
currentItem
exists, so we program defensively, so, if any anomaly occurs, we intend our code to handle it gracefully - if
currentItem
existed, then we add the current class, which isclasses[index]
EDIT
The initial solution I have implemented was assuming that we deal with a single such case, while your problem included multiple similar cases on the same page. To solve this issue, I have added an extra layer to the solution, querying the roots of all relevant subtrees in HTML and using them as the context of their respective problem-spaces.
Here is a snippet that illustrates it (yes, the first 3 tags will be unstyled, but this is not due to the logic of the code, but it is rather due to the styling specification of the structure):
$(document).ready( function() {
$(".grid-item .grid-meta-wrapper").each(function(e){
$(this).append('<div ><span >tag1</span><span >tag2</span><span >tag3</span><span >tag4</span><span >tag5</span><span >tag6</span></div>');
});
for (let context of $(".list-grid .grid-item")) {
let idDeclaration = context.id;
let classes = [...context.classList].filter(item => item.indexOf("tag-") === 0);
for (let index = 0; index < classes.length; index ) {
let currentItem = context.querySelector(".colour-tag-" (index 1));
if (currentItem !== null) {
currentItem.classList.add(classes[index]);
}
}
}
});
.product-view-item-colour-tags .tag-navy {
background-color: blue;
}
.product-view-item-colour-tags .tag-grey {
background-color: grey;
}
.product-view-item-colour-tags .tag-white {
background-color: black;
color: white;
}
.product-view-item-colour-tags .tag-red {
color: red;
}
.product-view-item-colour-tags .tag-black {
background-color: white;
color: black;
}
.product-view-item-colour-tags .tag-green {
color: green;
}
.product-view-item-colour-tags .tag-yellow {
background-color: black;
color: yellow;
}
.product-view-item-colour-tags .tag-orange {
color: orange;
}
.product-view-item-colour-tags .tag-pink {
color: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
<div id="thumb-product-3-9" >
<section >
<div >
<div > T-Shirt 1</div>
<div >
<div >
<span>9.99</span>
</div>
</div>
</div>
<div ></div>
</section>
</div>
<br>
<div id="thumb-product-3-12" >
<section >
<div >
<div > T-Shirt 2</div>
<div >
<div >
<span>12.99</span>
</div>
</div>
</div>
<div ></div>
</section>
</div>
<br>
<div id="thumb-product-3-1" >
<section >
<div >
<div > T-Shirt 3</div>
<div >
<div >
<span>14.99</span>
</div>
</div>
</div>
<div ></div>
</section>
</div>
<br>
<div id="thumb-product-3-4" >
<section >
<div >
<div > T-Shirt 4</div>
<div >
<div >
<span>15.99</span>
</div>
</div>
</div>
<div ></div>
</section>
</div>
</div>