generate random string for div id - javascript

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>

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?

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.

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

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

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

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.

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

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

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

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 except Safari:
const uuid = crypto.randomUUID()
console.log(uuid)
// prints e.g. "7f3f4512-fcf9-45fe-b726-512bba403426"

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)

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

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

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

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.

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.

Just use built-int crypto.randomUUID() which is supportted by all major browsers:
let uuid = crypto.randomUUID();
console.log(uuid);

Related

Javascript Count numbers

This probably is a very easy solution, but browsing other questions and the internet did not help me any further.
I made a javascript function which will give me a random value from the array with its according points:
function random_card(){
var rand = Math.floor(Math.random()*cards.length);
var html = "card: "+cards[rand][0]+"<br/>points: "+cards[rand][1]+"<br/><br/>";
document.getElementById("Player").innerHTML += html;
var punten = cards[rand][1];
document.getElementById("Points").innerHTML += punten;
}
I've added a += punten so i can see that it works correctly. It shows me all the point in the div with the id Points.
But what i wanted to do is count it all together so if i were to draw a 4, King and a 10 it should show 24 instead of 41010.
Thanks in advance! And if you're missing any information please let me know
Currently you are just adding strings together, which concatenate (join together) hence why you end up with 41010. You need to grab the current innerHTML (total) and use parseInt() to convert from a string to a number, then add your new cards that have been chosen, then assign this new value to the innerHTML of your element.
Try the following
function random_card(){
var rand = Math.floor(Math.random()*cards.length);
var html = "card: "+cards[rand][0]+"<br/>points: "+cards[rand][1]+"<br/><br/>";
document.getElementById("Player").innerHTML += html;
var punten = cards[rand][1];
var curPoints = parseInt(document.getElementById("Points").innerHTML, 10) || 0;
var total = curPoints + parseInt(punten, 10);
document.getElementById("Points").innerHTML = total;
}
More info on parseInt() here
EDIT
I've added this line -
var curPoints = parseInt(document.getElementById("Points").innerHTML, 10) || 0;
Which will try and convert the innerHTML of the "Points" div, but if it is empty (an empty string converts to false) then curPoints will be equal to 0. This should fix the issue of the div being blank at the start.
innerHTML is a string and JavaScript uses + for both string concatenation as numeric addition.
var pointsInHtml = parseInt(document.getElementById("Points").innerHTML, 10);
pointsInHtml += punten;
document.getElementById("Points").innerHTML = punten;
The second parameter 10 of the parseInt method is usually a good idea to keep there to avoid the function to parse it as an octal.
It might be easier to keep a points variable and only at the end put it in the #Points container, that would make the parseInt no longer necessary
innerHTML will be a string, so you need to convert it into an integer prior to adding the card value :)
function random_card(){
var rand = Math.floor(Math.random()*cards.length);
var html = "card: "+cards[rand][0]+"<br/>points: "+cards[rand][1]+"<br/><br/>";
document.getElementById("Player").innerHTML += html;
var punten = cards[rand][1],
curPunten = parseInt(document.getElementById('Points').innerHTML);
document.getElementById("Points").innerHTML = curPunten + punten;
}

Searching for most performant way for string replacing with javascript

