Random Items and linking - javascript

Sorry if the post was unclear, I’ll try to explain as best I can. I’m creating a social psychology experiment online, and I need a function to be able to select at random different names (like John, Mike, Alex etc.). While looking for help online I found this code:
function swapImages(){
var $active = $('#myGallery .active');
var $next = ($('#myGallery .active').next().length > 0) ? $('#myGallery.active').next() : $('#myGallery img:first');
$active.fadeOut(function(){
$active.removeClass('active');
$next.fadeIn().addClass('active');
});})
Using this code and the "mousetrap" library I was able to change the name when a key is pressed. But I have no clue on how I can make the names appear randomly (this means, not in the order they are on the code, but different every time I do it). And after 40 different names, I need to link to another html page.
Thanks for the help, and sorry if my last post was confusing.... This is my first approach to programing :)
Old post:
Im quite new to the programing world, i need some help making this code select random items, not in the order I put them on. Also, i got this from the web and i need it to stop after 40 items and link to antoher page.
Thanks for the help

If you simple need to select random names - selection from array using Math.Random is the simplest approach:
var names = ["John", "Mike", "Peter", "Sid", "Homer"]
var idx;
do {
idx = parseInt(names.length * Math.random());
alert(names[idx]);
names.splice(idx, 1);
} while (names.length > 0)
Basically it generates random index within boundaries of array's length, selects element at that index and then removes the element from array. Loop exits when there're no more elements to display.
Demo: http://jsfiddle.net/4NNTA/1/
If your list has over 40 items and you need to exit after 40 - add a counter and condition to the while. After exiting the loop you can redirect to another page by setting location.href to URL of page you want to go to.
UPDATE This is a function that used revised code above. It lets you specify arbitrary number of names:
var Names = function () {
var data;
var counter;
function initData() {
data = ["John", "Mike", "Peter", "Sid", "Homer"]
}
this.init = function (c) {
counter = c;
initData()
}
this.getName = function () {
if (counter === 0) {
return ""
} else {
if (data.length === 0) initData();
var idx = parseInt(data.length * Math.random());
var sName = data[idx]
data.splice(idx, 1);
counter--;
return sName
}
}
}
Inside of function initData you can specify array of names. Then you initialize it by passing number of names you want to display (this example initializes it to 40):
var myNames = new Names();
myNames.init(40);
And then every time you call
myNames.getName()
It will give you next random name. The names will not repeat until data is exhausted - then the array is reinitialized and random un-repeated names begin again. When all 40 names are retrieved - function returns empty string, which you can check and act accordingly.

Related

(how) can I tell my JavaScript to append a variable/column to the data Qualtrics exports?

