jQuery-UI and draggable flash video problems

Friday, July 10, 2009 No comments »

During my recent work with jQuery-UI, I discovered that on Safari, the embedded flash videos cannot be played if they are made draggable using the draggable plugin (http://dev.jqueryui.com/ticket/3575). Providing an inconsistent UI for our users on a browser used by approximately 8.5% (and rising, based on reports by hitslink http://marketshare.hitslink.com) of internet users, I investigated a little more about what the root cause of the issue was and found out that the issue manifested itself on Firefox in a different way. On Firefox 3, the flash video, once dragged, would just get stuck to the mouse and continue to drag even after the user let go of it. In other words, it was a “sticky” situation.

Turns out that jQuery-UI (version 1.7.1) prevents the default action for the mouse events – mousedown, mouseup, click – on the elements it’s plugins(or widgets) attach to. This is done by the mouse interaction handler plugin ($.ui.mouse) for the widgets. Instead the mouse plugin calls handlers for mouseStart, mouseDrag, mouseStop, and mouseCapture that the widgets override to handle mouse interactions.

I am not quite sure why that choice was made (http://groups.google.com/group/jquery-ui-dev/browse_thread/thread/ee35fd30ae7f7fe1) but apropos this problem, it seems an inconsistency introduced in jQuery 1.6 rc2.5 might explain atleast the behavior on Firefox. A change from jQuery 1.6rc2, the mouse plugin in 1.6rc2.5 doesn’t prevent the default action for mouseDown but does so for mouseUp.

With this information, here are the problems, causes, and solutions for the two browsers on which the draggable flash doesn’t work with by default :

Browser: Firefox 3

Problem: The video gets stuck to the cursor and continues to drag even after the primary primary mouse button is released.

Cause: The mouseup never reaches the draggable element (in my case, a div) which never receives a mouseUp event, and subsequently, doesn’t know when to stop dragging.

Solution: Attaching a mouseUp handler to the main video (”embed” in my case) tag and triggering a manual ‘mouseUp’ on the parent element from within the main video element’s mouseUp handler.

Browser: Safari 3

Problem:Controls on a draggable flash video do not respond. The video cannot be played or interacted with.

Cause: The major mouse events (mouseup, mousedown, click) never reach the flash video – which does respond to mouseOver and mouseOut though – and so the video is un-playable and un-interactable.

Solution: Change the jQuery-UI mouse plugin ( for jQuery-UI version 1.7.1: function _mouseUp in class $.ui.mouse in file ui.core.js) so that the mouseUp handler doesn’t prevent the default action for the mouseUp event. This is accomplished by changing the return value of the handler from false to true.

For a good introduction to events, you might want to read Peter-Paul Koch’s “Introduction to Events” at http://www.quirksmode.org/js/events_early.html. He also has very clearly-written and lucid introductions to various other front-end engineering concepts.

Finally, this problem is being tracked in jQuery-UI bug #3575 (http://dev.jqueryui.com/ticket/3575). I have submitted a fix for this problem in that bug (a patch on ui.core.js version 1.7.1) and hope it will get picked in the next release.

YUI vs jQuery : YAHOO.util.Connect vs $.ajax

Sunday, June 7, 2009 2 comments »

After defining the YQL tables for the RTM API (now a part of the main yql-tables on github : http://github.com/spullara/yql-tables/tree/master), I set out to build an example to show how they could be used. The YUI example is at : http://www.vipulb.com/yql/rtm1.html and the jQuery example is at : http://www.vipulb.com/yql/rtm.html

Having been used both YUI and jQuery in big projects before, I thought I would build an example using each library’s ‘Connection Manager’ to fetch data through YQL. YQL data can be fetched using Javascript even though it’s a cross-domain HTTP request since YQL supports the jsonp method (http://ajaxian.com/archives/jsonp-json-with-padding) of getting data.

Since the RTM API uses 3-legged-oAuth, multiple crossdomain requests had to be made with different callbacks for different requests. jQuery supports jsonp inherently so it was fairly straightforward to make that happen :


$.ajax({
url:query,
dataType:'jsonp',
success: successFn,
error: function(){}
});

The YUI library doesn’t differentiate between normal requests and jsonp requests so the developer has to append a “callback=func” to the URL manually in order to use the jsonp method of calling back a function on a successful HTTP return :


var yuiQuery = query + "&callback=func";

Also,  in this case, the callback function (’func’ here) must exist in the global namespace. In most simple cases, this is not a problem since all json requests are handled by one global function. However, in cases where different callbacks need to be called for different requests, extra code must be written.

Consider, for example, this case where the application needs the user to authenticate itself at the RTM website and grant authorization to the application, and then display the user’s to-do list. There are two YQL calls, one to obtain the authentication URL, and the other to obtain the to-do list once the user has finished the authentication process. A single function couldn’t handle the successful return of both the requests since different actions need to be taken in each case.

One way of solving this problem – which is how the jQuery library does this as well – is to create a new temporary callback in the global namespace for each request. Once a successful return for that request has been handled, the callback is removed from the global namespace. Here is the code to achieve that :


globalAjaxCallback = function(callbackFn) {

if( (typeof globalAjaxCallback.count).toLowerCase() == "undefined") {
globalAjaxCallback.count = 0;
}

var newCbName = "callbackFunc" + (++globalAjaxCallback.count);
window[newCbName] = function(jsonData) {
callbackFn(jsonData);
window[newCbName] = null;
delete window[newCbName];
}

return newCbName;
};

The ‘globalAjaxCallback’ function generates, and returns the name of, a temporary function in the global namespace ( ‘callbackFunc’ suffixed with a count ) for a particular request. The generated function, when called (on a successful return), calls the callback function specified by the user for that request, and then deletes itself from the global namespace. The error function should also clean up this temporary function from the global namespace, but for the sake of brevity (and laziness), it has been omitted for now.

YQL Execute and Remember the Milk

Monday, May 25, 2009 No comments »
RTM Logo

To experiment with Yahoo!’s new YQL Opentables, I created a few YQL tables to allow access to a user’s to-do list maintained at Remember The Milk (RTM) (www. rememberthemilk.com). The tables are currently available under the rtm folder under the yql-tables project in my github account (http://github.com/vipulb/yql-tables/tree/master)

I have also uploaded an example of how to use the tables and access the user’s to-do list at : http://vipulb.com/yql/rtm.html. The example uses jQuery and the open source RTM helper javascript library at : http://rtmapihelper.googlecode.com (a by-product of this project).

The RTM API uses a 3-legged-oAuth-like protocol to authenticate and authorize the application which can then call API methods to access and interact with the user’s to-do list.

I have currently defined the following four tables. (Note: The ‘user‘ below refers to the person who’s to-do list is being accessed. The ‘application‘ is the web-application trying to access the list)

  • rtm.auth.frob.xml: Used to obtain the initial frob and start the authentication process
  • rtm.auth.oauth_href.xml: Used to obtain a URL that the user can navigate to, enter his/her credentials and authorize this application to access his/her to-do list. Querying this table requires a frob obtained using the rtm.auth.frob table, and hence, a query to obtain this URL can include a sub-select which queries the rtm.auth.frob table. The table documentation has an example of this.
  • rtm.auth.token.xml: Used to obtain an authentication token used when the application calls API methods to interact with the user’s to-do list. This table is used ‘after‘ the user has authorized the application.
  • rtm.tasks.xml: Used to fetch the user’s task-list.

Finally, this being just a first version, there are bound to be loose ends.

Comments, criticism, questions, are all welcome.