Convertir cadena a título de caso con JavaScript

549

¿Hay una manera simple de convertir una cadena a mayúscula? Por ejemplo, se john smithconvierte John Smith. No estoy buscando algo complicado como la solución de John Resig , solo (con suerte) algún tipo de una o dos líneas.

MDCore
fuente
Existen varios métodos, ¿tenemos algunas estadísticas de rendimiento?
theAnubhav
Por favor, consulte esta respuesta corta stackoverflow.com/a/57689168/10373693 Espero que sea la respuesta que está buscando.
Abhishek Kumar

Respuestas:

740

Prueba esto:

    function toTitleCase(str) {
        return str.replace(
            /\w\S*/g,
            function(txt) {
                return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
            }
        );
    }
<form>
Input:
<br /><textarea name="input" onchange="form.output.value=toTitleCase(this.value)"  onkeyup="form.output.value=toTitleCase(this.value)"></textarea>
<br />Output:
<br /><textarea name="output" readonly onclick="select(this)"></textarea>
</form>

Greg Dean
fuente
14
¿Podría alguien explicar, por qué \w\S*se usa, en lugar de \w+o \w*por ejemplo? No sé por qué querrías incluir algo más que espacios y, por lo tanto, cambiar Jim-Bob a Jim-bob .
martinczerwi
55
@martinCzerwi \w\S*también causó el Jim-bobproblema de nuestra parte. Usando \w*resuelto esto.
Bouke
14
/([^\W_]+[^\s-]*) */gresuelve el Jim-Bobproblema, es decir:jim-bob --> Jim-Bob
recursion.ninja
15
Si jim-bob --> Jim-Bobes tu deseo, probablemente deberías hacerlo /\b\w+/g. Ejemplo:str.replace(/\b\w+/g,function(s){return s.charAt(0).toUpperCase() + s.substr(1).toLowerCase();});
vol7ron
3
\w\S*se usa en lugar de \w+o \w*para que las palabras como Don'tno se modifiquen Don'T, pero como otros han señalado, \w\S*causan problemas con las palabras con guiones.
doubleDown
198

Una forma un poco más elegante, adaptando la función de Greg Dean:

String.prototype.toProperCase = function () {
    return this.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
};

Llámalo como:

"pascal".toProperCase();
Tuan
fuente
3
Tenga en cuenta que si tiene un usuario con un guión en su nombre e ingresan Jo-Ann Smith, este código los convertirá a Jo-ann Smith(tenga aen cuenta las minúsculas Ann).
dbau
18
@daniellmb ¿Por qué no debería alterar el prototipo de String? Creo que es una buena solución. Piense en las clases abiertas de ruby, es perfectamente válido agregar funciones a las clases existentes y es ampliamente aceptado.
marco-fiset
97
@ marco-fiset ¡Porque no juega bien con los demás! Suceden cosas malas cuando tiene 2 bibliotecas que intentan modificar objetos JavaScript nativos con cambios incompatibles. Imagine que jQuery y Google Maps siguieran este patrón de diseño, no podría tener ambos en la misma página.
daniellmb
55
@daniellmb Un excelente punto. Prefijar el nombre del método debería ayudar a evitar esto, ya que hará que el método no sea enumerable.
mikemaccana
6060
Siento que la declaración "no modificar objetos JavaScript nativos" es como "nunca use goto" o "eval is evil". Hay muchos casos en los que está bien. Si tiene control total sobre su proyecto y, por supuesto, no planea lanzarlo como biblioteca, no veo problemas con este método.
FoxMulder900
175

Intente aplicar el estilo CSS de transformación de texto a sus controles.

p.ej: (text-transform: capitalize);

Solo use un enfoque JS cuando sea absolutamente necesario.

