Add a title property to elements with text-overflow: ellipsis - javascript

I am not sure if this is easily possible, but I thought I would ask just in case:
I am using the following CSS rules on a list of text:
{
width: 100px;
overflow: hidden;
text-overflow: ellipsis;
}
As expected, any text that goes outside the list will be truncated and have an ellipsis placed on the end.
I want to have an active title property for only those list items that trigger the text-overflow rule on the list. So you can hover the mouse over any text that is truncated and see a tooltip of its full text.
Something tells me this is difficult, if not impossible, to do. However I would love to be proven wrong. I am preferably looking for a solution that uses as little JavaScript as possible.

We use a similar, more generic ellipsify, which works perfectly for most cases. We also apply the title attribute (for all elements). Only applying the title if the element ellipsifies, is indeed difficult. The example below assumes that, if the element has the same width as the parent, we should set the title. Without the if statement it would always apply the title.
document.querySelectorAll('.ellipsify').forEach(function (elem) {
if (parseFloat(window.getComputedStyle(elem).width) === parseFloat(window.getComputedStyle(elem.parentElement).width)) {
elem.setAttribute('title', elem.textContent);
}
});
.ellipsify {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
max-width: 100%;
display: inline-block;
}
div {
width: 100px;
}
<div>
<span class="ellipsify">dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna</span>
<span class="ellipsify">dolor sit amet</span>
</div>

This is how i approached the solution.
If you don't want to use java-script.
Here is a Link to fiddle: https://jsfiddle.net/fryc4j52/1/
SNIPPET:
.ellipse{
width: 100px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin:0;
padding:0;
}
.content li{
margin:0;
padding:0;
overflow:hidden;
}
.ellipse:hover{
width: auto;
border: 2px solid #eee;
box-shadow: 0px 3px 10px 0px black;
padding:2px;
white-space: normal;
word-break: break-word;
z-index:5;
}
<ul class="content">
<li class="ellipse">A very looooooooooooooooooooooooooooooooooooooong line.</li>
<li> Other text</li>
<li class="ellipse">A veryvvvvvvvvvvvvvvvvvvvvvvverrrrryyyyyyyyy looooooooooooooooooooooooooooooooooooooong line.</li>
</ul>

document.querySelectorAll('.ellipsis').forEach(function (e) {
if (e.offsetWidth < e.scrollWidth) {
e.setAttribute('title', e.textContent);
} else{
e.removeAttribute('title');
}
});
.ellipsis {
text-overflow: ellipsis;
display: inline-block;
max-width: 100%;
overflow: hidden;
white-space: nowrap;
}

