110

I want to display YouTube videos on my website, but I need to be able to add a unique id for each video that's going to be shared by users. So I put this together, and I have run into a little problem. I am trying to get the JavaScript to add a random string for the div id, but it's not working, showing the string:

<script type='text/javascript' src='jwplayer.js'></script>
<script type='text/javascript'>
function randomString(length) {
    var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'.split('');

    if (! length) {
        length = Math.floor(Math.random() * chars.length);
    }

    var str = '';
    for (var i = 0; i < length; i++) {
        str += chars[Math.floor(Math.random() * chars.length)];
    }
    return str;
}

var div = randomString(8);
</script>

<div id='div()'>This text will be replaced</div>

<script type='text/javascript'>
  jwplayer('div()').setup({
    'flashplayer': 'player.swf',
    'file': 'http://www.youtube.com/watch?v=4AX0bi9GXXY',
    'controlbar': 'bottom',
    'width': '470',
    'height': '320'
  });
</script>
revelt
  • 2,312
  • 1
  • 25
  • 37
sarsar
  • 1,431
  • 4
  • 14
  • 17
  • 1
    Perhaps this would be helpful http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript – Maxx Jul 28 '11 at 14:45
  • I typically just create a global var and increment it :P – Joseph Marikle Jul 28 '11 at 14:48
  • Looks like the OP can generate a random string, but he can't get it into the id of the div. Until I get confirmation I wont post a solution. – Jamiec Jul 28 '11 at 14:49
  • @Jamiec yes that is my problem i cant get it into the divs ID – sarsar Jul 28 '11 at 14:50
  • @sarsar - jQuery or vanilla javascript? – Jamiec Jul 28 '11 at 14:50
  • It seems to me like the DIV needs to be generated dynamically inside the Javascript too and then injected at a set point. You need a wrapper function that does both tasks. You could even pass in the id of the Youtube video you want to display and use that as the unique id of the DIV. Might also be a way of checking the video hasn't been shared already by another user by seeing if the id already exists on the page. Just food for thought. – Adam Jul 27 '15 at 11:47
  • for people copying the code without checking, notice how the string "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz" is incomplete/wrong, e.g. there is a "T" after "WX" and no lowercase "j". Interestingly, you can google this string and find several copies through the years. There is a post from 2010 [here](https://blogs.sap.com/2010/08/12/twibap-the-abap-twitter-api/) with the same exact string... – Devis L. Oct 17 '17 at 22:48

18 Answers18

200

I really like this function:

function guidGenerator() {
    var S4 = function() {
       return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
    };
    return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
}

From Create GUID / UUID in JavaScript?

Community
  • 1
  • 1
Joe
  • 80,724
  • 18
  • 127
  • 145
  • 6
    ... but not really the problem he is asking about :-) – Soren Jul 28 '11 at 15:14
  • 224
    But exactly what I've Googled for :=) – fnkr May 07 '13 at 14:25
  • 9
    Warning: It could create Guid starting with number. Can't use that directly as id. Id should start with _ or letter. :) – Chaitanya Chandurkar Nov 02 '15 at 02:01
  • 3
    @jbyrd, this will guarantee unique id, but it **can't guarantee correct HTMLElement id**. The id for element can't begin from number. http://stackoverflow.com/questions/6860853/generate-random-string-for-div-id/6860916#38086864 – Ihor Dec 28 '16 at 14:25
  • 2
    For anyone stumbling upon here: This is not how real GUIDs work, which may be relevant if used for another purpose. The 13th and 17th hex digits are special and need to be set to 4 and one of {8,9,A,B,C,D}, respectively. https://en.wikipedia.org/wiki/Universally_unique_identifier#Format – The Vee Oct 10 '20 at 13:13
92

2018 edit: I think this answer has some interesting info, but for any practical applications you should use Joe's answer instead.

A simple way to create a unique ID in JavaScript is to use the Date object:

var uniqid = Date.now();

That gives you the total milliseconds elapsed since January 1st 1970, which is a unique value every time you call that.

The problem with that value now is that you cannot use it as an element's ID, since in HTML, IDs need to start with an alphabetical character. There is also the problem that two users doing an action at the exact same time might result in the same ID. We could lessen the probability of that, and fix our alphabetical character problem, by appending a random letter before the numerical part of the ID.

