js function or nested loop called in loop , breaks it - javascript

This function pretend to read from a csv and populate a table of input field . Having rows and columns I need to nest loops or call function in a loop, or even call function by itself . I tried already all the combinations . In the best case it populates only the first row ( A1,B1,C1, etc.. ) , it knows exactly the starting point in buffer and everything apparently is correct in the numbers it makes , BUT the outer loop is broken after the first iteration (whatever I do with my code about inner function, or inner loop, or nested function ) . I tried "continue", "return", the closure stuff.
function getPage(p) {
var init = buffer.indexOf("Page:" + p + ",");
var init_index = init + 1;
var linea = "";
var r = 1;
for (var x in buffer) {
if (x > init_index) {
linea = buffer[x].split(",");
read_line(linea, r);
r++;
}
}
}
function read_line(l, r) {
var debug = new Array();
var n = 0;
while (n < l.length + 1) {
var colons = ["A" + r, "B" + r, "C" + r, "D" + r, "E" + r, "F" + r, "G" + r, "H" + r, "se_ckbox" + r, "me_ckbox" + r, "sim_ckbox" + r, "I" + r, "J" + r, "K" + r, "L" + r, "M" + r, "N" + r, "O" + r, "P" + r, "Q" + r, "R" + r, "S" + r, "T" + r, "U" + r, "V" + r];
var field = l[n + 1];
debug.push("col:" + colons[n].toString() + "\nVAL:" + field + "\n");
document.getElementById(colons[n].toString()).value = field;
document.getElementById("debug").value = debug.toString();
n++;
}
return;
}

Related

about JS functioning

