My Blog

contains PHP and other web related content. (Sometimes there are some off topic things - don't freak out!)

Archive for the ‘javascript’ Category

How to handle AJAX errors with jQuery

Tuesday, August 24th, 2010

Many times, the ‘error’ property of the jQuery AJAX call is ignored. Most often, you’ll see just references to the success portion.

The error attribute of the $.ajax() is a callback – and receives three parameters. These are the XMLHttpRequest with the error, a type of error, and an error object, if one is thrown. For the most part, the first two are the only parts.

Now, the error attribute should be used for actual errors, not logical errors. For example, if you are making an AJAX call to log in the current user, and the user does not exist, this should return a success type message instead of some sort of error. Errors are things like 404′s for the AJAX call, or other HTTP issues. In fact, there are 4 types of errors that will be returned: Error – which is an HTTP error, parseerror – which is an xml/json parsing issue, timeout – which is a script that didn’t respond fast enough, and not modified.

I wrote a generic function to handle the errors. This could be name spaced I suppose or added to your standard library. In this case, it just alerts the error. (On some other sites, I generate a new modal box.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function ajaxError(request, type, errorThrown)
{
	var message = "There was an error with the AJAX request.\n";
	switch (type) {
		case 'timeout':
			message += "The request timed out.";
			break;
		case 'notmodified':
			message += "The request was not modified but was not retrieved from the cache.";
			break;
		case 'parseerror':
			message += "XML/Json format is bad.";
			break;
		default:
			message += "HTTP Error (" + request.status + " " + request.statusText + ").";
	}
	message += "\n";
	alert(message);
}

In this function, an error message is generated based on the error type. The only error that gets extra information is the default type – which is ‘error’. It then retrieves the HTTP Status code and the Status Text.

Here is an example of this in use:
ajax.php

1
2
<?php
header('HTTP/1.1 503 Service Unavailable');

And, here is the test page. When the user clicks the xx link, it will generate a request to ajax.php. This will generate a 503 error and the error handler will take over.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<html>
	<head>
	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
	</head>
	<body>
		<a href="#" id="test">xx</a>
		<script type="text/javascript">
			$(function(){
				$("#test").click(function(){
					$.ajax({
						url: "ajax.php",
						success: function(){
							alert('retrieved');
						},
						error: ajaxError
					});
 
					return false;
				});
			});
		</script>
	</body>
</html>

Using Google Charts to make QR Codes

Tuesday, July 13th, 2010

QR Code for this page

QR Code for this page

Google Charts is my hero yet again. This time, I happened to notice that they have a chart in their API for QR Codes. Considering I was just searching google for a PHP class to do this, I was pretty ecstatic.

To implement, I made a quick line of jQuery to generate my QR Codes. Of course, I did this after the page loaded :) My goal was to generate a QR code for the page that the user is currently viewing. Pretty simple:

1
$("#qrImage").attr('src', 'http://chart.apis.google.com/chart?chs=150x150&cht=qr&chl=' + escape(window.location.href) + '&choe=UTF-8');

You can find all of the details and other parameters here: http://code.google.com/apis/chart/docs/gallery/qr_codes.html

Twitter @anywhere proof of concepts

Thursday, May 13th, 2010

First off, let me just remind you to not be an idiot like I was. I simply found the documentation here and here and went to town. After hours of trying to figure out exactly what was going on, I stumbled across some very interesting comments in the news group: The @anywhere api is not in chirp_preview anymore – but its not done either. So some of the stuff won’t work – and that wasn’t my fault! Dang! However, I was able to create a few proof of concept things. I’m going to cover connecting to your application (which you should be familiar with anyway), showing the connection/authentication system, and retrieving information about other users via your authenticated account.

First, set up the HTML

The following is the snippet of HTML I used for my demonstration.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html>
	<head>
		<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
		<script src="http://platform.twitter.com/anywhere.js?id=YOUR_API_KEY&v=1" type="text/javascript"></script>
	</head>
	<body>
		<p>This should give some pretty cool features of the Twitter AT-anywhere API.</p>
		<hr />
		<div id="connect"></div>
		<div id="disconnect"></div>
		<div id="connectedUser"></div>
		<div id="connectedFunctions">
			<p>The following stuff can only be done if you're connected.</p>
			<label>Search this user: <input id="searchUser" /></label><button id="doSearch">Search this user</button>
		</div>
	</body>
</html>

This is pretty simple, create a document, load jquery and load the twitter api using your api key, and then create some placeholder boxes. Let’s check out the first set of javascript.

The Javascript for Authentication and User Information

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
			twttr.anywhere.config({
				assetHost: "twitter-anywhere.s3.amazonaws.com"
			});
 
			twttr.anywhere(function(T) {
				T("#connect").connectButton({
					authComplete: function() {
						$("#connect").hide();
						$("#disconnect").html('<a href="#" id="signoutlink"">Sign Out</a>');
 
						showUserInfo(T);
					},
					signOut: function() {
						$("#connect").show();
					}
				});
 
				if (T.isConnected()) {
					$("#connect").hide();
					$("#disconnect").html('<a href="#" id="signoutlink">Sign Out</a>');
					showUserInfo(T);
				}
			});

To access the twitter @anywhere functionality, there is a global object called twttr. Then, call the anywhere method and passing in a variable – in this case T. T refers to the current instance of the @anywhere object.

The first block is finding the div with the id of ‘connect’. This will make this a connect button. The connect button has two actions bound to it. The first is authComplete() which will be called once the user authorizes this application. The second is signOut() which is executed if someone clicks the button after they’ve connected. In my example, I’m going to not use this functionality. I did leave it in there, however, for demonstration.

The authComplete() method then hides the connect button. We’re already connected so we don’t need to show this box. It’s important to know that this box actually transforms into a ‘you are connected’ icon – and allows for disconnect. In my example, I thought this might be confusing for the user, so I remove the box entirely. Instead, I populate the disconnect box with a signout link. This has an ID that we’ll reference later. Finally, the showUserInfo() function is called. It receives a parameter of the current instance.

All that functionality only happens when the user uses the connect button. The page can still be refreshed or visited at a different time. This is where the next snippet comes in. When this call continues, it verifies if the user is connected with T.isConnected(). If so, it basically does the same stuff as the authComplete() method of the connectButton() call. (Yah, I should have put this in a different method..)

Next, lets look at the other code bits that we reference in this snippet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
				$("#signoutlink").live("click", function () {
					twitterSignout();
			    });
 
				function twitterSignout()
				{
					twttr.anywhere.signOut();
					$("#disconnect").hide();
                                         $("#connect").show();
					$("#connectedUser").html('');
				}
 
				function showUserInfo(T)
				{
					currentUser = T.currentUser;
				    screenName = currentUser.data('screen_name');
				    profileImage = currentUser.data('profile_image_url');
				    profileImageTag = "<img src='" + profileImage + "'/>";
				    $('#connectedUser').append("Logged in as " + profileImageTag + " @" + screenName);
				    T.hovercards();
				}

First, the link with the id of ‘signoutlink’ is now bound with jquery to the method twitterSignout(). Whenever the previous bit of javascript creates this link, and it gets clicked, the twitterSignout() method will be called. twitterSignout() simply calls the @anywhere signOut() method, hides the disconnect link, shows the connect button, and clears the information about the previously logged in user.

The showUserInfo() method’s content is a copy from the JS API documentation. All it does is access the currentUser of the T (twitter @anywhere instance) and retrieve that data. It then populates it into the div with the ID ‘connectedUser’. One thing I do extra is call the hovercards() method. hovercards() parses the document and highlights every twitter handle and creates a hover-card or popup. I thought this would be a nice edition for the user information.

The Javascript for Interacting with Other Users

The HTML still has an input box and button I need to add javascript for. For the proof of concept, all we’re going to do is search the user by their username and alert a few bits of information about them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
				$("#doSearch").click(function(){
					var username = $("#searchUser").val();
					if (!username) {
						alert('you must specify a user');
						return false;
					}
 
					twttr.anywhere(function(T) {
						if (!T.isConnected()) {
							alert('you can only use this if you are connected');
							return false;
						}
						T.User.find(username, function(user) {
							alert("user has " + user.attributes.friends_count + " friends");
							alert("user is following " + user.attributes.followers_count + " tweeple");
							alert("you are following them? " + user.attributes.following);
							alert(user.attributes.name + " last said: " + user.attributes.status.text);
						});
					});
				});

Once the button with the id ‘doSearch’ is clicked, the value of the input with the ID of ‘searchUser’ is evaluated. If empty, it tells the user to actually do something – or search someone! duh! Then, the twitter @anywhere instance is executed again. The first step is to make sure that the current visitor really is an authenticated user. If not, tell them they need to be. You’ve seen this code before in the upper snippet.

Next, the User.find() method is executed on the content of that username. The twitter user object is passed into the callback. The call back tells how many friends and followers the searched user has, whether the current user is following the searched user, and what that person’s last status was (it uses their name to start out the sentence.).

Ending Thoughts

I’m looking forward to what Twitter comes up with. So far, I’m super impatient. I was ready to make my full fledged application today – but was stuck by lack of documentation and lack of features. However, I’m sure when it’s done, it will be great. I’ll post something when it’s finished with a more indepth tutorial.

Use your own short domain while waiting for BitLy Pro

Tuesday, May 11th, 2010

If you’ve checked out BitLy Pro, you’re probably pretty excited like I am. I saw it and immediately registered saray.me for a short URL. When I went to sign up, I found it was still in a queue system where you had to wait to get an invite. In the mean time, I still want to start using my domain.

After reading some of the documentation, I found that once you sign up for a bit.ly pro account, your existing bit.ly links that were created when you were logged in will be accessible via your short URL. With this in mind, I decided to just continue to create my bit.ly links but redirect my domain to bit.ly for the time being.

Log In to Bit.Ly

Goto bit.ly and login. (or create an account if you want). This is necessary so that you can now create and track your links.

Modify your domain

I’m using GoDaddy. I decided to forward my domain.

First, select your domain in the domain manager. Then, choose the forward domain option at the top of the list.

On the popup, choose the advanced option link. Make sure to choose temporarily forward the domain. This is needed because at some point, we’ll be redirecting this domain’s nameservers to bit.ly again to natively do this URL forwarding. Enter “http://bit.ly” in the box and click ok.

Try it out

Now, goto bit.ly and shorten an URL. I’m shortening http://aaronsaray.com/blog. This is now: http://bit.ly/cZqq0e. When I enter http://saray.me/cZqq0e into the browser, it serves the short URL from bit.ly.

Yay!

Timesaving Feature

Since I do continue to get my bit.ly links with http://bit.ly instead of http://saray.me in the beginning, I decided to make a Firefox bookmarklet to replace this for me. It’s pretty simple. All it does is take bit.ly and replace with saray.me.

1
var x=prompt('Bit.ly URL');alert(x.replace('bit.ly','saray.me'));

Here, you can drag this to your toolbar if you want :)
Saray.Me the Bit.Ly