var randLetter = String.fromCharCode(65 + Math.floor(Math.random() * 26));
var uniqid = randLetter + Date.now();

This still has a chance, however slim, of colliding though. Your best bet for a unique id is to keep a running count, increment it every time, and do all that in a single place, ie, on the server.

Alex Turpin
  • 46,743
  • 23
  • 113
  • 145
  • 7
    Dates by themselves are not very random since two users doing the same operation at the same time can get the same date value. If you combine a date with a random number function, you will get something much more unique. – jfriend00 Jul 28 '11 at 15:06
  • Plus the `valueOf` representation is a number, which is not a valid html id (they have to start with an alpha character) – Jamiec Jul 28 '11 at 15:23
  • So remove the answer? It is factually incorrect, so why leave it? – Chris Baker Jan 03 '13 at 20:38
  • 4
    @Chris my answer was not factually incorrect, it just wasn't the best from answers here. I added some things. – Alex Turpin Jan 04 '13 at 17:40
  • 1
    That is an improvement, +1 – Chris Baker Jan 07 '13 at 23:24
  • Date.now() will not work in IE8. Most of the time, this is no loss but it is worth noting as sometimes you are depending on a random number to make other things work. I had a very difficult to track error (in IE8) that was because of this. Also, it is one of the IE8 issues Microsoft forgot to emulate in the IE8 emulation mode (ie. when you use Developer tools in IE11 to test IE8); hence, you'll only see the error in real IE8 browser. (new Date).valueOf() will work though. – Stephen Simpson Mar 03 '15 at 13:24
  • It's not guaranteed to be unique. It is possible - if unlikely - for javascript to make two calls within the same millisecond. You can easily reproduce this with a for loop. So, don't rely on this being unique. – Benubird Mar 09 '15 at 15:40
  • Just want to make a comment that in HTML5, [id's can be numbers.](http://www.w3.org/TR/html5/dom.html#the-id-attribute) `There are no other restrictions on what form an ID can take; in particular, IDs can consist of just digits, start with a digit, start with an underscore, consist of just punctuation, etc.` – dbinott May 07 '15 at 18:00
  • 7
    Collide: `var arr = [Date.now(), Date.now()];`. Easy to reproduce on modern CPUs. – mostruash Mar 22 '16 at 11:50
  • 4
    This is a *very bad* solution to the problem of any type of Id-generation, in particular for the actual question being posed (hinting that the question is not read). It is pretty likely that you'll end up with the same id for two divs (one millisecond is a very long time). The answer from @jfriend00 is much better (in particular the "Another way to do it"). If you're out to get very-likely-not-globally-colliding ids, then a bunch of random alphanums are much better - or just go for GUIDs (UUIDs) like 'Joe' suggests. – stolsvik Jan 08 '17 at 00:08
  • It is really wrong. I just noticed that values do collide very frequently. Vote up for mostruash comment. – Dmitriy Kachko Nov 07 '17 at 16:45
  • Since 2011 computers have gone fast enough that even for what would be particularly slow operations, you would in fact get the same result. I was using it to generate some ids for DOM elements, and it takes several hundred operations to go to the next time it uses the Date call, it even populates the DOM, and I still get the same value; this method isn't reliable at all anymore. – Onza Aug 07 '18 at 08:40
  • I've edited the answer to reflect the recent comments. – Alex Turpin Aug 07 '18 at 21:25
  • Doesn't work within a loop. – Lalnuntluanga Chhakchhuak Jul 01 '22 at 10:49
81

Here is the reusable function to generate the random IDs :

function revisedRandId() {
     return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(2, 10);
}

// It will not start with the any number digit so it will be supported by CSS3

bvmCoder
  • 1,131
  • 9
  • 8
  • This could result in an empty string, which wouldn't be a valid ID. `var lengths = {}, total = 1000000; for(var i = 0; i < total; i++){ var newLength = revisedRandId().length; lengths[newLength] = (lengths[newLength] || 0) + 1; } lengths[0] / total` - it looks like it would give an invalid ID about 0.03% of the time, so not often, but definitely possible. – 1j01 May 25 '18 at 22:55
  • Why do you discard the first 2 digits? – Fábio Jun 11 '18 at 15:02
  • `Math.random().toString(36)` -> `"0.v6doivsvnkg"`. Discarding first two characters is redundant as they are removed with the replace command: `Math.random().toString(36).replace(/[^a-z]+/g, '')` -> `"vdoivsvnkg"`. – Ivan Kovtun Sep 02 '20 at 20:02
33

I think some folks here haven't really focused on your particular question. It looks like the problem you have is in putting the random number in the page and hooking the player up to it. There are a number of ways to do that. The simplest is with a small change to your existing code like this to document.write() the result into the page. I wouldn't normally recommend document.write(), but since your code is already inline and what you were trying do already was to put the div inline, this is the simplest way to do that. At the point where you have the random number, you just use this to put it and the div into the page:

var randomId = "x" + randomString(8);
document.write('<div id="' + randomId + '">This text will be replaced</div>');

and then, you refer to that in the jwplayer set up code like this:

jwplayer(randomId).setup({

And the whole block of code would look like this:

<script type='text/javascript' src='jwplayer.js'></script>
<script type='text/javascript'>
function randomString(length) {
    var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz'.split('');

    if (! length) {
        length = Math.floor(Math.random() * chars.length);
    }

    var str = '';
    for (var i = 0; i < length; i++) {
        str += chars[Math.floor(Math.random() * chars.length)];
    }
    return str;
}

var randomId = "x" + randomString(8);
document.write('<div id="' + randomId + '">This text will be replaced</div>'); 

  jwplayer(randomId).setup({
    'flashplayer': 'player.swf',
    'file': 'http://www.youtube.com/watch?v=4AX0bi9GXXY',
    'controlbar': 'bottom',
    'width': '470',
    'height': '320'
  });
</script>

Another way to do it

I might add here at the end that generating a truly random number just to create a unique div ID is way overkill. You don't need a random number. You just need an ID that won't otherwise exist in the page. Frameworks like YUI have such a function and all they do is have a global variable that gets incremented each time the function is called and then combine that with a unique base string. It can look something like this:

var generateID = (function() {
    var globalIdCounter = 0;
    return function(baseStr) {
        return(baseStr + globalIdCounter++);
    }
})();

And, then in practical use, you would do something like this:

var randomId = generateID("myMovieContainer");  // "myMovieContainer1"
document.write('<div id="' + randomId + '">This text will be replaced</div>');
jwplayer(randomId).setup({
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • This answer's fine too, but I assume that inside that `jwplayer` code should be `div` not `'div()'`. – Jamiec Jul 28 '11 at 15:21
  • @jfriend00 Jamiec is right i need to be able to match the div id with the jw player code here `jwplayer('div').setup({` – sarsar Jul 28 '11 at 15:33
  • Yeah, I had no idea what the jwplayer code was doing or how it worked. I didn't know that was part of the question. Anyway, I looked that up on the web and modified my code so that the div with the random number ID is now passed to the jwplayer setup too. FYI, since CSS IDs are technically not allowed to start with a digit, I also put a letter at the beginning. – jfriend00 Jul 28 '11 at 15:44
  • I added a somewhat simpler way to do this at the end of my answer. A random number is not actually needed in this case, just a monotomically increasing number combined with a unique base string. – jfriend00 Jul 28 '11 at 17:04
  • If you need uniqueness across files, a random ID might be warranted. – aleclarson Feb 19 '15 at 16:21
  • You are missing "Y" in your character list, and have a duplicate "T" instead – Nathan Fox Dec 10 '18 at 23:17
  • @NathanFox - Fixed. Not sure how that happened. – jfriend00 Dec 11 '18 at 02:41
29

i like this simple one:

function randstr(prefix)
{
    return Math.random().toString(36).replace('0.',prefix || '');
}

since id should (though not must) start with a letter, i'd use it like this:

let div_id = randstr('youtube_div_');

some example values:

youtube_div_4vvbgs01076
youtube_div_1rofi36hslx
youtube_div_i62wtpptnpo
youtube_div_rl4fc05xahs
youtube_div_jb9bu85go7
youtube_div_etmk8u7a3r9
youtube_div_7jrzty7x4ft
youtube_div_f41t3hxrxy
youtube_div_8822fmp5sc8
youtube_div_bv3a3flv425
oriadam
  • 7,747
  • 2
  • 50
  • 48
19

I also needed a random id, I went with using base64 encoding:

btoa(Math.random()).substring(0,12)

Pick however many characters you want, the result is usually at least 24 characters.

Staale
  • 27,254
  • 23
  • 66
  • 85
  • i like how it always starts with 'MC4' (meaning '0.') because it makes sure the id doesn't start with a number. – oriadam Nov 07 '21 at 07:42
  • i'd use it like that instead: `btoa(Math.random()).replace(/=/g,'')` because you shouldn't put '=' in there. – oriadam Nov 07 '21 at 07:42
14

Based on HTML 4, the id should start from letter:

ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods (".").

So, one of the solutions could be (alphanumeric):

  var length = 9;
  var prefix = 'my-awesome-prefix-'; // To be 100% sure id starts with letter

  // Convert it to base 36 (numbers + letters), and grab the first 9 characters
  // after the decimal.
  var id = prefix + Math.random().toString(36).substr(2, length);

Another solution - generate string with letters only:

  var length = 9;
  var id = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, length);
Ihor
  • 3,219
  • 2
  • 18
  • 20
5

Or you could use Cripto since it's already built in(except in IE11, I swear these guys havent updated in years!)

https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#Examples

var id = new Uint32Array(10);
window.crypto.getRandomValues(id);

I also found this:

https://gist.github.com/6174/6062387#gistcomment-3255605

let length = 32;
let id = crypto.randomBytes(length).toString("base64");

There's a lot of ways to do this, but for most people, there's no reason to reinvent the wheel :)

Jaacko Torus
  • 796
  • 7
  • 24
5

For generating random ids, you can also use the standard crypto API with its randomUUID() function which is available in node.js (>=v16.7.0) and all relevant browsers:

const uuid = crypto.randomUUID()
console.log(uuid)
// prints e.g. "7f3f4512-fcf9-45fe-b726-512bba403426"
Kim Kern
  • 54,283
  • 17
  • 197
  • 195
4

A edited version of @jfriend000 version:

    /**
     * Generates a random string
     * 
     * @param int length_
     * @return string
     */
    function randomString(length_) {

        var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz'.split('');
        if (typeof length_ !== "number") {
            length_ = Math.floor(Math.random() * chars.length_);
        }
        var str = '';
        for (var i = 0; i < length_; i++) {
            str += chars[Math.floor(Math.random() * chars.length)];
        }
        return str;
    }
jfriend00
  • 683,504
  • 96
  • 985
  • 979
dude
  • 5,678
  • 11
  • 54
  • 81
3

I would suggest that you start with some sort of placeholder, you may have this already, but its somewhere to append the div.

<div id="placeholder"></div>

Now, the idea is to dynamically create a new div, with your random id:

var rndId = randomString(8); 
var div = document.createElement('div');
div.id = rndId
div.innerHTML = "Whatever you want the content of your div to be";

this can be apended to your placeholder as follows:

document.getElementById('placeholder').appendChild(div);

You can then use that in your jwplayer code:

jwplayer(rndId).setup(...);

Live example: http://jsfiddle.net/pNYZp/

Sidenote: Im pretty sure id's must start with an alpha character (ie, no numbers) - you might want to change your implementation of randomstring to enforce this rule. (ref)

Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • do i have to worry about the jw player javascript this part in particular `jwplayer('placeholder').setup({` – sarsar Jul 28 '11 at 15:12
  • @sarsar - I dont follow your question! I just added that part to show you you can re-use the `rndId` variable in your code to do with setting up jwplayer. – Jamiec Jul 28 '11 at 15:13
  • for that jwplayer code i need to place the same id for the div inside this code as well – sarsar Jul 28 '11 at 15:30
  • @sarsar - thats exactly what I demonstrated above. `rndId` contains the randomly generated code. – Jamiec Jul 28 '11 at 15:33
2

May I an share an intuitive way to generate a randomID ?

const getRandomID = (length: number) => {
    let text = '';
    const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

    for (let i = 0; i < length; i++) {
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
    return text;
}
Piyush Mahapatra
  • 213
  • 2
  • 13
2

Here is an easy one liner:

const generateUniqueID = (idLength) => [...Array(idLength).keys()].map((elem)=>Math.random().toString(36).substr(2, 1)).join("")

Where all you do is enter the idLength and it will return a unique id of that length.

generateUniqueID(23)
    
>>>'s3y9uebzuo73ih79g0s9p2q' // Id of length 23
Saaasaab
  • 31
  • 3
1

window.btoa(String.fromCharCode(...window.crypto.getRandomValues(new Uint8Array(5))))

Using characters except ASCII letters, digits, '_', '-' and '.' may cause compatibility problems, as they weren't allowed in HTML 4. Though this restriction has been lifted in HTML5, an ID should start with a letter for compatibility.

Denis Giffeler
  • 1,499
  • 12
  • 21
  • this brings results that starts with a number, includes `+` and `=` chars... may i suggest this flavor: `'id'+window.crypto.getRandomValues(new Uint32Array(1))[0].toString(36)` – oriadam Feb 18 '20 at 07:54
1

First. Assign an id to your div. Like this:

<div id="uniqueid">This text will be replaced</div>

After that, add inside your <script> tag following code:

Document.getElementById("uniqueid").id = randomString(8);
vsushkov
  • 2,445
  • 1
  • 19
  • 28
1
function id(prefix = '', length = 7) {
    let result = prefix;
    for(let i = 0; i < length; i++) {
        const random = Math.random();
        result += String.fromCharCode(Math.floor(random * 26) + (random < .5 ? 65 : 97));
    }
    return result;
}

a random number between 0 and 25 is generated then added to either 65 or 97. When added to 65 it will give you an ascii code for a capital letter and when added to 97, an ascii code for a small letter.

Kim Kern
  • 54,283
  • 17
  • 197
  • 195
Slev7n
  • 343
  • 3
  • 14
  • Please explain your code. Code only answers to not very useful – mousetail Oct 05 '21 at 07:13
  • a random number between 0 and 25 is generated then added to either 65 or 97. When added to 65 it will give you an ascii code for a capital letter and when added to 97, an ascii code for a small letter. I hope this helps. – Slev7n Oct 05 '21 at 08:44
  • Please [edit] your answer, don't post in a comment – mousetail Oct 05 '21 at 08:48
0

Just use built-int crypto.randomUUID() which is supportted by all major browsers:

let uuid = crypto.randomUUID();
console.log(uuid);
SeyyedKhandon
  • 5,197
  • 8
  • 37
  • 68
0

Putting all the great solutions here together:

/** @type {Set<string>} */
const generatedUIDs = new Set();

/**
 * @param {string} [prefix='x'] Prefix all UIDs by string to apply a namespace or ensure starts with [A-Z] character
 * @param {number} [n] Maximum number of variations needed. Calculated as 36^n.
  @return {string} */
function generateUID(prefix = 'x', n = 3) {
  let id;
  while (generatedUIDs.has(id = Math.random().toString(36).slice(2, n + 2)));
  generatedUIDs.add(id);
  return `${prefix}${id}`;
}

Reasoning:

  • Math.random() is not guaranteed to be unique and must be checked against pregenerated values.
  • crypto.randomUUID is not available on 99% of browsers (Safari was last to implement)
  • crypto.randomUUID is much slower than just a Random number
  • Each character is 36 variations. Unlikely to need more than 36^3 (46,656) unique ids/classes on a single DOM page (though you can increase this).

If you want to crypto.randomUUID, you can compress a bit by converting the hexadecimal values (base16) to base 36. Still, you have to prefix to ensure it starts with [A-Z]:

  return `x${crypto.randomUUID().split('-').map((n) => Number.parseInt(n, 16).toString(36)).join('')}`;

This skips the need to build a Set to prevent collisions, but it's still slower and longer than you probably need it to be. Even if Math.random() collides, it's faster to just regenerate.

Perf link

ShortFuse
  • 5,970
  • 3
  • 36
  • 36