3

I want to send a list of properties to a function that will temporarily disable (via comments) those properties. The purpose is similar to what is accomplished by Chrome Dev Tools when inspecting the style of an element, except that the user will not check/uncheck boxes, instead, the action will be performed by JavaScript.

function disableProperties(el, properties) {
    var property; // property value pair
    var cssStr = el.style.cssText.replace(/; /g, ";");

    for (let i = 0; i < properties.length; i++) {
        property = properties[i] + ": " + eval("el.style." + properties[i]) + ";";
        cssStr = cssStr.replace(property, "/* " + property + " */");
    }

    el.setAttribute("style", cssStr);
}

function restoreProperties(el, properties) {
    var outHtml = el.outerHTML;
    var key = 'style="';
    var idx1 = outHtml.indexOf(key) + key.length;
    var idx2 = outHtml.indexOf('"', idx1);
    var style = outHtml.substring(idx1, idx2);

    for (let i = 0; i < properties.length; i++) {
        str = "/* " + properties[i];
        let a = style.indexOf(str);
        let b = style.indexOf(" */", a + a.length) + 3;
        let comment = style.substring(a, b);
        let property = (comment).replace("/*", "").replace("*/", "");

        style = style.replace(comment, property);
    }

    el.style.cssText = style;
}

When elements are created, their style is embedded in the HTML instead of external CSS files. It is important that the properties are only temporarily disabled; their earlier values must be preserved.

UPDATE: I thought my comment code was not working because I was trying to retrieve the comment by asking for el.style.cssText; however, the comment was only available through outerHTML.

The code below is functional, but I'm sure that could be cleaned up. If you have suggestions on how I can improve this code, please advise. Here is a fiddle to demonstrate one example of how I am using the code.

4
  • 1
    Properties are correctly commented out (and not deleted) for me in Chrome, with the code you posted. Screenshot, JSFiddle Commented Feb 14, 2020 at 19:09
  • @NathanGreen I've deleted my answer because I don't think it's what you're looking for, based on your comments on it. You mentioned that you'll be editing the question so I'll wait for that and see if I can provide a more relevant answer based on your edit. Commented Feb 14, 2020 at 22:44
  • @blex thank you for letting me know that my code worked, I was trying to retrieve it with JS instead of inspecting it. My code to retrieve comments was the problem. Commented Feb 18, 2020 at 23:54
  • @volt thank you for you code suggestions; I was able to learn from your code to improve other areas of my own. Commented Feb 18, 2020 at 23:58

1 Answer 1

1

Expanding on Volts deleted answer, use data attributes to store the initial state of your element. You can then that information to reset the values. One catch is that the style property is read only, so if we want to reset all style properties, we have to loop all the properties.

This is much cleaner than hacking comments in and out. This works with styles set inline and with classes.

const disableProperties = (el, properties) => {
  //store the style so we can restore it
  
  el.dataset.styles = JSON.stringify(el.style);
  console.log(JSON.parse(el.dataset.styles));
  properties.forEach(property => {
    el.style[property] = "unset";
  })
}

const enableProperties = (el, properties) => {
  //Get our saved initial state
  let styles = JSON.parse(el.dataset.styles);
  console.log(styles);
  properties.forEach(property => {
    el.style[property] = styles[property];
  })
}

const restoreAll = (el) => {   
  let styles = JSON.parse(el.dataset.styles);
  console.log(styles);
  /*You might think the following line should work, but the styles property is read only*/
  /*el.style = styles;*/
  /*So loop our properties instead*/
  for(prop in styles){
    if(styles.hasOwnProperty(prop)){
      el.style[prop] = styles[prop];
    }    
  }
}

document.querySelector('.child').addEventListener("click", function() {
  disableProperties(this.parentNode, ["top", "left"])
})

let enableButtons = document.querySelectorAll(".enable");

for (var i = 0; i < enableButtons.length; i++) {
  enableButtons[i].addEventListener("click", function(event) {
    let property = this.dataset.restore;
    let target = document.querySelector(this.dataset.target);
    enableProperties(target, property.split(","));
  });
}

document.getElementById("restoreAll").addEventListener("click", function() {
  restoreAll(document.querySelector(".parent"));
});
.parent {
  /*top: 50px;*/
  left: 50px;
  position: absolute;
}

.child {
  background: red;
  width: 50px;
  height: 50px;
}

.container {position:relative; height:200px;}
Click the square before restoring

<div class="container">
  <div class="parent" style="top:50px;">
    <div class="child">
    </div>
  </div>
</div>
<button id="restoreLeft" class="enable" data-restore="left" data-target=".parent">Restore Left</button>
<button id="restoreTop" class="enable" data-restore="top" data-target=".parent">Restore top</button>
<button id="restoreAll">RestoreAll</button>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.