Replace too long strings with "..." - javascript

Lets say we have a <div style="width:100px;">This text is too long to fit</div>
The text in the div is dynamic. And I'd like to force the text to fit in width and not break.
So i need some kind of functionality to test if the text is going to fit, and if it is not, then i'd like to display the portion of the text that will actually fit. And append ...to the end.
Result for a too long text should be something like this: "This text is..."
Is there some standard way of doing what i want? Either by javascript, jquery, jsp or java?
Thanks!
Edit:
Thanks for your quick and many answers! I was doing this in java by guessing how many characters would fit. It seemed like a less than optimal solution, so thats why i came here.
The css solution is perfect for me. Its not that big of a deal that it doesnt work for firefox, since my clients all use ie anyway. :)

you could do it with css3 using text-overflow:ellipsis http://www.css3.com/css-text-overflow/
or if you insist on using the js way, you can wrap the text-node inside your div and then compare the width of the wrap with the with of the parent.

If you want to process the data you can use a function:
function TextAbstract(text, length) {
if (text == null) {
return "";
}
if (text.length <= length) {
return text;
}
text = text.substring(0, length);
last = text.lastIndexOf(" ");
text = text.substring(0, last);
return text + "...";
}
text = "I am not the shortest string of a short lenth with all these cows in here cows cows cows cows";
alert(TextAbstract(text,20));
EDIT: process all div with excess length in the text:
var maxlengthwanted=20;
$('div').each(function(){
if ($('div').text().length > maxlengthwanted)
$(this).text(TextAbstract($(this).text()));
});
EDIT: More compact version to process all div with excess length in the text, breaks on space.
function textAbstract(el, maxlength = 20, delimiter = " ") {
let txt = $(el).text();
if (el == null) {
return "";
}
if (txt.length <= maxlength) {
return txt;
}
let t = txt.substring(0, maxlength);
let re = /\s+\S*$/;
let m = re.exec(t);
t = t.substring(0, m.index);
return t + "...";
}
var maxlengthwanted = 23;
$('.makeshort').each(function(index, element) {
$(element).text(textAbstract(element, maxlengthwanted, " "));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="makeshort">This is a fun thing to process, modification of this is going to just be soo much fun</div>
<div class="makeshort">second This is a fun thing to process, modification of this is going to just be soo much fun</div>
<div class="makeshort">IBShort Wilson</div>
<div class="makeshort">another This is a fun thing to process, modification of this is going to just be soo much fun</div>
<div class="makeshort">more This is a fun thing to process, modification of this is going to just be soo much fun</div>
<span class="makeshort">Me also, a span that is a fun thing to process, modification of this is going to just be soo much fun</span>
<span class="makeshort">more This is a fun thing to process, modification of this is going to just be soo much fun</span>
<ul>
<li class="makeshort">li1 more This is a fun thing to process, modification of this is going to just be soo much fun</li>
<li class="makeshort">li 2 more This
is a
fun thing to process, modification of this is going to just be soo much fun</li>
<li class="makeshort">li 3 also moreThis is a fun thing to process, modification of this is going to just be soo much fun</li>
<li class="makeshort">li 4 also more This is fun thing to process, modification of this is going to just be soo much fun</li>
</ul>

if(text.length > number_of_characters) {
text = text.substring(from, to);
}

One liner using JavaScript
The below truncates the string to 10 characters with an ellipsis. If the length of the truncated string is below the limit (10 in the example below) then no ellipsis is added to the output.
const output = "abcdefghijk".split('', 10).reduce((o, c) => o.length === 9 ? `${o}${c}...` : `${o}${c}` , '');

Easiest way to shorten the variable using JavaScript:
function truncate(string, length){
if (string.length > length)
return string.substring(0,length)+'...';
else
return string;
};
Inspired by this answer: I want to truncate a text or line with ellipsis using JavaScript

If the string is a one-liner you can use the CSS solution. If its a multiline string you need to clip, i prefer using a lightweight JS plugin called cuttr.js.
Just a minimum of code needed to get it done. You could even omit the endingoption, because the three dots are the default output.
Vanilla JS implementation:
new Cuttr('.selector', {
length: 15,
ending: '...'
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/cuttr/1.3.2/cuttr.min.js"></script>
<div class="selector" style="width:100px;">This text is too long to fit</div>
jQuery implementation:
$('.selector').Cuttr({
length: 15,
ending: '...'
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cuttr/1.3.2/cuttr.min.js"></script>
<div class="selector" style="width:100px;">This text is too long to fit</div>
Simply add a class to the div and init the plugin. You can read more about truncating a text or line with ellipsis on the plugins website or github page - there are multiple ways to clip the string, even without messing up HTML tags.

text-overflow: ellipis
div {
text-overflow: ellipsis
}
Will be supported in FireFox 7 http://caniuse.com/#search=text-overflow

If you add an id tag to the div, you can use document.getElementById("divid").innerHTML to get the contents of the div. From there, you can use .length to get the length of the string. If the length of the string is over a certain threshold, just take a substring and append a "...".
You should try to do this server-side if you can, though. Relying on Javascript/CSS to format it correctly for the user is a less than ideal solution.

Try the CSS text-overflow property.

A more likely situation is that you can't possibly know how many characters are going to fit in a dom element, given it has its own font and so on. CSS3 is not currently an option (for me anyway). So, I create a little div offscreen and keep jamming test strings into it until the width is correct:
var text = 'Try to fit this text into 100 pixels!';
var max_width = 100;
var test = document.createElement('div');
test.className = 'Same Class as your real element'; // give it the same font, etc as a normal button
test.style.width = 'auto';
test.style.position = 'absolute';
test.style.left = '-2000px';
document.body.appendChild(test);
test.innerHTML = text;
if ($(test).width() > max_width) {
for (var i=text.length; i >= 0; i--) {
test.innerHTML = text.substring(0, i) + '...';
if ($(test).width() <= max_width) {
text = text.substring(0, i) + '...';
break;
}
}
}
document.body.removeChild(test);

Related

How to get number of visible characters inside a div(till its width), which has overflow text [duplicate]

----------------------------------------------------
| This is my text inside a div and I want the overf|low of the text to be cut
----------------------------------------------------
Please note that I want the overflow to be removed, so the CSS ellipsis property would not work for me. So basically, I want that the text above to appear like this:
----------------------------------------------------
| This is my text inside a div and I want the overf|
----------------------------------------------------
How is this possible with pure JavaScript?
EDIT
I need a JavaScript function to crop the text because I need to count the characters of the visible text.
Okay, I didn't see the addendum to the question. Although I had previously said it wasn't possible to do this using JavaScript and a font that isn't fixed-width... it actually is possible!
You can wrap each individual character in a <span>, and find the first <span> that is outside the bounds of the parent. Something like:
function countVisibleCharacters(element) {
var text = element.firstChild.nodeValue;
var r = 0;
element.removeChild(element.firstChild);
for(var i = 0; i < text.length; i++) {
var newNode = document.createElement('span');
newNode.appendChild(document.createTextNode(text.charAt(i)));
element.appendChild(newNode);
if(newNode.offsetLeft < element.offsetWidth) {
r++;
}
}
return r;
}
Here's a demo.
You can do this with Javascript. Here is a function that counts the number of visible characters in an element, regardless of external css sheets and inline styles applied to the element. I've only tested it in Chrome, but I think it is cross browser friendly:
function count_visible(el){
var padding, em, numc;
var text = el.firstChild.data;
var max = el.clientWidth;
var tmp = document.createElement('span');
var node = document.createTextNode();
tmp.appendChild(node);
document.body.appendChild(tmp);
if(getComputedStyle)
tmp.style.cssText = getComputedStyle(el, null).cssText;
else if(el.currentStyle)
tmp.style.cssText = el.currentStyle.cssText;
tmp.style.position = 'absolute';
tmp.style.overflow = 'visible';
tmp.style.width = 'auto';
// Estimate number of characters that can fit.
padding = tmp.style.padding;
tmp.style.padding = '0';
tmp.innerHTML = 'M';
el.parentNode.appendChild(tmp);
em = tmp.clientWidth;
tmp.style.padding = padding;
numc = Math.floor(max/em);
var width = tmp.clientWidth;
// Only one of the following loops will iterate more than one time
// Depending on if we overestimated or underestimated.
// Add characters until we reach overflow width
while(width < max && numc <= text.length){
node.nodeValue = text.substring(0, ++numc);
width = tmp.clientWidth;
}
// Remove characters until we no longer have overflow
while(width > max && numc){
node.nodeValue = text.substring(0, --numc);
width = tmp.clientWidth;
}
// Remove temporary div
document.body.removeChild(tmp);
return numc;
}
JSFiddle Example
You're trying to force a CSS problem into JavaScript. Put the hammer away and get out a screwdriver. http://en.wiktionary.org/wiki/if_all_you_have_is_a_hammer,_everything_looks_like_a_nail
Solving the answer of character count is probably irrelevant if you take a step back. The last character could be only partially visible, and character count is drastically different given font size changes, the difference of width between W an i, etc. Probably the div's width is more important than the character count in the true problem.
If you're still stuck on figuring out the characters visible, put a span inside the div around the text, use the css provided in other answers to this question, and then in JavaScript trim one character at a time off the string until the span's width is less than the div's width. And then watch as your browser freezes for a few seconds every time you do that to a big paragraph.
try this, it requires a fixed width if that is ok with you: http://jsfiddle.net/timrpeterson/qvZKw/20/
HTML:
<div class="col">This is my text inside a div and I want the overf|low of the text to be cut</div>
CSS:
.col {
width:120px;
overflow: hidden;
white-space:nowrap;
}​
.col { width:40px; overflow: hidden; white-space:nowrap; }
White-space: nowrap; is needed when the content has spaces.
Either way, long words in single lines do not appear. http://jsfiddle.net/h6Bhb/

Javascript - Remove empty paragraphs from HTML string

In a Javascript object, I have a string of HTML (node.innerHTML) and I need to remove empty paragraphs from the string, then return the string. Empty paragraphs include <p></p>, <p> </p>, and <p> </p>. Ideally, I think the string should be parsed as HTML code for processing as opposed to using a regex. I have tried all sorts of approaches and cannot seem to get it to work correctly.
Here is code I have tried, but it returns an object with only prevObject data, plus it does not seem to remove the empty paragraphs.
function strip_empty_p (node) {
var html = $(node.innerHTML);
html = html.filter($('p'),function () {
return this.innerHTML == "" ||
this.innerHTML == " " ||
this.innerHTML == " "
}).remove();
node.innerHTML = html.innerHTML;
return node.innerHTML;
}
If you have access to a node, it'd be much better to run through it as HTML instead of getting innerHTML and parsing it that way.
const parent = document.querySelector('div');
parent.childNodes.forEach(child => child.nodeType === document.ELEMENT_NODE
&& !child.innerText.trim()
&& parent.removeChild(child));
<div>
<p></p>
<p> </p>
<p>Not empty</p>
<p> </p>
<p>Also not empty</p>
<p></p>
</div>
This method will be infinitely more reliable and quicker than trying to parse it as if it were text.
If you load it as text from somewhere, convert it to an HTML node first, if it's well-formed enough.
If it's malformed HTML, then life becomes a lot more difficult and you'd have to do some tricky and error-prone string parsing.
You can do this via jQuery. You can either check .text() or innerHTML() of the paragraphs. Here's an example on jsfiddle: https://jsfiddle.net/akvap5mg/
$(document).ready(function(){
$("p").each(function(){
var $this = $(this);
if($this.text().trim() === '') {
$this.remove();
}
});
});
If you wish to remove empty paragraphs, one needs to exercise utmost caution if that is what you intend to literally do because every time an element gets removed it changes the whole ball game. This is what ultimately worked for me:
var d = document.getElementsByTagName("div")[0];
for (i=0, max=4; i <= max; i++) {
if ( d.children[i].textContent.trim() == ""){
d.removeChild(d.children[i]);
max--;
i--;
}
}
live code
If you don't adjust variables max and i, then detecting the DOM elements gets thrown off and an empty paragraph may not get removed.
Alternatively, the following code figuratively removes empty paragraphs and there is no need to adjust variables max and i:
var d = document.getElementsByTagName("div")[0];
for (i=0, max=4; i <= max; i++) {
if ( d.children[i].textContent.trim() == ""){
d.children[i].style.display="None";
}
}
live code
Incidentally, here's a more vivid example here

Javascript - How can I replace text in HTML with text in script

I am new to javascript. I was thinking getelementbyid but i don't know how to make it work
Like the title, here is what I mean
For example I have in HTML:
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
So what I want is to make script to replace those fw_93 fw_94 to what I want.
For example
Instead of displaying "fw_93" I want it to display "9.3". Same with fw_94 to 9.4
Replace fw_ with nothing, divide the number by 10:
Array.prototype.forEach.call(document.getElementsByTagName('p'), function(el) {
el.innerHTML = parseInt(el.innerHTML.replace(/[A-Za-z_]*/, '')) / 10;
});
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
Okay so select the tags.
Loop over the collection
read the html
match the string
replace the html
var ps = document.querySelectorAll("p");
for (var i=0; i<ps.length; i++) {
var p = ps[i];
var txt = p.innerHTML; //.textContent
var updated = txt.replace(/.+(\d)(\d)/, "$1.$2");
p.innerHTML = updated;
}
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
Using JQuery
Not sure why I did it with JQuery, guess I wasn't paying enough attention. No point in me re-writing as there are already good answers in JS. Though I will leave this in case it's of use to anyone that is using JQuery.
You can loop though each <p> element and covert the contents, something like this:
$("p").each(function() {
var text = $(this).html();
var text = text.substring(text.indexOf("_") + 1);
var text = text[0] + "." + text.substring(1);
$(this).html(text);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>fw_93</p>
<p>fw_94</p>
<p>fw_93</p>
You may need to add validation depending on how reliable your input is.
Note that the code makes the following assumptions:
There will always be a _ followed by at least 2 digits
The . will always go after the first digit
Your HTML:
<p id="p1">init_value</p>
Your JS:
document.getElementById("p1").innerHTML = "new_value";

Markdown to convert double asterisks to bold text in javascript

i'm trying to make my own markdown-able textarea like Stackoverflow has done. The goal is to allow people to type **blah blah** in a textarea and have the output in a div be <span style="font-weight:bold;">blah blah</span>.
I'm having trouble with the javascript to find and replace to the **asterisks with the HTML.
here's a jsfiddle which has gotten the party started: http://jsfiddle.net/trpeters1/2LAL4/14/
here's the JS on that just to show you where I'm at:
$(document.body).on('click', 'button', function() {
var val=$('textarea').val();
var bolded=val.replace(/\**[A-z][0-9]**/gi, '<span style="font-weight:bold;">"'+val+'" </span>');
$('div').html(bolded);
});
and the HTML...
<textarea></textarea>
<div></div><button type="button">Markdownify</button>
any thoughts would be greatly appreciated!
thanks,
tim
The other answers fail when a char is immediately before or after the asterisks.
This works like markdown should:
function bold(text){
var bold = /\*\*(.*?)\*\*/gm;
var html = text.replace(bold, '<strong>$1</strong>');
return html;
}
var result = bold('normal**bold**normal **b** n.');
document.getElementById("output").innerHTML = result;
div { color: #aaa; }
strong { color: #000; }
<div id="output"></div>
None of the provided answers works in all cases. For example, the other solutions wont work if we have a space next to the double star, ie:
This will ** not ** be bold
So I wrote this:
function markuptext(text,identifier,htmltag)
{
var array = text.split(identifier);
var previous = "";
var previous_i;
for (i = 0; i < array.length; i++) {
if (i % 2)
{
//odd number
}
else if (i!=0)
{
previous_i = eval(i-1);
array[previous_i] = "<"+htmltag+">"+previous+"</"+htmltag+">";
}
previous = array[i];
}
var newtext = "";
for (i = 0; i < array.length; i++) {
newtext += array[i];
}
return newtext;
}
Just call it like this:
thetext = markuptext(thetext,"**","strong");
and it will work in all cases. Of course, you can also use it with other identifiers/html-tags as you like
(the stackoverflow preview should have this too).
Choose the perfect regex that will fit your needs.
If you don't want styling to span through new line and also using ([^*<\n]+) makes sure at least one character is in between styles or else ** without a character in-between will result will become invisible.
function format_text(text){
return text.replace(/(?:\*)([^*<\n]+)(?:\*)/g, "<strong>$1</strong>")
.replace(/(?:_)([^_<\n]+)(?:_)/g, "<i>$1</i>")
.replace(/(?:~)([^~<\n]+)(?:~)/g, "<s>$1</s>")
.replace(/(?:```)([^```<\n]+)(?:```)/g, "<tt>$1</tt>")
}
β€’The downside to the above code is that, you can't nest styles i.e *_Bold and italic_*
To allow nested styles use this πŸ‘‡
format_text(text){
return text.replace(/(?:\*)(?:(?!\s))((?:(?!\*|\n).)+)(?:\*)/g,'<b>$1</b>')
.replace(/(?:_)(?:(?!\s))((?:(?!\n|_).)+)(?:_)/g,'<i>$1</i>')
.replace(/(?:~)(?:(?!\s))((?:(?!\n|~).)+)(?:~)/g,'<s>$1</s>')
.replace(/(?:--)(?:(?!\s))((?:(?!\n|--).)+)(?:--)/g,'<u>$1</u>')
.replace(/(?:```)(?:(?!\s))((?:(?!\n|```).)+)(?:```)/g,'<tt>$1</tt>');
// extra:
// --For underlined text--
// ```Monospace font```
}
πŸ‘† If you want your style to span through new line, then remove \n from the regex. Also if your new line is html break tag, you can replace \n with <br>
Thank me later!
Why create from scratch? With so many open source editors out there, you should pick a code base you like & go from there.
http://oscargodson.github.com/EpicEditor/
http://markitup.jaysalvat.com/home/
custom component in react who receives bold like boolean
{(() => {
const splitText = theText.split('**');
return (
<TextByScale>
{splitText.map((text, i) => (
<TextByScale bold={!!(i % 2)}>{text}</TextByScale>
))}
</TextByScale>
);
})()}
If you are using jQuery, replace this:
$(document.body).on('click', 'button', function() {
with this:
$("button").click(function () {
The following regular expression will find your asterisk-wrapped text:
/\x2a\x2a[A-z0-9]+\x2a\x2a/
I updated your fiddle as an example: http://jsfiddle.net/2LAL4/30/
Your regex is broken, for one thing. You probably want something more like:
/\*\*[A-z0-9]+\*\*/gi
The * is a special character in regular expressions. If you want to match against a literal *, then you need to escape it with \.
For instance: http://jsfiddle.net/2LAL4/22/
However, even with this change there's still a fair ways to go before you get to where you really want to be. For instance, your example will not work if the text area contains a mix of bold and non-bold text.

JavaScript to add HTML tags around content

I was wondering if it is possible to use JavaScript to add a <div> tag around a word in an HTML page.
I have a JS search that searches a set of HTML files and returns a list of files that contain the keyword. I'd like to be able to dynamically add a <div class="highlight"> around the keyword so it stands out.
If an alternate search is performed, the original <div>'s will need to be removed and new ones added. Does anyone know if this is even possible?
Any tips or suggestions would be really appreciated.
Cheers,
Laurie.
In general you will need to parse the html code in order to ensure that you are only highlighting keywords and not invisible text or code (such as alt text attributes for images or actual markup). If you do as Jesse Hallett suggested:
$('body').html($('body').html().replace(/(pretzel)/gi, '<b>$1</b>'));
You will run into problems with certain keywords and documents. For example:
<html>
<head><title>A history of tables and tableware</title></head>
<body>
<p>The table has a fantastic history. Consider the following:</p>
<table><tr><td>Year</td><td>Number of tables made</td></tr>
<tr><td>1999</td><td>12</td></tr>
<tr><td>2009</td><td>14</td></tr>
</table>
<img src="/images/a_grand_table.jpg" alt="A grand table from designer John Tableius">
</body>
</html>
This relatively simple document might be found by searching for the word "table", but if you just replace text with wrapped text you could end up with this:
<<span class="highlight">table</span>><tr><td>Year</td><td>Number of <span class="highlight">table</span>s made</td></tr>
and this:
<img src="/images/a_grand_<span class="highlight">table</span>.jpg" alt="A grand <span class="highlight">table</span> from designer John <span class="highlight">Table</span>ius">
This means you need parsed HTML. And parsing HTML is tricky. But if you can assume a certain quality control over the html documents (i.e. no open-angle-brackets without closing angle brackets, etc) then you should be able to scan the text looking for non-tag, non-attribute data that can be further-marked-up.
Here is some Javascript which can do that:
function highlight(word, text) {
var result = '';
//char currentChar;
var csc; // current search char
var wordPos = 0;
var textPos = 0;
var partialMatch = ''; // container for partial match
var inTag = false;
// iterate over the characters in the array
// if we find an HTML element, ignore the element and its attributes.
// otherwise try to match the characters to the characters in the word
// if we find a match append the highlight text, then the word, then the close-highlight
// otherwise, just append whatever we find.
for (textPos = 0; textPos < text.length; textPos++) {
csc = text.charAt(textPos);
if (csc == '<') {
inTag = true;
result += partialMatch;
partialMatch = '';
wordPos = 0;
}
if (inTag) {
result += csc ;
} else {
var currentChar = word.charAt(wordPos);
if (csc == currentChar && textPos + (word.length - wordPos) <= text.length) {
// we are matching the current word
partialMatch += csc;
wordPos++;
if (wordPos == word.length) {
// we've matched the whole word
result += '<span class="highlight">';
result += partialMatch;
result += '</span>';
wordPos = 0;
partialMatch = '';
}
} else if (wordPos > 0) {
// we thought we had a match, but we don't, so append the partial match and move on
result += partialMatch;
result += csc;
partialMatch = '';
wordPos = 0;
} else {
result += csc;
}
}
if (inTag && csc == '>') {
inTag = false;
}
}
return result;
}
Wrapping is pretty easy with jQuery:
$('span').wrap('<div class="highlight"></div>'); // wraps spans in a b tag
Then, to remove, something like this:
$('div.highlight').each(function(){ $(this).after( $(this).text() ); }).remove();
Sounds like you will have to do some string splitting, though, so wrap may not work unless you want to pre-wrap all your words with some tag (ie. span).
The DOM API does not provide a super easy way to do this. As far as I know the best solution is to read text into JavaScript, use replace to make the changes that you want, and write the entire content back. You can do this either one HTML node at a time, or modify the whole <body> at once.
Here is how that might work in jQuery:
$('body').html($('body').html().replace(/(pretzel)/gi, '<b>$1</b>'));
couldn't you just write a selector as such to wrap it all?
$("* :contains('foo')").wrap("<div class='bar'></div>");
adam wrote the code above to do the removal:
$('div.bar').each(function(){ $(this).after( $(this).text() ); }).remove();
edit: on second thought, the first statement returns an element which would wrap the element with the div tag and not the sole word. maybe a regex replace would be a better solution here.

Categories