Detect device, browser and version using javascript

The best way to decide which functionality to use is feature detection. If the feature exists then that  functionality is allowed to run. Libraries such as Modernizr give you feature detection out of the box or you can write your own.

Full page site with vertical centering using css only

One of the big trends on the internet is the full page site. It consists of a single page site with multiple sections which you can scroll through. The trick of this is to have each section fill the screen and to centre the content inside.

Internationalisation & Localisation in AngularJS

Set up AngularJS projects to be translated using html template tags. This post looks at how you can use the Angular libraries plus a custom filter to ensure content is contextualised to the user.

Automated Testing using JavaScript


How to run automated tests and take screenshots using JavaScript libraries such as PhantomJS and DalekJS.

Create your own Google Plus embedded timeline

Google Plus doesn't have an easy to use embeddable timeline. Here we look at how to make your own!

Did Apple invent anything?

After reading my previous post about why Apple didn't invent the smartphone, I came across some more evidence of how blatant the Apple copying is in design and features across nearly every product they have created. Here I've attempted to compile those infringements into one place.

iPhone jailbreak & unlock yourself using free tools

There's a lot of false information out there about how to reset your iPhone and/or jailbreak unlock it. Many of the sites and guides tell you to pay money or go through other unusual steps which simple aren't needed.

Responsive youtube video player using css

One of the most frustrating things about video players is keeping the aspect ratio in responsive designs. Luckily there is a workaround using css which retains a ratio. you will need to give the player 100% height and width and add surrounding div container.

Useful Javascript Links

A collection of useful links I found this week.

How to structure your website files and folders

Looking at the different ways to structure your files and folders and the advantages/disadvantages between each method.

Improved cross browser responsive css grid layout

After creating an awesome percentage based layout, I implemented it on several sites and found it to speed up development and be the most important tool I use. However there where some issues with my previous implementation.

Using unicode font icons

Unicode fonts contain lots of characters and symbols which are web friendly and can be used in your pages.

The ultimate layout engine for backend and frontend

I have created a lot of sites over the years and the single biggest problem I have, an always face is the layout engine. The layout engine is the way a view is mapped with data and outputted onto the page.

Backend libraries and frameworks have a tough choice of choosing between:
- fixed templates, predefined and hardcoded, less flexible
- loose templates, built using reusable blocks, look messy and unexpected results

Frameworks such as Drupal and Wordpress go for the flexible solution. However users end up overriding them using fixed templates because of the way they are structured. They also suffer from being far too complicated to edit and update and confusing users into putting the files in the wrong places.

So how can we solve this? We need a solution that sits firmly in the middle of fixed and flexible. The key is to determine which elements should be fixed and which should be flexible.

The solution is to have a flexible layout grid (rows and columns) with fixed module templates (item html). This works well because you retain control of both but in separate places. This is the basis behind the ultimate layout engine which I've developed.

backend code
- list of pages with urls (if the url is all then it will be shown on all pages)
- list of view templates that appear on each page
- each view specifies where it appears on the page using a row and col number
- each view also species which model (data) table and corresponding model (data) row should be mapped to it

The layout table

url view row col model modelrow
all Head 1
1
all Logo 1 1 1 0
all Contact 1 2 1 0
all Navigation 2 2 1

Banner 3 2 2 1

TextSmall 4 2 2 1

Highlights 4 2 1
events BannerText 3 1 3 0
events Highlights 3 2 1
all Foot 1
1

the logic of this table:
- loop through each item
- if item url equals the current page url, or the item url equals 'all' then render the view using the model table and model row
- then add each render view into an array of rows and cols for the page
- If no row or col values exists then don't put them inside a row and col, put them as their own item in the array.

Here is an example of the view rendered with model data, then put into an array in the correct order based upon it's row and col numbers:

The layout array

var data = [
    {
        'type': 'Head'
        'data': '<div class="head">head html</div>'
    },
    {
        'type': 'row'
        'data': [
            {
                'type': 'col',
                'data': '<div class="banner">banner 1 html</div>'
            }
        ]
    },
    {
        'type': 'row'
        'data': [
            {
                'type': 'col',
                'data': '<div class="text">text 1 html</div>'
            },
            {
                'type': 'col',
                'data': '<div class="text">text 2 html</div>'
            },
            {
                'type': 'col',
                'data': '<div class="text">text 3 html</div>'
            }
        ]
    }
]

the logic for this next step is to:
- loop through each item in the layout array
- if the type is not row or col then output the data html
- if the type is a row then create a row html
- if the type is a col then create col html
- add the inner html inside the col and output to the page

And this is how our html will look after all of this:

<div class="head">head html</div>
<div class="row">
    <div class="col">
        <div class="banner">banner 1 html</div>
    </div>
</div>
<div class="row">
    <div class="col">
        <div class="text">text 1 html</div>
    </div>
    <div class="col">
        <div class="text">text 2 html</div>
    </div>
    <div class="col">
        <div class="text">text 3 html</div>
    </div>
</div>

If you want more control over the layout then you can add some more columns to the layout table which contain classes for each row and col.

The layout table with row and col classes

url view row col model modelrow rowclasses colclasses
all Head 1
1
row980
all Logo 1 1 1 0 row980
all Contact 1 2 1 0 fill1of3
all Navigation 2 2 1
row980

Banner 3 2 2 1 row980

TextSmall 4 2 2 1 row980

Highlights 4 2 1
fill1of3
events BannerText 3 1 3 0 row980
events Highlights 3 2 1
all Foot 1
1
row980

Very simple logic, which makes your views much easier to maintain as they don't contain layout containers:

<div class="text">{{ item.name }}</div>

Hope that helps you!

Client-side compression techniques

There are lots of different ways to compress data, here are a few examples of common algorithms:

Index Compression
Values are saved in a flat store with an index number referencing each value. The more values that are the same the better results you will get with this.


Shared Dictionary Compression
Similar to index compression but the dictionary file of values is stored externally from the compressed string, which greatly reduces the size, but requires the dictionary file to be downloaded and stored for compression and decompression.


Huffman Compression
Loops through every single character value and creates a probability of how often it is used, then it creates a tree of values which can be navigated by switching left or right in the tree.



LZ Compression
Using the zip algorithm which matches repeating patterns in your binary data. This gives even better better results than index compression but require more cpu and time.

Each compression technique has different advantages and disadvantages depending on your data type and processing power available. However the options are reduced when you need to run these algorithms in the browser.


I've created my own version of Index compression which supports strings, arrays and json:
http://jsfiddle.net/kmturley/MCzN7/13/



JavaScript performance tests of different methods and libraries:
http://jsperf.com/json-compression/5

From my tests the JSONH library is not only the fastest library to pack and unpack, but it created a fairly small size string and the library is not very large. So I would choose this over any other method for compression client side.

Here's a real world example of compressing data using JSONH, then storing it in LocalStorage for retrieval later on:


function set(key, value) {
    var item = JSONH.pack(value);
    localStorage.setItem(key, JSON.stringify(item));
    return item;
}

function get(key, value) {
    var item = JSON.parse(localStorage.getItem(key));
    return JSONH.unpack(item);
}


var packed = set('people', data);
var unpacked = get('people', packed);

And a real-world example showing 58% of the size after compression which takes around 0.26 of second:
http://jsfiddle.net/kmturley/8cMY5/5/


Css only carousel dynamic width

Carousels are common features in pages and apps we use every day. As frontend developers we need to build them efficiently and to work across a range of devices and browsers. if we can do it without Javascript then even better!

The main features of a carousel are:
- multiple items in a list
- list has hidden content which can be scrolled into view
- items are the width of the carousel view or are the width of their own content
- we can have links to show each item in the view
- the carousel should work cross device and browser
- touch or mouse operated

So lets start with some simple html:



<div class="carousel">
    <ul>
        <li>
            <img src="image.jpg" />
            <span>Text</span>
        </li>
        <li>
            <img src="image.jpg" />
            <span>Text</span>
        </li>
        <li>
            <img src="image.jpg" />
            <span>Text</span>
        </li>
    </ul>
</div>

and some css to make the items flow using their content size, so multiple items are seen at the same time:

.carousel {
    overflow: auto;
    padding: 10px;
}

.carousel ul {
    display: table;
    table-layout: fixed;
}

.carousel li {
    display: table-cell;
    vertical-align: top;
    padding: 0 10px 0 0;
}

or alternatively if you would like to size the carousel items to fit the view, so only one is visible at one time:

.carousel {
    overflow: auto;
    padding: 10px;
}

.carousel ul {
    white-space: nowrap;
}

.carousel li {
    width: 100%;
    display: inline-block;
    white-space: normal;
    vertical-align: top;
}

.carousel img {
    float: left;
}

