1

The CSS I need to alter
I am looking for how to express the .g > input + span and
how to apply the set the style property only to the checkbox elements that have an ID that starts with "S".

.g > input + span::before {font-weight:400;content: 'G';color:#000;display: block;text-align: center;position: absolute;left: 0.36rem;top: 0.12rem;}
.g4 > input + span::before {font-weight:400;content: 'G4';color:#000;display: block;text-align: center;position: absolute;left: 0.19rem;top: 0.12rem;}

I would like a solution that does not use CSS variables.
This is not just a JS and CSS question.
This is NOT a question about pseudo elements

This page is not static.
There are over 2,000 checkboxes in this app.
The subset of checkboxes that is displayed at any given point in time is very dynamic.

The HTML

<div class="row">
<div class="dchk"><label class="e chk"> <input type="checkbox" id="C0081" class="chk" name="aC0081" value="1" /><span></span></label></div>
<div class="dchk"><label class="g4 chk"><input type="checkbox" id="C0083" class="chk" name="aC0083" value="3" /><span></span></label></div>
<div class="dchk"><label class="g chk"> <input type="checkbox" id="C0082" class="chk" name="aC0082" value="2" /><span></span></label></div>
<div class="inline">&nbsp;Pyrethrum</div></div>
<div class="row">
<div class="dchk"><label class="e chk"> <input type="checkbox" id="S0171" class="chk" name="aS0171" value="1" /><span></span></label></div>
<div class="dchk"><label class="g4 chk"><input type="checkbox" id="S0173" class="chk" name="aS0173" value="3" /><span></span></label></div>
<div class="dchk"><label class="g chk"> <input type="checkbox" id="S0172" class="chk" name="aS0172" value="2" /><span></span></label></div>
<div class="inline">&nbsp;Quinoline Yellow (#10)</div></div>



Explanation
These are order entry checkboxes for a doctor to order chemical allergy blood tests.
There are some chemicals (ID begins with "S") that can only be tested for E type antibodies
There are some chemicals (ID begins with "C") that can be tested for E, G, and G4 antibodies.

Example
JS Fiddle App Example
Only G and G4 can be checked for Annatto, Orris Root, Papain, and Pyrethrum

Unchecked

Unchecked

Checked

Checked

I have disabled the checkboxes G and G4 for the "IDs that begin with "S" with this JS:

JavaScript

const dc = ['S057','S021','S028','S058','S024','S042','S029','S013','S003','S072','S079','S034','S027','S082','S017','S085','S087','S093','S002','S015','S018','S090',]
for (id in dc){
   document.getElementById(dc[id] + '2').disabled = true;  // "2" is G
   document.getElementById(dc[id] + '3').disabled = true;  // "3" is G4
}

In this example I would like to change the opacity to 0.25 for the G and G4 checkboxes for Quinoline Yellow (#10)

The problem

While I can disable the checkboxes, I want to indicate to the doctor that the G and G4 selections are not available by dimming the text e.g. "G" and "G4".

I do not know how to express this in JS: .g > input + span::before{

What would go where the questions marks are in this expression:
(Or other what other Selector could be used)

document.getElementById(????????).style.opacity = 0.25;

If you have any other idea on how to do this, I have full control to alter CSS, HTML, and JS.
The above example I tried is likely ill-fated so do not get biased into thinking this is the way it needs to be done.

The page is generated with PHP.
The JS const dc is created in the PHP.
When the id begins with "S", I add that ID to the JS dc array.
I have lots of flexibility for any new ideas you can fathom.

if(substr($id,0,1) == 'S'){
  $js_dc .="'$code',";
}



Full Checkbox CSS

.dchk{font:700 .8em Arial,sans-serif;display:inline-block;padding:0;margin:0;vertical-align: middle;position: relative;}
.dchk{text-align:left;}
.chk {margin: 0;display: inline-block;height:0;cursor: pointer;position: relative;}
.chk > span {color: #fff; padding: 0; margin:0; height:0; display: inline-block;}
.chk > input {height: 1.3em;width: 1.5em;margin:0 1px 0 1px;padding:4px 0 0 0 ;appearance: none; border: 1px solid #000;border-radius: 4px;outline: none;transition-duration: 0.4s;cursor: pointer;}
.chk > input:checked {border: 1px solid #000;}
.chk > input:checked + span::before {font-weight:700;content: '✓';color: #fff; display: block;text-align: center;position: absolute;left: 0.34rem;top: -0.02rem;}
.chk > input:active {border: 2px solid #000;}
.e  > input{background-color: #f7f7fb;}
.e  > input:checked{background-color: #f00;}
.e  > input + span::before {font-weight:400;content: 'E';color:#000;display: block;text-align: center;position: absolute;left: 0.44rem;top: 0.12rem;}
.g4 > input{background-color: #f7f7fb;}
.g4 > input:checked{background-color: #ff0;}
.g4 > input + span::before {font-weight:400;content: 'G4';color:#000;display: block;text-align: center;position: absolute;left: 0.19rem;top: 0.12rem;}
.g  > input{background-color: #f7f7fb;}
.g  > input:checked{background-color: #00f;}
.g  > input + span::before {font-weight:400;content: 'G';color:#000;display: block;text-align: center;position: absolute;left: 0.36rem;top: 0.12rem;}
.g,.e > input:checked + span::before {color: #fff;}
.g4 > input:checked + span::before {color: #000;}
Misunderstood
  • 5,534
  • 1
  • 18
  • 25
  • 1
    Investigate CSS variables to set the opacity in the pseudo elements and alter these variables using JS. – A Haworth Oct 05 '22 at 05:41
  • from the duplicate: https://stackoverflow.com/a/49618941/8620333 – Temani Afif Oct 05 '22 at 09:29
  • @TemaniAfif I saw your answer before I posted this question. Your answer would have helped me if the CSS was `.g::before`. What I would like to know is how to represent the `.g > input + span` in JS. Plus the fact is I want the style property set only on the checkboxes where the element ID starts with an "S" as shown in the JS array `const dc = ['S057','S021',...` The array is not static, it is created as the page is being built in PHP. Around 2010 I took A W3C Best Practices course, they recommend not using CSS variables due to their overhead. The pseudo element is not the problem. – Misunderstood Oct 05 '22 at 19:09
  • 1
    like this: https://jsfiddle.net/ao95jnkg/ ? – Temani Afif Oct 05 '22 at 19:33
  • @TemaniAfif YES! That was the missing key. See: https://jsfiddle.net/dvnat062/1/ – Misunderstood Oct 05 '22 at 20:48
  • @TemaniAfif Bought you a coffee. I added a link to the end of my question. See the last line. I would clean up the question and add another answer (non-JavaScript) if this was not closed. After posting this question I came up with a very simple simple CSS solution. I'm going to vote to reopen. I kind of like the solution in the above link without the CSS variables. Do you agree? If not, why not? – Misunderstood Oct 05 '22 at 21:35
  • Thanks for the coffee but no need to add the link into your question ;). If I understand well, your issue is resolved with the selector `.g > input[id^=S] + span` ? if it's the case, then I can update the duplicate because the question becomes a selector question. Everything else is more or less irrelevant (the pseudo element and the JS part) – Temani Afif Oct 05 '22 at 21:57

2 Answers2

0

You can use document.querySelectorAll to fix your problem

CSS

.dim::before{
  opacity: 0.3; 
}

then, add class for element by javascript

var elements = document.querySelectorAll(".g  > input[id^=S] + span")
elements.forEach(element=>{
  element.className += " dim"
})
elements = document.querySelectorAll(".g4  > input[id^=S] + span")
elements.forEach(element=>{
  element.className += " dim"
})

please see:https://jsfiddle.net/nfrap0hd/

Misunderstood
  • 5,534
  • 1
  • 18
  • 25
diqye
  • 54
  • 2
  • This looks hopeful. The problem here is I only want to disable the `.g` when the Code begins with an "S". Although I could use a different CLASS for the G and G4 Codes that begin with an "S". I tried your code like this and it did not work: `let elements = document.querySelectorAll(".g > input + span::before") elements.forEach(element=>{ opacity = 0.2; })` – Misunderstood Oct 05 '22 at 03:41
  • I also tried `elements.forEach(element=>{ opacity: 0.2; }` – Misunderstood Oct 05 '22 at 04:18
  • Pseudo elements aren’t in the DOM so JS can’t alter them as it can with an actual element so the method given in this question will not work. – A Haworth Oct 05 '22 at 05:38
  • @AHaworth Okay. What would work? Remember I can change the HTML, CSS, and JS. – Misunderstood Oct 05 '22 at 06:24
  • 1
    See my comment re CSS variables. – A Haworth Oct 05 '22 at 06:27
  • @AHaworth Thanks, I previously did not see your CSS variable comment. That's a very good idea. Definitely a top contender. (The only contender.) `element.style.setProperty` is a simple solution. I have been creating web apps since Netscape 1.1 and it is very difficult to keep up. You are an impressive guy. There are too few developers that REALLY understand CSS like you. The existence of Bootstrap CSS drives me nuts. Not a fan of jQuery either. Or any third party add on. Thanks again. – Misunderstood Oct 05 '22 at 07:16
  • 1
    @Misunderstood ```javascript elements.forEach(element=>{ element.style.setProperty("opactity","0.2") }) ``` – diqye Oct 05 '22 at 08:48
  • @diqye I made some changes to your JS Fiddle. I added .querySelectorAll(".g > input`[id^=S]` +span. It now works exactly the way I want. Only the G and G4 id's that start with an "S" are dimmed. See: https://jsfiddle.net/dvnat062/1/ – Misunderstood Oct 05 '22 at 20:59
0

What I learned here was valuable to me. Thank You.
I did create a JavaScript routine that solved the problem.

LIKNK to JS Fiddle JavaScript Solution.

But I did not use it.
I prefer an PHP/HTML solution.
All my HTML is generated in PHP

Here is how I solved the issue.

I added two classes (dim and disable) to the <span> that is styled to look like the check box.

The PHP to generate the checkboxes:

foreach($selected as $code => $types){
  $dim = '';
  $disable = '';
  if(substr($code,0,1) == 'S'){
    $dim = ' class="dim"';
    $disable = 'disabled';
  }
  if($types[0] == 5){echo '<p class="cat">' . $selected[$code][4] . "</p>\n";$none = "<p class=\"none\">No " . $selected[$code][4] . '</p>';continue;}
  if(strlen($code) < 4){continue;}
  echo "<div class=\"row\">
<div class=\"dchk\"><label class=\"e chk\"> <input type=\"checkbox\" id=\"$code" . "1\" class=\"chk\" name=\"a$code" . "1\" value=\"1\" " . $checkmark[$types[1]] . "/><span></span></label></div>
<div class=\"dchk\"><label class=\"g4 chk\"><input type=\"checkbox\" id=\"$code" . "3\" class=\"chk\" name=\"a$code" . "3\" value=\"3\" " . $checkmark[$types[3]] . "$disable/><span $dim></span></label></div>
<div class=\"dchk\"><label class=\"g chk\"> <input type=\"checkbox\" id=\"$code" . "2\" class=\"chk\" name=\"a$code" . "2\" value=\"2\" " . $checkmark[$types[2]] . "$disable/><span $dim></span></label></div>
<div class=\"inline\">&nbsp;" . $types[4] . "</div></div>\n";

}

The HTML Generated:
The changed HTML classes are added to the span> at the end of the line.

When the checkbox id begins with a "C"

<span></span>

When the checkbox id begins with an "S"

<span  class="dim"></span></label></div>

Here is two rows of three checkboxes per row. One with a C and one with S

<div class="row">
<div class="dchk"><label class="e chk"> <input type="checkbox" id="C0081" class="chk" name="aC0081" value="1" /><span></span></label></div>
<div class="dchk"><label class="g4 chk"><input type="checkbox" id="C0083" class="chk" name="aC0083" value="3" /><span ></span></label></div>
<div class="dchk"><label class="g chk"> <input type="checkbox" id="C0082" class="chk" name="aC0082" value="2" /><span ></span></label></div>
<div class="inline">&nbsp;Pyrethrum</div></div>
<div class="row">
<div class="dchk"><label class="e chk"> <input type="checkbox" id="S0171" class="chk" name="aS0171" value="1" /><span></span></label></div>
<div class="dchk"><label class="g4 chk"><input type="checkbox" id="S0173" class="chk" name="aS0173" value="3" disabled/><span  class="dim"></span></label></div>
<div class="dchk"><label class="g chk"> <input type="checkbox" id="S0172" class="chk" name="aS0172" value="2" disabled/><span  class="dim"></span></label></div>
<div class="inline">&nbsp;Quinoline Yellow (#10)</div></div>
Misunderstood
  • 5,534
  • 1
  • 18
  • 25