combining text into a variable name in javascript - javascript

i have looked for an answer to this, but im also not sure im using the correct wording to give me a good search result. So without further adoo.
I am trying to make a random name generator in JavaScript, and I don't want a 300 line switch if it can be avoided. No Jquery if it can be avoided, mainly as i want to learn how to code in JS, for no other reason than that. But if i have to use Jquery, so be it. Learning and all.
The idea is that the script will take the race, gender, then randomly select the first name, surname and proffesion from an array. I can get this to work in IF statements and switches. But I want to try it on as little code as possible. The example below is for humans, but the idea is to pretty much use any fantasy race... dwarves, elves... yes its for dungeons and dragons. Maybe later on use JSON for the array data, but that's later.
var HumanFemale = ["Diane","Laura","Amy"];
var HumanMale = ["Steve","Dave","Tony"];
var HumanS = ["Druss","Hale","Taylor"];
var Proff = ["Theif","Mercenary","Soldier"];
function chargen(race,gender){
var x = race.concat(gender);
var xs= race.concat('S');
document.getElementById("OutputR").innerHTML= race;
document.getElementById("OutputG").innerHTML= gender;
document.getElementById("OutputF").innerHTML= x[Math.floor(Math.random()*x.length)];
document.getElementById("OutputS").innerHTML=xs[Math.floor(Math.random()*xs.length)];
document.getElementById("OutputJ").innerHTML=Proff[Math.floor(Math.random()*Proff.length)];
}
Maybe I need dynamic variables, but i'm not sure how to convert text into a var name.
Thanks

I think an object probably makes your life a little easier, but the idea is generally the same as what you appear to have.
In JavaScript you can reference a property of an object like an array. This means that if you have a property name that can be variable, you can use the array convention to fetch the property instead of the "." convention.
Here's an example:
var example = {
"first": "hello",
"second": "world"
}
//Using dot-notation
alert(example.first); //alerts "hello"
alert(example.second) //alerts "world"
//Using array-notation
alert(example["first"]); //alerts "hello"
alert(example["second"]); //alerts "world"
Now, if the property we want is variable, we can't use the dot-notation, but we can use the array-notation:
var prop_name = "second";
//Using dot-notation
alert(example.prop_name); //throws an error (undefined property)
//Using array-notation
alert(example[prop_name]); //alerts "world"
So, if you create essentially a dictionary object, you may find it's easier/more concise to complete your task:
var dict = {
"Human": {
"Male": ["Steve", "Dave", "Tony"],
"Female": ["Diane", "Laura", "Amy"],
"Surname": ["Druss", "Hale", "Taylor"]
},
"Elf": {
"Male": [/* names */],
"Female": [/* names */],
"Surname": [/*names */]
}
}
function rand_attributes(race, gender) {
var first_name_index = Math.floor(Math.random() * dict[race][gender].length),
last_name_index = Math.floor(Math.random() * dict[race]["Surname"].length),
first_name = dict[race][gender][first_name_index],
last_name = dict[race]["Surname"][last_name_index];
//Now first_name and last_name each contain random values
//Do what you need to with those values from here
}
That code is untested, but it should at least conceptually work out.

Here's what I crudely chucked together.
var Proff=["Theif","Mercenary","Soldier"];
var CharacterName={};
CharacterName['human']={};
CharacterName['human']['female'] = new Array('Diane','Laura','Amy');
CharacterName['human']['male'] = new Array('Steve','Dave','Tony');
CharacterName['human']['surname'] = new Array('Druss','Hale','Taylor');
//just add more stuff here!
document.getElementById('OutputR').innerHTML= 'boo';
function chargen(race,gender){
document.getElementById('OutputR').innerHTML= race;
document.getElementById('OutputG').innerHTML= gender;
document.getElementById('OutputF').innerHTML= grabrandom(CharacterName[race][gender]);
document.getElementById('OutputS').innerHTML= grabrandom(CharacterName[race]['surname']);
document.getElementById('OutputJ').innerHTML= grabrandom(Proff);
}
function grabrandom(arrayofvalues){
return arrayofvalues[Math.floor(Math.random()*arrayofvalues.length)];
}
chargen('human','female');
It's nothing special and a couple of bits could be sharpened, but it's functional and gives you the idea on how it could be done.

