Add text item in two line - css

I have to make text wrap convert into into two line and ellipse will add if the text is more than two line.
Currently it's wrap in multiple line and view look so weird.
What i have done so far in css:
<div class="list card item-text-wrap" ng-click="getNewsDetail(new)">
<a class="item item-thumbnail-left" href="#">
<img src="http:{{new.thumbnail}}">
<h2>{{new.summary}}</h2>
<p style="padding: 0;">{{new.date | date:'EEE, MMM d yyyy'}} {{new.date |
date:'shortTime'}}</p>
</a>
</div>
This is work perfectly when text length is short but i want to make it consistent in two line and rest of part is append with dot(...).
Any help would highly appreciate.

So you cannot accomplish this using only CSS because you must use white-space: nowrap; to be able to use text-overflow: elipsis; and nowrap will not let the words wrap down multiple lines.
Here is a similar question with a Jquery solutions: CSS word ellipsis ('...') after one or two lines
Here is a page dedicated to different version of text-overflow and the different ways to handle it: http://dotdotdot.frebsite.nl/
You are going to need JQuery to do this, but luckily you gain a lot of control and may find a better visual design rather than the ellipsis.
Of course, apply any styles to the parent elements holding the text.
e.g.
<!-- HTML -->
<!-- Give class of "date" -->
<p style="padding: 0;" class="date>{{new.date | date:'EEE, MMM d yyyy'}} {{new.date | date:'shortTime'}}</p>
// Jquery
if ($('.date').height() > 50) {
var words = $('.date').html().split(/\s+/);
words.push('...');
do {
words.splice(-2, 1);
$('.date').html( words.join(' ') );
} while($('.date').height() > 50);
}

Related

Custom styling of text substrings in dynamic Angular templates

Is it possible to apply styles like bold / italic or both together in angular 6 by just having starting and ending point of the text while creating or after creating the components dynamically ? Right now I'm able to apply styles for the whole component but i wanted to apply style only for a particular text in the element and the length of the text will be from JSON.
Please find stackblitz implementation here.
Actual result should apply the style to text based on the offset and length
Yes, you should be able to achieve this with a conditional ngStyle statement, based on the length of the text string, or other criteria. E.g. apply bold and italic styling if your text string is longer than 20 characters:
<div [ngStyle]="textString.length > 20 && {'font-weight': 'bold', 'font-style': 'italic'}">{{textString}}</div>
Further information here and here is an example on Stackblitz.
Alternatively you can apply ngClass conditionally in the same way, and have your custom styling in your CSS file.
Method 1 - Slice Pipe
If you want to add styling based on character positions within some text, rather than the overall length of some text, and you want to do this purely in your HTML template, you could achieve this with the slice pipe.
I've put an example of how this could be applied below and on Stackblitz. The HTML markup is horrible, and line breaks must not be used in the code because these introduce unwanted spaces into the rendered text, but I believe it covers what you're asking for:
For a single highlight:
TS:
singleString = 'London Kings Cross Station';
highlightStart = 3;
highlightLength = 5;
HTML:
<ng-container>{{singleString | slice:0:highlightStart}}</ng-container>
<span class="styled_text">{{singleString | slice:highlightStart:highlightStart+highlightLength}}</span>
<ng-container>{{singleString | slice:highlightStart+highlightLength:singleString.length}}</ng-container>
For multiple highlights:
TS:
textStrings = ['London Kings Cross', 'Bristol Temple Meads'];
stylePositions = [[3,3],[15,3]]; // Start position and length of sections to be styled
HTML:
<ul>
<li *ngFor="let textString of textStrings">
<ng-container *ngFor="let stylePosition of stylePositions; index as i">
<ng-container *ngIf="i==0">{{textString | slice:0:stylePositions[0][0]}}</ng-container><ng-container *ngIf="i!=0">{{textString | slice:stylePositions[i-1][0]+stylePositions[i-1][1]:stylePositions[i][0]}}</ng-container><span class="styled_text">{{textString | slice:stylePositions[i][0]:stylePositions[i][0]+stylePositions[i][1]}}</span><ng-container *ngIf="i==stylePositions.length-1">{{textString | slice:stylePositions[i][0]+stylePositions[i][1]:textString.length}}</ng-container>
</ng-container>
</li>
</ul>
CSS:
.styled_text {
font-weight: bold;
font-style: italic;
color: #ff0000;
}
Method 2 - Inner HTML
A different approach would be to apply the same principle, but use a function to break your string into sections and then pass this to a div in your template using innerHTML - see below and this Stackblitz.
Please note that for this to work, you must also include a custom pipe to declare the HTML as safe for Angular to render with styling. This is also included in the Stackblitz, with more details here.
styleText(string){
let styledText= '';
for (let i = 0; i < this.stylePositions.length; i++) {
if(i==0){
styledText+=string.substring(0, this.stylePositions[i][0]);
} else {
styledText+=string.substring(this.stylePositions[i-1][0]+this.stylePositions[i-1][1],this.stylePositions[i][0]);
}
styledText+='<span style="color:#ff0000">'+string.substring(this.stylePositions[i][0],this.stylePositions[i][0]+this.stylePositions[i][1])+'</span>';
if(i==this.stylePositions.length-1){
styledText+=string.substring(this.stylePositions[i][0]+this.stylePositions[i][1],string.length);
}
}
return styledText;
}

