206

I'm working on an app in CodeIgniter, and I'm trying to make a field on a form dynamically generate the URL slug. What I'd like to do is remove the punctuation, convert it to lowercase, and replace the spaces with hyphens. So for example, Shane's Rib Shack would become shanes-rib-shack.

Here's what I have so far. The lowercase part was easy, but the replace doesn't seem to be working at all, and I have no idea to remove the punctuation:

$("#Restaurant_Name").keyup(function() {
  var Text = $(this).val();
  Text = Text.toLowerCase();
  Text = Text.replace('/\s/g','-');
  $("#Restaurant_Slug").val(Text);  
});
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
GSto
  • 41,512
  • 37
  • 133
  • 184

26 Answers26

487

I have no idea where the 'slug' term came from, but here we go:

function convertToSlug(Text) {
  return Text.toLowerCase()
    .replace(/ /g, "-")
    .replace(/[^\w-]+/g, "");
}

console.log(convertToSlug("hello world!"));
console.log(convertToSlug("hello - world!"));

The first replace method will change spaces to hyphens, second, replace removes anything not alphanumeric, underscore, or hyphen.

If you don't want things "like - this" turning into "like---this" then you can instead use this one:

function convertToSlug(Text) {
  return Text.toLowerCase()
    .replace(/[^\w ]+/g, "")
    .replace(/ +/g, "-");
}

console.log(convertToSlug("hello world!"));
console.log(convertToSlug("hello - world!"));

That will remove hyphens (but no spaces) on the first replace, and in the second replace it will condense consecutive spaces into a single hyphen.

So "like - this" comes out as "like-this".

vanenshi
  • 65
  • 2
  • 11
Peter Boughton
  • 110,170
  • 32
  • 120
  • 176
  • 1
    don't forget to add "/" aswell if you need multi directories seperated – Val Jan 21 '11 at 13:35
  • 10
    the term "slug" came from wordpress – Brynner Ferreira Feb 01 '14 at 15:57
  • 35
    To avoid multiple sequential hyphens, I used `text.toLowerCase().replace(/ /g,'-').replace(/[-]+/g, '-').replace(/[^\w-]+/g,'');` instead of option 2. Option 2 will change "th--is" to "this". – Ryan Allen Mar 18 '14 at 20:58
  • How do I also allow dot in the URL? – Liron Harel Jan 12 '16 at 12:52
  • For avoid "_" in slug, override .replace(/ +/g,'-') to .replace(/ +|_/g,'-'). – Odin Thunder Mar 17 '17 at 13:47
  • you should use $.trim function to avoid blank spaces. $.trim($(this).val()).toLowerCase().replace(/ /g,'_').replace(/[^\w-]+/g,'') – Ankit Vishwakarma Apr 18 '17 at 10:59
  • this regex fails for a string that have spaces or symbols in the starting eg " (sd sdsds (lakem 0.5) " – sunitj Dec 26 '18 at 10:33
  • FWIW: Slug comes from the world of printing / typesetting. Originally it was the lead spacing material used with letterpress. Then later (with Linotype machines / hot metal typesetting) it was the actual text cast from molten metal (still usually lead). Here's a nice explanation of that process: https://www.uh.edu/engines/epi2259.htm – Matt Wolff May 24 '20 at 14:52
134
var slug = function(str) {
  str = str.replace(/^\s+|\s+$/g, ''); // trim
  str = str.toLowerCase();

  // remove accents, swap ñ for n, etc
  var from = "ãàáäâẽèéëêìíïîõòóöôùúüûñç·/_,:;";
  var to   = "aaaaaeeeeeiiiiooooouuuunc------";
  for (var i = 0, l = from.length; i < l; i++) {
    str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
  }

  str = str.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
           .replace(/\s+/g, '-') // collapse whitespace and replace by -
           .replace(/-+/g, '-'); // collapse dashes

  return str;
};

and try

slug($('#field').val())

original by: http://dense13.com/blog/2009/05/03/converting-string-to-slug-javascript/


EDIT: extended for more language specific chars:

