Replace end of multi HTML text with a few dots - javascript

I have the following mark-up:
if ($('.replacetext').text().length > 20) {
var linkText = $('.replacetext').text();
$('.replacetext').html(linkText.substring(0, 20) + "...")
$('.replacetext').on("click", function(e) {
console.log("linkText :: ", linkText);
$('.replacetext').html(linkText);
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<h5>
<a class="replacetext" href="">I am a very long title and I need to be shortened And Also I am a very long title and I need to be shortened</a>
</h5>
<h5>
<a class="replacetext" href="">I am a very long title and I need to be shortened And Also I am a very long title and I need to be shortened</a>
</h5>
How can I make it so that if the h5 text (h5 may be more then one) is above a certain number of characters, I get rid of the other characters and replace them with a "..."?
the problem with this code is it also replaces the text same at all h5 tags along with dots.

First up I would reconsider the use of the a tag. You don't have a link. Use something else. I'll leave that up to you.
Next, you want to store the original text. I will use data attributes for this.
Finally, you want to only update the text of the clicked element. We will use the this keyword to help out here.
//Go through each long title
$('.replacetext').each(function() {
//If long title
if ($(this).text().length > 20) {
//Store original string in data attribute
$(this).data("og", $(this).text());
//Replace text
$(this).html($(this).text().substring(0, 20) + "...")
}
});
$('.replacetext').on("click", function(e) {
//Stop the link going anywhere
e.preventDefault();
console.log("Original Text: " + $(this).data("og"));
//Replace with the original
$(this).text($(this).data("og"));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<h5>
<a class="replacetext" href="">I am a very long title and I need to be shortened And Also I am a very long title and I need to be shortened</a>
</h5>
<h5>
<a class="replacetext" href="">I am another very long title and I need to be shortened And Also I am a very long title and I need to be shortened</a>
</h5>
<h5>
<a class="replacetext" href="">I am short</a>
</h5>

See CSS text-overflow Property
div {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

Add all these. To make in single line.
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
width:100px; // some width
To do in multi line which actually you asked.
#content{
overflow: hidden;
width:100px;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
Please note that this multiline code is supported only in web-kit browsers for now.

This is just a proof of concept and has many unhandled potential pitfalls, but you could recursively iterate the children of the element and truncate the text nodes.
I'm not saying this is a good idea. You'll run into whitespace complications and edge cases. Just saying it could be done this way in theory.
const TEXT = 3;
const ELEMENT = 1;
function truncateElement (elem, maxlength) {
let remaining = maxlength;
[...elem.childNodes].forEach(node => {
if (node.nodeType === TEXT) {
node.nodeValue = node.nodeValue.substr(0, remaining);
remaining -= node.nodeValue.length;
}
else if (node.nodeType === ELEMENT) {
truncateElement(node, remaining);
}
});
if (!remaining) {
elem.appendChild(document.createTextNode('…'));
}
}
document.querySelector('button')
.addEventListener(
'click',
() => truncateElement(document.querySelector('h5'), 20)
);
<div class="demo">
<h5><a class="replacetext" href="">I am a very long title and I need to be shortened And Also I am a very long title and I need to be shortened</a></h5>
<button>Truncate to 20</button>
</div>

Related

Replace end of HTML text with a few dots [duplicate]

This question already has answers here:
Setting a max character length in CSS
(15 answers)
Closed 2 years ago.
I have the following mark-up:
<h5>
I am a very long title and I need to be shortened
</h5>
How can I make it so that if the h5 text is above a certain number of characters, I get rid of the other characters and replace them with a "..."?
This should work. You have to display the inline element as a block.
Edit: Just realized you want to add dots if the H5 exceeds a number of characters, not if it exceeds a width. I think to do that you will need to use JS - check out the other answer for that.
h5 {
display: block;
white-space: nowrap;
width: 12em;
overflow: hidden;
text-overflow: ellipsis;
color: red; /* This needs to match the color of the anchor tag */
}
a:link {
color: red;
}
<h5>
I am a very long title and I need to be shortened
</h5>
You can do this:
var name = $('a').text();
if (name.length > 20) {
var shortname = name.substring(0, 20) + " ...";
$('a').replaceWith(shortname);
}
If you want to use javascript, you can extend String object by prototyping:
String.prototype.limit = function(length) {
return this.length > length ? (this.substring(0, length) + '...') : this;
}
var str = 'qwertyuiop';
console.log(str.limit(5)); // qwert...
<h5 id="expansion">
<a id="myLink" href="javascript:void(0);">I am a very long title and I need to be shortened And Also I am a very long title and I need to be shortened</a>
</h5>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
if($('#myLink').text().length > 20){
var linkText = $('#myLink').text();
$('#myLink').html(linkText.substring(0,20)+"...")
$('#myLink').on("click",function(){
console.log("linkText :: ",linkText);
$('#myLink').html(linkText);
});
}
</script>
This one is working
<h5>
<a class ="one" href="javascript:void(0);">I am a very long title and I need to be shortened</a>
</h5>
<style>
.one
{
white-space: nowrap;
overflow:hidden;
text-overflow: ellipsis;
display:inline-block;
width : 100px;
}
</style>
set the width according to your website design

Truncate <a> tag text

In below code I'm attempting to truncate the <a> tag text :
<a href='test'>
<script>
truncate("truncate this text");
</script>
</a>
function truncate(string){
if (string.length > 5)
return string.substring(0,5)+'...';
else
return string;
};
https://jsfiddle.net/fcq6o4Lz/6/
But returns error Uncaught ReferenceError: truncate is not defined
How can this function be invoked from within <a> tag ?
Why
The reason you get the error is because your computer hasn't run the code that defined truncate yet. That function is running before the page finishes loading, that includes the JavaScript. Put the code in a window.onload with a setTimeout to be safe.
window.onload = function(){setTimeout(function () {
truncate("truncate this text");
},1);};
How
Also, unlike languages such as PHP. return won't place any text. Do something like:
<a id="result-location" href='test'>
<script>
window.onload = function(){setTimeout(function () {
document.getElementById('result-location').innerHTML = truncate("truncate this text");
},1);};
</script>
</a>
Fiddle
JSFiddle Fix
Remember to keep the function outside of a window.onload. You can change this in JSFiddle by setting it no no-wrap
CSS
You can use CSS to truncate text
.truncate {
width: 50px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
}
This will cause the text to truncate, after 50px;
.truncate {
width: 50px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
}
<a class="truncate">This text is truncated</a>
You don't invoke javascript code like this. Although you could use document.write to print result of javascript function into HTML element, it is stongly advised to avoid this, as it makes code really confusing.
Instead try something like this: select HTML element in question with CSS selector, select corresponding HTML element, and finally modify its inner content.
function truncate(selector) {
var obj = document.querySelector(selector),
string = obj.innerHTML;
if (string.length > 5) string = string.substring(0, 5) + '...';
obj.innerHTML = string;
};
truncate('#link');
truncate this text
You have to address the element with an ID, like this:
truncate this text
<script>
function truncate(id){
var string = document.getElementById(id).innerHTML;
if (string.length > 5) {
document.getElementById(id).innerHTML = string.substring(0,5)+'...';
}
};
truncate("test-id");
</script>
JSFiddle-Demo: http://jsfiddle.net/c8s3dc6q/1/
All javascript, including the function definition, should happen within a <script> ... </script> block. And that script block should stay in the end of the page, where the function "selects" the a tag with an id or class.
However I think that you might want to achieve the same results using pure CSS.
<a class="trim-text">This text should be trimmed!</a>
// add this to your css file / block
.trim-text {
display: inline-block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
h1 {
max-width: 100px;
}
If you're open to a css only method there's a way to do that. It's based on width and not character count so more precise for styling.
fiddle
http://jsfiddle.net/Hastig/ufe1t66v/3/
html
<a class="truncated-anchors">This be way too long</a>
<a class="truncated-anchors">This too is too long</a>
<a class="truncated-anchors">This as well, far too long</a>
<a class="truncated-anchors">This one is even longer if I add some more words</a>
css
.truncated-anchors {
display: inline-block;
width: 100px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
A more thorough explanation
http://makandracards.com/makandra/5883-use-css-text-overflow-to-truncate-long-texts
And there are options to not use ellipsis and just end it immediately.
Simply define the function before its call in the code, then use document.write to receive the output of the function
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script>
function truncate(string){
if (string.length > 5)
return string.substring(0,5)+'...';
else
return string;
};
</script>
</head>
<body>
hhhhhhh<br />
<a href='test'>
<script>
document.write(truncate("truncate this text"));
</script>
</a>
</body>
</html>
Checkout this DEMO

In the ordered sequence of words: "Word1, Word2, Word3": how to have 1 and only 1 hyperlink on "Word1" & "Word3"? Thus, skip a word in a single link?

How to skip a word in a hyperlink?
Imagine a random ordered sequence of words:
... Word 1 Word 2 Word3 ...
How would it be possible to have 1 unifying (i.e. not 2 seperate links) hyperlink on Word 1 & Word 3?
I.e.: when one hovers either Word 1 or Word 3, the spectator can immediately notice that the hyperlink will lead to a page that covers the meaning of both these words (visible by whatever the CSS of a:hover is in a particular document).
The result would be:
... Word 1 Word 2 Word3 ...
CRUCIAL REMARK: But then instead of having 2 seperate (in this case bold-formatted hyperlinks), they would be unified into 1 single hyperlink. Again: this could e.g. be visualised in CSS by having a text-decoraiton:underline on a:hover, covering Word 1 and Word 3 simultaneously.
Optionally:
It would be good to also have the possibility to add a second, other hyperlink to Word 2.
Use-case example:
In the sentence:
"This does not need any open (Word 1) bladder (Word 2) surgeries (Word 3)."
It would be nice to have 1 unifying hyperlink on Word 1 and Word3. This example clarifies the usefulness of such a word-skipping-hyperlink: Word 2 certainly shouldn't be included in the first unifying link, since the urinary bladder-Wikipedia han't got much to do with the open surgeries-Wikipedia.
The result would be:
"This does not need any open bladder surgeries."
CRUCIAL REMARK: Instead that the hyperlink on open and surgeries should be unified into one single hyperlink.
Optionally:
It would be good to also have the possibility to add a second, other hyperlink to Word 2:
"This does not need any open bladder surgeries."
The CRUCIAL REMARK from above, also applies here.
You cannot have one link that spans two separate words.
You can have one link on each of the words point to the same location and use a little bit of JavaScript to highlight all the links that have the same destination when the user hovers over one.
For convenience I'm using jQuery here, but the same thing isn't difficult to do without it.
$(function () {
function getKey(element) {
return element.href;
}
function sameGroupAs(element) {
var key = getKey(element);
return function () {
return getKey(this) === key;
}
}
$(document)
.on("mouseenter", "a", function () {
$("a").filter(sameGroupAs(this)).addClass("active");
})
.on("mouseleave", "a", function () {
$("a").filter(sameGroupAs(this)).removeClass("active");
});
});
a.active {
background-color: #A8C5FF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>"This does not need any open bladder surgeries."</p>
I've used the href as a grouping key, but you can use any other method of groping. Just modify the getKey() function.
Here's a pure HTML + CSS method. The trick is applying a negative z-index to the second word. That makes it unclickable:
a {
text-decoration: none;
}
a span:nth-child(1), a span:nth-child(3) {
font-weight: bold;
}
a:hover span:nth-child(1), a:hover span:nth-child(3) {
text-decoration: underline;
}
a span:nth-child(2) {
position: relative;
z-index: -1;
}
This does not need any
<a href="">
<span>open</span>
<span>bladder</span>
<span>surgeries</span>
</a>
.
If you want the second word to have a different link, I think you need to duplicate the HTML, making the first instance position: absolute, and the second word of the second instance position: relative. You can then change formatting based on hover:
a {
text-decoration: none;
font-weight: bold;
}
#a1 {
position: absolute;
}
#a2 span:nth-child(2) {
position: relative;
}
#a1:hover span:nth-child(1), #a1:hover span:nth-child(3) {
text-decoration: underline;
}
#a2:hover span:nth-child(2) {
text-decoration: underline;
}
This does not need any
<a id="a1" href="http://en.wikipedia.org/wiki/Invasiveness_of_surgical_procedures#Open_surgery">
<span>open</span>
<span>bladder</span>
<span>surgeries</span>
</a>
<a id="a2" href="http://en.wikipedia.org/wiki/Urinary_bladder">
<span>open</span>
<span>bladder</span>
<span>surgeries</span>
</a>
.
With Javascript it's easy - create a span for each word, style the two outer spans to look like links, and attach a single click function to both spans.
HTML
<span id = "one">one,</span>
<span id = "two">two,</span>
<span id = "three">three</span>
CSS
#one, #three {
cursor:pointer;
}
jQuery
$('#one, #three').click(function() {
location.href = 'http://www.google.com';
});
$('#one, #three').hover(function() {
$('#one, #three').css('text-decoration', 'underline');}, function(){
$('#one, #three').css('text-decoration', 'none');
});
using pure CSS, you can have one link that spans multiple words, and have only some of them clickable.
(and you can make it look nicer than my demo using some more CSS)
This answer doesn't fully meet the OP needs because it doesn't allow a different link within the context of the first link, but it's still worth mentioning.
In order to have one link only that spans multiple words, and also have a nested element that points to another link, we'd have to allow anchor tag nesting, but it's not supported, the best way to achieve the same behavior is to split the "big" anchor tag to pieces (manually or with JS like suggested in other answers)].
a span
{
color: black;
pointer-events: none;
}
first <span>second</span> third
The simplest way to go is maybe this css rule:
a {
text-decoration:none;
color:red;
}
span {
color:black;
cursor:default;
}
and a short inline js onclick event where you don't want the event propagated:
<span onclick="return false;"> Word2 </span>
jsFiddle example
But don't do that in production.
It's pointless and ugly.
If you want the second link inside the first one, for the sake of simplicity, i would do this:
<span onclick="document.location.href = 'YOUR_2ND_LINK_HERE'; return false;"> Word2 </span>
updated jsFiddle
Here you go then
new fiddle with visual hint
If this is what you want to achieve then:
Html:
<a href="http://www.wikipedia.org">
<span class="d">Link 1</span>
<span class="b">Link 2</span>
<span class="d">Link 1</span>
<span class="b">Link 2</span>
<span class="d">Link 1</span>
<span class="b">Link 2</span>
</a>
Css
a {
text-decoration:none;
}
.d {
color:blue;
text-decoration:underline;
}
.d.fake-hover {
background:blue;
color:#fff;
text-decoration:none;
}
.b {
color:darkRed;
text-decoration:underline;
}
.b.fake-hover {
background:darkRed;
color:#fff;
text-decoration:none;
}
Javascript:
var elems = document.getElementsByClassName('d');
var otherElems = document.getElementsByClassName('b');
var allElems = document.getElementsByTagName('span');
var _href = 'http://stackoverflow.com';
function fakeIt(what, el) {
var els = (el.classList.contains('d')) ? elems : otherElems;
for (var i = 0, x = els.length; i < x; i++) {
(what == 'hover') ? els[i].classList.add('fake-hover') : els[i].classList.remove('fake-hover');
}
}
function addCustomLink(e) {
e.preventDefault();
location.href = _href;
}
for (var i = 0, x = allElems.length; i < x; i++) {
var el = allElems[i];
el.addEventListener('mouseover', function(e) {
fakeIt('hover', e.target);
});
el.addEventListener('mouseout', function(e) {
fakeIt('out', e.target);
});
if (el.className == 'b') {
el.addEventListener('click', function(e) {
addCustomLink(e);
});
}
};
In jsFiddle apparently I can't use document.location.href so you have to manually edit the addCustomLink function.
Fiddle here

Text-overflow ellipsis on left side

I have a list of paths (for lack of a better word, maybe bread crumb trails describes them better). Some of the values are too long to display in their parent so I'm using text-overflow: ellipsis. The problem is that the important information is on the right, so I'd like the ellipsis to appear on the left. Something like this this ascii art:
----------------------------
|first > second > third |
|...second > third > fourth|
|...fifth > sixth > seventh|
----------------------------
Notice that the first row is short enough so it remains left aligned, but the other two are too long so the ellipsis appears on the left hand side.
I'd prefer a CSS only solution, but JS is fine if it can't be avoided. It's ok if the solution only works in Firefox and Chrome.
EDIT: At this point I'm looking for a work around for the bugs in Chrome that prevent it from rendering properly when a document is mixed RTL and LTR. That was all I really needed from the outset, I just didn't realize it.
How about something like this jsFiddle? It uses the direction, text-align, and text-overflow to get the ellipsis on the left. According to MDN, there may be the possibility of specifying the ellipsis on the left in the future with the left-overflow-type value however it's considered to still be experimental.
p {
white-space: nowrap;
overflow: hidden;
/* "overflow" value must be different from "visible" */
text-overflow: ellipsis;
width: 170px;
border: 1px solid #999;
direction: rtl;
text-align: left;
}
<p>first > second > third<br /> second > third > fourth > fifth > sixth<br /> fifth > sixth > seventh > eighth > ninth</p>​
I finally had to crack and do something in JavaScript. I was hoping that someone would come up with a hail-mary CSS solution but people seem to just be up-voting the answer that should be correct if it weren't for the Chrome bugs. j08691 can have the bounty for his work.
<html>
<head>
<style>
#container {
width: 200px;
border: 1px solid blue;
}
#container div {
width: 100%;
overflow: hidden;
white-space: nowrap;
}
</style>
<script>
function trimRows() {
var rows = document.getElementById('container').childNodes;
for (var i=0, row; row = rows[i]; i++) {
if (row.scrollWidth > row.offsetWidth) {
var textNode = row.firstChild;
var value = '...' + textNode.nodeValue;
do {
value = '...' + value.substr(4);
textNode.nodeValue = value;
} while (row.scrollWidth > row.offsetWidth);
}
}
}
</script>
</head>
<body onload='trimRows();'>
<div id="container" >
<div>first > second > third</div>
<div>second > third > fourth > fifth > sixth</div>
<div>fifth > sixth > seventh > eighth > ninth</div>​
</div>
</body>
</html>
Fiddle
Why not just using direction:rtl;
It's a little buggy, but maybe a point in the right direction
http://jsfiddle.net/HerrSerker/ZfbaD/50/
$('.container')
.animate({'width': 450}, 4000)
.animate({'width': 100}, 4000)
.animate({'width': 170}, 4000)
.container {
white-space: nowrap;
overflow: hidden; /* "overflow" value must be different from "visible" */
text-overflow: ellipsis;
width:170px;
border:1px solid #999;
direction:rtl;
}
.container .part {
direction:ltr;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<span class="part">second</span>
<span class="part">></span>
<span class="part">third</span>
<span class="part">></span>
<span class="part">fourth</span>
<span class="part">></span>
<span class="part">fifth</span>
<span class="part">></span>
<span class="part">sixth</span>
</div>
These solutions solve the problem with misinterpreted preceding or trailing weak or neutral BiDi characters such as /, \, ~, ., etc. (basically any punctuation or special characters).
CSS Solution
Use a combination of:
direction: rtl & ltr
unicode-bidi: bidi-override
p {
direction: rtl;
max-width: 180px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap; /* or pre (e.g. preserve multiple spaces) */
}
span {
direction: ltr;
unicode-bidi: bidi-override; /* or isolate, isolate-override, embed */
}
<p><span>/path/to/a/very/long/file.name</span></p>
<bdo> Solution
Another possibility uses the <bdo> Bidirectional Text Override element:
p {
max-width: 180px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap; /* or pre (e.g. preserve multiple spaces) */
}
<bdo dir="rtl">
<p>
<bdo dir="ltr">/path/to/a/very/long/file.name</bdo>
</p>
</bdo>
Using #Hemlocks, #Brian Mortenson and #Jimbo's solutions, I've built a jQuery plugin to solve this problem.
I've also added support to return the initial value using .html() rather than having it return the current innerHTML. Hopefully it will be useful to someone...
(function($) {
$.trimLeft = function(element, options) {
var trim = this;
var $element = $(element), // reference to the jQuery version of DOM element
element = element; // reference to the actual DOM element
var initialText = element.innerHTML;
trim.init = function() {
overrideNodeMethod("html", function(){ return initialText; });
trimContents(element, element);
return trim;
};
trim.reset = function(){
element.innerHTML = initialText;
return trim;
};
//Overide .html() to return initialText.
var overrideNodeMethod = function(methodName, action) {
var originalVal = $.fn[methodName];
var thisNode = $element;
$.fn[methodName] = function() {
if (this[0]==thisNode[0]) {
return action.apply(this, arguments);
} else {
return originalVal.apply(this, arguments);
}
};
};
var trimContents = function(row, node){
while (row.scrollWidth > row.offsetWidth) {
var childNode = node.firstChild;
if (!childNode)
return true;
if (childNode.nodeType == document.TEXT_NODE){
trimText(row, node, childNode);
}
else {
var empty = trimContents(row, childNode);
if (empty){
node.removeChild(childNode);
}
}
};
};
var trimText = function(row, node, textNode){
var value = '\u2026' + textNode.nodeValue;
do {
value = '\u2026' + value.substr(4);
textNode.nodeValue = value;
if (value == '\u2026'){
node.removeChild(textNode);
return;
}
}
while (row.scrollWidth > row.offsetWidth);
};
trim.init();
};
$.fn.trimLeft = (function(options){
var othat = this;
var single = function(that){
if (undefined == $(that).data('trim')) {
var trim = new $.trimLeft(that, options);
$(that).data('trim', trim);
$(window).resize(function(){
$(that).each(function(){
trim.reset().init();
});
});
}
};
var multiple = function(){
$(othat).each(function() {
single(this);
});
};
if($(othat).length>1)
multiple(othat);
else
single(othat);
//-----------
return this;
});
})(jQuery);
Initiate using:
//Call on elements with overflow: hidden and white-space: nowrap
$('#container>div').trimLeft();
//Returns the original innerHTML
console.log($('#test').html());
fiddle
Using a slightly more complex markup (using the bdi-tag and an extra span for the ellipsis), we can solve the problem fully in CSS, no JS required at all -- cross browser (IE, FF, Chrome) and including keeping punctuation marks to the right:
http://jsbin.com/dodijuwebe/1/edit?html,css,output
Granted, this is something of a hack, involving pseudo-element goodness. However, our team has been using this code in production and we haven't had any issues whatsoever.
The only caveats are: The height of the line needs to be fixed and the background color needs to be known explicitly (inherit won't work).
If you don't care the indexing of those texts, you could use this method (it reverses the text lines):
If you have in your texts other HTML elements besides <br> you need to make some arrangements to use this method.
HTML code:
<p>first > second > third<br/>
second > third > fourth <br>
fifth > sixth > seventh</p>
CSS code:
p{
overflow: hidden;
text-overflow: ellipsis;
unicode-bidi: bidi-override;
direction: rtl;
text-align: left;
white-space: nowrap;
width: 140px;
}
JavaScript code
[].forEach.call(document.getElementsByTagName("p"), function(item) {
var str = item.innerText;
//Change the operators
str = str.replace(/[<>]/g, function(char){ return ({"<" : ">", ">" : "<"})[char] });
//Get lines
var lines = str.split(/\n/);
//Reverse the lines
lines = lines.map(function(l){ return l.split("").reverse().join("") });
//Join the lines
str = lines.join("<br>");
item.innerHTML = str;
});
jsfiddle
Based on your edit:
At this point I'm looking for a work around for the bugs in Chrome
that prevent it from rendering properly when a document is mixed RTL
and LTR. That was all I really needed from the outset, I just didn't
realize it.
Have you looked into the unicode-bidi css property (see Sitepoint or W3C)? I actually just learned about this myself on another recent post. My guess is you would want to use the embed value for those pieces going the opposite direction to the main site. So in j08691's answer where it is direction: rtl add unicode-bidi: embed to the CSS. This should solve "mixed RTL and LTR" issues you are having.
I put some JavaScript together to regex out three items and add the ellipsis in where necessary. This does not explicitly look at how much text will fit in the box but if the box is fixed this may not be an issue.
<style>
p {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width:170px;
border:1px solid #999;
direction:rtl;
text-align:left;
}
</style>
<p>first > second > third<br />
second > third > fourth > fifth > sixth<br />
fifth < sixth < seventh < eighth < ninth</p>
<script>
var text = $( 'p' ).text(),
split = text.split( '\n' ),
finalStr = '';
for( i in split ){
finalStr = finalStr.length > 0 ? finalStr + '<br />' : finalStr;
var match = /(\w+\s?(<|>)?\s?){3}$/.exec( split[i] );
finalStr = finalStr + ( split[i].length > match[0].length ? '...' : '' ) + match[0];
}
$( 'p' ).empty().html( finalStr );
</script>

Need clean truncation of text for showing more-less

Using this javascript to show more-less, is there a simple way to make the text cut off clean so that it displayes whole lines of text (doesn't slice them horizontally)?
<div id="description" style="height: 20px; overflow: hidden">
Lots of text.
</div>
Show more/less>>
<script>
var open = false;
$('#more-less').click(function() {
if (open) {
$('#description').animate({height:'20px'});
}
else {
$('#description').animate({height:'100%'});
}
open = !open;
});
If it makes it easier I can truncate on <br /> tags.
Change 20px to a value in ems, such as 2em. One em is (approximately?) equal to the height of one line. You should also set the margin and padding on the p tag in ems.

Categories