Contents tagged with OpenAjax

  • Going to California

    I’m flying to San Jose tonight for tomorrow’s OpenAjax Alliance face to face meeting, which Microsoft is hosting. On Friday, we are also hosting a new event that aims at establishing a dialogue between JavaScript library developers and Microsoft. We’ll have talks from the IE, Visual Studio and ASP.NET teams, as well as talks from members of the community. This should be very interesting.

    Read more...

  • OpenAjax requests comments on browser wishlist

    The OpenAjax Alliance has been working with some of the top Ajax developers on a wishlist that aims at gathering and prioritizing the development features that we need the most from next generation browsers. The process is completely open and Wiki-based, so feel free to contribute.

    http://www.openajax.org/blogs/wp-trackback.php?p=53

    Read more...

  • OpenAjax InteropFest 1.0: Microsoft's entry

    Yesterday I got to write our entry in OpenAjax's InteropFest. The goal of this event is to demonstrate how different Ajax libraries can be parts of the OpenAjax ecosystem and interact with each other through the OpenAjax hub. The currently central feature of the hub is to expose a publish/subscribe message bus so that both producers and consumers of events can speak through a third party that is neutral to specific Ajax implementations.

    The OpenAjax Alliance provides a template for demo applications that shows a live data source feeding fake stock quotes through the hub to a visual component that then renders them.

    I've chosen to modify the live data source to be a Microsoft Ajax-style component. The visual component would not have been as interesting because it's really the application that is a consumer of events. The visual component itself doesn't strictly speaking communicate with the hub, the application does (through a trivial API call) and then transmits the results to the component for rendering. In other words, the data source is a lot more interesting because it exposes the event, and if it is a Microsoft Ajax component, it will use the Microsoft Ajax event pattern, which is quite different from the OpenAjax event pattern.

    I did refactor the consuming part of the application quite heavily, but that was more to understand it than anything and it's not the essential part of our entry.

    To achieve the mapping from Microsoft Ajax events to OpenAjax messages, I've written the following simple helper:

    Type.registerNamespace("Sys.OpenAjax");
    
    Sys.OpenAjax._Helper = function() {
    }
    Sys.OpenAjax._Helper.prototype = {
        mapEventToMessage:
    function(owner, eventName, messageName, publisherDataMapper) {
    var handler = function(sender, args) { OpenAjax.hub.publish(
    messageName,
    publisherDataMapper ?
    publisherDataMapper(sender, args) : null); } owner["add_" + eventName](handler); return handler; }, unmapEvent:
    function(owner, eventName, map) { owner["remove_" + eventName](map); } } Sys.OpenAjax._Helper.registerClass("Sys.OpenAjax._Helper"); Sys.OpenAjax.Helper = new Sys.OpenAjax._Helper();

    The application code can use that new API to map the events of any Microsoft Ajax component to become publishers of OpenAjax messages without any necessity for the component to contain any code specific to OpenAjax, let alone know about it. In other words, the component implementation remains completely decoupled from OpenAjax and it's the application that makes the connection.

    The application maps the quoteChanged event to the org.openajax.interopfest10.datagen.stockpriceupdate OpenAjax message like this:

    Sys.OpenAjax.Helper.mapEventToMessage(
        corpList, "quoteChanged",
        "org.openajax.interopfest10.datagen.stockpriceupdate",
        function (sender, args) {
            var quote = args.get_quote();
            return {
                tickerName: quote.symbol,
                corpName: quote.name,
                price: quote.price
            };
        }
    );

    From this moment on, all quoteChanged events will be published on the hub. An interesting thing to note is the use of an optional function that maps the Microsoft Ajax event argument to the expected OpenAjax data payload.

    Brad Abrams kindly hosts the demo on his personal website for the moment:
    http://brad_abrams.members.winisp.net/Projects/OpenAjax/index.html

    The source code can be downloaded by clicking here.

    Read more...

  • Microsoft Ajax events - part 2: exposing events from custom classes

     

    In part 1, I showed how to subscribe to events exposed by JavaScript classes built on Microsoft Ajax. In this post, I'll show how to expose new events from your own classes.

    Theoretically, the only things you have to do to expose an event are to implement "add_myEvent" and "remove_myEvent" methods that add or remove handlers, and to call all subscribers when relevant. In practice, managing the list of handlers for each event is really boilerplate code that you would have to reproduce for every event. This is why the Sys.Component base class exposes an events property that is an instance of Sys.EventHandlerList, which makes the event handler management a lot easier, and also has a few performance advantages. This is not a new pattern, System.Web.UI.Control also has an Events property of type System.ComponentModel.EventHandlerList, so if you know the .NET pattern you should feel right at home.

    Let's look at a very simple example for which we'll build a very simple timer component. Our timer will expose a single event: tick (in addition to the events the base class supports, but we'll get back to that in a moment). The code for the add and remove event accessors is really simple, and this is all you have to do to expose any event:

    add_tick: function(handler) {
        this.get_events().addHandler("tick", handler);
    },
    remove_tick: function(handler) {
        this.get_events().removeHandler("tick", handler);
    },

    The only thing that will vary in this code is the event name ("tick" here).

    Calling subscribers is done from the _tick private function of our Timer class:

    _tick: function() {
        var handler = this.get_events().getHandler("tick");
        if (handler) handler(this, Sys.EventArgs.Empty);
        // [...]
    }

    What's important in this method is how the _tick function gets a unique function reference for the "tick" event that will forward the calls to all subscribers. This makes Ajax events similar to .NET's multicast events. The function reference that getHandler returns can be null (in the case there are no subscribers) so it's important to test it before using it, but calling it is as simple as calling a regular function: the multicasting is entirely and internally handled by Sys.EventHandlerList.

    Note that this _tick function is wired using window.setTimeout from the start method as can be seen in the full source code. I also omitted the code that rewires the timeout for the next tick.

    It should be noted that the signature for the handlers is always (sender, arguments) where arguments are an instance of a class derived from Sys.EventArgs. Here, there's really no relevant information that we want to send to the handlers, so we're just using Sys.EventArgs.Empty, which is a special, empty instance of Sys.EventArgs.

    For your own events, you can build your own class that derives from Sys.EventArgs. You should clearly document that this new class works with your event. Typically, the new argument class should take a constructor parameter for each of the pieces of information you want to transmit to the handlers. There should also be a property getter for each of those, but there usually won't be a setter. The reason is that these arguments should most of the time be considered immutable. There are a few cases though when this is not true and the handlers should be able to communicate back to the event publisher. One example of that is cancellable events (see Sys.CancelEventArgs and its cancel property). What's important in those case is that handlers should never rely on the values of those mutable properties. Only the event publisher can do anything depending on them. In the cancellable case, for example, what setting cancel to true does is prevent an action that would have happened *after* all the handlers have been called, but it doesn't prevent the remaining handlers from being called.

    In the case of the Timer component, the event is raised by an externally happening source (the timeout feature exposed by JavaScript), which is why _tick is a private function. In some cases, it may be desirable to make it possible for public consumers of the class to raise the event. In this case, the convention is to expose a public method named "raise[event name]". For example, the base Sys.Component class exposes a raisePropertyChanged method that is typically called by derived classes to raise the propertyChanged event from the setters of properties that wish to advertise their changes.

    Most of the time though, the event will be raised as part of a larger operation, which is what's being exposed publicly, and there's no point in having a "raise..." method. Once more, an example of that can be found in Sys.Component: dispose raises the disposing event before it actually does its cleanup work.

    This pretty much covers what you need to know to implement your own custom events. In the next and final post in this series, I'll show how to integrate Microsoft Ajax events with the OpenAjax hub.

    Full code for the timer component:
    Timer.js.txt (rename to Timer.js before using that file)

    A sample page that uses the component:
    Clock.aspx.txt (rename to Clock.aspx and include in a Microsoft Ajax site with Timer.js to use)

    Read part 1 of this post:
    Microsoft Ajax events - part 1 - subscribing

    Read more...

  • Microsoft Ajax events - part 1: subscribing

    When building Ajax applications, you basically deal with two kinds of events. First, there are DOM events, and second, events from JavaScript objects. This second category is not part of the EcmaScript specs (or of the DOM specs, of course) so each framework needs to define its own pattern to expose events. This makes it more difficult for developers to include components built on different frameworks into a single page, which is one of the problems that OpenAjax tries to solve. I'll get back to this in a future post and show how to integrate Microsoft Ajax events in the OpenAjax hub.

    As with other parts of the Microsoft Ajax framework, we've tried to adhere to the .NET patterns as much as possible when we designed events in Microsoft Ajax. Events are defined by their "add" and "remove" accessors, which respectively add and remove handlers. For instance, PageRequestManager exposes a "beginRequest" event by exposing the "add_beginRequest" and "remove_beginRequest" methods. Both add and remove accessors have the same signature, which is that they take a single "handler" parameter of type Function.

    So handling an event is twofold. First, you must subscribe to an event, which is as simple as the following highlighted code:

    <%@ Page Language="C#" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Untitled Page</title> <script type="text/javascript"> function pageLoad() { var prm = Sys.WebForms.PageRequestManager.getInstance(); if (!prm.get_isInAsyncPostBack()) { prm.add_beginRequest(onBeginRequest); } } function pageUnload() { Sys.WebForms.PageRequestManager.getInstance()
    .remove_beginRequest(onBeginRequest); } function onBeginRequest(sender, args) { Sys.Debug.trace(args.get_postBackElement().value +
    " triggered a postback."); } </script> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager runat="server" ID="SM1"></asp:ScriptManager> <asp:UpdatePanel runat="server" ID="UP1"> <ContentTemplate> <asp:Button runat="server" ID="Button1" Text="Button 1" /> <asp:Button runat="server" ID="Button2" Text="Button 2" /> <asp:Button runat="server" ID="Button3" Text="Button 3" /> </ContentTemplate> </asp:UpdatePanel> <textarea id="TraceConsole" cols="40" rows="15"></textarea> </div> </form> </body> </html>

    This page starts by subscribing to the beginRequest event of the page request manager. The handler for the event which is passed to add_beginRequest, onBeginRequest, looks at the event arguments and displays the value of the button that triggered the postback in the trace console. This brings us to the second half of using events, writing the handler. All Microsoft Ajax event handlers, by convention, and exactly like in .NET, have a similar signature: they take two parameters, the event sender and the event arguments. The sender is the object that raised the event (in the example above, that would be the PageRequestManager) and the arguments are an instance of a type that derives from Sys.EventArgs. Many events will be associated with a specific argument class to enable the handler to get additional and specific information about the event. In the example above, we're using the postBackElement property of the arguments, which are of type Sys.WebForms.BeginRequestEventArgs. Similarly, the propertyChanged event on Sys.Component is associated with Sys.PropertyChangedEventArgs, which exposes a propertyName property that enables the handler to determine the name of the property that triggered the event. In other words, to learn how to properly handle an event, start by exploring its associated arguments class.

    In the next post, I'll show how to expose a custom event from your own classes:
    http://weblogs.asp.net/bleroy/archive/2007/05/22/microsoft-ajax-events-part-2-exposing-events-from-custom-classes.aspx

    Read more...

  • Microsoft joins OpenAjax

    OpenAjaxI'm extremely pleased to announce that we're joining OpenAjax today and that I'll represent the company in the organization's meetings starting this Thursday. This is a way for us to ensure that our user community can combine the Microsoft AJAX Library and ASP.NET 2.0 AJAX Extensions with other frameworks, today and in the future. Interoperability in the browser is a hard problem but it opens key Ajax scenarios. An industry-wide organization such as OpenAjax is a great way to ensure this goal is met in the long-term.

    Read more...