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
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

Adbot
ADBOT LOVES YOU

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

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

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

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

echinopsis
Apr 13, 2004

by Fluffdaddy

reversefungi posted:

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

I watched this video and I think now your post makes more sense to me lol.

echinopsis
Apr 13, 2004

by Fluffdaddy

fakemirage posted:

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

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)

I've been looking and trying to understand arrow functions, and I can't work out why changing it to an arrow function works?

when you post:
JavaScript code:
var clickOnCrimeButtonOutput = clickOnCrimeButton(buttonIndex); // undefined
document.getElementById(structOfCrimesIterator.name).addEventListener("click", clickOnCrimeButtonOutput); // .addEventListener("click", undefined)
you're trying to say that what I had originally posted is the equivalent to that... but why?

why does
code:
   document.getElementById(structOfCrimesIterator.name).addEventListener("click",clickOnCrimeButton(buttonIndex));
split into two commands? if I am understanding correctly? does anyone understand why I am confused?

echinopsis
Apr 13, 2004

by Fluffdaddy
wow guys poo poo you’ve given me a good series of answers. I won’t have a chance to sit down and get my head around it until tomorrow, but gosh I really appreciate your help and support here.

I feel like I am making a lot of break throughs, where my time is leaning more toward making progress on my program rather than spending time trying to work out how the heck I do anything

echinopsis
Apr 13, 2004

by Fluffdaddy






alright thanks guys. I really do understand now why my original code was failing. the notion of arrow functions is less intuitive to me, but I am working on that.

thanks again. good old something awful huh :unsmith:

echinopsis
Apr 13, 2004

by Fluffdaddy
at some stage while working on this I must have made a change and I don't know what, but I am unable to work out why a css selector isn't working on a div

when I inspect it in chrome, it's clear it's got the class on the div, but it's like the css isn't even there in my stylesheet. it's not like it's being overridden, just doesn't seem to be working at all.

I have this at the end of my css file
code:
.log {
  display: flex;
  border: 2xp;
  border-color: white;
  border-style: solid;
  flex: 0 0;
  height: 40%;

  color: white;
  text-transform: none;
  padding: 5px;
}
and there is a picture showing that class selected in the inspector but.. idk what I've done to stop it applying any of that css


you can view the source at http://crimecommitter.com

echinopsis
Apr 13, 2004

by Fluffdaddy
oh my god what a fuckin numbnuts

thanks guys

echinopsis
Apr 13, 2004

by Fluffdaddy
yeah 2 experience . that’s um not a typo


lol

next step is figuring out date()

i’ve just tested positive for covid so guess i have a week at home to work it out lol

echinopsis
Apr 13, 2004

by Fluffdaddy
day.js it is then

given how important it is to my game, i’m happy to use a library if it makes my life work

echinopsis
Apr 13, 2004

by Fluffdaddy
this day.js is very good, but I need relative times, which it can't do without a plugin, which requires "require" lol, which is a node thing, and probably needs a plugin to make it work in browser.

I might go with date-fns since it's not minimalist and hopefully means one package will be enough

echinopsis
Apr 13, 2004

by Fluffdaddy

echinopsis posted:

this day.js is very good, but I need relative times, which it can't do without a plugin, which requires "require" lol, which is a node thing, and probably needs a plugin to make it work in browser.

I might go with date-fns since it's not minimalist and hopefully means one package will be enough

poo poo this is driving me crazy.

is it normal that everything assumes you're running node?

at least the dayjs was straightforward, it worked well until I couldn't figure out how to include plugins

anyway, it's a slow road trying to get something as basic as datetime working it seems.

e:

have worked out half of how to import plugins with dayjs into the browser without required node or whatever. thanks for reading

echinopsis fucked around with this message at 02:21 on Jun 14, 2022

echinopsis
Apr 13, 2004

by Fluffdaddy

camoseven posted:

You usually want to use import for front end apps, though you can load scripts directly as indicated by the DayJS docs.