You can measure for the presence of overflow with a little JavaScript and only add the title attribute if it the element would have overflowed (had it not been truncated).
Constrain the content with a style.
Copy the content into a hidden test element with the same width.
Don't limit wrapping on the test element, allowing it to overflow.
Compare the heights.
$(".smart-overflow").each(function() {
var elementToTest = $(this),
contentToTest = $(this).text(),
testElement = $("<div/>").css({
position: "absolute",
left: "-10000px",
width: elementToTest.width() + "px"
}).appendTo("body").text(contentToTest);
if (testElement.height() > elementToTest.height()) {
elementToTest.attr("title", contentToTest);
}
});
.smart-overflow {
width: 100px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="smart-overflow">
short text
</div>
<div class="smart-overflow">
short text
</div>
<div class="smart-overflow">
Longer text; there should be a tooltip here.
</div>
<div class="smart-overflow">
More long text. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vestibulum lorem eget justo tempus posuere. Integer ac sagittis nisi. Phasellus eu malesuada sapien. Aliquam erat volutpat. Nunc aliquet neque sagittis eros ullamcorper,
blandit facilisis magna gravida. Nulla a euismod turpis.
</div>
<div class="smart-overflow">
More long text. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vestibulum lorem eget justo tempus posuere. Integer ac sagittis nisi. Phasellus eu malesuada sapien. Aliquam erat volutpat. Nunc aliquet neque sagittis eros ullamcorper,
blandit facilisis magna gravida. Nulla a euismod turpis.
</div>
<div class="smart-overflow">
short text
</div>
<div class="smart-overflow">
short text
</div>
jQuery used here for conciseness, but certainly not required.

Related

Distribute text with right-to-left script evenly in 15 lines inside its container

I want to display some text in 15 rows with full width and height regardless of which device or browser you view the page. How to achieve this using Html, CSS and JS ?
Please see screen shots
This is my screen shot which it has more than 15 rows and the last line is not full width.
.aya {
direction: rtl !important;
font-family: "uthmanic","Traditional Arabic", "Montserrat","sans-serif","Times New Roman";
font-weight: normal;
font-size:25px;
}
.ayaNumber {
font-size: 15px;
white-space: nowrap;
color: #050;
cursor: pointer;
font-weight: normal;
padding-left: 5px;
padding-right: 5px;
}
<div class="card h-100 card-body " dir="rtl" align="justify"
style="direction: rtl !important; background-color:#f7fce3;border-color: #f7fce3;">
<div class="card-body">
<!-- using 'text' class below -->
<p class="card-text text" align="justify" style="text-align-last: right;text-align: justify;" >
<span class="aya">
مَثَلُهُمْ كَمَثَلِ ٱلَّذِى ٱسْتَوْقَدَ نَارًا فَلَمَّآ أَضَآءَتْ مَا حَوْلَهُۥ ذَهَبَ ٱللَّهُ بِنُورِهِمْ وَتَرَكَهُمْ فِى ظُلُمَٰتٍ لَّا يُبْصِرُونَ﴿17﴾صُمٌّۢ بُكْمٌ عُمْىٌ فَهُمْ لَا يَرْجِعُونَ﴿18﴾أَوْ كَصَيِّبٍ مِّنَ ٱلسَّمَآءِ فِيهِ ظُلُمَٰتٌ وَرَعْدٌ وَبَرْقٌ يَجْعَلُونَ أَصَٰبِعَهُمْ فِىٓ ءَاذَانِهِم مِّنَ ٱلصَّوَٰعِقِ حَذَرَ ٱلْمَوْتِ ۚ وَٱللَّهُ مُحِيطٌۢ بِٱلْكَٰفِرِينَ﴿19﴾يَكَادُ ٱلْبَرْقُ يَخْطَفُ أَبْصَٰرَهُمْ ۖ كُلَّمَآ أَضَآءَ لَهُم مَّشَوْا۟ فِيهِ وَإِذَآ أَظْلَمَ عَلَيْهِمْ قَامُوا۟ ۚ وَلَوْ شَآءَ ٱللَّهُ لَذَهَبَ بِسَمْعِهِمْ وَأَبْصَٰرِهِمْ ۚ إِنَّ ٱللَّهَ عَلَىٰ كُلِّ شَىْءٍ قَدِيرٌ﴿20﴾يَٰٓأَيُّهَا ٱلنَّاسُ ٱعْبُدُوا۟ رَبَّكُمُ ٱلَّذِى خَلَقَكُمْ وَٱلَّذِينَ مِن قَبْلِكُمْ لَعَلَّكُمْ تَتَّقُونَ﴿21﴾ٱلَّذِى جَعَلَ لَكُمُ ٱلْأَرْضَ فِرَٰشًا وَٱلسَّمَآءَ بِنَآءً وَأَنزَلَ مِنَ ٱلسَّمَآءِ مَآءً فَأَخْرَجَ بِهِۦ مِنَ ٱلثَّمَرَٰتِ رِزْقًا لَّكُمْ ۖ فَلَا تَجْعَلُوا۟ لِلَّهِ أَندَادًا وَأَنتُمْ تَعْلَمُونَ﴿22﴾وَإِن كُنتُمْ فِى رَيْبٍ مِّمَّا نَزَّلْنَا عَلَىٰ عَبْدِنَا فَأْتُوا۟ بِسُورَةٍ مِّن مِّثْلِهِۦ وَٱدْعُوا۟ شُهَدَآءَكُم مِّن دُونِ ٱللَّهِ إِن كُنتُمْ صَٰدِقِينَ﴿23﴾فَإِن لَّمْ تَفْعَلُوا۟ وَلَن تَفْعَلُوا۟ فَٱتَّقُوا۟ ٱلنَّارَ ٱلَّتِى وَقُودُهَا ٱلنَّاسُ وَٱلْحِجَارَةُ ۖ أُعِدَّتْ لِلْكَٰفِرِينَ﴿24﴾
</span>
</p>
</div>
<footer style="text-align: center;">4</footer>
</div>
Below is what I want to achieve (15 rows, full width and height)
You can use a line clamp as well as vw in a font size to force it to 15 lines and also shrink the text size so it will fit in 15 lines or less. Please note though this is only good for so much text, you can't shrink the font size of an entire book to fit into 15 lines. But hopefully its good enough for what you're looking for.
here's the jsfiddle of an example so you can play with it by stretching and shrinking the output box: https://jsfiddle.net/drm6sqfx/
body {
margin: 20px;
}
.text {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 15; /* number of lines to show */
-webkit-box-orient: vertical;
font-size: 5vw;
}
<div class="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam consectetur venenatis blandit. Praesent vehicula, libero non pretium vulputate, lacus arcu facilisis lectus, sed feugiat tellus nulla eu dolor. Nulla porta bibendum lectus quis euismod. Aliquam volutpat ultricies porttitor. Cras risus nisi, accumsan vel cursus ut, sollicitudin vitae dolor. Fusce scelerisque eleifend lectus in bibendum. Suspendisse lacinia egestas felis a volutpat.

CSS transition works only if Chrome Dev Tools open

I've run into a bizarre anomaly with CSS transitions. The transition is completely ignored on load; but if I open up Chrome Dev Tools and navigate the DOM tree to #popup > div > img and select it, then click on the main image, the transition becomes functional, and remains so even if Dev Tools is closed.
My suspicion is that I've made some weird mistake that I can't see. But when opening Dev Tools to try to probe my CSS makes it suddenly start working, it's a bit hard to debug!
Tested on Chrome 66.0.3359.139. The behaviour is the same in Codepen and as a stand-alone HTML file.
My intention is for clicking on the small image to show a larger one. With the popup visible, clicking anywhere will dismiss that popup. Both showing and dismissing the popup should transition smoothly; for this demo, that's an opacity change followed by a change to the image's top (making it scroll in from above the screen). The popup is controlled by setting a class on the HTML element.
document.getElementById("clickme").onclick = function(ev) {
document.documentElement.classList.add("show-modal");
ev.stopPropagation();
}
document.documentElement.onclick = function() {
this.classList.remove("show-modal");
}
#clickme {
max-height: 300px;
cursor: pointer;
margin: 20px;
border: 1px solid #ddd;
border-radius: .25rem;
padding: 10px;
}
#popup {
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0px;
z-index: 2000;
padding-top: 30px;
display: none;
}
.show-modal #popup {
display: block;
}
#popup img {
display: block;
margin: auto;
position: relative;
top: -500px;
opacity: 0;
transition: top .5s 1s, opacity .25s;
}
.show-modal #popup img {
top: 0px;
opacity: 1;
}
#popup>div {
margin: auto;
}
<p><img id=clickme src="http://devicatoutlet.com/img/birthday.png"></p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut euismod, ipsum at porttitor condimentum, turpis ex porta erat, et laoreet purus dui a quam. Vestibulum eget consequat neque, in faucibus turpis. Interdum et malesuada fames ac ante ipsum primis
in faucibus. Praesent interdum sit amet odio eu consequat. Aliquam eget scelerisque odio. Suspendisse potenti. Aenean at risus a dolor facilisis dignissim. Sed et volutpat eros. Nam eget imperdiet lacus. Mauris imperdiet rutrum efficitur.</p>
<div id="popup">
<div><img src="http://devicatoutlet.com/img/birthday.png"></div>
</div>
View on CodePen
CSS can't animate between display: none; and display: block; (of the #popup element). I changed to visibility for #popup.
You can see the new code here: https://codepen.io/anon/pen/KRoPwM. Hope this helps.