Branding your Tweets using @anywhere tweetbox

Tuesday, May 4th, 2010

With Twitter’s new @anywhere features, it’s now possible to brand your tweets from your own web page. While I still like using Tweetdeck or Seesmic for my actual interaction on twitter, I have started tweeting a bit from my own web page as well.

@anywhere features an interactive tweetbox that you can embed on your website. The javascript call allows you to add your own content to the box – just waiting for the user to hit TWEET. (Of course, they have to connect to your website.) In order to leverage this for my own website, and brand my tweets from AaronSaray.com, I decided that I could use this box in my browser sidebar. Here are the steps – in case you want to do it yourself!

Get Your “App” an API Key

This is pretty simple. First, log into the web interface for twitter. Then, visit the apps page at http://twitter.com/apps. Click on register a new application if you need to.

On this page, you can enter all the details of your application. For the application name, I entered AaronSaray.com to provide proper branding. Last, make sure that you check Read/Write access. Your application needs to be able to post!

After this is complete, you may want to view your page’s settings. (You can do this by clicking on the name of the application on the apps page.) The important thing to do here is to access the ‘Consumer Key’ and copy this down.

Create your webpage

Next, I created a web page on my domain. It has the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
    <head>
        <title>Twitter</title>
        <style type="text/css">
            body {
                background-color: #f3f3f3;
            }
        </style>
        <script src="http://platform.twitter.com/anywhere.js?id=CONSUMER_KEY&v=1" type="text/javascript"></script>
    </head>
    <body>
        <div id="custom-tweetbox"></div>
        <script type="text/javascript">
        twttr.anywhere(onAnywhereLoad);
        function onAnywhereLoad(twitter) {
            twitter("#custom-tweetbox").tweetBox({
                label: "<span style='color: #aaa'>Tweet this:</span>",
                height: 90,
                width: 200
            });
        };
    </script>
    </body>
