The WebApp Wizard Web development made magical

4Oct/111

Time input mask, RegExp powered

Hi.

I dreamed about this for a long time. An input mask which would not allow any unvalid time such as 25:63. I know we can achieve this by checking this via a function bound on keydown, but the goal here is to do this without functions, but rather just via one regular expression. We could also try to check input on blur, for instance. But that could be misleading for the user, who could enter an invalid time and only be warned at the end.

You think that's no big deal? Maybe you think it is as simple as /^[0-2][0-9]:[0-5][0-9]$/

That's where the fun begins. At the time you type the first number, this expression will never match. "1" doesn't match /^[0-2][0-9]:[0-5][0-9]$/. Remember, we want to match on each keystroke.
So here is the one that matches :

/^(([0-1][0-9]|2[0-3]|[0-9])|([0-1][0-9]|2[0-3]|[0-9])(:|h)[0-5]?[0-9]?)$/

Boom. That bulky horror only matches a simple time input. Let's try to re-build this. First, we guess we will have a problem with the separator ":" or "h" sign. It cannot be optional, but if it isn't, we cannot type the first numbers, as the regexp won't match, right? Wrong. We have to use alternatives. We can have two numbers, or two numbers followed by the separator, followed by two other numbers.

/^((\d{1,2})|(\d{1,2})(:|h)(\d{0,2}))$/
  • On first keystroke (if we type a number), the first part of the alternative will match
  • On second keystroke, the first part will still match
  • On third keystroke, the first part won't match anymore (max 2 numbers). The second part will, though, if and only if this third character is a ":" or "h" separator
  • On fourth keystroke, the second part of the alternative will match (if we type a number)
  • On fifth keystroke, the second part will also match, if we type a number

That seems to be a good start, and it is not that complex. We also note that it allows to type something like "9:54", which can be a good thing (we do not need to fill with the initial "0"). However, it is far from perfect, as we can also type something like "89:76", which not at all a legit time input. But we're gonna fix this, and that's when we make this (almost) clean expression look like a pile of garbage.

Let's focus on the hours part. We want to be able to type 8:25 as well as 02:31 and 18:58, but not 24:14 neither 16:85. This is quite simple, we can, once again, use alternatives. Either we want one digit, between 0 and 9, either we want two digits, with the first one between 0 and 2, and the second one between 0 and 9, unless the first one is 2. Wow, slow down. So, we got:

  • Any single-digit number between 0 and 9 : [0-9] (or \d)
  • Any two-digits number between 0 and 19 : [0-1][0-9] (or [0-1]\d)
  • Any two-digits number between 20 and 23 : 2[0-3]

So we've got our hour-matching regexp, with range checking:

[0-9]|[0-1][0-9]|2[0-3]

It's way simpler for the minutes, as we just want to check a two-digits number comprised between 0 and 59. Remember we want to match while the user types, so we add "?" to make minutes numbers "optional"

[0-5]?[0-9]?

Just pop that in place of our previous naive \d{1,2} and \d{0,2}, and we've got our super-regexp:

/^(([0-1][0-9]|2[0-3]|[0-9])|([0-1][0-9]|2[0-3]|[0-9])(:|h)[0-5]?[0-9]?)$/

You can use this with Ruoso's compact and efficient jQuery regexMask if you want to give it a try.

I still don't know what to think about this: the regexp is not that complex, but still complex for such a simple case. What about more complex cases, like e-mail for instance? E-mail can be checked quite easily with a regexp (and still, the real e-mail regexp is not as simple as many believe), but if we add the "on-the-fly" checking, it must begin to be quite unreadable.

But hey, a single regexp...

Filed under: JavaScript 1 Comment
6Jul/113

Distributed, transparent NodeJS architecture in hostile environment

Hi everyone.

As we're trying to redesign an application at ORU-MiP, we're wondering if something already exists.