Figure out seamless scrolling w/ position: fixed element on iOS 8

What I need to achieve can be seen on this demo.
Basically a page with a rectangle area that you reach by scrolling down, where there's content that appears as if it were a position: fixed element. In the demo above, the revealed content is a page displayed through an iframe - I'm happy with just an image.
I only need this to work on iOS 8. From what I can see, the demo does it through some custom scrolling mechanism. I suspect they have somehow overwritten scrolling altogether - although I can't confirm it's a custom scrolling framework like iScroll.
My own approach was to re-position a clip: rect area on a position: fixed background image, through a onscroll handler. Sort of like moving a mask around, on an image. Example here
The code I use in my JS onscroll handler to re-position the clipping rectangle:
topY = adDiv.getBoundingClientRect().top + window.pageYOffset - adDiv.ownerDocument.documentElement.clientTop;
scrollT = (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
newY = topY - scrollT;
newHeight = rectHeight + newY;
document.getElementById("bgImg").style.clip = "rect("+newY+"px,1900px,"+newHeight+"px,0px)";
I'd be happy with this if there weren't for a delay while re-positioning the clip: rect area; you can see it if you test on anything iOS 8 (there is a slight delay when you scroll/swipe up and down around the area that reveals the image). Wasn't able to overcome this and fear it's by-design.
EDIT: please note I need to have the content that is above and below the reveal area, see-through; so with a transparent background that would allow you to see the page's background; can't mess with anything above and below.
I've stripped the demo you linked down to the essentials, in which there seems to be three elements of importance, one container, one which is used for the clipping, and the third for the content.
<div class="container">
<div class="clip-box">
<div class="content">
...
</div>
</div>
</div>
The "container" defines the area you want to use in line with the text;
.container {
position: relative;
width: 100%;
height: 10em;
}
The clip-element is where the interesting happens. It's made to fill the parent, which makes the clip: rect(auto ... auto) clip the element (and therefore also it's children) at its edges. It's important that this element is set position: absolute or position: fixed, as clipping only applies to absolutely positioned elements.
.clip-box {
position: absolute;
left: 0;
top: 0;
width:100%;
height:100%;
clip: rect(auto auto auto auto);
}
Lastly we have the content as a child of the clip-element. It is set to a fixed position but will only render in the clip-rect area defined by the parents’ bounding-box.
.content {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
margin: 0;
}
Here's a snippet of the above which uses only css.
body {
background-image: url("http://lorempixel.com/500/500/");
background-size: cover;
color: #FFF;
margin: 0;
text-align: center;
}
img {
width: 100%;
}
.content p {
position: absolute;
top: 0;
left: 0;
text-align: left;
}
.window {
position: relative;
width: 100%;
height: 10em;
}
.clip-box {
position: absolute;
left: 0;
top: 0;
width:100%;
height:100%;
clip: rect(auto auto auto auto);
}
.content {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
margin: 0;
}
<p>
Lorem ipsum
<br>dolor sit amet,
<br>consectetur adipiscing elit.
<br>Morbi convallis
<br>accumsan neque,
<br>eu accumsan magna
<br>laoreet cursus.
<br>Etiam feugiat mattis
<br>nunc eget luctus.
<br>Proin vel dictum est.
<br>Nullam suscipit quam
<br>at ullamcorper vestibulum.
<br>Lorem ipsum
<br>dolor sit amet,
<br>consectetur adipiscing elit.
<br>Curabitur rutrum
<br>elementum ligula,
<br>suscipit sodales
<br>nisl convallis a.
</p>
<div class="window">
<div class="clip-box">
<div class="content">
<img src="http://lorempixel.com/500/400/">
<p>
Lorem ipsum
<br>dolor sit amet,
<br>consectetur adipiscing elit.
<br>Morbi convallis
<br>accumsan neque,
<br>eu accumsan magna
<br>laoreet cursus.
<br>Etiam feugiat mattis
<br>nunc eget luctus.
<br>Proin vel dictum est.
<br>Nullam suscipit quam
<br>at ullamcorper vestibulum.
<br>Lorem ipsum
<br>dolor sit amet,
<br>consectetur adipiscing elit.
<br>Curabitur rutrum
<br>elementum ligula,
<br>suscipit sodales
<br>nisl convallis a.
</p>
</div>
</div>
</div>
<p>
Lorem ipsum
<br>dolor sit amet,
<br>consectetur adipiscing elit.
<br>Morbi convallis
<br>accumsan neque,
<br>eu accumsan magna
<br>laoreet cursus.
<br>Etiam feugiat mattis
<br>nunc eget luctus.
<br>Proin vel dictum est.
<br>Nullam suscipit quam
<br>at ullamcorper vestibulum.
<br>Lorem ipsum
<br>dolor sit amet,
<br>consectetur adipiscing elit.
<br>Curabitur rutrum
<br>elementum ligula,
<br>suscipit sodales
<br>nisl convallis a.
</p>
You should however note that the clip property is deprecated and developers are advised to use clip-path instead. This is an experimental technology though and if you're only wanting to use images anyway I'd recommend using background-attachment: fixed; which will give you the same result as the code above.

