Converter string em maiúsculas e minúsculas com JavaScript

549

Existe uma maneira simples de converter uma string em maiúsculas e minúsculas? Por exemplo, john smithtorna-se John Smith. Não estou procurando algo complicado como a solução de John Resig , apenas (espero) algum tipo de uma ou duas linhas.

MDCore
fonte
Existem vários métodos, temos algumas estatísticas de desempenho?
theAnubhav 2/16/16
Por favor, verifique esta resposta curta stackoverflow.com/a/57689168/10373693 Espero que seja a resposta que você está procurando.
Abhishek Kumar

Respostas:

740

Tente o seguinte:

    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
fonte
14
Alguém poderia explicar, por que \w\S*é usado, em vez de \w+ou \w*por exemplo? Não sei por que você gostaria de incluir algo além de espaços e, portanto, mudar Jim-Bob para Jim-bob .
martinczerwi
5
@martinCzerwi \w\S*também causou o Jim-bobproblema do nosso lado. Usando \w*resolveu isso.
Bouke
14
/([^\W_]+[^\s-]*) */gresolve o Jim-Bobproblema, ou seja:jim-bob --> Jim-Bob
recursion.ninja
15
Se esse jim-bob --> Jim-Bobé o seu desejo, você provavelmente deve fazer /\b\w+/g. Exemplo:str.replace(/\b\w+/g,function(s){return s.charAt(0).toUpperCase() + s.substr(1).toLowerCase();});
vol7ron 17/01
3
\w\S*é usado em vez de \w+ou \w*para que palavras como Don'tnão sejam modificadas Don'T, mas, como outros já apontaram, \w\S*causa problemas com as palavras hifenizadas.
DoubleDown #
198

Uma maneira um pouco mais elegante, adaptando a função de Greg Dean:

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

Chame assim:

"pascal".toProperCase();
Tuan
fonte
3
Lembre-se de que se você tiver um usuário com um traço no nome e ele inserir Jo-Ann Smith, esse código os converterá em Jo-ann Smith(observe a letra minúscula aem Ann).
precisa saber é
18
@daniellmb Por que ele não deve alterar o protótipo String? Eu acho que é uma boa solução. Pense nas classes abertas do ruby, é perfeitamente válido adicionar funções às classes existentes e é amplamente aceito.
marco-fiset 21/09/12
97
@ marco-fiset Porque não joga bem com os outros! As coisas ruins acontecem quando você tem duas bibliotecas que estão tentando modificar objetos JavaScript nativos com alterações incompatíveis. Imagine se o jQuery e o Google Maps seguissem esse padrão de design, você não poderia ter os dois na mesma página.
Daniellmb 21/09/12
5
@daniellmb Um ponto excelente. Prefixar o nome do método deve ajudar a evitar isso, pois tornará o método não enumerável.
Mikemaccana
60
Eu sinto que a declaração "não modifique objetos JavaScript nativos" é como "nunca use goto" ou "eval is evil". Existem muitos casos em que está tudo bem. Se você tem controle total sobre o seu projeto e, claro, não planeja liberá-lo como uma biblioteca, não vejo problemas com esse método.
FoxMulder900
175

Tente aplicar o estilo CSS de transformação de texto aos seus controles.

por exemplo: (text-transform: capitalize);

Use apenas uma abordagem JS quando for absolutamente necessário.

Talha Ashfaque
fonte
36
-1. Esse css funciona, mas não funciona como a maioria das pessoas espera, porque se o texto começar como maiúsculas, não haverá efeito. webmasterworld.com/forum83/7506.htm
whitneyland
2
@ Akshar: Uma regra em minúscula seria substituída por uma regra de maiúsculas. Como o css não modifica o conteúdo de origem, o efeito é que a regra em minúsculas é removida (deixando o conteúdo de fonte em maiúsculas) e, em seguida, a regra de titlecase seria aplicada (sem fazer nada).
Dokkaebi
42
JS é usado fora dos navegadores.
Mikemaccana
4
A pergunta era: "Existe uma maneira simples de converter uma string em maiúsculas e minúsculas?" . Esta resposta não converte uma string. Este é um estilo aplicado sobre uma string.
kingPuppy
Se você deseja que os dados do seu banco de dados sejam limpos, para que possam ser usados ​​de maneira limpa ao passar para serviços de terceiros ou exportados para CSV, o CSS não é realmente uma opção. O CSS é destinado a cosméticos e, embora tenha crescido muito ao longo dos anos e você possa usá-lo para resolver esse tipo de problema, a solução permanece cosmética e não resolve o problema subjacente.
Adam Reis
118