Let's settle the context first: it is an application designed for disater, emergency situations. It allows users (health professionals) to simply input victims basic data. There are three main concerns about this application:

  1. Anybody must be able to use it under difficult, extreme circumstances. Just imagine you have a ton of victims coming at you, and you must ask their names, age, etc. and type this as fast as possible in an unknown piece of software...
  2. It must just work. You have absolutely no time to configure anything, just plug your tablet PC / iPad / anything you want on the local network, type an URL in your browser, and you're ready to go.
  3. Maybe the most difficult part: we have absolutely no idea of what we're going to encounter. We cannot rely on one medium for the network part. 3G might not be available (imagine a subway crash). The hardware parts to connect could be too far apart to connect via RJ45. There might be some wave interferences, making any wireless attempt fail. A disaster can happen anywhere, anytime, so we must consider we are going to be in a really unfriendly environment. We're not talking about users in an office, sitting on a chair, in front of a 24 inches screen here.

The last 2 points are very important in this post.

So, what do we want to achieve? It's quite simple:

  1. Any client must be able to connect to the system and use it just by typing an URL in a browser
  2. The clients will have everything stored locally after the first step (hello localStorage, hello cache), and must be able to work independently of the network state.
  3. The server actually just broadcasts the messages it receives to the other connected clients (synchronization messages: create, update and delete).
  4. The server must be hosted on one of the clients (pre-installed). Less hardware to deploy is better.
  5. There might be more than one server one the network, just in case. In fact, every client will also be a server.
  6. If one server falls, another must be able to replace it instantly, with no action from the user.
  7. Everything must be absolutely transparent for the user.
  8. The user must have nothing to do (did I already say that?)

It seems like an HTML5 web app is a perfect fit for our needs. It allows us to combine ease of deployment (just type in an URL) and client-side storage and processing.

It could be really simple: one of the clients also hosts the server, and everything is synchronized by this server. But what if this server fails? What if the tablet PC on which it will be installed runs out of battery? What if the system crashes? What if the tablet PC is destroyed (unlikely, but still possible)? And believe me, these considerations are not here just for fun. It happens, and when it does, the system must continue with no action from the user.

So the idea is to duplicate the server on each client. We can pre-install the machines, unless it's some complicated, time-consuming stuff. The application is currently coded in C#.net, and it is a real pain to install/update the framework, install system updates, etc. We want to get rid of this.

Ok, so we have a few machines with the same lightweight server on it. NodeJS and Socket.IO are good choices as it allows to code fast and responsive web apps. The clients would be single-page web apps, so this is OK.

Here is how I plan to deal with the complicated stuff: each client, once connected to the server, would establish a socket connection with every server on the network (we would use some network detection protocol to achieve this). It would promote one of these sockets to the state of "pub" socket. This socket would be used to publish (pub) messages (add, update, delete of victims for instance). The other sockets would be only used to subscribe (sub) to other clients modifications.

So what happens when a client publishes a message on his "pub" socket? The server will broadcast the message to every connected client, which means every client, as every client is connected to every server via their "sub" sockets. Nice!

What happens if the server is down or unreachable? The client has a list of every other server on the network (remember the "sub" sockets). So it is possible to promote a "sub" socket to state of "pub" socket, and use this one instead. The client will then publish his message to another sever, chosen at random. The server will be able to broadcast the message to every other client, as every client is connected to every server.

In the end, after a few network connection issues, or unresponsive server for whatever reason, we might end up with every client connected to a different server, but it's no big deal, as the servers are stateless and only used to brodcast client messages.

Moreover, we could imagine that any client that was not intended to be used in the system could come in and help. Just connect to one of the servers via your browser, and you're ready. It just won't be able to be used as a server, but that's not that important. Somebody is walking by, we could ask him for help, and in a few seconds, he would be able to welcome victims and type in their names, ages, etc.

A little simplified diagram to sum things up (only two client sets of socket connections represented for the sake of readability...):

Distributed NodeJS architecture with automatic failover