I'm trying that final method, and the tricky part seems to be the dayjs.extend();

I don't seem to be able to paste source stuff into this but basically I
script src https://unpkg.com/dayjs@1.11.3/dayjs.min.js
script src https://unpkg.com/dayjs@1.11.3/plugins/relativetime.min.js

and then dayjs.extend(relativetime)

now that plain didn't work, so I tried extend(window.relativetime)

and that seems to work.. except it seems to be finding a problem
code:
Uncaught TypeError: Cannot read properties of undefined (reading '$i')
    at w.extend (dayjs.min.js:1:6457)
    at index.html:25:13
which kind of seems like it's saying the scripts I am referencing have errors. although I am sure it's something I am doing wrong.




e: but I finally got it working, I copied the scripts into my own folder and discovered I needed to extend day.js with dayjs_plugin_relativeTime not something else. which I only found by looking thru the relativetime.js

maybe I am dumb but I am not sure why that's not clear on the docs that you need to reference it like that, copying and pasting their stuff just didn't work.

NOW on with the show

echinopsis fucked around with this message at 02:56 on Jun 14, 2022

echinopsis
Apr 13, 2004

by Fluffdaddy

camoseven posted:

Capitalization matters for the extend, it's relativeTime

this didn't work, and neither did window.relativeTime, wasn't until I did the "dayjs_plugin_relativeTime" that it worked

thanks though. slowly hacking my way thru this

echinopsis
Apr 13, 2004

by Fluffdaddy
once I got over being mad at the less than obvious (for me) way to add the plugins to dayjs and got my head around it, it all ended up running smoothly.


thanks to everyone for their patience with me lol. the games called https://crimecommitter.com and no it’s not very good but at least it kind of works without being buggy and next step is flesh out the crime content

echinopsis
Apr 13, 2004

by Fluffdaddy
Hi, I've run into some confusing activity here.

so

JavaScript code:
function generateAccumulatedDataText(buttonIndex) {
    accumDataText = "<br><br>YOU'VE COMMITTED THIS CRIME " +
        setOfAccumlatedData[buttonIndex].numberTimesCommitted +
        " TIMES<br>" +
        "AND EARNED<br>" +
        setOfCrime[buttonIndex].notoEarned *
        setOfAccumlatedData[buttonIndex].numberTimesCommitted +
        " NOTORIETY<br>" +
        setOfCrime[buttonIndex].moneyEarned *
        setOfAccumlatedData[buttonIndex].numberTimesCommitted +
        " $<BR>AND SPENT " +
        dayjs
        .duration(
            setOfCrime[buttonIndex].timeToCompleteInMilliseconds *
            setOfAccumlatedData[buttonIndex].numberTimesCommitted,
            "millisecond"
        )
        .format("DD HH:mm:ss") +
        " DOING SO";
}
I had this very long string building thing in another function and it was working fine, but I was going to have to use it in two places so I pulled it out into it's own function, and now it does this
https://twitter.com/_crimecommitter/status/1537339000884953088?s=20&t=ZUgBbHaQLHz6uzWthzrg7A

at first the function returned the string and it had the same problem. then I thought I'd just abuse global variables so I do it that way, but the same problem.

In the console, if I access the variable it returns the correct string.

It wouldn't be so weird except it works if I just put that code into the original function.




e: fixing that next problem fixed this lol

echinopsis fucked around with this message at 09:52 on Jun 16, 2022

echinopsis
Apr 13, 2004

by Fluffdaddy
Also this also confuses me


ok so setOfAccumulatedData is an array of a function, which has the variable numberTimesCommitted in each function. I am using the function basically as a struct since javascript doesn't have structs
BUT

JavaScript code:
   setOfAccumlatedData[buttonIndex].numberTimesCommitted += 1;
appears to increment the numberTimeCommitted in each element of the array and not just the one defined by buttonIndex

I can't work out how the heck