Bootstrap popover text in divs overlaps without space

HTML:
<a href="#" data-container="body" data-id="54" data-toggle="popover" data-placement="left">
Popover on left
Javascript:
$('*[data-id]').mouseenter(function(event) {
var e=$(this);
var content = '<div class="row"><div class="col-xs-12"><div class="col-xs-8">
Element1Element1 Element1Element1Element1Element1Element1Element1 Element1Element1Element1Element1Element1Element1 Element1Element1Element1Element1</div><div class="col-xs-4">Element 2</div></div>';
e.popover({html:true,placement:'bottom', animation: false,
delay: { show: 1500, hide: 100 }, content: content}).popover('show')
});
It works fine but only if string in content contains spaces. If theres no spaces text overlaps with second div.
JS Fiddle:
http://jsfiddle.net/9Nt48/
How i can fix this?
This is the problem with continuous text, CSS will automatically place it in next line for you if it seems to overlap with the other divs but it doesn't have much of a choice when you don't give a space, this is because it doesn't know when to break, so you can specify it like:
.popover-content {
word-wrap:break-word;
}
Since your columns already have the width specified, if the text inside the div exceeds it, break it at that point.
DEMO
This is because your markup is wrong. A row in Bootstrap is what nests your columns. You have nested columns inside other columns, which is not correct.
<div class="row">
<div class="col-xs-12">
Element1Element1 Element1Element1Element1Element1Element1Element1 Element1Element1Element1Element1Element1Element1 Element1Element1Element1Element1
</div>
</div>
You also only need to use row and col-x-x classes is if you want to use columns in the tooltip. So you don't really have to use them if you are displaying simple text.
Finally, if you want multiple rows of text, just a p element to split the text.
Caveat: I'm not actually sure you can use the grid inside tooltips. So you might be better off using simple text without columns...

CSS counter fails to increment inside <ul>

