Skip to content

Commit

Permalink
Merge pull request #5 from EswaramoorthyKarthikeyan/style-support
Browse files Browse the repository at this point in the history
Added custom style support
  • Loading branch information
EswaramoorthyKarthikeyan authored Oct 16, 2024
2 parents fd464f2 + 019d453 commit da53cee
Show file tree
Hide file tree
Showing 11 changed files with 241 additions and 171 deletions.
2 changes: 1 addition & 1 deletion .npmignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
node_modules
color-contrast-checker
example
src
.prettierrc
*.html
*.css
*.map
vite.config.js
96 changes: 54 additions & 42 deletions colorContrast.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import { ColorUtil } from "./colorUtil.js";
class ColorContrastChecker {
constructor(containerElement, criteriaInfo = { fontSize: "23.994px", fontWeight: 700, contrastThreshold: 4.5 }) {
constructor(containerElement, criteriaInfo, styleObj) {
this.criteriaInfo = criteriaInfo
? criteriaInfo
: { fontSize: "23.994px", fontWeight: 700, contrastThreshold: 4.5 };
this.styleObj = styleObj
? styleObj
: {
"border-width": "2px",
"border-style": "dashed",
"border-color": "red",
};
this.colorUtil = new ColorUtil();
if (!containerElement) {
console.info(`since you didn't pass the container Element, we will use the document body`);
}
this.containerElement = containerElement ? containerElement : document.body;
this.contrastThreshold = criteriaInfo.contrastThreshold;
this.criteriaInfo = criteriaInfo;

this.startCheck;
}

init() {
Expand All @@ -19,65 +29,69 @@ class ColorContrastChecker {
}

startObserving() {
this.checkContrastForChildren();
this.observer = new MutationObserver((mutations) => {
for (var mutation of mutations) {
const isContrastRelatedChange =
mutation.attributeName &&
(mutation.attributeName.startsWith("data-color-") ||
mutation.attributeName.startsWith("data-border-"));

// if (mutation.type === "childList") {
// } else if (!isContrastRelatedChange && mutation.type === "attributes") {
// }

if (!isContrastRelatedChange) {
this.checkContrastForChildren(mutation.target);
this.startCheck = setTimeout(() => {
this.checkContrastForChildren();
this.observer = new MutationObserver((mutations) => {
for (var mutation of mutations) {
if (mutation.type === "childList") {
this.checkContrastForChildren(mutation.target);
} else if (mutation.type === "attributes") {
if (mutation.attributeName === "style" || mutation.attributeName === "class") {
this.checkContrastForChildren(mutation.target);
}
}
}
}
});
this.observer.observe(this.containerElement, {
childList: true,
subtree: true,
attributes: true,
});
});
this.observer.observe(this.containerElement, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ["style"],
attributeOldValue: true,
});
}, 1);
}

checkContrastForChildren(element = this.containerElement) {
const children = element.children;
for (const child of children) {
const isValidElement = !child.hasAttribute("disabled") && !child.hasAttribute("hidden");
const isNotDisabled = !child.hasAttribute("disabled");
const isNotHidden = !child.hasAttribute("hidden");
const isValidElement = isNotDisabled && isNotHidden;

if (isValidElement) {
const hasDirectText = Array.from(child.childNodes).some(
const hasValidText = Array.from(child.childNodes).some(
(node) => node.nodeType === Node.TEXT_NODE && node.textContent.trim() !== "",
);
const hasText =
"value" in child
? child.value !== "" && child.tagName.toLowerCase() === "li" && child.value !== 0
: hasDirectText;
: hasValidText && child.textContent !== "";

if (hasText) {
const childStyle = this.colorUtil.getElementStyle(child);
const contrast = this.calculateContrastRatio(
this.colorUtil.getEffectiveColor(child, "bgColor"),
this.colorUtil.getEffectiveColor(child, "color"),
childStyle.color,
);
// check whether the element matches the criteria or not
const isLargeFont = childStyle.fontSize <= this.criteriaInfo.fontSize;
const isBold = childStyle.fontWeight <= this.criteriaInfo.fontWeight;
this.contrastThreshold = isLargeFont && isBold ? 4.5 : 3.1;

if (contrast < this.contrastThreshold) {
console.log(hasDirectText, "has text content", child.tagName, hasText, "value" in child);
this.criteriaInfo.contrastThreshold = isLargeFont && isBold ? 4.5 : 3.1;

if (contrast < this.criteriaInfo.contrastThreshold) {
const currEleStyle = window.getComputedStyle(child);

child.setAttribute("data-color-contrast", contrast);
child.setAttribute("data-border-width", currEleStyle.borderWidth);
child.setAttribute("data-border-style", currEleStyle.borderStyle);
child.setAttribute("data-border-color", currEleStyle.borderColor);

child.style.border = "2px solid red";
if (currEleStyle.borderWidth !== "0px") {
child.setAttribute(
"data-border",
`${currEleStyle.borderWidth} ${currEleStyle.borderStyle} ${currEleStyle.borderColor}`,
);
}

this.colorUtil.setStyle(child, this.styleObj);

const childStyleVal = {
class: `${child.tagName.toLowerCase()}.${child.classList.value}`,
bgColor: this.colorUtil.getEffectiveColor(child, "bgColor"),
Expand All @@ -89,11 +103,9 @@ class ColorContrastChecker {
};
console.table(childStyleVal);
} else {
if (child.hasAttribute("data-border-width")) {
const borderWidth = child.attributes["data-border-width"];
const borderStyle = child.attributes["data-border-style"];
const borderColor = child.attributes["data-border-color"];
child.style.border = `${borderWidth} ${borderStyle} ${borderColor}`;
if (child.hasAttribute("data-border")) {
const border = child.attributes["data-border"];
child.style.border = `${border.value}`;
}
}
}
Expand Down
21 changes: 16 additions & 5 deletions colorUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,15 +150,19 @@ class ColorUtil {
currentElement = currentElement.parentElement;
}

const bodyBg = !this.isTransparent(this.getBgColor(document.body))
const rootBg = !this.isTransparent(this.getBgColor(document.body))
? this.getBgColor(document.body)
: this.getBgColor(document.documentElement);
: !this.isTransparent(this.getBgColor(document.documentElement))
? this.getBgColor(document.documentElement)
: "rgba(255,255,255,1)";

const bodyColor = !this.isTransparent(this.getColor(document.body))
const rootColor = !this.isTransparent(this.getColor(document.body))
? this.getColor(document.body)
: this.getColor(document.documentElement);
: !this.isTransparent(this.getColor(document.documentElement))
? this.getColor(document.documentElement)
: "rgba(255,255,255,1)";

return colorType === "bgColor" ? bodyBg : bodyColor;
return colorType === "bgColor" ? rootBg : rootColor;
}

getBgColor(element) {
Expand All @@ -168,6 +172,13 @@ class ColorUtil {
getColor(element) {
return this.getElementStyle(element).color;
}

setStyle(element, styleObj) {
for (const property in styleObj) {
element.style[property] = styleObj[property];
}
return;
}
}

export { ColorUtil };
2 changes: 1 addition & 1 deletion dist/es5/colorContrast.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit da53cee

Please sign in to comment.