2

I'm trying to create my own Radio Button. I have created a Switch prototype and I'm not able to select the :before of the this div.radio_button. How can I query the :before into a variable?

HTMLDivElement.prototype.Switch = function() {
  if ((this.getAttribute("class") == "radio_button")) {
    var s = this.querySelector("::before"); // s being null
    console.log(s);
  }
};
HTMLDivElement.prototype.selected = false;

document.querySelector("div.radio_button").Switch();
div.radio_button {
  height: 30px;
  width: 50px;
  background-color: rgb(190, 190, 190);
  -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
  -moz-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
  -webkit-border-radius: 25px;
  -moz-border-radius: 25px;
  border-radius: 25px;
  position: relative;
  margin: 0;
  -webkit-transition: 0.5s;
  transition: 0.5s;
}

div.radio_button:before {
  content: '';
  height: 30px;
  width: 30px;
  -webkit-border-radius: 50%;
  -moz-border-radius: 50%;
  border-radius: 50%;
  -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
  -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
  position: absolute;
  top: 0;
  left: 0;
  background-color: rgb(255, 255, 255);
  -webkit-transform: scale(1.1);
  -moz-transform: scale(1.1);
  -ms-transform: scale(1.1);
  -o-transform: scale(1.1);
  transform: scale(1.1);
  -webkit-transition: 0.5s;
  transition: 0.5s;
}
<div class="radio_button"></div>
adiga
  • 34,372
  • 9
  • 61
  • 83
aman
  • 307
  • 21
  • 48

4 Answers4

1

Thanks for you question! Let's achieve the effect in another way.


div.radio-button {
    height: 30px;
    width: 50px;
    background-color: rgb(190, 190, 190);
    -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
    -webkit-border-radius: 25px;
    -moz-border-radius: 25px;
    border-radius: 25px;
    position: relative;
    margin: 0;
    -webkit-transition: 0.5s;
    transition: 0.5s;
    cursor: pointer;
}
div.radio-button::before{
    content: '';
    height: 30px;
    width: 30px;
    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    border-radius: 50%;
    -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
    position: absolute;
    top: 0;
    background-color: rgb(255, 255, 255);
    -webkit-transform: scale(1.1);
    -moz-transform: scale(1.1);
    -ms-transform: scale(1.1);
    -o-transform: scale(1.1);
    transform: scale(1.1);
    -webkit-transition: 0.5s;
    transition: 0.5s;
}
div.radio-button.radio-sleep:before {
    left: 0;
}

div.radio-button.radio-active:before {
    left: 20px;
    background-color: rgb(255, 68, 75);
}
<div class="radio-button radio-sleep"></div>

    HTMLDivElement.prototype.switch = function() {
        let classList = this.classList;
        if (classList.contains("radio-button")) {
            if(classList.contains("radio-active")){
                classList.remove("radio-active");
                classList.add("radio-sleep");
            }else{
                classList.add("radio-active");
                classList.remove("radio-sleep");
            }
            this.selected = !this.selected;
        }
    };
    HTMLDivElement.prototype.selected = false;

    let divButton= document.querySelector("div.radio-button");

    divButton.addEventListener("click",e=>{
        divButton.switch();
    });

All problems is easy to solve in this way.

Chivenh
  • 114
  • 4
0

edit: Since you want it to be programmatically you could create a style tag that targets your pseudo selector via css and change the content in that styletag programmatically. Like this for example:

HTMLDivElement.prototype.Switch = function() {
  if ((this.getAttribute("class") == "radio_button")) {
    addRadioButtonStyle();
  }
};
HTMLDivElement.prototype.selected = false;

document.querySelector("div.radio_button").Switch();

function addRadioButtonStyle() {
    var css = '.radio_button:before {top: 0 }',
        head = document.head || document.getElementsByTagName('head')[0],
        style = document.createElement('style');

    head.appendChild(style);

    style.type = 'text/css';
    style.id = 'radio_button_style';
    if (style.styleSheet){
      style.styleSheet.cssText = css;
    } else {
      style.appendChild(document.createTextNode(css));
    }
}

function changeRadioButtonTopStyle(val) {
    var styleTag = document.getElementById('radio_button_style');
    var newStyle = '.radio_button:before { top: '+val+'px !important }';
    styleTag.innerText = newStyle;
}

changeRadioButtonTopStyle(50);
uke5tar
  • 399
  • 3
  • 8
  • I wanted to query the `before`, to edit its value `top`. how to do it? – aman Aug 31 '19 at 07:20
  • Do you need to change it only once or dynamically? If only once (or a few times) you could make one (or multiple) css classes which inherit the style you want and just switch out the classes. – uke5tar Aug 31 '19 at 07:26
  • i will have to change it many times – aman Aug 31 '19 at 07:27
  • I am not sure there is a way to directly set the pseudo element via javascript. A workaround if you need this somehow to be programmatic might be to create a styletag that has a class and :before which targets your selector. If you give this tag an id you can query the style tag and change its content (the top value you were mentioning). If you always keep the same class it will update automatically. It feels a bit overkill though but it's the only thing that comes to my mind right now. – uke5tar Aug 31 '19 at 07:34
0

It can be done through window.getComputedProperty() method. Like in this example:

<!DOCTYPE html>

<meta charset="utf-8">
<title>Test</title>

<style>
  h1:before {
    content: "AAA";
    color: red;
  }
</style>

<h1>BBB</h1>

<script>
  let elm = document.querySelector('h1')
  let pseudoElm = getComputedStyle(elm, ':before')

  console.log(pseudoElm.title)
  console.log(pseudoElm.color)
</script>
Vladislav Ladicky
  • 2,261
  • 1
  • 11
  • 13
0

You can edit pseudo element styles using css variables (caniuse?) this way:

$('div').css({"--bTop": "50px"});
div {
    position: relative;
}
div::before {
    content: '---';
    position: absolute;
    top: var(--bTop);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>Element</div>

Also on JSFiddle

No problem to animate them, too:

$('div').css({"--bTop": "30px"});
$({foo:30}).animate({foo:100}, {
    step: function(val) {
        $('div').css({"--bTop": val+"px"});
    },
 duration: 3000
});
div {
  position: relative;
  --bTop: 0;
}

div::before {
  content: '---';
  position: absolute;
  top: var(--bTop);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>Element</div>
skobaljic
  • 9,379
  • 1
  • 25
  • 51