Highlight text by keywords which are separated by comma - javascript

I would like to split up text by comma - i.e. keywords are as the following:
keyword1, keyword2, keyword3, keyword4
How can I have a the black style element for each and every keyword that is separated by a comma. Is there an easy way to do this? The text is always dynamic, so I never know exactly what those keywords will be and how many. So each keyword should have a box elements around it.
<span class="keyword-option-black">keyword1, keyword2, keyword3, keyword4</span>
.keyword-option-black {
color:white;
background-size:contain;
margin:10px;
padding:5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
background:black;
}

CSS is unable to select text.
In order to highlight the keywords on a page, you need to use programming languages such as JavaScript (for client-side) or PHP (or whatever else for server-side) to wrap the keywords by a wrapper element which has a special CSS style to distinguish the keys.
Here, I implemented the above approach by using jQuery (just to demonstrate):
Working Fiddle
JS part:
// Insert the keywords here,
// you can also get the keys automatically from the DOM if needed
var keywords = ['Google', 'Facebook', 'Social'];
$.each(keywords, function(index, key) {
var $content = $('#content'),
text = $content.html();
$content.html(
text.replace(
new RegExp("("+ key +")", 'ig'), "<span class='highlight'>$1</span>"
)
);
});
And here is the highlight class:
.highlight {
color: white;
background-size: contain;
margin:10px;
padding:5px;
border-radius: 5px;
background: black;
}

HTML and CSS are static. Since you don't know how many keywords are gonna be there, you need something dynamic. Depending on implementation, you can use JavaScript or any Back-end language you are using.
Basically, you want to add a span tag around each keyword and style that span (span in one with class keyword-option-black). So, when you enter keywords to HTML use <span>keywordX</span> in loop that adds elements or, alternatively, add those tags when document loads using JavaScript.
Hope this helps.

Using Django, I did it the following way.
Create a simple CSS class to perform the highlighting.
Create a custom tag that splits up data in template view into <span class="keyword">A</span><span class="keyword">B</span>. It takes the original view output and parses this into a format that already has the spans included.

Related

Modifying a form label text with JS using only the "for" attribute as a selector

I have access to a form that I need to modify a labels text. I can only add JS to the page otherwise I'd just change the HTML or even replace the text with CSS.
To make matters worse the label doesn't have an ID or NAME other than it's "for" attribute.
<label for='camper1Grade' class="control-label required">Grade entering, Fall 2020</label>
If I could just edit the CSS I would do this:
<style>
label[for=camper1Grade]:before {content: "Grade completing, Spring 2020";}
label[for=camper1Grade] { font-size: 0px;}
label[for=camper1Grade]:after { content: "*";color: red;}
</style>
But like I mentioned I can't add CSS directly.
I'm a pretty good CSS coder but know very little about JS. I'm sure there is a solution I just can't find a good explanation of how to do this. Thanks in advance to anyone who has an idea.
Almost all elements you can select with CSS you can also select with Javascript and querySelector. Unfortunately, ::before and ::after psuedo-elements are not among them. But, you can always inject another stylesheet using Javascript:
document.body.appendChild(document.createElement('style')).textContent = `
label[for=camper1Grade]::before { content: "Grade completing, Spring 2020"; }
label[for=camper1Grade] { font-size: 0px; }
label[for=camper1Grade]::after { content: "*"; color: red;}
`;
(note the two colons, which is the standard for CSS3)

Why would I ever use a class over an attribute in HTML and CSS?

