Web technologies -- Laboratory 6 -- 2009-2010 -- info.uvt.ro

JavaScript

edit

JavaScript (JS) is the name of Netscape Communications Corporation's and now the Mozilla’s foundation implementation of the ECMAScript standard, a scripting language based on the concept of prototype based programming.

The language is best known for its use in websites (as client side JavaScript), but is also used to enable scripting access to objects embedded in other applications.

IMPORTANT: JavaScript is not Java!

JS can be used to do various things but it primarily comes into hand when:

JS code can be placed:

  • inside a <script> tag:


<html>
	<head>
		<title>First JavaScript Example</title>
	</head>
	<body>
		<script type="text/javascript">
			alert("Hello World!!!");
		</script>
	</body>
</html>


  • in a different page and then you can refer function in that file from within the HTML:

page:


	<script src="myFirstJSFile.js"></script>


Insight on JS:

  • has a syntax that is very similar with the one of Java and C. Therefore programmers used to write programs in those languages will get used with it easily.
  • IS case sensitive
  • has 3 types of pop up windows: alerts, confirms and prompts.
    • alert("MessageText") - displays a popup with an alert and an OK button
    • confirm("ConfirmText") - displays a popup and 2 buttons OK and Cancel. It returns a boolean value, depending on the button which was clicked
    • prompt("InfoText","defaultValue") - prompts the user to enter a value in a text field. It returns the entered value
  • if-else and loop statements are like the ones in C and Java
  • functions and events:


<html>
	<head>
		<script type="text/javascript">
			//function definition
			function myHello() {
				alert("Hello World!!");
			}
		</script>
	</head>
	<body>
		<!-- the function myHello is called when the event onclick appears -->
		<input type=”button” value=”Say hello onclick=”myHello()”>
	</body>
</html>


  • browser detection and managing:
    • In order to find out information about your browser you need to use the navigator object with the following properties:
      • navigator.appCodeName – stores the codename of the browser
      • navigator.appName – stores the name of the browser
      • navigator.appVersion – stores the browser version
      • navigator.userAgent – stores the header information for the browser
      • navigator.platform – stores the platform on which the browser is been run
  • cookies are stored in the document.cookie (although it seems to act as a string it isn't!) property of the document object. Cookies are client side variables that keep information about a site, such as last visit, user name, IP address etc. In order to use them, one needs to allow cookies in your browser. Basically a cookie has the following form: cookieName=cookieValue; expires=Thu, 01-Jan-2010 00:00:01 GMT;. The document.cookie variable contains a string in the form cookieName1=cookieValue1; cookieName2=cookieValue2. All a programmer should do is to write down 3 simple functions that manage cookies: setCookie(...), delCookie(...) and getCookie(...):


function getCookie(NameOfCookie) {
	if (document.cookie.length > 0) {
		begin = document.cookie.indexOf(NameOfCookie+"=");
		if (begin != -1) {
			begin += NameOfCookie.length+1;
			end = document.cookie.indexOf(";", begin);
			if (end == -1)
				end = document.cookie.length;
			return unescape(document.cookie.substring(begin, end));
		}
	}
	return null;
}

function setCookie(NameOfCookie, value, expiredays) {
	var ExpireDate = new Date ();
	ExpireDate.setTime(ExpireDate.getTime() + (expiredays * 24 * 3600 * 1000));
	document.cookie = NameOfCookie + "=" + escape(value) + ((expiredays == null) ? "" : "; expires=" + ExpireDate.toGMTString())
}

function delCookie (NameOfCookie) {
	if (getCookie(NameOfCookie)) {
		document.cookie = NameOfCookie + "=" + "; expires=Thu, 01-Jan-70 00:00:01 GMT";
	}
}


  • form validation works most of the times as follows:
    • the user enters some values in the form fields
    • when clicking the submit, an onsubmit (attached to the form tag) event is called which triggers the execution of a javascript that return either true (when validation is successful) or false (otherwise): onsubmit="return validateFields()"

The JS (in our case validateFields() function), will check each value entered in the fields that need validation. It checks field by field and if one does not check it simply add something to an error string (or only puts a boolean variable called isValid to false). When all fields are checked it looks to see if the error string is empty (no validation errors) and returns true. If not, it displays an alert showing that error string, and return false. (or, if using a boolean variable it simply returns that variable’s value).

The following example shows how we could use DOM to validate an email field inside a form:


function validEmail()
{
	var s = "";
	// Check if the email field is empty. We assume that the name of the email field is: Email
	if (document.getElementById('Email').value == "") {
		s += ("* Please enter an Email address\n");
	}
	// If it is not empty check to be in the form abc@xyz.uvx
	if (document.getElementById('Email').value != "") {
		if (!echeck(document.getElementById('Email').value)) {
                               s += ("* Please enter a valid Email address");
		}
	}
	// If it is not OK i.e. our error string is not empty
	if (s != "") {
		alert(s);
		return false;
	}

	return true;
}


The echeck function is defined as follows:


function echeck(str) {
	var at="@"
	var dot="."
	var lat=str.indexOf(at)
	var lstr=str.length
	var ldot=str.indexOf(dot)
	if (str.indexOf(at)==-1) {
		return false;
	}
	if (str.indexOf(at)==-1 || str.indexOf(at)==0 || str.indexOf(at)==lstr) {
		return false;
	}
	if (str.indexOf(dot)==-1 || str.indexOf(dot)==0 || str.indexOf(dot)==lstr) {
		return false;
	}
	if (str.indexOf(at,(lat+1))!=-1) {
		return false;
	}
	if (str.substring(lat-1,lat)==dot || str.substring(lat+1,lat+2)==dot) {
		return false;
	}
	if (str.indexOf(dot,(lat+2))==-1) {
		return false;
	}
	if (str.indexOf(" ")!=-1) {
		return false;
	}
	return true;
}


IMPORTANT: DOM is the preferred way of validating (X)HTML forms!

NOTE: to refer to the HTML document using DOM use the document keyword:


	// Create a table element
	var tab = document.createElement("table");
	// Add table to the body
	document.getElementsByTagName('body')[0].appendChild(tab);
}

