una length eliminar cortar caracteres cadena array javascript text reference refactoring

length - split javascript



Truncar una cadena muy bien para caber dentro de un ancho de pĂ­xel determinado (4)

A veces tienes cadenas que deben caber dentro de un cierto ancho de píxeles. Esta función intenta hacerlo de manera eficiente. Por favor, publique sus sugerencias o refactorizaciones a continuación :)

function fitStringToSize(str,len) { var shortStr = str; var f = document.createElement("span"); f.style.display = ''hidden''; f.style.padding = ''0px''; document.body.appendChild(f); // on first run, check if string fits into the length already. f.innerHTML = str; diff = f.offsetWidth - len; // if string is too long, shorten it by the approximate // difference in characters (to make for fewer iterations). while(diff > 0) { shortStr = substring(str,0,(str.length - Math.ceil(diff / 5))) + ''&hellip;''; f.innerHTML = shortStr; diff = f.offsetWidth - len; } while(f.lastChild) { f.removeChild(f.lastChild); } document.body.removeChild(f); // if the string was too long, put the original string // in the title element of the abbr, and append an ellipsis if(shortStr.length < str.length) { return ''<abbr title="'' + str + ''">'' + shortStr + ''</abbr>''; } // if the string was short enough in the first place, just return it. else { return str; } }

ACTUALIZACIÓN: la solución de @ some a continuación es mucho mejor; por favor usa eso.

Actualización 2: Código ahora publicado como esencia ; siéntete libre de bifurcar y enviar parches :)


A simple vista, me parece bien. Aquí hay algunas sugerencias menores:

  • Use una búsqueda binaria para encontrar el tamaño óptimo en lugar de uno lineal.

  • (opcionalmente) agregue un mouseover para que una información sobre herramientas proporcione la cadena completa.


¿Puedes escribir la misma función pero para ajustar el ancho y la altura de un div? Tengo un div con ancho y alto fijos, donde necesito poner texto de la base de datos. si el texto es demasiado grande para div, quiero cortarlo y ad ... al final? ¿Posible? Gracias

EDIT: encontré la solución JS para mi pregunta:

