Select characters and wrap - javascript

I'm looking to wrap the last 2 characters in a piece of text in a <sup> using jQuery. I can do a console.log that returns the text I want to wrap, but it never gets wrapped. The code I have is really simple:
// get text of heading
var plansBlockHeading = $('.first .sub .one h4').text();
// filter to last 2 chars
var sup = plansBlockHeading.substr(plansBlockHeading.length-2);
// Wrap in a <sup></sup>
$(sup).wrap("<sup />");
I'm obviously missing something simple, but I'm not sure what. Any pointers?

I would use a regexp
var text = $('.first .sub .one h4').text();
text = text.replace(/^(.*)(.{2,2})$/, "$1<sup>$2</sup>");
$('.first .sub .one h4').html(text);
http://jsfiddle.net/evPhf/

var elem = $('.first .sub .one h4'),
text = elem.text(),
html = text.slice(0,-2) + '<sup>' + text.slice(-2) + '</sup>';
elem.html(html);​
FIDDLE

An idiomatic jQuery solution could look like this:
$('.first .sub .one h4').html(function(i, html) {
// make sure there's no whitespace issues
html = $.trim(html);
return html.slice(0, -2) + "<sup>" + html.slice(-2) + "</sup>";
});
This assumes there's no HTML markup inside the h4 (really just at the end would be an issue).
This also handles properly if you have more than one h4.

Related

How to add characters before and after h2 innerhtml

