Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
LongSack
Jan 17, 2003

Jabor posted:

If you create a new Auth0Client via the constructor and call getTokenSilently yourself, instead of using createAuth0Client, does that give you more insight into which part is breaking?

TypeScript code:
      //const auth0 = await createAuth0Client(authSettings);
      const auth0 = new Auth0Client(authSettings);
      console.log('auth0 client created');
      auth0.getTokenSilently();
      console.log('gettokensilently called');
      await log(Level.DEBUG, 'Auth0', 'Auth0 Client', auth0);
Doesn't compile now. Not flagged as an error until I start the app, then get the black screen on the browser with this message:
Compiled with problems:

ERROR in ./src/Contexts/AuthContext.tsx 9:0-71

Module not found: Error: Can't resolve '@auth0/auth0-spa-js/dist/typings/Auth0Client' in 'E:\home\Projects\jimco.employeeportal\src\Contexts'


It's definitely there though, and this is happening on my desktop. I'm missing something using the constructor rather than the factory method.

Edit: I changed from using await to calling the factory method directly and using .then(...) and it does exactly the same thing as when using await. Control never seems to return from the factory method. Neither the .then or the .catch blocks are ever called.

LongSack fucked around with this message at 18:20 on May 25, 2022

Adbot
ADBOT LOVES YOU

Janitor Ludwich IV
Jan 25, 2019

by vyelkin
Hi friends,

I'm working heavily with stuff in google sheets and I have been playing around with GAS (google apps script). I know this is based on javascript. I'm wondering if it's worth learning GAS specifically or if I should just learn the latest and greatest edition of javascript?

camoseven
Dec 30, 2005

RODOLPHONE RINGIN'

Janitor Ludwich IV posted:

Hi friends,

I'm working heavily with stuff in google sheets and I have been playing around with GAS (google apps script). I know this is based on javascript. I'm wondering if it's worth learning GAS specifically or if I should just learn the latest and greatest edition of javascript?

I hadn't heard of GAS, but it looks like it IS JavaScript. Not sure you could learn GAS separate from JS

Janitor Ludwich IV
Jan 25, 2019

by vyelkin

camoseven posted:

I hadn't heard of GAS, but it looks like it IS JavaScript. Not sure you could learn GAS separate from JS

I think that answers my question then! From what I read is GAS may be missing some newer syntax as it's mostly built on 1.6 / 1.7. it will also have a lot of Google specific functions.

But I think if I get to know how to do JS logic, loops, declarations I will be in good stead for understanding Google's documentation.

There is definitely a lot newer books for JavaScript but I did find a couple for GAS

camoseven
Dec 30, 2005

RODOLPHONE RINGIN'

Janitor Ludwich IV posted:

I think that answers my question then! From what I read is GAS may be missing some newer syntax as it's mostly built on 1.6 / 1.7. it will also have a lot of Google specific functions.

But I think if I get to know how to do JS logic, loops, declarations I will be in good stead for understanding Google's documentation.

There is definitely a lot newer books for JavaScript but I did find a couple for GAS

https://developers.google.com/apps-script/guides/v8-runtime

It looks like GAS uses V8 by default now, so you can use all the latest features of JS. Like you said there will be functions and stuff specific to the GAS environment, but you would be well served by doing a crash course in JS

LongSack
Jan 17, 2003

Jabor posted:

If you create a new Auth0Client via the constructor and call getTokenSilently yourself, instead of using createAuth0Client, does that give you more insight into which part is breaking?

