zomgistania

Main page | About | Articles | Previous Posts | Archives

Friday, August 25, 2006

Form validation with JS

How often do you fill in a form and submit it only to get a page telling you that something was wrong in your input? Yeah, pretty often...

Even though it's very easy to add simple JavaScript validation to the form which tells the user if his input is wrong, almost no form ever has such features.

In this post, I'll introduce some simple means to check the values in forms using JavaScript to provide a better browsing experience to the user.


How does this work?

In the HTML Input element you can have an onChange event and an onKeyUp event (and some others). We can use these to run JavaScript code.

We run a check and if the value in the field isn't what it should be, we can, for example, highlight the field with a red background color or display a message to the user telling the input is wrong.

Of course this will only work if the user has JavaScript enabled. Most browsers these days have JS support and users usually leave it on, but do not forget to validate the form inputs server-side using your scripting language of choice.


Using the events

The two important events are onChange and onKeyUp.

The onChange event fires when the value in an input field changes and the user selects something else, ie. clicks on somewhere else on the page or presses tab.

The onKeyUp event fires every time the user releases a key, ie. when typing.


Here's an example of using onChange


<input type="text" onChange="if(isNaN(this.value)) { alert('The value is not a number'); }" />

The code checks if the value in the field is Not a Number (NaN). If the input is something else than a number, the user gets a message saying "The value is not a number".

Note: the this keyword used in the check refers to the input element itself, so we can use it to get the value of the field


Validating

To make validating the fields easier, let's first create some functions.

Often there are fields that require numeric input, so let's create a function which can be used to check if the value is a number and optionally if it's between some values.

Another task is to limit the maximum input in a field so the user can only write, say, up to 250 characters to a field, so we'll create a function for that too.

Finally we'll also use a regular expression to see if the value in a field is a valid email address.

You can download a script file with all the functions from here, but I suggest you still go through the explanations if you're not completely familiar with them.


Let's start with the number check...

function IsNumber(field,start,end)
{
//Check if value is not a number
if(isNaN(field.value))
return false;

//if start and end are defined
//check if the number is between them
if(start && end)
{
if(field.value >= start && field.value <= end)
return true;
}
else
return true;
}

This function should be pretty simple to understand. The field should be the input element and start and end are the numbers between which the value has to be, but they are optional.

First, we just check if the value in the field is a number at all. If it isn't, we return false. After this we check if start and end are defined and if they are, compare the value to them.



Next, the max size function..

function MaxSize(field,num)
{
//if length of data is > than max,
//make it shorter
if(field.value.length > num)
field.value = field.value.substr(0,num);
}

Yet again, the field should be the input element and num the maximum amount of characters allowed. The length of the value in the field is just compared against the num, and the substr method is used to make its length to num characters if it's too long.


And finally the email check..

function IsEmail(field)
{
//this is a regular expression
var expr = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;

//Check if regexp matches the value in the field
if(expr.test(field.value))
return true;

return false;
}

You don't need to understand the syntax of the regular expression, just know that it matches only valid email addresses, so we can use it to test whether or not the value is a valid email address.


With these functions you can easily validate values in forms, but let's define one more function. This one can be used to highlight a field in some color

function Highlight(obj,col)
{
//just set the bgcolor of obj to col
obj.style.backgroundColor = col;
}

Yeah, we could probably just write obj.style.backgroundColor = 'something' when we want to change the color, but that's so much simpler to use and that's why we define it as a function.


Using our validation functions

Look at this example page which uses these functions. I'll explain the details of the code on that page here.

First there is the number only field

<input type="text" name="num" onchange="if(!IsNumber(this,1,100)) { this.value = 1; Highlight(this,'red'); } else { Highlight(this,''); }" />

the code in the onchange event first uses the IsNumber function to see if the value in the field is between 1 and 100. As there's the ! in front, the if is true when the value is NOT a number.

If the value isn't a number between 1 and 100, it sets the fields value to 1 with this.value = 1. Then it uses the Highlight function to highlight the field in red.