I've scoured for ways to do this, I'm probably just missing something very obvious, and for that I am sorry.
I'm trying to add two characters to a h2 element. Which I have done, but if I do more than one h2 the first one is copied. I would like the unique innerHTML of each h2 to have these characters added before and after.
I am aware I could do this with css but I already have before and after on the element doing other things.
$(window).on("load", function() {
// On page load, add greater than and less than signs to all h2s
var regH2 = $('h2').html();
$('h2').html( '<' + regH2 + '>' );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<h2>header1</h2>
<h2>header2</h2>
Try like this
$('h2').each(function(){
var regH2 = $(this).html();
$(this).html( '<' + regH2 + '>' );
});
Try to use the callBack function of .html(),
$(window).on("load", function() {
$('h2').html(function(_,regH2){
return '<' + regH2 + '>';
});
});
In the above code, regH2 will receive the old html string every time.
My answer uses CSS instead of JS:
h2:before { content:'<'; }
h2:after { content:'>'; }
<h2>header1</h2>
<h2>header2</h2>
This renders the content with "<" and ">" even before your page has loaded completely.
If :before and :after is already in use, consider adding extra elements like this:
h2 span:before { content:'<'; }
h2 span:after { content:'>'; }
<h2><span>header1</span></h2>
<h2><span>header2</span></h2>
For me I alway weep when static content is added via JS. ;)

Find and replace HTML string with jQuery

Links from the database are website titles and render on the page "Interesting Article: Author" - but occasionally the link is a question "Where's China?: GoogleMaps". The ?: looks silly so I wanted to replace the HTML ?</span>: with ?</span>.
Here is the jQuery I worked out:
$('#relatedinfo ul li a').html().replace('?</span>:','?</span>');
But this doesn't actually replace it in the DOM. How do I get that string to actually change the page?
I'd suggest:
$('#relatedinfo ul li a').html(function(index,html){
return html.replace(/<\/span>(\:)/,'');
});
JS Fiddle demo.
Or even:
$('#relatedinfo ul li a').text(function(index,text){
return text.replace(':','');
});
JS Fiddle demo.
An updated approach is to check that the last character in the span is in the array of ['?','!','.'] and, if it is, then to remove the : from the nextSibling's nodeValue:
$('#relatedinfo ul li a span').text(function(index,text){
var lastchar = text.split('').pop();
if (['?','!','.'].indexOf(lastchar) > -1) {
this.nextSibling.nodeValue = this.nextSibling.nodeValue.replace(':','');
}
});
JS Fiddle demo.
References:
html().
String.replace().
text().
You can also use regex :
var rx = new RegExp('(?![^<&]+[>;])' + searchString, 'gi');
$('#relatedinfo').html(function (i, html) {
return html.replace(rx, '<b>$&</b>')
});
source : jQuery to Find/Replace html text when not inside an html tag other than P, DIV, SPAN, TD

Find Characters and wrap with 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.

Does div with certain content exist

If I have a container div called #container which has a bunch of .inside divs in it, how would I go about checking whether a certain .inside div with a specified content (just a string of English text) exists or not? I'm doing this to prevent duplicates in a notification system I'm setting up for a website. I don't need the actual text - just whether it exists. Also, being able to modify the content of the .inside div if it's found would be good, so I can increment and show the number of times that message has occurred (grouping, if you like).
Thanks,
James
I like using selectors (others have used .filter, which is equally an option).
$(".inside:contains('waldo')").css({color: 'red'});
This is case sensitive.
Use the contains-selector[docs], then the length[docs] property to see how many were found.
var some_string = "test";
var els_with_string = $('#container .inside:contains(' + some_string + ')');
// use .length to check to see if there was at least one
if( els_with_string.length ) {
alert( "at least one already exists" );
}
From the docs:
Description: Select all elements that contain the specified text.
The matching text can appear directly within the selected element, in any of that element's descendants, or a combination thereof. As with attribute value selectors, text inside the parentheses of :contains() can be written as bare words or surrounded by quotation marks. The text must have matching case to be selected.
With respect to modifying the content if found, it would depend on what sort of modification you want to do. I don't know exactly what you mean by grouping.
EDIT: With respect to your comment, you could accomplish what you need like this:
var error = "ERROR:SomeError ";
var el_with_error = $('#container .inside:contains(' + error + ')');
if (el_with_error.length) {
var text = el_with_error.text();
if (/\(\d+\)/.test(text)) {
var new_text = text.replace(/\((\d+)\)/, function(s, g1) {
g1++;
return "(" + g1 + ")";
});
el_with_error.text(new_text);
} else {
el_with_error.text(text + " (2)");
}
} else {
$('#container').append('<div class="inside">' + error + '</div>');
}
Live Example: http://jsfiddle.net/ScZbV/
We could get by without the regular expression if you were able to wrap the grouping quantity in a <span> element.
var error = "ERROR:SomeError ";
var el_with_error = $('#container .inside:contains(' + error + ')');
if (el_with_error.length) {
var span = el_with_error.find('span');
if (span.length) {
var num = +span.text();
span.text( ++num );
} else {
el_with_error.append(" (<span>2</span>)");
}
} else {
$('#container').append('<div class="inside">' + error + '</div>');
}
Example: http://jsfiddle.net/ScZbV/1/
To check existence
$("#container .inside:contains('old text')").size() > 0
To modify the text
$("#container .inside:contains('old text')").text('new text');
Here's a slightly different way of looking at it...
Apply a class name for each "type" of notification. So your notification markup looks like:
<div class="inside error">Error</div>
Then inside of looking for a string inside these divs, use these new class names to your advantage and make use of .find(). If jQuery returns an object then its exists, so do something with it. But if it returns nothing then add it.
Example: http://jsbin.com/imexi4

Numbering in jQuery

How could I change the text below so that the text within it has a number appended to it.
<div class="right">This is some text</div>
<div class="right">This is some text</div>
<div class="right">This is some text</div>
So the code above would become,
This is some text
This is some text
This is some text
you should use an ordered list... ol
or else you will need use css and add the content property your selector with the :after pseudo element.
How about the following?
$("div.right").each(function(i){
$(this).prepend((i + 1) + ". ");
});
UPDATE:
Here is one way that should work.
"number" is a custom element (it can be anything you want) that will/should be ignored by browsers.
$("div.right").each(function(i){
$(this).find("number").remove().end()
.prepend("<number>(i + 1) + ". </number>");
});
OR use the following which is probably a little slower but semantically correct...
$("div.right").each(function(i){
$(this).find("span.number").remove().end()
.prepend("<span class='number'>" + (i + 1) + ". </span>");
});
OR an even better way would be to prepend span.number before your first drag:
$(function(){ // document ready...
// caching the "numbers" will only work if you use the DOM
// for updating div position (like jQuery's "append()", "prepend()", "before()", and "after()") and not "innerHTML" or "html()"
var numbers = $("div.right").each(function(i){
$(this).prepend("<span class='number'>" + (++i) + "</span>. ");
}).find("span.number");
function dragEnd(){
// do your drag end stuff here...
numbers.each(function(i){
this.innerHTML = ++i;
});
)};
});
This is really an elaboration on another comment. I can't format code in a comment, I guess. You could use jQuery core's each:
$('div.right').each(function(ii){
html = $(this).html();
$(this).html(ii + '. ' + html);
});
jQuery selectors are your friend...
Get your stuff and loop on through something like this:
texts = $("div.right");
for(i = 0;i < texts.length;i++)
{
node = $(texts[i]);
content = node.html();
number = i + 1;
node.html(number + ". " + content);
}
Update: Jeez, last time post untested code straight off the dome here (disclaimer: not actually the last time). In the interest of correctness, I've updated it to at least run (and work!) if you still want to do it this way. Although I admit the other solutions are cleaner and more elegant.
Does this have to be done dynamically through jquery? Can't you just combine all that text into one div and then make a ordered list around it?
Using [] notation with a result set will give you the raw DOM element which does not have the html() function. Use the eq() function to get each element wrapped in a jQuery object.
You can also use each() as mentioned above, but I prefer straight 'for loops' so I don't have to adjust for 'this' if I'm in an event handler.
var texts = $("div.right");
var elem;
for(i = 1; i < texts.length; i++) {
elem = texts.eq(i);
html = elem.html();
elem.html(i + '. ' + html);
}

Categories

Resources