I'm trying to make a kind of simple search engine, where
the user enters a string and if it's equal to the text inside
an element, that portion of text must be highlighted some way.
This is the html:
<input type="text">
<input type="button" value="Change text"><br>
Click here to get more info!
this is the css:
.smallcaps{
color:red;
}
and this is the jquery function that makes the search and replace:
$("input[type='button']").click(function(){
var textValue = $("input[type=text]").val();
$("a").html(function(_, html) {
return html.replace(new RegExp(textValue,"ig"), '<span class="smallcaps">'+textValue+'</span>');
});
});
This is an example of how it looks like:
Everything works fine, until the search string is equals to the name of a node element, so for example if the search string is a, the html will be broken.
How can I avoid the replace of the html itself?. I just want to work over the text.
This is the codepen:
http://codepen.io/anon/pen/mefkb
Thanks in advance!
I assume that you want to only highlight the last search and not store the ones from before.
With this assumption, you can store the old value if it is the first call and use the stored value in the calls afterwards:
$("input[type='button']").click(function(){
// Escape the html of the input to be able to search for < or >
var textValue = $('<div/>').text($("input[type=text]").val()).html();
if(textValue === '') return;
$("a").html(function(_, html) {
var old = $(this).data('content');
if(!old) {
old = html;
$(this).data('content', old);
}
var replacer = function(match) {
return match.replace(new RegExp(textValue, "ig"), '<span class="smallcaps">'+textValue+'</span>');
};
if(/[<>]/.test(old)) {
return old.replace(/^[^<>]*</gi, replacer).replace(/>[^<>]*</gi, replacer).replace(/>[^<>]*$/gi, replacer);
}
return replacer(old);
});
});
Also i fixed two bugs I found when testing:
if you search for an empty string, everything is broken.
If you search for html characters like < or > nothing is found as in the text they are converted to < or >.
One thing is not solved, as it is not possible to easily implement it without destroying the subelement structure: It is not possible to search in different subelements, as you have to remove the tags, search then and insert the tags at the right position afterwards.
Working fiddle: http://codepen.io/anon/pen/KlxEB
Updated Demo
A workaround would be to restore <a> to original text, instead of complicating the regex.
Your problem is a form the <span> tag is getting replaced.
var init = $("a").text(); //save initial value
$("input[type='button']").click(function(){
$('a').text(init); //replace with initial value
var textValue = $("input[type=text]").val();
$("a").html(function(_, html) {
return html.replace(new RegExp(textValue,"ig"), '<span class="smallcaps">'+textValue+'</span>');
});
});
Related
I have a function that adds text into an input box. Basically you click a div and it activates the function by onclick="addvalue(“Name”)"
function addvalue(newdate){
var input = $("#datestobeexcluded");
input.val(input.val()+","+newdate);
};
But what I really need to do is to check the string inside the input value,
If it’s not there to add the text, which it does, and remove it if text is already present in string.
I am not doing well with jquery at the moment. Thank you in advance
var input = $("#datestobeexcluded");
if(input.val().search(newdate) >= 0)
{
input.val(input.val().replace(newdate,''));
}
else
{
input.val(input.val()+","+newdate);
}
And if you have multiple occurrences:
input.val(input.val().replace(/newdate/g,''));
You can use includes with RegExp:
var input = $("#datetobeexcluded");
input.val(input.val().includes(newdate) ? input.val().replace(new RegExp(newdate, "g"), "") : `${input.val()},${newdate}`);
You may replace your inline on click binding with jQuery styled click listener.
Then you may use the next code.
const $input = $('#your-input')
$('.extra-option').click(function() {
const inputString = $input.val()
const content = inputString ? inputString.split(',') : []
const stringToAdd = $(this).html()
const stringIndex = content.indexOf(stringToAdd)
if (stringIndex === -1) {
content.push(stringToAdd)
} else {
content.splice(stringIndex, 1)
}
$input.val(content.join(','))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="your-input" type="text" />
<div class="extra-option">Name</div>
<div class="extra-option">Company</div>
<div class="extra-option">Address</div>
At first, you need to figure out how you will provide clicked element value. Your approach is definitely wrong because you need to bind function on click, while you return undefined. For test purposes I use innerText.
At the second, you need to check if your string contains clicked div string or not. To simplify this logic, I use splitting by delimiter and then manage with an array of entries.
The last step, you need to update your input value.
I guess it's all.
Let me know if you have any question.
I'm trying to learn some of jQuery/JS and I get a problem that I can't solve. I have one text like this:
blablablabla <b data-start="" data-end="">#foo</b> blablabla"
Note that I can have more than one tag in this text.
I need edit the attributes to their right values, so I was constructing a method to do this:
// "str" isn't static, but for pratical purposes, I'm using this as static.
str = 'blablablabla <b data-start="" data-end="">#foo</b> blablabla'
str.children('b').each(function(i){
$(this).attr('data-start', '');
$(this).attr('data-end', '');
})
As you can see, I don't have idea how I can do the code above. I though use:
str.children('b').each(function(i){
var start = $(this).indexOf('#');
$(this).attr('data-start', '');
$(this).attr('data-end', '');
})
But this will return the index 1, because I'm getting the index of text inside the b tag, and not inside the all text itself. So, how I can fix this problem and get initial position of "b" and final position of "b" (excluding the tag itself)?
umm.. something like this perhaps.. jsfiddle link
<span id="test" >
blablablabla <b data-start="" data-end="">#foo</b> blablabla"
</span>
and the jquery..
var str = $("#test").text();
var strB = $("#test b").text();
$("#test b").attr("data-start", str.indexOf(strB) );
$("#test b").attr("data-end", (str.indexOf(strB) + strB.length-1));
alert($("#test").html())
I am trying to find // (slashes) in the document and wrap it with a span.
I've tried
var slashes = "//";
/slashes+/
So output should be:
Hello There! I Am <span class="slashes">//</span> An Alien
With jQuery .replace() and :contains but nothing happens, and I am new to reguler expressions to do this correctly. How would I do this?
Edit: What have I tried:
Solution for this question didn't work:
function slashes($el) {
$el.contents().each(function () {
dlbSlash = "//";
if (this.nodeType == 3) { // Text only
$(this).replaceWith($(this).text()
.replace(/(dlbSlash)/gi, '<span class="slashes">$1</span>'));
} else { // Child element
slashes($(this));
}
});
}
slashes($("body"));
You need to escape the slashes in your regex. Try
var mystring = "adjfadfafdas//dsagdsg//dsafda"
mystring.replace(/\/\//g,'<span class="slashes">\/\/</span>');
Should output
"adjfadfafdas<span class="slashes">//</span>dsagdsg<span class="slashes">//</span>dsafda"
If you want to replace the slashes in h2 and p tags, you can loop through them like so:
$('h2, p').each(function(i, elem) {
$(elem).text(
$(elem).text().replace(/\/\//g,'<span class="slashes">\/\/</span>'));
});
This will blow away any additional html tags you may have had in your p and h2 tags, though.
This is one more way of doing this
//Find html inside element with id content
var html = $('#content').html();
//Replace // with <span style='color:red'>//</span>
html = html.replace(/\/{2}/g,"<span style='color:red'>$&</span>");
//Return updated html back to DOM
$('#content').html(html);
and here is the demo
I think you were looking in the right place. The only thing to fix is your regular expression:
.replace(/\/\//g, '<span class="slashes">$1</span>'));
Focusing on text nodes (type 3) is important, instead of doing a global replace of the body innerHTML that might break your page.
If you want to apply such replacement for single // only, go with
mystring = mystring.replace(/(\/{2})/g, "<span class=\"slashes\">$1</span>");
However if you want to apply that for 2 or more slashes, then use
mystring = mystring.replace(/(\/{2,})/g, "<span class=\"slashes\">$1</span>");
But if you want to apply it for any even quantity of slashes (e.g. //, ////, etc.) then you need to use
mystring = mystring.replace(/((?:\/{2})+)/g, "<span class=\"slashes\">$1</span>");
Test the code here.
How can I replace a specific text with HTML objects?
example:
var text = "some text to replace here.... text text text";
var element = $('<img src="image">').event().something...
function ReplaceWithObject(textSource, textToReplace, objectToReplace);
So I want to get this:
"some text to replace < img src...etc >.... text text text"
And I would like manipulate the object element without call again $() method.
UPDATE:
I solved.
thanx #kasdega, i made a new script based in your script, because in your script i can't modify the "element" after replace.
This is the script:
$(document).ready(function() {
var text = "some text to replace here.... text text text";
var element = $('<img />');
text = text.split('here');
$('.result').append(text[0],element,text[1]);
$(element).attr('src','http://bit.ly/mtUXZZ');
$(element).width(100);
});
I didnt know that append method accept multiples elements.
That is the idea, only need to automate for multiple replacements
thanx to all, and here the jsfiddle
do a split on the text you want to replace then use the array indexes 0 and 1...something like:
function ReplaceWithObject(textSource, textToReplace, objectToReplace) {
var strings = textSource.split(textToReplace);
if(strings.length >= 2) {
return strings[0] + objectToReplace.outerHTML() + strings[1];
}
return "";
}
UPDATE: I found another SO post Get selected element's outer HTML that pointed me to a tiny jquery plugin that helps here.
I believe this jsfiddle has what you want. outerHTML is the tiny jquery plugin I included in the JSFiddle.
You can also use replace which will reduce some code: http://jsfiddle.net/kasdega/MxRma/1/
function ReplaceWithObject(textSource, textToReplace, objectToReplace) {
return textSource.replace(textToReplace, objectToReplace.outerHTML());
}
function textToObj (text,obj,$src){
var className = "placeholder-"+text;
$src.html($src.html().replace(text,"<div class='"+className+"'></div>"));
$("."+className).replace(obj);
}
you can use $(selector).outerHtml to get the html string of an element
You can replace the html directly: http://jsfiddle.net/rkw79/qNFKF/
$(selector).html(function(i,o) {
return o.replace('old_html','new_html');
})
I want to implement readmore/less feature. i.e I will be having html content and I am going to show first few characters from that content and there will be a read more link in front of it. I am currently using this code :
var txtToHide= input.substring(length);
var textToShow= input.substring(0, length);
var html = textToShow+ '<span class="readmore"> … </span>'
+ ('<span class="readmore">' + txtToHide+ '</span>');
html = html + '<a id="read-more" title="More" href="#">More</a>';
Above input is the input string and length is the length of string to be displayed initially.
There is an issue with this code, suppose if I want to strip 20 characters from this string:
"Hello <a href='#'>test</a> output", the html tags are coming between and it will mess up the page if strip it partially. What I want here is that if html tags are falling between the range it should cover the full tag i.e I need the output here to be "Hello <a href='#'>test</a>" . How can I do this
Why not just hide the hidden part of the content instead of adding it later? I usually just use a display: none for hidden content and have it set to display: block when the read more is clicked..
Edit:
I'm sorry I didn't read the question good enough.
This should work though:
<div id="test">
This links to google
<strong>and</strong> some random text to make it a little bit longer!
</div>
<script type="text/javascript">
$(document).ready(function() {
var max_length = 21;
var text_to_display = "";
var index = 0;
var full_contents = $("#test").contents();
// loop through contents, stop after maxlength is reached
$("#test").contents().each(function(i) {
if ($(this).text().length + text_to_display.length < max_length) {
text_to_display += $(this).text();
index++;
} else {
return false;
}
});
// second loop removes unwanted content
$("#test").contents().each(function(i) {
if (i > index) {
$(this).remove();
}
return true;
});
// add link to show the full text
$('read more...').click(
function(){
$("#test").html($(full_contents));
$(this).hide();
}).insertAfter($("#test"));
});
</script>
This can be accomplished quite easilly using jQuery
<div id="test">This is a link to google</div>
<script type="text/javascript">
$(document).ready(function() {
alert($("#test").text());
});
</script>
Good luck!
You stated that the html tags would become an issue, so why not remove in the string conversion and replace with plain text, then on the Show More click, Toggle plain + Html
$(document).ready(function(){
var Contents = $('#post p'); //Object
var Plain = Contents.text(); //truncate this
//Hide the texts to Contents
Contents.hide();
var PlainContainer = $("<div>").addClass("Plain_Container").val(Plain)
//Add PlainContainer div after
Contents.append(PlainContainer);
var $('.show_hide').click(function(){
$(Plain_Container).remove(); //Delete it
Contents.Show(); //Show the orginal
$(this).remove(); //Remove the link
return false; //e.PreventDefault() :)
});
});
This way using the text() function will convert html tags to there values and remove the tag itself, all you have to do is toggle them :)
Note: The code above is not guaranteed to work and is provided as example only.