I'm creating a web app and need to decide on a consistent way to style my elements. I noticed that a lot of help online uses classes but I have generally used attributes (like the query selector [my-attr]) to style multiple elements, since I don't have to work with classList and can remove and set attributes very easily.
Using no external libraries, why would people use classes to style their elements over attributes? It seems like attributes can do everything classes can do but better, since you can also assign values to the attributes as well. I also haven't seen any discussion on performance differences anywhere, making me believe that attributes should be more appreciated than they are in tutorials on styling pages.
Any thoughts on instances where classes could do a better job than attributes at something would be greatly appreciated, even if the arguments are subjective and come down to some sort of preference!
Thanks!
Again, this is for vanilla javascript, HTML, and CSS. I understand that libraries like jQuery may make it easier to use classes, but I don't plan on using any libraries.
It's more consistent, is the end-all be all, truthfully. If you'd rather use attributes, go for it. However it makes it just that much more difficult for anyone who has to help you out later. CSS classes are designed for grouped selection and application of common styles. CSS just happens to also be able to select attributes as well, because it does make sense in some edge cases.
Generally, attributes should be reserved for anything non-style related that adds a value for a different use, be it screen-readers or variable containers for JavaScript, such as data-id="34" may let you make an asynchronous request with the ID parameter.
Consider this example, it's got some simple "class" based buttons:
.button {
display: inline-block;
border: 1px solid;
padding: 4px 10px;
text-decoration: none;
margin-bottom: 4px;
}
.primary {
background: currentColor;
}
.primary span {
color: #fff;
}
.blue {
color: #0095ee;
}
.red {
color: #ee3300
}
Red Button
<span>Red Button</span>
<br />
Blue Button
<span>Blue Button</span>
To replicate something like this with attributes, we'll be doing something like this with some obnoxious and rather arbitrary attribute names. Doing this I actually messed up because I used the wrong attribute name and value pair in one case.
[type="button"] {
display: inline-block;
border: 1px solid;
padding: 4px 10px;
text-decoration: none;
margin-bottom: 4px;
}
[status="primary"] {
background: currentColor;
}
[status="primary"] span {
color: #fff;
}
[color="blue"] {
color: #0095ee;
}
[color="red"] {
color: #ee3300
}
Red Button
<span>Red Button</span>
<br />
Blue Button
<span>Blue Button</span>
Does it not make more semantic sense to keep all your stylistic and group target attributes inside the class attribute? I mean, that's what it was designed for. I suppose you could drop the parameter value and just use parameter names, but you're really defeating the purpose of attributes, considering class is a Global Attribute in and of itself.
Here's a JavaScript example as well:
let classes = document.getElementsByClassName('button');
for( i = 0, n = classes.length; i < n; ++i ){
classes[i].style.background = 'red';
}
let attrs = document.querySelectorAll('[button]');
for( i = 0, n = attrs.length; i < n; ++i ){
attrs[i].style.background = 'blue';
}
a {
padding: 10px;
margin-bottom: 4px;
display: inline-block;
text-decoration: none;
color: #fff;
}
<a href="#" button>Attr 1</a>
<a href="#" button>Attr 2</a>
<a href="#" button>Attr 3</a>
<br />
Class 1
Class 2
Class 3
Putting aside the fact that JS has immense integration with class (and id) based functions for selectors, you have to use querySelector and querySelectorAll for the attribute buttons.
While not inherently a bad thing, (honestly I prefer querySelector over getElement(s)By… in general), but when you look at it, querySelectorAll('[button]') just does not read well, almost like I'm targeting a <button> element. Semantically it makes it harder to read than:
getElementsByClassName('button') - Clearly getting all elements that have a button class, or even
querySelectorAll('.button') - Since the . is universally understood as the "class" selector, and everyone working with HTML, CSS, and JS learns that on literally day 1 of any web development program/tutorial. So you're throwing a bit of a wrench into the project by removing such a fundamental piece of it.
I'm sure you've heard the phrase "Just because you can, doesn't mean you should." - I think that applies perfectly here. I mean, we actually used to use things like <font color="red">Red</font> and we moved away from it because it made more sense to group styles in a single Global Attribute. There's nothing stopping you, but I think it's asking for more trouble than it's worth to drop classes for arbitrary parameter names, not to mention if you have an issue and post your code for help, the first response will always be "Why are you doing that, what preprocessor are you using?"
I think it's just the functional probl, if you want to give style u should use class, but if you want to modify u can use query selector cause it will not added an inline style on your html and you can minify the script.

TagInput Tag Input - Mutli line input field

