When does InnerHTML execute immediately? - dom

I would expect this HTA code to print a to be replaced some time later by b. However, what it does is it prints nothing for some time, and then b.
With the MsgBox line enabled, it does print a first.
It seems that the execution of statusinfo.InnerHTML = "a" is postponed. Can any body tell me why this is? And how would I obtain the desired behavior (immediate refresh)?
<SCRIPT LANGUAGE=VBScript>
Sub doThis()
statusinfo.InnerHTML = "a"
'MsgBox "stop"
intensiveOperation
statusinfo.InnerHTML = "b"
End Sub
Sub intensiveOperation()
'takes long
End Sub
</SCRIPT>
<BODY>
<button onclick="doThis">Run</button>
<div id="statusinfo"> </div>
</BODY>
</HTML>

Scripts and rendering are executed in a single thread. This means, that doThis will be finished before rendering starts. In the meanwhile you've set the inner HTML to 'b', and that will be the only result you'll see.
To fix this, you've to finish the first sub, and call intensiveOperation with a short delay, and make the final HTML update at the end of the second sub, like so:
Sub doThis
statusinfo.InnerHTML = "a"
Call window.setTimeout(GetRef("intensiveOperation"), 4)
End Sub
Sub intensiveOperation()
'takes long
statusinfo.InnerHTML = "b"
End Sub
Finishing doThis will free the thread. Notice, that setTimeout won't halt the execution, the whole sub is executed to the end. After that browser can render the page.
intensiveOperation is called at some point after the rendering is finished, not earlier than the given delay, but possibly much later, depending on tasks CPU is doing at the time.
The answer to the question in the header of the question is basically: never.

Related

Word Form - using VBA to enable textbox on checkbox click

I have the following VBA code to enable a textbox everytime a checkbox is clicked.
Private Sub CheckName1_Click()
If CheckName1.Value = True Then
TextName1.Enabled = False
TextName1.SpecialEffect = fmSpecialEffectFlat
Else
TextName1.Enabled = True
TextName1.SpecialEffect = fmSpecialEffectSunken
End If
End Sub
The problem is my document will probably have 30 of these by the time I am done (CheckName1, CheckName2, CheckRent1, CheckRent2, etc). I am already having trouble with Word lagging, so I'd like to create a subroutine that will call this sub instead of copy/pasting it again and again.
I haven't spent a lot of time with functions and the like- and even less with VBA. I just know the basics and they always make my head spin. So, this is what I have.
I just don't know how to pass the textbox parameter, or if I even have the checkbox parameter right.
And if this is close, do I still create a call for each checkbox?
Private Sub CheckName1_Click()
Call NA
End Sub
Private Sub NA(checkbox, textbox)
If checkbox.value = True Then
textbox.Enabled = False
textbox.SpecialEffect = fmSpecialEffectFlat
Else
textbox.Enabled = True
textbox.SpecialEffect = fmSpecialEffectSunken
End Sub
Thanks in advance for any help!
Loop on all controls
Based on this example: http://www.ozgrid.com/VBA/control-loop.htm
Dim cCont As Control
For Each cCont In Me.Controls
If TypeName(cCont) = "TextBox" Then
'DO STUFF HERE
End If
Next cCont

Coffeescript running a second function before the first has finished executing

My code is as follows. I would expect the code inside configureMission() to finish running before running mapSurface. This does not appear to be happening.
missionCommands = "" # you don't have a mission yet
$('#startExploration').click -> # Set #missionControl as input for game configuration
configureMission()
mapSurface()
configureMission =->
$('#MissionControl').on "submit", ->
# cool helper function shamelessly pinched from http://jsfiddle.net/sxGtM/3/
$.fn.serializeObject = function() # not shown
missionCommands = JSON.stringify($('form').serializeObject())
return false #stops click event from firing
mapSurface =->
console.log('map')
console.log(missionCommands)
I have noticed that if I submit the form a second time, the missionCommands variable has been updated with the json data, so it appears that the form data has been processed, but that this is happening after the second function has run.
map login.js:60
login.js:61
map login.js:60
{"xMaximum":"","yMaximum":"","xCoord":["iuoiuyi",""],"yCoord":["",""],"orientaiton":["",""]} login.js:61
I can make it work by moving the mapSurface function inside the configureMission function, but this seems like bad form. I wonder, is there a more correct pattern I could use to achieve my desired result of processing the form data into json, setting this into a variable and passing the variable to a second function.
You're treating asynchronous commands as synchronous commands. JavaScript (and thereby CoffeeScript) works asynchronously, meaning that functions will be run in parallel.
You can solve this problem by specifying mapSurface() as the callback for configureMission() as follows:
missionCommands = ""
$('#startExploration').click ->
configureMission(mapSurface)
configureMission = (cb) ->
console.log "now running configureMission()"
$('#MissionControl').on "submit", ->
$.fn.serializeObject = function() # not shown
missionCommands = JSON.stringify($('form').serializeObject())
console.log "completed configureMission()"
return cb()
mapSurface = ->
console.log "now running mapSurface()"
console.log missionCommands
console.log "completed mapSurface()"
Learn about JavaScript callbacks here: http://recurial.com/programming/understanding-callback-functions-in-javascript/.

WWW::Mechanize::Firefox looping though links