In fact, I dream about the client to client communication protocol the W3C is working on. But in the meantime, we need a workaround. And, for the moment, this is the best one I've found. Every other solution I imagined would fail someday under certain circumstances (and remember, we're not talking about traditional web here, we have to consider that everything out there is trying to kill your system, and if it happens, it stacks up another disaster on top of the first one), and if so, would require some user action to continue working.

Technically, it might be pretty simple to implement. But I'm wondering:

  • Is there already some NodeJS framework or module that does the same kind of thing?
  • If not, would you be interested in one?

Thanks for reading this long post.

4May/112

jQuery 1.6 and backwards compatibility

jQuery 1.6 just came out, announcing big performance improvements, enhanced animations, and so on. At first, my brain cells were like having a big wild party, thinking about all the good stuff.

And then comes the hangover. Not backwards compatible? Maybe some little obsolete things won't work anymore, after all, that may not be so important.

But no, it is definitely important. And inconsistent, in some (weird) way.

OK, .prop() is born, taking some duty off .attr(). .attr() is for attributes (attributes don't change over time), and .prop() is for properties (they evolve. For example, is you want to retrieve the actual value of an input, you will use .prop(). OK, .val() exists. But just for the example. On the other side, .attr() will return the original value). Ouch, here is the first problematic change. Think about all the code that will break now...

But it's not only about that. They say that if you want to check a checkbox, you will have to use .attr('checked', true) instead of .attr('checked', 'checked'). Nice to see this more convenient way to do it, but... Shouldn't I use .prop('checked', true) instead? Attributes are not supposed to change, right?

So I'm very confused. As a plugin user AND author, what should I do? Shall I upgrade my plugins to support jQuery 1.6? As I use my own plugins (no? Really?), that would mean I'll have to upgrade my applications to jQuery 1.6 (no, I won't use a deprecated version of my own plugins. I use them in their last version). But if I do so, I'll probably break a good part of the plugins I'm using. If I don't, people who switched to jQuery 1.6 or newcomers probably won't be able to use my plugins. I don't like this.

Let's say I decide to upgrade my plugins. What should I do for the other plugins I use? Wait their respective authors to upgrade too? What if they don't? I could patch them myself, but I don't want to spend hours understanding how several plugins work. And that's without thinking about testing...

So, as an author or as a user, what do you plan to do regarding this good but non compatible version?

EDIT: Well, it seems that they changed their minds. jQuery 1.6.1 is out, with a fixed .attr() method which should be backwards compatible. Follow the story.

15Feb/114

Form submit confirmation, fast and easy

Following some demands, I recently released a new version of Fast Confirm, to make it more easy to implement when dealing, among others, with form submission.

But in the hurry, I forgot to include some features that I developed earlier, thinking "I'll put that online soon". And I didn't. So here there are, the missing features that some of you wanted. With version 2.1.0, you can now tell your confirm boxes that you want them to be unique, just by setting a boolean on invocation.

There is another little thing that I wanted to introduce alongside with the better event handling. Since version 2.0.0, you can simply bind FC to a form submit event, with the "eventToBind" parameter. There is a little problem with that.

Typically, a form will look like :

<form action="action.php" method="post">
   Username: <input type="text" name="username" />
   Email: <input type="text" name="email" />
   <input type="submit" value="Create user" />
</form>

So what happens when the confirm box opens? It opens pointing on the form. That makes no sense. A form is usually not a visual element. You will more likely want the confirm box to be opened on the submit button, or maybe on a fieldset, or even on a input field. But directly on the form tag? No way. Or at least, that would not be very frequent.

So I added the "targetElement" parameter. It simply is a selector that allows you to specify on which element, within the form, you want the confirm box to open. For example, a ":submit" selector will simply make the confirm box open on the submit button of the binded form.

Have a look at the demos!

23Jan/111

Fast Confirm, Universal Paginate, reloaded

Hi everyone.

I finally had some time to re-work on my web projects. Since FastConfirm has been quite appreciated, I decided to take a few minutes to rewrite it a bit. The main concerns were about events management and manipulating it programmatically.

So I decided to take it directly to version 2.0, breaking some backward compatibility. Nothing bad, the usage remains almost the same, except for the "close" method.

So now, you can call:

$('.click_me').fastConfirm('close');

To close the previously opened confirm box.

OK, so this was for the method calling stuff.

You can also now completely delegate event handling to FastConfirm. This feature has been asked for several times, and I must admit I was not really satisfied with the previous plugin usage (well, in fact, you can still use the plugin like you did before). This is mainly useful for form submit confirmation. So now, you can simply do:

$('.confirmable_form').fastConfirm({
   eventToBind: 'submit'
});

And FastConfirm will take care of binding the confirm box on the submit event, allowing it if the user says "yes", canceling it if the user says "no". The same could be true with any event. The new eventToBind parameter defaults to false, which will result on the same behavior than before.

As a reminder, you previously had to write something like this to achieve the same behavior:

$('.button').click(function() {
   $(this).fastConfirm({
      onProceed: function($trigger) {
         $trigger.closest('form').submit();
      }
   });
   return false;
});

That's amazing. But there's one more thing ©. ;-)

The user is now able to close the confirm box by hitting the Escape key. This is the same as clicking "No" and provides a quicker way for the power user. A little detail can sometimes greatly improve the user experience.

I hope you will like this new, rewrote, cleaner and easier version of Fast Confirm. As usual, you can find it here.

Universal Paginate has also been rewrote in order to provide a better control over plugin internals. Methods can now be called the standard way:

$(list).universalPaginate('changeItemTemplate', newItemTemplate); 

for example.

Also, Universal Paginate has a new parameter which overrides ajax requests defaults when querying the server for data on page changes.

As this is the official jQuery plugin authoring recommendations, this rewriting will happen for other plugins, too. It will provide a better consistency and probably less bugs / shitty code.

Oh, and, by the way, these two plugins now pass JSLint. :-)

