Style element from value in attribute

Viewed 80

I have actually asked this question first, but its my fault because I couldn't describe the thing correctly there, so I couldn't get the answer. But now I will describe everything here. Actually, I want a javascript function that can find a class with a specific prefix of any element in the full document. Lets take a example of a html markup :

 <body class="c:bg-#008eff">
 <h1 class="c:bg-#ff5c5c">Hello, <span class="c:bg-white">World !</span></h1>

In the above example, we get a common prefix c:bg- in all the classes. After the prefix we find names and hex of css colors. Consider, a function understand() that can :

(1) Find all the classes with the prefix c: in an html document.

(2) Looks for what is after the c: prefix, e.g. c:bg- will indicate that it is css background property, while c:text- will indicate thats it is css color property, etc.

(3) Looks for the value to set, e.g. c:bg-#008eff indicates that it is css background property with value #008eff etc.

(4) Removes the c:bg-, c:text- , etc. prefixes from the class obtained as string, and uses the remaining portion to define style.

We have got our example :

 <body class="c:bg-#008eff">
 <h1 class="c:bg-#ff5c5c">Hello, <span class="c:bg-white">World !</span></h1>

In the output of the above code in browser window, we will find the body with background #008eff, h1 with background #ff5c5c and span with background white.

Another example :

 <body>
 <h1 class="c:text-#ff5c5c c:pad-20px">Hello, <span class="c:text-#008eff c:mar-20px">World !</span></h1>

In the output of the above code in browser window, we will find h1 with color #ff5c5c and padding 20px and span with color #008eff and margin 20px.

And, yes very important ! If same type of code is repeated then last one overwrite the first one.

Example :

 <h1 class="c:bg-blue c:bg-red">Hello</h1> 
<!-- Executes red background -->

I wish, I am very clear now ! So, can my dream be a truth ? Is this possible to make the understand() function ?

Thanks For Giving Me Your Time

2 Answers

Here's how I'd tackle with a better solution, using data-* attribute:

const applyStyle = el => el.style.cssText = el.dataset.style;

document.querySelectorAll("[data-style]").forEach(applyStyle);
<h1 data-style="color:#f0b; background:#0bf;">TEST</h1>
<h1 data-style="color:#b0f; background:#fb0;">TEST</h1>

https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/cssText

Otherwise you could do something like:

const props = {
  bg: 'background',
  text: 'color',
  pad: 'padding'
};

const understand = el => {
  const c_classes = [...el.classList].filter(name => name.startsWith('c:'));
  return el.style.cssText = c_classes.map(k => {
    const pv = k.split('c:')[1].split('-');
    return `${props[pv[0]]}:${pv[1]}`;
  }).join(';');
}

const ELZ = document.querySelectorAll("[class^='c:'], [class*=' c:']");
ELZ.forEach(understand);
<h1 class="test c:bg-yellow c:pad-20px c:text-#0bf bla">
    Hello, <span class="c:bg-red">World !</span>
</h1>

Although I would agree that you should use data-* instead, here is a solution using regex to parse the classes:

function applyStyle(element, style, value) {

  const properStyle = shortToProper[style] || style;

  element.style[properStyle] = value;
}

const shortToProper = {
  "bg": "background",
  "text": "color",
  "pad": "padding",
  "mar": "margin"
};

const regexp = /c:(\w+)-([^\s]*)/g;

const elements = document.querySelectorAll(`[class^='c:'],[class*=' c:']`);

elements.forEach(element => {
  const matches = element.className.matchAll(regexp);

  for (const match of matches) {

    applyStyle(element, match[1], match[2]);
  }

});
<body class="test c:bg-#008eff">
  <h1 class="c:bg-#ff5c5c">Hello, <span class="c:bg-white">World !</span></h1>
  <h1 class="c:text-#ff5c5c c:pad-20px">Hello, <span class="c:text-#008eff c:mar-20px">World !</span></h1>
  <h1 class="c:bg-blue c:bg-red">Hello</h1>
</body>

Here is a preferred solution using data-c:

function applyStyle(element, style, value) {

  const properStyle = shortToProper[style] || style;

  element.style[properStyle] = value;
}

const shortToProper = {
  "bg": "background",
  "text": "color",
  "pad": "padding",
  "mar": "margin"
};


const regexp = /(\w+)-([^\s]*)/g;

const elements = document.querySelectorAll('[data-c]');

elements.forEach(element => {
  const matches = element.dataset.c.matchAll(regexp);

  for (const match of matches) {
    applyStyle(element, match[1], match[2]);
  }

});
<body data-c="bg-#008eff">
  <h1 data-c="bg-#ff5c5c">Hello, <span data-c="bg-white">World !</span></h1>
  <h1 data-c="text-#ff5c5c pad-20px">Hello, <span data-c="text-#008eff mar-20px">World !</span></h1>
  <h1 data-c="bg-blue bg-red">Hello</h1>
</body>

Related