I'm programming my own autocomplete textbox control using C# and javascript on clientside. On client side i want to replace the characters in string which matching the characters the user was searching for to highlight it. For example if the user was searching for the characters 'bue' i want to replace this letters in the word 'marbuel' like so:
mar<span style="color:#81BEF7;font-weight:bold">bue</span>l
in order to give the matching part another color. This works pretty fine if i have 100-200 items in my autocomplete, but when it comes to 500 or more, it takes too mutch time.
The following code shows my method which does the logic for this:
HighlightTextPart: function (text, part) {
var currentPartIndex = 0;
var partLength = part.length;
var finalString = '';
var highlightPart = '';
var bFoundPart = false;
var bFoundPartHandled = false;
var charToAdd;
for (var i = 0; i < text.length; i++) {
var myChar = text[i];
charToAdd = null;
if (!bFoundPart) {
var myCharLower = myChar.toLowerCase();
var charToCompare = part[currentPartIndex].toLowerCase();
if (charToCompare == myCharLower) {
highlightPart += myChar;
if (currentPartIndex == partLength - 1)
bFoundPart = true;
currentPartIndex++;
}
else {
currentPartIndex = 0;
highlightPart = '';
charToAdd = myChar;
}
}
else
charToAdd = myChar;
if (bFoundPart && !bFoundPartHandled) {
finalString += '<span style="color:#81BEF7;font-weight:bold">' + highlightPart + '</span>';
bFoundPartHandled = true;
}
if (charToAdd != null)
finalString += charToAdd;
}
return finalString;
},
This method only highlight the first occurence of the matching part.
I use it as follows. Once the request is coming back from server i build an html UL list with the matching items by looping over each item and in each loop i call this method in order to highlight the matching part.
As i told for up to 100 items it woks pretty nice but it is too mutch for 500 or more.
Is there any way to make it faster? Maybe by using regex or some other technique?
I also thought about using "setTimeOut" to do it in a extra function or maybe do it only for the items, which currently are visible, because only a couple of items are visible while for the others you have to scroll.
Try limiting visible list size, so you are only showing 100 items at maximum for example. From a usability standpoint, perhaps even go down to only 20 items, so it would be even faster than that. Also consider using classes - see if it improves performance. So instead of
mar<span style="color:#81BEF7;font-weight:bold">bue</span>l
You will have this:
mar<span class="highlight">bue</span>l
String replacement in JavaScript is pretty easy with String.replace():
function linkify(s, part)
{
return s.replace(part, function(m) {
return '<span style="color:#81BEF7;font-weight:bold">' + htmlspecialchars(m) + '</span>';
});
}
function htmlspecialchars(txt)
{
return txt.replace('<', '<')
.replace('>', '>')
.replace('"', '"')
.replace('&', '&');
}
console.log(linkify('marbuel', 'bue'));
I fixed this problem by using regex instead of my method posted previous. I replace the string now with the following code:
return text.replace(new RegExp('(' + part + ')', 'gi'), "<span>$1</span>");
This is pretty fast. Much faster as the code above. 500 items in the autocomplete seems to be no problem. But can anybody explain, why this is so mutch faster as my method or doing it with string.replace without regex? I have no idea.
Thx!

show only last 4 digits in bank account using javascript

I need help with Javascript. I need to replace however many characters there are previous to the last 4 digits of a text field that contains bank account number. I have searched through the net on this, but cannot find one code that works. I did find a code here on stackoverflow, which was regarding credit card,
new String('x', creditCard.Length - 4) + creditCard.Substring(creditCard.Length - 4);
I just replaced the creditCard with accounNumObject:
var accounNumObject = document.getElementById("bankAcctNum")
The input is pretty simple.
<cfinput type="text" name="bankAcctNum" id="bankAcctNum" maxlength="25" size="25" value="#value#" onblur="hideAccountNum();">
Can anyone help please?
To replace a string with x except for the last four characters in JavaScript, you could use (assuming str holds the string)...
var trailingCharsIntactCount = 4;
str = new Array(str.length - trailingCharsIntactCount + 1).join('x')
+ str.slice(-trailingCharsIntactCount);
jsFiddle.
You could also use a regular expression...
str = str.replace(/.(?=.{4})/g, 'x');
If you want to add the 4 from a variable, construct the regex with the RegExp constructor.
jsFiddle.
If you're fortunate enough to have the support, also...
const trailingCharsIntactCount = 4;
str = 'x'.repeat(str.length - trailingCharsIntactCount)
+ str.slice(-trailingCharsIntactCount);
Polyfill for String.prototype.repeat() is available.
Here is a fiddle showing what you're asking for:
http://jsfiddle.net/eGFqM/1/
<input id='account' value='abcdefghijklmnop'/>
<br/>
<input id='account_changed'/>
var account = document.getElementById('account');
var changed = document.getElementById('account_changed');
changed.value = new Array(account.value.length-3).join('x') +
account.value.substr(account.value.length-4, 4);
Edit: Updated fiddle to correct off by one problem pointed out by alex
Agreed with all above solutions.I just had one another approach.
const maskAccountId = (accountId) => {
if (accountId) { /** Condition will only executes if accountId is *not* undefined, null, empty, false or 0*/
const accountIdlength = accountId.length;
const maskedLength = accountIdlength - 4; /** Modify the length as per your wish */
let newString = accountId;
for (let i = 0; i < accountIdlength; i++) {
if (i < maskedLength) {
newString = newString.replace(accountId[i], '*');
}
}
return newString;
} else return /**Will handle if no string is passed */
}
console.log(maskAccountId('egrgrgry565yffvfdfdfdfdfgrtrt4t4'));