Last thing, I am very thankful to all of those who contributed to make we want to improve my work, whether with bits of code or simply with comments and requests.

14Dec/108

Javascript variable declaration and hoisting

Do you know what JS hoisting is? If you do, I guess you already declare your variables properly. But if you don't, I am pretty sure you can still improve your code a little bit, and make it much more reliable.

If you already experienced some strange variable behavior, like a variable's value being unexpectedly changed or not changed, this post is for you.

Let's see how JS handles variables through a few examples.

JavaScript variables scoping

First, let's have a look at how JS variables are scoped. One may think that JS is a C-like language. And yes, the syntax is quite C-ish. But the language works quite differently. And yes, variable scoping is really different from what you may see in C-like languages.

Most languages use block-level scoping. JS doesn't. It uses function-level scoping. You should keep this in mind at all times, as it is probably one of the greatest sources of confusion for newcomers.

So what happens if we execute this piece of code?

(function() {
  var a = 10;

  if (true) {
    var a = 35;
  }

  alert(a);
})();

Yes, it alerts 35. The same kind of program written in C would output 10 (provided you really re-declare your variable inside your block).

Well that's the first surprise. And not the last, nor the least.

JavaScript variables declaration

Well, let's see what happens when we declare a variable.

Let's take the following code:

var a = 10;
alert(a);

(function() {
  alert(a);
  var a = 200;
  alert('a now contains: ' + a);
})();

What do we have here? The first alert says "10", as we could expect. But the second one alerts "undefined". Why on earth would a be undefined? Try to remove the "var a = 200;" line. The second alert says "10" again? Right. So this declaration / initialization line has something to do with this strange behavior. No matter where you declare a variable in your function, this variable will be declared anywhere in this function. What about the initialization? It stays right where you wrote it.

Eventually, JavaScript hoisting

