Преобразовать строку в заголовок с помощью JavaScript

549

Есть ли простой способ конвертировать строку в заголовок? Например john smithстановится John Smith. Я не ищу чего-то сложного, такого как решение Джона Резига , просто (надеюсь) какой-то одно- или двухслойный.

MDCore
источник
Существуют различные методы, есть ли у нас статистика производительности?
Анубхав
Пожалуйста, проверьте этот короткий ответ stackoverflow.com/a/57689168/10373693 Я надеюсь, что это будет ответ, который вы ищете.
Абхишек Кумар

Ответы:

740

Попробуй это:

    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>

Грег Дин
источник
14
Может ли кто-нибудь объяснить, почему \w\S*используется, а не \w+или, \w*например? Я не знаю, почему вы захотите включить что-нибудь, кроме пробелов, и поэтому измените Джим-Боб на Джим-боб .
martinczerwi
5
@martinCzerwi \w\S*также вызвал Jim-bobпроблему с нашей стороны. Использование \w*решило это.
Bouke
14
/([^\W_]+[^\s-]*) */gрешает Jim-Bobпроблему, т.е.:jim-bob --> Jim-Bob
recursion.ninja
15
Если jim-bob --> Jim-Bobэто ваше желание, вы, вероятно, должны сделать /\b\w+/g. Пример:str.replace(/\b\w+/g,function(s){return s.charAt(0).toUpperCase() + s.substr(1).toLowerCase();});
vol7ron
3
\w\S*используется вместо \w+или \w*так, чтобы слова вроде Don'tне изменялись Don'T, но, как указывали другие, \w\S*вызывает проблемы с переносами слов.
DoubleDown
198

Немного более элегантный способ, адаптирующий функцию Грега Дина:

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

Назовите это как:

"pascal".toProperCase();
Туан
источник
3
Имейте в виду, если у вас есть пользователь с чертой в имени и он вводит Jo-Ann Smith, этот код преобразует его в Jo-ann Smith(обратите внимание на нижний регистр aв Ann).
dbau
18
@daniellmb Почему он не должен изменять прототип String? Я думаю, что это хорошее решение. Подумайте о рубиновых открытых классах, совершенно правильно добавлять функции к существующим классам, и это широко распространено.
Марко-Фисет
97
@ marco-fiset Потому что это плохо сочетается с другими! Плохие вещи случаются, когда у вас есть 2 библиотеки, которые пытаются изменить нативные объекты JavaScript с несовместимыми изменениями. Представьте себе, что если jQuery и Google Maps следуют этому шаблону дизайна, вы не можете иметь оба на одной странице.
Даниэльмб
5
@daniellmb Отличный момент. Префикс имени метода должен помочь избежать этого, так как сделает метод не перечисляемым.
mikemaccana
60
Мне кажется, что выражение «не изменять нативные объекты JavaScript» похоже на выражение «никогда не использовать goto» или «eval is evil». Есть много случаев, когда это нормально. Если вы полностью контролируете свой проект и, конечно, не планируете выпускать его в виде библиотеки, я не вижу проблем с этим методом.
FoxMulder900
175

Попробуйте применить CSS-стиль для преобразования текста к элементам управления.

например: (text-transform: capitalize);

Используйте подход JS только тогда, когда это абсолютно необходимо.

Талха Ашфак
источник
36
-1. Эта CSS работает, но не работает, как большинство людей ожидают, потому что, если текст начинается как все заглавные буквы, это не имеет никакого эффекта. webmasterworld.com/forum83/7506.htm
Уитниленд
2
@Akshar: правило нижнего регистра будет заменено правилом названия заглавия. Поскольку css не изменяет исходный контент, эффект состоит в том, что правило нижнего регистра удаляется (оставляя исходный контент во всех заглавных буквах), а затем применяется правило заголовка (ничего не делая).
Dokkaebi
42
JS используется вне браузеров.
mikemaccana
4
Вопрос был: «Есть ли простой способ преобразовать строку в регистр заголовков?» , Этот ответ не конвертирует строку. Это стиль, применяемый поверх строки.
kingPuppy
Если вы хотите, чтобы данные в вашей базе данных были чистыми, чтобы их можно было безошибочно использовать при передаче сторонним службам или экспортировать в CSV, тогда CSS на самом деле не вариант. CSS предназначен для косметики, и хотя он сильно вырос за эти годы, и вы можете использовать его для решения подобных проблем, решение остается косметическим и не решает основной проблемы.
Адам Рейс
118

