[Ur] Grabbing focus

Edward Z. Yang ezyang at MIT.EDU
Sat Jun 23 11:54:11 EDT 2012


Excerpts from Adam Chlipala's message of Sat Jun 23 10:28:57 -0400 2012:
> I think it's easy to give it the right semantics.  A value of [xml] type 
> doesn't have any side effects on its own; it's just code, much like an 
> 'IO' value in Haskell.  I can play all sorts of groaty tricks in 
> rendering these values into HTML, since Ur/Web enforces a convention of 
> executing all code appearing in <script> tags (and then deleting those 
> tags) each time HTML is added to the DOM.

Yes, I have come to a similar conclusion (having hacked up this system
for my project.)

> You already get the ability to associate ID's with tags, without needing 
> to use the FFI.

Yes. This works a little less well when the XML fragment does not have an
enclosing tag, but usually it is not too much trouble to add one.

> I could, easily enough, add a basis function with a type like 
> [transaction {} -> xbody], with the semantics that loading of a page 
> fragment triggers execution of all these computations, in the natural order.
> 
> However, I'm a bit wary of that general direction.  It's sort of like 
> changing Haskell to allow side effects anywhere, regardless of types.  
> Suddenly any piece of XML produced by a library (that someone else 
> wrote) might cause side effects when rendered.  For instance, it might 
> display alert dialogs over and over!  It seems much nicer to think of 
> XML fragments as inert.

I don't the analogy is quite right: a better analogy is that we've
expanded the set of 'main'-like functions to include all XML fragments
(which goes beyond the current set of the true main and event handlers.)
Any piece of XML might cause side effects *when an event happens*, and we
don't consider this particularly onerous.

I think the big question is whether or not there is a reasoning principle
that we gain from having XML fragments be inert ("why not") and what
functionality we gain of having XML fragments be active ("why").  We don't
lose the principle of locality: while a fragment may do arbitrary side-effects,
we don't have global state so these side effects don't leak out, except
for the "bad" UI elements like modal dialogues (which, by the way, are an
abomination.)  We don't lose composition: just run all of the handlers in
a postorder traversal.  I think the one thing we do lose the ability to
do this:

(**)
    x <- makeXml
    <xml>{x} {x}</xml>
(**)

where both inclusions are backed by the same underlying data structure
(so if you update one, the other reflects the changes), but this is no
different than the difference between an API that is 'onlyOnce :: IO (IO ())'
and 'everyTime :: IO ()': if you want to do 'onlyOnce' (the more expressive
interface), you code for it explicitly.

A big benefit Logitext would get for having active XML fragments is it
means that I can declare widgets inside the XML directly, rather have
to do all of my transactions ahead of time and then register onload
handlers for everything.  It would really make things more modular:
right now I have to do this:

(**)
    r <- newWorkspace 'A /\ B |- A'
    q <- newWorkspace 'A |- A \/ B'
    ...
    <xml><body onload={r.Onload; q.Onload}>
        {r.Body}
        {q.Body}
    </body></xml>
(**)

With active XML, I can just do:

(**)
    <xml><body>
        {newWorkspace 'A /\ B |- A}
        {newWorkspace 'A |- A \/ B}
    </body></xml>
(**)

which is substantially nicer.  Now, the reason why I need the Onload handlers
is to force code to run on the client side, due to Ur/Web's imperfect
support.  *If* that could be eliminated, and *if* we introduced syntax
sugar for embedding transactions in an <xml> tag that desugar to
running a bunch of transactions up front, and then generating the xml,
you could probably achieve the same style without requiring active xml.

> For your concrete case, it really does sound like a simple static 
> pseudo-attribute, for "give this focus when it appears in the DOM," 
> ought to get the job done.  To dynamically change focus, you can just 
> regenerate the suitable piece of the document.  Am I missing something 
> about the use case?

Yes, that seems fairly usable.  One thing not to like is focus is a document
global property, so you actually lose local reasoning when it gets involved
(I am not going to lose focus whoops I lost focus.)  But this is a similar
failing of many of the UI elements in modern browsers.

Cheers,
Edward



More information about the Ur mailing list