.carousel span {
    clear: left;
    float: left;
}

This is a great solution that works down to IE8 and Firefox 3.6. If you would like to support IE7 you should float the items rather than using display inline-block.

Also we would like to add links to jump to certain slides within the content area. This is also achievable without JavaScript, we can use anchor tags. Here is an example of paging/item navigation html:

<div>
    <ul>
        <li><a href="#item1">Item 1</a></li>
        <li><a href="#item2">Item 2</a></li>
        <li><a href="#item3">Item 3</a></li>
    </ul>
</div>

and we also need to update our carousel html to have id's when the anchor tags point to:

<div class="carousel">
    <ul>
        <li id="item1">
            <img src="image.jpg" />
            <span>Text</span>
        </li>
        <li id="item2">
            <img src="image.jpg" />
            <span>Text</span>
        </li>
        <li id="item3">
            <img src="image.jpg" />
            <span>Text</span>
        </li>
    </ul>
</div>

Now when you click the nav items the browser will try to show the item in the scroll area, vertically and horizontally. This works really well except for when the content is already slightly in view. One way to improve the experience is to show the user which slide they have selected is to use the target class:

:target { outline: solid red }

You can see a full working example of it here:
http://jsfiddle.net/kmturley/6yp6Q/5/

Updated example with CSS3 animations:
http://jsfiddle.net/kmturley/fs6wge3f/1/

Simple php templating, keeping your views passive

For some projects you will need to render a page with data values, but not want to include an entire php templating library.

One of the methods you can use is to use php as a templating language itself:

<?php  $item = array('url' => 'projects', 'name' => 'Projects'); ?>
<li><a href="<?php echo $item['url']; ?>"><?php echo $item['name']; ?></a></li>

This is great and one of the most efficient way to render a page quickly. However the more you use this, you find your html and php becoming mixed together. The result is confusing to read, update and maintain.

The second problem with php templates is that you are encouraged to put logic in your views. This is bad because views should not know anything about the data they rely on. Views should be passive and your data should be mapped correctly to match it.

By implementing a template language you can separate your html template views from your php logic, your html templates can then be reused across any platform javascript, php, python etc

If you want a full templating solution I suggest looking at Twig for php. However this can also encourage you to put logic in your views. So for our example we will implement our own single line templating solution which will force you to render your view with the correct data!

Item.html
<li><a href="{{ item.url }}">{{ item.name }}</a></li>

View.php
$item = array('url' => 'projects', 'name' => 'Projects');
$url = 'Item.html';
echo preg_replace('/\{{ item.([^\{]{1,100}?)\}}/e', '$item[$1]', file_get_contents($url));

This uses RegEx to match all instances of {{ item. }} and replace them with the matching object data.

If we would like to use that for multiple pages we can create it into a reusable class:


Item.html
<li><a href="{{ item.url }}">{{ item.name }}</a></li>

View.php

class View {
public function render($model, $template) {
$html = '';
if (gettype($model) == 'array') { foreach ($model as $item) { $html .= $this->replace($item, $template); } }
else { $html .= $this->replace(array('data' => $model), $template); }
return $html;
}
    private function replace($item, $template) {
return preg_replace('/\{{ item.([^\{]{1,100}?)\}}/e', '$item[$1]', $template);
}
}

Load.php

class Loader {
private $templates = array();

public function load($name, $url) {
if (!$this->templates[$name]) { $this->templates[$name] = file_get_contents($url); }
return $this->templates[$name];
}
}


Main.php
$item = array('url' => 'projects', 'name' => 'Projects');


require('Loader.php');
require('View.php');


$loader = new Loader();
$template = $loader->load('Item', 'Item.html');

$view = new View();
$view->render($item, $loader->load($item, $template);

You can then extend these classes to render loops of templates or save modules and embed them inside other modules. I've created an example of nested module templates loading from csv configuration files at:
https://github.com/kmturley/php-simple-templates

Sharing Server side and Client side templates

Often when creating a module or gadget you will want to render something server-side, then as the module loads with JavaScript, update the html with the new data/logic.

This presents a few questions:

- will the data load once, or refresh?
- is the data already embedded in the page?
- could the data take time to load?
- will we know that before creating our module?

- if data is coming from a javascript ajax request, will the html be empty until it loads?
- should we show a loader icon while this is happening?
- what if the server wants to render the module with some data and not load a feed?
- do we need a server-side template and then a javascript template

So many questions that prevent us from completing our module, and potentially could also force us to make changes to it later down the line as the functionality changes. I've come across this problem many times and come to a great solution.

Sharing server-side and client-side templates
Your html template should be the same for both server-side and client-side which means you need to pick the same library for both or implement the same custom template code. For this example i'm going to be using:

- Jinja for python,
- Twig for php
- Twig.js for JavaScript

A normal html file with div for javascript to attach to, javascript template and data would look something like this:

Main.html

<div id="list1" class="list"></div>


<script id="tmpl" type="text/template">
    <ul>
        {% for item in items %}
            <li><a href="{{ item.url }}">{{ item.name }}</a></li>
        {% endfor %}
    </ul>
</script>

<script>
    var list1 = new List('list1', [{'name': 'Item 1', 'url': 'http://www.google.co.uk'}]);
</script>


This is bad because html is combined with javascript script tags. The key is to separate the two cleanly.

Main.html
<div id="list1" class="list">
    {% include 'html/modules/Item.html' %}
</div>
<script id="tmpl" type="text/template">
    {% include 'html/modules/Item.html' %}
</script>


<script>
    var list1 = new List('list1', [{'name': 'Item 1', 'url': 'http://www.google.co.uk'}]);
</script>



List.html

  <ul>
  {% for item in items %}
    <li><a href="{{ item.url }}">{{ item.name }}</a></li>
  {% endfor %}
  </ul>

Now you can keep three files for each module which makes developing really easy:
List.html
List.css
List.js

Automated modules
Patterns start to emerge from writing our code this way, which allows us to automate processes. Lets output the modules dynamically:

Main.html

{%
    set modules = [
        { 'name': 'List', 'id': 'list1', 'data': [{'name': 'Item 1', 'url': 'http://www.google.co.uk'}] },
        { 'name': 'List', 'id': 'list2', 'data': [{'name': 'List 1', 'url': 'http://www.google.com'}] }
    ]
%}

{% for item in modules -%}

    <div id="{{ item.id }}" class="list">
        {% include 'html/modules/'~item.name~'.html' %}
    </div>
    <script id="tmpl" type="text/template">
        {% include 'html/modules/'~item.name~'.html' %}
    </script>


    <script>
        var {{ item.id }} = new {{ item.name }}('{{ item.id }}', {{ item.data }});
    </script>
{% endfor -%}

By outputting automatically you can keep all of your modules consistent while developing and ensure the all conform to the same structure.

An added benefit is that your backend developer can use you object to create the model for the CMS. He has all of the fields that the view requires to be rendered.

Saves a world of pain too when the data needs to be updated via ajax instead of server side.




Javascript modules with custom events

At some point when writing javascript modules you will want to start passing data between the modules.

1) One method is to hard wire the names of the callbacks but this creates dependancies and is obviously terrible e.g.

function load(data) {
    // do something here
    example.complete(data);
}

2) The second method is to pass through your callback through the chain until it's required e.g.


function load(data, callback) {
    // do something here
    callback(data);
}
function complete(items) {
    console.log('complete', items);
}

load({example:'test'}, complete);

However this is a one to one relationship, e.g. one callback to one function call. So if you want to pass the data through to multiple parts of your application then you would need a parent function which links them all together.

3) The ideal solution is to have a publish/subscribe pattern which allows you to subscribe to an event and receive updates whenever it's called. This can push updated to any number of callbacks and can be added and removed dynamically  giving you full control over your modules and events.

Here's a module that does exactly that, by saving every callback in an object using the event name as a key:


define('Events', {
    events: {},
    addEvent: function(name, callback) {
        if (!this.events[name]) { this.events[name] = []; }
        this.events[name].push(callback);
    },
    removeEvent: function(name, callback) {
        if (this.events[name]) {
            if (callback) {
                for (var i=0; i<this.events[name].length; ++i) {
                    if (this.events[name][i] === callback) { this.events[name].splice(i, 1); return true; }
                }
            }
            else { delete this.events[name]; }
        }
    },
    dispatchEvent: function(name, data) {
        if (this.events[name]) {
            for (var i=0; i<this.events[name].length; ++i) {
                this.events[name][i]({ data: data, target: this, type: name});
            }
        }
    }
});


If every module you create contains these functions you can chain any module to another using the following pattern. e.g.


define('Example', {
    extend: 'Events',
    init: function() {
        this.items = {item: 'testdata'};
    },
    load: function() {
        this.dispatchEvent('complete', this.items);
    }
});



var example = new Example('example1', {param: 'options'});
example.addEvent('complete', function(e) {
    console.log('oncomplete removed', e);
});

example.removeEvent('complete');

example.addEvent('complete', function(e) {
    console.log('oncomplete added again', e);
});
example.load();

Easy to use event creation, deletion and dispatching in 24 lines of code. Here's a working full example using my base module class:
https://github.com/kmturley/js-modules

Object Oriented Css - Simplified

Object oriented coding can sometimes be hard to understand. When working with other people I usually use this metaphor to explain oocss.

We want to create a list of books, that sit on a shelf within a library. As html it would look something like this:



<ul>
    <li>Book 1</li>
    <li>Book 2</li>
    <li>Book 3</li>
</ul>

The wrong way
The common (but very wrong) way is to apply specific class names to each level, combining structural and visual styles together under a single class e.g.

.library {
    margin: 0px auto 0 auto;
    width: 980px;
    background-color: #ffcc00;
}

.shelf {
    padding: 20px;
    background-color: #333333;
}

.book {
    display: inline-block;
    width: 100px;
    margin: 0px 10px 0px 0px;
    background-color: #ccff00;
}

The object oriented way
Separate structure/layout from style/theme. So in our example that would be:

Layout/Structure:
1) library - the bricks and mortar of the building
2) shelves - the shelves attached with hinges to the brick, x amount
3) book - the items containers with content inside them, x amount

Style/Theme:
1) library - The decoration on the walls, how it looks and is painted
2) shelves - the wood effect, shadows borders, spacing
3) books - whether the books are big blue hardbacks, or small red paperbacks

Layout

We can identify the common structural elements and give them their own name-spaced class:

.layout .row {
    max-width: 980px;
    margin: 0 auto 10px auto;
    overflow: auto;
}

.layout .row .row {
    margin: 0 -10px;
}

