[ 
https://issues.apache.org/jira/browse/TAP5-544?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Howard M. Lewis Ship reassigned TAP5-544:
-----------------------------------------

    Assignee: Howard M. Lewis Ship

> Improve JavaScript handling to prevent the user from clicking Ajax-oriented 
> links and forms before the page is "ready"
> ----------------------------------------------------------------------------------------------------------------------
>
>                 Key: TAP5-544
>                 URL: https://issues.apache.org/jira/browse/TAP5-544
>             Project: Tapestry 5
>          Issue Type: Improvement
>          Components: tapestry-core
>    Affects Versions: 5.1.0.1
>            Reporter: Howard M. Lewis Ship
>            Assignee: Howard M. Lewis Ship
>
> I think it's well time to open a discussion about Tapestry 5 and JavaScript. 
> I think Tapestry is getting a large number of things right, but also a small 
> number of things wrong. This is not a discussion about jQuery vs. Prototype 
> (that's a separate area), but more about the behavior of Tapestry JavaScript, 
> within the constrains of the browser.
> In standard usage, the JavaScript for a page is collected together and moved 
> to the bottom of the page: first a series of <script> tags to load JavaScript 
> libraries, then a single block of code to perform all kinds of 
> initialization; this block executes, ultimately, when the page is fully 
> loaded: after all HTML and JavaScript (but, depending on the browser, before 
> all images have fully loaded).
> This is good and bad; the good part is that we are following Yahoo's 
> performance guidelines: JavaScript at the bottom of the page, so it doesn't 
> slow down rendering of the markup.  However, this means that common 
> practices, such as using the "javascript:" psuedo-scheme (i.e. <a 
> src="javascript:...">) are not possible, since the referenced JavaScript 
> would not have been loaded yet.  In fact, many users must configure Tapestry 
> to move the scripts back up to the top of the page (inside the <head>) to 
> meet external demands (of third-party URL trackers and advertising solutions).
> Further, on a page that loads slowly (one that has a large number of external 
> scripts, is accsessed via a slow-bandwidth pipe, or has a very complex 
> layout), this means that JavaScript event handlers are not wired up until all 
> JavaScript has been downloaded and parsed.  The end result it that you can 
> "outrace" Tapestry, click a link that should update a zone and get incorrect 
> behavior or even a runtime exception. I actually see this when using Formo's 
> time-tracking application from home through a slow pipe, exacerbated by 
> HTTPS, where I get the error that "Block is not a valid response type". What 
> should have been an Ajax request was processed instead as a traditional page 
> render request, because the JavaScript was not ready.
> An earlier version of Tapestry 5 approached this problem by disabling the 
> link components when the zone parameter was in use; that is, the href 
> parameter was written out a "#", so the only way the link would be active is 
> via an attached onclick event handler.
> This solution was weak, because there was no graceful degradation: clients 
> without JavaScript would have a non-functioning application.  Thus it was 
> changed to render the href normally AND add an onclick event handler, which 
> leads to the race conditions described above.
> What I really would like to see is the following:
> The page renders normally.  If a user submits a form or clicks a link before 
> all initialization code has executed, then a popup dialog will appear to 
> inform the user that the page is still loading.  When the load is complete, 
> the message changes and the dialog fades out.
> Possibly, when a page is loading a more subtle floating "Loading ..." dialog 
> would appear and disappear once the page is, in fact, loaded. 
> What would it take to accomplish this?  
> Firstly, JavaScript libraries would have to move (back) to the <head>, 
> permanently, no configuration (well, short of replacing some internal 
> services).  We can't have inline javascript unless the javascript being 
> referenced loads first. Hopefully, we'll be able to make up the performance 
> difference (if measurable) with the future plans to minimize and combine 
> JavaScript for the page.  JavaScript initialization would still occur at the 
> bottom.
> Next, Ajax-y links and forms would have something like 
> onclick="javascript:Tapestry.waitForPageLoad();" written into their HTML; 
> this would be the logic that would raise the dialog if you clicked a link too 
> early.
> Once the Prototype dom:loaded event is fired, and all the normal JavaScript 
> initialization takes place (from what I gather about IE, it's still a good 
> idea to wait for dom:loaded, rather than simply putting the code at the 
> bottom of the page), part of the process would be to a) fade out the dialog 
> if showing and b) remove the onclick handler for any elements. This is 
> tricky, because the initialization code often adds onclick event handlers. 
> Perhaps the handlers can stay, but will be inactive because the page has 
> loaded.
> Anyway, this is how I think we should proceed. 
> I think this would keep compatibility with existing applications. 
> The cost would be: 
> - Slightly uglier HTML output (use of the "javascript:" psuedo-scheme)
> - Possibly slower render of page, as the browser waits for JavaScript to load
> - Increment increase in size of tapestry.js
> The advantage is less confusion on the client side and server side between 
> normal requests and Ajax partial render requests. The user can't "outrace" 
> the application anymore. 
> I'd like to see what people think of this plan and collect any comments or 
> observations I've missed.  

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to