Wow wow wow... What's that? Do you mean JS doesn't care about how I write my code? Not really. In fact, the previous piece of code will be interpreted like so:

var a = 10;
alert(a);

(function() {
  var a;
  alert(a);
  a = 200;
  alert('a now contains: ' + a);
})();

In fact, all the variable declarations, but not the initializations, are put at the top of your function. This is commonly called hoisting.

Note that this works with all declarations. Even the functions declarations. Be careful though, as the variable-like defined functions will only see their name hoisted (as we saw in the previous example with variable a), but not their body. "Traditionally" declared functions will be entirely hoisted (name and body). Here is a little example you can run to understand this phenomenon:

(function() {
  f1(); // Will run OK
  f2(); // Will throw an error

  f1() {
    alert("I'm in function f1");
  }

  var f2 = function() {
    alert("I'm in function f2, but I will never run before the f2 initialization...");
  };
})();

That may seem quite surprising, but that's how JS works. I can't say if that's a good thing or a bad thing, honestly, I don't see any advantage or drawback. It's just another way to work. As it pushes us to keep a clean code, with all vars declared at the top, it may be a good thing.

Speaking of code quality, your code won't pass JSLint (when you select "the good parts") if you don't declare all your variables at once in each function.

But what should I do then?

This is why you should always declare your variables at the top of your functions. You'll have no bad surprises since you respect this rule.

I hope this post was useful, and that it will help you achieve a better code quality.

2Nov/100

A new way to paginate

Hi.

Just a little post to tell you I released a new jQuery plugin, Universal Paginate.

It simply allows you to paginate any content, and is not limited to a type of list or table. You want to paginate simple paragraphs? Universal Paginate is here for you. A table? UP is here for you too! Any kind of list (dl, ul, ol)? UP is here, again.

It supports natively some advanced features like remote Ajax JSON datasources, jQuery Templates syntax, on-the-fly changing of the number of elements to display on one page, etc.

Check it out!

4Oct/100

Even lighter and prettier confirmation

Hi all.

I took advantage of working on a little Fast Confirm bug to enhance a bit the user experience. Facing my little confirm boxes, I told myself: these boxes don't stand out as much as they should. Don't disturb the user is nice, but we want him to answer anyway.

So I decided to use a few CSS3 features to make them a bit prettier, a bit more distinct from the rest of the page. So I added a shadow under the box and gave the buttons some color and depth.
I also wanted to get rid of the images I used to make the little arrows on the boxes. So I used some border techniques to achieve that.

The boxes looked like this before:

And now:

I hope you will have a nice time using it.

21Sep/102

How to ask politely the user

When working on a project, you often have to ask the user for information: choice, confirmation, etc. There are a few ways to achieve this: plain old confirm(), prompt(), or fancy dialog boxes (jQueryUI for example), or "inline" stuff.

After having tested Producteev for a while, I found out that I really like the "inline" way. So I decided to do it this way on my current project. I needed an easy, unobtrusive way of asking the user for confirmation. I didn't want to spend hours developing or debugging it, so I came out with this simple plugin: Fast Confirm. It allows you to ask simply and politely the user, without throwing a modal dialog box  in his face. Also, it clearly identifies the source of the confirmation so that there is no doubt what you're talking about.

As usual, there is a tiny demo page to show you how the plugin behaves on a simple use case. Feel free to try it out, download and play with it!

15Sep/100

The forgotten jQuery methods

jQuery is great, jQuery is fast, jQuery is the best JS library, etc. But what if it was more awesome than we think? Personally, I went through that, and I wanted to share.
At the beginning, like most other web developers, I discovered jQuery with very basic features, and, over time, I discovered new ones. One day, I decided to really go through the documentation to see if I could find shortcuts for what I do on a daily basis.
The problem is that we try to solve problems with the tools we know well. But sometimes, we could do a lot better with a new, stronger, sharper tool. That's what I am talking about here. The need to keep up to date, and always try new tools.