setInterval inside setTimeout not working... why? - javascript

I'm trying to make an element change opacity based on a series of values pre-set on an array. That action should begin after the user clicks a button AND the system waits for a second.
Here's what I got:
<script>
$(function() {
$("#Listening").click(function() {
setTimeout(triggerListening, 1000);
function triggerListening()
{
document.getElementById("listening").className = "listeningIn";
}
setTimeout(triggerUserTalking, 2000);
function triggerUserTalking()
{
var audioSim = [3, 2, 7, 15, 15, 16, 15, 7, 7, 3, 8, 8, 17, 17, 20, 20, 21, 21, 17, 17, 13, 13, 12, 12, 13, 13, 16, 16, 18, 18, 17, 17, 16, 16, 14, 10, 11, 11, 15, 15, 16, 16, 15, 15, 14, 14, 13, 13, 13, 13, 15, 15, 23, 44, 55, 55, 56, 55, 44, 44, 33, 29, 31, 31, 42, 50, 60, 63, 60, 54, 39, 39, 30, 28, 30, 30, 33, 33, 36, 39, 38, 38, 33, 16, 6, 6, 5, 7, 18, 18, 28, 31, 28, 28, 26, 26, 23, 22, 23, 23, 25, 28, 28, 28, 27, 27, 28, 28, 28, 28, 28, 28, 27, 27, 28, 28, 35, 35, 43, 43, 49, 54, 56, 55, 43, 36, 26, 28, 31, 52, 65, 70, 68, 68, 51, 45, 41, 41, 38, 40, 49, 49, 57, 58, 58, 31, 42, 42, 46, 51, 55, 55, 54, 42, 33, 31, 37, 37, 45, 46, 42, 42, 37, 38, 38, 41, 41, 44, 44, 46, 48, 47, 47, 43, 44, 44, 47, 47, 49, 49, 48, 45, 44, 44, 44, 44, 45, 45, 44, 44, 43, 39, 36, 34, 35, 59, 59, 85, 93, 98, 98, 100, 95, 67, 67, 43, 36, 34, 34, 39, 51, 62, 62, 68, 76, 75, 75, 50, 36, 27, 20, 18, 36, 57, 57, 52, 48, 43, 44, 49, 50, 50, 49];
var i = 0;
window.setInterval('step()', 20)
function step() {
var element = document.getElementById("listening");
element.style.opacity = "0." + audioSim[i];
i++;
if (i == audioSim.length) i = triggerStopTalking;
}
function triggerStopTalking()
{
document.getElementById("listening").className = "listeningOut";
}
}
});
});
</script>
This works fine expect the changing opacity part...
User clicks Listening and after 1 second the listening object appears on the screen by toggling the "listeningIn" class... after another second that element should change opacity a bunch of times based on the values inside "audioSim"... but it doesn't...
I've tested the setInterval code in a separate html file and it works fine... so I'm thinking I can't have a setInterval inside a setTimeout function? Help?

You're passing a string to setInverval.
Don't do that.
setInterval is evaling your string in the global scope; step() is a local variable. Therefore, it doesn't find anything.
Instead, you need to pass the function itself:
setInterval(step);

Instead of
window.setInterval('step()', 20);
try
window.setInterval(step, 20);
I believe the text version will be evaluated on the global scope where step may not exist.

In the line:
> window.setInterval('step()', 20)
setInterval is executed in a global context, but step is declared inside another context that window can't access. Change it to:
setInterval(step, 20)
so that you pass a reference to the function instead.

Related

reduce the size of a javascript array while keeping members that are evenly distributed in the original

