Javascript to change values in stylesheets - javascript

I'm looking to find a way to change every instance of a color in stylesheets that get loaded into a site. I'm working with Prestashop and working with large theme style sheets and modules' stylesheets... so I'm looking to change font colors and background colors. Yes I can do a search and replace... but I'd like to have reusable code that I can use on multiple sites and multiple files and themes.
I've been checking out a bunch of articles on here and found some code that selects all the elements loaded and checks the ComputedStyle and if it equals one value, it changes it to a new value.
function colorToHex(color) {
if (color.substr(0, 1) === '#') {
return color;
}
var digits = /(.*?)rgb\((\d+), (\d+), (\d+)\)/.exec(color);
var red = parseInt(digits[2]);
var green = parseInt(digits[3]);
var blue = parseInt(digits[4]);
var rgb = blue | (green << 8) | (red << 16);
return digits[1] + '#' + rgb.toString(16);
};
function changeColor(from, to) {
var elements = document.getElementsByTagName('*');
var to = '#babaff';
var from = '#f66685';
for (var i=0;i<elements.length;i++) {
var color = window.getComputedStyle(elements[i]).color;
var hex = colorToHex(color);
console.log('color=' ,color, elements[i]);
if (hex == from) {
elements[i].style.color=to;
console.log('its a color match!', elements[i]);
}
var backgroundColor = window.getComputedStyle(elements[i]).background;
console.log('bgcolor=' ,backgroundColor);
if (backgroundColor.indexOf('rgba')<0) {
var hex = colorToHex(backgroundColor);
if (hex == from) {
elements[i].style.backgroundColor=to;
}
}
}
}
It's partially working, but doesn't seem to work on conditional values... like hover or active states. So ideally I'm just looking for something that just finds a string of text (the hex code) and changes it out... and it doesn't care what the element is (class, tag, id) and doesn't matter the rule (background, background-color, color, border, ect) because these themes are pre-built and not standardized.

As you stated:
"ideally I'm just looking for something that just finds a string of text (the hex code) and changes it out"
Thats basically what a search and replace does. (besides the hex stuff)
If you are looking at a problem like replacing a single color in your whole style, and it is very time consuming atm, then you are probably doing something wrong.
As #delinear mentions in his comment, you probably want to use a sass script.
Using some javascript to change all colors after the css has already loaded is performance heavy and not really the way to do it.
I would really suggest a Search&Replace and to use sass variables afterwards.
(If you maybe want to change colors again)
there you can just do something like
$color: #ff00ff;
h1{
background-color: $color;
}
h2{
color: $color;
}
h3{
background: linear-gradient(135deg, red, $color);
}
h2:hover{
color: $color;
}

Related

How to find 5-10 colors which are shades away from a given color, which are all visually distinct (in JavaScript)?

