how to wrap keywords in html code with tooltip - javascript

What could be the best way to mark some keywords in an html code.
As an Example, I have this html code:
$text = '
<h1>Lorem Ipsum</h1>
<p>Lorem ipsum dolor sit āmet, consetetur sadipscing elitr, sed diam nonumy<br>
eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</p>
<p><img src="test.jpg" alt="Lorem Ipsum">
<p>At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,<br>
one, nò sea takimata 1 sanctus est Lorem ipsum dolor sit amet. Lörem ipsum dolor sit amet,<br>
consetetur sadipscing elitr, sed diam lor­em ipsum nonumy eirmod tempor invidunt ut labore et<br>
dolore magna aliquyam erat, sed diam voluptua.
</p>
';
And i would like to highlight the word "Lorem Ipsum" like this: <span class="tooltip">Lorem Ipsum</span>
Since the keywords originate from a database, it can happen that certain words only occur once and therefore twice:
$keywords = ['Lorem Ipsum', 'Lorem']
In this case, there should only be one marker. Because I don't want a code like this:
<span class="tooltip"><span class="tooltip">Lorem</span> Ipsum</span>
Also all tag attributes like title and altshould be ignored. The same should apply to links, because I don't wan't a double function like hover and click.
So the marked result should look like this:
$text = '
<h1><span class="tooltip">Lorem Ipsum</span></h1>
<p><span class="tooltip">Lorem ipsum</span> dolor sit āmet, consetetur sadipscing elitr, sed diam nonumy<br>
eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</p>
<p><img src="test.jpg" alt="Lorem Ipsum">
<p>At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,<br>
one, nò sea takimata 1 sanctus est Lorem ipsum dolor sit amet. Lörem ipsum dolor sit amet,<br>
consetetur sadipscing elitr, sed diam <span class="tooltip">lor­em ipsum</span> nonumy eirmod tempor invidunt ut labore et<br>
dolore magna aliquyam erat, sed diam voluptua.
</p>
';
As you can see, the keyword Lorem Ipsum should also match lorem ipsum in lowercase.
I would like to know what is the most promising way to solve this problem. PHP and Javascript would be possible. Could someone help me with an approach? Has anyone ever had to solve this problem?

