[Cosmo-dev] Re: [commits-cosmo] (br) [3041] some enhancements to ModalDialog:

Matthew Eernisse mde at osafoundation.org
Tue Dec 12 12:39:11 PST 2006


Inline, below ...

Bobby Rullo wrote:
> Sorry for messing with this stuff, but it really made no sense to me, 
> and I couldn't even envision a scenario in which it could make sense and 
> it was making things hard to track down, and you were out.

I should also do a better job of commenting what I've done if it's 
potentially 'interesting' code. I'll try to work harder at guessing what 
might seem odd to other people, since it's not a single-occupant 
dwelling anymore. :)

> So you are saying that if I execute three statements in a row like so:
> 
>     doDOMStuff1();
>     doDOMStuff2();
>     doDOMStuff3();
> 
> They don't execute in a row? But if I say:
> 
> doDOMStuff1() && doDOMStuff2() && doDOMStuff3();
> 
> then they do?

You need to return something from your functions for it to work.

So here's an example. Say we have three functions -- render(), center(), 
and show(). (The main dialog div starts out with a CSS 'display' prop of 
'none.')

function render() {
   // Build tree of DOM nodes
   // Append to the doc
   return true;
}

function center() {
   // Position main div by
   // setting mainDiv.style's 'left' and 'top'
   return true;
}

function show() {
   // Display the dialog
   // by setting mainDiv.style's 'display' to 'block'
   return true;
}

If I just do this:

render();
center();
show();

Then yes, there is a good chance that you will actually see the dialog 
box up in the upper left corner briefly before it 'jumps' down to the 
center (depending on lots of stuff like when you set up the widget).

Have a look at the Dojo dialog box in Adam's Stickies app to see the 
visual effect.

However, with the same function definitions above, if you do this:

if (render() && center()) {
   show();
}

Then the half-assed looking 'flash' behavior never happens, presumably 
because the each called function has to execute as a discrete unit and 
return before execution can continue.

Think of it this way: "If it's rendered, and it's centered, then show it."

> When do JavaScript operations occur asynchronously like this? Is it just 
> for DOM manipulation stuff?

I have no idea. :)

My guess is that it's not actually the JS operations that are async, but 
it has something to do with JS handing off to outside code -- the 
browser's DOM code. I guess we'd have to ask a Real ProgrammerTM who 
knows about the innards of the browser to know why it actually does that.

> Anyhow if we have to do stuff like this, I'd prefer not to put some 
> stuff chained with &&'s, and some stuff in braces - I especially don't 
> like adding another level of braces for a code path that in essence will 
> always execute (unless there's an error).
> 
> In other words, can you just do
> 
>     do1() && do2() && do3();
>     nextThing();
>     otherThing();

I can't tell if that's any different from just calling them one by one 
-- and I don't know if using the logical 'and' without an assignment or 
a test is legal syntax. (Although it doesn't give me an error in the js 
shell.)

But basically what you're writing there is just a statement of

true && true && true;

That doesn't seem right.

> instead of
>     if (do1() && do2() && do3()){
>         nextThing();
>         otherThing();
>     }
> 
> or does that not trick it? I'd even prefer
> 
>     var dummy = do1() && do2() && do3();

This looks better, since it's doing an actual assignment.

Using logical 'or' similarly seems to be a normal pattern too:

this.foo = foo || 'This is the default if no foo param';

I've also seen the same 'or' pattern used to try execution of number of 
functions until one succeeds:

var result = idealFunction() ||
   notQuiteAsGood() || fallbackDefault() ||
   function () { throw 'Oops!' }();

Of course each of the funcs needs to return something that evals to true 
for the pattern to work.

In fact, if you wanted to be really super-complete, I guess you could 
add fallback error handling to your code above:

var dummy = (do1() && do2() && do3()) ||
   function () { throw 'Something is amiss.' }();

> I just really don't like adding that extra level of braces everytime 
> there's a dom manip, when in essence it really doesn't mean anything - 
> you expect braces to mean a new scope, or a different execution path.
> 
> What do you think?

I think your second option is a much better bet. It follows standard JS 
syntax, and is guaranteed to have the same effect as an if-test.

And this is not something we really need to do every time we use DOM or 
CSS with JavaScript. It's something we should reserve for when stuff 
happens in an out-of-sync way.

And clearly, we should cordon off stuff done in that style with some 
comments so later on other people don't just think it's needlessly weird 
or crap code and 'fix' it. :)

Thanks very much for your patience with me on this.


M.






More information about the cosmo-dev mailing list