JS Chrome Plugin - find text located in currently active tab - javascript

The code below is based on the samples provided in this example:
StackOverflow Question
I am no good with JS but would like to adjust this code to highlight not just a number located in a on the website, but rather highlight specific text located anywhere in the active tab, by either changing the font color or the highlighting the text. How can I do that?
Appreciate any help, I am new to JS and a little lost.
Thanks,
A2k
EDIT:
To clarify, I want to highlight the words Apple, Banana, etc. when they are located ANYWHERE in the active tab, not necessarily in a table or a td. This means the words can just as well be in a paragraph of text, in a label, an input field, etc.
highlightText.js
// keyword to highlight
var keywordArray = ["apple","banana","orange"];
keywordArray.forEach(function(v){
var num = "(" + v + ")";
// Select the '<td>' that contains the number we are looking for
var td = $('td.col-question:contains('+num+')');
// Make sure that this number exists
if(td.length > 0){
// Now that we have it we need to single out the number and replace it
var span = td.html().replace(num,'<span class="highlight-num">'+num+'</span>');
var n = td.html(span);
}
// Now instead of '(1000)' we have
// '<span class="highlight-num">(1000)</span>'
// We will color it in the css file
});
highlight.css
span.highlight-num{
background-color: rgb(100, 255, 71);
}

Your issue is with:
var num = "(" + v + ")";
By doing this you are checking if the fruit (apple), (banana) or (orange) is in your table. Instead, you can remove this to check whether apple, banana or orange is contained in your table.
You can instead use a regular expression to replace the keywords if they appear with spans around them to highlight them.
This does have its downsides however, as it won't work properly with text inputs as the markup will not be rendered as HTML.
See working example below:
$(function() {
const keywordArray = ["apple", "banana", "orange"];
const body = $('body');
body.html((_, innerHTML) =>
innerHTML.replace(new RegExp(`(${keywordArray.join('|')})`, 'g'), '<span class="highlight-num">$1</span>')
);
});
span.highlight-num {
background-color: rgb(100, 255, 71);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<p>The big apple is big</p>
<em>The orange <strong>orange</strong> is orange</em>
<br />
<span>The green grape is green</span>
<h4>The banana is a banana</h4>
</body>

Related

Replace a word in a string with a styled span dynamically

I'm trying to do something pretty simple, but I'm embarrassed to say that I can't figure it out. I'm looking to find words in a string that start with '#' or '#' and give the word a styling color of blue. The string is coming from an API, so I can't initially set the word inside a span.
I've tried used string replace() with a regular expression to find words that start with '#', and replace it with a span that has the same text, but with the color blue. I've seen this answer pop up throughout SO, but when I try to implement it the entire span is rendered as text, instead of just the text itself. Moreover, the text doesn't have the color changed to blue– I'm getting <span style='color: blue;'>#user42</span> as text, instead of just #user42.
I used a different regexp to remove the spans from being rendered to the page as text but that just seems like I missing something and doing extra work to remedy what I'm unaware of.
Here's what I've tried to do to solve it without using .replace(), but I'm unable to insert the newly created span into the same position as the word being removed.
tweetText[0].split(' ').forEach((word) => {
if (word.innerText.startsWith('#') || word.innerText.startsWith('#')) {
const span = document.createElement('span');
span.innerText = word;
span.style.color = 'blue';
}
});
How can I use replace() to find a word that starts with '#' or '#' and replace it with the same text, but with a different color?
Added color, background-color, padding, and border-radius to look good.
const result = document.querySelector(".result");
function colorizeSelectedText(str) {
const result = str
.split(" ")
.map((word) => {
if (word.startsWith("#") || word.startsWith("#")) {
return `<span style='color: blue; background: bisque; padding: 0.25rem; border-radius: 4px;'>${word}</span>`;
}
return word;
})
.join(" ");
return result;
}
const text = colorizeSelectedText(
"This is #test for the #color that is not colored"
);
result.innerHTML = text;
<div class="result"></div>

Javascript/jQuery change word color by specific some text contains

I have a simple question with jQuery Css.
I would like to change color of my text by specific word contains using jQuery.
I have example like this:
<div class="me">I'm Groot</div>
I'm <-- will be always black color
Groot <-- will be always green color and Groot sometimes can be change with another word.
How can I do that with jQuery or javascript?
You could replace all occurrences of your specific text snippets with custom styled html elements:
const yourName = "Groot";
const element = document.querySelector(".me");
element.innerHTML = element.innerHTML
.replace("I'm", `<span class="black-class">I'm</span>`)
.replace(yourName, `<span class="green-class">${yourName}</span>`);
Alternatively you can also make everything green except the I'm like this:
.me {
color: green;
}
element.innerHTML = element.innerHTML
.replace("I'm", `<span class="black-class">I'm</span>`);
This way not only Groot is colored green but everything inside of the div. That way your JavaScript doesn't need to know the name.
Just group them like so
:
<div class="me">I'm <span id="changer">Groot</span></div>
Then for CSS, style it like so:
#changer {
color: green;
}
Then to change with javascript:
document.getElementById("changer").innerHTML = "Changed";
Which of course you can add a setTimeout to change continuously
Edit:
No problem, since the only part changing is "Groot" part,
So:
var changing = "Groot";
$('.me').text(`I'm <span id="changer">${changing}</span>`);
// then from here the value of the $('#changer') can be accessed and changed
$('#changer').text('Not Groot');