Hard to put into words but I am looking for a function that takes an array and reduces it down to a given size. The use case is specifying ticks for graph in d3.
const availableDatetimes: Date[] = [...]
const numberOfXTicks = chartWidth / 80
const tickValues = reduceArrSize(availableDatetimes, numberOfXTicks)
the result should have evenly distributed dates
I called it shrinkArray(), because reducing an array is the name of a different well-defined operation. Here it is:
const shrinkArray = (array, size) => {
const step = array.length / size
return array.filter((v, i) => Math.floor(i % step) == 0)
}
Let's shrink an array of size 100 to size 33:
const originalArray = (new Array(100).fill(0)).map((v, i) => i)
const shrunkenArray = shrinkArray(originalArray, 33)
console.log(shrunkenArray);
console.log(shrunkenArray.length == 33);
So:
[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99
]
is shrunken to:
[
0, 4, 7, 10, 13, 16, 19, 22, 25,
28, 31, 34, 37, 40, 43, 46, 49, 53,
56, 59, 62, 65, 68, 71, 74, 77, 80,
83, 86, 89, 92, 95, 98
]
that is of size 33.
In this example the array is integers from 0 to 99, but obviously the function works for any data type.

JavaScript - How do I dynamically assign a new key value pair to an object, using object-literal, and bracket notation, spread syntax in a one-liner?

I want to dynamically specify negative values as seen in this exact question.
Rules for unquoted JavaScript Object Literal Keys?
I want to also accomplish this using some method of dynamic bracket notation, using a string equivalent of a negative remainder (modulus operation).
bucketObj[key] reports undefined, since I have not pre set a key to store a corresponding value. How do I dynamically set a key of an object in either bracket notation, dot notation, or both?
function toDigitBuckets(array, radix) {
let bucket = JSON.parse(JSON.stringify([...Array(radix).fill([])]));
let bucketObj = Object.assign(bucket);
array.forEach(val => { let key = String.toString(val % 10); bucketObj[key].push(val) });
return bucket;
}
let array = [-7, -49, 84, 39, -31, 95, 7, -8, -13, -32, 93, 40, -81, -30, -57, -57, 49, 66, -64, 42, 35, 29, -57, 41, 93, 34, -45, -15, 51, 16, 97, -88, 52, -69, 56, -16, -91, 51, 10, -21, 80, 78, -5, 18, -20, -98, 72, -94, 11, -83, -31, 13, -21, 39, -47, 8, -98, 95, 52, -18, 77, -11, -38, -46, -98, 48, -45, -4, 76, -32, -81, 67, -82, 9, -60, -20, 0, 33, -12, 77, 65, 45, -22, 99, -47, -83, -81, 10, -99, 16, 23, 5, -57, 89, -62, 9, -16, 79, 5, -2];
let radix = 10;
console.log(JSON.stringify(toDigitBuckets(array, radix)));
You can use Array#reduce with an object as the accumulator. Each time a new key is encountered, first set that property value to be an empty array.
function toDigitBuckets(array, radix) {
return array.reduce((acc, curr) =>
((acc[curr % radix] ??= []).push(curr), acc), {});
}
let array = [-7, -49, 84, 39, -31, 95, 7, -8, -13, -32, 93, 40, -81, -30, -57, -57, 49, 66, -64, 42, 35, 29, -57, 41, 93, 34, -45, -15, 51, 16, 97, -88, 52, -69, 56, -16, -91, 51, 10, -21, 80, 78, -5, 18, -20, -98, 72, -94, 11, -83, -31, 13, -21, 39, -47, 8, -98, 95, 52, -18, 77, -11, -38, -46, -98, 48, -45, -4, 76, -32, -81, 67, -82, 9, -60, -20, 0, 33, -12, 77, 65, 45, -22, 99, -47, -83, -81, 10, -99, 16, 23, 5, -57, 89, -62, 9, -16, 79, 5, -2];
let radix = 10;
console.log(toDigitBuckets(array, radix));
.as-console-wrapper{max-height:100%!important;top:0}

The data from datastream of minio is coming multiple times