I will happily accept guidance/pointers/ideas if you don't have a complete response.
I am currently working on updating an Email system built using React and elements of Blueprint JS.
In the email dialog, I am attempting to move the To and CC fields from being a text input to a TagInput system using BlueprintJS/labs' TagInput.
http://blueprintjs.com/docs/v1/#labs/tag-input
You will see in the example contained in the link above, that their TagInput field will allow you to add new Tags to the input field. Once the length of those tags exceeds the width of the input field, it will add a new line to the input field and allow you to continue adding tags.
From my knowledge, input fields do not normally allow for multiple lines.
How can this be achieved? In my code currently, once the tags exceed the width of the input field, it will continue to add new tags on a new line below the input, however, it will not increase the height of the input field to compensate. (Giving the appearance of tags floating magically outside of the input, hovering over & obstructing other content.)
The image below shows the effect. (The CC field is the TagInput - as you can see, the tags below the first line just 'hover in space' and cover the subject field, and eventually move down to cover the email body.)
The TagInput is simply defined..
<TagInput
className='pt-fill pt-input-ghost'
onChange={(cc: string[]) => this.setState({cc})}
values={this.state.cc}
inputValue={this.state.cc_input}
placeholder='CC:'
leftIconName='document-share'
/>
Also, I have a little bit of modified CSS
.pt-input{
overflow-wrap: break-word;
}
.pt-tag-input{
padding-bottom: 2px;
}
.pt-tag {
margin-bottom: 2px;
margin-left: 2px;
}
.pt-tag-input-icon{
margin-right: 2px;
}
.pt-input-ghost{
border:none;
outline-style:none;
outline:none;
box-shadow:none;
border-color:transparent;
margin: 2px 0px;
background-color:transparent;
}
.pt-input-ghost:focus{
border:none;
outline-style:none;
outline:none;
box-shadow:none;
border-color:transparent;
background-color:transparent;
width: auto;
}
Thanks for all the help :)
Again, I will happily accept guidance/pointers/ideas if you don't have a complete response.
A few notes about the TagInput implementation: it's not actually an <input> element, just styled to look like one! The component is actually a div full of tags with an <input> at the end for you to type into.
The default styles of the component allow its height to grow to fit the content, which may wrap to multiple lines.
Your screenshot suggests that your app has some styles (not quoted above) that prevent the TagInput from growing as it should, so the tags spill out and cover the content below.

Is it possible to edit only a portion of the text content or HTML inside of an element?

The code below correctly changes the text inside of an HTML element by rewriting the entire line of text. This is accomplished using textContent but innerHTML can also do this.
document.querySelectorAll(".box")[0].textContent = 'The number of dollars in my bank account is $1';
body {
margin: 0;
padding: 0;
}
.box {
padding: 10px;
font-size: 2rem;
color: white;
font-family: sans-serif;
background-color: blue;
}
<div class="box">The number of dollars in my bank account is ?</div>
However is there a way to change just a portion of the text without having to rewrite the entire line? This probably isn't correct but something like .innerHTML[5, 10] that would change just those specifically targeted characters.
Put simply when Javascript is used to change text or tags inside of an element does it always rewrite the entire section? This might not be visible to the user but is that what always happens behind the scene? Thanks so much!
Far better approach would be to change your HTML to something like
<div class="box">The number of dollars in my bank account is <span id='amount'></span>.</div>
Then you can easily change just the amount with js:
document.getElementById('amount').innerHTML = '5$';
So your website displays:
The number of dollars in my bank account is 5$.
If you want to stick to your approach, only way to do that would be to save the entire content into a string and then perform some search on it, either by substring, filter or regex. Then you would replace the elements you want and put the string back in the HTML.
Use a nested span tag to display the dollar amount. Then you only have to update the span's text. And when you need the entire sentence you can just access the div.box 's textContent. It returns the textContent of all nested elements concatenated.

Colouring letters, numbers in HTML document

How is it possible to add style (colors) to text in an html document in a letter by letter basis (by numbers and any symbol as well), to each letter a defined color is applied.
Think you have grapheme-color synesthesia, in this case I have, and want to make a text editor with your colors applied to glyphs. Although there are ready programs I want to enjoy doing one myself and practice my JavaScript skills. Later I am planning a reader also.
One way is to wrap every letter in an html element in another element, say a span and apply style by class name being related to the wrapped letters name. I will use same idea also in a React Native app.
Is there any other more efficient or more proper way to achieve this?
Basic regular expression with replace to add spans. You can replace the string with a function so you can do something more dynamic to determine the color.
var ps = document.querySelectorAll("p");
[].forEach.call(ps, function (elem) {
elem.innerHTML = elem.innerHTML.replace(/(\S)/g, "<span>$1</span>");
});
span {
display: inline-block;
border: 1px solid black;
width: 20px; text-align: center;
}
<p>Mary had a slice of bacon. It cost $0.75 and tasted great.</p>
<p>Bill had no bacon. He was sad!</p>
Other than doing the looping and replacing, I do not think there is another way of doing it.
Below is the reference link,
Change this span tag in the referenced example,
ie. instead background give color in style tag
<span style="color:'+bgColor+'">'+ text.charAt(i) +'</span>
and
Change the css background:white
Reference link

Categories