Вот моя версия, ИМО, это легко понять и элегантно.

var str = "foo bar baz"

console.log(

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

)
// returns "Foo Bar Baz"

a8m
источник
3
Кроме того, вы можете в нижнем регистре подстроку в отображении:str.split(' ').map(i => i[0].toUpperCase() + i.substring(1).toLowerCase()).join(' ')
Dave Land
5
Я не согласен с вызовом .toLowerCase(). Имена, такие как «McDonald» или аббревиатуры, такие как «ASAP», должны сохранять заглавные буквы. Если кто-то фактически передал строку типа «heLLO», приложение не должно предполагать, что заглавные буквы неверны.
Томас Хиггинботам
1
@ThomasHigginbotham Как насчет этого? 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(' '); }
Шон Кендл
Да, предпочтительнее указывать строчные буквы.
Томас Хиггинботам
1
Это сломается, если strбудет один символ.
Madbreaks
103

Вот моя функция, которая преобразует в регистр заглавия, но также сохраняет определенные аббревиатуры в верхнем регистре и второстепенные слова в нижнем регистре:

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

Например:

"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:"
Джеффри Бут
источник
1
Мне понравился твой, я также сталкиваюсь с проблемами при работе с римскими числами ... просто исправил это с I, II, III, IV и т. Д.
Марсело
2
Исправлена. Регулярное выражение в третьей строке было изменено /\w\S*/gна /([^\W_]+[^\s-]*) */gна @ awashburn замечании выше для решения этой проблемы .
Джеффри Бут
2
Есть ли преимущество, которое вы можете получить, используя свой шаблон регулярных выражений /\b\w+/g, который я считаю более быстрым?
Майкл - Где Клэй Ширки
2
Не то чтобы я мог видеть, я просто принял предложение другого комментатора для решения проблемы дефисных слов; но ваше регулярное выражение, кажется, делает то же самое, и простота всегда лучше. Для потомков и будущих посетителей на этот пост, я просто изменил регулярное выражение в третьей строке от /([^\W_]+[^\s-]*) */gдо /\b\w+/gпер @ комментарий Майкла; пожалуйста, прокомментируйте, если вы найдете случай, когда необходимо более сложное регулярное выражение.
Джеффри Бут
1
Я изменил регулярное выражение 3-й строки /\b[\w-\']+/g, чтобы разрешить переносить слова и апостроф в словах.
Шамасис Бхаттачарья
47

Я предпочитаю следующее над другими ответами. Он соответствует только первой букве каждого слова и заглавными буквами. Более простой код, легче для чтения и меньше байтов. Он сохраняет существующие заглавные буквы для предотвращения искажений аббревиатур. Однако вы всегда toLowerCase()можете сначала вызвать вашу строку.

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

Вы можете добавить это к вашему прототипу строки, что позволит вам сделать 'my string'.toTitle()следующее:

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

Пример:

Том Кей
источник
3
Это даже лучше, как лямбдаconst titleCase = (str) => str.replace(/\b\S/g, t => t.toUpperCase());
0xcaff
Я не хотел ломать IE, но да, если приложение не чувствительно к устаревшему браузеру, оно может быть короче.
Том Кей
Это только частичное решение - операционная служба спросила, как преобразовать строку в регистр заголовков. Этот ответ не делает этого для входов, как NoT qUiITe.
Madbreaks
@Madbreaks Вопрос не предусматривал конвертирование входных данных в смешанном регистре. Тем не менее, я обновил ответ упоминания toLowerCase. Просто знайте, что это нарушит аббревиатуры. an HTML document: An HTML DocumentvsAn Html Document
Том Кей,
4
@Madbreaks Хотя ваш первоначальный пример был придуман, вы должны заявить, что выходные данные останутся неизменными, если входные данные были написаны заглавными буквами. При этом, я чувствую, что ответ «как есть» (с предложением редактирования toLowerCase) является более гибким / полезным, чем тот, который предполагает намерения разработчиков. Этот метод также отражает функциональность аналогичных встроенных методов других языков, таких как PHP ( ucwords) и Golang ( strings.Title). .NET ( TextInfo.ToTitleCase) интересно работает в смешанном регистре, но также оставит полностью заглавные строки без изменений.
Том Кей
20

Без использования регулярных выражений только для справки:

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

Майк
источник
Спасибо за бесплатное решение для регулярных выражений!
lucifer63
20

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

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

Симо
источник
Просто вопрос, конструкция () предназначена для определения совпадения любой из последовательности опций: то есть (a | b) соответствует a или b. Что делает конструкция (.)?
Майкл Блэкберн
Для тех, у кого был такой же вопрос, он определяет замену «blob», которая используется в разделе замены. Капли нумеруются последовательно, первый () помещается в $ 1, второй в $ 2. Я нашел этот сайт полезным: javascript.info/tutorial/regular-expressions-methods
Майкл Блэкберн
Я не могу заставить работать вышеперечисленное, но я далеко не волшебник регулярных выражений. Я использую 'string'.replace(/^(.)(.*)/,function(s,p1,p2){return p1.toUpperCase()+p2;}) Опять же, это работает только для заглавных букв первой буквы строки, но в случае, если это то, что вам нужно, моя конструкция работает.
Майкл Блэкберн
1
По какой-то причине FF35, кажется, задыхается '$1'.toUpperCase(), кажется, что заглавные буквы не были сделаны к моменту назначения значения. 'string'.replace(/^(.){1}/,function(match) { return match.toUpperCase(); })
Обошел
Привет всем, ответ исправлен! Я почти уверен, что это сработало к тому времени, как я его опубликовал. В любом случае, спасибо за вклад!
Симо
17

Вы можете сразу toLowerCaseстроку, а затем только toUpperCaseпервую букву каждого слова. Становится очень простым 1 вкладышем:

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

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

KevBot
источник
Мне нравится это решение; красиво и просто. Похоже, немного CoffeeScript проскользнул в ваш ответ (s => s.toUpperCase() ). Мой вариант делать то , что вы сделали, но расширения объекта String (как спорный , как есть):Object.defineProperty(String.prototype, '_toProperCase', {value:function() {return this.toLowerCase().replace(/\b(\w)/g, function(t) {return t.toUpperCase()})}})
Ваз
1
@ Waz, спасибо за идеи! Просто хотел уточнить на=> , что это встроенная функция стрелок (ES6), ссылка переходит к документам Mozillla на них, которая также предоставляет таблицу поддержки.
KevBot
16

На всякий случай, если вас волнуют эти слова-наполнители, вы всегда можете просто сказать функции, что не использовать заглавные буквы.

/**
 * @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();
    });
};

Надеюсь, что это помогает вам.

редактировать

Если вы хотите обработать начальные связующие слова, вы можете отслеживать эту w / еще одну переменную:

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
источник
2
Вы можете взорвать строку в массив. Таким образом, у нас могут быть предлоги на португальском, испанском, итальянском и французском языках:glue ='de|da|del|dos|do|das|des|la|della|delli'.split('|');
Junior Mayhé
Это не обеспечит заглавную букву первого слова; то есть and another thingстановится and Another Thing. Просто нужен элегантный способ всегда использовать первое слово с большой буквы.
Брэд Кох
@BradKoch - панель с пробелами, поэтому вы используете «и», «де» и т. Д. В качестве поискового слова, затем «И еще и еще» заменит «И еще и еще».
Иминь Ронг,
хорошо, за исключением заглавных букв и текста после 'и - как H'Dy или Number-One
Luk
Вместо использования троичного оператора вы можете просто использовать запасной вариант: glue = glue || ['of', 'for', 'and', 'a'];
tm2josep
14

Если регулярное выражение, используемое в приведенных выше решениях, вводит вас в заблуждение, попробуйте этот код:

function titleCase(str) {
  return str.split(' ').map(function(val){ 
    return val.charAt(0).toUpperCase() + val.substr(1).toLowerCase();
  }).join(' ');
}
immazharkhan
источник
любить это! нет преобразования в массивы.
neelmeg
1
э-э-э ... split действительно конвертирует его в массив, вы просто не видите это так очевидно, потому что mapозначает, что вам не нужно использовать []нотацию
MalcolmOcean
2
Это то же самое, что ответ a8m от 2 лет назад.
Майкл - Где Клэй Ширки
1
Разрывы для одно-символьных входов.
Madbreaks
1
@AlexChaffee проверьте историю изменений. a8m не использовал функцию стрелки в исходном ответе.
Спасибо,
9

Я сделал эту функцию, которая может обрабатывать фамилии (так что это не случай названия), такие как «Макдональд» или «Макдональд» или «О'Тул» или «Д'Орацио». Однако он не обрабатывает немецкие или голландские имена с "van" или "von", которые часто пишутся в нижнем регистре ... Я считаю, что "de" тоже часто в нижнем регистре, например, "Robert de Niro". Эти вопросы все еще должны быть решены.

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
источник
1
+1 для осознания имени. Однако, неправильно обрабатывает "Мэйси".
brianary
Это была единственная функция, которая правильно обрабатывает преобразование прописных и строчных букв в правильные и замечает инициалы типа «Виргинские острова США».
Родриго Поло
Вы можете обойти macyпроблему, положив туда негативную \b((m)(a?c))?(\w)\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 : "");
    }
)

Кажется, работает ... Протестировано с вышеупомянутым, "быстрый коричневый, лиса? / Прыжки / ^ над ^ ленивый! Собака ..." и "C: / программные файлы / какой-то поставщик / их второе приложение / а file1.txt».

Если вы хотите 2-й вместо 2-го, вы можете изменить на /([a-z])(\w*)/g .

Первая форма может быть упрощена как:

function toTitleCase(toTransform) {
  return toTransform.replace(/\b([a-z])/g, function (_, initial) {
      return initial.toUpperCase();
  });
}
PhiLho
источник
7

Попробуй это

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

пример

var str = 'john smith';
str.toProperCase();
Макси Баез
источник
7

Если вы можете использовать сторонние библиотеки в своем коде, тогда у lodash есть вспомогательная функция для нас.

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
источник
7

Попробуйте это, кратчайший путь:

str.replace(/(^[a-z])|(\s+[a-z])/g, txt => txt.toUpperCase());
Викрам
источник
7

ES 6

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

еще

str.split(' ').map(function (s) {
    return s.slice(0, 1).toUpperCase() + s.slice(1).toLowerCase();
}).join(' ')
jssridhar
источник
Наверное, так и должно быть, s.slice(0, 1).toUpperCase()если вы все еще хотите эту первую букву.
WindsofTime
@jssridhar, вы также должны исправить код в ES6.
caiosm1005
1
Breaks if str- одиночный персонаж
Madbreaks
@jssridhar может быть лучше для нас .charAt(0).toUpperCase().
roydukkey
2
дубликат ответа a8m
Спасибо,
6

Большинство этих ответов, похоже, игнорируют возможность использования метасимвола границы слова (\ b). Более короткая версия ответа Грега Дина, использующего его:

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

Работает для дефисных имен, таких как Джим-Боб тоже.

lewax00
источник
2
Это элегантное частичное решение, но не работает со строками ударения или заглавными буквами. Я получаю "Sofía Vergara" => "SofíA Vergara" или "Sofía VERGARA" => "SofíA VERGARA". Второй случай можно решить с помощью функции apply .toLowerCase () перед .replace (...). В первом случае нужно найти правильное регулярное выражение.
Asereware
2
Хм, это похоже на ошибку в реализации регулярных выражений, я бы подумал, что акцентированные символы должны быть символами слов (хотя вы и правы, поскольку в этих случаях это не работает).
lewax00
\wвключает в себя только символы [A-Za-z0-9_], а не все буквы. Для этого вам нужно использовать категорию Unicode \p{L}. Вам понадобится /uмодификатор (см. Здесь ) и другое решение \b, которое работает только между \Wи \w(см. Здесь )
cmbuckley
6

Я думаю, что самым простым является использование CSS.

function format_str(str) {
    str = str.toLowerCase();
    return '<span style="text-transform: capitalize">'+ str +'</span>';
}
wondim
источник
Я обновил код и проверил его. Это должно работать сейчас.
wondim
Вы можете использовать CSS только в той части среды, в которой используется JS, так что это решение нежизнеспособно. Также следует избегать встроенных стилей любой ценой.
Madbreaks
5

Используйте /\S+/gдля поддержки диакритических знаков:

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

Однако: " s unshine ( y ellow)" ⇒ " S unshine ( y ellow)"

le_m
источник
5

Я хотел добавить свой собственный ответ, так как мне нужна надежная toTitleCaseфункция, которая учитывает правила грамматики, перечисленные здесь (статья, рекомендованная Google). Существуют различные правила, которые зависят от длины входной строки. Ниже приведена функция + модульные тесты.

Функция также объединяет пробелы и удаляет специальные символы (измените регулярное выражение для ваших нужд)

Функция 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(' ');
}

Модульные тесты для проверки правильности

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

Обратите внимание, что я удаляю довольно много специальных символов из предоставленных строк. Вам нужно будет настроить регулярное выражение в соответствии с требованиями вашего проекта.

dipole_moment
источник
Я предпочитаю это решение, так как оно действительно заботится о заглавии. Это не «Унесенные ветром», это «Унесенные ветром»
russellmania
5
"john f. kennedy".replace(/\b\S/g, t => t.toUpperCase())
следующий месяц
источник
1
Работает для образца и o'henry, но делает странные вещи с horse's mouth.
Майкл - Где Клэй Ширки
"john f. kennEdy".toLowerCase().replace(/\b\S/g, t => t.toUpperCase())лучше 🤔
w3debugger
Не хотел редактировать ответ @ Proximo: \bи \Sявляются специальными классами символов, обозначающими «границу слова» и «один непробельный символ. Таким образом, регулярное выражение соответствует каждому отдельному символу, следующему за границей слова, и использует этот знак с большой буквы, применяя данную функцию стрелки.
Дженс
4

Используя решение «lewax00», я создал это простое решение, которое заставляет «w» начинаться с пробела или «w», которые инициируют слово, но не может удалить лишние промежуточные пробелы.

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

Результат "София Вергара".

Asereware
источник
4

Вот моя функция, которая заботится об акцентированных символах (важно для французского!) И которая может включать / выключать обработку исключений более низкого уровня. Надеюсь, это поможет.

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
источник
4

У нас здесь, в офисе, было обсуждение, и мы думаем, что попытка автоматически исправить то, как люди вводят имена в том виде, в котором вы хотите, чтобы это происходило, чревата возможными проблемами.

Мы придумали несколько случаев, когда разные типы автокапитализации распадаются, и это только для английских имен, каждый язык имеет свои сложности.

Проблемы с использованием заглавных букв первой буквы каждого имени:

• Сокращения, такие как IBM, не разрешенные для ввода, превратятся в Ibm.

• Имя McDonald превратится в Mcdonald, что неверно, то же самое относится и к MacDonald.

• Двуствольные имена, такие как «Мари-Тонкс», превратятся в «Мари-Тонкс».

• Имена как О'Коннор превратятся в О'Коннор.

Для большинства из них вы могли бы написать собственные правила, чтобы справиться с этим, однако, это по-прежнему имеет проблемы с сокращениями, как и раньше, и вы получаете новую проблему:

• Добавление правила для исправления имен с Mac, таких как MacDonald, приведет к тому, что имена разрывов, такие как Macy, превратят его в MacY.

Единственное решение, которое мы придумали, которое никогда не бывает неправильным, состоит в том, чтобы использовать каждую букву с заглавной буквы, которая является методом грубой силы, который, по-видимому, также использует DBS.

Так что, если вы хотите автоматизировать процесс, это так же невозможно, как без словаря каждого отдельного имени и слова, и как оно должно быть прописным. Если у вас нет правила, которое охватывает все, не используйте его как оно будет просто раздражать ваших пользователей и предлагать людям, которые хотят правильно ввести свои имена, пойти куда-нибудь еще.

jjr2000
источник
4

Вот еще одно решение с использованием CSS (и JavaScript, если текст, который вы хотите преобразовать, в верхнем регистре):

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
источник
3

Для тех из нас, кто боится регулярных выражений (смеется):

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
источник
3

Мое однострочное решение:

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

Затем вы можете вызвать метод capitalizeWords()для любой строки. Например:

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

>>> This Actually Works

Мое другое решение:

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

Затем вы можете вызвать метод capitalizeWords()для любой строки. Например:

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

>>> This One Works Too

Альтернативное решение на основе ответа Грега Дина:

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

Затем вы можете вызвать метод capitalizeWords()для любой строки. Например:

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

>>> Yes And No
Фуад Букредин
источник
3

Удивило, что никто не упомянул об использовании параметра rest. Вот простой вкладыш, который использует параметры ES6 Rest.

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

Капил Пандей
источник
2

Это основано на моем решении для Bonfire FreeCodeCamp "Заголовок дела" , которое требует, чтобы вы сначала преобразовали данную строку во все строчные буквы, а затем преобразовали каждый символ, начиная с пробела, в верхний регистр.

Без использования регулярных выражений:

function titleCase(str) {
 return str.toLowerCase().split(' ').map(function(val) { return val.replace(val[0], val[0].toUpperCase()); }).join(' ');
}
Джеймси Диммик Мэй
источник