I have two fields - an input of type "text" and a textarea.
If the input contains the word "dog" and the textarea contains the word "underdog", the "dog" in the textarea should be marked in red in the div with the id "rslt".
How can I achieve this with jQuery?
You can use indexOf to get the position of the current word in a string then apply some css there. This code handles multiple word highlighting.
function markText(text, word, index) {
if (index != -1) {
var left = text.substr(0, index);
var current = word;
var right = text.substr(index + word.length);
var current = '<span style="background-color: red">' + current + '</span>';
text = left + current + right;
if (right.indexOf(word) >= 0) {
text = markText(text, word, (left + current).length + right.indexOf(word));
}
}
return text;
}
$('#btn').click(function () {
if (($('#txtarea').val() == "") || ($('#bx').val() == "")) {
$('#rslt').html('Please fill both boxes!');
return;
}
var words = $('#bx').val().split(' ');
var text = $('#txtarea').val();
words.forEach(function (word) {
if (text.indexOf(word) >= 0) {
text = markText(text, word, text.indexOf(word));
}
});
$("#rslt").html(text); //WHAT HERE?
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Write here:</p>
<input type="text" id="bx"/><br/>
<p>and here:</p>
<textarea cols="100" rows="8" id="txtarea"></textarea><br/>
<button id="btn">GO</button>
<hr/>
<div id="rslt"></div>
Related
I am trying to make it so one or more specific words is highlighted with a button click.
The word is hard-coded in JavaScript. I also want this highlighted feature to not be case sensitive.
In the below code, the word "agreement" will highlight, but only one word - not multiple words or multiple case types.
The goal is for one button to highlight one or more words and another button to clear the highlight. I am able to do this but only for one instance of the word.
$('#clickpurpleagreement').click(function() {
highlightpurpleagreement('agreement')
});
function highlightpurpleagreement(text) {
console.log($('#inputText').text());
//inputText = document.getElementById("inputText")
var innerHTML = $('#inputText').text();
var index = innerHTML.indexOf(text);
if (index >= 0) {
innerHTML = innerHTML.substring(0, index) + "<span class='highlightpurpleagreementword'>" + innerHTML.substring(index, index + text.length) + "</span>" + innerHTML.substring(index + text.length);
$('#inputText').html(innerHTML);
}
}
$('#clear').click(function() {
clearpurple('agreement')
});
function clearpurple(text) {
console.log($('#inputText').text());
//inputText = document.getElementById("inputText")
var innerHTML = $('#inputText').text();
var index = innerHTML.indexOf(text);
if (index >= 0) {
innerHTML = innerHTML.substring(0, index) + "<span class='clearpurple'>" + innerHTML.substring(index, index + text.length) + "</span>" + innerHTML.substring(index + text.length);
$('#inputText').html(innerHTML);
}
}
.highlightpurpleagreementword {
background-color: #847bba;
}
.clearpurple {
background-color: #ffffff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div>
<a class="button" id="clear"><strong>Clear Highlight</strong></a>
<a class="button button-purple" id="clickpurpleagreement"><strong>Agreement</strong></a>
</div>
<div class="credits" id="inputText">The agreement, Agreement, or agreement is in review</div>
Instead of indexOf use a Regular Expression to find all occurrences of a substring:
function wordIndexes(text) {
var innerHTML = $('#inputText').text();
var regexp = new RegExp(text, 'igm');
while(match = regexp.exec(innerHTML)) {
console.log(match.index);
}
}
wordIndexes('agreement');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="credits" id="inputText">The agreement, Agreement, or agreement is in review</div>
Edit
You've asked for the full JavaScript that would allow you to hard-code the word that needs to be highlighted:
$('#clickpurpleagreement').click(function() {
highlightpurpleagreement('agreement')
});
function highlightpurpleagreement(text) {
var innerHTML = $('#inputText').text();
var regexp = new RegExp(text, 'igm');
var result = '';
var currentIndex = 0;
while(match = regexp.exec(innerHTML)) {
result += innerHTML.substring(currentIndex, match.index) +
'<span class="highlightpurpleagreementword">' + innerHTML.substring(match.index, match.index + text.length) + '</span>'
currentIndex = match.index + text.length;
}
result += innerHTML.substring(currentIndex);
$('#inputText').html(result)
}
.highlightpurpleagreementword {
background-color: #847bba;
}
.clearpurple {
background-color: #ffffff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<a class="button" id="clear"><strong>Clear Highlight</strong></a>
<a class="button button-purple" id="clickpurpleagreement"><strong>Agreement</strong></a>
</div>
<div class="credits" id="inputText">The agreement, Agreement, or agreement is in review</div>
<div>
<button id="clear"><strong>Clear Highlight</strong></button>
<button id="clickpurpleagreement"><strong>Agreement</strong></button>
</div>
<div class="credits" id="inputText">The agreement, Agreement, or agreement is in review</div>
<script>
var colorChanger = document.getElementById("clickpurpleagreement");
colorChanger.addEventListener("click",function() {
document.getElementById('inputText').style.color = "#847bba";
});
var colorChanger1 = document.getElementById("clear");
colorChanger1.addEventListener("click",function() {
document.getElementById('inputText').style.color = "black";
});
</script>
If you follow the script below, when you enter 1 time. Then it will be a paragraph. How to bring up paragraph after 2 or more enter? Because in the code, there is \n
$(document).ready(function() {
$('.button').on("click", function() {
var gogel = $('#mytxtarea').val();
$('#posttextareadisplay').html(telol(gogel));
});
$('#mytxtarea').on("input propertychange", function() {
var gogel = $('#mytxtarea').val();
$('#posttextareadisplay').html(telol(gogel));
});
})
function telol(str) {
$format_search = [
/\r\n|\r|\n|\n\r/g,
/(.*?)\001/g,
/\[arab\](.*?)\[\/arab\]/ig,
/\[b\](.*?)\[\/b\]/ig,
/\[i\](.*?)\[\/i\]/ig,
/\[u\](.*?)\[\/u\]/ig,
/\[\*\](.*?)(\n|\r\n?)/ig,
/\[ul\]/ig, /\[\/ul\]/ig,
/\[ol\]/ig, /\[\/ol\]/ig,
/\[url\](.*?)\[\/url\]/ig,
];
$format_replace = [
'\001',
'<p>$1</p>',
'<span class="lbs0">$</span>',
'<b>$1</b>',
'<em>$1</em>',
'<span style="text-decoration: underline;">$1</span>',
'<li>$1</li>',
'<ul>', '</ul>',
'<ol>', '</ol>',
'$1',
];
for (var i = 0; i < $format_search.length; i++) {
var arrText = str.trim().split(/\r|\n|\n\r|\r\n/);
var newText = '';
$.each(arrText, function(i, text) {
if (text.length < 1 || text == "\r\n" || text == "\n" || text == "\r" || text == "\n\r") {
return true;
}
newText += text.trim() + '\n';
});
str = newText.replace($format_search[i], $format_replace[i]);
}
return str;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form name="form1" method="post" action="">
<p>
<textarea name="mytxtarea" id="mytxtarea" class="ed">This is a sample text</textarea>
</p>
<p id="posttextareadisplay"></p>
<p>
</p>
</form>
OR LOGIC like this
A variable passed from PHP as below:
This is man.
Man like dog.
Man like to drink.
Man is the king."
I would like my result to look something like this after the Javascript converts it:
This is man<br />Man like dog. Man like to drink.<br />Man is the king."
Try this code. It show text on clicking 2 times on the button , by using $('.button').on('dblclick',function{........});
$(document).ready(function() {
$('.button').on("dblclick", function() {
var gogel = $('#mytxtarea').val();
$('#posttextareadisplay').html(telol(gogel));
});
$('#mytxtarea').on("input propertychange", function() {
var gogel = $('#mytxtarea').val();
$('#posttextareadisplay').html(telol(gogel));
});
})
function telol(str) {
$format_search = [
/\r\n|\r|\n|\n\r/g,
/(.*?)\001/g,
/\[arab\](.*?)\[\/arab\]/ig,
/\[b\](.*?)\[\/b\]/ig,
/\[i\](.*?)\[\/i\]/ig,
/\[u\](.*?)\[\/u\]/ig,
/\[\*\](.*?)(\n|\r\n?)/ig,
/\[ul\]/ig, /\[\/ul\]/ig,
/\[ol\]/ig, /\[\/ol\]/ig,
/\[url\](.*?)\[\/url\]/ig,
];
$format_replace = [
'\001',
'<p>$1</p>',
'<span class="lbs0">$</span>',
'<b>$1</b>',
'<em>$1</em>',
'<span style="text-decoration: underline;">$1</span>',
'<li>$1</li>',
'<ul>', '</ul>',
'<ol>', '</ol>',
'$1',
];
for (var i = 0; i < $format_search.length; i++) {
var arrText = str.trim().split(/\r|\n|\n\r|\r\n/);
var newText = '';
$.each(arrText, function(i, text) {
if (text.length < 1 || text == "\r\n" || text == "\n" || text == "\r" || text == "\n\r") {
return true;
}
newText += text.trim() + '\n';
});
str = newText.replace($format_search[i], $format_replace[i]);
}
return str;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form name="form1" method="post" action="">
<p>
<textarea name="mytxtarea" id="mytxtarea" class="ed">This is a sample text</textarea>
</p>
<p id="posttextareadisplay"></p>
<p>
</p>
</form>
<button class="button">
click here
</button>
In your format search and replace arrays, you're looking for a new line character from any major OS, and then replacing that as /001, which is next converted to a paragraph <p> element.
If you want, for instance, a single line break <br/> tag when there is only 1 carriage return, you could first look for \n\n (in all forms) and define those as \001, and then go back and look for all single newlines \n and define those as \002.
Then, whenever you see \001, it will be a <p> tag as you have it, and whenever you see a \002, it should be converted into a <br/>.
$format_search = [
/\r\n\r\n|\r\r|\n\n|\n\r\n\r/g,
/\r\n|\r|\n|\n\r/g,
/(.*?)\001/g,
/(.*?)\002/g,
...
];
$format_replace = [
'\001',
'\002',
'<p>$1</p>',
'$1<br/>',
...
];
This is the code I have so far. When the user enters a word into the input box, I want that word to be stored in an array via the Add Word button. Once a number of words have been entered, the user clicks the Process Word button and I want all the words in the array to appear. How would I do this? Also could someone also explain why when nothing is entered into the input box "field is empty" does not appear?
function begin() {
var word = "List of words";
var i = returnword.length
if (userinput.length === 0) {
word = "Field is empty"
}
document.getElementById('message2').innerHTML = word
while (i--) {
document.getElementById('message').innerHTML = returnword[i] + "<br/>" + document.getElementById('message').innerHTML;
}
}
function addword() {
var arrword = [];
returnword = document.getElementById('userinput').value;
arrword.push(returnword);
}
Addword()
Your function contains an array arrword. If you keep it inside your function it will be reset every time you call the function. You need to keep your array of words outside the function
Empty input
The empty input message should be shown when you click on the Add word button. Check the input and display a message if needed
Display word
You can simply use join() to display you array
var arrayOfWord = [];
var inputElement = document.getElementById('userinput');
var errorElement = document.getElementById('error');
var wordsElement = document.getElementById('words');
function addWord() {
errorElement.innerHTML = "";
var word = inputElement.value;
if (word.trim() === "")
errorElement.innerHTML = "Empty input";
else
arrayOfWord.push(word);
inputElement.value = "";
}
function process(){
words.innerHTML = arrayOfWord.join(' - ');
}
#error {
color: tomato;
}
#words {
color: purple;
}
Enter a word <input id="userinput" /><button onclick="addWord()">Add word</button>
<div id="error"></div>
<button onclick="process()">Process</button>
<div id="words"></div>
you can do something a bit clearer with jQuery! :)
if you handle the input with jquery you can write something like:
var arrWord = [] // your array
/* Attaching a click handler on your "Add Word" button that will
execute the function on user click */
$("#addWordButtonID").on("click", function () {
var wordTyped = $('#textInputID').val() // your var that collect userInput
if (wordTyped.length != 0) { // your if statement with length === 0 condition
arrWord.push(wordTyped) // adding word typed to the array
}
})
to add jquery to your html page, just add
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
in your html header
Hopefully you already have the right html. Then you can modify your script like below:
<script>
var arrword = [];
var returnword;
function begin() {
var word = "List of words";
var i = arrword.length;
if (arrword.length === 0) {
word = "Field is empty";
}
document.getElementById('message2').innerHTML = word;
while (i--) {
document.getElementById('message').innerHTML = arrword[i] + "<br/>" + document.getElementById('message').innerHTML;
}
}
function addword() {
returnword = document.getElementById('userinput').value;
arrword.push(returnword);
}
</script>
var arrword = [];
var returnword;
function begin() {
var word = "List of words";
var i = arrword.length;
if (arrword.length === 0) {
word = "Field is empty";
}
document.getElementById('message2').innerHTML = word;
while (i--) {
document.getElementById('message').innerHTML = arrword[i] + "<br/>" + document.getElementById('message').innerHTML;
}
}
function addword() {
returnword = document.getElementById('userinput').value;
arrword.push(returnword);
}
<button id="addWord" onclick="addword()">Add Word</button>
<button id="processWords" onclick="begin()">ProcessWords</button>
<input type="text" id="userinput" value=" " />
<div id="message2">
</div>
<div id="message">
</div>
I'm trying to highlight only matching text within a string at any point.
I have an input box which filters the results. Originally this worked fine to highlight the FIRST character, but the remit has changed to highlight the text within a string at any position.
Fiddle: Highlight matching text
It filters perfectly as it should, but highlights letters starting at the front, not the matching ones. I tried to use indexOf valThis to sort it out but I was probably doing it wrong.
Any help or pointers would be really appreciated.
$('#box').keyup(function () {
var valThis = this.value.toLowerCase();
var length = this.value.length;
$('.objType').each(function () {
var text = $(this).text(),
textL = text.toLowerCase(),
//n = textL.indexOf(valThis);
var htmlR = '<b>' + text.substr(0, length) + '</b>' + text.substr(length);
if(textL.includes(valThis))
{
$(this).html(htmlR).show()
}
else
{
$(this).hide();
}
});
});
The line
var htmlR = '<b>' + text.substr(0, length) + '</b>' + text.substr(length);
says "take length characters from the beginning of the string." You want to start with the first matching character, so you need to know where that is. So you want String#indexOf, not String#includes.
You also want to save the original text so you can compare against that, not against the text updated by the previous filter operation:
// Grab the original text
$(".objType").each(function() { // ***
$(this).data("original", $(this).text()); // ***
}) // ***
$('#box').keyup(function() {
var valThis = this.value.toLowerCase();
var length = this.value.length;
$('.objType').each(function() {
var text = $(this).data("original"), // ***
textL = text.toLowerCase(),
index = textL.indexOf(valThis); // ***
if (index !== -1) {
var htmlR = text.substr(0, index) + '<b>' + text.substr(index, length) + '</b>' + text.substr(index + length); // ***
$(this).html(htmlR).show()
} else {
$(this).hide();
}
});
});
Updated Fiddle, snippet:
// Grab the original text
$(".objType").each(function() { // ***
$(this).data("original", $(this).text()); // ***
}) // ***
$('#box').keyup(function() {
var valThis = this.value.toLowerCase();
var length = this.value.length;
$('.objType').each(function() {
var text = $(this).data("original"), // ***
textL = text.toLowerCase(),
index = textL.indexOf(valThis); // ***
if (index !== -1) {
var htmlR = text.substr(0, index) + '<b>' + text.substr(index, length) + '</b>' + text.substr(index + length); // ***
$(this).html(htmlR).show()
} else {
$(this).hide();
}
});
});
input[type="text"] {
width: 50%;
font-size: 110%;
margin: 10px;
padding: 5px;
float: left;
clear: left;
}
span {
float: left;
clear: left;
margin: 10px 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input placeholder="Filter results" id="box" type="text" />
<span class="objType" id="item1">Accepted Event Relation</span>
<span class="objType" id="item2">Case Status Value</span>
<span class="objType" id="item3">External Data Source</span>
<span class="objType" id="item4">Navigation Link Set</span>
Try this.
It does non-destructive copying
$('#box').keyup(function () {
var valThis = this.value.toLowerCase(),
length = this.value.length;
$('.objType').each(function () {
var text = $(this).text(),
textL = text.toLowerCase(),
textStart = textL.indexOf(valThis),
textEnd = textStart+valThis.length;
//n = textL.indexOf(valThis);
var htmlR = text.substring(0,textStart)+'<b>' + text.substring(textStart,textEnd) + '</b>' + text.substring(textStart+length);
if(textStart!=-1) {
$("#"+this.id+"r").html(htmlR).show()
$(this).hide();
}
else {
$("#"+this.id+"r").empty();
$(this).hide();
}
});
});
input[type="text"] {
width: 50%;
font-size: 110%;
margin:10px;
padding: 5px;
float:left;
clear:left;
}
span{
float:left;
clear:left;
margin:10px 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input placeholder="Filter results" id="box" type="text" />
<span class="objType" id="item1">Accepted Event Relation</span><span id="item1r"></span>
<span class="objType" id="item2">Case Status Value</span><span id="item2r"></span>
<span class="objType" id="item3">External Data Source</span><span id="item3r"></span>
<span class="objType" id="item4">Navigation Link Set</span><span id="item4r"></span>
I guess you need to use a combination of indexOf, RegEx and substring to find and highlight the position of the word in each string.
See Fiddle here:
https://jsfiddle.net/sxk7qj40/
$('#box').keyup(function () {
const valThis = this.value;
const length = this.value.length;
$('.objType').each(function () {
const text = $(this).text();
const textL = text.toLowerCase();
const position = textL.indexOf(valThis.toLowerCase());
if (position !== -1) {
const matches = text.substring(position, (valThis.length + position));
const regex = new RegExp(matches, 'ig');
const highlighted = text.replace(regex, `<mark>${matches}</mark>`);
$(this).html(highlighted).show();
} else {
$(this).text(text);
$(this).hide();
}
});
});
You would not want to hardcode your substring position at 0, as this will always begin at the start of the string regardless.
Instead, you need to use indexOf, which will return the starting position. You can then use that in the substring to find the starting point that you want to replace. Note that indexOf will return -1 if not found, hence the if statement.
Where to end though? Well, this will come in as a combination of the start position we already have + the string length you just typed.
NOTE: For my own convenience, I used some es2015 features like const and template literals, but you can't use es2015, simply run it through Babel,
or manually replace these parts with var and string concatenation
respectively.
Hope this makes sense?
e.g. ES5 safe:
$('#box').keyup(function () {
var valThis = this.value;
var length = this.value.length;
$('.objType').each(function () {
var text = $(this).text();
var textL = text.toLowerCase();
var position = textL.indexOf(valThis.toLowerCase());
if (position !== -1) {
var matches = text.substring(position, (valThis.length + position));
var regex = new RegExp(matches, 'ig');
var highlighted = text.replace(regex, '<mark>' + matches + '</mark>');
$(this).html(highlighted).show();
} else {
$(this).text(text);
$(this).hide();
}
});
});
I am creating a website with four textarea forms. Each form has a word limit.
textarea1: 250 word limit
textarea2: 500 word limit
textarea3: 500 word limit
textarea4: 250 word limit
I have tried using existing examples that I have found when trying to fix this problem but nothing seems to work.
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script>
var maxwords = 250;
//
function check_length(obj, cnt, rem)
{
var ary = obj.value.split(" "); // doubled spaces will throw this off
var len = ary.length;
cnt.innerHTML = len;
rem.innerHTML = maxwords - len;
if (len > maxwords) {
alert("Message in '" + obj.name + "' limited to " + maxwords + " words.");
ary = ary.slice(0,maxwords-1);
obj.value = ary.join(" "); // truncate additional words
cnt.innerHTML = maxwords;
rem.innerHTML = 0;
return false;
}
return true;
}
</script>
HTML
<textarea name="Message 1" onkeypress="
return check_length(this,
document.getElementById('count1'),
document.getElementById('remaining1'));"></textarea>
Word count: <span id="count1">0</span>
Words remaining: <span id="remaining1">250</span>
<textarea name="Message 2" onkeypress="
return check_length(this,
document.getElementById('count2'),
document.getElementById('remaining2'));"></textarea>
Word count: <span id="count2">0</span>
Words remaining: <span id="remaining2">500</span>
Does anyone know a solution to this problem?
Thanks in advance,
Tom
Add an extra parameter to your function, and send it the maxWords from each function call:
function check_length(obj, cnt, rem, maxwords)
{
//... rest of the function would stay the same
and when you call it, include the max words
<textarea name="Message 2" onkeypress="
return check_length(this,
document.getElementById('count2'),
document.getElementById('remaining2'), 250);"></textarea>
Word count: <span id="count2">0</span>
Words remaining: <span id="remaining2">500</span>
To remove the words remaining,
function check_length(obj, cnt, maxwords)
{
var ary = obj.value.split(" "); // doubled spaces will throw this off
var len = ary.length;
cnt.innerHTML = len;
if (len > maxwords) {
alert("Message in '" + obj.name + "' limited to " + maxwords + " words.");
ary = ary.slice(0,maxwords-1);
obj.value = ary.join(" "); // truncate additional words
cnt.innerHTML = maxwords;
return false;
}
return true;
}
and in your HTML,
<textarea name="Message 1" onkeypress="
return check_length(this,
document.getElementById('count1'),250);"></textarea>
Word count: <span id="count1">0</span>
insert a class attribute for those textareas, (like class='area250', class='area500' and so on) then include an if statement in the function
function check_length(obj, cnt, rem)
{
if(window.event.srcElement.getAttribute('class')=='area250')
maxwords=250;
else if(window.event.srcElement.getAttribute('class')=='area500')
maxwords=500;
else .......................................
}
The problem with your function is that you're always checking the amount of words inserted against maxwords variable (which is set to 250 words as the first textarea limit)
so a better attempt is to pass an extra parameter to the function with the original limit (different for each textarea)