NOTE: you can convert the DOM tree to string using: var domToString = document.getElementsByTagName('body')[0].innerHTML;. This method is useful if you want to send your modified HTML/XML DOM to the server for saving.

NOTE: in IE you can save the DOM using:

	// Instantiate a DOM object
	var doc = new ActiveXObject("msxml2.DOMDocument.4.0");
	doc.async = false;
	doc.resolveExternals = false;
	doc.validateOnParse = false;

	// Load an XML doc into the DOM instance
	var xmlDocAsString = document.getElementsByTagName('body')[0].innerHTML;
	doc.loadXML(xmlDocAsString);

	// Save the dom to a file
	doc.save("saved.xml");

IMPORTANT: however saving files locally is a security breach. This method is not 100% trusted or allowed by IE.


AJAX

edit

AJAX stands for Asynchronous JavaScript and XML, and it combines several technologies:

  • XHTML and CSS for marking up and styling information
  • The DOM accessed with a client-side scripting language especially ECMAScript implementations suh as JavaScript and Jscript, to dynamically display and interact with the information presented
  • XML is sometimes used as the format for transferring data between server and client
  • XMLHttpRequest object, used to exchange data asynchronously

NOTE: AJAX is (the preferred way) a good choice of handling incoming data from the server

The following code fragment shows how we can create a simple AJAX application which reads an XML from the server:


<script type="text/javascript" language="javascript">
	function makeRequest(url) {
		var httpRequest;
		// STEP 1: Create XMLHttpRequest object
		if (window.XMLHttpRequest) { // Mozilla, Safari, ...
			httpRequest = new XMLHttpRequest();
			// Some versions of FireFox do not work well if the response from the server does not contain an XML mime-type header
			httpRequest.overrideMimeType('text/xml');
		} else if (window.ActiveXObject) { // IE
			//try to get the most modern implementation
			var list = ["Microsoft.XmlHttp","MSXML2.XmlHttp","MSXML2.XmlHttp.3.0","MSXML2.XmlHttp.4.0","MSXML2.XmlHttp.5.0"];
			var ok = false;
			var i = 5;
			while (i>=0 && ok == false) {
				try {
					httpRequest = new ActiveXObject(list[i]);
					ok = true;
				} catch (e) {}
				i--;
			}
		}
		// Could not instantiate object so return false
		if (!httpRequest) {
			alert('Giving up:( Cannot create an XMLHTTP instance');
			return false;
		}
		// STEP 2: Create callback functions for asynchronous call
		// The HTTP request method: GET, POST, HEAD, etc (keep the words capitalized)
		httpRequest.open('GET', url, true);
		httpRequest.send(null);
		httpRequest.onreadystatechange = function () {
			// State: 0 – uninitialized, 1 – loading, 2 – loaded, 3 – interactive, 4 – complete
			if (httpRequest.readyState == 4) {
				if (httpRequest.status == 200 /*|| httpRequest.status == 0*/) {
					xml = httpRequest.responseXML;
					if (!xml || !xml.documentElement) {
						// IE doesn't always see the response correctly.
						// The following fixes the problem:
						if (window.ActiveXObject) {
							xml = new ActiveXObject("MSXML2.DOMDocument");
							xml.loadXML(httpRequest.responseText);
							// See next code snippet for details on this function
						
						}
					}
					//getImages(xml);
				} else
					alert ("Error loading page");
			}
		};
	}
</script>


IMPORTANT: JS does not allow users to acces local files (read/write) due to security issues (eg. viruses, trojans, etc.) so accessing a local file with an address other than starting with http:// is difficult. A solution would be to use the firefox's :

	try {
        	netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
	}
	catch(e) {
		alert("Error setting UniversalBrowserRead privileges");
		return;
	}