Aqui está minha versão, IMO também é fácil de entender e 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
fonte
3
Como alternativa, você pode minúscula a substring no mapeamento:str.split(' ').map(i => i[0].toUpperCase() + i.substring(1).toLowerCase()).join(' ')
Dave Land
5
Eu discordo de ligar .toLowerCase(). Nomes como "McDonald" ou acrônimos como "O MAIS CEDO POSSÍVEL" devem manter seus caracteres maiúsculos. Se alguém realmente passou uma string como "heLLO", o aplicativo não deve assumir que as letras maiúsculas estão incorretas.
Thomas Higginbotham
1
@ThomasHigginbotham Que tal isso? 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
Sim, é preferível fornecer uma opção para forçar letras minúsculas.
Thomas Higginbotham
1
Isso será interrompido se strhouver um único caractere.
precisa saber é o seguinte
103

Aqui está minha função que converte para maiúsculas, mas também preserva acrônimos definidos como maiúsculas e palavras 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 exemplo:

"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
fonte
1
Eu gostei sua, eu também encontrar problemas ao lidar com números romanos ... apenas remendado com I, II, III, IV, etc.
Marcelo
2
Fixo. O regex na terceira linha foi alterado de /\w\S*/gpara /([^\W_]+[^\s-]*) */go comentário de @ @ awashburn acima para resolver isso.
Geoffrey Booth
2
Existe uma vantagem a ser obtida com o uso do seu padrão regex /\b\w+/g, que considero mais rapidamente compreensível?
Michael - Onde está Clay Shirky
2
Não que eu possa ver, eu estava simplesmente aceitando a sugestão de outro comentarista para resolver o problema das palavras hifenizadas; mas sua regex parece ter o mesmo desempenho e a simplicidade é sempre melhor. Para a posteridade e futuros visitantes deste post, mudei a regex na terceira linha de /([^\W_]+[^\s-]*) */gpara /\b\w+/gpor @ comentário de Michael; comente se você encontrar um caso em que a regex mais complicada seja necessária.
Geoffrey Booth
1
Alterei o regex da terceira linha para /\b[\w-\']+/gpara permitir palavras hifenizadas e apóstrofo em palavras.
Shamasis Bhattacharya
47

Eu prefiro o seguinte sobre as outras respostas. Corresponde apenas à primeira letra de cada palavra e a coloca em maiúscula. Código mais simples, mais fácil de ler e menos bytes. Ele preserva as letras maiúsculas existentes para evitar acrônimos distorcidos. No entanto, você sempre pode chamar toLowerCase()sua string primeiro.

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

Você pode adicionar isso ao seu protótipo de string, o que permitirá o 'my string'.toTitle()seguinte:

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

Exemplo:

Tom Kay
fonte
3
É ainda melhor como um lambdaconst titleCase = (str) => str.replace(/\b\S/g, t => t.toUpperCase());
0xcaff
Eu não queria interromper o IE, mas sim, se o aplicativo não for sensível ao navegador herdado, poderá ser mais curto.
Tom Kay
Esta é apenas uma solução parcial - solicitou como converter uma string em maiúsculas e minúsculas. Esta resposta não consegue isso para entradas como NoT qUiITe.
precisa saber é o seguinte
@ Madbreaks A questão não estipulou que as entradas de maiúsculas e minúsculas deveriam ser convertidas. No entanto, atualizei a resposta mencionando toLowerCase. Esteja ciente de que isso quebraria siglas. an HTML document: An HTML DocumentvsAn Html Document
Tom Kay
4
@ Madbreaks Embora seu exemplo inicial tenha sido inventado, você faz um bom argumento ao afirmar que a saída seria inalterada se a entrada fosse maiúscula. Dito isto, sinto que a resposta como está (com a edição sugerindo toLowerCase) é mais flexível / útil do que aquela que assume as intenções dos desenvolvedores. Esse método também reflete a funcionalidade de métodos ucwordsinternos semelhantes de outras linguagens, como PHP ( ) e Golang ( strings.Title). O .NET ( TextInfo.ToTitleCase) funciona de maneira interessante para maiúsculas e minúsculas, mas também deixaria inalteradas as strings totalmente capitalizadas.
21418 Tom
20

Sem usar regex apenas para referência:

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()
)