Registering clicks on a button

I have created a button in JavaScript with the following details:
<td id='2,A,B,C' onclick='enterKey(this.id)'>2</td>
When the JS is passed through the function an array is created:
string = string.split(',')
meaning string[0] is 2, string[1] is A and henceforth....
The question I wanted to ask is how do I get JS to register multiple presses on the button.
So if the user presses the twice - they get A instead of 2. If they press it three times - they get B. But if they press is 5 times - it reverts back to 2.
Any advice on how I can achieve this? Many thanks in advance!
First off, you have an invalid ID:
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 (".").
However, assuming you either revise it to use, say, a period or something else, you can track it but just assigning the "click count" to an attribute on the td. For instance:
<script type="text/javascript">
function incCounter(e){
var count = e.getAttribute('data-clicks') || 0,
id = e.getAttribute('data-clickid').split(',');
e.innerHTML = id[++count % id.length];
e.setAttribute('data-clicks', count);
}
</script>
<td data-clickid="2,a,b,c" onclick="incCounter(this);"></td>
Working Demo
Then read the data attribute to determine which element of the "ID array" you need to reference.
A simple solution would be to declare a global variable outside of the method definition, and increment it on each press.
var count = 0;
function enterKey() {
//Split and whatnot here
var myValue = string[count];
count++;
if(count == 5) {
count = 0;
}
}
You would attach it dynamically somehow. So, for example, if you wanted to do this to all <td> elements:
var elements = document.getElementsByTagName('td');
var i, element;
for(i = 0; element = elements[i]; i++) {
(function(element) {
var data = element.getAttribute('data').split(',');
var numClicks = 0;
element.onclick = function() {
enterKey(data[numClicks++ % data.length]);
};
})(element);
}
Note that I used element.getAttribute('data') instead of element.id; #FelixKling is correct, that's an invalid ID.
Something like this?
var count = 0;
function enterKey( string ) {
string = string.split( "," );
return string[(count++) % string.length];
}

What is the most optimized or simplest way to reduce a file name in javascript

I recently created a function in javascript that takes in a file name and a max character limit where the result needs to follow these rules:
Always include file extension
If shrinking occurs, leave the first part and last part of the file name intact.
Always replace the removed characters with '...'
If file length is under the max then do nothing
You can assume the max is a least 5 chars long
Now I've already solved this, but it got me thinking if there is a more elegant or simple way to do this in javascript using regular expressions or some other technique. It also gave me an opportunity to try out jsFiddle. So with that in mind here is my function:
function ReduceFileName(name, max){
if(name.length > max){
var end = name.substring(name.lastIndexOf('.'));
var begin = name.substring(0, name.lastIndexOf('.'));
max = max - end.length - 3;
begin = begin.substr(0,max/2) + '...' + begin.substr(begin.length-(max/2) , max/2 + 1);
return begin + end;
}
return name;
}
And here it is on js Fiddle with tests
I'm not sure that regular expressions will be necessarily more elegant, but so far I came up with the following which passes your tests:
function ReduceFileName(name, max){
if(name.length > max) {
var ell ="\u2026"; // defines replacement characters
var ext = (/\.[^\.]*$/.exec(name) || [""])[0]; // gets extension (with dot) or "" if no dot
var m = (max-ell.length-ext.length)/2; // splits the remaining # of characters
var a = Math.ceil(m);
var z = Math.floor(m);
var regex = new RegExp("^(.{"+a+"}).*(.{"+z+"})"+ext, "");
var ret = regex.exec(name);
return ret[1]+ell+ret[2]+ext;
}
return name;
}
Since I didn't get much activity on this, I'm assuming there isn't a much better way to do this, so I'll consider my method as the answer until someone else comes up with something else.
function ReduceFileName(name, max){
if(name.length > max){
var end = name.substring(name.lastIndexOf('.'));
var begin = name.substring(0, name.lastIndexOf('.'));
max = max - end.length - 3;
begin = begin.substr(0,max/2) + '...' + begin.substr(begin.length-(max/2) , max/2 + 1);
return begin + end;
}
return name;
}

Categories