This is similar to bad words filter using php Using Google to search for it.
this function will determine if your text contain any of the words and replace it with * this is pretty much similar to what you looking for and same approach you will have to do.
Check if your text contain the word from the array
A. Yes Contain, you need to clean that word from your text of all html tags
you can use something like this strip_tags("Hello <b>world!</b>");
and then replace with whatever you want or just wrap it with <Mark>
B. No Doesn't contain, then you will continue.
Your string case Upper or Lower you can fix it by using
lcfirst('January'); // january
ucfirst('January'); // January
ucwords('a title without caps'); // A Title Without Caps
Example Function will change your words in the array to *
function filterwords($text){
$filterWords = array('Lorem Ipsum','Lorem','Else');
$filterCount = sizeof($filterWords);
for($i=0; $i<$filterCount; $i++){
$text = preg_replace('/\b'.$filterWords[$i].'\b/ie',"str_repeat('*',strlen('$0'))",$text);
}
return $text;
}
Usage
echo filterwords("
<h1><mark>Lorem Ipsum</mark></h1>
<p><mark>Lorem ipsum</mark> dolor sit āmet, consetetur sadipscing elitr, sed diam nonumy<br>
eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</p>
<p><img src="test.jpg" alt="Lorem Ipsum">
<p>At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,<br>
one, nò sea takimata 1 sanctus est Lorem ipsum dolor sit amet. Lörem ipsum dolor sit amet,<br>
consetetur sadipscing elitr, sed diam <mark>lor­em ipsum</mark> nonumy eirmod tempor invidunt ut labore et<br>
dolore magna aliquyam erat, sed diam voluptua.
</p>
");
Update if you want to highlight also you can do this using JS
function highlight(text) {
var inputText = document.getElementById("inputText");
var innerHTML = inputText.innerHTML;
var index = innerHTML.indexOf(text);
if (index >= 0) {
innerHTML = innerHTML.substring(0,index) + "<span class='highlight'>" + innerHTML.substring(index,index+text.length) + "</span>" + innerHTML.substring(index + text.length);
inputText.innerHTML = innerHTML;
}
}
function highlight(text) {
var inputText = document.getElementById("inputText");
var innerHTML = inputText.innerHTML;
var index = innerHTML.indexOf(text);
if (index >= 0) {
innerHTML = innerHTML.substring(0,index) + "<span class='highlight'>" + innerHTML.substring(index,index+text.length) + "</span>" + innerHTML.substring(index + text.length);
inputText.innerHTML = innerHTML;
}
}
.highlight {
background-color: yellow;
}
<button onclick="highlight('fox')">Highlight</button>
<div id="inputText">
The fox went over the fence
</div>

You can solve this simple by using the regular expression
/(>.)(Lorem Ipsum)(.?<)/gi
Check this

Related

How to use combined capturing groups in RegEx with string.prototype.matchAll?

I try to capture some patterns in my textInput (a string) by using the following RegEx:
let idPatterns = /\[id="(.*?)\"]|\[id="(.*?)"]|\[id="(.*?)"]/gim;
The part that matters to me, is the "id" included as: (.*?)
To extract the ids, I use the following:
patternsArray = [...textInput.matchAll(idPatterns)];
My result for the following text is:
text [id="B0076VLVXG"] text
Array:
0: "undefined"
but when I reduce the idPatterns variable to
let idPatterns = /\[asin="(.*?)"]/gim;
I get "B0076VLVXG" as result (as desired). So in conclusion, the concatenation of my idPatterns seems to be inaccurate, but works using each of them separately. How can I combine the three groups of patterns in my RegEx correctly? Thank you for your help.
function getIdsCombinedRegEx(textInput) {
const idPatterns = /\[id="(.*?)\"]|\[id="(.*?)"]|\[id="(.*?)"]/gim;
const idPatternsCollection = [...textInput.matchAll(idPatterns)];
return idPatternsCollection;
}
function getIdsSingleRegEx(textInput) {
const idPatterns = /\[id="(.*?)"]/gim;
const idPatternsCollection = [...textInput.matchAll(idPatterns)];
return idPatternsCollection;
}
let textInput = '[id="B07Q45WX5D"] Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. [id="B08CQTNK8S"]';
console.log(getIdsCombinedRegEx(textInput));
console.log(getIdsSingleRegEx(textInput));
Your regex should work as is, returning the match in group 2 (as it is captured by the group in the second branch of the alternation:
const idPatterns = /\[id="(.*?)\"]|\[id="(.*?)"]|\[id="(.*?)"]/gim;
const textInput = 'text [id="B0076VLVXG"] text';
const patternsArray = [...textInput.matchAll(idPatterns)];
console.log(patternsArray);
Since each alternation will return the match in a different group, it might be easier to rewrite the regex to a constant capture group. For example:
\[id(?:=|=)("|"|")(.*?)\1]
This looks for:
the characters [id
either = or =
one of ", " or " (captured in group 1)
a minimal number of characters (captured in group 2)
a match to what was captured in group 1 (the quote part)
a closing ]
Regex demo on regex101
For your expanded data:
const textInput = '[id="B07Q45WX5D"] Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. [id="B08CQTNK8S"]';
const idPatterns = /\[id(?:=|=)("|"|")(.*?)\1]/gim;
const idPatternsCollection = [...textInput.matchAll(idPatterns)];
// just get group 2
const idValues = idPatternsCollection.map(m => m[2]);
console.log(idValues);

Do not paste rich text formatting works only for the first text area

If you paste formatted text in the following two text areas, you can see that only for the first text area, there is no formatting. It should be for the second one, and maybe for a third one, the same. How is it possible to do that?
var editable = document.querySelector("[contenteditable]")
editable.addEventListener("paste", function(e) {
e.preventDefault()
var clipboard = e.clipboardData.getData("text/plain")
document.execCommand("insertText", false, clipboard)
})
* {
font-family: inherit;
}
div {
font-family: Papyrus;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div contenteditable="true" spellcheck="false">One: At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
<div contenteditable="true" spellcheck="false">Two: Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</div>
Would be very happy if somebody could help me! <3
document.querySelector() only returns the first match in the page
You need to use document.querySelectorAll() and loop over the collection to add a listener to each one
var editable = document.querySelectorAll("[contenteditable]");
editable.forEach(el => {
el.addEventListener("paste", function(e) {
e.preventDefault();
var clipboard = e.clipboardData.getData("text/plain");
document.execCommand("insertText", false, clipboard);
});
});
* {
font-family: inherit;
}
div {
font-family: Papyrus;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div contenteditable="true" spellcheck="false">One: At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</div>
<div contenteditable="true" spellcheck="false">Two: Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</div>

Mark.js not highligting the text

I am trying to use mark.js for highlighting text in a specified container.
var searchKeyword = "ipsum";
$(".box").mark(searchKeyword, options);
<div class="box">
<p>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea
takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores
</p>
</div>
Mark.Js: https://markjs.io/
Codepen example: https://codepen.io/anon/pen/eVMZyb
Working example
var searchKeyword = "ipsum";
//$(".box").mark(searchKeyword, options);
$(".box").mark(searchKeyword, {
"element": "span",
"className": "highlight"
});
https://codepen.io/anon/pen/mXxPQW

Show More/Less with pure Javascript

I need a simple read more/less example in pure javascript and CSS. How can I convert this jQuery example to pure Javascript?
https://jsfiddle.net/ngaffer/s75zj385/2/
I have several long paragraphs being generated on a page. In order to shorten the page to minimize scrolling, I want to hide the majority of each paragraph and display a link "read more". When the link is clicked the button will display the hidden text and change the link to "read less".
<section>
<div class="content hideContent">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</div>
<a class="show-more" href="#">Show more</a>
</section>
<section>
<div class="content hideContent">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</div>
<a class="show-more" href="#">Show more</a>
</section>
<script>
$("a.show-more").on("click", function() {
var $this = $(this);
var $content = $this.prev("div.content");
var linkText = $this.text().toUpperCase();
if(linkText === "SHOW MORE"){
linkText = "Show less";
$content.switchClass("hideContent", "showContent", 400);
} else {
linkText = "Show more";
$content.switchClass("showContent", "hideContent", 400);
};
$this.text(linkText);
});
</script>
<style>
.hideContent {
overflow: hidden;
line-height: 1em;
height: 2em;
}
.showContent {
line-height: 1em;
height: auto;
}
</style>
Here is a pure JS code that select anchors based on the class and with animation css trick:
var anchrorClassShow=document.getElementsByTagName('a');
for(var i=0;i<anchrorClassShow.length;i++){
if(anchrorClassShow[i].className!=='show-more'){
anchrorClassShow[i].remove();
}
}
for(var i=0;i<anchrorClassShow.length;i++){
anchrorClassShow[i].addEventListener('click', function(){
var parentDiv=this.parentElement;
if(parentDiv.children[0].className.match(/hideContent/g)){
parentDiv.children[0].className='content showContent';
}else{
parentDiv.children[0].className='content hideContent';
}
});
}
.hideContent {
max-height: 2em;
transition: max-height 0.15s linear;
overflow: hidden;
background: #d5d5d5;
}
.showContent {
max-height: 500px;
transition: max-height 0.35s linear;
}
<section>
<div class="content hideContent">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</div>
<a class="show-more" href="#">Show more</a>
</section>
<section>
<div class="content hideContent">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
</div>
<a class="show-more" href="#">Show more</a>
</section>
A conversion like this isn't a very lengthy process.
Here is a very useful resource to know how to replace a common jquery code with plain (vanilla) javascript.
At the same time, I also took the liberty of modifying your javascript in a new fiddle.
var click_event = function() {
var linkText = this.innerHTML.toUpperCase();
if (linkText === "SHOW MORE") {
this.innerHTML = "Show less";
this.previousElementSibling.classList.remove("hideContent");
this.previousElementSibling.classList.add("showContent");
}
else {
this.innerHTML = "Show more";
this.previousElementSibling.classList.remove("showContent");
this.previousElementSibling.classList.add("hideContent");
}
};
var elements = document.getElementsByClassName("show-more");
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', click_event, false);
}
This code implements all the basic functionalities in vanilla JS. However, I have left out the 400ms time delay, which I think would be a very interesting exercise for you to work on. I hope this helps you in future events.

google javascript spreadsheet

I am trying to make function that tells me how many there are words that contains less than 3 letters.
For example, "Tomorrow will be rain. So bring your umbrellas"
in this sentence, only "be" and "so" so equal two. Any help would be appreciated.
function (stri){
return ("less than 3 ").length;
}
( I am aiming to use \w (regular expression) if its possible.)
If you use lodash you can do the following...
<script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>
<script>
// create a function to call with your string and the min size of the word
function countSmalls(s,min) {
// split by non word characters
return _.where(s.split(/\W/),function(v,i,l){
// return true or false to satisfy the callback, all *truthy* values are added to the return value of _.where
return v && v.length < min;
}).length;
}
// create some text
var lorem = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.";
// call your function
countSmalls(lorem,3); // 24 (words that are < 3 characters)
</script>
function countSmallWords(stringToTest){
var smallWords = /\b\w{1,2}\b/g;
return stringToTest.match(smallWords).length;
}
Explanation: It uses the regular expression \b\w{1,2}\b with the global flag to match all words in a string that are one or two characters. Then it uses the match function on that string to give an array of the words. Finally, get the length property for the count.
Example usage:
//Example 1:
alert(countSmallWords("Tomorrow will be rain. So bring your umbrellas"));
//alerts 2
//Example 2:
var smallWordCount = countSmallWords("Hello. What a nice day it is.");
//smallWordCount == 3
//Example 3:
var smallWordCount = countSmallWords("Are there any small words in this sentence?");
console.log(smallWordCount);
//Press F12 and you will see 1 in the browser console.

Categories

Resources