Mike
fonte
Obrigado pela solução gratuita regex!
lucifer63
20

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

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

simo
fonte
Apenas uma pergunta, a construção () é para especificar uma correspondência em qualquer sequência de opções: ou seja, (a | b) corresponde a ou b. O que a construção (.) Faz?
Michael Blackburn
Para quem teve a mesma pergunta, define um "blob" de substituição usado na seção de substituição. Os blobs são numerados sequencialmente, o primeiro () é colocado em $ 1, o segundo em $ 2. Eu encontrei este site útil: javascript.info/tutorial/regular-expressions-methods
Michael Blackburn
Não consigo fazer o trabalho acima, mas estou longe de ser um assistente de regex. Estou usando 'string'.replace(/^(.)(.*)/,function(s,p1,p2){return p1.toUpperCase()+p2;}) Novamente, isso só funciona para colocar em maiúscula a primeira letra de uma string, mas, caso seja disso que você precisa, minhas obras de construção.
Michael Blackburn
1
Por alguma razão, o FF35 parece engasgar '$1'.toUpperCase(), parece que as letras maiúsculas não foram concluídas no momento em que o valor é atribuído. 'string'.replace(/^(.){1}/,function(match) { return match.toUpperCase(); })
Resolvido
Oi pessoal, a resposta foi corrigida! Tenho certeza de que estava funcionando no momento em que o publiquei. De qualquer forma obrigado pela contribuição!
simo
17

Você poderia imediatamente toLowerCasea string e, em seguida, apenas toUpperCasea primeira letra de cada palavra. Torna-se um liner 1 muito simples:

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

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

KevBot
fonte
Eu gosto desta solução; agradável e simples. Parece que um pouco de CoffeeScript entrou na sua resposta ( s => s.toUpperCase()). Meu variante é fazer o que você fez, mas estendendo o objeto String (tão controverso como que é):Object.defineProperty(String.prototype, '_toProperCase', {value:function() {return this.toLowerCase().replace(/\b(\w)/g, function(t) {return t.toUpperCase()})}})
Waz
1
@ Waz, obrigado pelas idéias! Só queria esclarecer sobre =>, que é uma função de seta nativa (ES6), o link pula para o Mozillla Docs neles, que também fornece uma tabela de suporte.
KevBot #
16

No caso de você estar preocupado com essas palavras de preenchimento, você sempre pode dizer à função o que não deve 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 isso ajude você.

editar

Se você deseja manipular as principais palavras de cola, acompanhe essa variável com mais uma:

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
fonte
2
Você pode explodir uma string em uma matriz. Para que pudéssemos ter preposições em português, espanhol, italiano e francês:glue ='de|da|del|dos|do|das|des|la|della|delli'.split('|');
Junior Mayhé
Isso não garantirá a capitalização da primeira palavra; ou seja, and another thingse torna and Another Thing. Só precisa de uma maneira elegante de sempre capitalizar a primeira palavra.
Brad Koch
@BradKoch - preencha com espaços para que você esteja usando 'e', ​​'de' etc. como palavra de pesquisa, 'E outro e outro' será substituído por 'E outro e outro'.
Yimin Rong
bom, exceto que capitaliza também texto depois de 'e - como H'Dy ou Number-One
luky
Em vez de usar um operador ternário, você pode simplesmente usar um fallback: cola = cola || ['de', 'para', 'e', ​​'a'];
precisa saber é o seguinte
14

Se o regex usado nas soluções acima estiver deixando você confuso, tente este código:

function titleCase(str) {
  return str.split(' ').map(function(val){ 
    return val.charAt(0).toUpperCase() + val.substr(1).toLowerCase();
  }).join(' ');
}
immazharkhan
fonte
adoro! nenhuma conversão para matrizes.
Neelmeg #
1
uhhh ... split não convertê-lo para um array, você simplesmente não vê-lo como, obviamente, porque mapsignifica que você não tem que usar []a notação
MalcolmOcean
2
É o mesmo que a resposta da a8m de 2 anos antes.
Michael - Onde está Clay Shirky
1
Quebras para entradas de caractere único.
precisa saber é o seguinte
1
@AlexChaffee verifica o histórico de revisões. o a8m não usou uma função de seta na resposta original.
Obrigado
9