<p id="truncateMe">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer. Etiam venenatis. Sed ultricies, pede sit amet aliquet lobortis, nisi ante sagittis sapien, in rhoncus lectus mauris quis massa. Integer porttitor, mi sit amet viverra faucibus, urna libero viverra nibh, sed dictum nisi mi et diam. Nulla nunc eros, convallis sed, varius ac, commodo et, magna. Proin vel risus. Vestibulum eu urna. Maecenas lobortis, pede ac dictum pulvinar, nibh ante vestibulum tortor, eget fermentum urna ipsum ac neque. Nam urna nulla, mollis blandit, pretium id, tristique vitae, neque. Etiam id tellus. Sed pharetra enim non nisl.</p> <script type="text/javascript"> var len = 100; var p = document.getElementById(''truncateMe''); if (p) { var trunc = p.innerHTML; if (trunc.length > len) { /* Truncate the content of the P, then go back to the end of the previous word to ensure that we don''t truncate in the middle of a word */ trunc = trunc.substring(0, len); trunc = trunc.replace(//w+$/, ''''); /* Add an ellipses to the end and make it a link that expands the paragraph back to its original size */ trunc += ''<a href="#" '' + ''onclick="this.parentNode.innerHTML='' + ''unescape(/'''+escape(p.innerHTML)+''/');return false;">'' + ''...<//a>''; p.innerHTML = trunc; } } </script>

Para mi propósito, eliminé el enlace de ..., ya que tengo otra pestaña en mi página que contiene el texto completo.



Hay un par de problemas con tu código.

  • ¿Por qué / 5 ? El ancho de los caracteres depende de font-family y font-size .
  • Debe escapar de str en el título abreviado (o bien un "hará que el código no sea válido").
  • diff no se declara y termina en el alcance global
  • La substring no debería funcionar así. ¿Qué navegador estás usando?
  • hidden no es un valor válido de style.display . Para ocultarlo debe usar el valor none pero luego el navegador no calcula el offsetWidth . Utilice style.visibility="hidden" lugar.
  • La búsqueda de la longitud correcta es muy ineficiente.
  • Debe escapar &lt;/abbr&gt; "

Lo reescribí por usted y agregué className para que pueda usar un estilo para establecer la font-family font-size y font-size . El Sr. Fooz sugirió que use un mouseover para mostrar toda la cadena. Eso no es necesario ya que los navegadores modernos lo hacen por usted (probado con FF, IE, Opera y Chrome)

function fitStringToSize(str,len,className) { var result = str; // set the result to the whole string as default var span = document.createElement("span"); span.className=className; //Allow a classname to be set to get the right font-size. span.style.visibility = ''hidden''; span.style.padding = ''0px''; document.body.appendChild(span); // check if the string don''t fit span.innerHTML = result; if (span.offsetWidth > len) { var posStart = 0, posMid, posEnd = str.length; while (true) { // Calculate the middle position posMid = posStart + Math.ceil((posEnd - posStart) / 2); // Break the loop if this is the last round if (posMid==posEnd || posMid==posStart) break; span.innerHTML = str.substring(0,posMid) + ''&hellip;''; // Test if the width at the middle position is // too wide (set new end) or too narrow (set new start). if ( span.offsetWidth > len ) posEnd = posMid; else posStart=posMid; } //Escape var title = str.replace("/"","&#34;"); //Escape < and > var body = str.substring(0,posStart).replace("<","&lt;").replace(">","&gt;"); result = ''<abbr title="'' + title + ''">'' + body + ''&hellip;<//abbr>''; } document.body.removeChild(span); return result; }

Editar: Mientras probaba un poco más encontré un par de errores.

  • Math.ceil lugar del Math.floor previsto (culpo a esto de que el inglés no es mi lengua materna)

  • Si la cadena de entrada tuviera etiquetas html, el resultado no estaría definido (no es bueno truncar una etiqueta en el medio o dejar etiquetas abiertas)

Mejoras:

  • Escape de la cadena que se copia al tramo en todos los lugares. Todavía puede usar entidades html, pero no se permiten etiquetas ( < y > se mostrarán)
  • Reescribió el while -statement (es un poco más rápido, pero la razón principal fue deshacerse del error que causó las rondas adicionales y deshacerse de la declaración break)
  • Se fitStringToWidth el nombre de la función a fitStringToWidth

Versión 2:

function fitStringToWidth(str,width,className) { // str A string where html-entities are allowed but no tags. // width The maximum allowed width in pixels // className A CSS class name with the desired font-name and font-size. (optional) // ---- // _escTag is a helper to escape ''less than'' and ''greater than'' function _escTag(s){ return s.replace("<","&lt;").replace(">","&gt;");} //Create a span element that will be used to get the width var span = document.createElement("span"); //Allow a classname to be set to get the right font-size. if (className) span.className=className; span.style.display=''inline''; span.style.visibility = ''hidden''; span.style.padding = ''0px''; document.body.appendChild(span); var result = _escTag(str); // default to the whole string span.innerHTML = result; // Check if the string will fit in the allowed width. NOTE: if the width // can''t be determined (offsetWidth==0) the whole string will be returned. if (span.offsetWidth > width) { var posStart = 0, posMid, posEnd = str.length, posLength; // Calculate (posEnd - posStart) integer division by 2 and // assign it to posLength. Repeat until posLength is zero. while (posLength = (posEnd - posStart) >> 1) { posMid = posStart + posLength; //Get the string from the beginning up to posMid; span.innerHTML = _escTag(str.substring(0,posMid)) + ''&hellip;''; // Check if the current width is too wide (set new end) // or too narrow (set new start) if ( span.offsetWidth > width ) posEnd = posMid; else posStart=posMid; } result = ''<abbr title="'' + str.replace("/"","&quot;") + ''">'' + _escTag(str.substring(0,posStart)) + ''&hellip;<//abbr>''; } document.body.removeChild(span); return result; }