The data (in Uint8Array format) from the minio client sometimes comes only once, but other times it comes 3-4 times.
s3Client.getObject(
bucketname,
`folder/file.jpg`,
function(err, dataStream) {
if (err) {
onError();
}
dataStream.on("data", function(data) {
console.log(data, "data");
const urlData = new Blob([data]);
}
}
)
The console is giving me the response:
Uint8Array(65536) [255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 255, 219, 0, 67, 0, 8, 6, 6, 7, 6, 5, 8, 7, 7, 7, 9, 9, 8, 10, 12, 20, 13, 12, 11, 11, 12, 25, 18, 19, 15, 20, 29, 26, 31, 30, 29, 26, 28, 28, 32, 36, 46, 39, 32, 34, 44, 35, 28, 28, 40, 55, 41, 44, 48, 49, 52, 52, 52, 31, 39, 57, 61, 56, 50, 60, 46, 51, 52, 50, 255, 219, 0, 67, 1, 9, 9, 9, 12, 11, 12, …] "data"
Uint8Array(36498) [90, 44, 146, 187, 26, 132, 98, 175, 32, 178, 248, 209, 107, 36, 152, 189, 209, 166, 133, 63, 189, 12, 194, 67, 249, 16, 191, 206, 189, 7, 71, 214, 180, 253, 122, 201, 110, 244, 235, 149, 154, 18, 112, 113, 193, 83, 232, 65, 228, 26, 230, 181, 31, 133, 222, 27, 188, 129, 197, 181, 180, 150, 115, 30, 146, 67, 35, 28, 31, 247, 88, 145, 143, 202, 160, 248, 125, 225, 13, 71, 194, 218, 134, 171, 246, 199, 70, 130, 80, 139, 11, 198, 220, 73, 130, 220, 145, 212, 17, 158, …] "data"
And after refreshing the page for the same image, the console is:
Uint8Array(102034) [255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 255, 219, 0, 67, 0, 8, 6, 6, 7, 6, 5, 8, 7, 7, 7, 9, 9, 8, 10, 12, 20, 13, 12, 11, 11, 12, 25, 18, 19, 15, 20, 29, 26, 31, 30, 29, 26, 28, 28, 32, 36, 46, 39, 32, 34, 44, 35, 28, 28, 40, 55, 41, 44, 48, 49, 52, 52, 52, 31, 39, 57, 61, 56, 50, 60, 46, 51, 52, 50, 255, 219, 0, 67, 1, 9, 9, 9, 12, 11, 12, …] "data"
I am already calling it in useEffect. It is hitting the minio client single time but function (err, dataStream) is not giving consistent data.
Because it appends different chunks of the file each time.
You can get the entire data from dataSteram.on("end", ...)
let size = 0
minioClient.getObject('mybucket', 'photo.jpg', function(err, dataStream) {
if (err) {
return console.log(err)
}
dataStream.on('data', function(chunk) {
size += chunk.length
})
dataStream.on('end', function() {
console.log('End. Total size = ' + size)
console.log(dataStream)
console.log(dataStream.socket._tlsOptions.session)
})
dataStream.on('error', function(err) {
console.log(err)
})
})

Dynamic class name with prefix

I am trying to assign ng-model names dynamicly so that the ng-model names will be able to be accessed in the controller by typing '$scope.numbers.no1', '$scope.numbers.no2' and so on.
So far I am trying this code with no result:
<div ng-repeat="row in numbersArray" class="numbersRow">
<div ng-repeat="num in row" class="number" ng-model="numbers['no' + num]">{{num}}</div>
</div>
in my controller:
$scope.numbers = {};
$scope.numbersArray = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
[21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
[31, 32, 33, 34, 35, 36, 37, 38, 39, 40],
[41, 42, 43, 44, 45, 46, 47, 48, 49, 50],
[51, 52, 53, 54, 55, 56, 57, 58, 59, 60],
[61, 62, 63, 64, 65, 66, 67, 68, 69, 70],
[71, 72, 73, 74, 75, 76, 77, 78, 79, 80]];
and to test I am executing:
$scope.numbers.no1 = 'A';
But nothing happens. What am I doing wrong here?
UPDATE:
What i figured out is that I am mistakenly trying to use an ng-model on a div.
What I am trying to achieve is to pick a random number out of the 80 numbers and make it's background black to show that it was picked.
https://plnkr.co/edit/vT6sU9XnYJsov4q7euwK?p=preview
<div ng-repeat="row in numbersArray" class="numbersRow">
<div ng-repeat="num in row" ng-class="{'clickedNumber': numbers[num]}"
ng-click="numbers[num] = !numbers[num]" class="number">{{num}}</div>
</div>
The code above loops over your $scope.numbersArray, and put it in $scope.numbers (key is input value). Hope it is what you are looking for:
<div ng-repeat="row in numbersArray">
<div ng-repeat="num in row">
<input ng-model="numbers['no' + num]" /> {{num}}
</div>
</div>
Demo on JsFiddle

How to map json array elements to option selected in drop down list?

I have a json array like this
{Id:[1,2,4,5,8,9,14,22,10,11,12,13,20,21,28,30,31,15,23,32,33,34,35,36,37,38,41,16,24,42,43,48,49,17,25,58,59,61,62,63,64,66,67,68,18,26,69,70,74,75,19,27,82,83,85,86,87,88,89,90,91,108,109,110,111,120]}
and want to select corresponding id when an option is selected from select tag which is also dynamic i.e also a json array which is displayed in select tag option as
<select id="list">
<option>--Select--</option>`enter code here`
<option>List gets updated by the json array</option>
</select>
and I have to do it using jQuery/javascript..any help will be appreciated.
Use Array#map method to iterate and generate option element using jQuery. Attach change() event handler to listen the event.
var data = {
Id: [1, 2, 4, 5, 8, 9, 14, 22, 10, 11, 12, 13, 20, 21, 28, 30, 31, 15, 23, 32, 33, 34, 35, 36, 37, 38, 41, 16, 24, 42, 43, 48, 49, 17, 25, 58, 59, 61, 62, 63, 64, 66, 67, 68, 18, 26, 69, 70, 74, 75, 19, 27, 82, 83, 85, 86, 87, 88, 89, 90, 91, 108, 109, 110, 111, 120]
};
$('#list').append(
data.Id.map(function(v) {
return $('<option/>', {
value: v,
text: v
})
})
).change(function() {
console.log(this.value);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="list">
<option>--Select--</option>
</select>
UPDATE : Since you need to get id based on the option selected update your code as follows. Where you can use Array#indexOf method to get the index of the selected element.
var data = {
"StoreName": ["10001 Main ST", "10002 Part1", "10004 MyStore1", "10005 M STR", "10008 Centro", "10009 MyStore 02", "1001 G", "1001 H", "10010 Store main ROAD", "10011 Central M Store", "10012 En Department", "10013 M Station", "10014 Test Center", "10015 SubStore1", "10016 AA", "10018 M part #", "10019 Test A - 26032016", "1002 B", "1002 I", "10020 Test Central B "],
Id: [1, 2, 4, 5, 8, 9, 14, 22, 10, 11, 12, 13, 20, 21, 28, 30, 31, 15, 23, 32, 3, 34, 35, 36, 37, 38, 41, 16, 24, 42, 43, 48, 49, 1, 25, 58, 59, 61, 62, 63, 4, 66, 67, 68, 18, 26, 69, 70, 74, 75, 19, 27, 82, 8, 85, 86, 87, 88, 89, 90, 1, 108, 109, 110, 111, 10]
};
$('#storenm').append(data.StoreName.map(function(v) {
// generate option with value and text content
return $('<option>', {
text: v,
value: v
})
})).change(function() {
console.log(data.Id[data.StoreName.indexOf(this.value)])
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<select id="storenm" name="name">
<option>--Select--</option>
</select>
</body>

Categories