The solution i got, heavily based on xjstratedgebx's responce.
var names = {
"Human": {
"Female": ["Diane","Laura","Amy"],
"Male": ["Steve","Dave","Tony"],
"Surname": ["Hall","Young","Taylor"]
}
}
function namegen(race,gender){
var firstname = names[race][gender][Math.floor(Math.random() * names[race][gender].length)];
var lastname = names[race]["Surname"][Math.floor(Math.random() * names[race]["Surname"].length)];
document.getElementById("OutputR").innerHTML= "Human";
document.getElementById("OutputG").innerHTML= "Female";
document.getElementById("OutputF").innerHTML= firstname;
document.getElementById("OutputS").innerHTML= lastname;
}

Related

Possible to use placeholders in sys_properties?

Is it possible to create a sys_property value such as:
This incident has been picked up by {person_name} for further investigation
And then in the code use something like:
var assignee = "John Doe";
var prop = gs.getProperty('my_property_name');
// and now replace person_name with the value of assignee variable?
You can use the RecordToHTML API, traditionally it's used for using the fields from a record as the replacement values for the string fields, however, with the help of .setValue(), you can bypass the record arguments and specify your own values. Note for this to work your "variables" in your string need to be wrapped in ${} and not {}:
var prop = gs.getProperty('my_property_name'); // "This incident has been picked up by ${person_name} for further investigation";
var assignee = "John Doe";
var rth = new RecordToHTML(null, null, prop);
rth.setValue("person_name", assignee); // replaces ${person_name} with "John Doe"
var result = rth.toString(); // "This incident has been picked up by John Doe for further investigation"
The above is a little hacky, as it bypasses the record arguments. If you want to go for another appraoch you can create your own function for this. You can firstly put assignee into an object that holds the key person_name and points to your assignee value, then use a function to replace values within {<key>} using the key as the key to index your object:
function interpolate(str, obj) {
return str.replace(/{([^}]+)}/g, function(match, key) {
return obj[key] || match; // if we can't find the key, return the original `{key}`
});
}
var variableMap = {
"person_name": "John Doe" // assignee
};
var prop = gs.getProperty('my_property_name');
var msg = interpolate(prop, variableMap); // "This incident has been picked up by John Doe for further investigation"
There are some other options that you can use that may do what you're after that are also worth looking into. One being using the first arguments of RecordToHTML() and another being gs.getMessage(). RecordToHTML can also be good if you have a particular record that contains the fields you want to replace from your string (note that your fields need to be wrapped in ${}):
var rth = new RecordToHTML("incident", incidentSysId, "This incident has been picked up by ${assigned_to} for further investigation", false);
var result = rth.toString();
There is also gs.getMessage(), which comes close, but it doesn't allow for named "variables" within your string and requires you to use indexes. It also performs a table query / lookup in the sys_ui_message table each time it is called which may be overkill:
// prop = This incident has been picked up by {0} for further investigation
var msg = gs.getMessage(prop, [assignee]);

Push a var in an array

Im fairly new to programming. Mostly I can find the solution to my problems online but not this time. I've found serveral posts about pushing a variable into an array, however when I console.log the array to check if the variable is actually in the array, he doesn't return the name of the variable that I want. What I get back is: [Card, Card], and what I want to see is: [card_Fireball, card_Waterbolt, etc]. The code I use is:
var Deck = [];
function Card(name, type, cost, points, damage, heal){
this.name = name;
this.type = type;
this.cost = cost;
this.points = points;
this.damage = damage;
this.heal = heal;
}
var card_Fireball = new Card("Fireball", "spell", 2, 1, 3, 0);
var card_Waterbolt = new Card("Waterbolt", "spell", 2, 1, 3, 0);
Deck.push(card_Fireball);
Deck.push(card_Waterbolt);
console.log(Deck);
The solution is probably fairly simple but I can't figure it out with my beginner experience :P Thanks for the help!!
You are doing everything correct just replace console.log with following:
console.log(JSON.stringify(Deck));
Access the card names with "Deck[x].name", where x is the index of the card in the array Deck.
To get all the names:
for(i=0;i<Deck.length;i++){
console.log(Deck[i].name);
}
Assuming you name all your cards the same way as you did in your example, you could use this to get the variable names:
for(i=0;i<Deck.length;i++){
console.log('card_' + Deck[i].name);
}
If you want to get an array of the variable names you have used, those are lost on the way.
In case you want an array of the names or any other property, try making a new array and pushing every value to it.
var names = [];
Deck.map(function(v) { names.push(v.name) })
console.log(names);
Output:
["Fireball", "Waterbolt"]

Text search - filter two words in two different objects/arrays