var from = "ÁÄÂÀÃÅČÇĆĎÉĚËÈÊẼĔȆĞÍÌÎÏİŇÑÓÖÒÔÕØŘŔŠŞŤÚŮÜÙÛÝŸŽáäâàãåčçćďéěëèêẽĕȇğíìîïıňñóöòôõøðřŕšşťúůüùûýÿžþÞĐđ߯a·/_,:;";
var to   = "AAAAAACCCDEEEEEEEEGIIIIINNOOOOOORRSSTUUUUUYYZaaaaaacccdeeeeeeeegiiiiinnooooooorrsstuuuuuyyzbBDdBAa------";
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
Taranttini
  • 1,435
  • 1
  • 11
  • 4
  • 7
    But not correctly. In German texts, `ü` should be replaced with `ue`, etc. – feklee Oct 28 '12 at 18:02
  • 6
    @feklee: "Not correctly" is true for German (and possibly some other languages), but in other languages it's just fine. For an English website, I would want "Márföldi" (last name of a Hungarian origin) to be converted into "marfoldi", and not "marfoeldi", as Germans would. – michalstanko Jan 13 '14 at 20:12
  • 1
    To ensure cross-platform compatibility, you may want to subsitute from="\u00E3\u00E0\u00E1\u00E4\u00E2\u1EBD\u00E8\u00E9\u00EB\u00EA\u00EC\u00ED\u00EF\u00EE\u00F5\u00F2\u00F3\u00F6\u00F4\u00F9\u00FA\u00FC\u00FB\u00F1\u00E7\u00B7/_,:;"; – Mike Godin Aug 07 '14 at 17:23
  • 2
    Nice solution! Missing the Scandinavian `å` though. – Fredric Oct 13 '14 at 10:15
  • 1
    You can add `İĞŞığş` to `from` variable and convert them to `IGSigs` to support Turkish characters. – CemilF Apr 10 '19 at 06:26
  • 1
    Hi @Taranttini, if you use `str.toLocaleLowerCase()`, you can drop all the uppercase letters in your replace :) – Andreas Jan 11 '20 at 03:38
27

First of all, regular expressions should not have surrounding quotes, so '/\s/g' should be /\s/g

In order to replace all non-alphanumerical characters with dashes, this should work (using your example code):

$("#Restaurant_Name").keyup(function() {
  var Text = $(this).val();
  Text = Text.toLowerCase();
  Text = Text.replace(/[^a-zA-Z0-9]+/g,'-');
  $("#Restaurant_Slug").val(Text);        
});

That should do the trick...

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
Philippe Leybaert
  • 168,566
  • 31
  • 210
  • 223
18

Hope this can save someone's day...