The else segment runs when the value is a number between 1 and 100. The only thing we do there is set the background color of the field to '' which in this case is the default "no color" value. We need it because the fields background might be red if the user had inputted an incorrect value first, so when he inputs a correct one the background will stop being red.


Next there's a textarea which allows only 20 characters. As you can see from this, these functions also work on textareas.

<textarea rows="5" onkeyup="MaxSize(this,20)">Max 20 chars!</textarea>

This one is very simple. When the user has typed in a key, it just uses MaxSize to crop the length if it's over 20 characters.


Lastly, the email field.

<input type="text" value="only.valid@email.com" onchange="if(!IsEmail(this)) { Highlight(this,'red'); } else { Highlight(this,''); }"/>

This one is pretty similar to the number only one. The field gets a red background if the value is not a valid email address.



There's one thing, however, which isn't demosntrated on that page but is quite important. It's the empty field check. You should do this when the user presses the submit button on the form.

Here's how it works:

First, set the onsubmit event of the form..
<form ... id="myform" onsubmit="return FormCheck()">

then create a function called FormCheck


function FormCheck()
{
//First, get the form element
var f = document.getElementById('myform');

//Now we can easily check values in fields like this
if(f.fieldName.value == '')
{
Highlight(f.fieldName,'red');

//if we return false, the form won't be submitted
//so the user can fix his errors
return false;
}

//if all was ok, return true so the form gets submitted
return true;
}

Checking if a field is empty is simple as you can see from that. Notice how I defined the form an ID so I can use the getElementById function there. Accessing inputs in a form is very simple after you have the form element, just put the fields name there as shown in the code.




As you can see, checking forms like that is very simple with JavaScript, yet it's not used almost at all. I wonder why...

Labels: ,

Monday, August 21, 2006

Moving settings over from an old widget to a new one


In Opera Widgets you can save settings using the widget.setPreferenceForKey method. It's very useful, but there's a small flaw in the design.

When you release a new version of your widget, the user must download the new version of the widget and they usually have to reconfigure it as the preferences you stored in the old widget do not move over to the new one.


Here's a very simple method to move the settings over from the old version to the new version. It's not completely automatic, but it shouldn't be too difficult or troublesome for the user.


First, you need a field in the widget. It can be an input or a textarea. This will be used to display the widgets internal data for the preferences so the user can copy it.


Getting the data to the field is very simple. You can use the JavaScript object serializer I introduced in an earlier post to create a text version of the array or the object you use to store the settings.

If you don't use an object or an array to store the settings, I'd recommend you start using one because it simplifies things a lot if there's much data.


Second, you need a button for loading the data in the field. This is used to have the widget load the data in the field.

The way this works is that the user has both the new and old version running, he goes to the field in the old one, copies the data there and pastes it into the new one and presses the load button. The new version then just uses the data in the field and loads itself instead of using the data stored in the widget.preferenceForKey thing. Simple huh?


I also wrote a small example widget to demonstrate the idea. Grab it from here. If it doesn't run as a widget, just load it from File->Load.

Put some values to the two value fields, press save. Then it should reload the widget and display the data string in the first field. You can then copy that and set some new values in the two value fields and save again.

Then just paste the string you copied from the first field back to the first field and press load... you should see how the two fields below revert to what they were when you copied the string :)


As usual, if anything was unclear or you have any questions, ask away!

Labels: , ,

Sunday, August 20, 2006

Intermediate C# Concepts


Here's my second C# article, intermediate C# concepts. This article explains some more C# concepts after the introduction article. In the end you'll have a simple text editor a bit like notepad. Topics covered include more about classes, arrays and lists, creating controls run-time with code etc.

Again, due to some limitations in the blogger system I'm hosting it elsewhere. Please post comments, questions or anything about it to here.

Read the article

Labels: , ,

Wednesday, August 16, 2006

Serialization of JavaScript objects

In the widget I'm working on I have to save the users preferences and settings. In Opera Widgets, this can be done by using a JavaScript function widget.setPreferenceForKey which can be used to store strings with keys.