Eu criei essa função que pode lidar com sobrenomes (por isso não é maiúscula), como "McDonald" ou "MacDonald" ou "O'Toole" ou "D'Orazio". No entanto, ele não lida com nomes alemães ou holandeses com "van" ou "von", que geralmente estão em minúsculas ... Eu acredito que "de" também é minúsculo, como "Robert de Niro". Estes ainda teriam 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
fonte
1
+1 para reconhecimento de nome. Também não lida com "macy" corretamente.
brianary
Essa foi a única função que manipulou corretamente a transformação de maiúsculas e minúsculas para a correta e notou iniciais como "Ilhas Virgens Americanas".
Rodrigo Polo
Você pode contornar o macyproblema, colocando um lookahead negativo em lá assim que \b((m)(a?c))?(\w)se torna\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 ... Testado com o exposto acima, "a raposa marrom-rápida? / Pula / ^ sobre ^ o cão preguiçoso!" E "C: / arquivos de programas / algum fornecedor / sua segunda aplicação / a file1.txt ".

Se você deseja 2º em vez de 2º, pode mudar para /([a-z])(\w*)/g .

A primeira forma pode ser simplificada como:

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

Tente isto

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

Exemplo

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

Se você pode usar bibliotecas de terceiros em seu código, o lodash possui uma função auxiliar para nós.

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
fonte
7

Tente da maneira mais curta:

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

ES 6

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

outro

str.split(' ').map(function (s) {
    return s.slice(0, 1).toUpperCase() + s.slice(1).toLowerCase();
}).join(' ')
jssridhar
fonte
Apenas um aviso, provavelmente deveria ser s.slice(0, 1).toUpperCase()se você ainda quiser a primeira letra.
WindsofTime
@jssridhar você também deve corrigir o código no ES6.
caiosm1005
1
Breaks, se stré um único caractere
Madbreaks
@jssridhar pode ser melhor para nós .charAt(0).toUpperCase().
roydukkey
2
duplicada da resposta de a8m
Obrigado
6

A maioria dessas respostas parece ignorar a possibilidade de usar a palavra metacaractere de limite (\ b). Uma versão mais curta da resposta de Greg Dean, utilizando-a:

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

Também funciona para nomes hifenizados como Jim-Bob.

lewax00
fonte
2
É uma solução parcial elegante, mas não funciona com acentos ou maiúsculas. Eu recebo "Sofía Vergara" => "SofíA Vergara" ou "Sofía VERGARA" => "SofíA VERGARA". O segundo caso pode ser resolvido com a função apply .toLowerCase () antes de .replace (...). O primeiro caso precisa encontrar uma expressão regular correta.
Asereware
2
Hmm, isso parece um bug na implementação do regex, eu acho que caracteres acentuados devem ser caracteres de palavras (você está correto, porém, pois não funciona nesses casos).
amigos estão dizendo sobre lewax00
\winclui apenas os caracteres [A-Za-z0-9_], nem todas as letras. Para isso, você precisará usar a categoria Unicode \p{L}. Você precisa ter o /umodificador (veja aqui ) e uma solução diferente para \b, que só funciona entre \We \w(ver aqui )
cmbuckley
6

Eu acho que o mais simples é usar css.

function format_str(str) {
    str = str.toLowerCase();
    return '<span style="text-transform: capitalize">'+ str +'</span>';
}
maravilhoso
fonte
Atualizei o código e testei-o. Deve funcionar agora.
wondim
Você só pode usar CSS em uma fração dos ambientes em que o JS é usado, portanto, esta solução não é viável. Também os estilos em linha devem ser evitados a todo custo.
precisa saber é o seguinte
5

Use /\S+/gpara suportar 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

No entanto: " s unshine ( y ellow)" ⇒ " S unshine ( y ellow)"

le_m
fonte
5

Queria adicionar minha própria resposta, pois precisava de uma toTitleCasefunção robusta que levasse em conta as regras gramaticais listadas aqui (artigo recomendado pelo Google). Existem várias regras que dependem do comprimento da sequência de entrada. Abaixo está a função + testes de unidade.

A função também consolida o espaço em branco e remove caracteres especiais (modifique a expressão regular para suas necessidades)