I have a problem where I would like to generate a chart using 5 to 10 variations of 1 primary color, and everything else is a different shade of the main color. The main color is selected by a customer, so this color may be any possible color. It may, for example, be very light, in which case every one of the 5-10 variant colors will be darker than it, or it may be very dark in which case every other variant is lighter than it, or it might be in the middle, so some are darker and some are lighter. It shouldn't matter. Ideally I pass in a given selected color, and it outputs an array of colors which are visually distinct. Something like this:
function getColorPalette(selectedColor, numberOfColorsInOutput = 10) {
// ?
}
I'm just not sure the best approach of figuring out where in the spectrum the color is, and then how to generate the lighter/darker. colors relative to that. Some trickiness involved there.
const givenColor = '#e6ffe6'
getColorPalette(givenColor, 8).map(buildForDOM).forEach(child => {
document.querySelector('#generated').appendChild(child)
})
function getColorPalette(selectedColor, numberOfColorsInOutput = 10) {
const colorObj = tinycolor(selectedColor)
const n = numberOfColorsInOutput
const output = new Array(n)
const fraction = 100 / n
let i = 0
while (i < n) {
output[i] = colorObj.darken(fraction * i).toHex()
i++
}
return output
}
function buildForDOM(color) {
const div = document.createElement('div')
div.style.width = '100px'
div.style.height = '100px'
div.style.background = `#${color}`;
return div
}
<script src="https://unpkg.com/tinycolor2#1.4.1/tinycolor.js"></script>
<div>Given:</div>
<div style="background: #e6ffe6; width: 100px; height: 100px"></div>
<div id="generated">Generated:</div>
This example code generates a few darker ones, but is incorrect as most of the tail is black. It should fill it in so it fills the spectrum with items as far apart as possible (like CSS justify-content: space-between sort of thing, but for the color output). So it somehow needs to figure out what the hue is or something, and it then generates the shades from that.
It doesn't need to be perfect, anything which generates a spectrum of distinct variations on a given hue will do, that covers the full space of shades (from very light to almost black, but not white and black). It doesn't necessarily even need to contain the selected/given color, just use the hue information from it somehow.
For this implementation I used TinyColor (a JS lib), but you can use that or any other color functionality for darkening/lightening things, doesn't matter to me. Just looking for the hex array at the end.
There are many possible approaches, but here is a very basic solution that uses hsl color in calculations and create an array of different lightness in colors (the levels are based on numberOfColorsInOutput).
It uses the same library and only added some conversion to hsl format (the output is kept as hex, in case it is needed to display on page).
A min and max of lightness can be specified for generated colors, so some control can be set to limit the generation of many darker colors.
If needed, further variations in saturation can be added to the calculation.
Example:
const givenColor = "#FF7F50";
const minLight = 0.1;
const maxLight = 0.9;
getColorPalette(givenColor, 8)
.map(buildForDOM)
.forEach((child) => {
document.querySelector("#generated").appendChild(child);
});
function getColorPalette(selectedColor, numberOfColorsInOutput = 10) {
const colorObj = tinycolor(selectedColor);
const n = numberOfColorsInOutput;
const output = new Array(n);
const calcLight = (i) => (i * (maxLight - minLight)) / (n - 1) + minLight;
let i = 0;
while (i < n) {
const baseColor = colorObj.clone().toHsl();
const outputColor = { ...baseColor, l: calcLight(i) };
output[i] = tinycolor(outputColor).toHexString();
i++;
}
return output;
}
function buildForDOM(color) {
const div = document.createElement("div");
div.style.width = "100px";
div.style.height = "100px";
div.style.background = `${color}`;
return div;
}
<script src="https://unpkg.com/tinycolor2#1.4.1/tinycolor.js"></script>
<div>Given:</div>
<div style="background: #FF7F50; width: 100px; height: 100px"></div>
<div id="generated">Generated:</div>
Hope this will help.

Is there a way to automatically change the shade of background color?

Was wondering if there was a way to use a spectrum to change the background color based off of variables such as temp the higher it is, the more the colour will become orange from blue? or would I actually have to assign values
if (temp < 10) {
document.body.className = "background-cold";
} else if (temp > 10) {
document.body.className = "background-warm";
}
.background-cold {
background: linear-gradient(
179.31deg,
rgba(48, 87, 89, 0.97) 9.28%,
#fdfeff 167.45%
);
}
.background-warm {
background: linear-gradient(
179.31deg,
rgba(204, 101, 26, 0.97) 9.28%,
#fdfeff 167.45%
);
}
var hue = temp * someScale; // use some formula to determine the appropriate hue from the temperature
var saturation = 1;
var lightness = 1;
document.body.style.backgroundImage = `linear-gradient(179.31deg, hsla(${hue}%,${saturation}%,${lightness}%) 9.28%, #fdfeff 167.45%)`;
For the approach you intend to do I don't recomemend using the .className attribution. It will be hardcoded and that's not what you want. You can just use style.setProperty(string, string) in wich the first parameter is the CSS atttribute and the second parameter is the CSS value. Both of them need to be strings in order to work.
let colorValue = 'linear-gradient(VALUES)';
document.body.style.setProperty('background', colorValue);
By using the previous code you can now set directly the background you want. However your still need a function to create a dynamic colorValue according to the temperature. This can become a little complex depending on the color values you intend to apply. A possible solution for this can be found in the following answer: https://stackoverflow.com/a/12934900/11860800.

