Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

JavaScript for C# developers: writing a library (part 2)

DZone's Guide to

JavaScript for C# developers: writing a library (part 2)

·
Free Resource

As I said last time, my first library object is going to be a cookie object. (Update: I‘ve revised this article a little since my original text was a little confusing. See comments.)

The browser API for this is remarkably simple. There’s a string property of the document object called cookie. Read from it and you get a semicolon-separated list of name=value pairs as a string. Each name is the name of a cookie and the value is its value. Write to it with a specially formatted string (again semicolon-separated) and you add or update a single cookie (you can only update a cookie one at a time). The string contains at least three parameters: a name=value pair, an expiry date for the cookie defined in UTC format, and a path from which the cookie is valid (usually everyone uses “/” for the root of the site, and this is what we’ll do). There are other parameters if you want to use them, but we’ll stick with these. Finally, to delete a cookie, you merely update it with an expiry date that’s in the past and the browser will delete it.

Things to note: the API does not give you a way to read a single cookie. You get them all and you have to parse the string looking for the one you want. You also don’t get back any ancillary information about the cookie (its expiry date, for example).

Also, it seems that we’ll need some date routines as well: we’ll need to calculate a date in the past to delete a cookie and it would be nice if we could make the expiry date optional in our API and the function calculate a date, say, a month in the future if so. Actually, for now, if you don’t mind I’ll shelve the addMonths() date function (it can be a pain to write and get right) and just have an addDays function.

Time for a date object in my library to take care of any date functions I may need. I start off with the usual base code in a file called jmbDate.js, code that you’re used to by now:

(function ($) {

  var $j = $.jmbLibrary;
  var $jd = $j.date = {};

})(jQuery);

(Quickly now: an auto-execute anonymous function taking one parameter, jQuery, such that it’s known as $ inside the function. Create a new empty object called date in the jmbLibrary object and give it a cute local name. You’re getting the drift.)

First let’s write a now function to mimic .NET’s DateTime.Now property. Pretty easy:

  $jd.now = function () {
return new Date();
};

Now, let’s write the addDays function. We’ll make use of a couple of JavaScript’s Date functions here: first the valueOf function returns passed date as the number of milliseconds since midnight on 1st January 1970. Then we’ll use one of Date’s constructors that takes a number of milliseconds and returns a new Date object.

  var getMs = function (date) {
return date.valueOf();
};

var dateFromMs = function (value) {
return new Date(value);
};

$jd.addDays = function (date, days) {
return dateFromMs(getMs(date) + days * 1000 * 60 * 60 * 24);
};

As you can see I decided to wrap those “raw” JavaScript functions into two local functions: it makes the code perhaps a little easier to read in the addDays function and it also means I can talk about function scope again. These two new functions are local to (and visible throughout) this outer anonymous function, they will not be visible outside. The addDays function will be visible outside since I’m adding it as a function to the new date object (the two local functions are not added to this object). The closure formed by the outer function gives me the ability to have private functions just for use inside the function (and hence for use by that same date object since it can “see” them too).

Finally I decided to add an isDate function too. In the next part of this series, as I mentioned above I shall be needing to see if the expiry date has been passed in to a function or not. So, I might as well write it now.

  $jd.isDate = function (date) {
return (!!date) && (typeof date === "object") && (date.constructor === Date);
};

Let’s explain this code. The three parts to the boolean expression that’s returned first check that the passed in date is not undefined or null (or more rigorously is not a falsy value like 0, NaN, or the empty string, or false, or undefined/null), that the parameter is an object, and then finally (since every object has a constructor) that it was constructed from the Date constructor.

The reason for the double negation in the first subexpression (which surely is the identity operator?) is a JavaScript quirk. It seems more obvious that I should be able to write

    return (date) && [...];

since the interpreter has to convert the date variable to a boolean in order to evaluate the expression. The quirk is that this conversion is merely temporary. With && (and || for that matter) the result of the expression may not be a boolean. In fact, if date is undefined/null, it’ll be temporarily evaluated as a boolean equal to false and the rest of the expression will be ignored. The temporary conversion is ignored and the result of the expression is date and not false, which is certainly not what we want. So I have to convert date manually to a boolean for the expression to be evaluated. One way is to split the code:

  $jd.isDate = function (date) {
if (!date) { return false; }
return (typeof date === "object") && (date.constructor === Date);
};

So, if the parameter is undefined/null (or any falsy value), explicitly return false. Otherwise, the parameter has some value, and so we can do the rest of the tests on what that value might be. The method I chose is to convert the parameter to a boolean by applying the negation operator, and then apply it once again to get the sense right. A little tricky I’ll admit, but it’s very much equivalent to this kind of idiomatic code:

someText = someText || "missing";

This code says, in essence “set someText equal to itself if it’s not undefined/null, otherwise set it equal to ‘missing’”. As you can see, this code would not work at all if the temporary check for true/false were permanent.

The code in jmbDate.js that creates the date object now looks like this:

(function ($) {
var $j = $.jmbLibrary;

var getMs = function (date) {
return date.valueOf();
};

var dateFromMs = function (value) {
return new Date(value);
};

var $jd = $j.date = {};

$jd.isDate = function (date) {
return (!!date) && (typeof date === "object") && (date.constructor === Date);
};

$jd.addDays = function (date, days) {
if (!isDate(date)) { return; }
return dateFromMs(getMs(date) + days * 1000 * 60 * 60 * 24);
};

$jd.now = function () {
return new Date();
};

})(jQuery);

At this point, I‘ll stop until next time, when we really will start to write the cookie code.

Topics:

Published at DZone with permission of Julian Bucknall, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}