How to robustly underline a letter in a HTML snippet via the DOM

I'm building a keyboard access library for my web app. To hint at what keys should be pressed i want to underline the key in links. E.g.
Orders --- Invoices --- Open Incidents
For pure text snippets this is easy (jQuery used here):
part.html(part.html().replace(new RegExp(key, 'i'), '<u>$&</u>'));
But this breaks horribly if there is any html markup inside part. Is there an elegant way to just update text nodes and never markup?
Clarification: My use case is hundreds of nested templates server side generating the HTML. Currently accesskey attributes are added by hand. Resulting in something like <i class="fa fa-fw fa-podcast"></i>Ange<b>bote</b>. A Javascript Front-End Script then among other things adds keybindings and trying to underline the bound keys.
To get to the text nodes only, and make the replacement there, you could use a tree walker. I would also create a function that isolates the found letter in a span element and returns that. Then you can use jQuery (or whatever methods) to decorate that element as you wish:
function getLetter(elem, letter){
if (elem.get) elem = elem.get(0); // remove jQuery wrapper
var nodes = document.createTreeWalker(elem, NodeFilter.SHOW_TEXT, null, null),
$node, text, pos, $span;
letter = letter.toLowerCase();
while ($node = $(nodes.nextNode())) {
text = $node.text();
pos = text.toLowerCase().indexOf(letter);
if (pos > -1) {
$span = $('<span>').text(text[pos]);
$node.replaceWith( // separate the letter from the other text
text.substr(0, pos),
$span,
text.substr(pos+1)
);
return $span; // return the element that just has that one letter
}
}
}
getLetter($('#orders'), 'o').addClass('underline');
getLetter($('#invoices'), 'i').addClass('underline');
getLetter($('#incidents'), 'n').addClass('underline');
.underline { text-decoration: underline }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3>Some mix of HTML:</h3>
<div id="orders">
<span style="color: purple">Order<i>(s)</i></span>
</div>
<div id="invoices">
<ul><li><b>!!</b>Invoices <i>(urgent)</i></li></ul>
</div>
<div id="incidents">
<table style="border: 1px solid"><tr><td>Open</td><td>incidents</td></tr></table>
</div>
Explanation of the Function
The function takes two arguments:
elem: the container element which has the text that needs to be searched. This element may or may not have nested HTML mark up.
letter: the letter to identify within that element: only the first occurrence of that letter will play a role.
The function returns:
undefined when there is no match, i.e. the provided letter does not occur in any text contained by the provided element.
A new span element that the function has created: it will contain the letter that was found. The remaining text is put in separate text nodes before and after that new element.
For single letters it should be trivial with the range API, since they won't be split over multiple nested nodes.
let range = document.createRange();
let div = document.createElement("div")
div.textContent = "Orders --- Invoices --- Open Incidents"
let textNode = div.firstChild
let underline = document.createElement("u")
range.setStart(textNode, 0);
range.setEnd(textNode, 1);
range.surroundContents(underline);
console.log(div.outerHTML)
// <div><u>O</u>rders --- Invoices --- Open Incidents</div>
[].forEach.call(document.getElementsByTagName('a'),function(el){
el.innerHTML=el.innerHTML.replace(el.getAttribute('acceskey'),
'<u>'+el.getAttribute('acceskey')+'</u>')
})
Try it here: JS FIddle