jquery - setting dynamic equal height of a floated div

I have 2 div containers, one navigation on the left, one content right to that:
#leftnav_static
{
padding:5px;
margin-top: 5px;
margin-left: 5px;
height: 1000px;
width: 195px;
font-size: 1.35em;
float:left;
background-image: url('pagenav.jpg');
}
#content_dynamic
{
margin-top: 5px;
margin-left: 215px;
height: auto;
width: 700px;
padding: 5px;
background-image: url('pagenav.jpg');
font-size: 1em;
line-height:1.6em;
white-space:nowrap;
}
Now I want to set leftnav to the same height as content (no faux columns if possible):
$('#leftnav_static').height($("#content_dynamic").height());
or
$('#leftnav_static').innerHeight($("#content_dynamic").innerHeight());
dont seem to work.
any suggestions as to why that is?
It does work. See this jsfiddle.
Are you running the code in a jQuery ready block? Also, if you want to maintain this height relationship through text size changes from browser 'zooms', you will need to respond to resize events. If at some point you make your content_dynamic div have a width of auto, you will also need to resize the sidebar div when the height of the content_dynamic div changes (again, by responding to a resize event).
jQuery only allows you to attach to a resize event at the window level, but there are plugins that ease translating that to a div level resize event.
HTML:
<div id="leftnav_static"></div>
<div id="content_dynamic">Lorem ipsum dolor sit amet,
consectetur adipiscing elit. Etiam iaculis ornare
sapien sit amet condimentum. Aliquam a diam vel eros
tristique fermentum vitae at turpis. Etiam fringilla,
enim nec viverra interdum, metus tortor vehicula mauris,
in luctus felis massa ut nulla. Proin et leo vel nunc ornare
pulvinar. Vestibulum quis lectus vel arcu tristique aliquet.
Fusce malesuada nisi non ante egestas semper.
</div>
CSS:
#leftnav_static {
padding:5px;
margin-top: 5px;
margin-left: 5px;
height: 1000px;
width: 195px;
font-size: 1.35em;
float:left;
background-color: blue;
}
#content_dynamic {
margin-top: 5px;
margin-left: 215px;
height: auto;
width: 700px;
padding: 5px;
background-color: red;
font-size: 1em;
line-height:1.6em;
//white-space:nowrap; //This makes the content div only one line,
//I commented this out to make the sizing clear.
}
JavaScript: (Assuming that the jQuery library is already loaded)
$(function() {
$('#leftnav_static').height($("#content_dynamic").height());
});
Note: The benefit of a faux columns or other pure CSS approaches is that you don't need to worry about zooming or resizes as much--and your site would work for people that have JavaScript turned off.
You have to understand that you are manipulating CSS attributes.
var myHeight = $("#content_dynamic").css("height");
$('#leftnav_static').css({"height": myHeight});
should do the trick.
Add display block to #leftnav_static
#leftnav_static
{
display: block;
}
...and this will work
$(document).ready(function() {
$('#leftnav_static').height( $('#content_dynamic').height() );
});
See my example; http://jsfiddle.net/D3gTy/