</html>

First off, make sure to change CONSUMER_KEY to the actual key from your applications settings page. Next, you can change the CSS in this page to match your theme if you want. Since I’m loading this in the side bar, this is the simple layout I chose.

Finally, include the javascript and configure the tweetbox. I chose not to prepopulate my tweetbox with content. However, you could if you wish…

Add Book Mark

Add the bookmark to your browser. I added mine to my firefox bookmark toolbar. Then, I right clicked and chose properties. I checked the ‘load this in the sidebar’ option.

Use It!

The first time you use the tweet box, it will prompt you to connect to your website. After this is done, you can use this easily. My branded tweets show that its from AaronSaray.com nicely. See?

Fixing c:\fakepath in filestyle jquery plugin

Friday, March 26th, 2010

The other day I ran across an issue with the FileStyle jquery plugin. Whenever a new file was chosen, windows and Internet Explorer would put c:\fakepath\ before the filename. Turns out its not FileStyle’s issue – but a security feature of Internet Explorer.

As a quick fix, however, I made the following changes to FileStyle:

BEFORE

1
2
3
4
5
6
//snip
            $(self).bind("change", function() {
                filename.val($(self).val());
            });
 
//snip

AFTER

1
2
3
4
            $(self).bind("change", function() {
            	var s = $(self).val().replace(/(c:\\)*fakepath/i, '');
                filename.val(s);
            });