at the beginning of your AJAX function, but it does not always work.

NOTE: When you access local files be sure to add httpRequest.status = 0 besides 200 as there is no response status value from local files accessed without using a web server.

The XMLHttpRequest object doesn't just provide a way to register a callback for the handling of the readystate change (onreadystatechange). It also lets you define callbacks for:

  • progress notification - onprogress
  • page loading - onload
  • page error - onerror

Other useful functions are:

  • overrideMimeType() - to force the change of a document's MIME-TYPE
  • setRequestHeader() - sets the request HTTP header before sending it
  • getResponseHeader() - gets the header of the response sent by the server
  • responseText() - gets the response as plain text
  • responseXML() - gets the response as XML

Given the previous code for asynchronously reading an XML we can write the following code for pre-loading and XML containing images:

  • XML file:


<?xml version="1.0" encoding="iso-8859-1"?>
	<pictures>
		<image type="jpg">image1</image>
		<image type="jpg">image2</image>
		<image type="jpg">image2</image>
		<image type="jpg">image3</image>
	</pictures>


  • JS code:


<script type="text/javascript" language="javascript">
	// Global variable!
	var pics = new Array();

	function getImages(xml) {
		var imgs = xml.getElementsByTagName('image');
		for (var i=0; i<imgs.length; i++) {
			// Preload images in a global array
			pics[i] = new Image();
			pics[i].src = imgs[i].firstChild.nodeValue + '.' + imgs[i].getAttribute('type');
		}
		return pics;
	}
</script>


Links:

JSON

edit

JavaScript Object Notation (JSON) is a a text based lightweight computer data interchange format similar to XML and aimed at replacing it inside browsers.

JSON objects are represented as follows:


	var myJSON = {};


Data is expressed as a pair of name:value list separated by commas:


	var myJSON = {"name":"John"};


Arrays are expressed in the same way only that elements are placed inside square brackets:


	var myJSON = { "persons":[ {"name":"John", "age":"22", "occupation":"student"}, {"name":"Jim", "age":"26", "occupation":"programmer"} ] };


The XML for the previous JSON looks like the following:


	<persons>
		<person>
			<name>John</name>
			<age>22</age>
			<occupation>student</occupation>
		</person>
		<person>
			<name>Jim</name>
			<age>26</age>
			<occupation>programmer</occupation>
		</person>
	</persons>


Accessing JSON data is straightforward. Several methods exist:

  • direct access:


	var firstName = myJSON.persons[0].name;
	alert(firstName);


  • using the eval function:


	var obj = eval(myJSON);
	alert(obj.persons[0].name);


  • using the parse function:
	// Notice that myJSON is a String!
	var myJSON = '{ "persons":[ {"name":"John", "age":"22", "occupation":"student"}, {"name":"Jim", "age":"26", "occupation":"programmer"} ] }';
	var obj = JSON.parse(myJSON);
	alert(obj.persons[0].name);


NOTE: parse only works in last generation browsers i.e. Firefox 3.5 and IE 8.0. For older versions use one of the scripts found at http://json.org/. For a comparison amongst them see http://code.google.com/p/json-sans-eval/. However when using them be sure to pass a string as argument to the function.

IMPORTANT: using parse to handle JSON this method is the preferred one! eval should only be used to parse JSON if the source of the JSON-formatted text is completely trusted as it CAN execute ANY JS code and thus provides great security holes.

Executing JSON code received using AJAX is trivial as the following code shows. The onreadystatechange function described earlier remains the same and all we add is the parse function for executing JSON code:


	httpRequest.onreadystatechange = function () {
		if ( httpRequest.readyState == 4 ) {
			if ( httpRequest.status == 200 ) {
				obj = JSON.parse(httpRequest.responseText);
			} else
				alert ("Error loading page");
		}
	};


Links:

JSON vs XML

edit

The debate over whether to chose JSON instead of XML is similar to that of choosing between PNG and JPG images in which developers of image-display applications decide their applications will handle one or the other. So it really comes down to a matter of scope and choice.

  • JSON is basically XML but with brackets instead of tags
  • They are Turing equivalent
  • JSON is basically serialized JS, XML is not and will (never) be
  • JSON is built for representing data structures whereas XML is built for giving semantic meaning to the text within documents
  • Every protocol i.e. SOAP. HTTP-POST, REST could be marshalled in JSON for faster processing
  • JSON is possibly better suited for client side processing
  • XML files are usually bigger while JSON is smaller due to its data interchange orientation

Links:

Exercises

edit
  • Validate ALL the fields inside the forms created for Web technologies -- Laboratory 2 -- 2009-2010 -- info.uvt.ro using JS and DOM. For example validate numeric fields to be numeric and also to be in the correct range i.e. between 0 and 100 for example;
  • Create a simple HTML page which loads several imagines inside a table with no borders using JS and AJAX. The locations of the images will be read from a JSON/XML based input. Use DOM to create the table.