Find key if text matches value - javascript

I'm trying to highlight only the number between the brackets in regular js. Colors are based on value (type of fruit in this scenario).
HTML
<a class="temple" href="something # URL">LARGE FRUIT (215)</a>
<a class="temple" href="something # URL">PINEAPPLE (38)</a>
<a class="temple" href="something # URL">RED APPLE (76)</a>
My Dict
var my_dict = {'BLUE':['ORANGE'], ['GRAPE']
'YELLOW':['PINEAPPLE'], ['KIWI']}
I could do them independently using but it's messy and may break the code if a tag is removed:
let Pineapple = document.querySelector('.temple')
PINEAPPLE.innerHTML = PINEAPPLE.innerHTML.replace(/\([^\)]*\)/, '<span class="red">$&</span>')
This is what I have so far:
function color(){
let fruits = document.querySelector('.temple')
for (let i = 0; i<fruits.length; i++) {
let str = fruits.innerHTML //this gives me the text I need.
My goal is to use the results (value) to find the key and ultimately color just the number.

that ?
const my_dict =
{ BLUE: [ 'ORANGE', 'GRAPE' ]
, YELLOW: [ 'PINEAPPLE', 'KIWI' ]
, RED: [ 'APPLE' ]
};
// ES5 code
const my_dict_reverse =
Object
.keys( my_dict)
.reduce( function(r,k)
{
my_dict[k].forEach( function(fruit) { r[fruit] = k } );
return r;
},{});
// my_dict_reverse = { ORANGE: 'BLUE', GRAPE: 'BLUE', PINEAPPLE: 'YELLOW', KIWI: 'YELLOW', APPLE: 'RED' }
document
.querySelectorAll('.temple')
.forEach( function(el)
{
let pos = el.textContent.search(/\([^\)]*\)/)
, fruit = el.textContent.slice(0,pos)
, val = el.textContent.slice(pos)
, colorClass = my_dict_reverse[ fruit.replace(/^\s+|\s+$/g,'')] || ''
;
el.innerHTML = fruit
+ '<span class="' + colorClass + '">'
+ val +'</span>';
});
/* ES10 code ...
const my_dict_reverse = Object.keys( my_dict).reduce((r,k)=>
{
my_dict[k].forEach(fruit=>r[fruit]=k)
return r
},{})
document.querySelectorAll('.temple').forEach(el=>
{
let [fruit, val] = el.textContent.split(/(?=\()|(?<=\))/)
, colorClass = my_dict_reverse[ fruit.trim()] ?? ''
;
el.innerHTML = `${fruit}<span class="${colorClass}">${val}</span>`
})
*/
body { background: steelblue; }
a.temple {
color : black;
float : left;
clear : both;
text-decoration : none;
}
span.RED { color : red; }
span.BLUE { color : blue; }
span.YELLOW { color : yellow; }
<a class="temple" href="something # URL">LARGE FRUIT (215)</a>
<a class="temple" href="something # URL">PINEAPPLE (38)</a>
<a class="temple" href="something # URL">APPLE (76)</a>

Related

regex to replace strings with img - js

hey there I am currently having the issues that I want to detect strings in a text with an image.
{"a":"img1.jpg", "ab":"img2.jpg"}
my current regex is:
/(a|ab)/g
When I have a text like:
yeah abc
it replaces the "a" in the yeah with img1.jpg but it also replaces the "ab"c with "img1.jpg".
I can avoid it through switching /(ab|a)/ but this is can't be the solution, since I have a huge unsorted json list as expressions (a, ab is just for simplicity). The reason I am doing this is to replace native emojis with images.
How can I say, that it only replaces the a if there is no b following?
Sort the emoji keys in descendig order, then build your regex pattern like this:
function replaceEmojis (str) {
const emojis = {
a: { src: 'imgA.jpg', color: 'red' },
abc: { src: 'imgABC.jpg', color: 'green' },
ab: { src: 'imgAB.jpg', color: 'blue' },
bc: { src: 'imgBC.jpg', color: 'orange' }
};
const fnDescendingOrder = ([x, y]) => x > y ? -1 : +(x != y);
const keys = Object.keys(emojis).sort((x, y) =>
fnDescendingOrder(x.length == y.length ? [x, y] : [x.length, y.length])
);
const pattern = new RegExp(keys.join('|'), 'g');
const transformed = str.replace(pattern, m => {
const emoji = emojis[m];
return '<img class="' + emoji.color + '" src="' + emoji.src + '">';
});
return transformed;
};
let str = 'yeah abc ab a abca bcaba';
result.innerHTML = replaceEmojis(str);
img { width: 10px; height: 100%; }
img.red { background: red; }
img.green { background: green; }
img.blue { background: blue; }
img.orange { background: orange; }
<div id="result"></div>
You have to sort in descending order first by length, next by alphabetical order. Cause bc should be checked after abc.

Json Pretty Print with syntactic coloration

I'm trying to pretty print my json data in html, and do some syntactic coloration.
But I'm having a little issue with empty values (empty list, empty string) in my code.
Here is the code :
if (!library)
var library = {};
function isInt(value) {
return !isNaN(value) && (function(x) { return (x | 0) === x; })(parseFloat(value))
};
library.json = {
replacer: function(match, pIndent, pKey, pVal, pEnd) {
var int = '<span class=json-int>';
var key = '<span class=json-key>';
var val = '<span class=json-value>';
var str = '<span class=json-string>';
var r = pIndent || '';
if (pKey)
r = r + key + pKey.replace(/[": ]/g, '') + '</span>: ';
if (pVal)
//r = r + (pVal[0] == '"'i ? str : val) + pVal + '</span>';
r = r + (isInt(pVal) ? int : str) + pVal + '</span>';
return r + (pEnd || '');
},
prettyPrint: function(obj) {
var jsonLine = /^( *)("[\w]+": )?("[^"]*"|[\w.+-]*)?([,[{])?$/mg;
return JSON.stringify(obj, null, 3)
.replace(/&/g, '&').replace(/\\"/g, '"')
.replace(/</g, '<').replace(/>/g, '>')
.replace(jsonLine, library.json.replacer);
}
};
var lint = {
"LintResult": "FAILED",
"CFN_NAG": [
{
"filename": "sam.yaml",
"file_results": {
"failure_count": 0,
"violations": []
}
}
],
"Comment": "If above CFN_NAG key has None value, check code execution log for errors/exceptions"
}
$('#lint').html(library.json.prettyPrint(lint));
//document.getElementById("json").innerHTML = JSON.stringify(data, undefined, 2);
pre {
background-color: ghostwhite;
bovrder: 1px solid silver;
padding: 10px 20px;
margin: 20px;
}
.json-key {
color: brown;
}
.json-value {
color: navy;
}
.json-string {
color: olive;
}
.json-int {
color: fuchsia;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="background-color:lightblue">
<h1>JSON Data:</h1>
<pre id="lint"></pre>
</div>
<p>A JSON string with 12 spaces per indentation.</p>
In the above code, the lint json variable has an empty list value for the violations item, and then this key is not print with the right color, it's just not processed.
I tried different way but I don't understand what is wrong.
You can try the code your self and will notice that the syntactic coloration doesn't work for this last item.
This might help you out:
function output(inp) {
document.body.appendChild(document.createElement('pre')).innerHTML = inp;
}
function syntaxHighlight(json) {
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key';
} else {
cls = 'string';
}
} else if (/true|false/.test(match)) {
cls = 'boolean';
} else if (/null/.test(match)) {
cls = 'null';
}
return '<span class="' + cls + '">' + match + '</span>';
});
}
var obj = {
"LintResult": "FAILED",
"CFN_NAG": [
{
"filename": "sam.yaml",
"file_results": {
"failure_count": 0,
"violations": []
}
}
],
"Comment": "If above CFN_NAG key has None value, check code execution log for errors/exceptions"
};
var str = JSON.stringify(obj, undefined, 4);
output(syntaxHighlight(str));
pre {outline: 1px solid #ccc; padding: 5px; margin: 5px; background: ghostwhite }
.string { color: olive; }
.number { color: fuchsia; }
.boolean { color: navy; }
.null { color: magenta; }
.key { color: brown; }

Javascript .replace() same character different outcome

I have a word : google, and I'm changing each character to a specific color, but I can't figure out how to make letters "o" different colors
This is my JS:
var text = $("#typed-strings").html().replace(/e/g, '<span class="red">e</span>').replace(/g/g, '<span class="blue">g</span>').replace(/l/g, '<span class="green">l</span>').replace(/o/g, '<span class="yellow">o</span>');
$("#typed-strings").html(text);
.red {
color: rgb(219, 50, 54);
}
.blue {
color: rgb(72, 133, 237);
}
.green {
color: rgb(60, 186, 84);
}
.yellow {
color: rgb(244, 194, 13);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="typed-strings">google</div>
maybe someone has ideas?
Thanks!
EDIT:
Thanks everyone for such a rich response, my question was edited by a moderator, perhaps that's why you've seen some changes.
I uploaded this tryout on heroku, to make things easier, but yeah, I have this long text, and every time letter "o" shows up I'd like it to either be, red or yellow, html doesn't really matter since it's purely for visualisation, but I've learned a lot from the conversations - thanks!
that's the app:
https://googlefonts.herokuapp.com
EDIT 2:
also added the non-working version within the page
As others have pointed out your issue is that you are replacing g with
<span class="...">g</span>
then replacing all l's in the last string which replaces the l in class.
Another way around this is to use a function for replace. While using a function each match is replaced in turn and any replacements you make are ignored.
Besides that you can use a separate key and boolean to track whether you have replaced the first o already or not. I added this to my example using the boolean as part of the replacement-key for the letter o to simplify things.
var replacements = {
g: '<span class="blue">g</span>',
o0: '<span class="red">o</span>',
o1: '<span class="yellow">o</span>',
l: '<span class="green">l</span>',
e: '<span class="red">e</span>'
};
var ele = $("#typed-strings");
var text = ele.html();
var firstODone = false;
text = text.replace(/[gogle]/g, function (letter) {
var key = letter;
if (key === 'o') {
key = key + (+firstODone); //Convert the boolean to an integer, 0 or 1
firstODone = true;
}
return replacements[key];
})
ele.html(text);
.red {
color: rgb(219, 50, 54);
}
.blue {
color: rgb(72, 133, 237);
}
.green {
color: rgb(60, 186, 84);
}
.yellow {
color: rgb(244, 194, 13);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="typed-strings">google</div>
If you only needed jQuery for this you can easily get rid of it, too. You can use
var ele = document.getElementById("typed-strings");
to get your element and
ele.innerHTML
to get and set your html to the element.
e.g.: ele.innerHTML = text
You might want to use the following regex:
letter + '{1}(?![^<]*\>)'
The above will replace only lowercase single letter G-s that are not inside a tag <>, here is an example:
function replaceWithSpanClass( string, letter, className ){
var regex = new RegExp( letter + '{1}(?![^<]*\>)', 'g' );
return string.replace( regex, '<span class="' + className + '">' + letter + '</span>')
}
var text = 'google';
text = replaceWithSpanClass( text, 'g', 'red' );
text = replaceWithSpanClass( text, 'o', 'blue' );
text = replaceWithSpanClass( text, 'l', 'yellow' );
text = replaceWithSpanClass( text, 'e', 'green' );
document.getElementById('result').innerHTML = text;
.yellow { color: yellow; }
.green { color: green; }
.blue { color: blue; }
.red { color: red; }
<div id="result"></div>
In this case it means that a class like yellow does not get its o replaced by <span class="blue">o</span>. That way you are sure you are only modifying outside your nodes.
<script type="text/javascript">
$(document).ready(() => {
let oldStr = $("#typed-strings").html();
let newStr = '';
for(let i = 0; i < oldStr.length; i++) {
if (oldStr[i] === 'g') {
newStr += '<span class="blue">g</span>'
} else if (oldStr[i] === 'o') {
newStr += '<span class="yellow">o</span>'
}
// Add other letters here
}
$("#typed-strings").html(newStr);
});
</script>
You can create a function that would return the color by the letter and use replace method with callback function like this:
var colors = {
g: 'blue',
o: 'yellow',
l: 'green',
e: 'red'
};
function wrapTheLetter(letter) {
var colorClass = colors[letter];
if (letter == 'o') {
// update it's color for the future
colors.o = 'grey';
}
return '<span class="' + colorClass + '">'+letter+'</span>';
}
var text = $("#typed-strings").html().replace(/\w/g, wrapTheLetter);
$("#typed-strings").html(text);

Comparing RGB colors in JavaScript

I'm trying to compare two RGB colors in a guessing game. There are 6 squares with 6 different colors. When the user clicks on the color that matches pickedColor, the result should be 'Correct!'. But I never get that result.
This is my code:
var colors = [
"rgb(255,0,0)",
"rgb(255,255,0)",
"rgb(0,255,0)",
"rgb(0,255,255)",
"rgb(0,0,255)",
"rgb(255,0,255)"
];
var squares = document.querySelectorAll(".square");
var pickedColor = colors[3];
var colorDisplay = document.getElementById("colorDisplay");
colorDisplay.textContent = pickedColor;
for (var i = 0; i < squares.length; i++) {
//add initinal colors to squares
squares[i].style.background = colors[i];
//add the click listener to the squares
squares[i].addEventListener("click", function () {
var clickedColor = this.style.background;
if (clickedColor === pickedColor) alert("Correct!");
else alert("Incorrect!");
});
}
Ok so I set up an example here and it looks like the problem is that your initial set of colours don't have spaces between the commas:
var colors = [
"rgb(255,0,0)",
"rgb(255,255,0)",
"rgb(0,255,0)",
"rgb(0,255,255)",
"rgb(0,0,255)",
"rgb(255,0,255)"
];
clickedColor has no spaces and the pickedColor does, so changing this to:
var colors = [
"rgb(255, 0, 0)",
"rgb(255, 255, 0)",
"rgb(0, 255, 0)",
"rgb(0, 255, 255)",
"rgb(0, 0, 255)",
"rgb(255, 0, 255)"
];
Should do the trick.
The trouble is that the color expression 'rgb(0,255,255)' is formatted differently by the browser. In the test clickedColor === pickedColor, you're comparing two strings that no longer look the same even if they represent the same color.
Different browsers can represent an RGB color in different ways, so it's unsafe to pick a particular format. A better approach is to extract the color components from the strings and compare the component values one by one, as in the code below.
function rgbExtract(s) {
var match = /^\s*rgb\(\s*(\d+),\s*(\d+),\s*(\d+)\)\s*$/.exec(s);
if (match === null) {
return null;
}
return { r: parseInt(match[1], 10),
g: parseInt(match[2], 10),
b: parseInt(match[3], 10) };
}
function rgbMatches(sText, tText) {
var sColor = rgbExtract(sText),
tColor = rgbExtract(tText);
if (sColor === null || tColor === null) {
return false;
}
var componentNames = [ 'r', 'g', 'b' ];
for (var i = 0; i < componentNames.length; ++i) {
var name = componentNames[i];
if (sColor[name] != tColor[name]) {
return false;
}
}
return true;
}
The rgbMatches function is demonstrated in the following snippet. You'll see that you can now click on the square with the correct color and you'll get the appropriate message even though the underlying RGB strings are formatted differently.
var colors = [
"rgb(255,0,0)",
"rgb(255,255,0)",
"rgb(0,255,0)",
"rgb(0,255,255)",
"rgb(0,0,255)",
"rgb(255,0,255)"
];
var squares = document.querySelectorAll(".square");
var pickedColor = colors[3];
var colorDisplay = document.getElementById("colorDisplay");
colorDisplay.textContent = pickedColor;
function message(s) {
document.getElementById('messageContainer').innerHTML = s;
}
function rgbExtract(s) {
var match = /^\s*rgb\(\s*(\d+),\s*(\d+),\s*(\d+)\)\s*$/.exec(s);
if (match === null) {
return null;
}
return { r: parseInt(match[1], 10),
g: parseInt(match[2], 10),
b: parseInt(match[3], 10) };
}
function rgbMatches(sText, tText) {
var sColor = rgbExtract(sText),
tColor = rgbExtract(tText);
if (sColor === null || tColor === null) {
return false;
}
var componentNames = [ 'r', 'g', 'b' ];
for (var i = 0; i < componentNames.length; ++i) {
var name = componentNames[i];
if (sColor[name] != tColor[name]) {
return false;
}
}
return true;
}
for (var i = 0; i < squares.length; ++i) {
var square = squares[i];
square.style.background = colors[i];
square.addEventListener("click", function () {
var clickedColor = this.style.background;
if (rgbMatches(clickedColor, pickedColor)) {
message('Correct! ' + clickedColor + ' matches ' + pickedColor);
} else {
message('Incorrect. ' + clickedColor + ' doesn\'t match ' + pickedColor);
}
});
}
body {
font-family: sans-serif;
}
.square {
display: inline-block;
margin: 5px;
width: 50px;
height: 50px;
border: 1px solid #888;
cursor: pointer;
}
.output {
margin: 10px 5px;
}
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="output" id="colorDisplay"></div>
<div class="output" id="messageContainer"></div>
I would be wary of comparing two rgb strings like this. Different browsers may store style background colors differently (as you have already discovered).
I would suggest writing a custom comparison function which parses two rgb strings and compares them.
Or you could convert them to hex color values and compare those instead.
Do not trust the color returned by the browser. Different browsers will use different formats.
Instead, use classes or data-* attributes to set the color, and check that:
var colors = ["red", "yellow", "lime", "cyan", "blue", "fuchsia"],
squares = document.querySelectorAll(".square"),
pickedColor = colors[Math.floor(Math.random()*colors.length)],
message = document.getElementById("messageContainer");
document.getElementById("colorDisplay").textContent = pickedColor;
for (var i = 0; i < squares.length; ++i) {
squares[i].setAttribute('data-color', colors[i]);
squares[i].addEventListener("click", function () {
var clickedColor = this.getAttribute('data-color');
message.textContent = clickedColor === pickedColor
? "Correct!" : "Incorrect!";
});
}
.square {
display: inline-block;
margin: 5px;
width: 50px;
height: 50px;
border: 1px solid #888;
cursor: pointer;
}
.output {
margin: 10px 5px;
}
[data-color=red] { background: rgb(255,0,0) }
[data-color=yellow] { background: rgb(255,255,0) }
[data-color=lime] { background: rgb(0,255,0) }
[data-color=cyan] { background: rgb(0,255,255) }
[data-color=blue] { background: rgb(0,0,255) }
[data-color=fuchsia] { background: rgb(255,0,255) }
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="output" id="colorDisplay"></div>
<div class="output" id="messageContainer"></div>

How to order the item categories in Javascript

I am having 20 records
I want to order the records in terms of Priority field.
Priority field is having 3 values( High, Medium, Low )
I want to display the records in High, Medium, Low records in sequence respectively.
Below is C# version ---> I need this to do in javascript
`var groupedRecords = records.OrderByDescending(x => x.Priority == "High").ThenByDescending(x > x.Priority == "Medium").ThenByDescending(x > x.Priority == "Low")`
In Javascript,
var csvRecords = priorities.split(','); // Now I am getting the csv with mixed orders. I need in sequence.
That is I want to get first all High records, then Medium records and atlast Low records.
You can take look at below simple code:
var points = [{Name: "House",Priority :"High"}, {Name: "Travel",Priority :"Medium"}, {Name: "Children",Priority :"High"}, {Name: "Personal Loan",Priority :"Low"}, {Name: "Car",Priority :"Medium"}, {Name: "Shopping",Priority :"Low"}];
document.getElementById("demo").innerHTML = JSON.stringify(points);
function myFunction() {
var priorityArray = ["High", "Medium","Low"]
points.sort(function(a, b){
var firstPrio = priorityArray.indexOf( a.Priority) ;
var secPrio = priorityArray.indexOf(b.Priority)
return firstPrio -secPrio
});
document.getElementById("sortedArray").innerHTML = JSON.stringify(points);
}
<p>Click the button to sort the array.</p>
<button onclick="myFunction()">Sort it</button>
<br/><br/>
Original Array:
<p id="demo"></p>
Sorted Array:
<p id="sortedArray"></p>
I hope it will help you a bit.
Condensed version using constants for sort order:
Data:
var data = [
{
name: 'Andy',
priority: 'High'
},
{
name: 'John',
priority: 'Low'
},
{
name: 'Tim',
priority: 'Medium'
},
{
name: 'Bob',
priority: 'Medium'
},
{
name: 'Lucas',
priority: 'Medium'
},
{
name: 'Mark',
priority: 'High'
},
{
name: 'Fred',
priority: 'Low'
}
];
Code:
var SORT_ASC = -1;
var SORT_DESC = 1;
function sort_by_priority ( order ) {
var prs = ['High', 'Medium', 'Low'];
data.sort(function ( a, b ) {
var x = prs.indexOf(a.priority);
var y = prs.indexOf(b.priority);
if ( x < y ) return -1 * order;
if ( x > y ) return 1 * order;
return 0;
});
}
Test:
sort_by_priority(SORT_DESC);
console.log(data);
Try this:
Fiddle
Code
var data = [];
var priority = ["low", "medium", "high"];
function createData() {
for (var i = 0; i < 10; i++) {
var index = Math.floor((Math.random() * 10) % 3);
var p = priority[index];
data.push({
"index": i,
"Priority": p
});
}
}
function createLI() {
var ul = document.getElementsByTagName("ul")[0];
var li = "";
data.forEach(function(row) {
li += "<li> " + row.index + " : " + row.Priority + " </li>";
});
ul.innerHTML = li;
}
function sortList(sortOrder) {
var order = (sortOrder == 'desc') ? -1 : 1;
data.sort(function(a, b) {
var p1, p2;
priority.forEach(function(row, index) {
if (a.Priority == row)
p1 = index;
if (b.Priority == row)
p2 = index;
})
if (p1 < p2) return -1 * order;
if (p1 > p2) return 1 * order;
return 0;
});
createLI();
}
(function() {
createData();
createLI();
})()
li {
list-style-type: none;
padding: 5px;
border-bottom: 1px solid #ddd;
margin-left: -20px;
width: 100px;
}
<ul></ul>
<button onclick="sortList('asc')">Asc Sort</button>
<button onclick="sortList('desc')">Desc Sort</button>
Try using String.prototype.match() with RegExp val + "\.\\w+(?=.*,)", "g" to match val followed by any character followed by any alphanumeric character ; where val is "High" , "Medium" , or "Low" stored in an array iterated within Array.prototype.forEach() , utilize Array.prototype.concat() to flatten resulting array res containing input text sorted from "High" to "Medium" to "Low" . Use res.push() to return three arrays sorted from "High" to "Medium" to "Low"
var priorities = "High:1,Medium:2,Low:3,Low:4,Medium:5,High:6,Medium:7,"
+ "High:8,Low:9,Low:10,Medium:11,High:12,Low:13,Medium:14,"
+ "High:15,High:16,Low:17,Medium:18,Low:19,High:20";
var keys = ["High", "Medium", "Low"], res = [];
keys.forEach(function(val) {
res = res.concat(priorities.match(new RegExp(val + "\.\\w+(?=.*,)", "g")))
});
document.body.innerHTML = JSON.stringify(res)

Categories