var kb_cards = document.querySelectorAll('div.kbCardContainer');
console.log("kb_cards length: " kb_cards.length);
<div >
<span aria-live="assertive" role="alert" />
<!-- ngIf: !(isMobileView == 'true') -->
<div ng-if="!(isMobileView == 'true')" style="">
<!-- ngRepeat: knowledgeBase in knowledgeBases |filter:excludeAll -->
<div role="none" tabindex="-1" ng-style="getStyle($index,knowledgeBase)" ng-click="clickKnowledgeBase(knowledgeBase)" ng-repeat="knowledgeBase in knowledgeBases |filter:excludeAll" style="border-left: 4px solid rgb(39, 142, 207);">
<span role="button" tabindex="0" aria-label="Company AAA 19 Articles">
<span aria-hidden="true">Company AAA</span>
<span >
<!-- ngIf: knowledgeBase.enable_socialqa -->
<span aria-hidden="true"> 19 Articles</span>
</span>
</span>
<span ng-init="subscribedLabel[knowledgeBase.sys_id] = 'Subscribed'">
<!-- ngIf: !knowledgeBase.isSubscribed -->
<span ng-attr-id="subscribe{{knowledgeBase.sys_id}}" ng-if="!knowledgeBase.isSubscribed" ng-click="knowledgeBase.isSubscribed = !knowledgeBase.isSubscribed; clickSubscribe(knowledgeBase, $event)" role="button" aria-label="Subscribe to Company AAA" tabindex="0" id="subscribe47f9af20dbaae810b2fe3313f39619df">
<i />Subscribe</span>
<!-- end ngIf: !knowledgeBase.isSubscribed -->
<!-- ngIf: knowledgeBase.isSubscribed -->
</span>
</div>
<!-- end ngRepeat: knowledgeBase in knowledgeBases |filter:excludeAll -->
<div role="none" tabindex="-1" ng-style="getStyle($index,knowledgeBase)" ng-click="clickKnowledgeBase(knowledgeBase)" ng-repeat="knowledgeBase in knowledgeBases |filter:excludeAll" style="border-left: 4px solid rgb(75, 215, 98);">
<span role="button" tabindex="0" aria-label="Company ADB 0 Articles">
<span aria-hidden="true">Company ADB</span>
<span >
<!-- ngIf: knowledgeBase.enable_socialqa -->
<span aria-hidden="true"> 0 Articles</span>
</span>
</span>
<span ng-init="subscribedLabel[knowledgeBase.sys_id] = 'Subscribed'">
<!-- ngIf: !knowledgeBase.isSubscribed -->
<span ng-attr-id="subscribe{{knowledgeBase.sys_id}}" ng-if="!knowledgeBase.isSubscribed" ng-click="knowledgeBase.isSubscribed = !knowledgeBase.isSubscribed; clickSubscribe(knowledgeBase, $event)" role="button" aria-label="Subscribe to Company ADB" tabindex="0" id="subscribe83f9af20dbaae810b2fe3313f39619e6">
<i />Subscribe</span>
<!-- end ngIf: !knowledgeBase.isSubscribed -->
<!-- ngIf: knowledgeBase.isSubscribed -->
</span>
</div>
<!-- end ngRepeat: knowledgeBase in knowledgeBases |filter:excludeAll -->
<div role="none" tabindex="-1" ng-style="getStyle($index,knowledgeBase)" ng-click="clickKnowledgeBase(knowledgeBase)" ng-repeat="knowledgeBase in knowledgeBases |filter:excludeAll" style="border-left: 4px solid rgb(255, 202, 31);">
<span role="button" tabindex="0" aria-label="Company BBD 0 Articles">
<span aria-hidden="true">Company BBD</span>
<span >
<!-- ngIf: knowledgeBase.enable_socialqa -->
<span aria-hidden="true"> 0 Articles</span>
</span>
</span>
<span ng-init="subscribedLabel[knowledgeBase.sys_id] = 'Subscribed'">
<!-- ngIf: !knowledgeBase.isSubscribed -->
<span ng-attr-id="subscribe{{knowledgeBase.sys_id}}" ng-if="!knowledgeBase.isSubscribed" ng-click="knowledgeBase.isSubscribed = !knowledgeBase.isSubscribed; clickSubscribe(knowledgeBase, $event)" role="button" aria-label="Subscribe to Company BBD" tabindex="0" id="subscribe07f9af20dbaae810b2fe3313f39619e9">
<i />Subscribe</span>
<!-- end ngIf: !knowledgeBase.isSubscribed -->
<!-- ngIf: knowledgeBase.isSubscribed -->
</span>
</div>
<!-- end ngRepeat: knowledgeBase in knowledgeBases |filter:excludeAll -->
</div>
<!-- end ngIf: !(isMobileView == 'true') -->
<!-- ngIf: (isMobileView == 'true') -->
</div>
In the snippet above, I have an extract of HTML from a Service Now Knowledge Base page.
When there are hundreds of KB categories, most of which have no articles against them, I wanted to work out how to add a style attribute to the divs with a class of kbCard
so that e.g. the background is yellow.
I realise I could do something like this:
var this_card = document.querySelectorAll('div.kbCard');
var_name.setAttribute("style", "background:yellow;");
However, in this scenario, I need to loop through all of the kbCard
divs nested below the parent kbCardContainer
div, and from there, check the value of the kb-count
span, and if it is not "0 Articles", then set the style attribute of the kbCard
div.
I realise that's asking for a lot though!
I'm familiar with looping through records and updating them - e.g.
var table_cells = document.querySelectorAll('td.vt');
for (var j = 0; j < table_cells.length; j ) {
var cell = table_cells[j];
cell.innerHTML = cell.innerHTML.replaceAll('Work in Progress', 'WIP');
cell.innerHTML = cell.innerHTML.replaceAll('Root Cause Analysis', 'RCA');
cell.innerHTML = cell.innerHTML.replaceAll('Development', 'Dev');
}
But in this case, I am stuck on a number of fronts because:
- The length of kbCardContainer is only returning 1 because there is only 1 div nested below it, with a class of
col-md-12
. I can't select on that class as there are other divs on the page with the same class. How can I select the contents of divcol-md-12
nested below thekbCardContainer
div? - Even if I could fix 1, I'm not sure how to check the contents of a SPAN nested below another DIV, and then set an attribute of the parent DIV...
Sorry, I am asking for "the moon on a stick" here, but thought I'd ask for advice anyway.
Apologies for my mistakes etc.
Thanks
CodePudding user response:
Fist you want to do, is to get all your cards, by doing something like it:
const cards = document.querySelectorAll(".kbCard");
Then you will need to loop throw them, to do what you need:
for(card of cards) {
let subChild = GetWantedSubchild(card);
if (!subChild) continue;
if (subChild.textContent.includes("0 Articles")) {
// Do what ever you want
card.setAttribute("style", "background:yellow;");
}
}
function GetWantedSubchild(element) {
let childLevel1 = element.children[0];
if (!childLevel1) return undefined;
return childLevel1.querySelector(".kb-card-details");
}
So now, how I created this GetWantedSubchild. I looked at the HTML structure you show us, and I tried to simplify it, by removing no "needed elements" (for our problem).
<div >
<span role="button" tabindex="0" aria-label="Company BBD 0 Articles">
<span aria-hidden="true">Company BBD</span>
<span >
<span aria-hidden="true"> 1 Articles</span>
</span>
</span>
</div>
So we have a .kbCard
div, inside there is a span element with no class or anything that can help us to select it. So you want to get the first child of your .kbCard
div:
let childLevel1 = element.children[0]; // "element" is the .kbCard div
This childLevel1
is this node : <span role="button" tabindex="0" aria-label="Company BBD 0 Articles">
. From that node, I take a look to the HTML. I see that the element you want (where "0 Articles" is written) has the class kb-card-details. So it will be easy to select it. So it exactly what I do with childLevel1.querySelector(".kb-card-details");
. And with this element I can check the content (if it is "0 Articles"), and do a treatment if it is.
Please note that I did fast so I miss a point, the real node I should select at the end is .kb-count
. It is the real span containing the value. But because it is the only node, I guess it still works.
I made a test on my side and it seems working :) Do not hesitate if you have any question.