I need to write a javascript function, which compares two arguments passed in. They will be strings. And represent CSS classes.
The aim of the function, is to weight CSS specificity. So if an argument passed in, is a CSS ID, it should be returned rather than the second argument. (EG if a = '#id', it will beat b = '.red').
Kinda getting lost on the best approach for my javascript function. Not sure whether to use if/else statements or switch/case. Either way, it's getting messy and need some pointers.
Here's what I'm trying to do:
A class selector beats a tagname. (eg div.red > p).
// '*' weakest - anything beats this
// tagname beats '*'. EG 'div' beats '*'
// 2 tagnames beats 1 tagname - EG 'div div' beats 'p'
// class selector beats tagname - EG 'div.red' beats 'div'
// id is strongest #id - '#ID' beats all the above
function compare(a,b){
const low = '*';
const tagname = /^[a-zA-Z]+$/;
const twoTagnames = /^[a-zA-Z\s]*$/;
if (a === low) {
a < b;
return b;
} else (b === low); {
b < a;
return a;
}
if (a.includes('#')) {
a < b;
return b;
} else if (b.includes('#')) {
b < a;
return a;
}
}
compare('*','#id');
I ran into this exact question recently during a job interview and I was able to figure it out like so:
function compare(a, b) {
let aItems = a.split([" "]);
let aRating = [0, 0, 0];
aItems.forEach((i) => {
if (i.split("#").length > 1) {
aRating[0] = aRating[0] + (i.split("#").length - 1);
}
if (i.split(".").length > 1) {
aRating[1] = aRating[1] + (i.split(".").length - 1);
}
if (!i.startsWith("#") && !i.startsWith(".")) {
aRating[2] = aRating[2] + 1;
}
});
let bItems = b.split([" "]);
let bRating = [0, 0, 0];
bItems.forEach((i) => {
if (i.split("#").length > 1) {
bRating[0] = bRating[0] + (i.split("#").length - 1);
}
if (i.split(".").length > 1) {
bRating[1] = bRating[1] + (i.split(".").length - 1);
}
if (!i.startsWith("#") && !i.startsWith(".")) {
bRating[2] = bRating[2] + 1;
}
});
if (aRating[0] > bRating[0]) {
return a;
} else if (bRating[0] > aRating[0]) {
return b;
}
if (aRating[1] > bRating[1]) {
return a;
} else if (bRating[1] > aRating[1]) {
return b;
} else if (
bRating[0] === aRating[0] &&
bRating[2] === 0 &&
aRating[2] === 0
) {
return b;
}
if (aRating[2] > bRating[2]) {
return a;
} else if (bRating[2] > aRating[2]) {
return b;
}
}
There is one issue though, say you are comparing tagnames
(ie, html
, body
where the more specific, the higher the specificity), then you might have some difficulty. I was able to hack my way through it string of if else tests.