I want to trim a string down to a particular pixel width so that it can properly fit in a container. It will be similar to substring, except that I am trimming based on pixel width as opposed to number of characters. is there a built in function for this?
Maybe this is what you're looking for:
jQuery Text Overflow plugin
Lg
warappa
You can do it via css: text-overflow: clip;
Note: This is not supported in FF < 7. Every other browser including IE6 supports it.
Try this:
function trimByPixel(str, width) {
var spn = $('<span style="visibility:hidden"></span>').text(str).appendTo('body');
var txt = str;
while (spn.width() > width) { txt = txt.slice(0, -1); spn.text(txt + "..."); }
return txt;
}
CSS might be the easiest/best option, especially if you're trying to keep text confined to an area. Check out both word-wrap and text-overflow, as they might be v
Related
I am trying to grab the HTML from a CSS truncated element and can't seem to get it right.
For example:
<span id=mySpan style=white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:50px>This is the contents of the span tag. It should truncate with an ellipsis if it is longer than 50px.</span>
If I use the standard jQuery way to grab the HTML, I get the full text, not the truncated version. I'm not sure if it is even possible.
html = jQuery('#mySpan').html();
text = jQuery('#mySpan').text();
Both return the full text. I'm stumped.
You can compute it :
$.fn.renderedText = function(){
var o = s = this.text();
while (s.length && (this[0].scrollWidth>this.innerWidth())){
s = s.slice(0,-1);
this.text(s+"…");
}
this.text(o);
return s;
}
var renderedText = $("#mySpan").renderedText(); // this is your visible string
Demonstration
Of course this only works for an element with overflow:hidden;text-overflow:ellipsis but it's easy to adapt when there's no text-overflow:ellipsis: just remove the +"…".
Note that this is compatible with all browsers and gives the exact result (the w3.org specifies that the … character is to be used by the browser).
#dystroy has given a nice answer, here is another (more future-friendly) way to do this though.
We can use document.caretPositionFromPoint. This is almost a FF only function, but most other browsers provide the same thing under their own function name and API. No I don't know what browsers have against devs but oh well...
Our method works like this:
select element
get bounding client position
put it in the above function to get text offset position
subtract 3 from it to remove the ellipsis thingy from the offset
extract text according to that offset from textContent property
Here is a quick demo (should work properly in Webkit and Gecko):
function getRenderedText (el) {
var pos = el.getBoundingClientRect();
var offset, range;
if (document.caretRangeFromPoint) {
range = document.caretRangeFromPoint(pos.right, pos.top);
offset = range.endOffset - 3;
}
else if (document.caretPositionFromPoint) {
range = document.caretPositionFromPoint(pos.right, pos.top);
offset = range.offset - 3;
}
else {
console.error('Your browser is not supported yet :(');
}
return el.textContent.slice(0, offset);
}
console.log(getRenderedText(el));
span {
text-overflow: ellipsis;
width: 40px;
white-space: nowrap;
display: block;
overflow: hidden;
}
<span id="el">foo bar is so much awesome it is almost the bestest thing in the world. devs love foo bar. foo bar all the things!</span>
I have seen an error of maximum 1 character in some cases (weird fonts or edge cases), but most of the time, it works fine.
Hope that helps!
Is it possible to get the width (using javascript or jQuery) of a float-affected element? When text is being pushed over due to a floating image is it possible to get its position and true width? I have attached an image to explain better.
Code example,
<div>
<img style="...float: left"/>
<h1>A title!</h1>
<p>Text!</p>
<h1>New header added.</h1>
</div>
Picture
I need to find the width starting from the arrow, (the gray box is the image)(the dotted line is the width according to Firefox inspect mode).
I would like to avoid changing all the elements display types if possible.
Thank you!
I'm a little late to the party, but I had a similar problem and came up with a solution which (so far) seems to work in all instances of this issue. I like this solution because as far as I can tell, it works independent of the floating element - all you need is the element whose true width/position you want to get, nothing more. I've done it in pure Javascript for speed purposes, but it can easily be streamlined with jQuery and a separate CSS Stylesheet if you so choose.
//Get the rendered bounding box for the content of any HTMLElement "el"
var getLimits = function(el) {
//Set a universal style for both tester spans; use "!important" to make sure other styles don't mess things up!
var testerStyle = 'width: 0px!important; overflow: hidden!important; color: transparent!important;';
//Create a 'tester' span and place it BEFORE the content
var testerStart = document.createElement('SPAN');
testerStart.innerHTML = '|';
var testerFloat = ' float: left!important;';
testerStart.setAttribute('style', testerStyle + testerFloat);
//Insert testerStart before the first child of our element
if (el.firstChild) {
el.insertBefore(testerStart, el.firstChild);
} else {
el.appendChild(testerStart);
}
//Create a 'tester' span and place it AFTER the content
var testerEnd = document.createElement('SPAN');
testerEnd.innerHTML = '|';
testerFloat = ' float: right!important;';
testerEnd.setAttribute('style', testerStyle + testerFloat);
el.appendChild(testerEnd);
//Measure the testers
var limits = {
top: testerStart.offsetTop,
bottom: testerEnd.offsetTop + testerEnd.offsetHeight,
left: testerStart.offsetLeft,
right: testerEnd.offsetLeft
}
//Remove the testers and return
el.removeChild(testerStart);
el.removeChild(testerEnd);
return limits;
};
So, in your case, the code would just be:
var paragraphBoundingBox = getLimits($('div>p').get(0));
A couple things to note:
1) The float direction would be reversed if you are using an RTL language
2) All of the four edge positions in the output object are relative to the el.offsetParent - use this handy function can find their positions relative to the document.
First of all, the "full width" is exactly the true width.
You can watch this picture, it can help you understand why the true width and true position of the affected element is the way firefox tells you.
http://i.stack.imgur.com/mB5Ds.png
To get the width of inline text where it's pushed right by the float image, there's no good way except using the full width minus the float image's width.
var w = $('p').width()
- $('img').width()
- $('img').css('margin-left').replace("px", "")
- $('img').css('margin-right').replace("px", "")
- $('img').css('padding-left').replace("px", "")
- $('img').css('padding-right').replace("px", "")
- $('img').css('border-left-width').replace("px", "")
- $('img').css('border-right-width').replace("px", "");
I am looking for a function which replaces part of a string which is wider than 50px with "...". I want to implement it in Javascript/jQuery.
Example:
Say I have a variable var="Theta Saving Non-Qualified Plan"; I want to put a restriction on the length of the string (based on pixel width). If the length of string is more that 50px, then the part of the string which is from the 51st pixel to theend of string will be replaced with "...".
Any idea guys?
Don't try to reinvent the wheel. Use a Jquery plugin like this: http://tpgblog.com/2009/12/21/threedots-the-jquery-ellipsis-plugin/
Here's a solution if you want to truncate the visual and don't really need to truncate the actual string:
<p>
<span style='width: 50px; height: 1em;
overflow: hidden; display: inline-block'>
This is the long string which should appear truncated followed by elipses
</span>
<span>...</span>
</p>
To make it work in IE6 and 7, I think you need to add the following CSS:
zoom: 1
*display: inline;
This cannot be deduced as easy as you would like it to be. Because how much width a character or set of characters will take will depend upon the font-size. And calculating a text width is hardly accurate.
So, its better you create your interface to be friendly with characters rather than the width.
var t = $("#div").text();
if(t.length > 50) {
$("#div").text(t.substr(0,50)+"...");
}
If your text is already enclosed in a block element with 50px width, you can use the text-overflow CSS rule, which is widely supported by virtually all browsers. Also see text-overflow at quirksmode.
I would split the string in an array, then add letter after letter testing the width of the element to know if it's lower than 50px
ie :
var vElement = $('.your_element');
var vStr = vElement.html();
var vShortStr = "";
var vArray = vStr.split("");
for (var i=0; i<vArray.length; i++){
vShortStr += vArray[i];
vElement.html(vShortStr);
if(vElement.width() > 50){
vShortStr = vShortStr.substring(0, vShortStr.length-1);
vShortStr += "...";
vElement.html(vShortStr);
break;
}
}
I'm trying to dynamically change the height of a cell than contains a div. Now i can change the height of the div, just fine, but when I try the cell, it just doesn't work, yet I get no errors. Any Ideas on why this doesn't work?
if( df0.checkbox1.checked)
{
document.getElementById('layerOne').style.visibility = 'visible';
document.getElementById('layerOne').style.height = 125;
document.getElementById('eftcell').height = '125px'
}
else
{
document.getElementById('layerOne').style.visibility = 'hidden';
document.getElementById('layerOne').style.height = 1;
document.getElementById('eftcell').height = '1px'
}
Use the "px" unit when changing style.property:
document.getElementById('layerOne').style.height = "125px";
document.getElementById('eftcell').height = 125;
I did a bit of testing in FireFox 4 (via Firebug), it seems to work for me. Here are some things to look for:
Try using just the number 125 for height, rather than the string '125px'
Make sure that the element with id="eftcell" is the <td> element, not its parent <tr>
Look into compatibility issues between browsers, maybe your browser doesn't allow a height attribute on <td>?
Needs px and to be in a string. Also HTML5 doesn't support javascript height on TD cells.
I need a Jquery script to truncate a text paragraph by line (not by character count).
I would like to achieve an evenly truncated text-block. It should have a "more" and "less" link to expand and shorten the text paragraph. My text paragraph is wrapped in a div with a class, like this:
<div class="content">
<h2>Headline</h2>
<p>The paragraph Text here</p>
</div>
The closest solution i could find on SOF is the one below (but it`s for textarea element and does not work for me):
Limiting number of lines in textarea
Many thanks for any tips.
Ben
For a basic approach, you could take a look at the line-height CSS property and use that in your calculations. Bear in mind that this approach will not account for other inline elements that are larger than that height (e.g. images).
If you want something a bit more advanced, you can get the information about each line using getClientRects() function. This function returns a collection of TextRectangle objects with width, height and offset for each one.
See this answer here for an example (albeit an unrelated goal) of how getClientRects() works.
Update, had a bit of time to come back and update this answer with an actual example. It's basic, but you get the idea:
http://jsbin.com/ukaqu3/2
A couple of pointers:
The collection returned by getClientRects is static, it won't update automatically if the containing element's dimensions change. My example works around this by capturing the window's resize event.
For some strange standards-compliance reason that I'm not understanding, the element you call getClientRects on must be an inline element. In the example I have, I use a container div with the text in another div inside with display: inline.
I made this little jQuery code to allow me truncate text blocks by line (via CSS classes), feel free to use and comment it.
Here is the jsFiddle, which also include truncate functions by char count or word count. You can see that currently, resize the window won't refresh the block display, I'm working on it.
/*
* Truncate a text bloc after x lines
* <p class="t_truncate_l_2">Lorem ipsum magna eiusmod sit labore.</p>
*/
$("*").filter(function () {
return /t_truncate_l_/.test($(this).attr('class'));
}).each(function() {
var el = $(this);
var content = el.text();
var classList = el.attr('class').split(/\s+/);
$.each(classList, function(index, item){
if(/^t_truncate_l_/.test(item)) {
var n = item.substr(13);
var lineHeight = parseInt(el.css('line-height'));
if(lineHeight == 1 || el.css('line-height') == 'normal')
lineHeight = parseInt(el.css('font-size')) * 1.3;
var maxHeight = n * lineHeight;
var truncated = $.trim(content);
var old;
if(el.height() > maxHeight)
truncated += '...';
while(el.height() > maxHeight && old != truncated) {
old = truncated;
truncated = truncated.replace(/\s[^\s]*\.\.\.$/, '...');
el.text(truncated);
}
}
});
});
why not make the p element with overflow: hidden; give fixed line height, caluclate the height of the div so id contains exactly the number of lines you require and the only change the height of the p from javascript.
p{
overflow:hidden;
line-height:13px;
height:26px; /* show only 2 rows */
}
<script type="text/javascript">
function seeMoreRows(){
$(p).height("52px");
}
</script>
I made a small module that works with pure text content, no nested tags and no css-padding on the text-containing element is allowed (but this functionality could easily be added).
The HTML:
<p class="ellipsis" data-ellipsis-max-line-count="3">
Put some multiline text here
</p>
The Javascript/Jquery:
( function() {
$(document).ready(function(){
store_contents();
lazy_update(1000);
});
// Lazy update saves performance for other tasks...
var lazy_update = function(delay) {
window.lazy_update_timeout = setTimeout(function(){
update_ellipsis();
$(window).one('resize', function() {
lazy_update(delay);
});
}, delay);
}
var store_contents = function(){
$('.ellipsis').each(function(){
var p = $(this);
p.data('ellipsis-storage', p.html());
});
}
var update_ellipsis = function(){
$('.ellipsis').each(function(){
var p = $(this);
var max_line_count = p.data('ellipsis-max-line-count');
var line_height = p.html(' ').outerHeight();
var max_height = max_line_count*line_height;
p.html(p.data('ellipsis-storage'));
var p_height = p.outerHeight();
while(p_height > max_height){
var content_arr = p.html().split(' ');
content_arr.pop();
content_arr.pop();
content_arr.push('...');
p.html(content_arr.join(' '));
p_height = p.outerHeight();
}
});
}
} )();
I hope you like it!
If you used a monospaced font, you'd have a shot at this working, as you'd have a good idea how many letters fit onto each line, for an element of a defined width. However, if a word breaks across lines, then this might get tricky..
e: found another question which is basically what you're after - they didn't really have a resolution either, but to my mind, the line-height and element height seems closest.
"How can I count text lines inside a dom element"
tl;dr - set a height on your container div and then use the jQuery dotdotdot plugin
Was about to make #Andy E's awesome example into a plugin, but then realized https://github.com/BeSite/jQuery.dotdotdot could pull this off. Our use case is we want to show one line on desktop widths and two lines on mobile/tablet.
Our CSS will just set the container div to the equivalent of one or two line-height's accordingly and then the dotdotdot plugin appears to handle the rest.