Here is an example of a string reverse function with recursion.
I'd like to understand why:
(1) If I switch the return line inner actions like this:
return word.charAt(0) + reversed(word.substring(1))
I get the string again but not reversed.
(2) Where the 'word.charAt()' letters are being saved through the nested calls (and overall if it's the same with a regular function), memory wise what I miss here, what keeps them accumulated with tact and where are they 'going'.
I'd like an explanation of some kind to how the memory concept works in js to understand better the relations as I code ( I think especially in and out of functions in my case).
var reverseArray = reversedItems(arr)
function reverseAll(items) {
return items.map(function reversed(word) {
if (word === "") return ""
return reversed(word.substring(1)) + word.charAt(0)
})
}
You should understand the reversed function separately before concerning yourself with reverseAll -
function reverse(word) {
if (word === "") return ""
return reverse(word.substring(1)) + word.charAt(0)
}
console.log(reverse("hello world"))
Starting with reverse("hello_world") we can easily trace the evaluation. Whenever the input word is non-empty, a new stack frame is opened with the recursive call to the sub-problem reverse(word.substring(1)). The ... + word.charAt(0) portion remains in the calling frame and only resumes after the descendant frame returns -
reverse("hello world") =
reverse("ello world") + "h" =
reverse("llo world") + "e" + "h" =
reverse("lo world") + "l" + "e" + "h" =
reverse("o world") + "l" + "l" + "e" + "h" =
reverse(" world") + "o" + "l" + "l" + "e" + "h" =
reverse("world") + " " + "o" + "l" + "l" + "e" + "h" =
reverse("orld") + "w" + " " + "o" + "l" + "l" + "e" + "h" =
reverse("rld") + "o" + "w" + " " + "o" + "l" + "l" + "e" + "h" =
reverse("ld") + "r" + "o" + "w" + " " + "o" + "l" + "l" + "e" + "h" =
reverse("d") + "l" + "r" + "o" + "w" + " " + "o" + "l" + "l" + "e" + "h" =
reverse("") + "d" + "l" + "r" + "o" + "w" + " " + "o" + "l" + "l" + "e" + "h" =
Here we meet the base case, recursion stops and empty string is returned. Now all of the open stack frames collapse, starting with the deepest frame returning its value to its caller -
"" + "d" + "l" + "r" + "o" + "w" + " " + "o" + "l" + "l" + "e" + "h" =
"d" + "l" + "r" + "o" + "w" + " " + "o" + "l" + "l" + "e" + "h" =
"dl" + "r" + "o" + "w" + " " + "o" + "l" + "l" + "e" + "h" =
"dlr" + "o" + "w" + " " + "o" + "l" + "l" + "e" + "h" =
"dlro" + "w" + " " + "o" + "l" + "l" + "e" + "h" =
"dlrow" + " " + "o" + "l" + "l" + "e" + "h" =
"dlrow " + "o" + "l" + "l" + "e" + "h" =
"dlrow o" + "l" + "l" + "e" + "h" =
"dlrow ol" + "l" + "e" + "h" =
"dlrow oll" + "e" + "h" =
"dlrow olle" + "h" =
And finally we can close the outermost call to reverse and return the result -
"dlrow olleh"
In this program, the stack is used to sequence operations and combine resulting values in the intended order. If the input word was significantly large, you would run into a stack overflow because too many frames would be opened and you essentially break the JavaScript runtime limit for such computations. Memory or heap is only used for all of the intermediate string allocations.
The ever-growing stack in the program above demonstrates a recursive process. This is characteristic of any recursive program that doesn't use a tail call. A tail call is simply the last call in your function, returned directly to its caller -
function reverse(word) {
function loop(r, w) {
if (w == "") return r
return loop(w[0] + r, w.substr(1)) // <- loop is the last called
}
return loop("", word)
}
console.log(reverse("hello world"))
This demonstrates a linear iterative process, so called because the process created by the recursive function stays flat and straight like a line -
reverse("hello world") =
loop("", "hello world") =
loop("h", "ello world") =
loop("eh", "llo world") =
loop("leh", "lo world") =
loop("lleh", "o world") =
loop("olleh", " world") =
loop(" olleh", "world") =
loop("w olleh", "orld") =
loop("ow olleh", "rld") =
loop("row olleh", "ld") =
loop("lrow olleh", "d") =
loop("dlrow olleh", "") =
"dlrow olleh"
Some languages have tail call optimization which means the recursive function like the one above would be safe from the stack overflow problem. The compiler or runtime effectively converts the recursive call into a loop -
function reverse(word) {
function loop(r, w) {
while (true) {
if (w == "") return r
r = w[0] + r
w = w.substr(1)
}
}
return loop("", word)
}
console.log(reverse("hello world"))
Above only 2 frames are used and memory allocations of 3 bindings, word, r and w. Memory allocations to compute + and w.substr(1) are also made and are recaptured by the runtime's automatic garbage collector.
In ECMAScript 6, tail call elimination was added to the specification however it is unsupported in almost every popular runtime and that is unlikely to change. That doesn't mean however we are constrained to writing recursive programs using imperative style while loops. There are various techniques to make recursive programs safe even in JavaScript, even in runtimes that do not support this optimization.
Consider this implementation of reverse using loop and recur -
const reverse = word =>
loop
( (r = "", w = word) =>
w == ""
? r
: recur(w[0] + r, w.substr(1))
)
The non-recursive loop and recur functions are generic and allow us to use them to write most recursive programs that will not cause a stack overflow -
const recur = (...values) =>
({ recur, values })
const loop = run =>
{ let r = run ()
while (r && r.recur === recur)
r = run (...r.values)
return r
}
console.log(reverse("hello world"))
This has a very similar performance profile to the while loop above. Only 2 stack frames and 3 bindings with an small overhead of some immediately garbage-collected values like +, substr and recur -
Expand the snippet below to verify the result in your own browser -
const recur = (...values) =>
({ recur, values })
const loop = run =>
{ let r = run ()
while (r && r.recur === recur)
r = run (...r.values)
return r
}
const reverse = word =>
loop
( (r = "", w = word) =>
w == ""
? r
: recur(w[0] + r, w.substr(1))
)
console.log(reverse("hello world"))
"dlrow olleh"
In fact, any recursive program, tail call or not, can be made stack-safe using various techniques. If this sort of thing sounds interesting to you, see this related Q&A for an in-depth exploration of the topic.

Getting color property value as hex value [duplicate]

Using the following jQuery will get the RGB value of an element's background color:
$('#selector').css('backgroundColor');
Is there a way to get the hex value rather than the RGB?
TL;DR
Use this clean one-line function with both rgb and rgba support:
const rgba2hex = (rgba) => `#${rgba.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+\.{0,1}\d*))?\)$/).slice(1).map((n, i) => (i === 3 ? Math.round(parseFloat(n) * 255) : parseFloat(n)).toString(16).padStart(2, '0').replace('NaN', '')).join('')}`
2021 updated answer
Much time has passed since I originally answered this question. Then cool ECMAScript 5 and 2015+ features became largely available on browsers, like arrow functions, Array.map, String.padStart and template strings. Since some years, it's possible to write cross-browser one-liner rgb2hex:
const rgb2hex = (rgb) => `#${rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/).slice(1).map(n => parseInt(n, 10).toString(16).padStart(2, '0')).join('')}`
// Use as you wish...
console.log(rgb2hex('rgb(0,0,0)'))
console.log(rgb2hex('rgb(255, 255, 255)'))
console.log(rgb2hex('rgb(255,0,0)'))
console.log(rgb2hex('rgb(38, 170, 90)'))
It works by using a regular expression to get each digit inside the rgb string, slice(1) to get only the digits (the first result of match is the full string itself), map to iterate through each digit, each iteration converting to Number with parseInt, then back to an hexadecimal String (through a base-16 conversion), adding zero if needed via padStart. Finally, join each converted/adjusted digit to a unique String starting with '#'.
Of course, we could extend it without much effort as an one-liner rgba2hex:
const rgba2hex = (rgba) => `#${rgba.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+\.{0,1}\d*))?\)$/).slice(1).map((n, i) => (i === 3 ? Math.round(parseFloat(n) * 255) : parseFloat(n)).toString(16).padStart(2, '0').replace('NaN', '')).join('')}`
// Now it doesn't matter if 'rgb' or 'rgba'...
console.log(rgba2hex('rgb(0,0,0)'))
console.log(rgba2hex('rgb(255, 255, 255)'))
console.log(rgba2hex('rgb(255,0,0)'))
console.log(rgba2hex('rgb(38, 170, 90)'))
console.log(rgba2hex('rgba(255, 0, 0, 0.5)'))
console.log(rgba2hex('rgba(0,255,0,1)'))
console.log(rgba2hex('rgba(127,127,127,0.25)'))
And that's it. But if you want to dive deep in the old school JavaScript world, keep reading.
Original 2010 answer
Here is the cleaner solution I wrote based on #Matt suggestion:
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
Some browsers already returns colors as hexadecimal (as of Internet Explorer 8 and below). If you need to deal with those cases, just append a condition inside the function, like #gfrobenius suggested:
function rgb2hex(rgb) {
if (/^#[0-9A-F]{6}$/i.test(rgb)) return rgb;
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
If you're using jQuery and want a more complete approach, you can use CSS Hooks available since jQuery 1.4.3, as I showed when answering this question: Can I force jQuery.css("backgroundColor") returns on hexadecimal format?
var hexDigits = new Array
("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
//Function to convert rgb color to hex format
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
function hex(x) {
return isNaN(x) ? "00" : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
}
(Source)
Most browsers seem to return the RGB value when using:
$('#selector').css('backgroundColor');
Only I.E (only 6 tested so far) returns the Hex value.
To avoid error messages in I.E, you could wrap the function in an if statement:
function rgb2hex(rgb) {
if ( rgb.search("rgb") == -1 ) {
return rgb;
} else {
rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
}
Updated #ErickPetru for rgba compatibility:
function rgb2hex(rgb) {
rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
I updated the regex to match the alpha value if defined, but not use it.
Here's an ES6 one liner that doesn't use jQuery:
var rgb = document.querySelector('#selector').style['background-color'];
return '#' + rgb.substr(4, rgb.indexOf(')') - 4).split(',').map((color) => parseInt(color).toString(16).padStart(2, '0')).join('');
Here is a version that also checks for transparent, I needed this since my object was to insert the result into a style attribute, where the transparent version of a hex color is actually the word "transparent"..
function rgb2hex(rgb) {
if ( rgb.search("rgb") == -1 ) {
return rgb;
}
else if ( rgb == 'rgba(0, 0, 0, 0)' ) {
return 'transparent';
}
else {
rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
}
Short
// c - color str e.g."rgb(12,233,43)", result color hex e.g. "#0ce92b"
let rgb2hex=c=>'#'+c.match(/\d+/g).map(x=>(+x).toString(16).padStart(2,0)).join``
// rgb - color str e.g."rgb(12,233,43)", result color hex e.g. "#0ce92b"
let rgb2hex= c=> '#'+c.match(/\d+/g).map(x=>(+x).toString(16).padStart(2,0)).join``
console.log(rgb2hex("rgb(12,233,43"));
Function that returns background color of an element in hex.
function getBgColorHex(elem){
var color = elem.css('background-color')
var hex;
if(color.indexOf('#')>-1){
//for IE
hex = color;
} else {
var rgb = color.match(/\d+/g);
hex = '#'+ ('0' + parseInt(rgb[0], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[1], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[2], 10).toString(16)).slice(-2);
}
return hex;
}
usage example:
$('#div1').click(function(){
alert(getBgColorHex($(this));
}
jsfiddle
Readable && Reg-exp free (no Reg-exp)
I've created a function that uses readable basic functions and no reg-exps.
The function accepts color in hex, rgb or rgba CSS format and returns hex representation.
EDIT: there was a bug with parsing out rgba() format, fixed...
function getHexColor( color ){
//if color is already in hex, just return it...
if( color.indexOf('#') != -1 ) return color;
//leave only "R,G,B" :
color = color
.replace("rgba", "") //must go BEFORE rgb replace
.replace("rgb", "")
.replace("(", "")
.replace(")", "");
color = color.split(","); // get Array["R","G","B"]
// 0) add leading #
// 1) add leading zero, so we get 0XY or 0X
// 2) append leading zero with parsed out int value of R/G/B
// converted to HEX string representation
// 3) slice out 2 last chars (get last 2 chars) =>
// => we get XY from 0XY and 0X stays the same
return "#"
+ ( '0' + parseInt(color[0], 10).toString(16) ).slice(-2)
+ ( '0' + parseInt(color[1], 10).toString(16) ).slice(-2)
+ ( '0' + parseInt(color[2], 10).toString(16) ).slice(-2);
}
Same answer like #Jim F answer but ES6 syntax , so, less instructions :
const rgb2hex = (rgb) => {
if (rgb.search("rgb") === -1) return rgb;
rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
const hex = (x) => ("0" + parseInt(x).toString(16)).slice(-2);
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
};
color class taken from bootstrap color picker
// Color object
var Color = function(val) {
this.value = {
h: 1,
s: 1,
b: 1,
a: 1
};
this.setColor(val);
};
Color.prototype = {
constructor: Color,
//parse a string to HSB
setColor: function(val){
val = val.toLowerCase();
var that = this;
$.each( CPGlobal.stringParsers, function( i, parser ) {
var match = parser.re.exec( val ),
values = match && parser.parse( match ),
space = parser.space||'rgba';
if ( values ) {
if (space === 'hsla') {
that.value = CPGlobal.RGBtoHSB.apply(null, CPGlobal.HSLtoRGB.apply(null, values));
} else {
that.value = CPGlobal.RGBtoHSB.apply(null, values);
}
return false;
}
});
},
setHue: function(h) {
this.value.h = 1- h;
},
setSaturation: function(s) {
this.value.s = s;
},
setLightness: function(b) {
this.value.b = 1- b;
},
setAlpha: function(a) {
this.value.a = parseInt((1 - a)*100, 10)/100;
},
// HSBtoRGB from RaphaelJS
// https://github.com/DmitryBaranovskiy/raphael/
toRGB: function(h, s, b, a) {
if (!h) {
h = this.value.h;
s = this.value.s;
b = this.value.b;
}
h *= 360;
var R, G, B, X, C;
h = (h % 360) / 60;
C = b * s;
X = C * (1 - Math.abs(h % 2 - 1));
R = G = B = b - C;
h = ~~h;
R += [C, X, 0, 0, X, C][h];
G += [X, C, C, X, 0, 0][h];
B += [0, 0, X, C, C, X][h];
return {
r: Math.round(R*255),
g: Math.round(G*255),
b: Math.round(B*255),
a: a||this.value.a
};
},
toHex: function(h, s, b, a){
var rgb = this.toRGB(h, s, b, a);
return '#'+((1 << 24) | (parseInt(rgb.r) << 16) | (parseInt(rgb.g) << 8) | parseInt(rgb.b)).toString(16).substr(1);
},
toHSL: function(h, s, b, a){
if (!h) {
h = this.value.h;
s = this.value.s;
b = this.value.b;
}
var H = h,
L = (2 - s) * b,
S = s * b;
if (L > 0 && L <= 1) {
S /= L;
} else {
S /= 2 - L;
}
L /= 2;
if (S > 1) {
S = 1;
}
return {
h: H,
s: S,
l: L,
a: a||this.value.a
};
}
};
how to use
var color = new Color("RGB(0,5,5)");
color.toHex()
Just to add to #Justin's answer above..
it should be
var rgb = document.querySelector('#selector').style['background-color'];
return '#' + rgb.substr(4, rgb.indexOf(')') - 4).split(',').map((color) => String("0" + parseInt(color).toString(16)).slice(-2)).join('');
As the above parse int functions truncates leading zeroes, thus produces incorrect color codes of 5 or 4 letters may be... i.e. for rgb(216, 160, 10) it produces #d8a0a while it should be #d8a00a.
Thanks
This one looks a bit nicer:
var rgb = $('#selector').css('backgroundColor').match(/\d+/g);
var r = parseInt(rgb[0], 10);
var g = parseInt(rgb[1], 10);
var b = parseInt(rgb[2], 10);
var hex = '#'+ r.toString(16) + g.toString(16) + b.toString(16);
a more succinct one-liner:
var rgb = $('#selector').css('backgroundColor').match(/\d+/g);
var hex = '#'+ Number(rgb[0]).toString(16) + Number(rgb[1]).toString(16) + Number(rgb[2]).toString(16);
forcing jQuery to always return hex:
$.cssHooks.backgroundColor = {
get: function(elem) {
if (elem.currentStyle)
var bg = elem.currentStyle["backgroundColor"];
else if (window.getComputedStyle) {
var bg = document.defaultView.getComputedStyle(elem,
null).getPropertyValue("background-color");
}
if (bg.search("rgb") == -1) {
return bg;
} else {
bg = bg.match(/\d+/g);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(bg[0]) + hex(bg[1]) + hex(bg[2]);
}
}
}
Since the question was using JQuery, here’s a JQuery plugin based on Daniel Elliott’s code:
$.fn.cssAsHex = function(colorProp) {
var hexDigits = '0123456789abcdef';
function hex(x) {
return isNaN(x) ? '00' : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
};
// Convert RGB color to Hex format
function rgb2hex(rgb) {
var rgbRegex = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
return '#' + hex(rgbRegex[1]) + hex(rgbRegex[2]) + hex(rgbRegex[3]);
};
return rgb2hex(this.css(colorProp));
};
Use it like:
var hexBackgroundColor = $('#myElement').cssAsHex('background-color');
Here's a solution I found that does not throw scripting errors in IE:
http://haacked.com/archive/2009/12/29/convert-rgb-to-hex.aspx
Steven Pribilinskiy's answer drops leading zeroes, for example #ff0000 becomes #ff00.
A solution is to append a leading 0 and substring off the last 2 digits.
var rgb = $('#selector').css('backgroundColor').match(/\d+/g);
var hex = '#'+ String('0' + Number(rgb[0]).toString(16)).slice(-2) + String('0' + Number(rgb[1]).toString(16)).slice(-2) + String('0' + Number(rgb[2]).toString(16)).slice(-2);
Improved function "hex"
function hex(x){
return isNaN(x) ? "00" : hexDigits[x >> 4] + hexDigits[x & 0xf];
// or option without hexDigits array
return (x >> 4).toString(16)+(x & 0xf).toString(16);
}
Here is my solution, also does touppercase by the use of an argument and checks for other possible white-spaces and capitalisation in the supplied string.
var a = "rgb(10, 128, 255)";
var b = "rgb( 10, 128, 255)";
var c = "rgb(10, 128, 255 )";
var d = "rgb ( 10, 128, 255 )";
var e = "RGB ( 10, 128, 255 )";
var f = "rgb(10,128,255)";
var g = "rgb(10, 128,)";
var rgbToHex = (function () {
var rx = /^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i;
function pad(num) {
if (num.length === 1) {
num = "0" + num;
}
return num;
}
return function (rgb, uppercase) {
var rxArray = rgb.match(rx),
hex;
if (rxArray !== null) {
hex = pad(parseInt(rxArray[1], 10).toString(16)) + pad(parseInt(rxArray[2], 10).toString(16)) + pad(parseInt(rxArray[3], 10).toString(16));
if (uppercase === true) {
hex = hex.toUpperCase();
}
return hex;
}
return;
};
}());
console.log(rgbToHex(a));
console.log(rgbToHex(b, true));
console.log(rgbToHex(c));
console.log(rgbToHex(d));
console.log(rgbToHex(e));
console.log(rgbToHex(f));
console.log(rgbToHex(g));
On jsfiddle
Speed comparison on jsperf
A further improvement could be to trim() the rgb string
var rxArray = rgb.trim().match(rx),
My beautiful non-standard solution
HTML
<div id="selector" style="background-color:#f5b405"></div>
jQuery
$("#selector").attr("style").replace("background-color:", "");
Result
#f5b405
Convert RGB to Hex
I am using Jasmine protractor and I was getting errors like
- Expected [ 'rgba(255, 255, 255, 1)' ] to contain '#fff'.
Below function worked fine for me.
function RGBAToHexA(test:string) {
let sep = test.toString().indexOf(",") > -1 ? "," : " ";
const rgba = test.toString().substring(5).split(")")[0].split(sep);
console.log(rgba)
let r = (+rgba[0]).toString(16),
g = (+rgba[1]).toString(16),
b = (+rgba[2]).toString(16),
a = Math.round(+rgba[3] * 255).toString(16);
if (r.length == 1)
r = "0" + r;
if (g.length == 1)
g = "0" + g;
if (b.length == 1)
b = "0" + b;
if (a.length == 1)
a = "0" + a;
return "#" + r + g + b + a;
}
describe('Check CSS', function() {
it('should check css of login page', async function(){
browser.waitForAngularEnabled(true);
browser.actions().mouseMove(element(by.css('.btn-auth, .btn-auth:hover'))).perform(); // mouse hover on button
csspage.Loc_auth_btn.getCssValue('color').then(function(color){
console.log(RGBAToHexA(color))
expect( RGBAToHexA(color)).toContain(cssData.hoverauth.color);
})
To all the Functional Programming lovers, here is a somewhat functional approach :)
const getHexColor = (rgbValue) =>
rgbValue.replace("rgb(", "").replace(")", "").split(",")
.map(colorValue => (colorValue > 15 ? "0" : "") + colorValue.toString(16))
.reduce((acc, hexValue) => acc + hexValue, "#")
then use it like:
const testRGB = "rgb(13,23,12)"
getHexColor(testRGB)
my compact version
//Function to convert rgb color to hex format
function rgb2hex(rgb) {
if(/^#/.test(rgb))return rgb;// if returns colors as hexadecimal
let re = /\d+/g;
let hex = x => (x >> 4).toString(16)+(x & 0xf).toString(16);
return "#"+hex(re.exec(rgb))+hex(re.exec(rgb))+hex(re.exec(rgb));
}
full cases (rgb, rgba, transparent...etc) solution (coffeeScript)
rgb2hex: (rgb, transparentDefault=null)->
return null unless rgb
return rgb if rgb.indexOf('#') != -1
return transparentDefault || 'transparent' if rgb == 'rgba(0, 0, 0, 0)'
rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
hex = (x)->
("0" + parseInt(x).toString(16)).slice(-2)
'#' + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3])
Hi here's my solution after getting the element's color with Javascript
function rgb_hex(rgb_string_js){ //example: "rgb(102,54,255)"
var new_rgb_list = rgb_string_js.replace("rgb(","").replace(")","").split(",");
return ("#" + parseInt(new_rgb_list[0]).toString(16) + parseInt(new_rgb_list[1]).toString(16) + parseInt(new_rgb_list[2]).toString(16));
}

Check if given three line segments represented by coordinates of 4 element array can form a triangle

I need to check if given three line segments form a triangle. A line segment can be expressed as an array of 4 integers giving the end-points coordinates in the form [ x1, y1, x2, y2 ].
So I need to write a function that is given as input three line segments K, L and M and will return 1 if they form a triangle, 0 otherwise.
If the input parameters are outside the range of the algorithm supports I need to return -1.
Examples :
function trigTest(K, L, M)
var K=[2,3,6,9], L=[8,1,6,9], M=[8,1,2,3], X=[1,7,6,9]
trigTest(K, L, M) // -> 1
trigTest(L, K, M) // -> 1
trigTest(M, K, L) // -> 1
trigTest(L, L, M) // -> 0
trigTest(X, L, M) // -> 0
I actually have a solution but it's pretty cumbersome and I don't think it is the right way. First I calculate the distance of every line segment and then I use triangle inequalities to check if they can actually form a triangles base on their lengths.
function distance(line){
var x1 = line[0],
y1 = line[1],
x2 = line[2],
y2 = line[3];
return Math.sqrt(Math.pow((x2-x1),2) + Math.pow(y2-y1),2)
}
function trigTest(K,L,M){
var distanceK = distance(K), distanceL = distance(L), distanceM = distance(M);
if((distanceK + distanceL) > distanceM && (distanceK + distanceM) > distanceL && distanceL + distanceM > distanceK){
// algorithm here
}else{
return 0;
}
}
Update
Thanks to #antoniskamamis and #trincot I have made a similar solution if someone wants to stick with arrays instead of working with strings. Big shout out to them.
function trigTest(K, L, M) {
var points = [];
var k = dots(K), l = dots(L), m = dots(M);
if(ifDotsOnSameLineAreEqual(k) || ifDotsOnSameLineAreEqual(l) || ifDotsOnSameLineAreEqual(m)){
return false;
}else{
return points.concat(k,l,m).every(function(point, index, array){
return array.filter(function(i){ return ifTwoDotsAreEqual(i,point)}).length == 2;
})
}
}
function dots(line) {
var x1 = line[0],
y1 = line[1],
x2 = line[2],
y2 = line[3];
return [[x1,y1],[x2, y2]];
}
function ifTwoDotsAreEqual(x,y){
return x[0] == y[0] && x[1] == y[1];
}
function ifDotsOnSameLineAreEqual(line){
return ifTwoDotsAreEqual(line[0],line[1]);
}
you could use this approach
function trigTest(a,b,c){
var parts = [];
Array.prototype.slice.call(arguments).forEach(function(item){
parts.push(item.slice(0,2).join("|"));
parts.push(item.slice(2).join("|"));
})
return parts.every(function(item, index, array){
return array.filter( function(x){ return x == item}).length == 2;
})
}
What it does is:
runs through the list of arguments
Array.prototype.slice.call(arguments).forEach
seperates the arrays into points first two, last two as strings parts.push(item.slice(0,2).join(""));parts.push(item.slice(2).join(""));
given the array of points it checks that each point is present two times parts.every(function(item, index, array){ return array.filter( function(x){ return x == item}).length == 2; })
Using a 'one liner'
function trigTest(a,b,c){
var slice = Array.prototype.slice;
return slice.call(arguments).reduce(function(previous, current){
previous.push(current.slice(0,2).join("|"));
previous.push(current.slice(2).join("|"));
return previous;
}, [])
.every(function(item, index, array){
return array.filter( function(x){ return x == item; }).length == 2;
})
}
Checking for zero length lines
if we know that the inputs are not validated to be lines before we have to add a check if any of the given lines has start and end points the same (is a 0 length line or a point)
in this case our code will have to be like this
function trigTest(a,b,c){
var slice = Array.prototype.slice;
if(slice.call(arguments).some(isPoint)){
return false;
};
return slice.call(arguments).reduce(function(previous, current){
previous.push(current.slice(0,2).join("|"));
previous.push(current.slice(2).join("|"));
return previous;
}, [])
.every(function(item, index, array){
return array.filter( function(x){ return x == item; }).length == 2;
})
}
function isPoint(value){
return value[0] == value[2] && value[1] == value[3];
}
Based on your examples, the key criteria is that you have exactly two copies of three x,y coordinates, so rather than deal with this from a geometric or trigonometric standpoint, you may have an easier time dealing with this based on basic set-theory: to have a triangle formed from three points A, B, C, your line segments must follow the pattern [Ax, Ay, Bx, By], [Bx, By, Cx, Cy], [Cx, Cy, Ax, Ay].
These segments are not required to be in that order, such as [Bx, By, Ax, Ay] is also valid for the first term.
To check for a valid triangle, count repeated coordinates first to verify two repeats of three unique coordinates (this will also eliminate repeated line segments), then verify that each line segment is non-zero in length (not [Ax, Ay, Ax, Ay]). Those two checks will handle the first two requirements.
I don't know the boundary limits, so I cannot advise on how to test whether it is outside the bounds of the algorithm, but I suspect that will require checking the actual coordinate range, which is integer arithmetic.
This approach should be usable in any javascript engine, although your specific choice of javascript engine will determine the best way to implement it.
var getRandom = () => 1+ Math.floor( Math.random() * 3 ) ;
// get random line
var getLine = () =>
{
do
var l = {
'a' : {
'x' : getRandom(),
'y' : getRandom()
},
'b' : {
'x' : getRandom(),
'y' : getRandom()
}
};
// repeat until startPoint differ from endPoint
while ( l.a.x == l.b.x & l.a.y == l.b.y )
return l;
};
var match = (K, L, M) => {
// Tirangle consist of three points
// three lines -> six points
var p1 = K.a.x + "," + K.a.y,
p2 = K.b.x + "," + K.b.y,
p3 = L.a.x + "," + L.a.y,
p4 = L.b.x + "," + L.b.y,
p5 = M.a.x + "," + M.a.y,
p6 = M.b.x + "," + M.b.y;
// count frequency
var freq = {};
freq[p1] = freq[p1] + 1 || 1;
freq[p2] = freq[p2] + 1 || 1;
freq[p3] = freq[p3] + 1 || 1;
freq[p4] = freq[p4] + 1 || 1;
freq[p5] = freq[p5] + 1 || 1;
freq[p6] = freq[p6] + 1 || 1;
// result Array
var result = Array();
for ( point in freq ){
// if the point is common for two lines add to result array
freq[point] == 2 ? result.push( point ) : false;
}
return result;
}
var test = () => {
// Three random lines
var K = getLine(), L = getLine(), M = getLine();
// Test if three lines has three common points
if ( match(K, L, M).length == 3 ) {
printSvg(K,L,M);
return 1
} else {
return 0
}
}
// run when document ready
var app = () => {
// div#box needed to print svg with triangles
const box = document.getElementById('box');
// test random lines, repeat
for (x =0; x <= 1000; x++) {
t = test ();
}
}
// fire app() when document ready
document.onreadystatechange = ()=> document.readyState == "complete" ? app() : false;
// format legend html
var printWsp = (L) => "("+ L.a.x + ","+ L.a.y+") ("+L.b.x+","+L.b.y+")";
// append svg to div#box
var printSvg = (K, L, M) => {
var legend = '<div class="legend">K ' + printWsp(K) +"<br>L " + printWsp(L) +"<br>M "+ printWsp(M) + "</div>";
var svgStr = "<svg height='250' width='250'>";
svgStr += "<line x1="+K.a.x*60 +" y1="+K.a.y*60 +" x2="+K.b.x*60 +" y2="+K.b.y*60 +" style='stroke:rgb(255,0,0);stroke-width:2' />";
svgStr += "<line x1="+L.a.x*60 +" y1="+L.a.y*60 +" x2="+L.b.x*60 +" y2="+L.b.y*60 +" style='stroke:rgb(0,255,0);stroke-width:2' />";
svgStr += "<line x1="+M.a.x*60 +" y1="+M.a.y*60 +" x2="+M.b.x*60 +" y2="+M.b.y*60 +" style='stroke:rgb(255,0,255);stroke-width:2' />";
svgStr += "</svg> ";
box.insertAdjacentHTML('beforeend', legend);
box.insertAdjacentHTML('beforeend', svgStr);
}

javascript find correct gray for black and white effect

I have a function that will convert a hex code into rgb for me:
function getRGB(color){
var matchColors = /#(\w{2})(\w{2})(\w{2})/;
var match = matchColors.exec(color);
var r = parseInt(match[1], 16).toString() + ",";
var g = parseInt(match[2], 16).toString() + ",";
var b = parseInt(match[3], 16).toString();
answer = 'rgb(' + r + g + b + ')' ;
return answer;
}
I would like to have a second function that will also take a hex code, but then modify it such that it is the equivalent gray of what the -webit-filter: grayscale(100%) would do.
the function would look like this:
function gray(color){
var matchColors = /#(\w{2})(\w{2})(\w{2})/;
var match = matchColors.exec(color);
var r = parseInt(match[1], 16).toString() + ",";
var g = parseInt(match[2], 16).toString() + ",";
var b = parseInt(match[3], 16).toString();
//code to modify figure out the rgb gray value and assign it to the variable G
answer = 'rgb(' + G + ',' + G + ',' + G + ')' ;
return answer;
}
I am not sure on what determines the equivalent gray based on a color, and my research did not help much either. Any ideas?
Use the grayscale formula, like this:
var r = parseInt(match[1], 16),
g = parseInt(match[1], 16),
b = parseInt(match[1], 16),
val = Math.floor(0.2126 * r + 0.7152 * g + 0.0722 * b)
answer = 'rgb(' + val + ',' + val + ',' + val + ')'
return answer
This is the formula:
Y' = 0.2126R + 0.7152G + 0.0722B
Updated fiddle

convert rgb color to hex using js or jquery when jquery .css gives rgb [duplicate]

Using the following jQuery will get the RGB value of an element's background color:
$('#selector').css('backgroundColor');
Is there a way to get the hex value rather than the RGB?
TL;DR
Use this clean one-line function with both rgb and rgba support:
const rgba2hex = (rgba) => `#${rgba.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+\.{0,1}\d*))?\)$/).slice(1).map((n, i) => (i === 3 ? Math.round(parseFloat(n) * 255) : parseFloat(n)).toString(16).padStart(2, '0').replace('NaN', '')).join('')}`
2021 updated answer
Much time has passed since I originally answered this question. Then cool ECMAScript 5 and 2015+ features became largely available on browsers, like arrow functions, Array.map, String.padStart and template strings. Since some years, it's possible to write cross-browser one-liner rgb2hex:
const rgb2hex = (rgb) => `#${rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/).slice(1).map(n => parseInt(n, 10).toString(16).padStart(2, '0')).join('')}`
// Use as you wish...
console.log(rgb2hex('rgb(0,0,0)'))
console.log(rgb2hex('rgb(255, 255, 255)'))
console.log(rgb2hex('rgb(255,0,0)'))
console.log(rgb2hex('rgb(38, 170, 90)'))
It works by using a regular expression to get each digit inside the rgb string, slice(1) to get only the digits (the first result of match is the full string itself), map to iterate through each digit, each iteration converting to Number with parseInt, then back to an hexadecimal String (through a base-16 conversion), adding zero if needed via padStart. Finally, join each converted/adjusted digit to a unique String starting with '#'.
Of course, we could extend it without much effort as an one-liner rgba2hex:
const rgba2hex = (rgba) => `#${rgba.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+\.{0,1}\d*))?\)$/).slice(1).map((n, i) => (i === 3 ? Math.round(parseFloat(n) * 255) : parseFloat(n)).toString(16).padStart(2, '0').replace('NaN', '')).join('')}`
// Now it doesn't matter if 'rgb' or 'rgba'...
console.log(rgba2hex('rgb(0,0,0)'))
console.log(rgba2hex('rgb(255, 255, 255)'))
console.log(rgba2hex('rgb(255,0,0)'))
console.log(rgba2hex('rgb(38, 170, 90)'))
console.log(rgba2hex('rgba(255, 0, 0, 0.5)'))
console.log(rgba2hex('rgba(0,255,0,1)'))
console.log(rgba2hex('rgba(127,127,127,0.25)'))
And that's it. But if you want to dive deep in the old school JavaScript world, keep reading.
Original 2010 answer
Here is the cleaner solution I wrote based on #Matt suggestion:
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
Some browsers already returns colors as hexadecimal (as of Internet Explorer 8 and below). If you need to deal with those cases, just append a condition inside the function, like #gfrobenius suggested:
function rgb2hex(rgb) {
if (/^#[0-9A-F]{6}$/i.test(rgb)) return rgb;
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
If you're using jQuery and want a more complete approach, you can use CSS Hooks available since jQuery 1.4.3, as I showed when answering this question: Can I force jQuery.css("backgroundColor") returns on hexadecimal format?
var hexDigits = new Array
("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
//Function to convert rgb color to hex format
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
function hex(x) {
return isNaN(x) ? "00" : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
}
(Source)
Most browsers seem to return the RGB value when using:
$('#selector').css('backgroundColor');
Only I.E (only 6 tested so far) returns the Hex value.
To avoid error messages in I.E, you could wrap the function in an if statement:
function rgb2hex(rgb) {
if ( rgb.search("rgb") == -1 ) {
return rgb;
} else {
rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
}
Updated #ErickPetru for rgba compatibility:
function rgb2hex(rgb) {
rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
I updated the regex to match the alpha value if defined, but not use it.
Here's an ES6 one liner that doesn't use jQuery:
var rgb = document.querySelector('#selector').style['background-color'];
return '#' + rgb.substr(4, rgb.indexOf(')') - 4).split(',').map((color) => parseInt(color).toString(16).padStart(2, '0')).join('');
Here is a version that also checks for transparent, I needed this since my object was to insert the result into a style attribute, where the transparent version of a hex color is actually the word "transparent"..
function rgb2hex(rgb) {
if ( rgb.search("rgb") == -1 ) {
return rgb;
}
else if ( rgb == 'rgba(0, 0, 0, 0)' ) {
return 'transparent';
}
else {
rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
}
Short
// c - color str e.g."rgb(12,233,43)", result color hex e.g. "#0ce92b"
let rgb2hex=c=>'#'+c.match(/\d+/g).map(x=>(+x).toString(16).padStart(2,0)).join``
// rgb - color str e.g."rgb(12,233,43)", result color hex e.g. "#0ce92b"
let rgb2hex= c=> '#'+c.match(/\d+/g).map(x=>(+x).toString(16).padStart(2,0)).join``
console.log(rgb2hex("rgb(12,233,43"));
Function that returns background color of an element in hex.
function getBgColorHex(elem){
var color = elem.css('background-color')
var hex;
if(color.indexOf('#')>-1){
//for IE
hex = color;
} else {
var rgb = color.match(/\d+/g);
hex = '#'+ ('0' + parseInt(rgb[0], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[1], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[2], 10).toString(16)).slice(-2);
}
return hex;
}
usage example:
$('#div1').click(function(){
alert(getBgColorHex($(this));
}
jsfiddle
Readable && Reg-exp free (no Reg-exp)
I've created a function that uses readable basic functions and no reg-exps.
The function accepts color in hex, rgb or rgba CSS format and returns hex representation.
EDIT: there was a bug with parsing out rgba() format, fixed...
function getHexColor( color ){
//if color is already in hex, just return it...
if( color.indexOf('#') != -1 ) return color;
//leave only "R,G,B" :
color = color
.replace("rgba", "") //must go BEFORE rgb replace
.replace("rgb", "")
.replace("(", "")
.replace(")", "");
color = color.split(","); // get Array["R","G","B"]
// 0) add leading #
// 1) add leading zero, so we get 0XY or 0X
// 2) append leading zero with parsed out int value of R/G/B
// converted to HEX string representation
// 3) slice out 2 last chars (get last 2 chars) =>
// => we get XY from 0XY and 0X stays the same
return "#"
+ ( '0' + parseInt(color[0], 10).toString(16) ).slice(-2)
+ ( '0' + parseInt(color[1], 10).toString(16) ).slice(-2)
+ ( '0' + parseInt(color[2], 10).toString(16) ).slice(-2);
}
Same answer like #Jim F answer but ES6 syntax , so, less instructions :
const rgb2hex = (rgb) => {
if (rgb.search("rgb") === -1) return rgb;
rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
const hex = (x) => ("0" + parseInt(x).toString(16)).slice(-2);
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
};
color class taken from bootstrap color picker
// Color object
var Color = function(val) {
this.value = {
h: 1,
s: 1,
b: 1,
a: 1
};
this.setColor(val);
};
Color.prototype = {
constructor: Color,
//parse a string to HSB
setColor: function(val){
val = val.toLowerCase();
var that = this;
$.each( CPGlobal.stringParsers, function( i, parser ) {
var match = parser.re.exec( val ),
values = match && parser.parse( match ),
space = parser.space||'rgba';
if ( values ) {
if (space === 'hsla') {
that.value = CPGlobal.RGBtoHSB.apply(null, CPGlobal.HSLtoRGB.apply(null, values));
} else {
that.value = CPGlobal.RGBtoHSB.apply(null, values);
}
return false;
}
});
},
setHue: function(h) {
this.value.h = 1- h;
},
setSaturation: function(s) {
this.value.s = s;
},
setLightness: function(b) {
this.value.b = 1- b;
},
setAlpha: function(a) {
this.value.a = parseInt((1 - a)*100, 10)/100;
},
// HSBtoRGB from RaphaelJS
// https://github.com/DmitryBaranovskiy/raphael/
toRGB: function(h, s, b, a) {
if (!h) {
h = this.value.h;
s = this.value.s;
b = this.value.b;
}
h *= 360;
var R, G, B, X, C;
h = (h % 360) / 60;
C = b * s;
X = C * (1 - Math.abs(h % 2 - 1));
R = G = B = b - C;
h = ~~h;
R += [C, X, 0, 0, X, C][h];
G += [X, C, C, X, 0, 0][h];
B += [0, 0, X, C, C, X][h];
return {
r: Math.round(R*255),
g: Math.round(G*255),
b: Math.round(B*255),
a: a||this.value.a
};
},
toHex: function(h, s, b, a){
var rgb = this.toRGB(h, s, b, a);
return '#'+((1 << 24) | (parseInt(rgb.r) << 16) | (parseInt(rgb.g) << 8) | parseInt(rgb.b)).toString(16).substr(1);
},
toHSL: function(h, s, b, a){
if (!h) {
h = this.value.h;
s = this.value.s;
b = this.value.b;
}
var H = h,
L = (2 - s) * b,
S = s * b;
if (L > 0 && L <= 1) {
S /= L;
} else {
S /= 2 - L;
}
L /= 2;
if (S > 1) {
S = 1;
}
return {
h: H,
s: S,
l: L,
a: a||this.value.a
};
}
};
how to use
var color = new Color("RGB(0,5,5)");
color.toHex()
Just to add to #Justin's answer above..
it should be
var rgb = document.querySelector('#selector').style['background-color'];
return '#' + rgb.substr(4, rgb.indexOf(')') - 4).split(',').map((color) => String("0" + parseInt(color).toString(16)).slice(-2)).join('');
As the above parse int functions truncates leading zeroes, thus produces incorrect color codes of 5 or 4 letters may be... i.e. for rgb(216, 160, 10) it produces #d8a0a while it should be #d8a00a.
Thanks
This one looks a bit nicer:
var rgb = $('#selector').css('backgroundColor').match(/\d+/g);
var r = parseInt(rgb[0], 10);
var g = parseInt(rgb[1], 10);
var b = parseInt(rgb[2], 10);
var hex = '#'+ r.toString(16) + g.toString(16) + b.toString(16);
a more succinct one-liner:
var rgb = $('#selector').css('backgroundColor').match(/\d+/g);
var hex = '#'+ Number(rgb[0]).toString(16) + Number(rgb[1]).toString(16) + Number(rgb[2]).toString(16);
forcing jQuery to always return hex:
$.cssHooks.backgroundColor = {
get: function(elem) {
if (elem.currentStyle)
var bg = elem.currentStyle["backgroundColor"];
else if (window.getComputedStyle) {
var bg = document.defaultView.getComputedStyle(elem,
null).getPropertyValue("background-color");
}
if (bg.search("rgb") == -1) {
return bg;
} else {
bg = bg.match(/\d+/g);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(bg[0]) + hex(bg[1]) + hex(bg[2]);
}
}
}
Since the question was using JQuery, here’s a JQuery plugin based on Daniel Elliott’s code:
$.fn.cssAsHex = function(colorProp) {
var hexDigits = '0123456789abcdef';
function hex(x) {
return isNaN(x) ? '00' : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
};
// Convert RGB color to Hex format
function rgb2hex(rgb) {
var rgbRegex = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
return '#' + hex(rgbRegex[1]) + hex(rgbRegex[2]) + hex(rgbRegex[3]);
};
return rgb2hex(this.css(colorProp));
};
Use it like:
var hexBackgroundColor = $('#myElement').cssAsHex('background-color');
Here's a solution I found that does not throw scripting errors in IE:
http://haacked.com/archive/2009/12/29/convert-rgb-to-hex.aspx
Steven Pribilinskiy's answer drops leading zeroes, for example #ff0000 becomes #ff00.
A solution is to append a leading 0 and substring off the last 2 digits.
var rgb = $('#selector').css('backgroundColor').match(/\d+/g);
var hex = '#'+ String('0' + Number(rgb[0]).toString(16)).slice(-2) + String('0' + Number(rgb[1]).toString(16)).slice(-2) + String('0' + Number(rgb[2]).toString(16)).slice(-2);
Improved function "hex"
function hex(x){
return isNaN(x) ? "00" : hexDigits[x >> 4] + hexDigits[x & 0xf];
// or option without hexDigits array
return (x >> 4).toString(16)+(x & 0xf).toString(16);
}
Here is my solution, also does touppercase by the use of an argument and checks for other possible white-spaces and capitalisation in the supplied string.
var a = "rgb(10, 128, 255)";
var b = "rgb( 10, 128, 255)";
var c = "rgb(10, 128, 255 )";
var d = "rgb ( 10, 128, 255 )";
var e = "RGB ( 10, 128, 255 )";
var f = "rgb(10,128,255)";
var g = "rgb(10, 128,)";
var rgbToHex = (function () {
var rx = /^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i;
function pad(num) {
if (num.length === 1) {
num = "0" + num;
}
return num;
}
return function (rgb, uppercase) {
var rxArray = rgb.match(rx),
hex;
if (rxArray !== null) {
hex = pad(parseInt(rxArray[1], 10).toString(16)) + pad(parseInt(rxArray[2], 10).toString(16)) + pad(parseInt(rxArray[3], 10).toString(16));
if (uppercase === true) {
hex = hex.toUpperCase();
}
return hex;
}
return;
};
}());
console.log(rgbToHex(a));
console.log(rgbToHex(b, true));
console.log(rgbToHex(c));
console.log(rgbToHex(d));
console.log(rgbToHex(e));
console.log(rgbToHex(f));
console.log(rgbToHex(g));
On jsfiddle
Speed comparison on jsperf
A further improvement could be to trim() the rgb string
var rxArray = rgb.trim().match(rx),
My beautiful non-standard solution
HTML
<div id="selector" style="background-color:#f5b405"></div>
jQuery
$("#selector").attr("style").replace("background-color:", "");
Result
#f5b405
Convert RGB to Hex
I am using Jasmine protractor and I was getting errors like
- Expected [ 'rgba(255, 255, 255, 1)' ] to contain '#fff'.
Below function worked fine for me.
function RGBAToHexA(test:string) {
let sep = test.toString().indexOf(",") > -1 ? "," : " ";
const rgba = test.toString().substring(5).split(")")[0].split(sep);
console.log(rgba)
let r = (+rgba[0]).toString(16),
g = (+rgba[1]).toString(16),
b = (+rgba[2]).toString(16),
a = Math.round(+rgba[3] * 255).toString(16);
if (r.length == 1)
r = "0" + r;
if (g.length == 1)
g = "0" + g;
if (b.length == 1)
b = "0" + b;
if (a.length == 1)
a = "0" + a;
return "#" + r + g + b + a;
}
describe('Check CSS', function() {
it('should check css of login page', async function(){
browser.waitForAngularEnabled(true);
browser.actions().mouseMove(element(by.css('.btn-auth, .btn-auth:hover'))).perform(); // mouse hover on button
csspage.Loc_auth_btn.getCssValue('color').then(function(color){
console.log(RGBAToHexA(color))
expect( RGBAToHexA(color)).toContain(cssData.hoverauth.color);
})
To all the Functional Programming lovers, here is a somewhat functional approach :)
const getHexColor = (rgbValue) =>
rgbValue.replace("rgb(", "").replace(")", "").split(",")
.map(colorValue => (colorValue > 15 ? "0" : "") + colorValue.toString(16))
.reduce((acc, hexValue) => acc + hexValue, "#")
then use it like:
const testRGB = "rgb(13,23,12)"
getHexColor(testRGB)
my compact version
//Function to convert rgb color to hex format
function rgb2hex(rgb) {
if(/^#/.test(rgb))return rgb;// if returns colors as hexadecimal
let re = /\d+/g;
let hex = x => (x >> 4).toString(16)+(x & 0xf).toString(16);
return "#"+hex(re.exec(rgb))+hex(re.exec(rgb))+hex(re.exec(rgb));
}
full cases (rgb, rgba, transparent...etc) solution (coffeeScript)
rgb2hex: (rgb, transparentDefault=null)->
return null unless rgb
return rgb if rgb.indexOf('#') != -1
return transparentDefault || 'transparent' if rgb == 'rgba(0, 0, 0, 0)'
rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
hex = (x)->
("0" + parseInt(x).toString(16)).slice(-2)
'#' + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3])
Hi here's my solution after getting the element's color with Javascript
function rgb_hex(rgb_string_js){ //example: "rgb(102,54,255)"
var new_rgb_list = rgb_string_js.replace("rgb(","").replace(")","").split(",");
return ("#" + parseInt(new_rgb_list[0]).toString(16) + parseInt(new_rgb_list[1]).toString(16) + parseInt(new_rgb_list[2]).toString(16));
}

Categories