Appending and styling label and span inside a div correctly

What am I doing wrong in this fiddle? Fiddle
What I am trying to accomplish is have multiple divs inside another div that have labels and spans inside of them. label has to be on the left and span with text on the right with a solid border on the bottom of each div to separate them.
In the fiddle above, I can't even set the background to a color for the div. Something like this:
<div class="standards">
<div class=""><label></label><span><span></div>
<div class=""><label></label><span><span></div>
<div class=""><label></label><span><span></div>
</div>
so eventually result should look like
HTO some text
__________________
HTO some text
__________________
$('.tab_field_pair') selects all html nodes that have the corresponding class. So when you appended the first one and want to append the 2nd one, it would select both div's.
Here is what you can do:
var code = "HT0";
var label = 'evaluate the social, political, economic, and cultural contributions of individuals and groups from various societies, past and present'
var length = 5;
for (var i = 0; i <= length; i++){
var $div=$("<div class='tab_field_pair'> </div>");
$('.standards').append($div);
$div.append("<label id='standardscode'>" + code + "</label><span id='standardslabel'>" + label + "</span>")
}
http://jsfiddle.net/2dJAN/1351/

Javascript add class to selected text, not first occurrence of the selected text

I want to add a class (and later on to send that string to php) to a text with javascript. Whenever I try to do that, the code is adding the class to the first occurrence of my selection, not to the actual selection. Keep in mind that I want to send that EXACT selection to php (and put it in a database as well so it keep that class even after refresh).
JQ
$("#highlight").click(function(){
paraval = $('#para').html();
sel = window.getSelection();
newst = '<a class="selectedText">' + sel + '</a>';
newvalue = paraval.replace(sel, newst);
$('#para').html(newvalue);
});
HTML
<p>Will only highlight if text is selected from comment class div only</p>
<div class="comment" id="para" contenteditable="true">Here goes some text Here goes some text Here goes some text Here goes some text
Some other text</div>
<input type="button" value="Highlight" id="highlight"/>
CSS
.selectedText{
background-color:yellow;
}
.comment{
border: solid 2px;
}
.comment::selection {
background-color: yellow;
}
example here: http://jsfiddle.net/zq1dqu3o/3/
try to select the last occurrence of the word "text". the first one will get the class "selectedText"...
thanks
Call me lazy, but if you don't mind span being you selection marker tag, you can use rangy's cssApplier class.
var cssApplier;
$(document).ready(function() {
rangy.init();
cssApplier = rangy.createCssClassApplier(
"selectedText", {normalize: true,
applyToEditableOnly:true});
});
$("#highlight").click(function(){
if(cssApplier != undefined)
{
cssApplier.toggleSelection();
}
});
I use applyToEditableOnly here to make it only work in that specific div. (I'm not sure how cross-browser compatible that particular setting is. Worked in Chrome and Firefox though.) This uses position rather than selection text to decide what to mark.
JS Fiddle Here: http://jsfiddle.net/zq1dqu3o/7/
You can get the last occurence with lastIndexOf() and proceed like this:
$("#highlight").click(function(){
paraval = $('#para').text();
sel = "text";
var n = paraval.lastIndexOf(sel);
var before = paraval.substring(0,n);
newst = before + '<a class="selectedText">' + sel + '</a>';
newvalue = paraval.replace(paraval, newst);
$('#para').html(newvalue);
});
Just created a fiddle for it: Replacing last occurence
Note: This quick example is only working because the word you want to highlight is at the last position of the text, but you can check out if this solution is ok for your request. In case the last occurence of the word is elsewhere, just create a variable "after" that contains the text following the last occurence of the word to the end.
Have just provided an example for this in updated fiddle: Replacing last occurence update
with following update to previous code:
var after = paraval.substring(n + sel.length, paraval.length);
newst = before + '<a class="selectedText">' + sel + '</a>' + after;

Categories