pdf.js: Get the text colour

I have a simple pdf file, containing the words "Hello world", each in a different colour.
I'm loading the PDF, like this:
PDFJS.getDocument('test.pdf').then( onPDF );
function onPDF( pdf )
{
pdf.getPage( 1 ).then( onPage );
}
function onPage( page )
{
page.getTextContent().then( onText );
}
function onText( text )
{
console.log( JSON.stringify( text ) );
}
And I get a JSON output like this:
{
"items" : [{
"str" : "Hello ",
"dir" : "ltr",
"width" : 29.592,
"height" : 12,
"transform" : [12, 0, 0, 12, 56.8, 774.1],
"fontName" : "g_font_1"
}, {
"str" : "world",
"dir" : "ltr",
"width" : 27.983999999999998,
"height" : 12,
"transform" : [12, 0, 0, 12, 86.5, 774.1],
"fontName" : "g_font_1"
}
],
"styles" : {
"g_font_1" : {
"fontFamily" : "serif",
"ascent" : 0.891,
"descent" : 0.216
}
}
}
However, I've not been able to find a way to determine the colour of each word. When I render it, it renders properly, so I know the information is in there somewhere. Is there somewhere I can access this?
As Respawned alluded to, there is no easy answer that will work in all cases. That being said, here are two approaches which seem to work fairly well. Both having upsides and downsides.
Approach 1
Internally, the getTextContent method uses whats called an EvaluatorPreprocessor to parse the PDF operators, and maintain the graphic state. So what we can do is, implement a custom EvaluatorPreprocessor, overwrite the preprocessCommand method, and use it to add the current text color to the graphic state. Once this is in place, anytime a new text chunk is created, we can add a color attribute, and set it to the current color state.
The downsides to this approach are:
Requires modifying the PDFJS source code. It also depends heavily on
the current implementation of PDFJS, and could break if this is
changed.
It will fail in cases where the text is used as a path to be filled with an image. In some PDF creators (such as Photoshop), the way it creates colored text is, it first creates a clipping path from all the given text characters, and then paints a solid image over the path. So the only way to deduce the fill-color is by reading the pixel values from the image, which would require painting it to a canvas. Even hooking into paintChar wont be of much help here, since the fill color will only emerge at a later time.
The upside is, its fairly robust and works irrespective of the page background. It also does not require rendering anything to canvas, so it can be done entirely in the background thread.
Code
All the modifications are made in the core/evaluator.js file.
First you must define the custom evaluator, after the EvaluatorPreprocessor definition.
var CustomEvaluatorPreprocessor = (function() {
function CustomEvaluatorPreprocessor(stream, xref, stateManager, resources) {
EvaluatorPreprocessor.call(this, stream, xref, stateManager);
this.resources = resources;
this.xref = xref;
// set initial color state
var state = this.stateManager.state;
state.textRenderingMode = TextRenderingMode.FILL;
state.fillColorSpace = ColorSpace.singletons.gray;
state.fillColor = [0,0,0];
}
CustomEvaluatorPreprocessor.prototype = Object.create(EvaluatorPreprocessor.prototype);
CustomEvaluatorPreprocessor.prototype.preprocessCommand = function(fn, args) {
EvaluatorPreprocessor.prototype.preprocessCommand.call(this, fn, args);
var state = this.stateManager.state;
switch(fn) {
case OPS.setFillColorSpace:
state.fillColorSpace = ColorSpace.parse(args[0], this.xref, this.resources);
break;
case OPS.setFillColor:
var cs = state.fillColorSpace;
state.fillColor = cs.getRgb(args, 0);
break;
case OPS.setFillGray:
state.fillColorSpace = ColorSpace.singletons.gray;
state.fillColor = ColorSpace.singletons.gray.getRgb(args, 0);
break;
case OPS.setFillCMYKColor:
state.fillColorSpace = ColorSpace.singletons.cmyk;
state.fillColor = ColorSpace.singletons.cmyk.getRgb(args, 0);
break;
case OPS.setFillRGBColor:
state.fillColorSpace = ColorSpace.singletons.rgb;
state.fillColor = ColorSpace.singletons.rgb.getRgb(args, 0);
break;
}
};
return CustomEvaluatorPreprocessor;
})();
Next, you need to modify the getTextContent method to use the new evaluator:
var preprocessor = new CustomEvaluatorPreprocessor(stream, xref, stateManager, resources);
And lastly, in the newTextChunk method, add a color attribute:
color: stateManager.state.fillColor
Approach 2
Another approach would be to extract the text bounding boxes via getTextContent, render the page, and for each text, get the pixel values which reside within its bounds, and take that to be the fill color.
The downsides to this approach are:
The computed text bounding boxes are not always correct, and in some cases may even be off completely (eg: rotated text). If the bounding box does not cover at least partially the actual text on canvas, then this method will fail. We can recover from complete failures, by checking that the text pixels have a color variance greater than a threshold. The rationale being, if bounding box is completely background, it will have little variance, in which case we can fallback to a default text color (or maybe even the color of k nearest-neighbors).
The method assumes the text is darker than the background. Otherwise, the background could be mistaken as the fill color. This wont be a problem is most cases, as most docs have white backgrounds.
The upside is, its simple, and does not require messing with the PDFJS source-code. Also, it will work in cases where the text is used as a clipping path, and filled with an image. Though this can become hazy when you have complex image fills, in which case, the choice of text color becomes ambiguous.
Demo
http://jsfiddle.net/x2rajt5g/
Sample PDF's to test:
https://www.dropbox.com/s/0t5vtu6qqsdm1d4/color-test.pdf?dl=1
https://www.dropbox.com/s/cq0067u80o79o7x/testTextColour.pdf?dl=1
Code
function parseColors(canvasImgData, texts) {
var data = canvasImgData.data,
width = canvasImgData.width,
height = canvasImgData.height,
defaultColor = [0, 0, 0],
minVariance = 20;
texts.forEach(function (t) {
var left = Math.floor(t.transform[4]),
w = Math.round(t.width),
h = Math.round(t.height),
bottom = Math.round(height - t.transform[5]),
top = bottom - h,
start = (left + (top * width)) * 4,
color = [],
best = Infinity,
stat = new ImageStats();
for (var i, v, row = 0; row < h; row++) {
i = start + (row * width * 4);
for (var col = 0; col < w; col++) {
if ((v = data[i] + data[i + 1] + data[i + 2]) < best) { // the darker the "better"
best = v;
color[0] = data[i];
color[1] = data[i + 1];
color[2] = data[i + 2];
}
stat.addPixel(data[i], data[i+1], data[i+2]);
i += 4;
}
}
var stdDev = stat.getStdDev();
t.color = stdDev < minVariance ? defaultColor : color;
});
}
function ImageStats() {
this.pixelCount = 0;
this.pixels = [];
this.rgb = [];
this.mean = 0;
this.stdDev = 0;
}
ImageStats.prototype = {
addPixel: function (r, g, b) {
if (!this.rgb.length) {
this.rgb[0] = r;
this.rgb[1] = g;
this.rgb[2] = b;
} else {
this.rgb[0] += r;
this.rgb[1] += g;
this.rgb[2] += b;
}
this.pixelCount++;
this.pixels.push([r,g,b]);
},
getStdDev: function() {
var mean = [
this.rgb[0] / this.pixelCount,
this.rgb[1] / this.pixelCount,
this.rgb[2] / this.pixelCount
];
var diff = [0,0,0];
this.pixels.forEach(function(p) {
diff[0] += Math.pow(mean[0] - p[0], 2);
diff[1] += Math.pow(mean[1] - p[1], 2);
diff[2] += Math.pow(mean[2] - p[2], 2);
});
diff[0] = Math.sqrt(diff[0] / this.pixelCount);
diff[1] = Math.sqrt(diff[1] / this.pixelCount);
diff[2] = Math.sqrt(diff[2] / this.pixelCount);
return diff[0] + diff[1] + diff[2];
}
};
This question is actually extremely hard if you want to do it to perfection... or it can be relatively easy if you can live with solutions that work only some of the time.
First of all, realize that getTextContent is intended for searchable text extraction and that's all it's intended to do.
It's been suggested in the comments above that you use page.getOperatorList(), but that's basically re-implementing the whole PDF drawing model in your code... which is basically silly because the largest chunk of PDFJS does exactly that... except not for the purpose of text extraction but for the purpose of rendering to canvas. So what you want to do is to hack canvas.js so that instead of just setting its internal knobs it also does some callbacks to your code. Alas, if you go this way, you won't be able to use stock PDFJS, and I rather doubt that your goal of color extraction will be seen as very useful for PDFJS' main purpose, so your changes are likely not going to get accepted upstream, so you'll likely have to maintain your own fork of PDFJS.
After this dire warning, what you'd need to minimally change are the functions where PDFJS has parsed the PDF color operators and sets its own canvas painting color. That happens around line 1566 (of canvas.js) in function setFillColorN. You'll also need to hook the text render... which is rather a character renderer at canvas.js level, namely CanvasGraphics_paintChar around line 1270. With these two hooked, you'll get a stream of callbacks for color changes interspersed between character drawing sequences. So you can reconstruct the color of character sequences reasonably easy from this.. in the simple color cases.
And now I'm getting to the really ugly part: the fact that PDF has an extremely complex color model. First there are two colors for drawing anything, including text: a fill color and stroke (outline) color. So far not too scary, but the color is an index in a ColorSpace... of which there are several, RGB being only one possibility. Then there's also alpha and compositing modes, so the layers (of various alphas) can result in a different final color depending on the compositing mode. And the PDFJS has not a single place where it accumulates color from layers.. it simply [over]paints them as they come. So if you only extract the fill color changes and ignore alpha, compositing etc.. it will work but not for complex documents.
Hope this helps.
There's no need to patch pdfjs, the transform property gives the x and y, so you can go through the operator list and find the setFillColor op that precedes the text op at that point.

