Is there any way to use regular expression alone or with help of javascript to do the following
from
<div class="type-c red blue">
to
<div type="c" class="red blue">
Is there any way to use regular expression alone or with help of javascript to do the following
from
<div class="type-c red blue">
to
<div type="c" class="red blue">
You don't even need regular expressions.
(Okay, you do, but only to find the x
value in type-x
. Proof here.)
You can use a mix of attribute selectors, the data-* attribute standard, and the Element.setAttribute() method.
Here's an example.
function doChange() {
// Find all divs with a 'type-x' class
let myDivs = document.querySelectorAll('div[class*="type-"]');
myDivs.forEach(curDiv => {
// Get the specific 'x' for the type
let curType = /(?<=type-)[A-Za-z\-]+/.exec(curDiv.classList.toString())[0];
// Set the 'data-type' attribute
curDiv.setAttribute('data-type', curType);
// Remove the 'type-x' class
curDiv.classList.toggle('type-' + curType);
// Write the 'classList' and 'data-type' attributes for show
curDiv.innerText = 'classList: ' + curDiv.classList
+ '; data-type: ' + curDiv.getAttribute('data-type') + ';';
});
}
<div class="type-a red blue">classList: type-a red blue; data-type: undefined;</div>
<div class="red type-b blue">classList: red type-b blue; data-type: undefined;</div>
<div class="red blue type-c">classList: red blue type-c; data-type: undefined;</div>
<button onclick="doChange()">Click Me</button>
This isn't the solution. Just offers some insights on text parsing this problem without regex. As the OP did mention a possible non-regex solution. Also this answer was posted during a very long comment session, and as such requirements changed.
This solution (in like fashion of @DakotaMethvin's) also attempts to solve it without regex, and as well, resides on a more exact pattern match with class="type-
. As such the following code will indeed break (logically) if that's not the match.
However in light of FanCheung's more recent comment [type-x] not always the first class entry
, I'm only posting this answer because I already started on posting it.
function replaceIt( s, sentinel ) {
// sentinel: e.g. class="type-
if (sentinel) {
}
else sentinel = 'class="type-';
return s.replaceAll(sentinel , function( match, offset ) {
// get the position of the whitespace after "type-c"
nextSpace = s.indexOf(" ", offset);
// extract the "type" up until and excluding the "next space"
typeVar = s.substring( offset + sentinel.length, nextSpace);
// get the position of the 2nd double quote char
nextDoubleQuote = s.indexOf("\"", nextSpace);
// extract the new "class" names e.g. red blue
newClass = s.substring( nextSpace + 1, nextDoubleQuote);
// create the replacement string. Also something must be done with the leftover chars; prepend them with 'data-source'.
replacement = 'type="' + typeVar + '" class="' + newClass +'" data-source="';
// debugging code
console.log( match + ": " + offset + ": " + typeVar + ": " + newClass);
return replacement;
});
}
console.log( replaceIt( '<div class="type-c red blue">') );
But as noted on recent developments on what I noted on The entire before "class" string will have to be tokenized.
So this solution only works if "type-" is the 1st class.
This regular expression will match what you describe, regardless of the position of "type-xxx" in class attribute
/class="([^"]*)type-(\w+)([^"]*)"/g
Combining with a string replace
let value = '<div class="type-a b">test</div><div class="a type-b">test 2</div>';
value.replace(/class="([^"]*)type-(\w+)([^"]*)"/g, 'type="$2" class="$1$3"');
this will yield the result
<div type="a" class="b">test</div><div type="b" class="a">test 2</div>