I'm having a problem that seems very simple, but still I don't know how to solve it.
So, I have this tag in my HTML file:
<p id="best-individual-text" style="display: inline-block"></p>
For context, I'm building a simple genetic algorithm to evolve a population of individuals (strings) in order to reach a target phrase. In my .js file, I have a loop that creates the new population and finds the best individual of that population, and the loop only stops when one of the individuals is identical to the target phrase.
What I want to do is to update the best-individual-text text content with the string of the best individual in each generation. Since the while loop creates a new population in each iteration, there's going to be a new best individual at every iteration.
Inside this while loop, I have the following line of code:
document.getElementById("best-individual-text").textContent = getBestIndividual();
Note: getBestIndividual() returns a string
And here lies my problem: the HTML doesn't get updated. The tag remains blank until the loop stops, and only after that the tag is filled with the last best individual.
It works fine if I try this manually, that is, outside of the while loop. My only guess is that the while loop runs too fast for the HTML to be updated. Still, I think I've seen people update the HTML in a while loop, so I really don't understand the reason it is now working.
Also, I've tried making a setInterval instead of a while loop, but it still doesn't work. Even if it did work, it is not of my interest to have any sort of interval for each loop.
What could the problem be, and how can it be fixed?
Thank you in advance!
Here's the github in case anyone needs to see more of the code: https://github.com/pedroheck/genetic-algorithms/tree/main/Word%20Race
I tried out your code, and in the cases I hit where you enter some text, click "Submit", and nothing happens, what is actually happening is that your algorithm is in some sort of infinite, or long-running loop, and it never hits the point where you try to modify the HTML.
You can tell this by simply setting a breakpoint at the line that tries to modify the HTML, and notice that it simply doesn't get hit. Another clue is that the window becomes unresponsive.
My recommendation would be to look closer at your algorithm and try to set some limits. console.log statements will be your friend, because they'll help you see what parts of the code are running the most.
Related
I would like to use code to clear a Blockly workspace, and in some cases overwrite with new Blockly XML. The issue I am facing, however, is that Workspace.clear() moves current items to trash, which can be annoying when trying to reset a workspace, or overwrite it with blocks (which means clearing it first, as otherwise the current blocks would be overwritten). I have found that I am able to clear the trashcan with workspace.trashcan.contents = [], but this results in some unexpected behaviour regarding the rendering of the lid, which appears slightly ajar despite it being empty.
Even if I could find a way to clear the trashcan, this would still result in clearing all previous items in there, while all I'm looking for is to do a single clear action without impacting the trashcan. I've tried looking at docs for Workspace.Clear, but they don't seem to give any semantic way to do this. I've also tried looping through Workspace.getTopBlocks() with Events.Delete, but that also results in moving items to the trashcan.
I've also tried to implement a manual solution, something along the lines of:
const contentsBeforeClearing = workspace.trashcan.contents_;
workspace.clear();
workspace.trashcan.contents_ = contentsBeforeClearing;
For the first line, I've also tried Object.assign([], workspace.trashcan.contents_) and workspace.trashcan.contents_.slice(), but in all three cases (including the top one), the end result is equivalent to simply calling workspace.clear. I'm guessing this is something to do with getter-setters manipulating contentsBeforeClearing (as the variable's value has changed if you test it in the console after the clearing to have the deleted block(s)), but how to get around that is beyond me.
How can I clear the workspace without manipulating (not just resetting) trashcan contents?
I am a lowly operations employee without authorization to change the programs and permissions on my machine, and I would like to automate some highly repetitive data entry. I know there are a lot of programs that can do that, however, for the sake of this discussion we'll assume that I'm not allowed to have any of them and I can only script through the debug F12 menu in Chrome. I also probably don't understand half of these words as well as I should.
I have to run test cases on a third-party vendor's highly dynamic website, and I've already successfully written javascript which adds texts to elements in the DOM and presses the "next" button.
The problem is, upon .click()ing the "next" button, it takes time for the page to update, and the update creates new elements which weren't in the DOM when the script was initialized. I need to find a way to delay the execution of the script until the DOM contains all the elements I need to update.
As a really, really crude proof of concept I wrote the pre-filler for each page as a function, and I serially called each function at the end of the previous function, using setTimeout(nextfunct, 10000) to let the page update before executing the next line. (I was going to refine that by trying to create some kind of object listener instead of an arbitrary 10 second delay, but I wasn't even able to get that far.) This approach creates two errors.
1) The script seems to be checking whether the elements are on the DOM before the end of the setTimeout(), so it still gives me an error. If nextfunct is defined as
document.getElementById("doesntexistyet").value = "Fill Me";
console.log("nextfunct ran");
I will get the error message stating there is no element with the id "doesntexistyet" immediately, not after a delay of 10 seconds. The element on the next page will not update.
2) The DOM updating interrupts my script. In the above code, the console output will not ever appear in my console. If I comment out the missing element, so the function only prints a comment, it will still not appear in my console. However, if I comment out the code and I switch the setTimeout to 1ms, "nextfunct ran" will appear in my console, until the page updates, at which time the console will be deleted.
Are there ways around this which I can implement using only vanilla JS and a browser? I'm sure there's a keyword I can search for where someone has discussed this before, but it seems like the vast majority of JS autofilling discussions are oriented towards people designing code to be integrated into a website,
Thanks
Since I've tried and not succeeded many times I figure it's time to ask. I would like have several elements on the screen on which the user can click. Once the user decides to double click somewhere on the body I would like to console.log the text elements of the array.
This isn't nearly as intuitive as I thought it was going to be. The following example isn't all that practical, just curious why I can't get it to work.
EDIT: I would like to NOT use a global variable.
Fiddle can be found here
You just need to alter the scope of the array textArray so that your function ferryArray() can access it and loop over.
Here is the working fiddle.
Alright lets see if I can describe this.
I have a handful of functionality that was created sometime ago, and works swimmingly. However there is a new desired spec, so without having to rewrite the code base in a matter of speaking, and without having to double up on code to pull the same effect off I am trying to figure out how I can go about making something jump back higher in the code within the same function to repeat the run of the function rather then doing the same code again below.
What I have is a click based triggers ie:
$('.selector').click(function(){});
In this function is about 30 lines of functionality to create a new element and populate it accordingly. However unfortunately in that same bit of functionality there is conditions to wether it should or not.*The previous requirement was when the element it creates is open and populated just throw an alert() saying essentially wrap up what your doing, and then go on to the next. *Now the new requirement is just close that and open a new element. Which I've gotten to close out the existing, and do everything I want it to do, except the population of the new element which is above where the condition is currently. Knowing there is no "go to" type of logic in javascript (or last I knew). the only thing I can think of is taking the same code from above and putting it in the condition as well, doubling up on the code and having litterally 2 copies of the same bit. I want to avoid that, but cant think of a way to do it. So here I am looking for ideas
Knowing there is no "go to" type of logic in javascript (or last I
knew). the only thing I can think of is taking the same code from
above and putting it in the condition as well, doubling up on the code
and having litterally 2 copies of the same bit. I want to avoid that,
but cant think of a way to do it. So here I am looking for ideas
Why don't you just pull this piece of code out into a function? You can run the function if the conditional is true in the original instance, and run it all the time in your callback? This is fairly minimal refactoring, just move the code out of the logic into a separate function, keeping it as is and maybe making some of the referenced variables into parameters.
So something like this if you want to run all the actions regardless of the conditional statements:
...
if(condition){
actionA();
}
if(condition2){
actionB();
}
...
$('.selector').click(function(){
actionA();
actionB();
});
You're familiar with that pattern, right?
var aCallback = function(){........};
$('.selector').click(aCallback);
Been looking for hours. At https://stackoverflow.com/questions/ask how does the "Tags" section make the blue boxes appear below?
I don't think they are using keyup event trigger, since the blue boxes are not being updated on every keypress.
You can test this by going to https://stackoverflow.com/questions/ask and typing:
"aadfadasdfasdfasdfasdfasfasdfsaf"
As you type, you will notice that the blue box "aadfadasdfasdfasdfasdfasfasdfsaf" will only appear a few seconds AFTER typing. Not during.
They probably call setTimeout and clearTimeout to run their code 1 second after the last keyup event.
It's just a case of autocomplete. There are many ways of accomplishing this.
One way is to store the list of words to autocomplete on the client end. This is very fast and there won't be any delay (unless you program one in).
The other way is to make an AJAX call to the server and have it return a list of autocomplete words. This is how SO does it. Since you don't want to make an ajax call every time the user types in a letter, there is a delay implemented to save bandwidth and improve performance.
If you want to implement a similar feature on your own website, I suggest looking into jQuery plugins to achieve this as there are many freely available ones out there.
EDIT: The trigger is likely a keyup event as you mentioned. However the trigger will likely wait for a second or so using setTimeout() before showing the list of possible autocompletes. clearTimeout() is used if another key has been pressed during the delay to prevent multiple calls from being made.
Check out the source code using Firebug or another web inspector. You'll see that there's a file called full.js. It's minimized, but you can expand the code using a variety of online tools; I go the very lazy approach of copying/pasting the whole thing into the "javascript" box in jsfiddle and hitting "tidy". I'm sure there are better (and faster) ways to do it.
Anyway, in that file, there are a few functions that may interest you: StackExchange.tagPreferences and it's subfunctions, initTagRenderer, and StackExchange.inlineEditing. I think the last function is the one that causes the specific delay you're referring to, but it's pretty hard to tell.