JQuery Related Posts by ThinqLinq

Select Many with Rx and RxJs

A while back, I showed how you could use the query syntax and Rx to code a drag-drop operation similar to the way you might describe  the process to your mother. As a review, let’s take another look at the code, this time in C# as a preparation for moving it over to javaScript.


var mouseDown = from evt in Observable.FromEventPattern<MouseButtonEventArgs>(image, "MouseLeftButtonDown")
                select evt.EventArgs.GetPosition(image);
var mouseUp = Observable.FromEventPattern&;lt;MouseButtonEventArgs>(this, "MouseLeftButtonUp");
var mouseMove = from evt in Observable.FromEventPattern<MouseEventArgs>(this, "MouseMove")
                select evt.EventArgs.GetPosition(this);

var q = from startLocation in mouseDown
        from endLocation in mouseMove.TakeUntil(mouseUp)
        select new
        {
            X = endLocation.X - startLocation.X,
            Y = endLocation.Y - startLocation.Y
        };

What might not be evident from this code is that the query syntax is actually using the SelectMany extension method when we use the from x in xs from y in ys above. If we wanted to, we could re-write this using the Lambda/method syntax as follows:


var q = mouseDown
        .SelectMany(startPos =>
              mouseMove
                    .TakeUntil(mouseUp)
                    .Select(movePos =>
                        new
                        {
                            X = movePos.X - startPos.X,
                            Y = movePos.Y - startPos.Y
                        })
                     );

Personally, I prefer the query syntax and find the lambda syntax a bit messy with SelectMany. Let’s try to tear this down a bit to see if we can understand what’s going on. Here we still have 3 different sets of Observables—mouseDown, mouseMove and mouseUp. The SelectMany extends mouseDown taking in the instance of each observed value as it is produced. SelectMany then takes a function (lambda) which will generate a new set of Observables of some other type which may or may not include values from the first observed value and values from the second variable.

In this case, we create the second observable set from the mouseMoves that we start listening to as the result of the SelectMany. We can then generate an new observable set by projecting (Select) the mouseDown’s startPos and mouseMove’s movePos offsets. For those who think pictures say more than words, here’s a marble diagram illustrating how SelectMany works:

image

In this case the Ox represents the MouseDown observables. fx represents the function supplied in the Lambda parameter and Oy represents the resulting Observable set of offsets. Wes and Jeffrey walk through SelectMany in their Channel 9 video as well.

Moving to RxJs

