LA.NET [EN]

JavascriptArchive

Nov 15

Quick tip: measuring the performance of your JS code? Don’t hit F5 from VS!

Posted in Javascript       Comments Off on Quick tip: measuring the performance of your JS code? Don’t hit F5 from VS!

Today’s post presents a quick tip: if you’re interesting in measuring the performance of your web app (also applicable to Windows Store apps written in JS), then don’t start it by hitting F5 in VS. IF you start your app in debug mode, your JS code won’t be JITed and the results will be different from the ones you get when you load your app directly in the browser.

Oct 28

Undefined? Didn’t you mean undefined?

Posted in Javascript       Comments Off on Undefined? Didn’t you mean undefined?

After publishing my latest post, I’ve received a couple of emails from fellow readers asking me if I didn’t mess up things when I’ve mentioned Undefined. Shouldn’t it be undefined? And the answer is no, I didn’t make an error because I was talking about types (and not about values). This kind of detail is important if you intend to become a proficient JavaScript developer (which means reading the spec). So, if you read the spec, you’ll see that it talks about the Undefined type and about the undefined value.

Undefined is a type whose sole value is undefined (notice the lower case u). The undefined (lower case u again!) value is a primitive value (recall that Undefined is one of the primitive types) that is used when a variable hasn’t been assigned a value. Here’s an example:

var aux;
//aux === undefined is true

To sum up, whenever you declare a variable and don’t initialize it, it will end up with an undefined value. Notice that the existence of undefined value lets you distinguish between declared variables that have been initialized or not. Take a look at the following example:

var aux;
//aux ===  undefined is true
var aux2 = null;
//aux2 === undefined is false

As you can see, you can initialize a variable to null. When this happens, the value no longer returns undefined, but null. null is also a primitive value and it was introduced in the language to represent the intentional absence of any value (notice that a variable initialized or set to null has been initialized and that means it’s not undefined). Since we’re talking about null, I’m going to take this opportunity to mention that null is the only value of the primitive Null type (yes, we have those nasty case differences between type and value again Smile).

And I guess that it’s all for now. Stay tuned for more!

Oct 21

So, what is an object in JavaScript?–part I

Posted in Javascript       Comments Off on So, what is an object in JavaScript?–part I

After publishing my previous post, I’ve received some questions from friends which make me believe that I probably need to elaborate further on my “what is an object in JavaScript thesis”. So be it. If you’ve read the previous post, you probably remember me writing this:

“In JavaScript, you can think of objects as being containers for key/value pairs.”

Well, it’s not completely wrong, but the truth is that there’s a little more to an object than that and ECMAScript5 has made those little things more visible than ever. So, here’s a better definition of what an object is in JavaScript (taken from the ECMAScript 6 draft):

“An ECMAScript object is a collection of properties each with zero or more attributes that determine how each property can be used—for example, when the Writable attribute for a property is set to false, any attempt by executed ECMAScript code to change the value of the property fails.”

Did you notice the attribute part that is applied to each property? Yes, that’s the part I’ve omitted from my initial definition and that is an important part of how you can create objects from ECMAScript5 onwards. In practice, ECMAScript5 introduces several methods which allow us to influence the way a property is created and we’ll come back to them in a future post.

Notice that properties of an object will always hold other objects which will also have its own properties, primitive values or functions. Currently, ECMAScript defines primitive type as a value of one of the following types: Undefined, Null, Boolean, Number and String. If a value doesn’t belong to one of the previous types, then it is an Object. “What about functions?”, you ask. Well, functions are special types of objects which can be “called” (ie, you can use them with the () operator in order to get a result back). Besides Object and primitive values, the spec introduces several predefined types (aka ECMAScript entities or objects) that we can use in a program (ex: Date, RegExp, etc.) and some predefined operators.

And I’d say that this is a better (though still formal) definition of an object. In the next post, we’ll dig a little deeper and see how the spec “lays” objects in memory.

Oct 18

By now, I think there’s no doubt about how important JavaScript is. And that’s why I thought it would probably be a good idea to write a little bit more about it. By doing it, I’ll refresh my memory and I’m also hoping to learn one or two new things that I might have missed before. To get things started, I’ve decided it would probably be a good idea to talk about object construction in JavaScript.

In JavaScript, it’s common to create an object by writing code like this:

//option 1: literal
var obj1 = {};
//option 2: construtor -> bad
var obj2 = new Object();
//option 3: so ECMAScript 5
var obj3 = Object.create(Object.prototype);

In practice, you’ll probably see option 1 used often. Option 2 is really a bad practice and you shouldn’t use it (I’m not sure if I can remember seeing option 2 used in the real world…). Option 3 is only available if your runtime is compatible with ECMAScript5 (I’ll return to it in a future post). Notice that all of these options produce the same result: an empty object.

In JavaScript, you can think of objects as being containers for key/value pairs. After creating an instance, you can use the . notation for adding a new property or changing the value of an existing property. Alternatively, you can resort to the [] notation for accessing a property. Here’s an example:

obj1.name = 'Luis';
obj2['name'] = 'Luis';

Once again, the previous instructions end up generating similar results. In both cases, you’ll end up with an object that has a name property and whose value is set to Luis. If you’re creating a new object with the literal syntax, then you can do it all at once:

var obj1 = { name: 'Luis' };

By now, you’ve probably noticed why the literal syntax is used so often. There’s still an alternative way of creating properties which is more powerful, but only compatible with ECMAScript5 (we’ll leave it for a future post). Going back to object creation, there’s still a final approach: we can create a function and use it as a “constructor”. A function is “transformed” into a “constructor” when it’s prefixed with the new keyword during its invocation. Here’s a quick example of how you can build a simple object by using a constructor:

function Person(name) {
    this.name = name;
}
var p = new Person("Luis");

In this case, you’ll also end up with an object which has a single property name, whose value is also set to Luis. Even thought the results  are similar, there are some important differences between the objects created. For instance, if you check the constructor property, you’ll notice that p returns a reference to Person while obj1 returns a reference to Object. As we’ll see, this difference might be important, but for now, we don’t have to worry about it because we’re simply interested in creating objects.

If you’re coming from a strongly typed language like C# or Java, you might be thinking that our last approach (where we created a function that is used as a constructor) is the way to go when you need to create objects in JavaScript. Well, it might be a viable option, but as you’ll see, it typically isn’t the way to go when you’re working in JavaScript.

And that’s it for now. Stay tuned for more.

PS: does anyone have any suggestion on how to format the code  before pasting it in Windows Live Writer? I’m using code snippet for  now, but I’d prefer to have a dark scheme for my code…

Jul 18

The wrapper object trick

Posted in Javascript       Comments Off on The wrapper object trick

Whenever people ask me what I think about the JavaScript wrapper objects (ex.: String, Number, etc.), I tend to tell them that it’s better to forget that they exist and simply use the literal values (and simply let the runtime perform the conversions between literal an wrapper object automatically and whenever it’s needed). I tend to abide by this rule but today, when I was talking to an old friend, I remember an trick which I’ve learned some time ago which justified the direct use of the wrapper object: I’m talking about (what I call) the wrapper object trick. Here’s some code which illustrates its use:

var someObject = new Boolean(true);
someObject.someOtherProperty = true;
someObject.somethingElse = { id: 1, name: "hello" };

If you’re a Modernizr user, then you’ve probably recognize this kind of object! No…really? ok, then take a look at the following Modernizr tests:

if (Modernizr.video) {
    if (Modernizr.video.ogg === "probably") {
        
    }
}

And now you’ve probably understand what I’m talking about, right? What we’re doing is taking advantage of the fact that Boolean is an object and that means we can add properties to it. If you take a look at the Modernizr source code, you’ll notice that it’ll only create an object whenever it knows that the receiving literal Boolean is true. And there’s a reason for that behavior: since new Boolean ends up creating an object, then a Boolean instance will always evaluate to true in any test. Here’s an example of what I mean:

var someObject = new Boolean(false);
if (someObject) { //alwayks true
    console.log("true???");
}

So, we need to change the code so that it behaves correctly. Here’s how you’re supposed to write the previous snippet:

var aux = (function (initValue) {
    if (initValue) {
        var someObject = new Boolean(initValue);
        someObject.someOtherProperty = true;
        someObject.somethingElse = { id: 1, name: "hello" };
        return someObject;
    }
    return initValue;
})(true);

 

And now, it all depends on the values you pass to the anonymous function. If you pass it false, then that’s it: you’ll end up with a literal false Boolean. If you pass it true, then you’ll get a slightly modified Boolean object. Unfortunately, I forgot to add this technique to my JavaScript book. If you’ve bought it, please add an URL to this post on section 7.2 Smile

And that’s it for now. Stay tuned for more.

Jan 03

undefined and NaN changes are no longer permitted in ECMAScript 5

Posted in Javascript       Comments Off on undefined and NaN changes are no longer permitted in ECMAScript 5

Happy New Year to everyone! After a small vacation period, I’m back :,,)

