I am using one function
to shorten words, but what I really want is to create in the function
shorten string, without shortening words
function getSubString($string, $length=NULL){
//Si no se especifica la longitud por defecto es 50
if ($length == NULL)
$length = 15;
//Primero eliminamos las etiquetas html y luego cortamos el string
$stringDisplay = substr(strip_tags($string), 0, $length);
//Si el texto es mayor que la longitud se agrega puntos suspensivos
if (strlen(strip_tags($string)) > $length)
$stringDisplay .= '...';
return $stringDisplay;
}
//Veamos la ejecución de la misma.
$texto = "Este es un acortador de palabras, y yo deseo ser un acortador de cadenas no de palabras";
echo '<span>'.getSubString($product).'</span>';
The result that is printed is the following:
This is a hair shortener...
When inspecting the source code with the browser's developer tool it shows the following:
<span>Este es un acortador de palabras, y yo deseo ser un acortador de cadenas no de palabras</span>
Update
After having had so many very interesting answers but all unfortunately failed.
I came up with the idea using jQuery to delimit the word and then join it, for example we are going to limit the characters to be displayed from 10
any text, taking as an example the following text *"php 7 basic" the result will be the following:
php 7...
Inspecting the output with the browser's developer tool will display the following: (not what I thought) but more ideal
<h2 id="result">php 7...<h2 id="original" style="display: none;"> basic</h2></h2>
Why ideal?
Because this way it will not show an incomplete text in the future in the search engines, now if we remove the display:none;
it will show this:
php 7...basic
And it's perfect but there are two problems:
It is adding
id
to the tagh2
and since there are several elements to trim, this will not be valid for the correct validation of HTML, the HTML validation documentation says that there should not be more than one content with theid
same name, the solution is to migrate the a jQuery codeid
inclass
an article toclass
use.each()
its jQuery functions.The second error is that it only works with a single element that contains the
id="original"
if I add more than one in the same document it only shortens the first one the rest of the elements don't.
$(function() {
var maxlength = 10;
var dots = $('#original').text().length>maxlength?'...':'';
var hello = $('#original').text().length>maxlength?$('#original').text().substring(0,maxlength).replace(/\W\w+\s*(\W*)$/, '$1'):$('#original').text();
$('#original').before('<h2 id="result">'+hello+dots+'</h2>')
$('#original').text($('#original').text().substring(hello.length))
.css('display','none')
.appendTo('#result');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2 id="original">php 7 basic</h2>
<h2 id="original">Otro texto de otro contenedor</h2>
<h2 id="original">Otro texto de otro contenedor dos</h2>
In the javascript(jQuery) section I changed this
('#original')
to this$('.original')
but it didn't work, when making those changes the first content is repeated and the rest is ignored, it can be seen in the following link https://jsfiddle.net/mrfndefx/
A solution would be to use wordwrap :
Perhaps an adjustment such as compare if it is < (70-3) should be made (the three is for the three continuous points), but the wordwrap function cuts the sentence with spaces respecting the words... So you don't need the loop, which it can give you problems.
Documentation: http://php.net/manual/es/function.wordwrap.php
The idea you have is not going to be achieved just with
PHP
since you are manipulating it on the server side and you would have to work with several variables, one that shows you the trimmed and the other with the complete string and then you would have to manipulate it on the client side ... bone many steps to be able to do it withCSS
simply using:text-overflow: ellipsis;
Example:
Edit: (according to comments)
If you want to use the effect of
Udemy
you have to use the property-webkit-line-clamp
(caniuse.com
)If you're in a browser that supports that property you won't have a problem, try watching Udemy in FF and you'll see that the effect disappears... but we wouldn't be OSes if there wasn't a solution for it.
Better said a
Fallback
, for that we check if it supports-webkit-line-clamp
with@supports
(... and YES ...@supports
it is not supported in the (old) IE browsers), in case it does not support-webkit-line-clamp
, we put a gradient effect on the text which simulates the disappearance of the same... otherwise it shows the ellipsis(...)
In pure
CSS
:Another example would be to use a bit of
JS
( original code ), here we trim it indicating the desired length without trimming in the middle of the word and then add an ellipsis-like link to display the rest of the text:Hace tiempo implementé la siguiente función para recortar cadenas a una cierta longitud, respetando palabras completas, puedes incluir un trozo de html y también verifica que los puntos suspensivos no estén precedidos de otros signos de puntuación.
Si lo probaras con tu código y una longitud de 34 caracteres:
Obtendrías como resultado correctamente:
Espero que te sirva. Saludos.
Edición:
Si pretendes mostrar lo anterior pero poder acceder al contenido completo, puedes enviarlo de distintas maneras para poder obtenerlo, una de ellas es utilizar los atributos
data-*
a los que puedes acceder víajQuery
:Puedes acceder al contenido del
data-contenido
de esespan
utilizando:Edición 2:
Si lo que pretendes es mostrar recortado, pero que el texto esté completo, puedes hacer lo mismo que hice, pero al revés:
y luego con
jQuery
"recortar" la cadena, mostrando el recorte en lugar del contenido:Si es una cuestión de SEO, el contenido del marcado es la cadena completa, aunque posteriormente se manipule y se coloque la cadena recortada.
Edición 3:
Puede hacerse aún más simple y enviar únicamente la longitud de la cadena como data-recorte y que jQuery se encargue de recortar, del lado de PHP:
El tercer parámetro de string_cut es una cadena vacía para evitar que agregue los puntos suspensivos.
Saludos!
La verdad me ha parecido muy curiosas tu duda, creo entender lo siguiente:
Basado en estas premisas, descartamos PHP como solución, y teniendo en cuenta que no deseas incrustar etiquetas dinámicamente parece que la solución mas viable es a través de CSS, pero debido a que quieres controlar el numero de caracteres máximo a visualizar por si solo CSS es insuficiente. Así que te puedo sugerir la siguiente alternativa:
Tengo claro que es posible optimizar lo anterior pero trato de mostrarte la idea de manera sencilla. El uso de la pseudoclase
:after
no requiere de incrustar mas contenido al rededor de tus párrafos y al ser dinámico puedes manipular el texto que te muestra.Propuesta basada en el algoritmo de la pregunta
Espero que te sea de utilidad.
Te voy a poner dos métodos equivalentes, uno para PHP y el otro para JavaScript. La idea sería usar
strrpos
en PHP olastIndexOf
en JavaScript y el resultado final será el mismo en ambos casos, aunque quizás sería mejor hacerlo en PHP para evitar las consecuencias de hacerlo en JavaScript (un flashazo de texto antes de cortarse).PHP:
strrpos
La función
strrpos
devuelve la posición de la última ocurrencia del carácter especificado. A diferencia destrpos
(que devuelve la primera ocurrencia) una ventaja destrrpos
es que permite buscar desde el final de la cadena y no sólo desde el principio. Esto se hace poniendo un número negativo como offset.Aquí te dejo una pequeña función de cómo sería:
El script anterior dará como resultado:
Ahora podrías hacer un ejemplo más elaborado que en lugar de mandar la cadena recortada mande toda la cadena y se esconda una parte con CSS (aunque siga ahí por lo que los buscadores la indexarán).
Los estilos serían algo como esto (los puedes ver funcionando con más detalle en el ejemplo de JavaScript):
Y el PHP se vería así:
JavaScript:
lastIndexOf
Podrías usar JavaScript y la función
lastIndexOf
para encontrar la última posición que es un espacio en blanco antes de una posición dada. Con eso ya sabrás por dónde tienes que romper la cadena si hace falta.Una vez rota la cadena entre lo que se debe mostrar y no mostrar, puedes crear dos elementos:
::after
mostrará una elipsis (...)font-size: 0
quedará invisible.Algo como esto (en JavaScript puro):
Como los pseudo-elementos no son seleccionables pero los elementos con tamaño 0 sí lo son (aunque no estén visibles), entonces al seleccionar y copiar el texto de arriba te estarán copiando las cadenas originales.
O si lo quieres con jQuery, podrías hacerlo así:
You are defining
$descripcion
afterfor
and should be before:When you make the database query, try to have it defined before the
for
.I'm going to leave you with an example that I tried a short time ago, which shortens the string without cutting the word, which is what I understood you want in your example.
A possible example:
Result:
I leave this function, which shortens respecting the words with a simple regex:
Let's do some tests:
Let's cut
5
:Result:
Let's cut
15
:Result:
Source: PHP: TruncatingText
There are other truncation functions that may be of interest to you.
If strictly client-side text rendering is what you're after, you achieve this by creating a css class and applying it to the texts you want to be cut off if they're too long.
If this is too "rigid" you can use the alternative of the Clamp.js library where you can manipulate the HTML as follows
Hoy justo tuve que resolver este mismo problema y lo hice con este plugin de jQuery:
http://dotdotdot.frebsite.nl