e: I create the function like this
JavaScript code:
// struct for accumulated data (I expect to add more as time goes on)
function structOfAccumulatedData(numberTimesCommitted) {
    this.numberTimesCommitted = numberTimesCommitted;
}
and initialise it like this
code:
// initialise the accumulated data array
var setOfAccumlatedData = new Array(setOfCrime.length).fill(
    new structOfAccumulatedData(0)
);
according to the console log, the setOfAccumulatedData contains a bunch of structOfAccumulatedData

it's like there is only one numberTimeCommitted variable rather than one per each in the array



e2: I have fixed it, but only by expanding my initialisation method, and just expanded it, but it feels messy, and I'm sure the problem is me misunderstanding how to automatically make an array of functions


e3: I just expanded it to this:
JavaScript code:
// initialise the accumulated data array
var setOfAccumlatedData = new Array(setOfCrime.length);
// use a for loop to fill them
for (let initAccumDataIndex = 0; initAccumDataIndex < setOfCrime.length; initAccumDataIndex++) {
    setOfAccumlatedData[initAccumDataIndex] = new structOfAccumulatedData(0);
}
and it now works. kind of feels gross to have had to expanded it to a for loop but whelp

echinopsis fucked around with this message at 09:38 on Jun 16, 2022

echinopsis
Apr 13, 2004

by Fluffdaddy

Jabor posted:

This code:
code:
// initialise the accumulated data array
var setOfAccumlatedData = new Array(setOfCrime.length).fill(
    new structOfAccumulatedData(0)
);
creates one new object, and then makes every slot of the array point to that one single object.

Your fixed code creates a different object for every array slot.

For reference though one the things people find really handy about JS is how easy it is to make new "plain old data" objects:

code:
var foo = {
  key: "value"
}
You'll probably find this more convenient than making a new Function object just so you can attach extra values to it.

You can also use array.push instead of explicitly iterating over the array indices:

code:
var things = [];
for (var i = 0; i < numberOfThings; i++) {
  things.push(makeThing(i));
}
hmm I'm too deep into my code to change it now, but does that method allow you to basically create a struct?

this is what I am doing :

code:
function structOfCrimes(
  buttonid,
  name,
  cost,
  requiredNoto,
  moneyEarned,
  notoEarned,
  timeToCompleteInSeconds,
  timeToCompleteInHours,
  datetimeCrimeStarted,
  datetimeCrimeWillEnd
) {
  this.buttonid = buttonid;
  this.name = name;
  this.cost = cost;
  this.requiredNoto = requiredNoto;
  this.moneyEarned = moneyEarned;
  this.notoEarned = notoEarned;
  this.timeToCompleteInSeconds = timeToCompleteInSeconds;
  this.timeToCompleteInHours = timeToCompleteInHours;
  this.timeToCompleteInMilliseconds = timeToCompleteInHours * 60 * 60 * 1000 + timeToCompleteInSeconds * 1000;
  // state refers to where the crime is at
  // 0 = ready to run
  // 1 = running
  // 2 = completed but haven't collected resources
  // 3 = unavailable (need more noto)
  this.datetimeCrimeStarted = 0;

  this.datetimeCrimeWillEnd = 0;
}

// this creates an array "setOfCrime" that contains different crimes
var setOfCrime = [
  new structOfCrimes("loit", "Loitering", 0, 0, 0, 2, 12, 0, 0, 0),
  new structOfCrimes("skate", "Skateboarding", 0, 10, 0, 5, 45, 0, 0, 0),
  new structOfCrimes("litt", "Littering", 0, 2, 0, 1, 4, 0, 0, 0),
  new structOfCrimes("watch", "Selling Counterfeit Watches", 0, 20, 5, 2, 60, 0, 0, 0),
  new structOfCrimes("baby", "Candy from a Baby", 0, 12, 0, 3, 28, 0, 0, 0),
  new structOfCrimes("jorts", "Wearing Jorts", 5, 17, 0, -5, 60, 0, 0, 0),
];
creating a function that acts as a struct, and then creating an array of that struct to act as one large data hoard

