Javascript (jQuery) if statement rewrite - javascript

I'm writing some JavaScript (with jQuery) that needs to be more flexible. However, I'm not sure how to approach this. This is my code:
var scrollTop = $(this).scrollTop();
var scrollArr = $('.data').html().split(","); // eg. array is 0,80,240,350,380,630
function doIt() {
if (scrollTop<parseInt(scrollArr[0])) {
//$('.scrollShow img').eq(0).removeClass('h')
}
if (scrollTop>parseInt(scrollArr[0])&&scrollTop<parseInt(scrollArr[1])) {
$('.scrollShow .anim').eq(0).addClass('o01s')
}
if (scrollTop>parseInt(scrollArr[1])&&scrollTop<parseInt(scrollArr[2])) {
$('.scrollShow .anim').eq(1).addClass('o01s')
}
if (scrollTop>parseInt(scrollArr[2])&&scrollTop<parseInt(scrollArr[3])) {
$('.scrollShow .anim').eq(2).addClass('o01s')
}
}
The problem is that the amount of elements in the array (scrollArr) will vary each time the doIt() function is run, so if/else statements are not practical in my opinion. What should I replace them with? The code to be executed would be the same (as the above example - with the number increment) and so a flexible function seems more appropriate. Or am I going about this the wrong way? Any input would be appreciated.

for (var i=0; i<scrollArr.length; i++) {
if(scrollTop>parseInt(scrollArr[i])&&scrollTop<parseInt(scrollArr[i+1]))
{
$('.scrollShow .anim').eq(i).addClass('o01s')
}
}

Related

How do I get my function to run when a criteria is met?