Javascript and CSS Compression and Cache

Thursday, February 25th, 2010

I’ve been researching caching and compression techniques for my external resources for some time. My first design of JEMDiary was very greedy with HTTP connections. Couple that with having a less-than-perfect host (Dreamhost bleh…), users could feel the burn. I didn’t like it because it would even take ME forever to use my own website. I went on to discover many different key points I use when creating sites now – the Steps to Optimize Assets.

Steps to Optimize Assets

There are a few steps I live by when I design my websites now.

  • Use a subdomain for images, js and css. While I don’t go overkill with this (see: not 5 page brochure website), I do try to separate assets over multiple subdomains. The important thing is not to have too many – but none what so ever limit your user from loading your site as quick as possible. I generally use one for my assets and one for user submitted assets.
  • Use sprites. Whenever possible, reduce the amount of HTTP requests by combining images. It is faster to load an image that is 3x the size of the one you’re displaying than to open 2 more HTTP connections after you download the first image.
  • Cache non changing elements as long as possible. One of the biggest things I noticed on my dreamhost server was the misconfiguration of e-tags. After disabling them, I went and looked further into caching techniques. I found that most of my assets didn’t change – so I cached them up to a year.
  • Compress away white space. After you edit the source of your css, it doesn’t need to be pretty. In fact, things like comments and white space in css and javascript are just wasted bytes… bytes you could remove… but bytes you shouldn’t remove from your source. I deal with this by making a compressed copy on build.

These are my main rules. This article, however, is going to focus on how I deal with Javascript and CSS.

Disclaimer: The methods I’m going to describe here can be labor intensive. When you build your own system, you should strive to make some of these automated.

Preparing CSS for deployment

The first thing I do is create that subdomain. For my site example.com, users can visit http://example.com for the content. I create a subdomain called assets.example.com which is where I expect to get my content from. I generally create a server alias in the main config. This technically means that duplicate content could be served at both assets.example.com and example.com. I finish up by adding the following lines to the .htaccess file:

1
2
3
4
5
6
#make sure assets load properly
RewriteCond %{HTTP_HOST} ^assets.example.com
RewriteCond %{REQUEST_URI} !^/css
RewriteCond %{REQUEST_URI} !^/js
RewriteCond %{REQUEST_URI} !^/images
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]

This make sure that if the host is assets.example.com and the content is not coming form the css, js or images folder, to redirect with a 301 to the main domain. This will stop duplicate content.

Enough about this, what about my CSS?

I actually hold my css in a different folder in my architecture – not some place that is world readable. I usually call it the public_source folder – which is at the same level in the source tree as say the www or html folder. In this example, I’m going to call my example file main.css. So it is actually located at /var/www/public_source/main.css.