So what does all of this have to do with JavaScript? In the process of rewriting some of my Rx talks to RxJs, I wanted to include the MouseMove sample. Since JavaScript doesn’t support the syntactic sugar that enable query expressions, we are forced to use the method syntax. If you want to skip to the chase, you can download my RxJs samples and look at the DragDrop.htm to try this out. As we did with the Silverlight/WPF version of DragDrop, we start by setting up three sets of Observables to track the MouseDown, MouseMove and MouseUp events.


    <script type="text/javascript" src="Scripts/rx.js"></script>
    <script type="text/javascript" src="Scripts/jquery-1.4.1.min.js"></script>
    <script type="text/javascript" src="Scripts/rx.jQuery.js"></script>

    <script type="text/javascript">
        $(document).ready(function () {
            var dragTarget = $("img");
            var mouseUp = dragTarget.toObservable("mouseup");
            var mouseMove = dragTarget.toObservable("mousemove");
            var mouseDown = dragTarget.toObservable("mousedown")
                .Select(function (event) {
                    return {
                        left: event.clientX - dragTarget.offset().left,
                        top: event.clientY - dragTarget.offset().top
                    };
                });
    </script>
    <img alt="logo" src="Images/RxLogo.png" style="position: absolute; top:400; left:400; height: 100;
        width: 100" id="RxLogo" />

Now that we have our observables, we can merge the streams using SelectMany and subscribe to the end result to actually move the image on the screen by altering the css left and top positions accordingly.


            var moves = mouseDown.SelectMany(function (imageOffset) {
                return mouseMove
                        .Do(function (event) { event.preventDefault(); })
                        .Select(function (pos) {
                            return {
                               left: pos.clientX - imageOffset.left,
                                top: pos.clientY - imageOffset.top
                            };
                        })
                        .TakeUntil(mouseUp);
            });
            moves.Subscribe(function (pos) {
                dragTarget.css("left", pos.left);
                dragTarget.css("top", pos.top);
            });

With the exception of the JavaScript function syntax which I tend to think of as a hybrid of C# and VB’s lambda syntaxes, we essentially have the same code that we did with the C# lambda syntax for SelectMany.

It can take a bit of mind twisting to get your head around the lambda syntax for SelectMany, but once you’ve done that, you can start doing some powerful manipulations to extend and coordinate observable event streams in both .Net and RxJs.

Posted on - Comment
Categories: Rx - JQuery - C# -

devLINK RxJs and Async session materials available

I would like to thank everyone who came out to my DevLINQ sessions this week. The materials for both of the sessions are not available on the Files tab  of this site. In addition, here are the descriptions and direct links to each of these downloads:

  • Reactive Extensions for JavaScript (RxJs)
  • The Reactive Extensions allow developers to build composabile, asynchronous event driven methods over observable collections. In web applications, you can use this same model in client side processing using the RxJs framework. We'll show you how you can take advantage of this framework to simplify your complex asynchronous client side operations.

    Includes slides and samples demonstrating some of the uses of the Reactive Extensions for JavaScript (RxJs). The samples illustrate using RxJs for LINQ style queries, Timer based web page rotator, Mock observable sensor, Mouse drag drop, Dictionary Suggest, and Bing Translator over multiple languages.

  • Async Programming in .Net
  • While .Net 4 added parallel programming capabilities, these tools primarily help when your application is CPU bound. In many cases, parallel processing doesn't address IO Latency issues. In these cases, we need to provide the perception of responsive applications by using asynchronous programming tools. We will explore some of these options including Delegates, Callbacks, Iterators, Observers, and the new C# Async/Await keywords.

    Includes slides and samples demonstrating ways of performing Asynchronous operations from .Net 1.0 through .Net 5.0. In addition to the standard Visual Studio 2010 install, you will also need to download and in stall the following libraries to use these samples:

Posted on - Comment
Categories: Code Camp - C# - Rx - JQuery -

Using RxJs for an Image Rotator with jQuery

In trying to come up with some compelling demos for RxJs, I happened upon a scenario that some of you may find helpful. I wanted to create the ability to display images on a timer loop and keep looping through them while the user is on the page. I realize that there are a plethora of jQuery plugins that do this already, but  I have a new hammer (RxJs), I might as well see how well it works myself.

As I did in my port of the ObservableSensor in the last RxJs post,  let’s start by defining the presentation portion:

<!DOCTYPE html>
<html>
<head>
     <title>Observable Rotator</title>
     <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.2.min.js"></script>
     <script type="text/javascript" src="Scripts/rx.js"></script>
</head>
<body>
     <img id="imageRotator" alt="rotating" />
</body>
</html>

Clean and simple HTML5, except I didn’t set the source of the image. We’ll do that in our JavaScript code instead. Let’s get right to it then:

<script type="text/javascript">
    $(function () {
        var images = ["Images/image1.png",
                    "Images/somethingElse.png",
                    "Images/someAd.png",
                    "Images/JimHeadShot.jpg",
                    "Images/logo.gif"
                    ];

        $("#imageRotator").attr("src", images[0]);

        var delayedSites = Rx.Observable.GenerateWithTime(
             1,                                           // Starting index
            function (x) { return true; },                // Keep iterating always
            function (index) {               
                if (index < images.length - 1) 
                    return index + 1;                     // Increment index
                else
                    return 0; // if the current index exceeds the array bounds, reset the index 
            },
            function (index) { return images[index]; },  // OnNext
            function () { return 5000 });                // Time interval


        delayedSites
            .Subscribe(function (uri) {
                $("#imageRotator").attr("src", uri);
            });
    });
</script>

The start of this method should be easy enough. I’m setting up an array containing the locations of the images I want to rotate through. Of course, you could get this array from a xml file, json service request, using the FileSystemObject, or any number of other options. It doesn’t matter how you get the array.

Once we have the array, we’ll go ahead and populate the first item in that array as the starting image using the jQuery attr method setting the src attribute to images[0].  With that out of the way, we’re ready to start with the RxJs goodness.

In order to push out items from our array, we could use Rx.Observable.FromArray which is the same as the .ToObservable extension method in .Net, however we would need to set-up a custom scheduler to handle the delay. Instead, we’ll just use the GenerateWithTime method to pull items from the array OnNext passing in a time delay (30000 for 30 seconds). We also check to see if the current iteration index exceeds the number of items in the list and if so, reset the index to start looping from the start again.

Now that we are sending out new image uri’s every 30 seconds, we simply need to change the src attribute of the imgageRotator img tag, which we’ll do as the function we pass into the Subscribe method.

Naturally, there are plenty of enhancements that can be done to this example, including randomizing the starting index, setting the size of the imageRotator to keep all of them the same, adding jQuery fadeIn/fadeOut and other animation effects, etc. I’ll leave these tasks as an exercise for the reader.

My question dear reader is, do you thinq that the RxJs version is any better or worse that other image rotator examples you’ve seen? Why?

Posted on - Comment
Categories: Rx - JQuery -

VB Syntax Highlighting with JQuery and Chili

At CodeStock, I attended Rod Paddock's intro to JQuery session since I hadn't played with JQuery yet. As often happens when I go to conferences, being in the different environment starts to get the mind thinking in different ways. Sometimes the benefit of the conference isn't necessarily something stated directly, but rather a thought when the mind wanders. One such thought occurred during Rod's presentation where I thought that it might be interesting to "query" sets of text over a larger document and apply formatting to selected words (similar to how Visual Studio colors keywords and other code elements).

A quick search on syntax highlighting found that I was not alone thinking that JQuery might be a good option for syntax highlighting. Chili is a JQuery based code highlighter that already supports a number of languages. It is relatively easy to incorporate into the site. First, you need to add a script reference to JQuery by adding the following:

<script type="text/javascript" src=http://jquery.com/src/jquery-latest.pack.js" />

Next, we add a link to the chili script code:

<script type="text/javascript" src="jquery/chili/jquery.chili-2.2.js" />

Third, we designate the path that contains the various language specific implementation details in a script block:

<script id="setup" type="text/javascript"> 
    ChiliBook.recipeFolder = "jquery/chili/";
</script>

Now, when we want to add highlighting to our code, we include it inside a <code> tag that is assigned to the class name of the language we want to colorize. Unlike the popular SyntaxHighlighter, Chili doesn't require you to specify the location of each language individually. It loads it dynamically based on matching up the file name with the class name.

To see how I added colorization to the source on the above code, see how the actual code is wrapped by a <code class="js"> … </code> tag. In this case, there is a js.js file in the recipeFolder that Chili uses to highlight this code. In addition, I'm wrapping the code tag inside a pre tag to eliminate otherwise unnecessary markup (like &nbsp; and <br />). This makes copying and pasting the code easier.

<pre><code class="js">


  <script id="setup" type="text/javascript">
     ChiliBook.recipeFolder = "jquery/chili/";
  </script>
</code></pre>

There's a problem with directly integrating Chili into this site however. Chili does not include a native VB syntax highlighter. However, adding new code definitions is as simple as adding a new .js file containing a collection of JSON objects defining what terms are to be colorized and how the styles should be applied. For the current VB implementation, I've added the following colorizations:

  • Comments are green
  • String literals are red
  • Processing instructions (like #Region and #If) are silver
  • Keywords and LINQ keywords are #4040c2
  • XML Literal expression hole symbols (<%= and %>) are a bit different as they use a yellow background with dark gray foreground, but we can easily set this through the style tag.

To do this, we set up a JSON structure to contain the various Regular Expression match patterns and the corresponding styles:

{
      _name: "vb"
    , _case: true
    , _main: {
          com    : { 
              _match: /'.*/ 
            , _style: "color: green;"
        }
        , string : { 
              _match: /(?:\'[^\'\\\n]*(?:\\.[^\'\\\n]*)*\')|(?:\"[^\"\\\n]*(?:\\.[^\"\\\n]*)*\")/ 
            , _style: "color: red;"
        }
        , preproc: { 
              _match: /^\s*#.*/ 
            , _style: "color: silver;"
        }
        , keyword: { 
              _match: /\b(?:AddHandler|AddressOf|AndAlso|Alias|And|Ansi|As|Assembly|Auto|
Boolean|ByRef|Byte|ByVal|Call|Case|Catch|
CBool|CByte|CChar|CDate|CDec|CDbl|Char|CInt|Class|CLng|CObj|
Const|CShort|CSng|CStr|CType|Date|Decimal|Declare|Default|Delegate|
Dim|DirectCast|Do|Double|Each|Else|ElseIf|End|Enum|Erase|Error|Event|Exit|
False|Finally|For|Friend|Function|Get|GetType|GoSub|GoTo|Handles|
If|Implements|Imports|In|Inherits|Integer|Interface|Is|Let|Lib|Like|Long|Loop|
Me|Mod|Module|MustInherit|MustOverride|MyBase|MyClass|
Namespace|New|Next|Not|Nothing|NotInheritable|NotOverridable|
Object|On|Option|Optional|Or|OrElse|Overloads|Overridable|Overrides|
ParamArray|Preserve|Private|Property|Protected|Public|
RaiseEvent|ReadOnly|ReDim|REM|RemoveHandler|Resume|Return|
Select|Set|Shadows|Shared|Short|Single|Static|Step|Stop|String|Structure|
Sub|SyncLock|Then|Throw|To|True|Try|TypeOf|Unicode|Until|Variant|
When|While|With|WithEvents|WriteOnly|Xor)\b/ 
            , _style: "color: #4040c2;"
        }
        , linqkeyword: { 
              _match: /\b(?:From|Select|Where|Order By|Descending|Distinct
|Skip|Take|Aggregate|Sum|Count|Group|Join|Into|Equals)\b/ 
            , _style: "color: #4040c2;"
        }
        , xmlexpressionhole: {
              _match: /\<%=|\%>/
            , _style: "background: #fffebf; color: #555555;"
        }
    }
}

If you want, you can download this file at http://www.thinqlinq.com/jquery/chili/vbasic.js. Now, to use the new definition, simply add the file to the path you defined as the chiliBook.RecipeFolder above. Then add code to your page like the following:


<pre><code class="vbasic">
Private Function FormatCategories(ByVal post As PostItem) As String If post.CategoryPosts.Count > 0 Then 'Categories found. Return them Dim response = _ From catPost In post.CategoryPosts _ Select val = _ <span> <a href=<%= "default.aspx?CategoryId=" & _ catPost.Category.CategoryId %>> <%= catPost.Category.Description.Trim %></a> </span>.ToString() Return String.Join(", ", response.ToArray) Else Return "" End If End Function
</code></pre>

There are a couple issues with this implementation: First, the highlighting only works if you view the page on the site. If you are viewing this through an aggregator, you won't see the syntax highlighting. Personally, I find this to be an acceptable tradeoff to the alternative--injecting the styles inline with the code as is done with the CopySourceAsHtml project or the Windows Live Writer VSPaste plug-in. Although the code is correctly highlighted when viewed from an aggregator, it is horrendous when consumed by a reader for the blind with screen reader systems.

The second issue with this implementation is that it doesn't take context into account. As a result, if you have an object with the same name as one of the keywords, it will be highlighted  incorrectly. This will become more of an issue in VS 2010 when we (finally) get type colorization in VB. To do type colorization, we need access to the object symbols which are unavailable outside of the compiler's environment.

The third issue is that this version doesn't correctly colorize the XML Literals. While I'm sure it is possible, I'm not enough of a Regular Expression expert to figure out all of the options required to enable syntax highlighting for the XML Literals. If someone wants to add that, I would love to try out your suggestions.

Posted on - Comment
Categories: VB - JQuery - VB Dev Center -