Display space characters in pre tag - javascript

In visual studio and other code editors it is possible to view the white space characters. These would appear as small ellipses in the line.
Is it possible to mimic this feature in html. I have been able to use the pre tag to display the text but I am at a loss on how to display the white space characters.
Is it possible via CSS or javascript to show the white space characters?

You can wrap each space in your pre elements in a span with background, so the spaces become visible, but you could copy the text as usually. Here is a JSFiddle example.
Example script (assuming there are no nested tags in the pre):
var pres = document.querySelectorAll('pre');
for (var i = 0; i < pres.length; i++) {
pres[i].innerHTML = pres[i].innerHTML.replace(/ /g, '<span> </span>')
}
CSS:
pre > span {
display: inline-block;
background: radial-gradient(circle, #cc0, rgba(192,192,0,0) 2px);
}
Alternatively, you can use a custom font for pre elements, in which the whitespace characters are replaced with something visible.

you could replace whitespace chars with the ellipsis symbol, like
jsstring.replace(/[\s]/g, "\u2026");
where jsstring denotes a javascript variable with the text to alter. note that you can get and set the textual representation of an html tag including its contentby means of the jquery html() function.
in case you wish to keep line breaks, use
jsstring.replace(/[ \t]/g, "\u2026");
(example available on jsfiddle: http://jsfiddle.net/collapsar/ARu7b/3/).
in fact, [\s] is just a shorthand for [ \t\r\n]. you may define your own character class containing exactly what you consider to be a whitespace character.

It's impossible to do that by CSS but in Javascript you can do something like this. Note that I used jQuery; if you are not loading jQuery in your project let me know to change my code to plain JavaScript.
for example you have something like:
<pre>
ul.nav-menu { list-style: none; }
ul.nav-menu li:last-child { border: none; }
ul.nav-menu li a { color: #b3b3b3; display: block; }
</pre>
You can do:
<script>
var text = $("pre").html();
$("pre").empty()
words = text.split(" ");
for (i = 0; i < words.length; i++) {
$("pre").append(words[i] + '%');
}
</script>
And it will replace spaces with any characters like '%' or whatever.
Result will be:
ul.nav-menu%{%list-style:%none;%}
ul.nav-menu%li:last-child%{%border:%none;%}
ul.nav-menu%li%a%{%color:%#b3b3b3;%display:%block;%%}

Related

How to delete specified text in a string if it contains specific text and do it for each line in a textarea using JS?

I need to delete <annot:annotationLevel><annot:body> and </annot:body></annot:annotationLevel> only if the line contains "(a)" through "(zzz)"
It's for something that looks like this:
<annot:annotationLevel><annot:body><p>“(a) Definitions. In this section:</p></annot:body></annot:annotationLevel>
<annot:annotationLevel><annot:body><p>“(1) List of Material Interested Parties. The term “List of Material Interested Parties” means the List of Material Interested Parties established under subsection (c)(1).</p></annot:body></annot:annotationLevel>
<annot:annotationLevel><annot:body><p>“(2) Oversight Board. The term “Oversight Board” has the meaning given the term in section 5 of PROMESA (48 U.S.C. 2104).</p></annot:body></annot:annotationLevel>
<annot:annotationLevel><annot:body><p>“(b) Required Disclosure.</p></annot:body></annot:annotationLevel>
In the above sample, (a) and (b) should have their annot tags deleted and only have p tags left.
NOTE: It should only work for lowercase alpha characters and NOT on uppercase alpha. (Now I wonder how I'll differentiate alpha with roman numeral (i), (v), and (x), cause those shouldn't be affected, but maybe that's for later)
I've been solving this but my current solution isn't working for some reason. In this one, I'm only trying to target "(a)" and not yet the rest using RegEx.
function annotationWrapCleanups() {
let lines = document.querySelector('#textarea3').value.split('\n');
for (let i = 0; i < lines.length; i++) {
if (lines[i] !== "" && lines[i].includes('(a) Definitions.')) {
lines[i].replace('<annot:annotationLevel><annot:body>', '')
lines[i].replace('</annot:body></annot:annotationLevel>', '')
}
}
}
.main-textarea {
height: 50px;
width: 99%;
}
.main-textarea:focus {
outline: none;
}
.cleanup-btn {
padding: 10px;
margin-top: 10px;
}
<textarea class="main-textarea annotation-wrap" id="textarea3"></textarea>
<button class="cleanup-btn" onclick="annotationWrapCleanups();">clean</button>
Anyways, thank you in advance for any help, any insight would be appreciated!
Check if the line matches the Regex /<p>“\([a-z]+\)/.
Our matched string should:
<p>" Start with this. So that we're looking at the beginning of the element's text content.
This avoids matching things like (c) in your second line
\( Match an open bracket.
\ is to escape what ( normally does in regex.
[a-z]+ Match one or more lowercase letters
\) Match a closing bracket
Using combining this and roman numerals will be a whole different beast, because the simplest question would be, how could you know if it's (i) the letter or (i) as in one.
I set it up for you in the snippet, just click clean and check if the results match what you're looking for. I added the extra line breaks after cleaning to make it clearer to see.
function annotationWrapCleanups() {
const textArea = document.querySelector('#textarea3')
let lines = textArea.value.split('\n');
for (let i = 0; i < lines.length; i++) {
if (lines[i].match(/<p>“\([a-z]+\)/g)) {
lines[i] = lines[i].replace('<annot:annotationLevel><annot:body>', '')
lines[i] = lines[i].replace('</annot:body></annot:annotationLevel>', '')
}
}
textArea.value = lines.join('\r\n\n')
}
document.querySelector('#textarea3').value = `<annot:annotationLevel><annot:body><p>“(a) Definitions. In this section:</p></annot:body></annot:annotationLevel>
<annot:annotationLevel><annot:body><p>“(1) List of Material Interested Parties. The term “List of Material Interested Parties” means the List of Material Interested Parties established under subsection (c)(1).</p></annot:body></annot:annotationLevel>
<annot:annotationLevel><annot:body><p>“(2) Oversight Board. The term “Oversight Board” has the meaning given the term in section 5 of PROMESA (48 U.S.C. 2104).</p></annot:body></annot:annotationLevel>
<annot:annotationLevel><annot:body><p>“(b) Required Disclosure.</p></annot:body></annot:annotationLevel>`
.main-textarea {
height: 50px;
width: 99%;
}
.main-textarea:focus {
outline: none;
}
.cleanup-btn {
padding: 10px;
margin-top: 10px;
}
<textarea class="main-textarea annotation-wrap" id="textarea3"></textarea>
<button class="cleanup-btn" onclick="annotationWrapCleanups();">clean</button>

Replace a word in a string with a styled span dynamically

I'm trying to do something pretty simple, but I'm embarrassed to say that I can't figure it out. I'm looking to find words in a string that start with '#' or '#' and give the word a styling color of blue. The string is coming from an API, so I can't initially set the word inside a span.
I've tried used string replace() with a regular expression to find words that start with '#', and replace it with a span that has the same text, but with the color blue. I've seen this answer pop up throughout SO, but when I try to implement it the entire span is rendered as text, instead of just the text itself. Moreover, the text doesn't have the color changed to blue– I'm getting <span style='color: blue;'>#user42</span> as text, instead of just #user42.
I used a different regexp to remove the spans from being rendered to the page as text but that just seems like I missing something and doing extra work to remedy what I'm unaware of.
Here's what I've tried to do to solve it without using .replace(), but I'm unable to insert the newly created span into the same position as the word being removed.
tweetText[0].split(' ').forEach((word) => {
if (word.innerText.startsWith('#') || word.innerText.startsWith('#')) {
const span = document.createElement('span');
span.innerText = word;
span.style.color = 'blue';
}
});
How can I use replace() to find a word that starts with '#' or '#' and replace it with the same text, but with a different color?
Added color, background-color, padding, and border-radius to look good.
const result = document.querySelector(".result");
function colorizeSelectedText(str) {
const result = str
.split(" ")
.map((word) => {
if (word.startsWith("#") || word.startsWith("#")) {
return `<span style='color: blue; background: bisque; padding: 0.25rem; border-radius: 4px;'>${word}</span>`;
}
return word;
})
.join(" ");
return result;
}
const text = colorizeSelectedText(
"This is #test for the #color that is not colored"
);
result.innerHTML = text;
<div class="result"></div>

Targeting :first-letter of :after content pseudoelement

I have a pseudoelement :after content defined in CSS.
div:after {
content:'This is the sentence.';
}
Can anyone please advise me how to target the first character of the content and change its style. Jquery is OK but I'm trying to do it with first* pseudoelement.
The only time :first-letter could possibly match the first letter of an :after pseudo-element is if the pseudo-element is inline, and there is no other content preceding the pseudo-element (at least in the usual LTR writing mode anyway). Furthermore, pseudo-elements cannot contain their own pseudo-elements, so you couldn't do :after:first-letter either.
If your div element has content, then you won't be able to do this using an :after pseudo-element. You will need to use an actual child element instead. You can easily generate one using jQuery's .append() method, but if you want to target :first-letter of that element, you will need to display it as either block or inline-block instead of inline:
$('div').append('<span class="after">This is the sentence.</span>');
div > .after {
display: inline-block;
}
div > .after:first-letter {
color: red;
}
You won't be able to do anything like div::after::first-letter for the time being, but you can achieve the same end-results relatively easily by merely creating the content you wish to manipulate, and injecting it into your DOM where the div::after pseudo elements would have been placed had they been used:
(function () {
var aftr = document.createElement( "div" ),
divs = document.querySelectorAll( "div" );
aftr.className = "after";
aftr.textContent = "This is the sentence.";
for ( var i = 0; i < divs.length; i++ ) {
divs.item(i).appendChild( aftr.cloneNode( true ) );
}
}());
With these elements now in place, you can move on to styling them:
.after:last-child::first-letter {
color: red;
padding: .5em 1em;
border: 1px solid red;
}
Fiddle: http://jsfiddle.net/jonathansampson/7gmbvewh/
One thing that immediately makes me uncomfortable is the distance between the markup and the text you want displayed within these elements. You could place the text within the markup as a data attribute:
<div data-after="After content">Original Content</div>
And then use that (if it exists) in the final loop:
for ( var i = 0; i < divs.length; i++ ) {
var clone = aftr.cloneNode( true ),
after = divs.item(i).dataset.after;
if ( after ) {
clone.textContent = after;
}
divs.item(i).appendChild( clone );
}
Fiddle: http://jsfiddle.net/jonathansampson/7gmbvewh/2/
If this is a feature question, then the answer is:
Unfortunatelly you can't target and manipulate with pseudo-elements.
But there are workarounds (don't use :after, but actual elements), read the comments under your question.

Change style of all occurrences of a string

I want my site title to display in a unique font from the rest of the content every time it appears in a heading, for branding reasons. For simplicity, let's pretend my special font is Courier and my company is called SparklePony. So, a line like,
<h1 class="title">SparklePony Board of Directors</h1>
would show a headline with the word SparklePony in Courier and Board of Directors in my site default font, Arial. (Yes, I know this would be hideous.)
I've tried using a jQuery string replacement, but I don't want to replace the string, I just want to see it in Courier (adding a class to just that word, or something of the like.) Replacing SparklePony with <span class="sparkle-pony">SparklePony</span> caused the whole ugly string with tags and everything to show on my site, rather than adding the class.
Am I doing something wrong with my string replace, or is there a better way to style all occurrences of a string?
You can do it like this - specifying the selector you want - #('h1') or by class.
$('.title').html(function(i,v){
return v.replace(/SparklePony/g,'<span class="sparkle">SparklePony</span>');
});
​
http://jsfiddle.net/cQjsu/
Without seeing the code (which would be kinda important in questions like this), best guess is that you're using .text() instead of .html() which would parse the HTML correctly.
It could do with some tidying, but this may be a good starting point: http://jsfiddle.net/c24w/Fznh4/9/.
HTML
<div id="title">Highlight this blah blah HiGhLiGhT THIS blah</div>
<button id="clickme">Click to highlight text</button>
CSS
#title{
font-family: sans-serif;
font-size: 20pt;
margin: 30px 0;
}
span.highlight{
color: #09f;
font-weight: bold;
}
JavaScript
function highlightText(element, phrase, allOccurrences, caseSensitive){
var modifiers = (allOccurrences ? 'g' : '') + (caseSensitive ? '' : 'i');
var text = element.innerHTML;
element.innerHTML = text.replace(new RegExp(phrase, modifiers), function(match){
return '<span class="highlight">' + match + '</span>';
});
}
var button = document.getElementById('clickme');
var el = document.getElementById('title');
button.onclick = function(){
highlightText(el, 'highlight this', true, false);
button.onclick = null;
};
Try Something like that :
$.each($(".title"),function({
$(this).html($(this).html().replace("SparklePony","<span class='sparkle-pony'>SparklePony</span>"))
});
Nice and short:
var $body = $("body");
$body.html($body.html().replace(/SparklePony/ig, "<span class='cool'>SparklePony</span>"));​
But keep in mind that $("body") is a very costly selector. You should consider a more precise parent target.
Demo here (fiddle)

Applying a style to and inserting a line break after the first word in a link

I've been asked to recreate an HTML site in WordPress and have it all done except for a meny bar that has me stumped. See image at: http://img36.imageshack.us/img36/8964/menubare.jpg
In short, I need a way to stylize the first word of an element differently than the rest of it and insert a line break following that first word. I'm sure it's a quick jQuery hack, but don't know enough about jQ to make it happen on my own.
Here's the catch: Those little arrows signal a drop-down menu shows up. I have the dropdowns working, but want to make sure whatever solution applies to the main menu, skips the dropdown ones (They're UL lists within an LI item).
Any help would be appreciated.
$('#nav').children('li').find('a').each(function(){
var old = $(this).text();
$(this).html(old.substring(0,old.indexOf(' ')) +'<br/>'+old.substring(old.indexOf(' '),old.length));
});
if you need to apply some class
$(this).html('<span class="first">'+old.substring(0,old.indexOf(' ')) +'</span><br/><span class="next">'+old.substring(old.indexOf(' '),old.length)+"</span>");
Without an HTML example of your menu, its hard to give you a specific answer.
But you could use some jQuery like the following, it will allow you to add styling to the first word, and the rest of them. It will .split() the HTML on spaces, giving you an array. Wrap the first item in a span allowing styling. Then uses jQuery's .each() to loop through the rest of the items adding them back to the string. Then replaces the HTML with the new version:
$('#header > ul.nav > li > a').each(function() {
var obj = $(this);
var text = obj.html();
var parts = text.split(' ');
var replace = '<span class="firstWord">'+parts[0]+'</span><br />';
parts.shift();
$.each(parts, function(key, value) {
replace += ' '+value;
});
obj.html(replace);
});
Example CSS:
.firstWord {
font-size: 15px;
}
.menuHeader {
margin-left: 10px;
float: left;
font-size: 40px;
}
.menu {
width: 100%;
height: 120px;
background-color: #FF8C00;
}
Take a look at a working demo
Update to the demo reflect code from comment.
Use the selector:
$('#header > ul.nav > li > a')
To select only the first menu item. You should only need to add:
.firstWord {
font-size: 15px;
}
To your CSS to adjust the size of the first item.
Good suggestion by Edwin V., you could change the jQuery to:
$('#header > ul.nav > li > a').each(function() {
var obj = $(this);
var text = obj.html();
var parts = text.split(' ');
var replace = '<span class="firstWord">'+parts[0]+'</span><br />';
parts.shift();
replace += parts.join(' ');
obj.html(replace);
});
To shorten it a little. Demo here..

Categories