Next, I’ll create a file called dev.php in the assets folder where I plan to test my css from. So, this file is located at /var/www/html/css/dev.php. It may contain this content:

1
2
header ('Content-type: text/css');
readfile('/var/www/public_source/main.css');

So, now when I load my website, I can do the following to load my source css:

1
<link rel="stylesheet" type="text/css" href="http://assets.example.com/css/dev.php" />

Of course, when the website is built and deployed, we will be using a different URL.

Next, lets talk about compression of the CSS. I use CSS Tidy to compress my code. The code to invoke this is pretty simple.

1
2
3
4
5
6
7
8
9
10
11
require 'csstidy-1.3/class.csstidy.php';
$cssSource = file_get_contents('/var/www/public_source/main.css');
 
$css = new csstidy();
$css->load_template('highest_compression');
$css->set_cfg('remove_last_;',TRUE);
$css->set_cfg('sort_properties', TRUE);
$css->parse($cssSource);
$cssFinished = $css->print->plain();
 
file_put_contents('/var/www/html/css/main.1.css', $cssFinished);

You’ll notice that I named the file main.1.css. The number will be explained later (its used for caching).

So, the CSS is read, compressed and cleaned, and outputted to a location that the webserver can serve it from. Now, instead of using dev.php as the source, we’ll use main.1.css. Congratulations – a smaller CSS file!

The final thing to do is adjust the caching of this script. Whenever we change the CSS on the development platform, we’re reading it in new using dev.php. However, when this is built and deployed, it should be a built version (or compressed) of the file. This means every code deploy requires this build system. And with release numbers on main software, we’re also going to increment our file name. So our second deployment of the software package (if the CSS source has changed) will now be built using main.2.css – and the link statement will be pointed towards that.

The caching then can make the assumption that this file will never change. The CSS may change but the file is a new name then. And since we can’t just load portions of a file whenever there is a change, even a small change in a non-cached file will make the entire file load. So with this in mind, I cache my CSS files for one year. I put the following in my config:

1
2
3
ExpiresActive On
#1 yr
ExpiresByType text/css A31536000

