Regex and PHP: adding ellipsis after X number of chars - php

Should be fairly simple for someone who knows regex. I am unfortunately not among those in the know.
How can one append ellipsis to anything over 27 chars in the below example, so that the fourth link listed will appear as http://iamanextremely.com/long/lin?
<?php
$input = <<<EOF
http://www.example.com/
http://example.com
www.example.com
http://iamanextremely.com/long/link/so/I/will/be/trimmed/down/a/bit/so/i/dont/mess/up/text/wrapping.html
EOF;
$output = preg_replace("/(http:\/\/|(www\.))(([^\s<]{4,27})[^(\s|,)<]*)/",
'http://$2$4', $input);

You could use preg_replace_callback to apply a callback to all matched urls. In the callback you can make stuff as fancy as you wish.
$output = preg_replace_callback('#(http://|www\\.)[^\\s<]+[^\\s<,.]#i',
'trimlong',$input);
function trimlong($match)
{
$url = $match[0];
$disp = $url;
if ( strlen($disp) > 24 ) $disp = substr($disp,0,24)."...";
return "$disp";
}
(ps. I just took your regexp to start with, I don't think matching a url should be that cumbersome.)

Unless you need to match a specific format, i.e. only the http:// links, a regex is overkill. Just use string functions and loop over your urls testing their length. If you want to get fancy, use explode() and array_walk()
if (strlen($url) > 27) {
echo substr($url, 0, 27) . '...';
}
else {
echo $url;
}

If this is for display in an HTML page, you might consider using CSS to style it with an ellipsis rather than manually truncating it.
You would use CSS something like this:
.cutshort {
overflow: hidden;
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
white-space: nowrap;
width:100%;
}
The text would then be truncated on screen and be given an ellipsis, even though the HTML code contained the full string.
This technique is not suited to all cases, but where it works it is an excellent alternative to hacking around with your content before sending it to the user.
One important note: The current version of Firefox browser doesn't display the ellipsis dots. It does still truncate correctly though, so it's not a disaster. All other browsers do show the dots, and hopefully a new version of firefox due soon will add it too.

Related

Laravel description formatting

I have a table of items which has description field. When listing out all items I would like to show exactly three rows of text followed by "..." if the text is longer.
I can do something like
<style>
.box {
overflow: hidden;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
-ms-text-overflow: ellipsis;
height: 60px;
}
</style>
...which works fine when there is a lot of text and the text is split in several lines. But if I have no new line chars in text I see only one line of text which is shortened.
Also if I have text formated like
Something
//blank-line
//blank-line
I am writing about something, because something is not nothing
I get my three lines...but it looks bad because first line is only "Something", and the two other are blank. So I figured I'd have to pre-format it before I send it from controller to view, and I tried first to approach that problem by removing empty lines and connecting whole text to one line, however this does nothing
$description = preg_replace( "/\r|\n/", "", $array[0]->description);
return $description
Which is maybe excepted since HTML formatted text enters the database
<p class="MsoNormal">Something<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Blah blah...something else...
Does anyone have an idea how to solve this?
Naturally, text will flow to the next line when it reaches the edge of its container element in the browser. I assume your container's width is controlled by some styling (whether fixed or responsive).
So in your case I'd ditch the ellipsis styling, see (from physically looking in the browser) how many characters it takes to produce the 3 lines you desire, and then do (I also assume you don't want to keep the HTML):
$description = strip_tags($array[0]->description);
if (strlen($description) > $maximumLength) {
$description = substr($description, 0, $maximumLength) . "...";
}
return $description
Of course there are other ways to do it on the client side with CSS or JavaScript, but what I see on most sites is they settle on a fixed length for their excerpt and just say any text longer than x characters must be truncated.

PHP print tabs from database