I was finally able to track down what was causing the error when debugging locally: the auth0.spa.js tool requires a secure connection when not connecting to localhost. Firefox on Linux finally gave me the error. Apparently, chrome on iPad/iPhone just fails silently (I had chrome://inspect open to catch console messages, but it's not really a reliable tool).

Now I'm back to my original error, which is that isAuthenticated() is returning false even when I am authenticated. I suspect it has something to do with the page being rerendered before the authentication flow is complete, but trying to track it down is a nightmare.

Fake Edit: I just downloaded the sample React app from the Auth0 site and it runs just fine. So it's time to rip out all my authentication code and start over with the basics.

N.Z.'s Champion
Jun 8, 2003

Yam Slacker

Rockybar posted:

Took a few hours of head scratching but came up with this solution:
JavaScript code:
      if (JSON.stringify(data2) !== JSON.stringify(data)) {

Probably better to use a deep isEqual comparison function rather than comparing stringifying objects.

The potential issue is key order and how JSON.stringify({a: 1, b: 2}) !== JSON.stringify({b: 2, a: 1}). JSON.stringify won't sort/normalize the order of your keys. Before ES2015 most browsers used key insertion order, but since ES2015 key orders are more complicated.

So to avoid a weird confusing bug (eg refactoring that changes key insertion order) it's probably easier to use a deep equal comparison function.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Had fun playing around with crazy Typescript types today. Not a question, just bragging because I'm impressed with myself.

code:
type TGen<T> = T | (() => T);

export type TBuild<T> = {
    [K in keyof T]: T[K] extends object ? TGen<TBuild<T[K]>> : TGen<T[K]>;
};
export type TOverride<T> = {
    [K in keyof T]?: T[K] extends object ? TGen<TOverride<T[K]>> : TGen<T[K]>;
};
Basically my library accepts some arbitrary structure that accepts functions in place of variables... But I also wanted the developer to be able to define their own type to be returned from it.

So I wrap it in this type that says "ok you want that type out that means we accept this type in".

I needed it to allow nesting, so the alternative "function that returns a specific type" typing needed to apply all the way down the chain. I did something similar for the override later on too. Which is basically "ok you want that type out that means we accept this partial type in". But the partial utility type provided by typescript doesn't support nesting. I combined both into that fancy type "TOverride<T>", note the little question mark.

It works brilliantly. Now my definitions can look insane and it still provides me with the types that I need. It even works perfectly with arrays, I won't question it.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Typescript has just impressed me.

I realized my helper modules needed to return accurate types otherwise it would cause no small amount of headaches. They were using a more generic type but by giving Typescript the chance to do good it has.

code:
export function sequence<T = number> (generator?: (i: number) => TGen<T>): () => T {
    let count = 0;
    const isFunction = typeof generator === 'function';

    return function () {
        count++;
        return (isFunction ? parseValue(generator(count)) : count) as unknown as T;
    };
}
Given this crazy function when no type is given, it is inferring type from the return type of the generator parameter. And that parameter can be a function inside of a function, through some kind of dark arts it still infers it correctly.

code:
        const sequencer = sequence((i) => () => `hello-${i}`);
        const sequencer = sequence((i) => `hello-${i}`);
Both recognize that `sequencer` is a function that returns a string. I'm very impressed.

danishcake
Aug 15, 2004
I'm having a fight with Typescript type guards. If undefined or null is a member of a type union then my type guard always seems to narrow to undefined rather than the full union

JavaScript code:
type ValidValue = '1' | undefined;
function validateValue(value: string | undefined): asserts value is ValidValue {
  if (value !== undefined && value !== '1') {
    throw new Error('Invalid value');
  }
}

// Get a value from some unverified source
const unverifiedValue = ((): string | undefined => {
  return '1';
})();

unverifiedValue; // unverifiedValue inferred to have type string | undefined
validateValue(unverifiedValue);
unverifiedValue; // unverifiedValue inferred to have type undefined. WUT?
Did I miss a fundamental memo somewhere? Why is undefined obliterating the other elements of the type union?

Edit: TS Playground link
https://www.typescriptlang.org/play...igAHUAKoAFQA-EA

danishcake fucked around with this message at 08:52 on Jun 1, 2022

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
I've wanted typescript to add runtime type checking for quite a while.

I want to say something like "check if this is the right type" without all the "if then error" boilderplate. But, considering how complicated types can get like my example above I'm starting to understand why it's not really feasible.

What you wrote looks right. I played around with it and got the union to work with more generic types. The problem I imagine is that you're playing with a beta feature, apparently one I am looking forward to. I didn't kno about it.

I won't have to say "as unknown as Type" anymore.

camoseven
Dec 30, 2005

RODOLPHONE RINGIN'
I'm really confused about what y'all are trying to do. Just using TS and setting things to a type will do all the type checking for you at compile time. Why are you trying to add if statements to do what TS already gives you out of the box?

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Because I'm writing libraries, they can be used by non-typescript users who might input invalid data. You can also just tell typescript to ignore what you're typing, either of which would cause strange failures in my library.

It's easy enough to say "this is what I expect this value to be" and run through the entire application with that assumption. But after it's compiled, in practice, anything can turn up there.

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

Nolgthorn posted:

Because I'm writing libraries, they can be used by non-typescript users who might input invalid data. You can also just tell typescript to ignore what you're typing, either of which would cause strange failures in my library.

It's easy enough to say "this is what I expect this value to be" and run through the entire application with that assumption. But after it's compiled, in practice, anything can turn up there.

That's on the other developer for not using your typescript definitions. They chose to not use typescript and ignore your definitions, why should it be your problem?

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Because I don't have a high opinion of people especially in javascript especially in open source. The issue tracker becomes filled with "this doesn't work" instead of "I get this error that tells me exactly what I'm doing wrong".

The latter requires me to close the ticket and the former requires me to talk to them.

teen phone cutie
Jun 18, 2012

last year i rewrote something awful from scratch because i hate myself
you could always just use a validation lib. yup is popular as all hell

https://github.com/jquense/yup#getting-started

LongSack
Jan 17, 2003

Anyone doing pure front-end code (i.e., React, Angular, View, straight JavaScript) and using a third-party authentication provider, how do you protect your keys?

I've seen all the suggestions:

1. put them in a .env file then add .env to your .gitignore. Works great for keeping the key out of my git repo, but oops - when I go through the CI/CD process it pulls from Git so there's no .env file, and that doesn't work.
2. Use a back-end service to actually make the call, then have your front-end call that. That might work for accessing a weather service, but not for authentication. The whole point is that the user gets redirected to the third party site and I never have to see their credentials.
3. Call a back-end service and request the key. Nope. Anything my front end can do, anyone else can do too.

I realize that there's probably no way to protect the key absolutely since It's is required to initialize the Auth0Provider (I happen to be using React). But I also don't want it in my Git repo.

So is there a good way to (a) keep the key out of my Git repo while (b) still allowing Azure DevOps CI/CD to build and deploy my app?

I do have my Auth0 APIs and Applications locked down pretty tightly in terms of allowed origins, login, and logout urls, so should I even bother? I mean origins can be faked, right?

Thanks

teen phone cutie
Jun 18, 2012

last year i rewrote something awful from scratch because i hate myself

LongSack posted:

Anyone doing pure front-end code (i.e., React, Angular, View, straight JavaScript) and using a third-party authentication provider, how do you protect your keys?

I've seen all the suggestions:

1. put them in a .env file then add .env to your .gitignore. Works great for keeping the key out of my git repo, but oops - when I go through the CI/CD process it pulls from Git so there's no .env file, and that doesn't work.
2. Use a back-end service to actually make the call, then have your front-end call that. That might work for accessing a weather service, but not for authentication. The whole point is that the user gets redirected to the third party site and I never have to see their credentials.
3. Call a back-end service and request the key. Nope. Anything my front end can do, anyone else can do too.

I realize that there's probably no way to protect the key absolutely since It's is required to initialize the Auth0Provider (I happen to be using React). But I also don't want it in my Git repo.

So is there a good way to (a) keep the key out of my Git repo while (b) still allowing Azure DevOps CI/CD to build and deploy my app?

I do have my Auth0 APIs and Applications locked down pretty tightly in terms of allowed origins, login, and logout urls, so should I even bother? I mean origins can be faked, right?

Thanks

typically you just define the variables in your pipeline:

https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch
https://stackoverflow.com/questions/58591548/how-to-set-process-env-var-in-devops-azure-pipeline

LongSack
Jan 17, 2003


Wow that was easy. Thanks!

Edit: After getting it all working, I discover that Auth0 actually uses my client id in the name of it's cookies, so there's no benefit to any kind of obfuscation or whatever. I'll just have to rely on the list of allowed redirect URLs - those for sure work, I've messed them up enough times to know. Keeping the client id out of Git is about the best I can do.

LongSack fucked around with this message at 19:46 on Jun 1, 2022

worms butthole guy
Jan 29, 2021

by Fluffdaddy
Hey there, not sure if anyone has an idea but I have a weird question.

I am using HubSpot which uses a weird Jinja style templating language. In this, I have a javascript "module" that is essentially a image mapper. If I load one instance of this it works perfectly. If I load more than one on the page any additional instances of the module bug out. I'm guessing because the jQuery it uses for this can't have multiple instances?

So I guess my question is:

1. Is there a way to load and unload javascript code depending on like a button click?


I know otherwise I could go through the code and rewrite a different instance per use of the "module" but I imagine there's a way to do this that's more efficient.

Thanks Goons!

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense

Nolgthorn posted:

Had fun playing around with crazy Typescript types today. Not a question, just bragging because I'm impressed with myself.

code:
type TGen<T> = T | (() => T);

export type TBuild<T> = {
    [K in keyof T]: T[K] extends object ? TGen<TBuild<T[K]>> : TGen<T[K]>;
};
export type TOverride<T> = {
    [K in keyof T]?: T[K] extends object ? TGen<TOverride<T[K]>> : TGen<T[K]>;
};
Basically my library accepts some arbitrary structure that accepts functions in place of variables... But I also wanted the developer to be able to define their own type to be returned from it.

So I wrap it in this type that says "ok you want that type out that means we accept this type in".

I needed it to allow nesting, so the alternative "function that returns a specific type" typing needed to apply all the way down the chain. I did something similar for the override later on too. Which is basically "ok you want that type out that means we accept this partial type in". But the partial utility type provided by typescript doesn't support nesting. I combined both into that fancy type "TOverride<T>", note the little question mark.

It works brilliantly. Now my definitions can look insane and it still provides me with the types that I need. It even works perfectly with arrays, I won't question it.

Limitation of this "extends object" stuff from my example. I can't seem to get it to use the type wrapper when object parameters are optional.

playground link

Edit:

I've has success with this: playground link

Using
code:
export type TBuilder<T> = T extends object ? TGen<{
    [K in keyof T]: TBuilder<T[K]>;
}> : TGen<T>;
Instead of
code:
export type TBuilder<T> = {
    [K in keyof T]: T[K] extends object ? TGen<TBuilder<T[K]>> : TGen<T[K]>;
};
At the cost of my confidence, am I doing this right?

Nolgthorn fucked around with this message at 13:08 on Jun 3, 2022

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Sort of, but my input shouldn't allow a method as a parameter, which causes types everywhere to freak out a bit and it isn't the correct interface for the user. What I seem to need is two types.
code:
type TBuilder<T> = T extends object ? TGen<{
    [K in keyof T]: TBuilder<T[K]>;
}> : TGen<T>;

export type TBuilderData<T> = {
    [K in keyof T]: TBuilder<T[K]>;
}>;
Then I say:
code:
export function build<T = TData> (builder: TBuilderData<T>) {
    // app
}
And I seem to get everything I want.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Problem:

By doing the above I'm having a new problem with my "oneOf" helper method. Likely part of a larger problem but it's a fairly clear example of what's going on.

playground link

Given something like:
code:
type TestType = 'hello' | 'there';
type Test = {
    test: TestType;
};

build<Test>({
    test: oneOf('hello', 'there')
});
Value 'test' is expected to be of type `TGen<"hello"> | TGen<"there">` as opposed to type `TGen<"hello" | "there">`.

This causes typescript to believe both are unassignable.

For example `() => 'hello'` is not assignable to `() => 'there'` and vice versa. Ideally It would believe that the value of 'test' is `TGen<"hello" | "there">`, otherwise readable as `"hello" | "there" | (() => "hello" | "there")` but I've melted my brain.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
It looks like your situation is explicitly called out in the docs: https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types

If you make the change it suggests to your TBuilder definition, `test` becomes typed as `TGen<'hello' | 'there'>`, which appears to be what you want in this case.

e: alternatively you might be able to mess around so that the return value of `oneOf` is destructured the same way, which might make things cleaner if you ever have a type that's like, an object or a primitive.

Jabor fucked around with this message at 15:39 on Jun 3, 2022

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
That is so awesome, I don't know how I would have found that. Thanks. It does seem to revert me to the previous problem where `null | object` isn't an object, I'll have to mess around with it more in line with what you said.

I think the right track would be fixing the return type of oneOf.

Edit edit:

The problem is actually with the `test` type.
code:
Type '() => "hello" | "there"' is not assignable to type 'TGen<"hello"> | TGen<"there">'.
  Type '() => "hello" | "there"' is not assignable to type '() => "hello"'.
    Type '"hello" | "there"' is not assignable to type '"hello"'.
      Type '"there"' is not assignable to type '"hello"'
What's being returned from oneOf is of type `() => "hello" | "there"'` and I'm trying to assign it to something of type `() => "hello" | () => "there"`, which Typescript thinks isn't possible due to the fact that `there` is not assignable to type `hello`.

This is very confusing. Sorry for so many posts.

I'm not sure what can be done. Because if test is of type `() => "hello" | "there"'` then objects aren't being handled properly. For example `null | object` does not extend from type `object` and therefore fails it's conditional type check.

Can I tell Typescript to split up a union type into a distributive type? Maybe I could attack this from the opposite direction.

Nolgthorn fucked around with this message at 17:46 on Jun 3, 2022

Tad Naff
Jul 8, 2004

I told you you'd be sorry buying an emoticon, but no, you were hung over. Well look at you now. It's not catching on at all!
:backtowork:
So... What's the modern way to put stuff in the clipboard anymore? I found navigator.clipboard but for some reason the duck duck go browser on Android just hates it and says 'document not focused'. I'm focusing on it right now drat it

echinopsis
Apr 13, 2004

by Fluffdaddy
ok so I am a baby,

on a webpage, what's the accepted way to do an infinite loop

this page is a game, a idle game, so I am constantly calculating countdowns etc

ynohtna
Feb 16, 2007

backwoods compatible
Illegal Hen
window.requestAnimationFrame, or .requestIdleCallback for thematic consistency bonus points.

setInterval, setTimeout for the taste of poorly scheduled trash.

Watch out for fun when browser tabs are backgrounded.

ynohtna fucked around with this message at 11:39 on Jun 5, 2022

Osmosisch
Sep 9, 2007

I shall make everyone look like me! Then when they trick each other, they will say "oh that Coyote, he is the smartest one, he can even trick the great Coyote."



Grimey Drawer

echinopsis posted:

ok so I am a baby,

on a webpage, what's the accepted way to do an infinite loop

this page is a game, a idle game, so I am constantly calculating countdowns etc

Just use while(true) if you're just getting the hang of things.

Or put a stop condition like pressing escape in the while condition.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Osmosisch posted:

Just use while(true) if you're just getting the hang of things.

Or put a stop condition like pressing escape in the while condition.
This option is off the table with javascript.

The more complicated way (but that won't have any weird effects based on tab not having focus) is Web Workers.

The usual way for an idle game is to use one of the callback mechanisms ynohta suggested, and make sure your update loop is of the form "how much time has passed? Update things for that much time" rather than "update things by one unit". That way if the callback doesn't happen for 20 minutes because the tab didn't have focus, when the tab *gets* focus you apply 20 minutes of update and it's all good.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
The best solution to my above duck talk that I've found is:
code:
export type TBuilder<T> = {
    [K in keyof T]: TGen<T[K] extends object ? TBuilder<T[K]> : T[K]>
};
In place of:
code:
export type TBuilder<T> = {
    [K in keyof T]: T[K] extends object ? TGen<TBuilder<T[K]>> : TGen<T[K]>>
};
This essentially is the difference between getting a whole bunch of `() => Type | () => Type` instead of `() => Type | Type`. Everything else I tried had different issues. The only problem I have now is if the user doesn't provide a type to the builder it accepts a nesting of functions.

This is because if the user provides a value of:
code:
const builder = build({
    test: () => 'value'
});
They are saying "this is a string in the resulting type".

But it's inferred as `string | () => 'string'` which means there's no reason you couldn't put `test: () => () => 'value'` in there which is interpreted as `TGen<string | (() => string)>` otherwise read as `string | (() => string) | (() => string | (() => string))` which isn't the end of the world.

My library handles it, it's just weird that's all and might not be very clear what's happening to the developer. It'd be nice to say "yeah this can be a function that returns a string or it can be a string but the type will be a string".

I'm starting to understand why some people get headaches with typescript. Not sure how typescript could be simpler though.

echinopsis
Apr 13, 2004

by Fluffdaddy
so in this game, I have a bunch of "things" to do, which are represented as buttons, and I add then via js

I have a function that makes a button element, gives it a few properties, and the uses getElementById().appendChild() to add the button into the flex box

it works, but one of the things I am trying to add to the button before I put it in the box is an event listener

and it just aint working. I even wait until I have appended the button into the flex container, then using getElementById().addEventListener()

but it just doesn't work, and it doesn't show up in the inspector's event listener thing.

Is there something I need to know about this? is it becasue it's been made from inside a function called by a for each loop? because that's why I try to add the event listener after it's been appended

fakemirage
Nov 6, 2012

Can't see the haters.

echinopsis posted:

Is there something I need to know about this? is it becasue it's been made from inside a function called by a for each loop? because that's why I try to add the event listener after it's been appended
Should be fine to add the event listener before or after adding it to the container, but if you're using getElementById you'll have to make sure that the buttons have unique identifiers.

Do you have any code examples you could post where adding an event listener doesn't work?

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
The html element definitely doesn't need to be in the DOM to attach events to it.

echinopsis
Apr 13, 2004

by Fluffdaddy

fakemirage posted:

Do you have any code examples you could post where adding an event listener doesn't work?

code:
// this function builds the crime windows and places them in the flexbox
function createCrimeWindows(structOfCrimesIterator, buttonIndex) {

    // create a new div that will be added to the flexbox
    var newWindowButton = document.createElement("button");

    // set it's class and give it a unique id
    newWindowButton.className = "crime";
    newWindowButton.id = structOfCrimesIterator.name;

    // create the text that goes in the window
    var newWindowText = structOfCrimesIterator.name;

    // add the text to the div
    newWindowButton.innerHTML = newWindowText;
    
    // append the newly created div to the flexbox
    document.getElementById('crimeID').appendChild(newWindowButton);

    // add function to the button for when it is clicked
   document.getElementById(structOfCrimesIterator.name).addEventListener("click",clickOnCrimeButton(buttonIndex));
}

// this function is called when a crime button is clicked
function clickOnCrimeButton(idOfButton) {
    var buttonText = setOfCrime[idOfButton].name;
    document.getElementById("infoID").textContent = buttonText;
}
I ran a test by doing a .textContent on the buttons via their Id and that worked, and it's not complaining that getelementById is null, so I think I have successfully given them an iD



at the moment this code is meant to put the name of the button, which is also it's id, into another box. I'm just trying to get the button working.

Appreciate any help.

echinopsis fucked around with this message at 19:33 on Jun 7, 2022

fakemirage
Nov 6, 2012

Can't see the haters.
Haven't gone through everything, but I noticed the following line.

echinopsis posted:

JavaScript code:
    // add function to the button for when it is clicked
   document.getElementById(structOfCrimesIterator.name).addEventListener("click",clickOnCrimeButton(buttonIndex));
This will execute the clickOnCrimeButton function and place the result as the event handler. You'll probably want something like this:

JavaScript code:
    // add function to the button for when it is clicked
   document.getElementById(structOfCrimesIterator.name).addEventListener("click", () => clickOnCrimeButton(buttonIndex));
Which means that you'll call clickOnCrimeButton when the event happens and not before then.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

EDIT: Yeah, I think that's the problem. It's basically the same as writing the following.
JavaScript code:
var clickOnCrimeButtonOutput = clickOnCrimeButton(buttonIndex); // undefined
document.getElementById(structOfCrimesIterator.name).addEventListener("click", clickOnCrimeButtonOutput); // .addEventListener("click", undefined)

fakemirage fucked around with this message at 20:00 on Jun 7, 2022

echinopsis
Apr 13, 2004

by Fluffdaddy
yeah I noticed it was being called immediately, but wasn’t sure why. Thanks mate

it does seem odd that it calls it, but suppose that’s my immature understanding of js

reversefungi
Nov 27, 2003

Master of the high hat!
The addEventListener function registers a callback function, whose execution is delayed until everything is exhausted in the main thread and you've entered the event loop. However the "registering" happens on that main thread, and in this case you were invoking a function and registering its output, hence the immediate call.

If you're not super familiar with the event loop and really want to dig in, this video is worth watching and will pay itself back quickly by saving you hours of debugging annoying js stuff:

https://youtu.be/8aGhZQkoFbQ

echinopsis
Apr 13, 2004

by Fluffdaddy
That'll probably come in super handy considering what I am trying to do, which is basically a spin on an idle game.

Thanks

Adbot
ADBOT LOVES YOU

lifg
Dec 4, 2000
<this tag left blank>
Muldoon
The biggest mistake I’ve been making while learning JS is thinking that the event loop is something like multithreading. But the control is a lot more implicit. Like I can’t just say “stop everything until this async function is finished.”

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply