Programming

Basic AJAX: Using XMLHttpRequest

May3111May 31, 11

So, XMLHttpRequest is a feature in JavaScript that lets a page make HTTP requests to a web server on the same domain (note: there are ways to make requests to subdomains, they are not covered here).
First, you get an instance of it:
var xhr = new XMLHttpRequest();
You need some way to be notified when the HTTP request is done loading and the data is ready.
It's very similar to the listen() method in chat.botApi.
To listen for the end of the request, you create a function and assign it as the readyState Change Handler:
xhr.onreadystatechange = function() {
// your stuff here
};
You need to check that the request has ended, cause that function gets called 3 or 4 times depending on the browser, to indicate the various request states (sending, waiting, receiving, done - with done being readyState 4)
So, in your handler, check the readyState:
xhr.onreadystatechange = function() {
if (this.readyState===4) {
// huzzah, the data is here!
alert(xhr.responseText);
}
};
Once you have that, you open a connection to the server, with the request type (GET or POST, same as for a <form> action), the URL you want to reach, and Boolean true.
(the last param, true, means asynchronous, which allows the browser and page to do other stuff while the request is loading. It's important, and you should never use false for that value, if you do browser makers will come to your house and change it. And they won't tell you.)
So that part goes like this:
xhr.open("GET", "/path/to/file.html", true);
Finally, you need to submit the request to the server. That part is easy, it only takes one parameter - the POST variables (exactly like <input> fields in a <form>)
if you want to send an HTTP post to your server, for a form or whatever, you need to URL-encode all the parameters and send it as a string
if you're just making a GET request, leave it blank, like so:
xhr.send();
... and we're done!

Let me know if this helps you out, or if you would be interested in more articles covering JavaScript basics!


Smallest JSONp Implementation

Apr0611Apr 06, 11

Here's a tiny chunk of JavaScript I wrote while experimenting with writing an insanely small web chat client. I think this might be the worlds smallest JSONp implementation that doesn't suck.


/** Pico JSONp: */
function jsonp(u,cb){var a=jsonp._c=(jsonp._c||0)+1,b='picojsonp_'+a,c=document,d=c.body,s=c.createElement('script');window[b]=function()
{d.removeChild(s);cb.apply(cb,arguments);cb=c=d=s=null;};s.src=u.replace('{callback}',b);d.appendChild(s);}

/** Example usage: */
jsonp('http://example.com/timeline.json?callback={callback}', function(response) {
    console.log(response);
});

Style HR Horizontal Rule with CSS

May2710May 27, 10

Update: (May 27th, 2010) Corrected IE issue, removed outdated Opera and Safari workarounds.

It's a tricky subject, the <hr /> element. Like the <br /> element, it's syntactically odd and browsers have specific default styles for it that vary quite a bit. Since the goal is always to keep our HTML uncluttered, I thought I would explain how to work with this unruly piece of a document.

First, the HTML for this tutorial is always the following:
<hr />

 - That's how the HTML specifications say we are to indicate a horizontal line, so that's all we want to use in the content layer. Presentation, on the other hand, will be a little more messy and unusual. First, let's remember the major browser quirks associated with the HR element, many of them from this article:
Internet Explorer allows color to define the background color, and gives it precedence over background-color
The border property does not behave correctly in Opera
The height property is (by default) broken in Safari
With these rendering issues in mind, the goal is to make our HR elements look like they have been cut into the page - a common visual effect used most notably by Apple:


Not that we should do everything Apple does, but they can whip up a mean UI.

To avoid this going on forever, here are the two bug fixes that need to be used to get things working across the major browsers:

The workarounds below are no longer needed by Opera and Safari:
Fixing the height property in Safari:
This one is simple, but not intuitive. For whatever reason, the height property is limited to a minimum of 3px in Safari. The easiest way to get around this is to set the max-height property to whatever the height of your HR needs to be. In our case, we're only using borders to style the element, so the max-height should be 0.
height: 0;
max-height: 0;

Fixing Opera's borders:
It looks like Opera renders the border-top and border-bottom properties correctly. That's a bonus, because those are the only ones we need. You might have noticed, though, that Opera has the same problem as Safari when setting the height of a horizontal rule element. Thankfully, the fix is also the same.


Making Internet Explorer 6 Behave:
First, we're not using the color or background-color properties, so that eliminates those IE bugs. Second, I don't test on IE6 because that browser only accounts for about 2% of the visitors to most of my sites. But, everyone should at least be able to view the un-styled HTML properly. The beauty of using only a single HR element to show horizontal lines is that the degradation is already built into every browser.

However, it's always a good idea to predict when IE6 can be made to work with little extra effort. Typically, the problems people run into are with minimum heights due to the font-size property having precedence, and floats not breaking properly. To avoid these potential annoyances, I decided to include a few lines:

font-size: 1px;
line-height: 0;
overflow: visible;

The rest is the same as you would have used if styling an empty div element instead of an hr element:

display: block;
position: relative;
padding: 0;
margin: 8px auto;
width: 100%;
clear: both;
border: none;
border-top: 1px solid #AAA;
border-bottom: 1px solid #FFF;
font-size: 1px;
line-height: 0;
overflow: visible;

Now we've got a working horizontal rule, styled properly using only CSS. 
It looks like this:



And in Internet Explorer 5.5, we have the exact same style applied:

Beautiful, sleek, and it looks identical across all the browsers people use.


Serialize Objects in JavaScript

Aug2809Aug 28, 09

Author's note: This is a simplification, and it is not recommended for use in public projects. The de-facto JSON library is written by Douglas Crockford, and is available at json.org/json2.js.

I recently needed to store user preferences for a JavaScript application (on amoebaOS) in a file. Since JavaScript's support for XML is not amazing and XML in general is just an under-performing format for data storage (in my opinion), I opted for a JSON-encoded string as a means of storing the preferences. I know there are many libraries out there that might have this same functionality (JSON.stringify), I felt like it would be a chance to post my simplification of a JavaScript Object serialization method for the masses.

The goal was to have this code working perfectly without doing any intermediary testing, and that's what I did. The unserialize method is not elegant, but it's simpler than parsing manually and still safer than running a standard eval - you'll notice the dangerous global objects (or those that I could think of off the top of my head) are not available because the TinyJSON object declares internal variables that take precedence.

var TinyJSON = (function(){
	var window,top,self,parent,location,reload,back,forward,
		alert,confirm,prompt,stop,frames,document;
	
	function addslashes(t){
		return t.replace(/(*)'/gim,"$1$1'");
	}
	function strval(v) {
		switch((v.constructor.name+"").toLowerCase()) {
			case "number":
				return v+0;
			break;
			case "string":
				return "'" + addslashes(v).replace(/r?n/gim,'n') + "'";
			break;
			case "date":
				return "date("+v.getTime()+")";
			break;
			case "boolean":
				return v===true?"true":"false";
			break;
			case "array":
				var t = "[";
				for(var i=0; i<v.length; i++) {
					t += strval(v[i]) + ",";
				}
				return t.replace(/,$/,'')+"]";
			break;
			case "object":
				return branch(v);
			break;
			default:
				return "null";
			break;
		}
	}
	function branch(obj) {
		var t = "{";
		for(var n in obj) {
			t += """ + n + "":" + strval(obj[n]) + ",";
		}
		return t.replace(/,$/,'')+"}";
	}
	
	var self = {
		serialize : function(obj) {
			return branch(obj);
		},
		unserialize : function(str) {
			function date(s) {
				var d = new Date();
				d.setTime(s+0);
				return d;
			}
			return eval('(' + str + ')');
		}
	};
	
	return self;
})();

You can serialize a JavaScript Object to its string representation as follows:

var obj = {
	type : "myObj",
	data : [
		123456,
		new Date()
	],
	fun : true,
	going : 11,
	parent : {
		type : "parentObj"
	}
};
var str = TinyJSON.serialize( obj );

You can convert a TinyJSON string back to object form as follows:

var str = "{"type":'myObj',"data":[123456,date(1251442681016)], 
	"fun":true,"going":11,"parent":{"type":'parentObj'}}";
var obj = TinyJSON.unserialize( str );
JavaScript URL Encoding Mar2409Mar 24, 09
Image Rollovers Feb1109Feb 11, 09
Iframe Resizer Nov2008Nov 20, 08
Object Oriented JavaScript Oct2308Oct 23, 08
JavaScript Click Menu Jan0308Jan 03, 08