my "background" if you will is unreal engine and so I work things how I worked them there



Jabor posted:

This code:
code:
// initialise the accumulated data array
var setOfAccumlatedData = new Array(setOfCrime.length).fill(
    new structOfAccumulatedData(0)
);
creates one new object, and then makes every slot of the array point to that one single object.

yeah I suspected something like this was happening

echinopsis
Apr 13, 2004

by Fluffdaddy
O yep I see

I actually have a CSV file with that data in it that I use a hacky python script to that outputs to a file that I copy and paste into my code, so that over time it's easy for me to add more crimes without fiddling in the code.

I could probably work out how to have a separate data file lol.

echinopsis
Apr 13, 2004

by Fluffdaddy
Thankyou. I’ve enjoyed the whole process and even come to like javascript lol. I’m certainly proud of how far I’ve come, and I thought I was going to have to spend a day working out cookies and I managed to knock it out in a few hours, the best part being the section where I combine an array into a single cookie (by joining them into one string with “;”) and then later pull them apart with split, I managed to write all at once and it all worked.

I know I’m getting better when I can write entire sections that work first try.

I did have other problems with cookies though and it didn’t help that I couldn’t debug them without uploading to the website but managed to get it working.


The game is highly functional now, and just needs me to put some decent time into making a decent list of crimes to do. which weirdly I fine quite difficult. BUT no excuses, and I have 6 more days off due to covid so I should be able to get it done.

And there is definite work on the css left to be done lol. while a small amount of jankiness contributes to its aesthetic, I defo need to make it work on more than just full sized desktop screens. and link to a merch page or course. lol

With cookies now working, it’s feasible to have crimes that take days and weeks to complete* and also should be able to update it and add to it without breaking it so in theory there’s maybe interesting things for people to come back to

* I don’t use any kind of countdown per se, I just encore the end datetime the moment you hit go on any particular crime, so it doesn’t matter if you close the browser, and when you come back it’ll recalc their state so you’ll come back to completed crimes ready to collect


I’m quite “excited” about making some other websites though.

A major step would be logins, and I understand using something like django would take a lot of the hard
work out, except at the moment it’s 100% client side and hosted at github and so I am sure if I took the next big step of having logins it’d mean quite a significant change. although it would allow me to email people to tell them they’ve got uncollected crimes. ugh there is always scope for adding features lol



Thanks to everyone in this thread who helped, you’ve all been helping and the fact you were so willing to help also meant so much.

echinopsis
Apr 13, 2004

by Fluffdaddy

Osmosisch posted:

Agreeing that following your progress has been fun!

You could look into hosting on glitch, they have a lot of features for free pet projects like this one, up to and including dbs/logins as I understand it.

Time to rack up some more notoriety.

Thanks for the tip, I'll look into it :)

tbh I don't mind paying some money either. I've offered a local comedian $100 for an hour or so work to write up some paragraphs for the crimes, to provide incentive to play deeper and deeper

echinopsis
Apr 13, 2004

by Fluffdaddy
seeing as I've hired a person to write me up some descriptions etc, I suppose it would be wise to store these in a data file,

now I've been looking around, is JSON the best format to use for this? will it have trouble with commas etc? (spose I can always encode those somehow)

because it makes sense to me to store this data, which will be large character wise, in it's own file and keep the javascript file clean.

and I could store all that information that I declare into my function in the data file, and if it's json then it's designed from the ground up to be readily read by javascript, right?

The other day I was thinking about storing it in csv, but then I'd need a special way to convert out of csv, but if it's json then it's kind of ready to go? am I understanding that correctly? I could easily make a for loop that cycled through all the json entries and fill up my setOfCrime array? or as I am writing this, perhaps even skip that step and directly reference the json file where and when I need to instead of an intermediate array of structs?