There's a simple way to include when there's a new line in the database (nl2br), but is there anything similar for tabs?
I've tried different solutions which works in the way of the look, but not when you're copying the code. I've tried a CSS style and made it like:
#br{
margin-right: 30px;
float: left;
}
But once I copy the code, there's no tab. In my database there's a TAB, but how do I print the tab?
You can use a bit of CSS to display tabs as tabs.
#br {
white-space: pre-wrap;
tab-size: 4;
}
pre-wrap is the best solution, I think, because it still allows the text to wrap normally when a line is full. pre is also possible, but then the text won't break at the end of a line.
tab-size is optional. By default it is set to 8 spaces, but you can change that by specifying a number of spaces in this property.
Note that I've copied your CSS selector, #br, but normally I would make a class for this, so you can easily apply this style to any number of elements in your page.
Also note, since pre-wrap also displays line breaks as actual breaks, you probably won't need to call nl2br on the server anymore.
You can write a function like nl2br(). Something like:
<?php
function tab2span($str){
if(strpos($str, "\t"){
$str = str_replace('\t','<span class="tabbed"> </span>',$str);
}
return $str;
}
?>
Then you can also adjust your CSS to style it better if you need.

PHP: How can you remove/replace a specific href attribute value

I am parsing some articles from a database with php and in the articles there are links which I would like to overwrite. Link always start with "http://cdn.example.com/" and the end parser is htmlspecialchars_decode($item->parse_articles(), ENT_NOQUOTES).
So before the articles are passed to the HTML DOM, I would like to replace all those href's that contain (?) example.com or maybe even if faster and possible to remove the <a> completely.
.
How is this possible? and if possible, is this considered faster option than passing it first to the DOM and manipulating it from there on the client-side?
You could try something like the following in PHP:
$newtext = preg_replace('/^("http:\/\/cdn\.example\.com\/){1}(.*)("){1}$/', '"#" class="disabled-link"', $oldtext);
$oldtext being your input article as a string.
$newtext being the text to echo on the page.
Broken down:
Find text starting with "http://cdn.example.com/
Then match anything
Stop at "
Replace with "#" class="disabled-link"
This should let you remove the link and also I added the class part so that you can add some CSS to style the links as text.
Example:
.disabled-link{
color:#000;
pointer-events: none;
cursor: default;
text-decoration: none;
}
All this combined will provide users with a link that is completely invisible without looking into the DOM or the source.

preg_replace capture group check

I'm trying to add a new bbcode to my phpfusion application. Im using with preg_replace. Here's the code:
$text = preg_replace(
"#\[gameimg( float:(left|center|right))?\]((http|ftp|https|ftps)://)(.*?)(\.(jpg|jpeg|gif|png|JPG|JPEG|GIF|PNG))\[/gameimg\]#sie",
"'<span style=\"display: block; max-width: 350px; margin: 0 0 5px 5px; $1\"><img src=\"'
. (strlen('$3') > 0 ? '$3' : BASEDIR.GAMESDIR)
. '$5$6\" alt=\"$5$6\" style=\"border:0px; max-width: 350px;\" /></span>'",
$text
);
If I supply an absolute url (for ex. [gameimg]http://localhost/dirname/file.jpg[/gameimg]) everything works fine, the picture shows up as expected. But if i omit the protokol and hostname using relative url ([gameimg]dirname/file.jpg[/gameimg]) i expect to append the basedir.gamedir constant to the given url but it doesn't work at all, it prints out the original bbcode without any replacement, not the image. What am i doing wrong?
A couple things here:
That is a giant preg_replace call. Maybe you could break this problem into smaller parts so that it is easier to understand/maintain?
You are using the "ignore case" modifier (i), yet you have things like (jpg|JPG). This is redundant.
Your question asks why [gameimg] tags without http://.. don't get matched. Well this is because of the required ((http|ftp|https|ftps)://) in your regex. You should make this section optional by adding a ?, like this:
((http|ftp|https|ftps)://)?

How to crop a text that it can fit into a block-type tag?

In my form I'm asking users to enter a text and then when they submit the form the text is sent to my database. When I query the entered text and I insert it into my html page it doesn't fit the container instead if a line has to many words it outputs the line in length. I'd like to know how can I do to crop the line if its size is way too much assuming the size of the container in which it reads. and oh ! to extend my request : what is the best way to treat user input and retrieve it in the exactly same format ??
If you need to "crop" text you can simply use substr.
echo substr($string,0,150);
This will cut your string up to 150 chars
#OP: after reading your question. Did you mean the css ?
overflow: hidden;
Anyway even if you div is set to display:block; it shouldn't show the horizontal scrollbar
Addendum
The problem with your link is that your div has the class listing with
white-space: pre;
you should change it
white-space: normal;
This is not a perfect solution, but you could do it like this:
$string = 'yourstring';
if (strlen($string) > TheMaxSizeOfYourString) {
$string = substr($string, 0, TheMaxSizeOfYourString-3);
$string .= '...';
}
This isn't perfect as the actual width of your string varies on the font you use.
Not sure what the problem is. If you specify the maxlength of a text input, you'll always have a set max length of your text. Otherwise you can do substr($yourstring, 0, your_set_length). However simply setting maxlength makes more sense.
you can shorten text to a specific length and 'round' it to the nearest full word by using something like i've got below, and even have it add some trailing "..." if needed...
function ShortenText($text,$chars) {
// Change to the number of characters you want to display
$orig = $text;
$text = $text." ";
$text = substr($text,0,$chars);
$text = substr($text,0,strrpos($text,' '));
// Add ... if the text actually needs shortening
if (strlen($orig) > $chars) {
$text = $text."...";
}
return $text;
}
If the only problem related to formating is the new lines then I would go like this:
User enters some text in text area.
I clean the text which is I remove all new lines, (also if you like remove tabs or multiple spaces).
Store the clean text in the database.
When the text will be retrieved then you output it in html page, if you place it inside a div then you don't have to worry because the text will break on its own.
If you need to show a preview of it you choose the substr as indicated above.
Conclusion I don't think that your request to get the text in excactly same format is a good idea (except that you have sth unusual-else in your mind). In contrast you want to clean the text that the user inserts. Hope I have understood correct what you are trying to do!

Categories