I've implemented a task in Qualtrics that randomly selects a number between 0 and 3, and then selects a corresponding word pool to sample 5 words from. To be able to analyze these data, though, I need to know which 5 words (or at minimum, the index number or name of the word pool being sampled from) is presented to each respondent. Is there a way to implement the recording of this information within JavaScript? Ideally this information would show up when I use Qualtrics' native "export" options, but if I have to somehow create a second spreadsheet with this treatment data, that works just fine as well.
Qualtrics.SurveyEngine.addOnload(function()
{
// first, create four arrays for the four word pools used in task
var wordpool1 = []
var wordpool2 = []
var wordpool3 = []
var wordpool4 = []
// assemble word list arrays into one array, with index 0-3
let masterwordlist = [wordpool1, wordpool2, wordpool3, wordpool4]
// function that randomly chooses an integer between x and y
function randomInteger(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// function that shuffles (randomizes) a word list array (Fisher-Yates shuffle )
function shuffle(target){
for (var i = target.length - 1; i > 0; i--){
var j = Math.floor(Math.random() * (i + 1));
var temp = target[i];
target[i] = target[j];
target[j] = temp;
}
return target;
}
// function that chooses 5 words from a shuffled word list array, returns those 5 words as array
function pickWords(target) {
var randomwords = shuffle(target)
return randomwords.slice(0, 5);
}
// top-level function
function genWords(masterlist){
var x = randomInteger(0, 3)
return pickWords(masterlist[x])
}
// actually running the function
randomwords = genWords(masterwordlist)
// save final output as embedded qualtrics data
Qualtrics.SurveyEngine.setEmbeddedData("randomwords", randomwords);
Is there a way I can have this code record (within Qualtrics or otherwise) which values var x or var randomwords take on?
EDIT: I found another answer on here which may be relevant. According to this answer, though, it looks like I have all the code needed to record my variable selection; do I simply need to set embedded data within the survey flow, as well?
See here: Is it possible to save a variable from javascript to the qualtrics dataset?
Yes, you need to define the embedded data field randomwords in the survey flow.

I am trying to stop my function from displaying the same object twice when clicking a button

I have for quite some time now been trying to figure out how I can stop my code to print the same quote twice.
Also, when every single object in the array has been printed out, I'd like for it to reset somehow. So that you can browse through the quotes once you've gone through all of them.
This is the essential parts of my code:
document.getElementById('loadQuote').addEventListener("click", printQuote, false);
The printQuote function simply contains information that's accessing information from my array:
var randomObjectNumber = getRandomQuote();
var html = "<p class='quote'>"
+ quotes[randomObjectNumber].quote +
"</p>";
document.getElementById('quote-box').innerHTML = html;
One random object is displayed each time you click the eventListener:
function getRandomQuote () {
var randomObjectNumber = Math.floor(Math.random() * quotes.length );
return randomObjectNumber;
}
I have some ideas on how to do this and I have tried them but without success. I tried giving each object a boolean property but I can't really seem to assign each property a boolean value without messing the printQuote function up.
I also tried assigning the object displayed to a different array but the same problem occurred there.
I feel like there is some concepts around the eventListener that I don't fully understand, because every time I try to manipulate a displayed object I just end up changing every single object.
This is what a typical object in the array looks like by the way:
{quote : "Darkness is merely the absence of light"}
(I also have other properties assigned to the object but i feel like presenting them would be redundant)
If someone could explain, or give me a hint, on how to solve this problem I've been struggling with for some time.
Some hints would be greatly appreciated!
Have a nice day.
Sebastian.
EDIT: All code: https://jsfiddle.net/fusqb7hz/
Basically what you need:
Create a separate array that will store all quotes that you've already used.
Remove quote from initial array.
Check if you still have quotes in initial array, if not, get them back from backup array.
The problem is that you call addEventListener twice:
//Let's developers create multiple eventListeners without being redundant.
function onClicking (printFunction) {
document.getElementById('loadQuote').addEventListener("click", printFunction, false);
}
onClicking(printColor);
onClicking(printQuote);
by calling onClicking twice you make the click happen twice, so addEventListener is added twice, meaning one click counts as two.
Change the above code for this:
//Let's developers create multiple eventListeners without being redundant.
document.getElementById('loadQuote').addEventListener("click", function(){
printColor();
printQuote();
});
Here is the jsfiddle:
https://jsfiddle.net/fusqb7hz/3/
I think the easiest approach is to shuffle your quote array and then go through them one by one. This gives you the next "random" as yet unseen quote. The only part I'm not keen on is this shuffler (a derivation of Fisher Yates) modifies the original quote array. You might not care about that though.
// --------------------------------
// A bunch of quotes
// --------------------------------
var quotes = [];
quotes.push({quote : "Darkness is merely the absence of light"});
quotes.push({quote : "quote 2"});
quotes.push({quote : "quote 3"});
quotes.push({quote : "quote 4"});
quotes.push({quote : "quote 5"});
// --------------------------------
// --------------------------------
// Your favorite array shuffle utility
// --------------------------------
var shuffle = function(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
};
// --------------------------------
// --------------------------------
// construct a function to get a random unseen quote until
// all quotes have been seen. Then reset...
// --------------------------------
var getQuote = (function(quotes, shuffle){
var current = 0;
var get = function(){
if ( !quotes || !quotes.length ) { return ""; }
if ( current >= quotes.length ){ current = 0; }
if ( current === 0 ){
console.log("randomizing quotes...");
shuffle(quotes);
}
return quotes[current++].quote;
};
return get;
})(quotes, shuffle);
// --------------------------------
var printQuote = function(){
document.getElementById('quote').innerText = getQuote();
};
document.getElementById('loadQuote').addEventListener("click", printQuote, false);
<div id="quote"></div>
<button id="loadQuote">get quote</button>

Is it possible to store both a number and name for a value in an array?

I'm currently writing a function to pre-load all images used by a small game to draw on an array. Currently I store the paths to the sources in two different array to solve this, but would it be possible to have an array that can use both a number i or a name n when getting a value from it? This would help it be easier to use the value to assign as a search on my pictures later on, and using gameimage[153] as a source value doesn't look very tidy and I'd rather use gameimage["snakehead"]
current code example:
//add images to the gameimages array to be loaded before gamestart
//add the snake images
var gameimages = [];
gameimages.push("snake30px.png", "snake30pxdown.png", "snake30pxup.png","snake30pxauch.png");
var gameimagesnumber = gameimages.length;
//start the startGame() when all images in the gameimages array is loaded, to avoid albino snake and lack of stuff to crash into
//NOTE: This is kinda "hackish" as the images is just loaded to make sure it is cached in browser...
//they're not actually used, but seem to have the same effect :x
for(var i = 0; i < gameimagesnumber; i++){
console.log("Loading " + gameimages[i]);
var image = new Image();
image.onload = function(){
//add the image in gameimagesnames for easier use in the code when needed
gameimagesnames[this.src.substring(this.src.lastIndexOf("/") + 1,this.src.length - 4)] = this.src;
checkforgamestart();
};
image.src = "images/" + gameimages[i];
}
//checking for gamestart
function checkforgamestart(){
if(gameimagesnumber > 1) gameimagesnumber--;
else startGame();
}
Absolutely!
In JS, you can make an array of any data type. You also have access to objects. So let's combine those.
var obj = {
name: 'a test name',
value: 1
}
var array = [obj];
array[0].name; // == 'a test name'
array[0].value; // == 1
var anotherObj = {
name: 'another name',
value: 7
}
array.push(anotherObj);
array[1].name; // == 'another name'
array[1].value; // == 7
Reading your question in more detail, I see you're also looking to have a get method that can pull from either value. That's a bit trickier.
The other answer provided will do this, but stores the data in two separate locations in the object (not an array), and also loses the array prototypes.
To better solve this within the Array class type, let's just take advantage of Array.filter!
array.filter(function(item) { return item.name === 'another name' })
This will provide you with a subArray of elements that meet whatever criteria you provide within the given callback function. In this case, using my array above, it would pass back an array with one element in it; anotherObj.
If you want to access by both, use object
var arr = {}
arr[1] = arr['myKey'] = 'myValue'
Then you can access them both by number and by key.

Text Input Value sometimes does't change even though it thows no errors, and seems to work

So I have a simple program to change the value of an input field every time you blur it. It logs the already used values in an array, an I use that array to check if it's been used. It practically works as intended, but after a few tries it will return true and logs, yet the value wont change.
Updated Code:
var dftvalue = ['Freddy the Grocer', 'Jack the Fiddler', 'Cane the Sheep Herder', 'Arnold the Fish Monger', 'Luke the Car Salesman', 'Josh the Tailor', 'Carol the Baker', 'Tiara the Nacho Vendor', 'example#email.com', 'Your message here.'];
var logused = new Array(); //create new array to log the used indexs
function setdftvalue() {
var newval = dftvalue[Math.floor(Math.random() * 7)];
if (logused.indexOf(newval) == -1) {
this.value=newval;
logused.push(newval);
console.log(logused);
} else if (logused.indexOf(newval) >= 0) {
setdftvalue();
}
if (logused.length == 8) {
for (i=0; i<=7; i++){
logused.pop();
}
}
}
document.getElementById('formname').onblur=setdftvalue;
JSFIDDLE
https://jsfiddle.net/e5pdz37e/8/
Your approach is unnecessarily complicated. At a high level I would recommend an approach that's more like this:
function setdftvalue() {
if (index === (dftvalue.length - 1)) {
// Shuffle your names array
index = -1;
}
input.value = dftvalue[++index];
}
This way you won't need to use any recursion and make unnecessary function calls. And the only time you'll need to randomize is when you've used up all of your available names.
Here's a working example: http://jsfiddle.net/bvaughn/163mqdeL/
Original answer
After a few invocations, your function will fill up the logused Array, at which point calling it again will do nothing. Actually, worse than nothing - it will recursively call itself without end.

Should all javascript be put inside a load() on body event?

Should I put all this inside a load() body event so that it loads after the page has rendered and the DOM objects have been created? (I did find I had to use .innerhtml rather than .value for it to work.) If so how...
(*I know this is rubbish code, but it is better than my last attempt and worse than my next attempt. Once I get some time to comeback to this I will recreate it using a literal constructor with internal functions. I am not looking to take this Javascript any further in functionality. The back-end php I have will handle security and checks)
<script type="text/javascript">
//To get the price of a product applying discount
function getPrice(location,quantity)
{
//Get the product choice
var e = document.getElementById("productList["+location+"]");
var productSelected = e.options[e.selectedIndex].value;
//TODO: Determine discounts based on product choice
switch(productSelected)
{
case '0':
return 0;
case '1':
return 10;
case '2':
return 15;
}
return null;
}
//To update product only
function updateProduct(location)
{
updateRow(location,document.getElementById("quantity["+location+"]").value);
}
//To update only that row
function updateRow(location,quantity)
{
//Check Quantity is a valid Number and also not a float or negative
if (!isNaN(quantity) && parseFloat(quantity) && isFinite(quantity) && (quantity >= 0)) {
quantity = Math.floor(quantity);
} else {
quantity = 0;
};
//Update the quantity input field to whatever quantity is - Investigate later!
document.getElementById("quantity["+location+"]").value = quantity;
//Store old Price for changing total
var oldTotal = document.getElementById("totalPrice").innerHTML;
var oldLinePrice = document.getElementById("linePrice["+location+"]").innerHTML;
//Calculate and Store Prices to adjust the total
var productPrice = getPrice(location,quantity).toFixed(2);
var newLinePrice = (quantity*productPrice).toFixed(2);
//Apply Updates
document.getElementById("unitPrice["+location+"]").innerHTML = productPrice;
document.getElementById("linePrice["+location+"]").innerHTML = newLinePrice;
document.getElementById("totalPrice").innerHTML = (oldTotal-oldLinePrice+parseFloat(newLinePrice)).toFixed(2);
}
</script>
You only need to put any getElement calls, or calls to functions that get elements, in a load function.
Well, you could, but that then could delay some js code from getting started working on parts of your .html coding which get loaded first. It also makes code be indented more than it needs to be, causing a readability issue.

Categories