I had written a function in my Clock-class which made a string of its data, like the name, GMT offset, GMT minute offset, DST settings etc.

As you can see, there's quite a lot of things already on that list. I started to getting into trouble when I started working on alerts.

I wanted to save the alerts to each clock, so I would've had to write even more code to get a string of the clock, which I just found a bit stupid. In PHP you have a Serialize() function which creates a string of an object or an array, which I thought would be very useful to have in JavaScript as well for purproses like this.


So I coded my own Serialize() and Unserialize() functions for JS!


How it works

The Serialize-function takes an object or an array as its parameter and returns a string representation of it, which can be then given to Unserialize() along with a base-object and you get an object with the same properties as when Serialized.

For a simple array, the serialize output might look like this:

s:0:5:Hello:n:1:2:20:s:2:14:I'm the cell 2

The above data would result in an array as follows:

Array[0] = "Hello";
Array[1] = 20;
Array[2] = "I'm the cell 2";


So how exactly is that converted into an obscure string like that?


The Serialize() -code


//JavaScript object serializer
// Returns a string representation of an object
function Serialize(o)
{

//The serialized data is stored here
var data = '';

//It's an array if o.length is defined
//Arrays must be enumereated differently than
//other objects, so the check has to be made
if(o.length)
{
//Array-mode

for(var i = 0; i < o.length; i++)
{
ParseProp(i);
}
}
else
{
//Object-mode

for(property in o)
{
ParseProp(property);
}
}
//strip : from end
data = data.substr(0,(data.length-1));

return data;

//Internal function which parses the properties
function ParseProp(p)
{
//Functions aren't serialized
if(typeof o[p] != 'function')
{
switch(typeof o[p])
{
//If property is a number
case 'number':
//Convert to string and find length
var len = String(o[p]).length;
data += 'n:'+p+':'+len+':'+o[p];
break;

//if prop is a string
case 'string':
var len = o[p].length;
data += 's:'+p+':'+len+':'+o[p];
break;

//If prop is bool
case 'boolean':
var b = (o[p]) ? 1 : 0;
data += 'b:'+p+':'+b;
break;

//If prop is another object
case 'object':
//Run a serialize on the child-object
var objdata = Serialize(o[p]);
var len = objdata.length; //take data length

//Find the type of the object from its constructor
var type = o[p].constructor.toString();

//Find location of the constructors name
var sindex = type.indexOf(' ') + 1;
var sindex2 = type.indexOf('(');

//Extract the name of the constructor
type = type.substring(sindex,sindex2);


data += 'o:'+type+':'+p+':'+len+':'+objdata;
break;

}
data += ':';
}
}
}


There we go. So firstly, the code checks whether the object is an array. Arrays require a bit different approach to enumerating through its properties as seen in the code.

The ParseProp function inside the Serialize does most of the work. It parses the properties of the object into strings. First, it uses typeof to check if the property is not a function, as we don't want to serialize functions.

Then we continue to a switch statement to parse the different types.

Numbers and strings are parsed in almost the same way: we find its length by converting it into a string using String() and its .length property. Then its saved into the data-block. n is the key for Number type, after which comes the name of the property and after that the length and finally the value.

Strings only differ that we don't need to convert them to find the length. Their key is s.

Boolean variables (true/false) are saved into the datastring, depending on their state, as either 0 or 1 to save space.

The object parser is probably the most complicated here. First, it serializes the child-object using a recursive call to Serialize(). Then it finds the length of the serialized data.
It also has to find the type of the object, which we can find from the objects constructor with a bit of string manipulation: as the constructor looks like "function Name() { some code here }", we just take the first location of a space and the first location of a ( to find the Name part and save it.

The object notation in the data goes like this: o is the key for the object, then comes the type name, property name, data length and the actual data.


All of the data are appended with a : if we later need to add more properties to the string, so after all props have been parsed, we simply remove the last character from the data and return it.


The Unserialize() -code


//JavaScript object unserializer
// Returns an object from the serialized data
function Unserialize(data,o)
{

//Invalid Serialize-data. Should begin with s,b,o or n
if(data[0] != 's' && data[0] != 'b' && data[0] != 'o' && data[0] != 'n')
return o;

var i; //Counter defined here so it's accessible from GetNextString

for(i = 0; i < data.length; i++)
{
var mode = GetNextString(); //Get mode

var d = null; //stores the final prop
var propname; //stores name of the prop
if(mode == 's')
{
//string-mode

propname = GetNextString();
//Find next delimiter

var len = Number(GetNextString());
//Extract data
d = data.substr(i,len);

//i is incremented in the end, otherwise we'd have
//to go forward datalength + 1 here!
i += len; //advance pointer
}
else if(mode == 'n')
{
//Number mode
propname = GetNextString();
var len = Number(GetNextString());
d = Number(data.substr(i,len));
i += len;
}
else if(mode == 'b')
{
propname = GetNextString();

d = (data[i] == 1) ? true : false;

//i is incremented in the end, otherwise we'd have
//to go forward + 2 here!
i++; //pointer forward
}
else if(mode == 'o')
{
var type = GetNextString();
propname = GetNextString();
var len = Number(GetNextString());
var odata = data.substr(i,len);

//We need to use eval to create a new
//instance of "type"
eval('d = new '+type);


d = Unserialize(odata,d);

i += len;
}

//Save
o[propname] = d;

}

return o;

//this is used to get data from the datastring
function GetNextString()
{
var n = data.indexOf(':',i);

//Extract property name
var strdata = data.substring(i,n);

i += strdata.length + 1; //advance pointer

return strdata;
}
}


Now this is a bit more complicated than the Serialize() function. You have to pass the serialized data as a parameter and an object which is used to save the props from the serialized data. So if you had an serialized array, the object has to be an array.

First, there's a check to determine whether the serialized data is ok. This is done by checking whether it starts with one of the keys used for different datatypes. Not absolutely necessary, but I think it's a good thing to have.

The i variable is defined before the for this time, so GetNextString can access it. GetNextString is just something which simplifies a few string operations, so I don't have to write a substring call and an i+=length call every time.


We loop until we have reached the end of the data. First, we get the mode (n for number, s for string, b for bool, o for object) from the data.

Parsing strings is pretty simple. The propertys name and length are taken from the data to be able to use substr to extract the actual data.

Note: we can't use GetNextString to extract the actual data! If there's a : in the data, things will screw up, so that's why we also store the data length.


Parsing numbers is pretty much the same as for strings, we just use Number() to convert the data into a number.

Boolean parsing is even more simple, as it only takes one character after the initial prop name.


Now, the object parser is yet again a bit more complicated as expected.

First we find the type name, prop name, data length and the data from the serialized data. Then we use eval() to create a new instance of the type stored in the variable. After this it's just a matter of a recursive Unserialize call and we're done.

After the if-section, the property is saved into the object. Finally the new object is returned.


Wrap up

Using this method to save data is pretty simple:

var a = new Array('Example',true,'Yes sire',1234);
var data = Serialize(a); //store a to a string

var newArray = new Array();
newArray = Unserialize(data,newArray);
//now newArray contains the same things as a



There are, however, some things to note:

In custom objects, only the variables defined with this are saved! Take this into account when working with this. I'm not sure if there's a method to save private members as well, so if you know a better method of going through the properties, please post a comment.

Labels: , ,

Monday, August 14, 2006

Opera Widgets: Imitating alert() behavior using a custom object

As I've been tinkering around a lot with widgets, I've sometimes needed a function like the alert() in JavaScript, ie. something which can be used to display a message to the user.

In this post, I'll go over my MessageBox class, which can be used for just that.


The idea behind it all

Idea is to make showing alert boxes as simple as possible, while still giving some functionality to the user. As it's not possible to use alert() in Opera Widgets, you need to code this yourself. I also wanted to be able to either display timed boxes which would disappear after a certain time in addition to "normal" ones with an OK button.


Give me the code!


//Displays a generic textbox in the style of alert
//w = width, h = height, rOK = require the press of OK button to close
function MessageBox(w,h,rOK)
{
var element = null;
var width = w
var height = h;
var left = 30;
var top = 10;
var requireOK = rOK;

//shows the messagebox
//msg = message in the box, time = time how long the message remains visible
//note: if requireOK is true, the box won't close until OK is pressed
this.Show = function(msg,time)
{
element = document.createElement('div');
element.style.left = left+'px';
element.style.top = top+'px';
element.style.width = width+'px';
element.style.minHeight = height+'px';
element.style.border = '1px solid black';
element.style.backgroundColor = 'white';
element.style.position = 'absolute';
element.style.textAlign = 'center';

element.innerHTML = msg+'<br /><br />';

if(requireOK)
{
var okbutton = document.createElement('button');
okbutton.text = 'OK';
okbutton.addEventListener('click',function() { Hide(); },false);
element.appendChild(okbutton);
}

document.appendChild(element);
if(!requireOK) setTimeout("Hide()",time);

}


Hide = function()
{
document.removeChild(element);
element = null;
}
}


There we go. There's not much to explain if you already know JS and DOM, but let's go through it a bit for those who don't.

We define some variables to hold various data on the messagebox. The element variable will store the reference to the actual div we use to display the messagebox, which is needed so we can hide it later. Rest of them are probably obvious, except requireOK, which is used to check whether we want to display an OK button on the messagebox or not.


The Show function is used to display the box. First we create a div element to hold the message and change some of its CSS properties. We use absolute positioning to make the div appear exactly where we want and ignore the positions of the other elements. We also add the message user wants the box to show to its innerHTML.

If the requireOK is defined as true, the code creates a new button element and assigns it a click event which calls the Hide function. Finally the button is added to the base div with appendChild.

After this, the div is appended to the document and if we don't have an OK button, a timeout is set to hide the box after the time the user specified in the parameter.


The Hide function is quite simple: we simply use document.removeChild to remove the messagebox div element from the document.


Using the class is simple:

var message = new MessageBox(100,100,true);
message.Show("Hello World!",0);


This would display a 100x100 messagebox with text "Hello World!". It closes when the user presses the OK button displayed on the box. Simple and fun.


Wrapping it up

Using classes like this is a good way to add reusable functionality to widgets. This one for example can be used in all widgets you want, instead of possible static code in a single widget which would do the same. Sure, the static one could be faster and easier to code... but what would be the fun in that? :)