JavaScript animate resizing div

I'm trying to put a small animation on a page. I've got 2 divs side by side, the second of which has its content called via Ajax, so the div height varies without page refresh.
<div id="number1" style="float:left; padding-bottom:140px">Static content, 200px or so</div>
<div id="number2" style="float:left">AJAX content here</div>
<div style="clear:left"></div>
<img src="image" margin-top:-140px" />
This basically gives me a 2 column layout, and the image nests up underneath the left hand column no matter what the height. All good!
The thing I'm trying to do though is animate the transition of the image when the page height changes thanks to incoming Ajax content. At present the image jerks around up and down, I'd quite like to have it smoothly glide down the page.
Is this possible? I'm not really into my JavaScript, so I'm not sure how to do this. I'm using the jQuery library on the site, so could that be a way forward?
OK, I've just put together a very quick and dirty example.
Here's the HTML:
<body>
Add content
<div id="outerContainer">
<div id="left" class="col">
<p>Static content</p>
<img src="images/innovation.gif" width="111px" height="20px">
</div>
<div id="right" class="col">
<p>Ajax content</p>
</div>
</div>
</body>
The jQuery used is here
jQuery(function($){
var addedHTML = "<p class='added'>Lorem ipsum dolor sit amet, Nunc consectetur, magna quis auctor mattis, lorem neque lobortis massa, ac commodo massa sem sed nunc. Maecenas consequat consectetur dignissim. Aliquam placerat ullamcorper tristique. Sed cursus libero vel magna bibendum luctus. Nam eleifend volutpat neque, sed tincidunt odio blandit luctus. Morbi sit amet metus elit. Curabitur mollis rhoncus bibendum. Phasellus eget metus eget mi porttitor lacinia ac et augue. Nulla facilisi. Nam magna turpis, auctor vel vehicula vitae, tincidunt eget nisl. Duis posuere diam lacus.</p>";
$("#addContent").click(function(e){
$("#right").append(addedHTML);
var rightHeight = $("#right").height();
//Animate the left column to this height
$("#left").animate({
height: rightHeight
}, 1500);
});});
And CSS:
#outerContainer {
position: relative;
border: 1px solid red;
margin: 20px auto 0;
overflow: hidden;
width: 400px;}
.col {
width: 180px;
display: inline;
padding: 0 0 40px;}
#left {
float: left;
border: 1px solid cyan;
position: relative;}
#left img {
position: absolute;
bottom: 0;
left: 0;}
#right {
position: absolute;
top: 0;
left: 180px;
border: 1px solid green;}
#addContent {
text-align: center;
width: 100px;
margin: 20px auto 0;
display: block;}
I have added a button just to add some 'Ajax' content. When you do this it grabs the new height of the div and animates to that height. You could add some easing to the animation / change the speed to make it a little more polished.
I hope this helps.
Maybe you could use a container around the content divs (with overflow hidden) and resize that one according to the height of the contents, thus achieving what you're trying to do?
I agree with the answer above. You could apply the image as a background image to the container then animate the container. That way the background image will move down with the container (assuming you anchor it to the bottom that is!)

Categories

Resources