Truncar una cadena JavaScript directo

167

Me gustaría truncar una cadena cargada dinámicamente usando JavaScript directo. Es una url, por lo que no hay espacios, y obviamente no me importan los límites de las palabras, solo los caracteres.

Esto es lo que obtuve:

var pathname = document.referrer; //wont work if accessing file:// paths
document.getElementById("foo").innerHTML = "<a href='" + pathname +"'>" + pathname +"</a>"
Beto
fuente
1
¿Qué parte quieres truncar? Su ejemplo no transmite muy bien la intención.
Larsenal
1
oh ok, quiero truncar la URL en una cierta cantidad de caracteres, para que cuando establezca el innerHTML de "foo" no fluya fuera del div si es demasiado largo.
Bob
1
* pero- solo el innerHTML, no el nombre de ruta var en sí.
Bob
1
¿Por qué no simplemente usar css para ocultar el desbordamiento del div? desbordamiento: oculto
Samuel
2
@Samuel Debido a que sería una mala práctica de la interfaz de usuario, si el usuario espera ver la URL de la que acaba de llegar (document.referrer), y la estoy acortando, quiero indicarles que solo están viendo una parte de la url, y que no hubo un error. Aparte de eso, el método que propone reduciría los caracteres a la mitad, lo que se vería horrible.
Bob

Respuestas:

334

Use el método de subcadena :

var length = 3;
var myString = "ABCDEFG";
var myTruncatedString = myString.substring(0,length);
// The value of myTruncatedString is "ABC"

Entonces en tu caso:

var length = 3;  // set to the number of characters you want to keep
var pathname = document.referrer;
var trimmedPathname = pathname.substring(0, Math.min(length,pathname.length));

document.getElementById("foo").innerHTML =
     "<a href='" + pathname +"'>" + trimmedPathname + "</a>"
Larsenal
fuente
1
Si desea una subcadena que comience desde 0, entonces la función substr hará exactamente lo mismo con 3 caracteres menos;)
jackocnr
1
substr se comportan de manera extraña si la cadena es más corta que length- devuelve vacía
RozzA
Si su "cadena" es un número, también debe insertarla .toString().para convertirla en una cadena que substring()pueda manejar.
not2qubit
16

Sí, subcadena. No necesitas hacer un Math.min; La subcadena con un índice más largo que la longitud de la cadena termina en la longitud original.

¡Pero!

document.getElementById("foo").innerHTML = "<a href='" + pathname +"'>" + pathname +"</a>"

Esto es un error. ¿Qué pasa si document.referrer tiene un apóstrofe? O varios otros caracteres que tienen un significado especial en HTML. En el peor de los casos, el código del atacante en el referente podría inyectar JavaScript en su página, que es un agujero de seguridad XSS.

Si bien es posible escapar de los caracteres en pathname manualmente para evitar que esto suceda, es un poco molesto. Es mejor usar métodos DOM que jugar con cadenas innerHTML.

if (document.referrer) {
    var trimmed= document.referrer.substring(0, 64);
    var link= document.createElement('a');
    link.href= document.referrer;
    link.appendChild(document.createTextNode(trimmed));
    document.getElementById('foo').appendChild(link);
}
bobince
fuente
Estoy confundido, ¿cómo evita su solución el agujero de seguridad?
Bob
10
Cuando utiliza métodos DOM como 'createTextNode' y '.href = ...', está configurando directamente el valor real de texto sin formato subyacente. Cuando escribe HTML, ya sea en un archivo HTML o mediante innerHTML, debe obedecer las reglas de escape HTML. Entonces, mientras 'createTextNode (' A <B&C ')' está bien, con innerHTML tendría que decir 'innerHTML =' A & lt; B & amp; C ''.
bobince
11

Pensé en darle una mención a Sugar.js . Tiene un método truncado que es bastante inteligente.

De la documentación :

Trunca una cadena. A menos que la división sea verdadera, truncar no dividirá las palabras, y en su lugar descartará la palabra donde ocurrió el truncamiento.

Ejemplo:

'just sittin on the dock of the bay'.truncate(20)

Salida:

just sitting on...
Brian
fuente
9
Sugar is a Javascript library that extends native objects... La extensión de objetos nativos en JavaScript generalmente se considera una mala idea ™.
Jezen Thomas
@JezenThomas En algún momento, la mala idea es la más adecuada.
viditkothari
10

El siguiente código trunca una cadena y no dividirá las palabras, y en su lugar descarta la palabra donde ocurrió el truncamiento. Totalmente basado en la fuente Sugar.js.

function truncateOnWord(str, limit) {
        var trimmable = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u2028\u2029\u3000\uFEFF';
        var reg = new RegExp('(?=[' + trimmable + '])');
        var words = str.split(reg);
        var count = 0;
        return words.filter(function(word) {
            count += word.length;
            return count <= limit;
        }).join('');
    }
Beto Frega
fuente
2
Sería bueno agregar un "..." si el resultado! == str;
Leo Caseiro
9

Aquí hay un método que puede usar. Esta es la respuesta para uno de los desafíos de FreeCodeCamp:

function truncateString(str, num) {


if (str.length > num) {
return str.slice(0, num) + "...";}
 else {
 return str;}}
mandrei100
fuente
6

Versión ES6 actualizada

const truncateString = (string, maxLength = 50) => {
  if (!string) return null;
  if (string.length <= maxLength) return string;
  return `${string.substring(0, maxLength)}...`;
};

truncateString('what up', 4); // returns 'what...'
Sam Logan
fuente
esto siempre invoca la subcadena, incluso cuando puede no ser necesario ...
Clint Eastwood
@ClintEastwood buena retroalimentación, he actualizado la respuesta. Verificar la longitud de la cadena frente a la longitud máxima también significaba que podía eliminar el showDots const y ternary haciéndolo más ordenado. Salud.
Sam Logan
3

Sí, substringfunciona muy bien:

stringTruncate('Hello world', 5); //output "Hello..."
stringTruncate('Hello world', 20);//output "Hello world"

var stringTruncate = function(str, length){
  var dots = str.length > length ? '...' : '';
  return str.substring(0, length)+dots;
};
Arnaud Anato
fuente
0

en caso de que quieras truncar por palabra.

function limit(str, limit, end) {

      limit = (limit)? limit : 100;
      end = (end)? end : '...';
      str = str.split(' ');
      
      if (str.length > limit) {
        var cutTolimit = str.slice(0, limit);
        return cutTolimit.join(' ') + ' ' + end;
      }

      return str.join(' ');
    }

    var limit = limit('ILorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus metus magna, maximus a dictum et, hendrerit ac ligula. Vestibulum massa sapien, venenatis et massa vel, commodo elementum turpis. Nullam cursus, enim in semper luctus, odio turpis dictum lectus', 20);

    console.log(limit);

Fhulufhelo Mokhomi
fuente
0

var pa = document.getElementsByTagName('p')[0].innerHTML;
var rpa = document.getElementsByTagName('p')[0];
// console.log(pa.slice(0, 30));
var newPa = pa.slice(0, 29).concat('...');
rpa.textContent = newPa;
console.log(newPa)
<p>
some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here
</p>

sadeq alshaar
fuente