This question concerns using the CSS counter feature in HTML5 inside a list (e.g. <ul>).
Given this in the .css file:
body {
counter-reset:figCounter;
counter-reset:figRefCounter;
counter-increment: figRefCounter;
}
.caption {
counter-increment: figCounter;
}
.figNumber:before {
content: "Figure";
}
.figNumber:after {
content: counter(figCounter);
}
The example below works correctly, that is, the divs generate "Figure 1" and "Figure 2" respectively:
<div class="caption">
<p><span class="figNumber"> </span>: First Caption</p>
</div>
<div class="caption">
<p><span class="figNumber"> </span>: Second Caption</p>
</div>
On the other hand, the counter does not increment -- both divs end up generating "Figure 1" -- if I put the first div inside a list, like so:
<ul>
<li>
<div class="caption">
<p><span class="figNumber"> </span>: First Caption</p>
</div>
</li>
</ul>
<div class="caption">
<p><span class="figNumber"> </span>: Second Caption</p>
</div>
How can I get the counter to increment inside a list, so that the second div generates "Figure 2" like it does without the list?
When using multiple Counter-resets, you should define them in one line:
body {
counter-reset:figCounter, figRefCounter;
counter-increment: figRefCounter;
}
jsFiddle
Note it is not neccesary to increase the counter at the body, it will be one by default for the first time
Your code as is working just fine.
See this fiddle: http://jsfiddle.net/SrewW
Moreover, if you make the list-style-type to none, then it looks seamless:
See this fiddle: http://jsfiddle.net/SrewW/1/
Result in both cases:
1 : First Caption
2 : Second Caption
And,
If you remove the trailing comma after .figNumber:before, then the result is like this:
Figure 1 : First Caption
Figure 2 : Second Caption
See this fiddle: http://jsfiddle.net/SrewW/2/
Update: (Moving the comments here for easy ref)
You do not actually need to put colons and spaces in your html markup. Also, you do not need counter-increment on caption. You can do that on your fignumber span itself.
Please understand the counters. This link will help you: https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Counters
You can have many counters. You can reset them anywhere, but safe would be to reset in body. But you increment those on an element where you want to show the counter.
Please see this fiddle for reference: http://jsfiddle.net/m6u6a/4/
For example:
body {
counter-reset: figCounter 10 figRefCounter 0;
}
.figNumber:before {
counter-increment: figCounter 2;
content: "Figure " counter(figCounter) ": ";
}
Here, figCounter is initialized to 10 and figRefCounter is initialized to 0 in body. However, on the span with class figNumber, the figCounter is incremented to 2 and displayed with supporting text in the:before` pseudo-class.
The result:
Figure 12: First Caption
Figure 14: Second Caption
Hope that makes it clear to you.

Using String.split inline to set CSS classes in the view

In my model I have a field type string called god_type.
Example:
Ice,Fire
Ranged,Cannon
Fire,Ranged
I'm going to be using Isotope to filter these models based on their god_type.
I need the output HTML to look like:
<div class="item Fire Ranged">
</div>
Here's what I've tried:
#gods-list.isotope-container
- for god in #gods
.item class='#{god.god_type.split(",").each { |c| c }}'
a href='#{god_path(god)}' class='god'
img src='#{god.thumbnail.url(:thumb)}'
h2= god.name
And the resulting HTML:
<div class="item ["Fire", "Ranged"]">
...
</div>
What am I doing wrong?
I'd suggest:
.item class='#{god.god_type.gsub(/\,/, " ")}'
You could also wrap it in a method, within a decorator, or directly in the model, or even an application helper. Here's a general idea:
class God
def god_type_classes
god_type.gsub(/\,/, " ").downcase
end
end
# your view
.item class='#{god.god_type_classes}'
Noticed I've used .downcase on the string. This is just to address standard CSS naming (should be item fire ranged).

Can CSS give me paragraph styling based on the previous heading class?

So I want to rig up some css rules for interview transcripts. The format I have in mind looks something like this:
<h2 class="interviewer">Alice: [00:00:00]</h2>
<p>Is it ok if I ask you a question now?</p>
<h2 class="interviewee">Bob: [00:00:03]</h2>
<p>Sure go ahead.</p>
I'd like the paragraph to be a particular colour based on the class of the preceeding heading. Is there a way to do this, as it would make the html markup significantly simpler.
You can use following-sibling combinator: +
h2.interviewer + p { /* style goes here */ }
Sure:
h2.interviewer + p {
color: red;
}
I'm not entirely sure how to do it with multiple paragraphs though. Perhaps if you encased the entire set of paragraphs in a div:
<h2 class="interviewer">Alice: [00:00:00]</h2>
<div>
<p>Is it ok if I ask you a question now?</p>
<p>More text here.</p>
</div>
<h2 class="interviewee"> class="interviewee">Bob: [00:00:03]</h2>
<div>
<p>Sure go ahead.</p>
</div>
You could then do this:
h2.interviewer + div {
color: red;
}
By the way, there are better HTML elements for displaying a conversation, like the newly introduced <dialog> tag
http://www.quackit.com/html_5/tags/html_dialog_tag.cfm
UPDATE:
The <dialog> element never made it into HTML5. It does not exist.

Resources