Função 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(' ');
}

Testes de unidade para garantir a correção

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');
  });
});

Observe que estou removendo um pouco de caracteres especiais das strings fornecidas. Você precisará ajustar a regex para atender aos requisitos do seu projeto.

dipole_moment
fonte
Eu prefiro esta solução, uma vez que realmente cuida do título. Não é "Gone With The Wind" É "Gone with the Wind"
russellmania
5
"john f. kennedy".replace(/\b\S/g, t => t.toUpperCase())
Proximo
fonte
1
Funciona para a amostra e o'henry, mas faz coisas estranhas horse's mouth.
Michael - Onde está Clay Shirky,
"john f. kennEdy".toLowerCase().replace(/\b\S/g, t => t.toUpperCase())better 🤔
w3debugger
Não queria editar a resposta do @ Proximo: as classes de caractere especial são \be denotam "limite de palavras" e "caractere único, sem espaço em branco. Portanto, a expressão regular corresponde a cada caractere após um limite de palavra e coloca em maiúscula esse caractere aplicando a função de seta fornecida. \S
Jens
4

Tomando a solução "lewax00", criei esta solução simples que força "w" começando com espaço ou "w" que inicia o word, mas não é capaz de remover os espaços intermediários extras.

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

O resultado é "Sofía Vergara".

Asereware
fonte
4

Aqui está minha função que cuida de caracteres acentuados (importantes para o francês!) E que pode ativar / desativar o tratamento de exceções menores. Espero que ajude.

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
fonte
4

Temos discutido aqui no escritório e achamos que tentar corrigir automaticamente a maneira como as pessoas inserem nomes da maneira atual que você quer que seja está repleto de possíveis problemas.

Chegamos a vários casos em que diferentes tipos de capitalização automática se desintegram e estes são apenas para nomes em inglês, cada idioma tem suas próprias complexidades.

Problemas ao colocar em maiúscula a primeira letra de cada nome:

• Acrônimos como IBM não podem ser inseridos, se tornariam Ibm.

• O nome McDonald se transformaria em Mcdonald, o que está incorreto, a mesma coisa também é MacDonald.

• Nomes de cano duplo, como Marie-Tonks, seriam transformados em Marie-Tonks.

• Nomes como O'Connor se tornariam O'connor.

Para a maioria deles, você pode escrever regras personalizadas para lidar com isso, no entanto, isso ainda tem problemas com acrônimos como antes e você recebe um novo problema:

• A adição de uma regra para corrigir nomes no Mac, como MacDonald, quebraria nomes como Macy, transformando-o em MacY.

A única solução que encontramos que nunca é incorreta é colocar em maiúscula todas as letras que são um método de força bruta que o DBS parece também usar.

Portanto, se você deseja automatizar o processo, é tão impossível quanto fazer sem um dicionário de cada nome e palavra e como deve ser capitulado. Se você não tem uma regra que cubra tudo, não o use como apenas irritará seus usuários e solicitará que as pessoas que desejam inserir seus nomes corretamente possam ir para outro lugar.

jjr2000
fonte
4

aqui está outra solução usando css (e javascript, se o texto que você deseja transformar estiver em maiú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
fonte
3

Para aqueles de nós que têm medo de expressões regulares (risos):

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
fonte
3

Minha solução de uma linha:

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

Em seguida, você pode chamar o método capitalizeWords()em qualquer sequência. Por exemplo:

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

>>> This Actually Works

Minha outra solução:

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(" ");
};

Em seguida, você pode chamar o método capitalizeWords()em qualquer sequência. Por exemplo:

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

>>> This One Works Too

Solução alternativa baseada na resposta 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);
};

Em seguida, você pode chamar o método capitalizeWords()em qualquer sequência. Por exemplo:

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

>>> Yes And No
Fouad Boukredine
fonte
3

Surpreso ao ver que ninguém mencionou o uso do parâmetro rest. Aqui está um liner simples que usa os parâmetros Rest ES6.

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

kapil pandey
fonte
2

Isso se baseia na minha solução para o Bonfire "Title Case" do FreeCodeCamp , que exige que você primeiro converta a sequência especificada para todas as letras minúsculas e, em seguida, converta todos os caracteres que procedem de um espaço para letras maiúsculas.

Sem usar regex:

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