.layout .col {
    float: left;
    padding: 0 10px;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

So how would our html look with the structural css class names?

<div class="layout">
    <ul class="row">
        <li class="col">Book 1</li>
        <li class="col">Book 2</li>
        <li class="col">Book 3</li>
    </ul>
</div>

Theme

Then identify the common visual/styling elements and give them their own name-space class:

.light {
    color: #333333;
    background-color: #ffffff;
}

.light .c1 {
    color: #333333;
}

.light .c2 {
    color: #2989D8;
}

.light .bg1 {
    background-color: #ffffff;
}

.light .bg2 {
    background-color: #eeeeee;
}

Now how would our html look with these style/theme classes?

<div class="layout">
    <ul class="row light">
        <li class="col c1 bg1">Book 1</li>
        <li class="col c1 bg1">Book 2</li>
        <li class="col c1 bg1">Book 3</li>
    </ul>
</div>

Now we can reuse our classes and even move the theme around to theme just a single row if we want or even add a second theme for that row of items:

<div class="layout">
    <ul class="row light">
        <li class="col c1 bg1">Book 1</li>
        <li class="col c2 bg1">Book 2</li>
        <li class="col c1 bg2">Book 3</li>
    </ul>
    <ul class="row dark">
        <li class="col c1 bg1">Book 1</li>
        <li class="col c2 bg1">Book 2</li>
        <li class="col c1 bg2">Book 3</li>
    </ul>
</div>

.dark {
    color: #ffffff;
    background-color: #111111;
}

.dark .c1 {
    color: #ffffff;
}

.dark .c2 {
    color: #2989D8;
}

.dark .bg1 {
    background-color: #111111;
}

.dark .bg1 {
    background-color: #333333;
}

To see a real-world example check out my simple responsive template on github:
https://github.com/kmturley/alley


Cross domain, cross browser ajax with jsonp

Previously I looked at ways to send ajax GET requests cross domain using CORS. This is a great solution and works well across the browsers normally supported IE8+. This requires the server to have allow access from all origins though and is not supported by older browsers.

JSONP is a variation of json which stands for json with padding. It is a method which allows you to wrap any json data with a function callback on the server feed. This means that when it is loaded your function is called and the json is passed back as a parameter.

Here is an example of a feed of JSON
https://gdata.youtube.com/feeds/api/videos?q=dogs&v=2&alt=jsonc&max-results=5

The first line looks something like this:


{apiVersion: "2.1"...



However if we pass through a callback parameter we get can see the server also supports JSONP
https://gdata.youtube.com/feeds/api/videos?q=dogs&v=2&alt=jsonc&max-results=5&callback=functionname

Now the first line of the data returned shows:
functionname({"apiVersion":"2.1"

This means a function called functionname() {} will be called on our page with the data passed back to us.

So how do we make this usable when sending ajax requests? We can let the browser do the request for us using the script tag. First we need to generate a new function name automatically from the browser timestamp


var timestamp = 'callback'+new Date().getTime();

Then we create the function dynamically from the function name:

window[timestamp] = function(e) { console.log(e); };

Now we just need to append the url to a script tag in the page dynamically:

var script = document.createElement('script');
script.src = url+'&callback='+timestamp;
document.getElementsByTagName('head')[0].appendChild(script);

After the script tag has loaded, your function will be called and the data returned!

Lets put that into a reusable function we can call multiple times:

function ajax(url, callback) {
    var timestamp = 'callback'+new Date().getTime();
    window[timestamp] = function(e) { callback(e); };
    var script = document.createElement('script');
    script.src = url+'&callback=window.'+timestamp;
    document.getElementsByTagName('head')[0].appendChild(script);
}

usage would look like this:

ajax('https://gdata.youtube.com/feeds/api/videos?q=dogs&v=2&alt=jsonc&max-results=5', function(e) {
    console.log(e);
}

Here is an example of my full ajax function supporting CORS and JSONP

function ajax(url, callback, filetype, type) {
        filetype = filetype ? filetype : 'json';
        type = type ? type : 'GET';
        var success = function(e) {
            var items = '';
            switch(filetype) {
                case 'csv': items = csv(e); break;
                case 'json': items = JSON.parse(e); break;
                default: items = e; break;
            }
            callback(items);
        }
        var error = function(e) {
            console.log('Please enabled CORS using access-control-allow-origin');
        }
        if (filetype == 'jsonp') {
            var timestamp = 'callback'+new Date().getTime();
            window[timestamp] = function(e) { success(e); };
            var script = document.createElement('script');
            script.src = url+'&callback='+timestamp;
            document.getElementsByTagName('head')[0].appendChild(script);
        }
        else {
            var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
            if (window.XDomainRequest && !sameOrigin(url)) { xhr = new XDomainRequest(); xhr.onload = function(){ success(xhr.responseText); }; }
            if (filetype == 'image' && xhr.overrideMimeType) { xhr.overrideMimeType('text/plain; charset=x-user-defined'); }
            xhr.onerror = error;
            xhr.onreadystatechange = function(e) { if (xhr.readyState == 4 && xhr.status == 200) { success(xhr.responseText); } }
            try {
                if ('withCredentials' in xhr) { xhr.open(type, url, true); }
                else { xhr.open(type, url); }
                xhr.send(null);
            }
            catch(e) { error(e); }
        }
}


function sameOrigin(url) {
        var split = url.split('/');
        if (split[0]+'//' == window.location.protocol+'//') { return split[2] != window.location.host ? false : true; }
        else { return true; }
}

And here is a link to my Utils module where I store my ajax and other helper functions:
http://www.kimturley.co.uk/js/modules/Utils.js




Cross browser cross domain ajax requests

When programming JavaScript you will eventually hit several cross browser inconsistencies. One of the most frustrating is the ajax request. This allows you to send and load data from other files or urls. A quick search will show that the modern browsers support a simple syntax:


var xhr = new XMLHttpRequest();
xhr.addEventListener('load', function(e) {
  console.log(e.target.responseText);
})
xhr.open('GET', 'http://echo.jsontest.com/key/value/one/two');
xhr.send();

This works in Chrome, Safari and other modern browsers. But what happens when we need to older browsers such as Internet Explorer and Firefox 3.6? Well a simple search returns almost every answer as "use jQuery".

The reason behind this is that there are many inconsistencies between browsers and whether requests are cross domain, when the server requires credentials and pre-flighted request that it becomes a nightmare to support.


What happens if we don't want to include a 30KB library just for ajax requests? Well it is fairly simple to support cross browser ajax requests if you know how.

The first step is to check if the browser is IE then use an ActiveXObject to support local requests (This can be used for cross domain requests but it is limited by browser security restrictions, so may not be ideal for some users e.g. inside company internal network). I've also defined success and error functions which we will reference later in several places.



var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
var success = function(e) { console.log(e); }
var error = function(e) { console.log(e); }
if (window.XDomainRequest && !this.sameOrigin(url)) { xhr = new XDomainRequest(); xhr.onload = success; }



Now we need to reference those complete and error functions which will be fired based on whether onload or on readystatechange functions are available. If the request is crossdomain use XDomainRequest for IE only.


if (window.XDomainRequest && !sameOrigin(url)) { xhr = new XDomainRequest(); xhr.onload = success; }
xhr.onerror = error;
xhr.onreadystatechange = function(e) { if (xhr.readyState == 4 && xhr.status == 200) { success(e); } }


If you would like to load images then you will need to override the mimetype to grab the data

if (file == 'image' && xhr.overrideMimeType) { xhr.overrideMimeType('text/plain; charset=x-user-defined'); }

Also if the request needs credentials then you need to send the value true through, we will surround this with a try catch block as IE throws an access denied error for request without CORS enabled. If you get the error message you need to ensure the feed header has 'access-control-allow-origin: *'


try {
    if ('withCredentials' in xhr) { xhr.open(type, url, true); }
    else { xhr.open(type, url); }
    xhr.send(null);
}
catch(e) { error(e); }


There you have a working cross browser ajax request. Great, but not exactly a good idea to duplicate this into every part for our app. Lets convert this into a reusable function which I store in my Utils module.

function ajax(url, callback, filetype, type) {


    filetype = filetype ? filetype : 'json';
    type = type ? type : 'GET';
    var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
    var success = function(e) {
        var items = '';
        switch(filetype) {
            case 'csv': items = csv(xhr.responseText); break;
            case 'json': items = JSON.parse(xhr.responseText); break;
            default: items = xhr.responseText; break;
        }
        callback(items);
    }
    var error = function(e) {
        console.log('Please enabled CORS using  access-control-allow-origin');
    }
    if (window.XDomainRequest && !sameOrigin(url)) { xhr = new XDomainRequest(); xhr.onload = success; }
    if (filetype == 'image' && xhr.overrideMimeType) { xhr.overrideMimeType('text/plain; charset=x-user-defined'); }
    xhr.onerror = error;
    xhr.onreadystatechange = function(e) { if (xhr.readyState == 4 && xhr.status == 200) { success(e); } }
    try {
        if ('withCredentials' in xhr) { xhr.open(type, url, true); }
        else { xhr.open(type, url); }
        xhr.send(null);
    }
    catch(e) { error(e); }


}

The check for sameDomain matches the url against the current window location url:

function sameOrigin(url){
    var split = url.split('/');
    if (split[0]+'//' == window.location.protocol+'//') { return split[2] != window.location.host ? false : true; }
    else { return true; }
}


And to use it you would write:

ajax('http://echo.jsontest.com/key/value/one/two', function(e) {
    console.log(e);
});

I'm using this technique combined with a csv to json convertor script to load data into my site. My csv to json function:

function csv(string, divider) {
    divider = divider || ',';
    var regex = new RegExp(("(\\"+divider+"|\\r?\\n|\\r|^)"+"(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +"([^\"\\"+divider+"\\r\\n]*))"), 'gi');
    var regex2 = new RegExp("\"\"", 'g');
    var items = [];
    var fields = [];
    var matches = null;
    while (matches = regex.exec(string)) {
        var match = matches[1];
        var value = '';
        if (match.length && match != divider) { items.push({}); }
        if (matches[2]) { value = matches[2].replace(regex2, '\"'); }
        else { value = matches[3]; }
        if (items.length == 0) { fields.push(value); }
        else {
            var index = Utils.size(items[items.length-1]);
            var name = fields[index];
            items[items.length-1][name] = value;
        }
    }
    return items;
}

If you want to test it working you can try these test feeds:


// cross domain json feed without CORS
var url = 'http://www.kimturley.co.uk/data/projects.json';

// cross domain json feed with CORS
var url = 'http://pipes.yahooapis.com/pipes/pipe.run?_id=giWz8Vc33BG6rQEQo_NLYQ&_render=json';

// same domain json feed
var url = '/echo/json/';

// google docs example
var url = 'https://docs.google.com/spreadsheet/pub?key=0AsnymCBa0S5PdGh4ZVF5Uktfc2hyYm5ibHduTHAzQ1E&output=csv';

Here is a working example with all of the code:
http://jsfiddle.net/kmturley/4RCBg/

Hope that helps some of you guys