There are some things that could be added to this class, however. Someone might want to be able to change the position or the colors of the box, so functionality for that could be added if necessary.

Labels: , ,

More Object-Oriented JavaScript

Here's some more stuff related to OO-JavaScript

How to create a function which is both callable from inside the class and from outside?

This had caused me some problems up to now... I wasn't able to make a function inside a class work from both inside the class and from outside. Here's how to "properly" create one of those:


function Example()
{
this.FunctionName = InternalFunctionName

function InternalFunctionName()
{
// do something funky
}
}


In the above example, the InternalFunctionName function is callable with that name from inside the class. From outside, the same function is callable with the name FunctionName. Of course they can both share the same name, the different name was just for the sake of the example.



Expanding objects

In JavaScript, you can easily expand objects/classes which already exist. For example, you can add a function to the built-in Array object.


Array.prototype.SayHello = function()
{
alert('hello');
}


After doing that, all Array objects can show you an alert box containing text Hello. Yeah, it's pretty useless but it works as an example. You could take the CopyArray and Equals functions from my post about comparing and copying arrays in JS and add those if you wanted something useful.

You can also add functions to already existing instances, which isn't very useful but possible


var s = new SomeClass();
s.DoSomething = function()
{
//do something
}



Inheriting from a base-class

To inherit from a base-class, do the following


function BaseClass()
{
function A()
{
//something
}
}