I am using a foreach to loop through links. Do I need a $mech->back(); to continue the loop or is that implicit.
Furthermore do I need a separate $mech2 object for nested for each loops?
The code I currently have gets stuck (it does not complete) and ends on the first page where td#tabcolor3 is not found.
foreach my $sector ($mech->selector('a.link2'))
{
$mech->follow_link($sector);
foreach my $place ($mech->selector('td#tabcolor3'))
{
if (($mech->selector('td#tabcolor3', all=>1)) >= 1)
{
$mech->follow_link($place);
print $_->{innerHTML}, '\n'
for $mech->selector('td.dataCell');
$mech->back();
}
else
{
$mech->back();
}
}
You cannot access information from a page when it is no longer on display. However, the way foreach works is to build the list first before it is iterated through, so the code you have written should be fine.
There is no need for the call to back as the links are absolute. If you had used click then there must be a link in the page to click on, but with follow_link all you are doing is going to a new URL.
There is also no need to check the number of links to follow, as a for loop over an empty list will simply not be executed.
To make things clearer I suggest that you assign the results of selector to an array before the loop.
Like this
my #sectors = $mech->selector('a.link2');
for my $sector (#sectors) {
$mech->follow_link($sector);
my #places = $mech->selector('td#tabcolor3');
for my $place (#places) {
$mech->follow_link($place);
print $_->{innerHTML}, '\n' for $mech->selector('td.dataCell');
}
}
Update
My apologies. It seems that follow_link is finicky and needs to follow a link on the current page.
I suggest that you extract the href attribute from each link and use get instead of follow_link.
my #selectors = map $_->{href}, $mech->selector('a.link2');
for my $selector (#selectors) {
$mech->get($selector);
my #places = map $_->{href}, $mech->selector('td#tabcolor3');
for my $place (#places) {
$mech->get($place);
print $_->{innerHTML}, '\n' for $mech->selector('td.dataCell');
}
}
Please let me know whether this works on the site you are connecting to.
I recommend to use separate $mech object for this:
foreach my $sector ($mech->selector('a.link2'))
{
my $mech = $mech->clone();
$mech->follow_link($sector);
foreach my $place ($mech->selector('td#tabcolor3'))
{
if (($mech->selector('td#tabcolor3', all=>1)) >= 1)
{
my $mech = $mech->clone();
$mech->follow_link($place);
print $_->{innerHTML}, '\n'
for $mech->selector('td.dataCell');
#$mech->back();
}
# else
# {
# $mech->back();
# }
}
I am using WWW:Mechanize::Firefox to loop over a bunch of URLs with loads of Javascript. The page does not render immediately so need test if a particular page element is visible (similar to suggestion in Mechanize::Firefox documentation except 2 xpaths in the test) before deciding next action.
The page eventually renders a xpath to 'no info' or some wanted stuff after about 2-3 seconds. If no info we go to next URL. I think there is some sort of race condition with both xpaths not existing at once causing the MozRepl::RemoteObject: TypeError: can't access dead object error intermittently (at the sleep 1 in the loop oddly enough).
My solution that seems to work/improve reliability is to enclose all the $mech->getand$mech->is_visible in an eval{}; like this:
eval{
$mech->get("$url");
$retries = 15; #test to see if element visible = page complete
while ($retries-- and ! $mech->is_visible( xpath => $xpath_btn ) and ! $mech->is_visible( xpath => $xpath_no_info )){
sleep 1;
};
last if($mech->is_visible( xpath => $xpath_no_info) ); #skip rest if no info page
};
Others might suggest improvements on this.

form_load subroutine in MS Access VBA

I am writing a code in MS Access VBA, which is as follows:
Private Sub Form_Load()
MsgBox "loggedIn = " + CStr(loggedIn)
If (loggedIn = 1) Then
Else
Exit Sub
End If
End Sub
I want to decide whether to load the form or not based on loggedIn variable. If loggedIn variable is 1, form shall be loaded. If the same is not 1, form shall not be loaded.
Issue that I am facing is that, whatever I do in ELSE part of the code above, I am not able to stop the form from loading.
How can I achieve this?
Pls comment if any additional information is required.
Thank you.
If the loggedIn value is available at form open, you could cancel the form open event.
Private Sub Form_Open(Cancel As Integer)
Cancel = Not (loggedIn = 1)
End Sub
If the value of loggedIn is not available until the form's load event, you can close the form.
Private Sub Form_Load()
If loggedIn <> 1 Then
DoCmd.Close acForm, Me.Name
End If
End Sub

simple parallel processing in perl

I have a few blocks of code, inside a function of some object, that can run in parallel and speed things up for me.
I tried using subs::parallel in the following way (all of this is in a body of a function):
my $is_a_done = parallelize {
# block a, do some work
return 1;
};
my $is_b_done = parallelize {
# block b, do some work
return 1;
};
my $is_c_done = parallelize {
# block c depends on a so let's wait (block)
if ($is_a_done) {
# do some work
};
return 1;
};
my $is_d_done = parallelize {
# block d, do some work
return 1;
};
if ($is_a_done && $is_b_done && $is_c_done && $is_d_done) {
# just wait for all to finish before the function returns
}
First, notice I use if to wait for threads to block and wait for previous thread to finish when it's needed (a better idea? the if is quite ugly...).
Second, I get an error:
Thread already joined at /usr/local/share/perl/5.10.1/subs/parallel.pm line 259.
Perl exited with active threads:
1 running and unjoined
-1 finished and unjoined
3 running and detached
I haven't seen subs::parallel before, but given that it's doing all of the thread handling for you, and it seems to be doing it wrong, based on the error message, I think it's a bit suspect.
Normally I wouldn't just suggest throwing it out like that, but what you're doing really isn't any harder with the plain threads interface, so why not give that a shot, and simplify the problem a bit? At the same time, I'll give you an answer to the other part of your question.
use threads;
my #jobs;
push #jobs, threads->create(sub {
# do some work
});
push #jobs, threads->create(sub {
# do some other work
});
# Repeat as necessary :)
$_->join for #jobs; # Wait for everything to finish.
You need something a little bit more intricate if you're using the return values from those subs (simply switching to a hash would help a good deal) but in the code sample you provided, you're ignoring them, which makes things easy.