Now that the HTML book has gone to revision (more about that in future posts), I guess it’s time to start posting some useful tips in this blog. One of my new year’s resolution is to pay much more attention to JavaScript and that’s why I’ve chose this topic for this year’s first post. If you’ve been reading my blog, you’ll probably recall an old post where I advert for the possibility that anyone can redefine the global undefined and NaN variables. Since this might end up producing some very undesirable effects, I’m really happy to find out that ECMAScript 5 (ie, the JavaScript specification) has forbidden this type of information.

To be more precise, the value properties Nan, Infinity and undefined introduced by the Global Object can’t be changed or configured, nor can they be enumerated in a for–in enumeration. What does that mean? Take a look at the following sample:

<!DOCTYPE html>
<html>
  <head>
    <title>Testing undefined assignment</title>
    <script>
      alert(undefined);
      undefined = "hi";
      alert(undefined);
    </script>
  </head>
  <body></body>
</html>

Now, if you run the previous code in IE9 or in FF 4 (or even in Safari 5), you’ll end up getting the string undefined twice. Notice that you don’t end up getting an exception. You won’t simply be able to change the value…it’s as if you never run the undefined assignment…

Unfortunately, not all browsers are compatible with this new behavior, but I’m thinking that it won’t take long until all of them are compatible with the specs. And that’s it for now. Stay tuned for more  JavaScript posts.

Sep 22

Oh damn! Can’t you see that’s a constructor?

Posted in Javascript       Comments Off on Oh damn! Can’t you see that’s a constructor?

Even though I’ve been in Silverlight/C#/WCF land in these last months, the truth is that I’ve always been a JavaScript aficionado. In fact, if you’ve been reading my blog, you’ll probably recall a small series I’ve done on it a few months ago(if not, then don’t worry: you can still read it here). After speaking with a friend today, I think I might have missed a cool advice on how to define constructors in JavaScript.

As we all know, JavaScript OO programming is a little different from what we’re used to in traditional languages like C# or Java. You see, you can’t really reuse the same style of programming because things work in a completely different way in JavaScript land. Anyway, I still believe that it’s one of the coolest, more flexible languages you can use  (provided you don’t try to write JavaScript a la C# or Java). I’m not really getting into details here, but there are times where you want to create a constructor. oh, and yes,in JavaScript a function can be a constructor. And this is where problems might occur. Let’s start with a simple example:

var Point = function (x,y) {
    this.x = x;
    this.y = y;
}

var pt = new Point(1, 1); //correct usage
var anotherPt = Point(1, 1);//hum…not the intended usage

Ok, so can you see what’s happening here? Btw, before you start laughing, I’ve seen this happen  in the past (yes, in the real world!). When Point was created, it was meant to be used as constructor. But that doesn’t mean that a rookie or someone who is not paying attention can’t  call the Point function directly without using the new instruction. When that happens, the this special variable won’t point to a Point instance. In this case, it was probably referencing the window object, but it all depends on the existing context at time of invocation.

Now, if you’re writing frameworks, this is really a nightmare. You need to have some way of not allowing this. The good news is that there’s a way to fix this and it involves using the instanceof operator in 2 or 3 lines of code. Take a look at the next snippet:

var Point = function (x, y) {
    if (!(this instanceof Point)) {
        return new Point(x, y);
    }
    this.x = x;
    this.y = y;
}

And that’s it! really! When the function is invoked, we start by checking if this points to an instance of Point. When you use new, this does reference a Point instance. However, that doesn’t happen when you call the Point function as a function. With this small change, you’re ensuring that you’ll always get a new initialized Point instance from that method. Wasn’t that easy enough? And that’s it for now. Stay tuned for more.

Nov 30

I’d like to apologize for the lack of posts lately…no, I haven’t given up in my Silverlight series, but I’ve been busy updating my existing ASP.NET book to the 4.0 version. It seems like I will have a lot of work (much more than I had anticipated, but the truth is that I really enjoy writing about technical stuff) so the Silverlight series won’t really go as fast as the one on MS AJAX…sorry for that…now back to business :,,)

I really didn’t gave it any thoughts until I spoke with a friend who he asked me about the options we have for requiring a script (when using MS AJAX, of course!). So, lets see…we can specify it by:

  • using the scripts object : Sys.scripts.Core loads the basic MS AJAX JavaScript file
  • using the components object: Sys.components.dataView loads all the JavaScript files required for using the DataView component;
  • using the plugins object: Sys.plugins.bind will load all the JavaScript file required for using the bind method;
  • name: “History” will load all the scripts required for supporting the history feature.

All of them requires that you “define” your scripts in a JavaScript file which must be included in the page after the start.js file. And the best thing is that you can mix them all when using the Sys.required method. Fantastic, right?

Nov 24

Some observations on MS AJAX and JQuery integration

Posted in Javascript, MS AJAX       Comments Off on Some observations on MS AJAX and JQuery integration

In my last post, I’ve talked a little bit about the new plugins introduced by the latest release of MS AJAX (beta, at the time of writing). One of the things that didn’t enjoy much was that I had to call the JQuery’s get method in order to get a reference to the DOM element array. What I was forgetting was that MS AJAX has really good integration with JQuery (something that Dave Ward was kind enough to reminded me).

In practice, this means that I can simply pass a string with the selector I want and I’ll automatically get the correct DOM element array. here’s the updated code:

<script type="text/javascript">
  Sys.require(
        [Sys.scripts.jQuery, Sys.scripts.ComponentModel],
        function () {
          $.addHandler(
                "input",
                "click",
                function (evt) {
                  alert("JQuery: " + evt.target.id);
                });
        }
    );
  </script>

Notice that you can use more complex selectors too. All the selectors which can’t be interpreted by MS AJAX will be delegated to JQuery. As you can see, MS AJAX is becoming a really cool lib, don’t you think?

Nov 23

MS AJAX beta – new plugins

Posted in Javascript, MS AJAX       Comments Off on MS AJAX beta – new plugins

The MS AJAX beta release adds some new plugins to the previous ones. Besides the existing setCommand and bind, we now have access to the following plugins:

  • addHander: you can use this plugin to set up a handler for one event fired by one or several DOM elements;
  • removeHandler: as you can probably guess from its name, you can use this to cancel an existing DOM event subscription;
  • addHandlers: similar to the addHandler. However, in this case you can hook up several events (instead of passing the name of the event, you’re supposed to use a literal JS object where you specify the events and corresponding handlers);
  • clearHandlers: used for cancelling all event subscriptions that have been previously setup;
  • activateElements: used for activating the indicated elements with a specific binding context. Generally, you get activation for free. However, there are a couple of times where  you may need to activate an element explicitly. In those cases, this is the quickest (and shortest – yes, I’m counting key strokes) way to do that.

I’m not sure if you recall it, but plugins get promoted to Sys helper methods. Take a look at the following code which shows how to use the addHandler plugin to hook up the click event over all the existing buttons:

<head runat="server">
 <script type="text/javascript" 
src="Scripts/MicrosoftAjax/Start.debug.js">
</
script> <script type="text/javascript"> Sys.require([Sys.scripts.ComponentModel], function () { var buttons = document.getElementsByTagName("input"); Sys.addHandler(buttons, "click",function (evt) { alert(evt.target.id); }); }); </script> </head> <body> <input type="button" id="bt1" value="Button 1" /> <input type="button" id="bt2" value="Button 2" /> <input type="button" id="bt3" value="Button 3" /> </body>

Whenever you click over a button,you should get an alert message with the ID of the button. Now, since we’re talking about handlers, here’s how you’d use the addHanders plugin:

Sys.addHandlers(Sys.get("#bt1"),
    {
        click: function (evt) {
            alert("bt-1");
        }
    }
    );     

As you can see, I’ve used a literal JS object for specifying the events I want to handle. You should only use this plugin when you want to pass several handlers to different events. Notice that both plugins (addHandler and addHandlers) expect a reference to one or more DOM elements (you can see how to pass several references in the first snippet; the second passes a single DOM element reference). That’s why you should only use the second (addHandlers) when you need to setup several events at once.

Here’s what you get when you click “Button 1” after adding the last snippet to the page:

addHandlers

Notice that if you add this last snippet to the previous page, you should see two alert messages because you’re effectively adding two handlers to “button 1” click event.

One of the nicest things about plugins is their integration with JQuery. For instance, take a look at the following code:

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <script type="text/javascript" 
src="Scripts/MicrosoftAjax/Start.debug.js"></script> <script type="text/javascript"> Sys.require(
[Sys.scripts.jQuery,Sys.scripts.ComponentModel],
function () { $.addHandler( $("input").get(), "click", function (evt) { alert("JQuery: " + evt.target.id); }); } ); </script> </head> <body> <input type="button" id="bt1" value="Button 1" /> <input type="button" id="bt2" value="Button 2" /> <input type="button" id="bt3" value="Button 3" /> </body> </html>

As you can see, I’ve started by requiring JQuery and the MS AJAX JavaScript files needed for using the addHandler method (oh, btw, I could have specified the dependency through the Sys.plugins.addHandler too). After getting all the files, my anonymous callback function will be called and that’s where everything interesting is happening.

There’s an addHandler method which got added to the jQuery object (aliased to the $) during JQuery loading. Notice that the addHandler plugin still expects the same arguments and that’s why we need to use the JQuery’s get method to get a reference to an array with all the DOM elements of the internal wrapped set.

This behavior is pretty cool and also works with other plugins. The only thing you should keep in mind is that non-behavior/control plugins always get added to the $ object; on the other hand, behaviors/controls get added to the $.fn object (and that means that these plugins are “transformed” into “instance” methods of the JQuery object – take a look at this post to see what I mean).

And that’s it”. Stay tuned for more on MS AJAX.

Nov 23

In the last week, MS AJAX beta was released during PDC 2009. One of the things that this released added is ACT script loader support. If you go into the samples, you’ll see that there is an Extended folder which holds all the client files for the behaviors and controls exposed by the AjaxControlToolkit.

extended

The code files have all been updated so that its” definitions are wrapped into an execute function (which is also placed inside an anonymous function). As you probably recall from previous posts, this function is called when all the dependencies have been loaded. Notice that  with the previous CTP you could download the ACT from codeplex and make the changes present in all the files that come with this release. In other words, wrapping all the code within functions is the easiest part when you want to adapt an existing script so that it can be used with the new script loader component.

To me, the most important script file is the ExtendedControl Javascript file because it contains all the definitions (and dependencies) required by all the ACT controls. In practice, this means that you can simply drop this file on a page (plus the base start.js Javascript file) and use any of the ACT controls. Don’t believe me? Here’s some demo code which uses the calendar behavior:

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
 <link rel="stylesheet" type="text/css"
   href=
"Scripts/MicrosoftAjax/Extended/Calendar/Calendar.css" /> <script type="text/javascript" src="Scripts/MicrosoftAjax/Start.debug.js"></script> <script type="text/javascript" src="Scripts/MicrosoftAjax/Extended/ExtendedControls.debug.js"></script> <script type="text/javascript"> Sys.require([Sys.components.calendar], function () { Sys.create.calendar(Sys.get("#date")); }); </script> </head> <body> <input type="text" id="date" /> </body> </html>

And that’s it: I’ve just added two scripts and that’s all I needed to use the CalendarBehavior. Btw, here’s the results I got on my machine after loading the page:

calendar

Nice, right?

Nov 20

You can get it from here. I’m curious to see if it contains new features…

Nov 13

At least, when the RTM version is released!

Ok, I guess you need some context: in the previous post, I talked about a problem which was mentioned to me by Andy in the comments of an existing post. The problem was that the __msajaxBindings field ended up being added to an object used in a live binding and that really means trouble when you try to serialize it (because you end up with a cyclic reference which generates a runtime exception).

In the previous post, I suggested a hack for it. Fortunately, Dave saw it and emailed me assuring that the hack won’t be necessary and that the internal __msajax… fields should only be added to HTML elements. As you’re probably expecting by now, the problem I mentioned in the previous post is the result of a bug (which will be solved before the RTM is out).

After being alerted by Dave, I’ve decided to take a closer look at the code…And yes, there’s a problem and it’s on the Sys.UI.DomElement.isDomElement method. This method ends up invoking the _isDomElement method which has a check that returns a “false positive”:

Sys._isDomElement = function Sys$_isDomElement(obj) {
   var val = false;
   if (typeof (obj.nodeType) !== ''number'') {
     var doc = obj.ownerDocument || obj.document || obj;
     if (doc != obj) {
       var w = doc.defaultView || doc.parentWindow;
       val = (w != obj);
     }
     else {
       val = (typeof (doc.body) === ''undefined'');
     }
  }
  return !val;
}

Can you spot the problem? Yep, the val = (typeof(doc.body)… line is responsible for considering the object a DOM element (remember: section had a property called body and if you look at the code, you’ll see that it ends up messing everything). While the good guys at MS don’t publish a new release which solves this bug, you really shouldn’t use any property named body in an object which is used in a binding relationship (at least,if you intend to serialize that object). Ok,to be fair, you can always use the previous awful hack, but If I were you, I’d renamed the property 🙂

And that’s it for now. Stay tuned for more.

Nov 11

In my “goodbye MS AJAX post”, reader Andy asked a really interesting question: how to serialize an object which is used in a binding relationship? The main problem is that the JavaScriptSerializer doesn’t support circular references. Unfortunately, it doesn’t also provide a way for you to specify which properties should be serialized. However, the problem is still there: how do you serialize the objects used in binding relationships?

I’m still hopping that the team will fix the serializer before MS AJAX RTMs is released, but meanwhile, we’re still left with the problem. I’ve thought a little bit about it and it seems like the best option is to “suspend” the binding, serialize it, and then “resume” it again. Notice that the code you’re about to see has not been tested (it was written during my bus trip home, so it might have one or two bugs 🙂 ,,). Let’s take a look at the example (I’ve reused most of Andy’s example and I’d like you to concentrate on the save method):

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="Scripts/MicrosoftAjax/start.debug.js"
        type="text/javascript">
    </script>
    <script type="text/javascript">
        var instance = [
            { title: ''New document'',
                content: {
                    sections: [
                        { body: ''Enter text here'' },
                        { body: ''other text'' }
                    ]
                }
            }
        ];
        Sys.require([Sys.components.dataView],
            function () {
                var view = Sys.create.dataView(
                        "#maincontent",
                        { itemTemplate: ''#edit'',
                          data: instance});
        }); 
function onSave(){ var data = Sys.get("$maincontent").get_data(); var backup = {}; function cleanupMetadata(obj, propName, key) { if (obj.hasOwnProperty(propName)) { backup[key] = {}; backup[key][propName] = obj[propName]; delete obj[propName]; } } function restoreMetadata(obj, propName, key) { if (backup[key] !== undefined) { obj[propName] = backup[key][propName]; delete backup[key]; } } for (var i = 0; i < data.length; i++) { var sections = data[i].content.sections; for (var j = 0; j < sections.length; j++) { cleanupMetadata(sections[j], "_msajaxBindings",
i+
"-"+j); } } var serialized =
Sys.Serialization.JavaScriptSerializer.serialize(data);
for (var i = 0; i < data.length; i++) { var sections = data[i].content.sections; for (var j = 0; j < sections.length; j++) { restoreMetadata(
sections[i],
"_msajaxBindings", i + "-" + j); } } alert(serialized); } </script> </head> <body xmlns:sys="javascript:Sys" xmlns:dataview="javascript:Sys.UI.DataView"> <div id="edit" class="sys-template"> <label>Title</label> <input sys:value="{binding title}"/> <div sys:attach="dataview" dataview:data="{{ content.sections }}" class="sys-template"> <label>Body</label> <textarea>{binding body}</textarea> </div> </div> <div id="maincontent"></div> <button onclick="onSave()">Save</button> </body> </html>

We’re using two helper methods: cleanupMetadata and restoreMetadata. In the cleanupMetadata, we store the _msajaxBinding info in the backup object. As you can see, we’re building a key by combining the positions of the objects so that we can recover that metadata later. Yes, this isn’t really reusable code and I’d really prefer to have the serializer filter the properties which shouldn’t be serialized. However, this approach will probably be enough for now if you need to serialize an object used in a binding relationship.

And that’s it for now…

Nov 09

Well, this really doesn’t deserve any special attention. Ok, let me put it another way: there’s a lot of work going on behind the scenes, but you shouldn’t have to worry with any of it.

I’ve thought about writing a post on the objects that end up being used by the AdoNetDataContext to propagate changes back to the server, but after some thought, I’ve give up on that idea because I’m not seeing anyone use any of these classes directly (yes, the AdoNetDataContext should do it all for you).

And that’s why I’m wrapping up this series on MS AJAX preview 6. I hope you’ve enjoyed it as much as did…Now, I do need to find another topic to keep me busy looking at new stuff…any ideas?

Nov 09

Here we are again, for more on the MS AJAX library. In the previous post, we’ve seen that we can interact with ADO.NET Data Services by using the AdoNetDataContext instances. Today, we’ll be looking at more advanced features of the ADO.NET Data Services which are also available in the MS AJAX library.

Before going on, I must confess that I’m not really an ADO.NET Data Service user (I guess this has made me curious enough for taking a peek in the future). However, since the MS AJAX library offers such great support for it, I couldn’t resist doing some digging and seeing which options are available for interacting with an existing data service.

According to the docs, ADO.NET Data Services can “be surfaced as a REST-style resource collection that is addressable with URIs and that agents can interact with using standard HTTP verbs such as GET, POST, PUT or DELETE”. In practice, and if we go back to our previous example, we can get all the images by using the uri http://:…/Services/ImageDataService.svc/Images. Besides this simple option,which returns all the images contained in the object,there are still other interesting options. For instance:

  • we can navigate through related properties;
  • we can expand associated properties;
  • we can filter the returned results;
  • we can paginate the returned data.

All these operations are specified through uris. We can easily do them by building the uris by hand. For instance, we can modify the previous example so that it also displays the associated :

<body xmlns:sys="javascript:Sys"
      xmlns:dv="javascript:Sys.UI.DataView">
    <div
      id="myView"
      class="sys-template"
      sys:attach="dv"
      dv:autofetch="true"
      dv:dataprovider="{{ _ctx }}"
      dv:fetchoperation="Images"
      dv:fetchparameters="{{ {$expand: ''Tags''} }}">
        <h2>{{Name}}</h2>
        <img sys:src="{{Uri}}" sys:alt="{{Name}}" />
        <div class="sys-template"
            sys:attach="dv"
            dv:data="{{ Tags }}">
            <span>{{Name}}</span>,
        </div>
    </div>
</body>

By using the $expand parameter, we’ll end up getting each image’s associated tags and we can display them by using a nested DataView control. The next image shows what happens when we load the previous page:

expand

We could specify all the “special” parameters this way. However, there is another way: we can rely on the Sys.Data.AdoNetQueryBuilder class for doing building the uri for us.

The AdoNetQueryBuilder’s constructor expects the base uri and exposes several properties which we can use to build the uri which performs a specific operation against the existing ADO.NET Data Service. You’ll probably end up using the ones which are present in the following list:

  • skip and top: we can combine them for paginating data;
  • orderby: used for indicating the sorting order;
  • filter: responsible for filtering the returned data;
  • expand: used for specifying the properties which will be “expanded” and included in the response.

I must confess that I really didn’t find the use of this object intuitive at first. However, after running some experiences, everything started making sense. In order to show you how you might end up using this object, suppose we want to get all the images and associated tags and that we want to order them by name. Here’s a possible solution:

<head runat="server">
    <style type="text/css">
      .sys-template{
        display: none;
      }
      img{
        width:320px;
        height:212px;
      }
    </style>
    <script type="text/javascript"
      src="../Scripts/MicrosoftAjax/start.debug.js">
    </script>
    <script type="text/javascript">
      var _ctx = null;
      Sys.require([Sys.components.adoNetDataContext,
                   Sys.components.dataView],
      function () {
        var uriBuilder = 
new Sys.Data.AdoNetQueryBuilder("Images"); uriBuilder.set_expand("Tags");//$expand uriBuilder.set_orderby("Name");//$orderby _ctx = Sys.create.adoNetDataContext({ serviceUri: "../Services/ImagesDataService.svc" }); Sys.create.dataView( Sys.get("#myView"), { dataProvider: _ctx, autoFetch: true, fetchOperation: uriBuilder.toString() }); }); </script> </head> <body xmlns:sys="javascript:Sys" xmlns:dv="javascript:Sys.UI.DataView"> <div id="myView" class="sys-template"> <h2>{{Name}}</h2> <img sys:src="{{Uri}}" sys:alt="{{Name}}" /> <div class="sys-template" sys:attach="dv" dv:data="{{ Tags }}"> <span>{{Name}}</span>, </div> </div> </body>

This time, I’ve opted for using an imperative approach. Things are really similar to what we had before; however, notice that now we’re using an AdoNetQueryBuilder object to set the fetchOperation property of the DataView object.

We start by instantiating the AdoNetQueryBuilder object. If you recall it, I said that this wasn’t really intuitive…it was only looking at the source code that I’ve understood that I was supposed to pass the name of the resource I wanted to access (instead of passing the base uri for the service – not sure on why the constructor’s only parameter is called uri, when resource would have make things so much easier!). Since I was interested in retrieving images, I only had to pass the string “Images” to the constructor.

After having an instance and setting the required properties (recall from above that we wanted to get images+tags and to order everything by name), we can simply call the toString method to get the string which represents the operation we need to perform. And that’s it. We’ll still be speaking about MS AJAX in future posts, so stay tuned for more!

Nov 09

Getting started with the AdoNetDataContext

Posted in Javascript, MS AJAX       Comments Off on Getting started with the AdoNetDataContext

Today we’re going to start looking at the AdoNetDataContext. This class expands the DataContext object and uses several specific methods for ensuring the correct interaction with an existing ADO.NET Data Service.

These internal methods added by the AdoNetDataContext are essentially used in identity related operations. In other words, it extends the base DataContext class by introducing several methods which turn on identity support (btw, I’m talking about the stuff we’ve seen in several of the previous posts).

In this post, I’ll be reusing the sample ADO.NET Data Service which is included in MS AJAX preview 6. Here’s the model used internally by the ImageDataService.svc ADO.NET service:

adonetmodel

In this case, and since this is just an intro post, we’ll build a simple page which shows all the images returned by this ADO.NET service:

<head runat="server">
    <style type="text/css">
      .sys-template{
        display: none;
      }
      img{
        width:320px;
        height:212px;
      }
    </style>
    <script type="text/javascript"
      src="../Scripts/MicrosoftAjax/start.debug.js">
    </script>
    <script type="text/javascript">
      var _ctx = null;
      Sys.require([Sys.components.adoNetDataContext,
                   Sys.components.dataView],
      function () {
        _ctx = Sys.create.adoNetDataContext({
            serviceUri: "../Services/ImagesDataService.svc",
            mergeOption: Sys.Data.MergeOption.appendOnly
        });
    });
    </script>
</head>
<body xmlns:sys="javascript:Sys"
      xmlns:dv="javascript:Sys.UI.DataView">
    <div
      id="myView"
      class="sys-template"
      sys:attach="dv"
      dv:autofetch="true"
      dv:dataprovider="{{ _ctx }}"
      dv:fetchoperation="Images">
        <h2>{{Name}}</h2>
        <img sys:src="{{Uri}}" sys:alt="{{Name}}" />
    </div>
</body>

By now, you shouldn’t really be surprised by anything that is shown in the previous snippet. As you can see, the AdoNetDataContext class protects us from all those nasty details associated with the communication with the ImageDataService.svc server side service. I’m not going to show you how to add, edit or remove items because the samples released with preview 6 already have code which shows how to do those things.

On the next post,we’ll see how to do more interesting operations by using the AdoNetQueryBuilder object. Stay tuned for more on MS AJAX.

Nov 08

The DataContext component: creating entities

Posted in Javascript, MS AJAX       Comments Off on The DataContext component: creating entities

Before we can move on and take a look at the AdoNetDataContext component, we need to talk about one more topic: creating entities and how it might be integrated with DataContext component. The DataContext exposes a createEntity method which can be used for  creating new objects of a specific type. Internally, that method will always delegate the creation of a new entity to the function to which the createEntityMethod property points to.

As you’re probably wondering, this is something you’ll only need to configure if you need to use the DataContext features associated with identity (and even in that case, setting the createEntityMethod is optional if you’ve set the getNewIdentityMethod property).

The createEntityMethod property should reference a function which receives two parameters (a DataContext reference and a string with the “type” of the object that should be created) and initializes the metadata necessary for tracking that object. If you recall the previous posts, you’ll surely remember that we’ve added an internal __meta property to all the objects stored by the DataContext instance.

We could improve our DataContext used at the time by setting the createEntityMethod to a function which initializes the metadata associated to that object. Here’s how I’d augment the entityManager we’ve been using with a new method used for creating new entities:

createNewEntity: function (dataContext, entitySet) {
    var obj = {};
    entityManager.getNewIdentity(dataContext, obj, entitySet);
    return obj;
}

As you can see, we’re simply relying in the getNewIdentity method because it is responsible for setting the __meta object used for that purpose. Referencing entityManager instead of this might seem little strange at first, but that’s needed because the DataContext won’t call the reference through the entityManager instance (it will simply call the function through the reference it got to it during initialization:

var ctx = Sys.create.dataContext(
  {
      serviceUri: "PeopleService.svc",
      getIdentityMethod: entityManager.getEntityId,getNewIdentityMethod: entityManager.getNewIdentity,isDeferredPropertyMethod: entityManager.isDeferredProperty,
      getDeferredPropertyFetchOperationMethod: 
entityManager.getDeferredProperty, createEntityMethod: entityManager.createNewEntity } );

And that’s it. There’s really not much to say about the createEntity method. Stay tuned for more on MS AJAX.

Nov 07

The DataContext component: deferred properties

Posted in Javascript, MS AJAX       Comments Off on The DataContext component: deferred properties

Today we’ll keep looking at the DataContext component and we’ll see how it supports deferred properties. Deferred properties are properties which are lazy loaded as “needed”. Using deferred properties means that the component will try to make a remote call for getting the value of that property. As you’re probably expecting, this means that you’ll have to write code on the client and server side. On the client, we’ll need some JavaScript functions which are responsible for:

  • checking if a specific property is deferred;
  • returning an instance of the Sys.NetWebServiceOperation which has all the data needed for performing the remote call which returns the value of that property.

After creating the functions and configuring the DataContext component’s isDeferredPropertyMethod and getDeferredPropertyFetchOperationMethod , we can get the deferred value of the property by using the DataContext’s fetchDeferredProperty method. Let’s take a look at the client side code (which augments the code we introduced in previous posts):

var entityManager = {
    metaCounter: {},
    getEntityId: function (dataContext, entity) {
       //removed: check previous posts
    },
    getNewIdentity: function (dataContext, entity, entitySet) {
        //removed: check previous posts
    },
    isDeferredProperty: function (dataContext, entity, propertyName) {
        var id = dataContext.getIdentity(entity);
        return propertyName === "contacts" &&
               id !== null &&
               /$new/.test(id);
    },getDeferredProperty: function (
dataContext,entity, propName, parameters, userContext) {
//returns web service operation var id = dataContext.getIdentity(entity); return new Sys.Net.WebServiceOperation( "GetContactsFor", {id: parseInt(/(d+)/.exec(id)[0]) }, "get" ) ; } };

It goes without saying (I think!) that this is just demo code (you’ll need better code for real world scenarios). As you can see, the contacts property will only be lazily loaded when we’re trying to get it from an object which has been previously persisted in the server side (once again, you’ll need to go back to the previous posts to understand what’s going on here). In the real world, I’d probably check that property against undefined too so that you’d only ask for the data when the property hasn’t been initialized.

The getDeferredProperty tries to find the id of the current person’s instance (don’t forget that person instances which have been previously persisted are on the form people$xxx where xxx is an integer which identifies the current instance) and uses it to build a JS literal object which is used to pass parameters to the server side code. Notice that the Sys.Net.WebService’s “constructor” expects three parameters: the first identifies the name of the operation; the second is a literal object which represent the parameters that will be passed to the server side method. Finally, the third parameter is a string which identifies the HTTP method that should be used in the server side call.

Now, we’re ready to create a new DataContext instance:

var ctx = Sys.create.dataContext(
  {
    serviceUri: "PeopleService.svc",
    getIdentityMethod: entityManager.getEntityId,
    getNewIdentityMethod: entityManager.getNewIdentity,
    isDeferredPropertyMethod: entityManager.isDeferredProperty,
    getDeferredPropertyFetchOperationMethod: 
entityManager.getDeferredProperty } );

One additional note before looking at the server side code: we *really* need to set the serviceUri property when we intend to use deferred property fetching. If you don’t set it, you’ll end up receiving an exception when you try to get the value of the property from the server side:

ctx.fetchDeferredProperty(
    people[0],
    "contacts",
    null,
    null,
    function(){
        var contacts = people[0].contacts;
       //contacts already filled here!
    });

The fetchDeferredProperty method receives several parameters:

  • a reference to the entity whose property is going to be obtained through the remote call;
  • name of the property which is being lazily fetched;
  • parameter: literal object with parameter info that will be passed to the server side. Note that this object will be merged with the parameter object encapsulated by the WebServiceOperation returned from the DataContext’s getDeferredPropertyFetchOperationMethod function;
  • mergeOptions: the Sys.Data.MergeOption which identifies the merge which will be used when the data is returned from the web service;
  • succeededCalback: callback function which will be invoked when the data is returned from the server and has already been passed to the property;
  • failedCallback: function invoked when the remote call ends up generating an error;
  • timeout: timeout defined in ms;
  • userContext: object which will be passed to the callback method when the DataContext receives a response from the server side.

In order for the previous client code work, we need to update our server side service’s code by adding the GetContactsFor method. Once again, and since is just demo code, I’ll implement in the easiest way possible: I’ll make it return a collection with a single predefined contact:

[OperationContract]
public IEnumerable<Contact> GetContactsFor(Int32 id) {
    return new List<Contact>{
        new Contact{
                Type = ContactType.Phone,
                Ct  = "123123123"
        }
    };
}

And there you go: you don’t need anything else for making the DataContext component get the value of the contacts property lazily. And that’s it for now. Stay tuned for more on MS AJAX.

Nov 05

The DataContext component: linking objects

Posted in Javascript, MS AJAX       Comments Off on The DataContext component: linking objects

Today we’ll keep going in our study of the DataContext component and we’ll see how we can establish relationships between objects through links. I guess you’re probably asking something like: “Hum…establishing relationships between objects…how about using properties?” For instance, suppose we’re working with person and contact instances from the previous post…We can say that a person has one contact and that is easily expressed through JavaScript which looks like this:

var personWithContact = {
  id: 6,
  name: "dumb",
  contact: { value: 1, contact: "123123123" }
};

Now, this is perfectly good code…really…so, why would I want to use links then? Glad you asked :,,)

Before going on, I’d like to point out that this is a feature which was added in order to support ADO.NET Data Services. Fortunately, the team wrote it in a generic way so that you could use it even if you’re not using ADO.NET Data Services (I said fortunately because you can reuse this feature if you want). But I’m divagating…why would we use links? For bookkeeping, of course! Whenever you create a link between two objects, you end up setting a property in the source and you’ll also get an entry in the changes array (internal _changelist array).

When working with links, you’ve got several methods which you can use:

  • addLink: you should use this method when you need to add items to a collection. For instance, suppose you’ve got a property which is an array and you want to add an object to that array. The addLink method is the way to go;
  • setLink: also used for adding a new link between two objects. This is the method you should use when you’re thinking of “simple” properties (instead of collections);
  • removeLink: used for deleting an existing link between two objects. You should only use this method when you’re removing an item from a collection

As I’ve said above, you should keep in mind that these methods end up changing the internal changes list maintained by the DataContext control. Establishing and cancelling links produces different results when you’re working with single properties and collections. For instance, take a look at the following code (based in code presented in the previous post):

var newPerson = { name: "joseph", address: "fx", 
contacts: [] };
var ct1 = { value: 1, contact: "123123123" }; var ct2 = { value: 2, contact: "222333444" }; ctx.addLink(newPerson, "contacts", ct1);//collection ctx.setLink(newPerson, "contact", ct2);//single prop ctx.setLink(newPerson, "contact", null);//removing single ctx.removeLink(newPerson, "contacts", ct1);//removing coll.

In the previous snippet, we’ve introduced a new person instance and several contacts in order to show you how to establish links between the objects. If you stop the code in the addLink method, you’ll see something like this:

addlink

As you can see, establishing the link through the add method ended up adding the contact to the contacts array of the person object and inserting a new entry in the changes list. If you stop the code’s execution after the setLink line, you’ll see something similar (depending on what changes were made to the DataContext):

addlink2

As you can see, the main difference is that setLink ends up setting an item instead of adding it to a collection. Canceling a relationship established through the setLink method involves using that method again, but passing null instead of a valid value. On the other hand, removing an item from the collection should always be done with the removeLink method. Interestingly, these methods produce different results in this scenario (don’t forget that we still haven’t committed the changes, ie, we still haven’t committed our setLink and addLink changes). Take a look at the following picture to see what I mean:

addlink3

As you can see, the removeLink call ended up deleting the previous addLink entry (while also removing the entry from the contacts array). However, the setLink method doesn’t affect the changes array in the same way; instead, it will simply update the existing entry so that it points to the new target that has been passed to it. Notice that this means that you’ll have to pay attention to this if you’re writing custom code in the server side which is responsible for persisting the changes.

And I guess this sums it up quite nicely. but there’s still more to discuss…so stay tuned for more on MS AJAX.

Nov 05

Regular expressions and JavaScript – part II

Posted in Javascript       Comments Off on Regular expressions and JavaScript – part II

In the previous post, we’ve seen that we can build regular expression objections through a constructor ( RegExp) or by using a literal (/…/). Today I thought I’d be writing some code for illustrating the use of regular expressions. However, I think I’ll concentrate on MS AJAX and I’ll point you to this site if you want to know more about regular expressions.

Nov 04

Regular expressions and JavaScript

Posted in Javascript       Comments Off on Regular expressions and JavaScript

After writing my last post on getting style properties from JavaScript, I’ve noticed that I still haven’t written anything about JavaScript and regular expressions…and that’s why I’ll be writing a couple of posts on this topic. Before going on, a disclaimer: I’m not really an expert on regular expressions (do note that people have written books on them! and since we’re at it, I’m not really an expert in any field…but I’m really curious and that counts, right? 🙂 ,,). However, I guess I’ll be able to share with you some of the basics about them I’ve picked along the years.

I think I won’t be far from truth by saying that you can see regular expressions as a language which you can use to search, replace and extract data from/in an existing string. Unfortunately, regular expressions tend to be rather cryptic… and that means that they might be hard to read and/or write. A regular expression is always a string which might use one or more characters from a special characters’ list. Special characters are so called because they have a special meaning. For instance, d means something like “match any digit”…I’m not going to show you all speciall characters here. Instead, I’ll redirect you to this page.

I’ve already mentioned that writing and reading complex regular expressions is not for those who have heart problems…the main problem I see with them is that, unlike traditional code, you can’t really use white spaces nor can you use comments for explaining something better (notice that I’m talking about the regular expression itself here). A regular expression string is really a compact string which gets harder and harder to read as you get better at understanding them…

In JavaScript, regular expressions are represented by RegExp objects. Instantiating a RegExp object means that you’ll have to (at least!) pass an expression which identifies a pattern. If you want, you can also specify the type of operation which should performed by specifying an optional flags parameter (for instance, passing “i” to it means you don’t care about case). Here’s a quick example of a new Regular expression which will match strings which have at least 1 digit:

var reg = new RegExp("\d");
alert(reg.test("have 1 digit"));

The previous snippet introduced one of the methods exposed by the RegExp class: the test method. You can use it for checking if the string that was passed to it matches the regular expression encapsulated by that RegExp object. There’s still one more interesting thing to notice about the previous snippet: we had to escape the char since we’re using a string to define the regular expression.

Notice that JavaScript also supports the concept of regular expression literal. A regular expression literal is delimited by a pair of slashes (/reg. expression goes here/). For instance, the next snippet is equivalent to our first example:

alert(/d/.test("have 1 digit"));

In case you’re wondering, the flag parameter can also be specified when using regular expression literals:

alert(/d/g.test("have 1 digit"));

If you need to, you can pass several flags by just putting the corresponding letters after the ending slash (don’t worry to much about these flags…we’ll come back to them in future pots). Most of the time, you’ll probably end up using regular expressions literals due to their compactness (when compared with the equivalent RegExp instantiation).

As you can probably guess, the hardest part on using regular expressions is building the regular expression itself. And that’ what we’ll start looking at on the next post. Stay tuned for more on regular expressions and JavaScript.

Nov 04

Getting the CSS display value: there’s more to it than you might think at first

Posted in Javascript       Comments Off on Getting the CSS display value: there’s more to it than you might think at first

Well, I’m spoiled… that’s what happens when you use frameworks like JQuery…Everything is good until that one day…someone says something stupid: “I need you to write some JS code but I don’t want external references on JQuery!”. Yep, I thought exactly the same thing: WTF???

“Now, that we’re clear on external frameworks, can you please write me a function which  receives a reference to a DOM element and returns the value of its CSS display property?”, someone asked. “Sure! no problem”, I said…After all, getting the display is just a matter of getting the CSS’ display property and we all know that it’s readily available from the style object, right? So, here’s my first attempt on this problem:

function display(elem) {
  //basic parameter checking removed
  return elem.style.display;
}

Simple, right…Then I though about writing a simple test. I’ve started with the following HTML:

<div id="a1" style="display: none"></div>

And now, the JavaScript:

alert(display(document.getElementById("a1")));

And yes,an alert with ‘none’ popped up…things were good…until that I’ve decided to add two more elements to my test page:

<div id="a2">sss</div>
<div id="a3">sss</div>

How about testing CSS applied through style sheets:

<style type="text/css">
    #a3{
        display: none;
    }
</style>

And then,I’ve simply duplicated the alert calls:

alert(display(document.getElementById("a2")));
alert(display(document.getElementById("a3")));

“And…wtf is going on here??? Where are the display values???” Yes, you’re screwed…style.display will only return a “valid” value when it’s explicitly set from JS or from the style attribute which is applied to the element (ie, the style attribute that you can use in the HTML tags). Now, how do we solve this?

There is a way, but once again, we need to write some browser testing code  because different browsers use different approaches…I’m talking about the currentStyle vs getComputedStyle dilemma…Here’s my next attempt for a cross-browser solution (where cross-browser really means IE, FF, Chrome and Opera):

function display(elem) {
  //basic parameter checking removed
  if (elem.style.display) {
    return elem.style.display;
  }

  if (elem.currentStyle) {
    return elem.currentStyle.display;
  }
  if (document.defaultView.getComputedStyle) {
    return document.defaultView
.getComputedStyle(elem,
null)
.getPropertyValue(
"display"); } return ""; }

Now, before you start thinking in adapting this code so that you can get any style property, there’s one additional detail you should keep in mind: Mozilla and Opera browsers expect CSS syntax while IE relies on JS names (ex.: background-color vs backgroundColor).

In my opinion, the easies solution for this problem is require CSS names and adapt then, when needed, convert it to JS syntax. Here’s a possible solution which expects CSS property names syntax:

function display(elem, propName) {
  //basic parameter checking removed
  if (elem.style.display) {
    return elem.style[propName];
  }
  if (elem.currentStyle) {
//copied directly from JQuery’s source –:)
var jsName = propName
.REPLACE(cast(/-(w)/g as nvarchar(max)),cast(
function (all as nvarchar(max)),cast( letter as nvarchar(max))) { return letter.toUpperCase(); }); return elem.currentStyle[jsName]; } if (document.defaultView.getComputedStyle) { return document.defaultView .getComputedStyle(elem, null) .getPropertyValue(propName); } return ""; }

Well, even with this code, it’s still interesting to notice that if, for example, you set the background-color CSS property to red, you’ll get different results (some browsers return red while others return rgb(255, 0,0). You gotta love web development!!!

I hope this imaginary scenario will help you (I should have probably said your boss!) understand that web development is more complicated than it seems at first…yes, we don’t have to do memory management (though we still need to pay attention to memory leaks), but there are still a ton of stuff to worry about…and yes, doing web development without using a modern JS framework (ex.: JQuery) is pure suicide. DON’T DO IT!

Nov 04

In the previous post, we’ve started looking at identity and how it’s supported by the DataContext component. Today we’ll improve the initial algorithm so that we’re able to support more advanced scenarios.

Even though the first algorithm for identity management was really simple, it ended up showing that identity management ends up adding (at least) two important problems:

  • how to generate new identities;
  • how to distinguish new entities from existing ones and how to distinguish different types of entities.

One possible solution for these problems relies on adding some sort of metadata to our objects. Going back to our initial example, we’ll start by adding an internal __meta object which will hold two important pieces of data:

  • the type of object;
  • the identity of that object;

Notice that the identity of the object must be enough for identifying that object (even amongst objects of different “types”). Another important detail to keep in mind is that we need some way to identify the current type of an object (if we were using a strongly typed language, this wouldn’t be necessary, but with dynamic languages, it’s something that must also be tracked). It’s also important to understand that the objects that will be passed to the trackData method should have this info correctly filled up (unlike objects which will be inserted, where the metadata is supposed to be generated by the identity methods):

var people = [
    { id: 1, name: "luis", address: "fx", 
__meta: { set:
"people", id: "people$1"} },{ id: 2,name: "john", address: "fx",
__meta: { set:
"people", id: "people$2"} }, { id: 3, name: "peter", address: "fx",
__meta: { set:
"people", id: "people$3"} } ];

There’s not much we can say about the previous snippet. It represents a collection of person instances which have their __meta properties set up. Notice that from now on, the identity of each of these objects is given by the __meta.id value (instead of relying in the id field of the object).

Our implementation of the identity related methods need to handle more details. Due to that, I’ve decided to create a helper object which encapsulates all the work needed for getting and creating new identities:

var entityManager = {
  metaCounter: {},
  getEntityId: function (dataContext, entity) {
    return entity.__meta && entity.__meta.id ?
           entity.__meta.id :
           null;
  },
  getNewIdentity: function (dataContext, entity, entitySet) {
    if (!entitySet) {
      Error.invalidOperation("entity set must be defined");
    }
    var _this =entityManager;
    function createMetaInfo(entity, entitySet) {
      var generatedId = _this.metaCounter[entitySet] =
        _this.metaCounter[entitySet] !== undefined ?
            _this.metaCounter[entitySet] + 1 : 0;
      return {
        set: entitySet,
        id: entitySet + "$new:" + generatedId
      };
    }
    if (!(entity.__meta && _entity.__meta.id)) {
      entity.__meta = createMetaInfo(entity, entitySet);
    }
    return entity.__meta.id;
  }
};

A couple of observations regarding the previous helper:

  • the identity of an item relies on the __meta.id property. As you can see, identity relies on concatenating IDs with the type of the current object;
  • new identities must be different from those that belong to objects which have already been persisted (probably in a db on the server side). That’s why new identity use the $new instead of using only $ (I think this is easy to handle on the server side);
  • I’ve introduced the metaCounter object so that we can reuse this object for allowing the insertion of different types of objects.

Now, we can start adding several kinds of objects without any problem. For instance, take a look at the following code:

ctx.insertEntity({ name: "joseph", address: "fx" }, 
"people"); ctx.insertEntity({ name: "joseph", address: "fx" },
"people"); ctx.insertEntity({ value: 1, contact: "123123123" },
"contacts");

And the next image shows the final result:

betteralgorithm

As you can see, with this approach we no longer set the id property of a new person object (that will be done by the server side, when it process an eventual commit performed by the DataContext instance).

Notice that until now we’ve seen the client code needed for supporting addition of new items. A complete solution would still need more work in the server side in order to ensure that items are correctly persisted. On the next post, we’ll start looking at links between objects. Stay tuned for more on MS AJAX.

Nov 03

The DataContext component: getting started with identities

Posted in Javascript, MS AJAX       Comments Off on The DataContext component: getting started with identities

We’ve already met several interesting features of the DataContext component. Today we’ll keep going and we’ll start discussing identity. I’m not sure if you’ve noticed, but the DataContext exposes several identity related methods. For instance, the getIdentity method is used by the control to get the identity of an object.

In order for you to activate identity related features, you need to (at least) configure the component so that it knows how to get or create a new identity for an object. This is done by setting two properties:

  • getIdentityMethod: function used for getting the identity of an object. This method expects two parameters: the first references the DataContext; the second, references the entity you’re interested in getting the ID of;
  • getNewIdentityMethod: function which is used for creating a new identity for an object. This method expects three parameters: the first two match the getIdentityMethod’s parameters; the last one is an optional string which identifies the type of object that is asking for a new identity.

Setting these properties is all that is need for activating identity support for a DataContext component. Notice that using identities means  that you’ll end up using the internal _items object for storing all the objects maintained in the current DataContext component. This object is used as a dictionary, where the identity of each object is used as the key of a specific entry. In practice, this means that you can mix object of different types in the same _items dictionary (we’ll talk about this in a future post).

As you’ve probably guessed, identity is one of those features which exists (mainly) for supporting ADO.NET data service. However, nothing prevents us from exploring it, right? So let’s get starting…and we’ll start simple…Suppose you want to track changes to the array presented in the next snippet:

var people = [
    { id: 1, name: "luis", address: "fx" },{ id: 2,name: "john", address: "fx" },
    { id: 3, name: "peter", address: "fx" }
  ];

In this case, things are pretty simple, right? We’re only interested in managing simple objects (lets call them person instances) and that means that we can use the id value as the identity of each object. There’s still one little problem: what to do with new items?

In this case, and since we’re supposed to create a function for calculating new identities, we can write it so that it also sets the id of any new person object. Here’s the code needed for instantiating a DataContext component which does exactly that:

var ctx = Sys.create.dataContext(
  {
    getIdentityMethod: function (dataContext, entity) {
      return entity.id;
    },
    getNewIdentityMethod: function (
dataContext, entity, entitySet) {
if (entity.id === undefined) { var contextItems = ctx.get_items(); var max = 0; for (var id in contextItems) { if (parseInt(id) > max) { max = parseInt(id); } } entity.id = max + 1; } return entity.id; } } );
ctx.trackData(people);

With these properties sets, we can add new objects without having to worry with the ID of a new person instance:

ctx.insertEntity({ name: "joseph", address: "fx" });

The next image shows the changes made to the DataContext instance after the previous insert:

identitychanges

As you can see, identity activation leads to several changes:

  • new elements get added to the private _items dictionary with the new identity used as the key;
  • the new inserted object is updated: a new id property is added and set to the new identity which was calculated by the DataContext’s newIdentityMethod function;
  • the _inserts array references only the id of the item that was inserted (notice the id$4 entry in the previous image).

The example we’ve seen is really intended to get you started with identities. Unfortunately, things aren’t so easy in the real world. there will be times where you can’t really set the ID of an item (ex.: suppose it gets mapped to an auto number field of a table). There will also be other times where you need to support several “types” of objects…in these scenarios, you’ll need a more advanced way to identifying each instance.

In the next post we’ll take a look at more advanced ways of generating IDs for these scenarios. Stay tuned for more on MS AJAX.

Nov 02

The DataContext component: Committing changes – take II

Posted in Javascript, MS AJAX       Comments Off on The DataContext component: Committing changes – take II

In the previous post, we’ve seen how easy it is to commit the changes that are buffered by a DataContext instance. At the time, I said that there were still a couple of things related with the saveChanges method that needed further discussion…and that’s what we’ll do in this post.

To illustrate one scenario you might end up facing in the real world, lets assume that our person instances have a piece of information which can only be set in the server side. For instance, lets say that all created instances need to have a creation date that can only be set in the server side. Going back to our initial example, that means that each person instance in the initial items array needs to be updated with this extra info (keep in mind that items is supposed to have info about previously saved elements):

var items = [
    { name: "luis", address: "fx", date: new Date() },
    { name: "john", address: "fx", date: new Date() },
    { name: "peter",address: "fx",date: new Date() }
  ];

To make the code more real, we’ll be adding a DataView control which allows us to edit/add new items to this array. Take a look at the following image:

commit1

The code used for generating this page looks like this:

<head runat="server">
    <style type="text/css">
        .sys-template{
            display: none;
        }
    </style>
    <script type="text/javascript"
      src="Scripts/MicrosoftAjax/start.debug.js">
    </script>
    <script type="text/javascript">
        var items = [
          { name: "luis", address: "fx", date: new Date() },
          { name: "john", address: "fx", date: new Date() },
          { name: "peter", address: "fx", date: new Date() }
        ];
        var aux = { name: "charles", address: "lx" };
        var ctx = null;
        Sys.require([Sys.components.dataContext,
                     Sys.components.dataView],
            function () {
              Sys.Observer.makeObservable(items);
              ctx = Sys.create.dataContext({
                serviceUri: "PeopleService.svc",
                saveOperation: "SavePeople",
                saveHttpVerb: "POST"
              });
              ctx.trackData(items);
              $addHandler(
                      Sys.get("#add"),
                      "click",
                      function () {
                       var item = { name: "", address: "" };
                       ctx.insertEntity(item);
                       items.add(item);
                      });
              $addHandler(
                    Sys.get("#save"),
                    "click",
                    function () {
                      ctx.saveChanges();
                    });
            });
    </script>
</head>
<body
      xmlns:sys="javascript:Sys"
      xmlns:dv="javascript:Sys.UI.DataView">
    <div id="view"
         class="sys-template"
         sys:attach="dv"
         dv:data="{{items}}">
      <div>
        <input type="text" sys:value="{binding name}" />
        <input type="text" sys:value="{binding address}" />
        <span>{binding date}</span>
      </div>
    </div>
    <input type="button" value="add new" id="add" />
    <input type="button" value="save changes" id="save" />
</body>

As you can see, the items array is used in two places: it feeds the data shown by the DataView control and it is tracked by the DataContext component. We’ve transformed the items array into an observable array so that the DataView is able to automatically pick up insertions and deletions.

Even though this works, there’s still a small problem here: the date of each new person instance can only be set in the server side. The previous web service didn’t return anything from the server side and that is why you’ll always get null for the date property.

If you look at the code of the DataContext component, you’ll notice that it checks for values that are returned from the server for a save operation. Take a look at the _processResults method (edited for improved readability):

function Sys$Data$DataContext$_processResults(
dataContext, changes, results) {
if (results && results.length === changes.length) { dataContext._ignoreChange = true; try { for (var i = 0, l = results.length; i < l; i++) { var result = results[i],
change = changes[i],
item = change.item;
if (result && typeof(result) === "object") { dataContext._fixAfterSave(
change, item, result); } } }
finally { dataContext._ignoreChange = false; } } }

As you can see, if the web service method used for saving returns a collection, the component will try to merge the client information with the one returned from the server side. It’s imperative that the returned collection has the same size as the array of changes (_changelist property) that was sent to the server and that each returned item’s position matches the “correct” position in the changes array. With this info, we can easily solve our initial problem by updating the server side save method:

[OperationContract]
public IEnumerable<Person> SavePeople(
IEnumerable<PersonOperation> changeSet) { var changed = new List<Person>(); foreach (var change in changeSet) { change.Person.Date = DateTime.Now;//bad!!!demo only _executors[change.OperationType](change.Person); changed.Add(change.Person); } return changed; }

We’ve updated the web service save method so that it returns the collection of person instances it received from the client. Notice that in this case I’ve forced an update of the Date property and that info will be propagated back to the client and picked up by the internal _processResults method (you shouldn’t really do this for all items – after all, we only need to set the date for insertions). And that’s why you’ll get dates after you click the save changes button:

commit2

And I guess that’s all for now. Stay tuned for more on MS AJAX.

Nov 02

Ok, we’ve already seen one option for fetching data from a remote web service. In this post, we’ll see how to commit changes tracked by the DataContext component. Committing buffered changes means that you’ll need to set (at least) two DataContext instance properties: serviceUri and saveOperation. serviceUri identifies the URI of the web service that is responsible for persisting the changes; saveOperation is used for identifying the server side method which persists the changes that were buffered by the DataContext instance.

To illustrate committing, we’ll be updating the PeopleService we’ve introduced in a previous post. For now, we’ll start by writing some JavaScript code:

var items = [
    { name: "luis", address: "fx" },
    { name: "john", address: "fx" },
    { name: "peter", address: "fx" }
  ];
  Sys.require([Sys.components.dataContext],
    function () {
      var ctx = Sys.create.dataContext({
        serviceUri: "PeopleService.svc",
        saveOperation: "SavePeople",saveHttpVerb: "POST"
      });
      ctx.trackData(items);
      var aux = { name: "charles",address: "lx" };
      ctx.insertEntity(aux);
      ctx.saveChanges();
    });

As you can see, we’re configuring three properties for our DataContext object:

  • serviceUri: we’re using this to pass the URI to the web service that is going to be used for saving the changes;
  • saveOperation: identifies the name of the method exposed by the web service that should be used for saving the changes;
  • saveHttpVerb: we’re setting this property to specify the HTTP verb that should be used when the DataContext tries to commit the changes previously buffered.

Btw, notice that we’re using the trackData method for initiating data tracking. I’ve opted for doing this to show you that saving does not depend on fetching data from the same web service. You should also keep in mind that the saveChanges method might receive three parameters:

  • the first, identifies the success callback function;
  • you can also pass an error callback function (second parameter);
  • finally, you can pass additional custom context that will be passed for the callback methods you’ve passed as first and second parameters.

Before showing the server side code, we need to know what is passed to the server side when someone calls the saveChanges method. The answer shouldn’t be too hard (at least, after thinking a little bit about it): we’ve already seen that the DataContext component saves all changes by adding entries to the internal _changelist field. And that is the information which gets send back to the server when the component tries to persist the buffered changes.

With this information, we can start updating the server side code. The first thing we need to do is create  a new C# class which represents an instance of a change. In other words, we need to mimic the Sys.Data.ChangeOperation in the server side. Now, if I was building a reusable class, I’d use templates and I’d duplicate all the properties exposed by the ChangeOperation type.

However, since this is demo code and I know that the buffered operations will only involve insertions, editions and removals of Person objects (after all, we still haven’t talked about links), I’ve opted for only replicating the properties that are used in this scenario:

[DataContract]
public class PersonOperation
{
    [DataMember(Name="item")]
    public Person Person{ get; set; }
    [DataMember(Name="action")]
    public OperationType OperationType { get; set; }
}
public enum OperationType
{
    Insert,
    Update,
    Remove
}

As you can see, we’ve added a new enum too. That was necessary because the client side ChangeOperation instance relies in using an enum for specifying the operation that is being performed (the only thing we need to ensure is that the enum entries have the same values as the ones specified in the client side).

The PersonOperation class mimics the Sys.Data.ChangeOperation “type” we have in the client side. As you can see, we’re using the DataMemberAttribute for mapping each of the server properties to the ones used in the client side. Oh, and just for completion, here’s the code for the Person class:

[DataContract]
public class Person {
    [DataMember(Name="name")]
    public String Name { get; set; }
    [DataMember(Name="address")]
    public String Address { get; set; }
}

Now, we’re still missing the web service’s save method. We’ve already established that it receives a collection of changes (ie, an array of Sys.Data.ChangeOperation objects). However, there’s still one important piece of information missing: we need to know the name of the parameter used for sending that information. In this case, the DataContext object uses the changeSet name. And now we’re read for taking a peek at the web service code:

[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(
RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)] public class PeopleService { static List<Person> _people = new List<Person> { new Person{ Name = "luis", Address = "fx"}, new Person{ Name = "john", Address = "lx"}, new Person{ Name = "peter", Address = "pt"} }; private readonly
IDictionary<OperationType, Action<Person>> _executors; public PeopleService() { _executors =
new Dictionary<OperationType, Action<Person>> { {OperationType.Insert, InsertItem}, {OperationType.Update, UpdateItem}, {OperationType.Remove, DeleteItem} }; } [OperationContract] [WebGet] public IEnumerable<Person> GetPeople(SortOrder sort){ var ordered = _people.OrderBy(
p => (sort == SortOrder.Name ? p.Name : p.Address) ); return ordered; } [OperationContract] public void SavePeople(
IEnumerable<PersonOperation> changeSet) { foreach (var change in changeSet) { _executors[change.OperationType](change.Person); } } private void InsertItem(Person person) { //do something } private void UpdateItem(Person person) { //update person } private void DeleteItem(Person person) { //delete item } }

We rely on the OperationType property of each PersonOperation instance to decide if we’re inserting, updating or removing an item (I’ve opted for using a dictionary for eliminating the switch that you’ll see in most cases). It’s just that simple, really! The only thing to watch out for are the mappings: you need to ensure proper mapping between the client and side objects (and this includes method parameter names too!).

This has become a rather large post, so I guess this is it for now. There are still a couple of interesting observations that can be made about the server side save method, but we’ll leave it for a future post. Stay tuned for more!

Nov 02

Until now, we’ve met some of the basic features introduced by the DataContext component. As I’ve said, you can think of this control as a buffer which keeps track of changes performed to several items it keeps track of. We’ve already seen that we can use the trackData method for initiating a tracking operation. What I haven’t mentioned yet is that you can also configure the control so that it fetches data automatically from a web service (or even from an ADO.NET data service).

Getting data from a web service means that you’ll have to (at a minimum!)configure the URI of the web service. Currently, you can do that by setting the DataContext’s serviceUri property. After setting the URI, you can get the data by calling the fetchData method. Here’s an example (btw, I’m reusing the web service presented here):

<script type="text/javascript">
  Sys.require([Sys.components.dataContext],
    function () {
      var ctx = Sys.create.dataContext(
        {
          serviceUri: "PeopleService.svc"
        }
      );
      ctx.fetchData(
        "GetPeople", //method
        {sort: 0 }, //method parameters
        Sys.Data.MergeOption.overwriteChanges, //merge options
        "GET", //http verb
        function () { //succeded
          //could use parameters, but wil use
          //lastFetchedResults for demo purpose
          var items = ctx.get_lastFetchDataResults();
          for (var i = 0; i < items.length; i++) {
            alert(items[i].name);
          }
        });
    });
</script>

After setting the serviceUri property,we end up calling the fetchData method (while passing it several parameters which influence the remote web service call) for getting the data from the web service. As you can see,we’re only passing the succeeded callback function to ensure that the lastFetchDataResults property is correctly filled up (in this case, we’re just iterating over each item and printing the value of its name property).

The fetchData exposed by the DataContext component matches the one defined by the IDataProvider interface. This isn’t just coincidence… it happens because the DataContext implements this interface and needs to provide an implementation for its fetchData method:

Sys.Data.IDataProvider.prototype = {
    fetchData: Sys$Data$IDataProvider$fetchData
}

Btw, here’s the current signature for the fetchData method:

function Sys$Data$IDataProvider$fetchData(operation, 
parameters,
mergeOption,
httpVerb,
succeededCallback,
failedCallback,
timeout,
userContext) {

I guess that the parameters are self-explanatory, so I won’t be wasting your time with additional details on them. If you’ve been following along, then you’re probably read one of the posts on how to configure the DataView control to fetch data from a remote web service.

At the time, I’ve said that one of the options is configuring the DataView’s dataProvider property with a valida IDataProvider instance. Since the DataContext implements this interface, then you can also use an object of this type for getting the data that is rendered by the DataView control. Here’s a quick example that shows how to configure the DataView control so that it gets the data from a DataContext:

<head runat="server">
    <style type="text/css">
        .sys-template{
            display: none;
        }
    </style>
    <script type="text/javascript"
      src="Scripts/MicrosoftAjax/start.debug.js">
    </script>
<script type="text/javascript">
  Sys.require([Sys.components.dataContext,
               Sys.components.dataView],
    function () {
      var ctx = Sys.create.dataContext({
        serviceUri: "PeopleService.svc"
      });
      var view = Sys.create.dataView(
        Sys.get("#view"),
        { itemTemplate: "#template",
          autoFetch: true,
          dataProvider: ctx,
          httpVerb: "GET",
          fetchOperation: "GetPeople",
          fetchParameters: {
            sort: Sys.Data.MergeOption.overwriteChanges
          }
        });
    });
</script>
</head>
<body>
    <div id="view">
    </div>
    <div class="sys-template"
        id="template">
        <span>{{name}}</span>-
        <span>{{address}}</span>
        <br />
    </div>
</body>

The code is pretty straightforward (I think): we create a new DataContext instance and set its serviceUri property. After that, we initialize a DataView control and pass it the remaining info that is needed to perform the remote call. And that’s it. There’s nothing more to it than that…

The next step in your study guide is see how to configure the DataContext so that it propagates changes from the client to the server side. Stay tuned for more!

Nov 02

The DataContext class: cancelling changes

Posted in Javascript, MS AJAX       Comments Off on The DataContext class: cancelling changes

In the previous post, we’ve see how to execute some basic actions over a DataContext instance. In this post we’ll keep looking at the it and we’ll see the available options for working with changes made over the data tracked by the control. Before getting started, we’ll assume that _ctx references an existing DataContext object created previously with the code shown in the previous post.

The first thing you can do is cancel all the changes that have been made to the data encapsulated by the control. You can easily do this by calling the clearChanges method. This method ends up doing several things:

  • it starts by cleaning the internal arrays used for keeping track of the items that were inserted, edited and removed (ie, it sets the _inserts_edits and _deletes objects to null);
  • it clears the private _changelist array (by using the Sys.Observer.clear method);
  • it sets the _hasChanges property to false and generates the propertyChanged event.

Here’s some demo code that shows how to use this method:

var aux = { name: "charles", address: "lx" };
_ctx.insertEntity(aux);
Sys.Observer.setValue(aux, "address", "pt");
alert(_ctx.get_changes().length); //at least 1 change here!
_ctx.clearChanges();
alert(_ctx.get_changes().length);//no changes here

As you can see, inserting a new entity ensures that the _changelist is not empty. After calling the clearChanges method, all pending changes are deleted. Even though pending changes are cancelled (ie, cleared), you still have access to the initial data that was tracked by the control (that is,if the control encapsulated any data that was being tracked).

If you also need to clear the tracked data,then you’ll need to resort to the clearData method. Besides clearing pending changes, this method will also clear the internal arrays it uses (including _items and _lastResults) ensuring proper clean up of the internal state of the control. Here’s some demo code that shows how to use this method:

_ctx.clearData();
alert(_ctx.get_lastFetchDataResults() === null);//true!

As you can see, calling the clearData method means that you’ll end up “nulling” the private _getchanges field of the DataContext instance.

Besides cancelling changes, you can also “commit” changes. But before we go into this topic, we need to talk about interacting with remote web services. And that’s what we’ll start doing in the next post. Stay tuned for more.