I've written some code in JS that's basically supposed to work like a CSS media query and start this slideshow when the viewport width threshold has been crossed. I know it works because it runs when I call the function in the console, but I cannot figure out why it won't just run on it's own as intended.
I'm guessing I've either done something wrong with the responsive part or there's a super basic error somewhere that I've yet to learn.
So far I've tried "window.InnerWidth", I've tried "screen.width" "document.body.clientWidth" and "window.matchMedia" (and to be honest, I would love to know more about each because I'm fairly new to JS).
Here's the snippet:
function resetCards() {
card.forEach(elem => elem.classList.remove("show"));
}
function showCards(index) {
resetCards();
card[index].classList.add("show");
}
function cardSlide() {
var i = 1;
function loop() {
setTimeout(function() {
showCards(i);
i++;
if (i < card.length) {
loop();
} else if (i == card.length) {
i = 0;
loop();
}
}, 4000);
}
loop();
}
function runShow() {
var i = window.matchMedia("(max-width: 1024px)");
if (i.matches) {
cardSlide();
} else {
console.log("Error!");
}
}
runShow();
Your code only checks once. But the good news is that matchMedia returns an object that as a change event you can hook into that gets triggered whenever the result of the media query changes:
function runShow(e) {
if (e.matches) {
cardSlide();
}
}
window.matchMedia("(max-width: 1024px)").onchange = runShow;
If you want it to run once right away, you need to do that proactively:
function runShow(e) {
if (e.matches) {
cardSlide();
}
}
var match = window.matchMedia("(max-width: 1024px)");
match.onchange = runShow;
runShow(match);
Live Example
That example doesn't do anything when the query goes from matching to non-matching. You might want to do something in an else or similar.
The reason it won't check the width after a certain time is because you are using the setTimeout function, this will only run once. If you want it to check multiple times you should use the setInterval function.
You however want to avoid this as it is not accurate / efficient. you could use eventlisteners instead!
Like one of the answers here stated, you are able to use the onchange event of the window.matchMedia object.

Call next iteration after each callback

Lets say I've got the following code,
function someFunction(){
var i = 0;
while (i < 10){
someAsyncProcess(someField, function(err, data){
i++;
// i want the next iteration of the while loop to occur after this
}
}
}
The someAsyncProcess runs, and increments 'i'.
However, due to the async nature of JavaScript, the while loop runs thousands of times before i = 10. What if I want the while loop to run exactly 10 times. What if I want the while loop to execute the code inside only after the callback function has finished executing.
Is it possible to do this without a setTimeout function?
Please note that I am still relatively new to JavaScript so if I incorrectly used any jargon, correct me.
while is synchronous. You cannot make it wait until an asynchronous process is done. You cannot use a while loop in this case.
Instead you can put your code in a function and call the function itself again if the condition is met.
Example:
function someFunction() {
var i = 0;
function step() {
if (i < 10) {
someAsyncProcess(someField, function(err, data) {
i++;
step();
});
}
}
step();
}
There are quite a few libraries out there that provide ready-made solutions for this. You might also want to look into promises in general.
Use node package q which will help you return promises. You can achieve the same in the following manner using q.
var q = require('q');
function someFunction(){
var promises = []
var i = 0;
while (i < 10) {
promises.push(function() {
i++;
//write code here for using current value of i
})
}
return q.all(promises);
}
You can call someFunction() as below
someFunction().then(function(arrayOfResponseFromEachPromiseFunction) {
console.log(JSON.stringify(arrayOfResponseFromEachPromiseFunction, null, 4));
}).catch(function(err){
console.log(err);
}).done();
Please rectify if you find any syntax error. Hope it helps.
You need to use replace while loop Iteration with function recursion
function someFunction() {
var i = 0;
(function asyncWhile() {
if (i < 10) {
someAsyncProcess(someField, function(err, data) {
//You code here
i++;
asyncWhile();
});
}
})(); //auto invoke
}

Break or continue loop within function calls

My question is: How can I trigger a break; or continue; for a loop through a function that gets called? The thing is, I do not want to nest all possible conditions within a loop to avoid code complexity. I was thinking about some pseudo example:
var someObjects = [...] //array with some js objects
for (var i = 0; i < someObjects.length; i++) {
var element = someObjects[i];
doSomething(element);
}
function doSomething(object) {
//some code here
if (somethingIsDefined) {
doSomethingElse(object);
}
}
function doSomethingElse(anotherObject) {
//some more code here
if (somethingMatches) {
//here i would like to break the most upper loop
}
}
//someObjects will be processed
I know that it would be possible to introduce for example a boolean variable and check within the loop if it is true or false and depending on that, break; or continue;.But this - even if it is just one line - would increase the nesting. Do you see any possible solutions?
If you are using the Underscore library, which I recommend, you could write the following:
_.any(someObjects, doSomething);
function doSomething(object) {
//some code here
return somethingIsDefined &&
doSomethingElse(object);
}
function doSomethingElse(anotherObject) {
//some more code here
return somethingMatches;
}

How to use setTimeout in a recursion to avoid browser from getting stuck on complicated processes

I have this code that uses an inefficientProcess() that consumes plenty of memory:
My goal is to use some sort of setTimeout(function(){...},0) technique so the browser will not get stuck while executing the code.
How do I change the code so it will work with setTimeout?
function powerOfTwo(num) {
inefficientProcess();
if (num > 0) {
return powerOfTwo(num-1)*2;
} else {
return 1;
}
}
function inefficientProcess() {
var sum;
for (var i=0; i < 500000; i++) {
sum+=10;
}
}
powerOfTwo(1000);
My goal is ofcourse to learn how to avoid browser crush when executing heavy calculations.
Javascript is single-threaded, and all your code is blocking.
There is a new standard in HTML5, WebWorkers API, that will allow you to delegate your task to a different thread. You can then pass a callback function to be executed with the result.
https://developer.mozilla.org/en-US/docs/DOM/Using_web_workers
Simple example:
function powerOfTwo(num, callback) {
var worker = new Worker('inneficient.js');
worker.postMessage('runTask');
worker.onmessage = function(event) {
var num = event.data.result;
var pow;
if (num > 0) {
pow = Multiply(num-1)*2;
} else {
pow = 1;
}
callback(pow);
};
}
powerOfTwo(1000, function(pow){
console.log('the final result is ' + pow);
});
in inneficient.js you have something like:
//inneficient.js
function inefficientProcess() {
var sum;
for (var i=0; i < 500000; i++) {
sum+=10;
}
postMessage({ "result": sum});
}
inefficientProcess();
As was mentioned in Andre's answer, there's a new HTML5 standard that will allow you to set off a task on a different thread. Otherwise, you can call setTimeout with a time of 0 to allow the current execution path to finish (and perhaps some UI changes to render) before the inefficientProcess is called.
But whether you can use HTML5 or not, the powerOfTwo function has to be changed to be asynchronous - whoever calls it needs to provide a callback method that will be called when (a) a thread spun up via WebWorkers returns, or (b) the setTimeout method finishes.
Edited to add example:
function powerOfTwo(num, callback)
{
setTimeout(function ()
{
inefficientProcess();
if (num > 0)
callback(Multiply(num-1)*2);
else
callback(1);
}, 0);
}
function inefficientProcess() { ... }
The HTML element allows you to define when the JavaScript
code in your page should start executing. The “async” and “defer”
attributes were added to WebKit early September. Firefox has been
supporting them quite a while already.
Saw that on this Site

google script (JS) - maximum recursion depth

What is the maximum recursion depth in Google Apps Script scripts? I have a function, match_recurse, which looks like the following pseudocode:
function match_recurse(array) {
for (i=0, i<3, i++) {
var arr2 = array.copy().push(i);
if (is_done(arr2)) break;
match_recurse(arr2);
}
}
(It also returns its results, but I don't want to bloat the question.)
Now, because the execution errored, the execution transcript and the logs were not saved, so I have no way of knowing whether my is_done function is doing its job wrong. I can do a few cases of the problem on paper and check recursion depth, but I don't know what the maximum is supposed to be.
Looking on the web, I saw an article mentioning that IE has a max call stack of 13 if you go through the Window object, but nothing else.
It is 1000, as one can see from here:
function recurse(i) {
var i = i || 1;
try {
recurse(i+1);
} catch (e) {
Logger.log(i);
}
}
The stack depth value is not documented. Executing the following code shows that this value is equal to 1000.
function getStackDepth(curvalue) {
try {
curvalue = getStackDepth(curvalue) + 1;
}
catch(err) {
}
return curvalue;
}
function test() {
var depth = getStackDepth(2);
debugger;
}

Categories