Talha Ashfaque
fuente
36
-1. Este CSS funciona, pero no funciona como la mayoría de la gente espera porque si el texto comienza con mayúsculas, no hay ningún efecto. webmasterworld.com/forum83/7506.htm
whitneyland
2
@Akshar: una regla en minúsculas se reemplazaría por una regla de mayúsculas y minúsculas Como css no modifica el contenido de origen, el efecto es que la regla en minúsculas se elimina (dejando el contenido de origen en mayúsculas) y luego se aplicaría la regla de título (sin hacer nada).
dokkaebi
42
JS se usa fuera de los navegadores.
mikemaccana
44
La pregunta era: "¿Hay una forma simple de convertir una cadena en mayúsculas y minúsculas? . Esta respuesta no convierte una cadena. Este es un estilo aplicado encima de una cadena.
kingPuppy
Si desea que los datos en su base de datos estén limpios, de modo que puedan usarse limpiamente al pasar a servicios de terceros o exportarse a CSV, entonces CSS no es realmente una opción. CSS está destinado a cosméticos, y aunque ha crecido mucho a lo largo de los años y puede usarlo para resolver este tipo de problemas, la solución sigue siendo cosmética y no resuelve el problema subyacente.
Adam Reis
118

Aquí está mi versión, IMO también es fácil de entender y elegante.

var str = "foo bar baz"

console.log(

str.split(' ')
   .map(w => w[0].toUpperCase() + w.substr(1).toLowerCase())
   .join(' ')

)
// returns "Foo Bar Baz"

a8m
fuente
3
Alternativamente, puede minúscula la subcadena en el mapeo:str.split(' ').map(i => i[0].toUpperCase() + i.substring(1).toLowerCase()).join(' ')
Dave Land
55
No estoy de acuerdo con la llamada .toLowerCase(). Los nombres como "McDonald" o siglas como "ASAP" deben conservar sus caracteres en mayúscula. Si alguien realmente pasó una cadena como "heLLO", la aplicación no debería asumir que las letras mayúsculas son incorrectas.
Thomas Higginbotham
1
@ThomasHigginbotham ¿Qué tal esto? String.prototype.toTitleCase = function (blnForceLower) { var strReturn; (blnForceLower ? strReturn = this.toLowerCase() : strReturn = this); return strReturn .split(' ') .map(i => i[0].toUpperCase() + i.substr(1)) .join(' '); }
Sean Kendle
Sí, sería preferible proporcionar una opción para forzar minúsculas.
Thomas Higginbotham
1
Esto se romperá si stres un solo personaje.
Madbreaks
103

Aquí está mi función que se convierte en mayúsculas y minúsculas, pero también conserva los acrónimos definidos como mayúsculas y las palabras menores como minúsculas:

String.prototype.toTitleCase = function() {
  var i, j, str, lowers, uppers;
  str = this.replace(/([^\W_]+[^\s-]*) */g, function(txt) {
    return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
  });

  // Certain minor words should be left lowercase unless 
  // they are the first or last words in the string
  lowers = ['A', 'An', 'The', 'And', 'But', 'Or', 'For', 'Nor', 'As', 'At', 
  'By', 'For', 'From', 'In', 'Into', 'Near', 'Of', 'On', 'Onto', 'To', 'With'];
  for (i = 0, j = lowers.length; i < j; i++)
    str = str.replace(new RegExp('\\s' + lowers[i] + '\\s', 'g'), 
      function(txt) {
        return txt.toLowerCase();
      });

  // Certain words such as initialisms or acronyms should be left uppercase
  uppers = ['Id', 'Tv'];
  for (i = 0, j = uppers.length; i < j; i++)
    str = str.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'), 
      uppers[i].toUpperCase());

  return str;
}

Por ejemplo:

"TO LOGIN TO THIS SITE and watch tv, please enter a valid id:".toTitleCase();
// Returns: "To Login to This Site and Watch TV, Please Enter a Valid ID:"
Geoffrey Booth
fuente
1
Me gustó el suyo, también me encuentro con problemas al tratar con números romanos ... sólo parcheado con I, II, III, IV, etc.
Marcelo
2
Fijo. La expresión regular en la tercera línea se ha cambiado de /\w\S*/ga /([^\W_]+[^\s-]*) */gpor comentario de @ awashburn arriba para abordar esta cuestión.
Geoffrey Booth
2
¿Se puede obtener una ventaja al usar su patrón regex /\b\w+/g, que creo que es más rápido de comprender?
Michael - ¿Dónde está Clay Shirky?
2
No es que pueda ver, simplemente estaba tomando la sugerencia de otro comentarista para resolver el problema de palabras con guiones; pero su expresión regular parece funcionar igual de bien, y la simplicidad siempre es mejor. Para la posteridad y futuros visitantes a este post, acabo de cambiar la expresión regular en la tercera línea de la /([^\W_]+[^\s-]*) */gque /\b\w+/gpor el comentario de Michael @; comente si encuentra un caso en el que es necesaria la expresión regular más complicada.
Geoffrey Booth
1
Cambié la expresión regular de la tercera línea /\b[\w-\']+/gpara permitir palabras con guiones y apóstrofe en las palabras.
Shamasis Bhattacharya
47

Prefiero lo siguiente sobre las otras respuestas. Solo coincide con la primera letra de cada palabra y la capitaliza. Código más simple, más fácil de leer y menos bytes. Conserva las letras mayúsculas existentes para evitar distorsionar los acrónimos. Sin embargo, siempre puede llamar toLowerCase()primero a su cadena.

function title(str) {
  return str.replace(/(^|\s)\S/g, function(t) { return t.toUpperCase() });
}

Puede agregar esto a su prototipo de cadena que le permitirá lo 'my string'.toTitle()siguiente:

String.prototype.toTitle = function() {
  return this.replace(/(^|\s)\S/g, function(t) { return t.toUpperCase() });
}

Ejemplo:

Tom Kay
fuente
3
Es aún más agradable como lambdaconst titleCase = (str) => str.replace(/\b\S/g, t => t.toUpperCase());
0xcaff
No quería romper IE, pero sí, si la aplicación no es sensible al navegador heredado, podría ser más corta.
Tom Kay
Esta es solo una solución parcial: el operador preguntó cómo convertir una cadena a mayúscula. Esta respuesta no logra eso para entradas como NoT qUiITe.
Madbreaks
@Madbreaks La pregunta no estipula que las entradas de mayúsculas y minúsculas se deben convertir. Sin embargo, he actualizado la respuesta mencionando toLowerCase. Solo tenga en cuenta que rompería acrónimos. an HTML document: An HTML DocumentvsAn Html Document
Tom Kay
44
@Madbreaks Mientras que su ejemplo inicial fue ideado, usted hace un buen punto al afirmar que la salida no se modificaría si la entrada se capitalizara. Dicho esto, creo que la respuesta tal como está (con la edición que sugiere toLowerCase) es más flexible / útil que una que asume las intenciones de los desarrolladores. Este método también refleja la funcionalidad de métodos integrados similares de otros lenguajes como PHP ( ucwords) y Golang ( strings.Title). .NET ( TextInfo.ToTitleCase) funciona de manera interesante para mayúsculas y minúsculas, pero también dejaría las cadenas totalmente en mayúscula sin cambios.
Tom Kay
20

Sin usar regex solo como referencia:

String.prototype.toProperCase = function() {
  var words = this.split(' ');
  var results = [];
  for (var i = 0; i < words.length; i++) {
    var letter = words[i].charAt(0).toUpperCase();
    results.push(letter + words[i].slice(1));
  }
  return results.join(' ');
};

console.log(
  'john smith'.toProperCase()
)

Miguel
fuente
¡Gracias por la solución libre de expresiones regulares!
lucifer63
20

var result =
  'this is very interesting'.replace(/\b[a-z]/g, (x) => x.toUpperCase())

console.log(result) // This Is Very Interesting

simo
fuente
Solo una pregunta, la construcción () es para especificar una coincidencia en cualquiera de una secuencia de opciones: es decir, (a | b) coincide con a o b. ¿Qué hace la construcción (.)?
Michael Blackburn
Para cualquiera que tenga la misma pregunta, define un "blob" de reemplazo que se usa en la sección de reemplazo. Los blobs están numerados secuencialmente, el primero () se pone en $ 1, el segundo en $ 2. Este sitio me pareció útil: javascript.info/tutorial/regular-expressions-methods
Michael Blackburn
No puedo hacer que lo anterior funcione, pero estoy lejos de ser un asistente de expresiones regulares. Estoy usando 'string'.replace(/^(.)(.*)/,function(s,p1,p2){return p1.toUpperCase()+p2;}) nuevamente, esto solo funciona para poner en mayúscula la primera letra de una cadena, pero en caso de que sea lo que necesita, mi construcción funciona.
Michael Blackburn
1
Por alguna razón, FF35 parece ahogarse '$1'.toUpperCase(), parece que la mayúscula no se ha hecho cuando se asigna el valor. Se 'string'.replace(/^(.){1}/,function(match) { return match.toUpperCase(); })
solucionó
Hola a todos, la respuesta está arreglada! Estoy bastante seguro de que estaba funcionando cuando lo publiqué inicialmente. ¡De todos modos, gracias por la entrada!
simo
17

Podrías inmediatamente toLowerCasela cadena, y luego solo toUpperCasela primera letra de cada palabra. Se convierte en un 1 liner muy simple:

function titleCase(str) {
  return str.toLowerCase().replace(/\b(\w)/g, s => s.toUpperCase());
}

console.log(titleCase('iron man'));
console.log(titleCase('iNcrEdible hulK'));

KevBot
fuente
Me gusta esta solucion; Agradable y simple. Sin embargo, parece que un poco de CoffeeScript se deslizó en su respuesta ( s => s.toUpperCase()). Mi variante es hacer lo que has hecho, pero extender el objeto String (tan controvertido como es):Object.defineProperty(String.prototype, '_toProperCase', {value:function() {return this.toLowerCase().replace(/\b(\w)/g, function(t) {return t.toUpperCase()})}})
Waz
1
@Waz, ¡gracias por las ideas! Solo quería aclarar sobre =>, que es una función de flecha nativa (ES6), el enlace salta a los documentos de Mozillla en ellos, que también proporciona una tabla de soporte.
KevBot
16

En caso de que esté preocupado por esas palabras de relleno, siempre puede decirle a la función qué no capitalizar.

/**
 * @param String str The text to be converted to titleCase.
 * @param Array glue the words to leave in lowercase. 
 */
var titleCase = function(str, glue){
    glue = (glue) ? glue : ['of', 'for', 'and'];
    return str.replace(/(\w)(\w*)/g, function(_, i, r){
        var j = i.toUpperCase() + (r != null ? r : "");
        return (glue.indexOf(j.toLowerCase())<0)?j:j.toLowerCase();
    });
};

Espero que esto te ayude.

editar

Si desea manejar las palabras adhesivas iniciales, puede realizar un seguimiento de esta con una variable más:

var titleCase = function(str, glue){
    glue = !!glue ? glue : ['of', 'for', 'and', 'a'];
    var first = true;
    return str.replace(/(\w)(\w*)/g, function(_, i, r) {
        var j = i.toUpperCase() + (r != null ? r : '').toLowerCase();
        var result = ((glue.indexOf(j.toLowerCase()) < 0) || first) ? j : j.toLowerCase();
        first = false;
        return result;
    });
};
fncomp
fuente
2
Puede explotar una cadena en una matriz. Entonces podríamos tener preposiciones en portugués, español, italiano y francés:glue ='de|da|del|dos|do|das|des|la|della|delli'.split('|');
Junior Mayhé
Esto no asegurará la capitalización de la primera palabra; es decir se and another thingconvierte and Another Thing. Solo necesito una forma elegante de capitalizar siempre la primera palabra.
Brad Koch
@BradKoch - rellena con espacios para que estés usando 'y', 'de', etc. como la palabra de búsqueda, luego 'Y otro y otro' reemplazará a 'Y otro y otro'.
Yimin Rong
bueno, excepto que capitaliza también el texto después de 'y, como H'Dy o Number-One
luky el
En lugar de usar un operador ternario, podría usar una alternativa: glue = glue || ['de', 'para', 'y', 'a'];
tm2josep
14

Si la expresión regular utilizada en las soluciones anteriores te confunde, prueba este código:

function titleCase(str) {
  return str.split(' ').map(function(val){ 
    return val.charAt(0).toUpperCase() + val.substr(1).toLowerCase();
  }).join(' ');
}
immazharkhan
fuente
¡quiéralo! sin conversión a matrices.
neelmeg
1
uhhh ... split lo convierte en una matriz, simplemente no lo ves como obviamente porque mapsignifica que no tienes que usar la []notación
MalcolmOcean
2
Esto es lo mismo que la respuesta de a8m de 2 años antes.
Michael - ¿Dónde está Clay Shirky?
1
Descansos para entradas de un solo carácter.
Madbreaks
1
@AlexChaffee verifique el historial de revisiones. a8m no usó una función de flecha en la respuesta original.
Gracias
9

Hice esta función que puede manejar los apellidos (por lo que no es el caso del título) como "McDonald" o "MacDonald" o "O'Toole" o "D'Orazio". Sin embargo, no maneja nombres alemanes u holandeses con "van" o "von", que a menudo están en minúsculas ... Creo que "de" a menudo también está en minúsculas, como "Robert de Niro". Estos aún tendrían que ser abordados.

function toProperCase(s)
{
  return s.toLowerCase().replace( /\b((m)(a?c))?(\w)/g,
          function($1, $2, $3, $4, $5) { if($2){return $3.toUpperCase()+$4+$5.toUpperCase();} return $1.toUpperCase(); });
}
Lwangaman
fuente
1
+1 para conocimiento del nombre. Sin embargo, tampoco maneja "macy" correctamente.
brianary
Esta fue la única función que manejó correctamente la transformación de mayúsculas y minúsculas al caso correcto y que notó iniciales como "Islas Vírgenes de los Estados Unidos".
Rodrigo Polo
Puede macysolucionar el problema colocando una mirada negativa hacia adelante para que se \b((m)(a?c))?(\w)convierta\b((m)(a?c))?(\w)(?!\s)
Ste
8
var toMatch = "john w. smith";
var result = toMatch.replace(/(\w)(\w*)/g, function (_, i, r) {
      return i.toUpperCase() + (r != null ? r : "");
    }
)

Parece funcionar ... Probado con lo anterior, "el zorro marrón rápido / saltos / ^ sobre ^ el perro perezoso ..." y "C: / archivos de programa / algún vendedor / su segunda aplicación / a file1.txt ".

Si desea 2º en lugar de 2º, puede cambiar a /([a-z])(\w*)/g .

La primera forma se puede simplificar como:

function toTitleCase(toTransform) {
  return toTransform.replace(/\b([a-z])/g, function (_, initial) {
      return initial.toUpperCase();
  });
}
PhiLho
fuente
7

Prueba esto

String.prototype.toProperCase = function(){
    return this.toLowerCase().replace(/(^[a-z]| [a-z]|-[a-z])/g, 
        function($1){
            return $1.toUpperCase();
        }
    );
};

Ejemplo

var str = 'john smith';
str.toProperCase();
Maxi Baez
fuente
7

Si puede usar bibliotecas de terceros en su código, lodash tiene una función auxiliar para nosotros.

https://lodash.com/docs/4.17.3#startCase

_.startCase('foo bar');
// => 'Foo Bar'

_.startCase('--foo-bar--');
// => 'Foo Bar'
 
_.startCase('fooBar');
// => 'Foo Bar'
 
_.startCase('__FOO_BAR__');
// => 'FOO BAR'

waqas
fuente
7

Prueba esto de la manera más corta:

str.replace(/(^[a-z])|(\s+[a-z])/g, txt => txt.toUpperCase());
Vikram
fuente
7

ES 6

str.split(' ')
   .map(s => s.slice(0, 1).toUpperCase() + s.slice(1).toLowerCase())
   .join(' ')

más

str.split(' ').map(function (s) {
    return s.slice(0, 1).toUpperCase() + s.slice(1).toLowerCase();
}).join(' ')
jssridhar
fuente
Solo un aviso, probablemente debería serlo s.slice(0, 1).toUpperCase()si todavía quieres esa primera letra.
WindsofTime
@jssridhar también debe corregir el código en ES6.
caiosm1005
1
Se rompe si stres un solo personaje
Madbreaks
@jssridhar podría ser mejor para nosotros .charAt(0).toUpperCase().
roydukkey
2
duplicado de la respuesta de a8m
Gracias
6

La mayoría de estas respuestas parecen ignorar la posibilidad de usar el metacaracter de límite de palabra (\ b). Una versión más corta de la respuesta de Greg Dean utilizándola:

function toTitleCase(str)
{
    return str.replace(/\b\w/g, function (txt) { return txt.toUpperCase(); });
}

Funciona también para nombres con guiones como Jim-Bob.

lewax00
fuente
2
Es una solución parcial elegante pero no funciona con cadenas de acento o mayúsculas. Me sale "Sofía Vergara" => "Sofía Vergara" o "Sofía VERGARA" => "Sofía VERGARA". El segundo caso podría resolverse con la función apply .toLowerCase () antes de .replace (...). El primer caso necesita encontrar una expresión regular correcta.
Asereware
2
Hmm, eso parece un error en la implementación de expresiones regulares, creo que los caracteres acentuados deberían ser caracteres de palabras (sin embargo, estás en lo correcto, ya que no funciona para esos casos).
lewax00
\wsolo incluye los caracteres [A-Za-z0-9_], no todas las letras. Para eso necesitarías usar la categoría Unicode \p{L}. Necesitará el /umodificador (ver aquí ) y una solución diferente para \b, que solo funciona entre \Wy \w(ver aquí )
cmbuckley
6

Creo que lo más simple es usar CSS.

function format_str(str) {
    str = str.toLowerCase();
    return '<span style="text-transform: capitalize">'+ str +'</span>';
}
wondim
fuente
Actualicé el código y lo probé. Debería funcionar ahora.
wondim
Solo puede usar CSS en una fracción de entornos en los que se usa JS, por lo que esta solución no es viable. También los estilos en línea deben evitarse a toda costa.
Madbreaks
5

Úselo /\S+/gpara soportar diacríticos:

function toTitleCase(str) {
  return str.replace(/\S+/g, str => str.charAt(0).toUpperCase() + str.substr(1).toLowerCase());
}

console.log(toTitleCase("a city named örebro")); // A City Named Örebro

Sin embargo: " s unshine ( y ellow)" ⇒ " S unshine ( y ellow)"

le_m
fuente
5

Quería agregar mi propia respuesta, ya que necesitaba una toTitleCasefunción robusta que tenga en cuenta las reglas gramaticales enumeradas aquí (artículo recomendado por Google). Hay varias reglas que dependen de la longitud de la cadena de entrada. A continuación se muestran las pruebas de función + unidad.

La función también consolida espacios en blanco y elimina caracteres especiales (modifique la expresión regular para sus necesidades)

Función toTitleCase

const toTitleCase = (str) => {
  const articles = ['a', 'an', 'the'];
  const conjunctions = ['for', 'and', 'nor', 'but', 'or', 'yet', 'so'];
  const prepositions = [
    'with', 'at', 'from', 'into','upon', 'of', 'to', 'in', 'for',
    'on', 'by', 'like', 'over', 'plus', 'but', 'up', 'down', 'off', 'near'
  ];

  // The list of spacial characters can be tweaked here
  const replaceCharsWithSpace = (str) => str.replace(/[^0-9a-z&/\\]/gi, ' ').replace(/(\s\s+)/gi, ' ');
  const capitalizeFirstLetter = (str) => str.charAt(0).toUpperCase() + str.substr(1);
  const normalizeStr = (str) => str.toLowerCase().trim();
  const shouldCapitalize = (word, fullWordList, posWithinStr) => {
    if ((posWithinStr == 0) || (posWithinStr == fullWordList.length - 1)) {
      return true;
    }

    return !(articles.includes(word) || conjunctions.includes(word) || prepositions.includes(word));
  }

  str = replaceCharsWithSpace(str);
  str = normalizeStr(str);

  let words = str.split(' ');
  if (words.length <= 2) { // Strings less than 3 words long should always have first words capitalized
    words = words.map(w => capitalizeFirstLetter(w));
  }
  else {
    for (let i = 0; i < words.length; i++) {
      words[i] = (shouldCapitalize(words[i], words, i) ? capitalizeFirstLetter(words[i], words, i) : words[i]);
    }
  }

  return words.join(' ');
}

Pruebas unitarias para garantizar la corrección

import { expect } from 'chai';
import { toTitleCase } from '../../src/lib/stringHelper';

describe('toTitleCase', () => {
  it('Capitalizes first letter of each word irrespective of articles, conjunctions or prepositions if string is no greater than two words long', function(){
    expect(toTitleCase('the dog')).to.equal('The Dog'); // Capitalize articles when only two words long
    expect(toTitleCase('for all')).to.equal('For All'); // Capitalize conjunctions when only two words long
    expect(toTitleCase('with cats')).to.equal('With Cats'); // Capitalize prepositions when only two words long
  });

  it('Always capitalize first and last words in a string irrespective of articles, conjunctions or prepositions', function(){
    expect(toTitleCase('the beautiful dog')).to.equal('The Beautiful Dog');
    expect(toTitleCase('for all the deadly ninjas, be it so')).to.equal('For All the Deadly Ninjas Be It So');
    expect(toTitleCase('with cats and dogs we are near')).to.equal('With Cats and Dogs We Are Near');
  });

  it('Replace special characters with space', function(){
    expect(toTitleCase('[wolves & lions]: be careful')).to.equal('Wolves & Lions Be Careful');
    expect(toTitleCase('wolves & lions, be careful')).to.equal('Wolves & Lions Be Careful');
  });

  it('Trim whitespace at beginning and end', function(){
    expect(toTitleCase(' mario & Luigi superstar saga ')).to.equal('Mario & Luigi Superstar Saga');
  });

  it('articles, conjunctions and prepositions should not be capitalized in strings of 3+ words', function(){
    expect(toTitleCase('The wolf and the lion: a tale of two like animals')).to.equal('The Wolf and the Lion a Tale of Two like Animals');
    expect(toTitleCase('the  three Musketeers  And plus ')).to.equal('The Three Musketeers and Plus');
  });
});

Tenga en cuenta que estoy eliminando bastantes caracteres especiales de las cadenas proporcionadas. Tendrá que ajustar la expresión regular para abordar los requisitos de su proyecto.

momento bipolar
fuente
Prefiero esta solución ya que realmente se ocupa del caso del título. No es "Ido con el viento" es "Ido con el viento"
russellmania
5
"john f. kennedy".replace(/\b\S/g, t => t.toUpperCase())
Del mes próximo
fuente
1
Funciona para la muestra y o'henry, pero hace cosas raras con horse's mouth.
Michael - ¿Dónde está Clay Shirky?
"john f. kennEdy".toLowerCase().replace(/\b\S/g, t => t.toUpperCase())mejor 🤔
w3debugger
No quería editar la respuesta de @ Proximo: las \by \Sson clases de caracteres especiales que denotan "límite de palabra" y "carácter único, sin espacios en blanco. Por lo tanto, la expresión regular coincide con cada carácter que sigue un límite de palabra y capitaliza ese carácter aplicando la función de flecha dada.
Jens
4

Tomando la solución "lewax00", creé esta solución simple que obliga a "w" a partir del espacio o "w" que inicia la palabra, pero no puede eliminar los espacios intermedios adicionales.

"SOFÍA vergara".toLowerCase().replace(/\b(\s\w|^\w)/g, function (txt) { return txt.toUpperCase(); });

El resultado es "Sofía Vergara".

Asereware
fuente
4

Aquí está mi función que se ocupa de los caracteres acentuados (¡importante para el francés!) Y que puede activar / desactivar el manejo de excepciones menores. Espero que ayude.

String.prototype.titlecase = function(lang, withLowers = false) {
    var i, string, lowers, uppers;

    string = this.replace(/([^\s:\-'])([^\s:\-']*)/g, function(txt) {
        return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
    }).replace(/Mc(.)/g, function(match, next) {
        return 'Mc' + next.toUpperCase();
    });

    if (withLowers) {
        if (lang == 'EN') {
            lowers = ['A', 'An', 'The', 'At', 'By', 'For', 'In', 'Of', 'On', 'To', 'Up', 'And', 'As', 'But', 'Or', 'Nor', 'Not'];
        }
        else {
            lowers = ['Un', 'Une', 'Le', 'La', 'Les', 'Du', 'De', 'Des', 'À', 'Au', 'Aux', 'Par', 'Pour', 'Dans', 'Sur', 'Et', 'Comme', 'Mais', 'Ou', 'Où', 'Ne', 'Ni', 'Pas'];
        }
        for (i = 0; i < lowers.length; i++) {
            string = string.replace(new RegExp('\\s' + lowers[i] + '\\s', 'g'), function(txt) {
                return txt.toLowerCase();
            });
        }
    }

    uppers = ['Id', 'R&d'];
    for (i = 0; i < uppers.length; i++) {
        string = string.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'), uppers[i].toUpperCase());
    }

    return string;
}
Ouatataz
fuente
4

Hemos tenido una discusión aquí en la oficina y creemos que tratar de corregir automáticamente la forma en que las personas ingresan los nombres en la forma actual que usted quiere que esté hecho está plagado de posibles problemas.

Hemos presentado varios casos en los que los diferentes tipos de capitalización automática se desmoronan y estos son solo para nombres en inglés, cada idioma tiene sus propias complejidades.

Problemas con el uso de mayúsculas en la primera letra de cada nombre:

• Acrónimos como IBM no pueden ser ingresados, se convertirían en Ibm.

• El nombre McDonald se convertiría en Mcdonald, lo cual es incorrecto, lo mismo es MacDonald también.

• Los nombres de doble cañón como Marie-Tonks se convertirían en Marie-tonks.

• Nombres como O'Connor se convertirían en O'connor.

Para la mayoría de estos, podría escribir reglas personalizadas para tratarlo, sin embargo, esto todavía tiene problemas con Acronyms como antes y obtiene un nuevo problema:

• Si se agrega una regla para arreglar nombres con Mac, como MacDonald, los nombres de ruptura como Macy lo convertirían en MacY.

La única solución que hemos encontrado que nunca es incorrecta es poner en mayúscula cada letra, que es un método de fuerza bruta que parece que también usa el DBS.

Entonces, si desea automatizar el proceso, es imposible hacerlo sin un diccionario de cada nombre y palabra y cómo se debe capitular, si no tiene una regla que cubra todo, no lo use ya que solo molestará a sus usuarios y les pedirá a las personas que quieran ingresar sus nombres correctamente que vayan a otro lado.

jjr2000
fuente
4

Aquí hay otra solución usando CSS (y JavaScript, si el texto que desea transformar está en mayúsculas):

html

<span id='text'>JOHN SMITH</span>

js

var str = document.getElementById('text').innerHtml;
var return_text = str.toLowerCase();

css

#text{text-transform:capitalize;}
Henrie
fuente
3

Para aquellos de nosotros que tenemos miedo de las expresiones regulares (lol):

function titleCase(str)
{
    var words = str.split(" ");
    for ( var i = 0; i < words.length; i++ )
    {
        var j = words[i].charAt(0).toUpperCase();
        words[i] = j + words[i].substr(1);
    }
    return words.join(" ");
}

lashja
fuente
3

Mi solución de una línea:

String.prototype.capitalizeWords = function() {
    return this.split(" ").map(function(ele){ return ele[0].toUpperCase() + ele.slice(1).toLowerCase();}).join(" ");
};

Luego, puede llamar al método capitalizeWords()en cualquier cadena. Por ejemplo:

var myS = "this actually works!";
myS.capitalizeWords();

>>> This Actually Works

Mi otra solucion:

function capitalizeFirstLetter(word) {
    return word[0].toUpperCase() + word.slice(1).toLowerCase();
}
String.prototype.capitalizeAllWords = function() {
    var arr = this.split(" ");
    for(var i = 0; i < arr.length; i++) {
        arr[i] = capitalizeFirstLetter(arr[i]);
    }
    return arr.join(" ");
};

Luego, puede llamar al método capitalizeWords()en cualquier cadena. Por ejemplo:

var myStr = "this one works too!";
myStr.capitalizeWords();

>>> This One Works Too

Solución alternativa basada en la respuesta de Greg Dean:

function capitalizeFirstLetter(word) {
    return word[0].toUpperCase() + word.slice(1).toLowerCase();
}
String.prototype.capitalizeWords = function() {
    return this.replace(/\w\S*/g, capitalizeFirstLetter);
};

Luego, puede llamar al método capitalizeWords()en cualquier cadena. Por ejemplo:

var myString = "yes and no";
myString.capitalizeWords()

>>> Yes And No
Fouad Boukredine
fuente
3

Sorprendido de ver que nadie mencionó el uso del parámetro rest. Aquí hay un revestimiento simple que utiliza los parámetros de descanso de ES6.

let str="john smith"
str=str.split(" ").map(([firstChar,...rest])=>firstChar.toUpperCase()+rest.join("").toLowerCase()).join(" ")
console.log(str)

kapil pandey
fuente
2

Esto se basa en mi solución para el "Caso de título" de la hoguera de FreeCodeCamp , que requiere que primero convierta la cadena dada a minúsculas y luego convierta cada carácter con un espacio en mayúsculas.

Sin usar regex:

function titleCase(str) {
 return str.toLowerCase().split(' ').map(function(val) { return val.replace(val[0], val[0].toUpperCase()); }).join(' ');
}
Jamesy Dimmick May
fuente