I'm using angularJS for my webapp and I have the following problem. When I use angularjs' filter to search for, let's say "John Smith", my object, which is built as follow ({firstname: 'John', lastname: 'Smith'}), won't be recognized because the first name and the last name are not part of the same key.
Any idea how to make the space to be either a space or a search in other keys (or arrays)?
EDIT:
Per your requirements, I came up with this:
$scope.compFunc = function(actual, expected) {
var expectedSplit = expected.split(' ');
var fullActual;
//Search people for the person the name belongs to
$scope.names.forEach(function(person){
angular.forEach(person, function(name){
if (name === actual) {
fullActual = person;
}
})
})
//create an array from the names object for comparison
var fullActualArray = [];
angular.forEach(fullActual, function(name, key){
if (key != '$$hashKey')
fullActualArray.push(name = name.toLowerCase());
})
fullActualArray.sort();
expectedSplit.sort();
return actual.toLowerCase().indexOf(expected.toLowerCase()) > -1||
fullActualArray.join(',') === expectedSplit.join(',');
};
This should work just how you expect.
FIDDLE
Note: I used forEach for the sake of clarity, but if you have large amounts of data you may want to change it to for loops, which are 90% faster and can break when a match is found.
Previous solutions:
It's very simple, checks if either the value entered in the search (expected) exists in either firstname or lastname (actual), or the opposite. So entering "Robert Downy" should work, but so will "Robert blargh" or "abcDownyefg". Checking against the whole thing (firstname + lastname) is something that you have to do outside the comparison function, and is not supported out of the box with angular as far as I know.
I've also used the following to create a new array for comparison using the full names:
$scope.fullnames = $scope.names.map(function(name){
return {
firstname: name.firstname,
lastname: name.lastname,
fullname :name.firstname + " " + name.lastname
}
})
While extending the original array can be done like this:
$scope.names.forEach(function(name){
angular.extend(name,{fullname:name.firstname + " " + name.lastname});
})
This is simple and effective, and is what I would do.
You can create your own custom filter, and have it search whatever you want.

passing an index value to a javascript namespaced array

As part of a joomla site, I have a fair number (>20) of quite long arrays (~50 elements) of English sentences located in several files. These arrays are to be accessed by jquery click events which will display the sentences as examples of English word use.The click event functionality which generates the array indices for individual sentences is working. I want to namespace the arrays using a module pattern. According to
http://www.2ality.com/2011/04/modules-and-namespaces-in-javascript.html, module definitions can be spread over several locations. This would be very useful from the point of view of module scalability. I've modified a module from the above article, thus:
var namespace = function() {
var index = 2; // for example
var arr = ["the boy is going home",
"You and I are friends",
"He has a book of mine"];
return {
get values() {
return arr[index];
}
};
}();
console.log(namespace.values);
This works as far as it goes. However, I want to pass an array index to the module and have it return the corresponding text. How can this be done?
var namespace = function() {
var arr = ["the boy is going home",
"You and I are friends",
"He has a book of mine"];
return {
values: function(index) {
return arr[index];
}
};
}();
console.log(namespace.values(1));
So when the IIFE returns the objet properties for namespace, we make values a function (method) and pass in the index. Once the IIFE executes you could think of it like this;
var namespace = {
values: function(index) {
return arr[index];
}
}
but with the initialised arr array.
Try this:
namespace = function() {
this.index = 2; // for example
this.arr = ["the boy is going home",
"You and I are friends",
"He has a book of mine"];
};
namespace.prototype.getValueAt = function(index){
return this.arr[index];
};
console.log(namespace.getValueAt(0));

How to add a new item to struct in JavaScript?

I have a struct in JavaScript
settings = {
"type-1": {
"setting-1": true,
"setting-2": 2
}
"type-2": {
"setting-3": "value",
}
};
I can modify the items:
settings["type-1"]["setting-1"] = false;
But how can I add a new item in this struct?
Trying
settings["type-new"]["setting-100"] = "new one";
But settings["type-new"] is undefined. So how to add a new one?
you can do it on one line:
settings["type-new"] = {"setting-100": "new one"}
You need to set settings["type-new"] to an object first.
settings["type-new"] = {};
settings["type-new"]["setting-100"] = "new one";
Dogbert got it right, since you're using object literals (that's what they're called, not structs :P), you have to create them, before you can assign values to them. Doing settings["type-new"]["setting-100"] = "new one"; is equivalent to undefined["setting-100"] = "new one";. That's why it doesn't work.
On the side, you're really better off not using dashes in your keys, I find it easier to write code like yours along the lines of:
settings.typeNew.setting100 = "new one";
Which is more intuitive (the [""] notation is very serviceable in cases where the property name is the value of a variable, and you -rightly so- don't want to use eval).

Categories

Resources