Algorithm to separate dark colors from light colors? (example: anything under #ffffff/2 is dark?)

I have an iframe that needs to be embedded on various sites and 2 stylesheets (light and dark) are applied based on the site text color. At this moment, I apply the stylesheets this way:
if text color > #ffffff / 2 => dark stylesheet
if text color < #ffffff / 2 => light stylesheet
But obviously this doesn't always work.
So I need to find a better algorithm to separate dark colors from light colors. I know this can never be 100% accurate, but at least I need something that is better than my solution.
Any ideas?
Thanks!
coffeescript code:
calculateTheme = (hexcol)->
if (parseInt(hexcol, 16) > 0xffffff/2)
return "dark"
else
return "light"
I would have thought that part of the problem lies in the fact that RGB colours have 3 elements and can be darkened or lightened, to make a mic of colours.
I.e: #FF0000 is red, but as the value decreases, it gets closer to dark red, #EE0000
The same principle applies to the other 2 components. I would recommend building the algorithm, where you extract all 3 components and then test, then to see how close they are to 00.
Source: http://www.rapidtables.com/web/color/RGB_Color.htm
EDIT: This article seems like a good source of information.
Check if following code works
function getNumberRange(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getRandomHexColor() {
var result = "0x";
for (var i = 0; i < 6; i++) {
result += getNumberRange(0, 15).toString(16);
}
return result;
}
var colorVal = getRandomHexColor();
if (colorVal > 0xffffff / 2) {
alert(colorVal + " : is light");
} else {
alert(colorVal + " : is dark");
}

How to compare colors in JavaScript?

Why doesn't this work? Even though the colour is equal to #ECECF4 it still alerts "No".
It is selecting the corrent element as I have tested it. Is there a better way to write this?
<script type="text/javascript">
function weekclick() {
if (document.getElementById('w1').style.backgroundColor == "#ECECF4") {
alert("Yes");
} else {
alert("No");
}
}
</script>
Comparing colors as part of the business logic should be avoided at all cost.
Instead, keep the logic in JavaScript and act according to a state kept somewhere. Then, if you want to send a visual feedback to the user through a change of color, add a class to the element. That way, JavaScript only knows about class names and the styling is always isolated in the CSS as it should.
$(".list").on("click", "li", function(){
$(this).toggleClass('active');
});
.list {
width: 100%;
padding: 0;
}
.list li {
padding: 5px 10px;
list-style: none;
cursor: pointer;
}
.list li:hover {
background-color: rgba(0, 0, 0, 0.05);
}
.list li.active {
background-color: #eeeecc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list">
<li>test 1</li>
<li>test 2</li>
<li>test 3</li>
</ul>
That being said, OP's code works for me with Chrome 17.0.963.56 and Firefox 8.0. When you don't know what to compare, just use console.log() to see what it looks like.
Note that #ECECF4 is the same color as rgb(236, 236, 244) but in a different representation.
IE7 and IE8 output the HEX value, IE9 and up and other browsers output the RGB format. So comparing color with cross-browser compatibility is a tricky task and the best way to do it isn't beautiful.
I made a simple function which works for most cases with most browser, even with color set through CSS.
function weekclick() {
var elemColor = getStyle(this, "backgroundColor"),
color = "rgb(238, 238, 204)";
console.log("Broswer returned elem color: ", elemColor);
// IE7 and IE8 output the hex value
if (elemColor.slice(0, 1) === '#') elemColor = hexToRgb(elemColor);
console.log(elemColor, " === ", color, "?", elemColor === color);
}
// Source: https://stackoverflow.com/a/41354868/1218980
// Inspired by: https://stackoverflow.com/a/22744598/1218980
function getStyle(el, prop) {
return (typeof getComputedStyle !== 'undefined' ?
getComputedStyle(el, null) :
el.currentStyle
)[prop];
}
// Slightly modified version to quickly return a string
// https://stackoverflow.com/a/5624139/1218980
function hexToRgb(hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? "rgb(" + [
parseInt(result[1], 16),
parseInt(result[2], 16),
parseInt(result[3], 16)
].join(', ') + ")" : null;
}
#css-div {
background-color: #eeeecc;
}
<div style="Background-color:#eeeecc" onclick="javascript:weekclick.call(this);">#eeeecc</div>
<div style="Background-color:#EEC" onclick="javascript:weekclick.call(this);">#EEC</div>
<div style="background-color:hsla(60, 50%, 86.7%, 1)" onclick="javascript:weekclick.call(this);">hsla(60, 50%, 86.7%, 1)</div>
<div style="background-color:rgb(238, 238, 204)" onclick="javascript:weekclick.call(this);">rgb(238, 238, 204)</div>
<div id="css-div" onclick="javascript:weekclick.call(this);">css</div>
I call the weekclick function with javascript:weekclick.call(this) passing the element itself as the context of the callback, making it easy to access the element with this.
It could be extended to take alpha into account when using HSLA or RGBA.
When I originally wrote this answer back in 2012, I used navigator.appName === "Microsoft Internet Explorer" to know if it was IE7 and the color to compare was changed to its HEX equivalent. Don't do that as it won't work today.
Use a canvas to compare colors.
Fill one pixel using the color string
and the other pixel using the Element getComputedStyle color property.
Compare the two pixels data using Array.from and JSON.stingify
/**
* Test if Element color property holds a specific color.
* https://stackoverflow.com/a/60689673/383904
*
* #param {Object} el The DOM Node Element
* #param {String} prop A CSS property color property
* #param {String} color A valid CSS color value
* #return {Boolean} True if element color matches
*/
function isElPropColor(el, prop, color) {
const ctx = document.createElement('canvas').getContext('2d');
ctx.fillStyle = color;
ctx.fillRect( 0, 0, 1, 1 );
ctx.fillStyle = getComputedStyle(el, null).getPropertyValue(prop);
ctx.fillRect( 1, 0, 1, 1 );
const a = JSON.stringify(Array.from(ctx.getImageData(0, 0, 1, 1).data));
const b = JSON.stringify(Array.from(ctx.getImageData(1, 0, 1, 1).data));
ctx.canvas = null;
return a === b;
}
// TEST (PS: see CSS!):
const el = document.body;
const prop = 'background-color';
console.log(isElPropColor(el, prop, 'red')); // obviously true :)
console.log(isElPropColor(el, prop, '#f00')); // true
console.log(isElPropColor(el, prop, 'rgb(255, 0, 0)')); // true
console.log(isElPropColor(el, prop, 'hsl(0, 100%, 50%)')); // true
console.log(isElPropColor(el, prop, 'hsla(0, 100%, 50%, 1)')); // true
body {background: red; }
The buts and whys
Most modern browsers calculate and convert the color value to RGB/A.
But we should not rely on doing strict equality comparison like:
// (Say the element is really red)
const isRed = myElement.style.backgroundColor === "rgb(255,0,0)"; // false
False because it's actually "rgb(255, 0, 0)", with spaces.
No guarantee some browser tomorrow will not convert to "rgba(255, 0, 0, 1)", or HSLA perhaps?
Edge and IE will return the value used in CSS or overwritten by our JS
We cannot reliably compare two DIV styles using getComputedStyle
and we cannot even create an "in-memory" DIV element since we need to - append it to the DOM, than use getComputedStyle(tempDIVElement, null).getPropertyValue('background-color') and than remove it from the DOM. It's a waste of DOM recalculations, paints, and it's not guaranteed some wondering stylesheet !important did not messed up our temporary DIV styles div {background: fuchsia !important; } giving false-positives "Is red? True! blue is blue because of !important".
Why canvas?
A canvas can stay in memory. No need to append to DOM, set colors, remove element.
The returned pixel data is always guaranteed to be [R, G, B, A] (RGBA being 0-255 values)
A wondering CSS rule will not mess up the assigned color
Useful links:
Canvas_API MDN
CanvasRenderingContext2D/getImageData MDN
Array/from MDN
JSON/stringify MDN
Window/getComputedStyle MDN
I'm actually just learning javascript, but instead of creating a function that converted rgb() to hex you can create a div of the same background-color you are looking for and compared it to that div's background color. If you happen to already have a div of that hex value you can just do this:
//javascript
if (document.getElementId('desiredElementToCompare').style.backgroundColor === document.getElementId('elementWithTheDesiredHexString').style.backgroundColor)
//jQuery
if ($('#desiredElementToCompare').css('background-color') === $('#elementWithTheDesiredHexString').css('background-color')
You can create a div with a function and then do the comparison like this:
var compareHex = (hex) => {
var hexString = document.createElement('div')
hexString.style.backgroundColor = `${hex}`
return hexString.style.backgroundColor
}
//then compare
//javascript
if (document.getElementId('desiredElementToCompare').style.backgroundColor === compareHex("#ECECF4"))
//jQuery
if($('#desiredElementToCompare').css('background-color') === compareHex("#ECECF4")
This way suggests using JQuery's background-color which standardises the response to rgb(r, g, b).
How to get the background color of an element using javascript?
Maybe this answer could help. Convert the color code to hex and then compare each RGB color/channel (i don't know the word)
https://stackoverflow.com/a/25666938/1757214
I think is better and easy compare two numbers than two strings
I would advice using the '===' stric equal (i think this is the name).
Like:
if (document.getElementById('test').style.backgroundColor === "rgb(236, 236, 244)") {

Categories

Resources