This means that the file will be cached one year from the first time it is accessed. So, if the source HTML continues to point at the same CSS file (say… main

Making Friendly Javascript Errors – Client and Server

Thursday, January 14th, 2010

The more I look at my code I wrote in my earlier posts about the unknown _popupControl() function and the Javascript Error Handler, I see opportunities to leverage these errors into useful user interactions.

Doing a service for your visitor

After your javascript is tried and tested and error free, there are still chances that errors can be logged using my utility. These usually are the result of Spyware that is left on the user’s machine. Sometimes some removal processes don’t capture all of it. The _popupControl() method was one such remnant.

I thought that instead of just ignoring these issues, I could gently alert the user to the issue. Perhaps, I could even get affiliate commissions for a product that I know for sure removes these threats.

There are two ways to go about handling these javascript errors: client side and server side.

Client Side

Client side javascript error handling requires a bit more front-end programming. It also shows a lot of your cards to the outside world. By looking at the code in the javascript portion of your page, visitors could see all types of errors that you’re trying to detect. While I don’t think this is a deterrent to using this method, you may feel otherwise.

First things first – if you can’t remember, check out my Javascript Error Handler and Logger entry to see the code I’ll be expanding on.

My new code is going to look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
            window.onerror = function (message, url, line) {
                /** log message **/
                var i = new Image();
                i.src = 'error.php?url=' + escape(url) + '&message=' + escape(message) + '&line=' + line;
 
                if (message.indexOf('spywareWindowGenerator')) {
                    var d = document.createElement('div');
                    d.innerHTML = 'Sounds like you got spyware';
                    document.body.appendChild(d);
                }
                else if (message.indexOf('otherbaddie')) {
                    var d = document.createElement('div');
                    d.innerHTML = 'Sounds like you got some other baddie';
                    document.body.appendChild(d);
                }
            }

I’ll break it down:

First, the standard logging service is initiated on error. The error.php file will log the javascript error for further research later.

Next, I evaluate the actual message that was sent to the error handler. In this example, I’m looking for two possible issues, a reference to the function _spywareWindowGenerator() and a reference to someOtherBaddie(). Both of these functions are not defined in my code and can be considered to be remnants of the spyware infestation.

The first ‘if’ statement checks for the existence of ‘spywareWindowGenerator’ in the message. If it exists, it creates a new DIV HTML element. Then, it populates it with a message regarding this error. (Note, you could also load an image, create link, etc.). Finally, just for demonstration purpose, that DIV is added to the end of the body and is displayed.

The second if statement is simply checking for the case of ‘otherBaddie’ – and will do a similar process.

Like I mentioned before, this lays all of your cards out on the table – could potentially make your page load longer (especially if you have a lot of spyware you’re tracking), but be most versatile.

Server Side

With server side, I’m going to rely on the image that the javascript error handler is loading. If this image is populated by my error.php file, then I’ll show it.

First, the modified javascript for our error handler now looks like this:

1
2
3
4
5
6
7
8
9
10
11
            window.onerror = function (message, url, line) {
                /** log message **/
                var i = new Image();
                i.src = 'error.php?url=' + escape(url) + '&message=' + escape(message) + '&line=' + line;
 
                /** now check to see if we have something to show **/
                if (i.height) {
                    /** add it to the page **/
                    document.body.appendChild(i);
                }
            }

The first part is the standard logging mechanism that we’re used to. However, after that, I check for a height of the image that was requested. If no image was generated by the PHP GET request, then the height will be 0. Otherwise, the image object will return a height. Then, just for demonstration, I append that image to the bottom of the body of the document.

This means that we put a little bit more of the responsibility for determining the message to display to the user on the back end. At first it seems like it could be a little less verbose – as it is just an image. However, we could expand the javascript error handler to detect what ‘link’ it could display based on the image dimensions, etc. (This is for a different entry if need be…)

Next, I had to edit my error.php file. It now contains this code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$keys = array();
$keys['_spywareWindowGenerator'] = 'badSypware.png';
$keys['otherBadGuy'] = 'otherBadGuy.png';
 
/**
 * check for an image to show
 */
 
$imageToShow = '';
foreach ($keys as $substring=>$image) {
    if (stripos($_GET['message'], $substring) !== false) {
        $imageToShow = $image;
    }
}
 
if (!empty($imageToShow)) {
    header('Content-Type: image/png');
    readfile($imageToShow);
    die();
}
else {
    error_log("{$_GET['message']} occured on line {$_GET['line']} of URL {$_GET['url']}");
}

The first step is to determine all of the key words that could appear in javascript error messages. Then, associate them with an image that conveys our message.

The next bit of code looks through and searches the message for any of the possibilities. If it finds one, it sets the image to be the associated value for that key.

Finally, the PHP code checks to see if there is an image to show. If so, it sends the proper header and reads the file to the output buffer. Otherwise, it assumes it is an error that we’re not familiar with and logs it.

In this example, I used the following two images just for testing.

Using Google Analytics Asynchronously

Monday, January 11th, 2010

I came across the following link on google’s code pages:
http://code.google.com/apis/analytics/docs/tracking/asyncTracking.html

It basically details the asynchronous loading of google analytics. I found this to be a very cool addition to an already powerful package that I rely on.

However, one thing that I haven’t been able to successfully figure out. What happens when you want to load in two instances or two different accounts? On one of my sites, I use my own google analytics account plus the clients. This tracks the traffic fine with the non-asynchronous method. You simply make a new instance of the ga object and assign a new ID to it. However, can I do the same thing with this asynch method? I’m kind of wary to try it because I don’t want to lose any data.

Anyone have any experience or have any links to where I can find this detail?

document.URL vs document.location.href

Friday, December 18th, 2009

When reviewing some javascript security ideas, I came across the document.URL property. Turns out that my normal way of retrieving the location (document.location.href) is both a getter and a setter. The document.URL is just a getter.

Check it out with this code:

1
2
3
4
alert(document.URL);
alert(document.location.href);
document.URL = 'http://google.com';
document.location.href = 'http://yahoo.com';

The results are simple: you will get the current location twice – and then an error. If you comment out the document.URL line, it will redirect to yahoo.

  • twitter loader

Follow me on twitter: @aaronsaray

The views on this website are my own and do not reflect the opinions of my employer or clients.
Creative Commons License Home | Open Source | Book | Music | Art | Bio | Resume | Contact
My Baby