function OtherClass()
{
//inherit from BaseClass
this.prototype = BaseClass.prototype;
}


This would make OtherClass get function A from BaseClass. Very simple, but the syntax is probably a bit different from what it usually is.

Labels: ,

Sunday, August 13, 2006

World goes 'round

Been starting on school again here... not many courses though... one. Dealing with MS SQL Server, which I already am pretty comfortable with. In addition to that, I need to do some exams, but I'm expecting an easy fall term.

I've been writing some articles on C#. As you can see from the previous post dealing with introduction to C#. The next ones in the series are in the works and I can hopefully get them up sometime soon~ish. I'm also been tinkering with some localization (adding multiple language support to an app) issues, so you can look forward to an in-depth look into that as well!


For my projects, I've been starting work on some website work for a LAN Party and an accounting application. I also need to continue my game development, as I'm intending on doing my scholarly thesis on that project. Maybe some posts on those subjects here. Not forgetting the JavaScript, of course... the World Clocks -widget is still pretty fun and intresting so I'll probably write about some things related to JS developement too.



But now I think I'm going to catch some sleep. Later!

Monday, August 07, 2006

Introduction to C#

I've written an introductionary article to the programming language C#.

The article introduces you to the C# programming language and the Visual Studio developement environment. Topics covered include basics about classes, Windows applications, error handling etc. You should preferably have some past programming experience, but you might make something even if you don't.

Please post any comments, questions and feedback to this post.


Read the article: Introduction to C#

Labels:

Friday, August 04, 2006

Implementing automatic version checking in an Opera Widget

Updated August 18th, fixed an issue with the source code which causes a lockup if you're not connected to the internet when the update check runs


As I've been working on my Opera widget World Clocks, I've done a bunch of version updates with new features and such. Of course people might not come back to the download page to check if there's anything new, so it would be useful to be able to tell them automatically when you have a new version available.


So I went and added an automatic new version check, and now I'll tell you how to create one as well.


Preparing the widget

Okay, for the Widget to know when there's a new version you need something to compare. What's better than having a variable store the version of the widget?

var widgetVersion = "1.0";


And what do we compare that with? Let's save a file somewhere on the internet, with the current version of the Widget. For example, I put the current version of my clock widget to here. As you can see, it's just a number.

To allow our widget to access a page in the internet, we must add this to the config.xml file:


<security>
<access>
<protocol>http</protocol>
<host>admins.fi</host>
</access>
</security>

For example, my file is at http://admins.fi/~eagleeye/clockversion.txt, so I set the protocol as http and host to admins.fi.


Creating the update checker

To access that page, we will use the XMLHttpRequest object. For the sake of reusability, let's make our object a bit better than just some code accessing a static page... let's make it reusable in other projects as well!


//parameters:
//vurl: the url where the file to compare is
//cver: current version of the widget
//callback: the function to call when a new version is out
function UpdateChecker(vurl,cver,callback)
{
var checkUrl = vurl;
var currentVersion = cver;
call = callback;

//this function checks for the update
this.Check = function()
{
var req = new XMLHttpRequest();
req.onreadystatechange = function()
{
if(req.readyState == 4)
{
//simply compare the page to the version number
if(req.responseText != currentVersion)
call();
}
}
req.overrideMimeType('text/plain');

//the random part is used to bypass Operas caching.
//sometimes the page stays in cache and wont be updater properly
req.open('GET',checkUrl+'?random='+Math.random(), true);

try
{
req.send(null);
}
catch (e)
{
//problem connecting
}
}
}


it's a very simple XMLHttpRequest function there. To use it, we could do...



function Init()
{
var updater = new UpdateChecker('http://site.com/ver.txt','2.0',newVersion);
updater.Check();
}

function newVersion()
{
//put some code here
//which tells the user
//that a new version is out
}



Simple as that. I'm not going to go into details about using XMLHttpRequest here, there's a very good article at http://developer.mozilla.org/en/docs/AJAX:Getting_Started