Initially my setOfCrime array was carrying mutable gamestate data but I've moved that into it's own array now so the setOfCrime array is read-only anyway, could I entirely skip that step and read from the json where and when I need it? Or would it still be wise to have that intermediate variable hanging around in memory or not for performance reasons*?



*because I tell you what, my code is NOT efficient lol, I know I do a lot of inefficient refreshes for the sake of making it easy to code and think about. every single page redraw (however many times per second that is) checks every single crime to see if it's finished, updates the time on it, refreshes the top banner, the current time.
When I have more crimes to do, spose it might be prudent to reduce this to every half second or so. seeing as it's not my cpu cycles I'm using doing this lol.

echinopsis
Apr 13, 2004

by Fluffdaddy
Thankyou, that certainly settles it for me that I'll use a JSON file to store all this data.

I'll probably keen defining the array in my main code, just directly reference the data in the JSON file, and try to format the data in the JSON file exactly as I will be using it in my code.

echinopsis
Apr 13, 2004

by Fluffdaddy
can I ask a question about JSON

I'm trying to hold all my crime data (read only stuff) in a JSON file, and I am unsure of how to have the layout.

my goal would be to access it like
code:
JSONFile.crimes[12].name
here's what I have with thr JSON file so far
code:
{
  "crimes": [
    {
      "buttonid": "",
      "name": "",
      "cost": 0,
      "requiredNoto": 0,
      "moneyEarned": 0,
      "notoEarned": 0,
      "timeToCompleteInSeconds": 0,
      "timeToCompleteInHours": 0
    },
    {
      "do more of the same"
    }
  ]
}

{
    "spiels":[
        {
            "buttonid":"some great words"
        },
        {
          do more of the same
        }
        
    ]
}
one large array for the crime data and a second large array that holds just some text/spiel/praragraph about the crimes


am I heading in the right direction?

echinopsis
Apr 13, 2004

by Fluffdaddy

roomforthetuna posted:

That's a fine layout, though why a json file rather than a js module?

oo I never saw this

although I am thinking about importing a csv library and parsing a csv file at runtime because it’s much easier for me to maintain the data in excel and export to csv when I’m done and then that’s it, not another step

Analytic Engine posted:

Looks good, just drop the two lines with } and { after crimes and put a comma there instead. Those are keys in the object

Future tip: JSON doesn't allow extraneous commas like JS does, and you can't serialize a non-dictionary object (becomes "[object]") or a circular dictionary

about dictionaries

I finally worked out how to use them for ordinary key:value pairs

but what I want to know is if I can use a dictionary so that I can access a handful of variables via the dictionary key. eg


code:
dictionaryVariable[”primaryKey”].oneOfAFewVariables 
or maybe it’s addressed
code:
dictionaryVariable[primaryKey][secondaryKey]
or something


code:
let dictionaryVariable = [ primaryKey:[secondKeyA:”some stuff”, secondKeyB:”something else”]]
have a dictionary inside a dictionary?

I realise I’ve coded some stuff very poorly, and if I could create data structures that used keys to access them it’d be incredible

echinopsis
Apr 13, 2004

by Fluffdaddy
I used a basic dictionary for some functionality I recently added and man it just worked so easily lol

echinopsis
Apr 13, 2004

by Fluffdaddy

Doom Mathematic posted:

echinopsis, you need someone to pair program with for an afternoon.

I had literally thought about something like this, even paying someone for a couple hours or something, help me crack open some of these awful implementations of mine.

Video Nasty posted:

Object.keys() will let you iterate over the JSON object and you can pull from that. Echi I can provide assistance for you tomorrow but I'm not on NZ time.

I appreciate this, but it is a bit of a challenge to find a time given I've got kids and work and squeeze this in just when I can, but I might take you up on this if at some stage, if you're still keen and willing.

Adbot
ADBOT LOVES YOU

echinopsis
Apr 13, 2004

by Fluffdaddy
e:dw

echinopsis fucked around with this message at 09:11 on Jan 24, 2024

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