/* Encode string to slug */
function convertToSlug( str ) {
    
  //replace all special characters | symbols with a space
  str = str.replace(/[`~!@#$%^&*()_\-+=\[\]{};:'"\\|\/,.<>?\s]/g, ' ')
           .toLowerCase();
    
  // trim spaces at start and end of string
  str = str.replace(/^\s+|\s+$/gm,'');
    
  // replace space with dash/hyphen
  str = str.replace(/\s+/g, '-');   
  document.getElementById("slug-text").innerHTML = str;
  //return str;
}
<input 
  type="text" 
  onload="convertToSlug(this.value)" 
  onkeyup="convertToSlug(this.value)"
  value="Try it Yourself" 
/>
<p id="slug-text"></p>
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
bmatovu
  • 3,756
  • 1
  • 35
  • 37
11

I found a good and complete solution for English

function slugify(string) {
  return string
    .toString()
    .trim()
    .toLowerCase()
    .replace(/\s+/g, "-")
    .replace(/[^\w\-]+/g, "")
    .replace(/\-\-+/g, "-")
    .replace(/^-+/, "")
    .replace(/-+$/, "");
}

Some examples of it in use:

slugify(12345);
// "12345"

slugify("  string with leading   and   trailing whitespace    ");
// "string-with-leading-and-trailing-whitespace"

slugify("mIxEd CaSe TiTlE");
// "mixed-case-title"

slugify("string with - existing hyphens -- ");
// "string-with-existing-hyphens"

slugify("string with Special™ characters");
// "string-with-special-characters"

Thanks to Andrew Stewart

zahid9i
  • 596
  • 1
  • 8
  • 17
11

Combining a variety of elements from the answers here with normalize provides good coverage. Keep the order of operations to incrementally clean the url.

function clean_url(s) {
    return s.toString().normalize('NFD').replace(/[\u0300-\u036f]/g, "") //remove diacritics
            .toLowerCase()
            .replace(/\s+/g, '-') //spaces to dashes
            .replace(/&/g, '-and-') //ampersand to and
            .replace(/[^\w\-]+/g, '') //remove non-words
            .replace(/\-\-+/g, '-') //collapse multiple dashes
            .replace(/^-+/, '') //trim starting dash
            .replace(/-+$/, ''); //trim ending dash
}

normlize('NFD') breaks accented characters into their components, which are basic letters plus diacritics (the accent part). replace(/[\u0300-\u036f]/g, "") purges all the diacritics, leaving the basic letters by themselves. The rest is explained with inline comments.

OXiGEN
  • 2,041
  • 25
  • 19
  • 1
    Thanks you. This is simple and works well with my test-cases. Even the Vietnamese character ``` const testCases = [ { input: 'is it a good slug', expect: 'is-it-a-good-slug' }, { input: '-----is-----it-----a-----good-----slug-----', expect: 'is-it-a-good-slug' }, { input: 'CÔNG cha như núi Thái Sơn', expect: 'cong-cha-nhu-nui-thai-son' }, { input: '-Haha--Nhất-Nguyễn', expect: 'haha-nhat-nguyen' } ]``` – Phat Tran Feb 02 '20 at 23:01
  • If anyone is triggering this as soon as a character is typed, leave out the last line that replaces the ending dash ```.replace(/-+$/, '');``` for ```onblur``` i.e. when the user leaves the input field. Doing this will allow the user fully type their slug otherwise it will always remove the '-' before the next letter. – alkadelik Sep 09 '20 at 08:16
  • Also ".replace(/[^\w\-]+/g, ' ') //remove non-words" should be ".replace(/[^\w-]+/g, ' ')", and .replace(/\-\-+/g, '-') //collapse multiple dashes should be ".replace(/--+/g, '-')" – alkadelik Sep 09 '20 at 09:17
  • If you change normalize('NFD') to normalize('NFC'), (or just normalize(), because "NFC is the default), you won't have to do another run of replace() removing decomposed diacritical marks. – cababunga Oct 04 '21 at 17:39
  • normalize('NFC') only is not enough!!! even spaces stay there. How do you mean your "advice" @cababunga – Eduard Void Apr 05 '22 at 20:42
  • 1
    @EduardVoid, the comment is about removing diacritical marks. Of course, call to normalize() is not the whole solution. – cababunga Apr 05 '22 at 22:40
8

All you needed was a plus :)

$("#Restaurant_Name").keyup(function() {
  var Text = $(this).val();
  Text = Text.toLowerCase();
  var regExp = /\s+/g;
  Text = Text.replace(regExp,'-');
  $("#Restaurant_Slug").val(Text);        
});
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
karim79
  • 339,989
  • 67
  • 413
  • 406
8

Take a look at this slug function to sanitize URLs, developed by Sean Murphy at https://gist.github.com/sgmurphy/3095196

/**
 * Create a web friendly URL slug from a string.
 *
 * Requires XRegExp (http://xregexp.com) with unicode add-ons for UTF-8 support.
 *
 * Although supported, transliteration is discouraged because
 *     1) most web browsers support UTF-8 characters in URLs
 *     2) transliteration causes a loss of information
 *
 * @author Sean Murphy <sean@iamseanmurphy.com>
 * @copyright Copyright 2012 Sean Murphy. All rights reserved.
 * @license http://creativecommons.org/publicdomain/zero/1.0/
 *
 * @param string s
 * @param object opt
 * @return string
 */
function url_slug(s, opt) {
    s = String(s);
    opt = Object(opt);

    var defaults = {
        'delimiter': '-',
        'limit': undefined,
        'lowercase': true,
        'replacements': {},
        'transliterate': (typeof(XRegExp) === 'undefined') ? true : false
    };

    // Merge options
    for (var k in defaults) {
        if (!opt.hasOwnProperty(k)) {
            opt[k] = defaults[k];
        }
    }

    var char_map = {
        // Latin
        'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE', 'Ç': 'C', 
        'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I', 'Î': 'I', 'Ï': 'I', 
        'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O', 'Õ': 'O', 'Ö': 'O', 'Ő': 'O', 
        'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 'Ü': 'U', 'Ű': 'U', 'Ý': 'Y', 'Þ': 'TH', 
        'ß': 'ss', 
        'à': 'a', 'á': 'a', 'â': 'a', 'ã': 'a', 'ä': 'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', 
        'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e', 'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i', 
        'ð': 'd', 'ñ': 'n', 'ò': 'o', 'ó': 'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', 'ő': 'o', 
        'ø': 'o', 'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u', 'ű': 'u', 'ý': 'y', 'þ': 'th', 
        'ÿ': 'y',

        // Latin symbols
        '©': '(c)',

        // Greek
        'Α': 'A', 'Β': 'B', 'Γ': 'G', 'Δ': 'D', 'Ε': 'E', 'Ζ': 'Z', 'Η': 'H', 'Θ': '8',
        'Ι': 'I', 'Κ': 'K', 'Λ': 'L', 'Μ': 'M', 'Ν': 'N', 'Ξ': '3', 'Ο': 'O', 'Π': 'P',
        'Ρ': 'R', 'Σ': 'S', 'Τ': 'T', 'Υ': 'Y', 'Φ': 'F', 'Χ': 'X', 'Ψ': 'PS', 'Ω': 'W',
        'Ά': 'A', 'Έ': 'E', 'Ί': 'I', 'Ό': 'O', 'Ύ': 'Y', 'Ή': 'H', 'Ώ': 'W', 'Ϊ': 'I',
        'Ϋ': 'Y',
        'α': 'a', 'β': 'b', 'γ': 'g', 'δ': 'd', 'ε': 'e', 'ζ': 'z', 'η': 'h', 'θ': '8',
        'ι': 'i', 'κ': 'k', 'λ': 'l', 'μ': 'm', 'ν': 'n', 'ξ': '3', 'ο': 'o', 'π': 'p',
        'ρ': 'r', 'σ': 's', 'τ': 't', 'υ': 'y', 'φ': 'f', 'χ': 'x', 'ψ': 'ps', 'ω': 'w',
        'ά': 'a', 'έ': 'e', 'ί': 'i', 'ό': 'o', 'ύ': 'y', 'ή': 'h', 'ώ': 'w', 'ς': 's',
        'ϊ': 'i', 'ΰ': 'y', 'ϋ': 'y', 'ΐ': 'i',

        // Turkish
        'Ş': 'S', 'İ': 'I', 'Ç': 'C', 'Ü': 'U', 'Ö': 'O', 'Ğ': 'G',
        'ş': 's', 'ı': 'i', 'ç': 'c', 'ü': 'u', 'ö': 'o', 'ğ': 'g', 

        // Russian
        'А': 'A', 'Б': 'B', 'В': 'V', 'Г': 'G', 'Д': 'D', 'Е': 'E', 'Ё': 'Yo', 'Ж': 'Zh',
        'З': 'Z', 'И': 'I', 'Й': 'J', 'К': 'K', 'Л': 'L', 'М': 'M', 'Н': 'N', 'О': 'O',
        'П': 'P', 'Р': 'R', 'С': 'S', 'Т': 'T', 'У': 'U', 'Ф': 'F', 'Х': 'H', 'Ц': 'C',
        'Ч': 'Ch', 'Ш': 'Sh', 'Щ': 'Sh', 'Ъ': '', 'Ы': 'Y', 'Ь': '', 'Э': 'E', 'Ю': 'Yu',
        'Я': 'Ya',
        'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo', 'ж': 'zh',
        'з': 'z', 'и': 'i', 'й': 'j', 'к': 'k', 'л': 'l', 'м': 'm', 'н': 'n', 'о': 'o',
        'п': 'p', 'р': 'r', 'с': 's', 'т': 't', 'у': 'u', 'ф': 'f', 'х': 'h', 'ц': 'c',
        'ч': 'ch', 'ш': 'sh', 'щ': 'sh', 'ъ': '', 'ы': 'y', 'ь': '', 'э': 'e', 'ю': 'yu',
        'я': 'ya',

        // Ukrainian
        'Є': 'Ye', 'І': 'I', 'Ї': 'Yi', 'Ґ': 'G',
        'є': 'ye', 'і': 'i', 'ї': 'yi', 'ґ': 'g',

        // Czech
        'Č': 'C', 'Ď': 'D', 'Ě': 'E', 'Ň': 'N', 'Ř': 'R', 'Š': 'S', 'Ť': 'T', 'Ů': 'U', 
        'Ž': 'Z', 
        'č': 'c', 'ď': 'd', 'ě': 'e', 'ň': 'n', 'ř': 'r', 'š': 's', 'ť': 't', 'ů': 'u',
        'ž': 'z', 

        // Polish
        'Ą': 'A', 'Ć': 'C', 'Ę': 'e', 'Ł': 'L', 'Ń': 'N', 'Ó': 'o', 'Ś': 'S', 'Ź': 'Z', 
        'Ż': 'Z', 
        'ą': 'a', 'ć': 'c', 'ę': 'e', 'ł': 'l', 'ń': 'n', 'ó': 'o', 'ś': 's', 'ź': 'z',
        'ż': 'z',

        // Latvian
        'Ā': 'A', 'Č': 'C', 'Ē': 'E', 'Ģ': 'G', 'Ī': 'i', 'Ķ': 'k', 'Ļ': 'L', 'Ņ': 'N', 
        'Š': 'S', 'Ū': 'u', 'Ž': 'Z', 
        'ā': 'a', 'č': 'c', 'ē': 'e', 'ģ': 'g', 'ī': 'i', 'ķ': 'k', 'ļ': 'l', 'ņ': 'n',
        'š': 's', 'ū': 'u', 'ž': 'z'
    };

    // Make custom replacements
    for (var k in opt.replacements) {
        s = s.replace(RegExp(k, 'g'), opt.replacements[k]);
    }

    // Transliterate characters to ASCII
    if (opt.transliterate) {
        for (var k in char_map) {
            s = s.replace(RegExp(k, 'g'), char_map[k]);
        }
    }

    // Replace non-alphanumeric characters with our delimiter
    var alnum = (typeof(XRegExp) === 'undefined') ? RegExp('[^a-z0-9]+', 'ig') : XRegExp('[^\\p{L}\\p{N}]+', 'ig');
    s = s.replace(alnum, opt.delimiter);

    // Remove duplicate delimiters
    s = s.replace(RegExp('[' + opt.delimiter + ']{2,}', 'g'), opt.delimiter);

    // Truncate slug to max. characters
    s = s.substring(0, opt.limit);

    // Remove delimiter from ends
    s = s.replace(RegExp('(^' + opt.delimiter + '|' + opt.delimiter + '$)', 'g'), '');

    return opt.lowercase ? s.toLowerCase() : s;
}
Max
  • 4,965
  • 17
  • 49
  • 64
  • 1
    In the commets someone said "This will not work with use strict in IE11- browsers because of duplicates in char_map object." – BBaysinger Mar 31 '17 at 16:48
6
function slugify(text){
  return text.toString().toLowerCase()
    .replace(/\s+/g, '-')           // Replace spaces with -
    .replace(/[^\u0100-\uFFFF\w\-]/g,'-') // Remove all non-word chars ( fix for UTF-8 chars )
    .replace(/\-\-+/g, '-')         // Replace multiple - with single -
    .replace(/^-+/, '')             // Trim - from start of text
    .replace(/-+$/, '');            // Trim - from end of text
}

*based on https://gist.github.com/mathewbyrne/1280286

now you can transform this string:

Barack_Obama       Барак_Обама ~!@#$%^&*()+/-+?><:";'{}[]\|`

into:

barack_obama-барак_обама

applying to your code:

$("#Restaurant_Name").keyup(function(){
    var Text = $(this).val();
    Text = slugify(Text);
    $("#Restaurant_Slug").val(Text);
});
  • Not sure why this isn't selected as the correct answer. Many of the answers don't count on removing # or ? from the slug - URL's get damaged this way. Even the top-used react libraries don't have this feature implemented. This answer is very simple, yet universal. – Vladimir Marton Jun 21 '19 at 10:22
6

Note: if you don't care about an argument against the accepted answer and are just looking for an answer, then skip next section, you'll find my proposed answer at the end

the accepted answer has a few issues (in my opinion):

1) as for the first function snippet:

no regard for multiple consecutive whitespaces

input: is it a good slug

received: ---is---it---a---good---slug---

expected: is-it-a-good-slug

no regard for multiple consecutive dashes

input: -----is-----it-----a-----good-----slug-----

received: -----is-----it-----a-----good-----slug-----

expected: is-it-a-good-slug

please note that this implementation doesn't handle outer dashes (or whitespaces for that matter) whether they are multiple consecutive ones or singular characters which (as far as I understand slugs, and their usage) is not valid

2) as for the second function snippet:

it takes care of the multiple consecutive whitespaces by converting them to single - but that's not enough as outer (at the start and end of the string) whitespaces are handled the same, so is it a good slug would return -is-it-a-good-slug-

it also removes dashes altogether from the input which converts something like --is--it--a--good--slug--' to isitagoodslug , the snippet in the comment by @ryan-allen takes care of that, leaving the outer dashes issue unsolved though

now I know that there is no standard definition for slugs, and the accepted answer may get the job (that the user who posted the question was looking for) done, but this is the most popular SO question about slugs in JS, so those issues had to be pointed out, also (regarding getting the job done!) imagine typing this abomination of a URL (www.blog.com/posts/-----how-----to-----slugify-----a-----string-----) or even just be redirected to it instead of something like (www.blog.com/posts/how-to-slugify-a-string), I know this is an extreme case but hey that's what tests are for.

a better solution, in my opinion, would be as follows:

const slugify = str =>
  str
  .trim()                      // remove whitespaces at the start and end of string
  .toLowerCase()              
  .replace(/^-+/g, "")         // remove one or more dash at the start of the string
  .replace(/[^\w-]+/g, "-")    // convert any on-alphanumeric character to a dash
  .replace(/-+/g, "-")         // convert consecutive dashes to singuar one
  .replace(/-+$/g, "");        // remove one or more dash at the end of the string

now there is probably a RegExp ninja out there that can convert this into a one-liner expression, I'm not an expert in RegExp and I'm not saying that this is the best or most compact solution or the one with the best performance but hopefully it can get the job done.

Waddah
  • 2,459
  • 1
  • 14
  • 5
  • This has a flaw where converting non-alphanumeric characters to dashes will possibly restore a dash at the beginning of the line. But please don't make it a one liner. This one is easy to understand! – Timo Apr 29 '20 at 17:31
3

I create a plugin to implement in most of languages: http://leocaseiro.com.br/jquery-plugin-string-to-slug/

Default Usage:

$(document).ready( function() {
    $("#string").stringToSlug();
});

Is very easy has stringToSlug jQuery Plugin

Leo Caseiro
  • 1,667
  • 1
  • 22
  • 35
3

For people already using lodash

Most of these example are really good and cover a lot of cases. But if you 'know' that you only have English text, here's my version that's super easy to read :)

_.words(_.toLower(text)).join('-')

Frexuz
  • 4,732
  • 2
  • 37
  • 54
3

Well, after reading the answers, I came up with this one.

const generateSlug = (text) => text.toLowerCase()
                                   .trim()
                                   .replace(/[^\w- ]+/g, '')
                                   .replace(/ /g, '-')
                                   .replace(/[-]+/g, '-');
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
Siraj Alam
  • 9,217
  • 9
  • 53
  • 65
3
$("#Restaurant_Name").keyup(function() {
  var Text = $(this).val();
  Text = Text.toLowerCase();
  Text = Text.replace(/[^a-zA-Z0-9]+/g,'-');
  $("#Restaurant_Slug").val(Text);        
});

This code is working

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
3
function slugify(content) {
   return content.toLowerCase().replace(/ /g,'-').replace(/[^\w-]+/g,'');
}
// slugify('Hello World');
// this will return 'hello-world';

this works for me fine.

Found it on CodeSnipper

Al Quarashi
  • 107
  • 2
2

You can use your own function for this.

try it: http://jsfiddle.net/xstLr7aj/

function string_to_slug(str) {
  str = str.replace(/^\s+|\s+$/g, ''); // trim
  str = str.toLowerCase();

  // remove accents, swap ñ for n, etc
  var from = "àáäâèéëêìíïîòóöôùúüûñç·/_,:;";
  var to   = "aaaaeeeeiiiioooouuuunc------";
  for (var i=0, l=from.length ; i<l ; i++) {
    str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
  }

  str = str.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
    .replace(/\s+/g, '-') // collapse whitespace and replace by -
    .replace(/-+/g, '-'); // collapse dashes

  return str;
}
$(document).ready(function() {
    $('#test').submit(function(){
        var val = string_to_slug($('#t').val());
        alert(val);
        return false;
    });
});
MGE
  • 803
  • 2
  • 12
  • 22
2

You may want to take a look at the speakingURL plugin and then you just could:

    $("#Restaurant_Name").on("keyup", function () {
        var slug = getSlug($("#Restaurant_Name").val());
        $("#Restaurant_Slug").val(slug);
    });
Kornel
  • 4,184
  • 4
  • 28
  • 30
2

More powerful slug generation method on pure JavaScript. It's basically support transliteration for all Cyrillic characters and many Umlauts (German, Danish, France, Turkish, Ukrainian and etc.) but can be easily extended.

function makeSlug(str)
{
  var from="а б в г д е ё ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ы ь э ю я ā ą ä á à â å č ć ē ę ě é è ê æ ģ ğ ö ó ø ǿ ô ő ḿ ʼn ń ṕ ŕ ş ü ß ř ł đ þ ĥ ḧ ī ï í î ĵ ķ ł ņ ń ň ř š ś ť ů ú û ứ ù ü ű ū ý ÿ ž ź ż ç є ґ".split(' ');
  var to=  "a b v g d e e zh z i y k l m n o p r s t u f h ts ch sh shch # y # e yu ya a a ae a a a a c c e e e e e e e g g oe o o o o o m n n p r s ue ss r l d th h h i i i i j k l n n n r s s t u u u u u u u u y y z z z c ye g".split(' ');
 
  str = str.toLowerCase();
  
  // remove simple HTML tags
  str = str.replace(/(<[a-z0-9\-]{1,15}[\s]*>)/gi, '');
  str = str.replace(/(<\/[a-z0-9\-]{1,15}[\s]*>)/gi, '');
  str = str.replace(/(<[a-z0-9\-]{1,15}[\s]*\/>)/gi, '');
  
  str = str.replace(/^\s+|\s+$/gm,''); // trim spaces
  
  for(i=0; i<from.length; ++i)
    str = str.split(from[i]).join(to[i]);
  
  // Replace different kind of spaces with dashes
  var spaces = [/(&nbsp;|&#160;|&#32;)/gi, /(&mdash;|&ndash;|&#8209;)/gi,
     /[(_|=|\\|\,|\.|!)]+/gi, /\s/gi];

  for(i=0; i<from.length; ++i)
   str = str.replace(spaces[i], '-');
  str = str.replace(/-{2,}/g, "-");

  // remove special chars like &amp;
  str = str.replace(/&[a-z]{2,7};/gi, '');
  str = str.replace(/&#[0-9]{1,6};/gi, '');
  str = str.replace(/&#x[0-9a-f]{1,6};/gi, '');
  
  str = str.replace(/[^a-z0-9\-]+/gmi, ""); // remove all other stuff
  str = str.replace(/^\-+|\-+$/gm,''); // trim edges
  
  return str;
};


document.getElementsByTagName('pre')[0].innerHTML = makeSlug(" <br/> &#x202A;Про&amp;вер<strong>ка_тран</strong>с…литеърьации\rюга\nи&ndash;южного&nbsp;округа\t \nс\tёжикам&#180;и&nbsp;со\\всеми&ndash;друзьями\tтоже.Danke schön!ich heiße=КáÞÿá-Skånske,København çağatay rí gé tőr zöldülésetekről - . ");
<div>
  <pre>Hello world!</pre>
</div>
anakod
  • 127
  • 1
  • 4
1

The accepted answer didn't meet my needs (it allows underscores, doesn't handle dashes at the beginning and end, etc.), and the other answers had other issues that didn't suit my use case, so here's the slugify function I came up with:

function slugify(string) {
    return string.trim() // Remove surrounding whitespace.
    .toLowerCase() // Lowercase.
    .replace(/[^a-z0-9]+/g,'-') // Find everything that is not a lowercase letter or number, one or more times, globally, and replace it with a dash.
    .replace(/^-+/, '') // Remove all dashes from the beginning of the string.
    .replace(/-+$/, ''); // Remove all dashes from the end of the string.
}

This will turn ' foo!!!BAR_-_-_baz-' (note the space at the beginning) into foo-bar-baz.

Justin Michael
  • 5,634
  • 1
  • 29
  • 32
1

Yet another one. Short and keeps special characters:

imaginação é mato => imaginacao-e-mato

function slugify (text) {
  const a = 'àáäâãèéëêìíïîòóöôùúüûñçßÿœæŕśńṕẃǵǹḿǘẍźḧ·/_,:;'
  const b = 'aaaaaeeeeiiiioooouuuuncsyoarsnpwgnmuxzh------'
  const p = new RegExp(a.split('').join('|'), 'g')

  return text.toString().toLowerCase()
    .replace(/\s+/g, '-')           // Replace spaces with -
    .replace(p, c =>
        b.charAt(a.indexOf(c)))     // Replace special chars
    .replace(/&/g, '-and-')         // Replace & with 'and'
    .replace(/[^\w\-]+/g, '')       // Remove all non-word chars
    .replace(/\-\-+/g, '-')         // Replace multiple - with single -
    .replace(/^-+/, '')             // Trim - from start of text
    .replace(/-+$/, '')             // Trim - from end of text
}
Lucas Bustamante
  • 15,821
  • 7
  • 92
  • 86
0
//
//  jQuery Slug Plugin by Perry Trinier (perrytrinier@gmail.com)
//  MIT License: http://www.opensource.org/licenses/mit-license.php

jQuery.fn.slug = function(options) {
var settings = {
    slug: 'slug', // Class used for slug destination input and span. The span is created on $(document).ready() 
    hide: true   // Boolean - By default the slug input field is hidden, set to false to show the input field and hide the span. 
};

if(options) {
    jQuery.extend(settings, options);
}

$this = $(this);

$(document).ready( function() {
    if (settings.hide) {
        $('input.' + settings.slug).after("<span class="+settings.slug+"></span>");
        $('input.' + settings.slug).hide();
    }
});

makeSlug = function() {
        var slug = jQuery.trim($this.val()) // Trimming recommended by Brooke Dukes - http://www.thewebsitetailor.com/2008/04/jquery-slug-plugin/comment-page-1/#comment-23
                    .replace(/\s+/g,'-').replace(/[^a-zA-Z0-9\-]/g,'').toLowerCase() // See http://www.djangosnippets.org/snippets/1488/ 
                    .replace(/\-{2,}/g,'-'); // If we end up with any 'multiple hyphens', replace with just one. Temporary bugfix for input 'this & that'=>'this--that'
        $('input.' + settings.slug).val(slug);
        $('span.' + settings.slug).text(slug);

    }

$(this).keyup(makeSlug);

return $this;
    };

This helped me with the same problem !

0
String.prototype.slug = function(e='-'){
  let $this=this
        .toUpperCase()
        .toLowerCase()
        .normalize('NFD')
        .trim()
        .replace(/\s+/g,e)
        .replace(/-\+/g,'')
        .replace(/-+/g,e)
        .replace(/^-/g,'')
        .replace(/-$/g,'')
        .replace(/[^\w-]/g,'');
  return $this
        .toUpperCase()
        .toLowerCase()
        .normalize('NFD')
        .trim()
        .replace(/\s+/g,e)
        .replace(/-\+/g,'')
        .replace(/-+/g,e)
        .replace(/^-/g,'')
        .replace(/-$/g,'')
        .replace(/[^\w-]/g,'');
}

I filtered it twice because more - could be put in because of some unwanted characters

Deliq
  • 1
  • 1
0
<!DOCTYPE html>

<html>

<head>

    <style>

        fieldset.slugify {
            color: #515151;
            border: 1px solid #ccc;
            padding: 15px;
        }

        .slugify legend {
            font-size: 16px;
            font-weight: 600;
            padding: 0 10px;
        }

        .slugify input {
            display: block;
            padding: 8px;
            margin: 8px;
        }

        .slug-output {
            color: #05ab13;
            font-size: 20px;
            font-weight: 500;
        }

    </style>

</head>
 
<body>

    <form>

        <fieldset class="slugify">

            <legend>GeeksforGeeks</legend>

            <label for="slug-source">Input Title: </label>

            <input type="text" value="" id="slug-source" onkeyup="myFunction()" />

            <label for="slug-target">URL Slug: </label>

            <input type="text" value="" id="slug-target" />

            <button type="button" >

                Convert
            </button>       
    
            <p>

                <span class="slug-output">
                    Generated URL Slug
                </span>:

                <span id="slug-target-span"></span>

            </p>

        </fieldset>

    </form>

<script>

    function myFunction() {

        var a = document.getElementById("slug-source").value;

        var b = a.toLowerCase().replace(/ /g, '-')

            .replace(/[^\w-]+/g, '');

        document.getElementById("slug-target").value = b;

        document.getElementById("slug-target-span").innerHTML = b;

    }

</script>

</body>
 
</html>
James Risner
  • 5,451
  • 11
  • 25
  • 47
0

A bit extended version of Taranttini answer - https://stackoverflow.com/a/5782563/14431043

var from = "ªºÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿØĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐőŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſȘșȚț€£OơƯưẦầẰằỀềỒồỜờỪừỲỳẢảẨẩẲẳẺẻỂểỈỉỎỏỔổỞởỦủỬửỶỷẪẫẴẵẼẽỄễỖỗỠỡỮữỸỹẤấẮắẾếỐốỚớỨứẠạẬậẶặẸẹỆệỊịỌọỘộỢợỤụỰựỴỵɑǕǖǗǘǍǎǏǐǑǒǓǔǙǚǛǜ·/_,:;";
var to = "aoAAAAAAACEEEEIIIIDNOOOOOUUUUYTsaaaaaaaceeeeiiiidnoooooouuuuytyOAaAaAaCcCcCcCcDdDdEeEeEeEeEeGgGgGgGgHhHhIiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnnNnOoOoOoOoRrRrRrSsSsSsSsTtTtTtUuUuUuUuUuUuWwYyYZzZzZzsSsTtE--oUuAaAaEeOoOoUuYyAaAaAaEeEeIiOoOoOoUuUuYyAaAaEeEeOoOoUuYyAaAaEeOoOoUuAaAaAaEeEeIiOoOoOoUuUuYyaUuUuAaIiOoUuUuUu------";
0

This is the actual solutions

text.replace(/\./g, ' ').trim().toLowerCase().replace(/ /g,'-').replace(/[-]+/g, '-').replace(/[^\w-]+/g,'');
MD TAREK HOSSEN
  • 129
  • 2
  • 11
-5
private string ToSeoFriendly(string title, int maxLength) {
    var match = Regex.Match(title.ToLower(), "[\\w]+");
    StringBuilder result = new StringBuilder("");
    bool maxLengthHit = false;
    while (match.Success && !maxLengthHit) {
        if (result.Length + match.Value.Length <= maxLength) {
            result.Append(match.Value + "-");
        } else {
            maxLengthHit = true;
            // Handle a situation where there is only one word and it is greater than the max length.
            if (result.Length == 0) result.Append(match.Value.Substring(0, maxLength));
        }
        match = match.NextMatch();
    }
    // Remove trailing '-'
    if (result[result.Length - 1] == '-') result.Remove(result.Length - 1, 1);
    return result.ToString();
}