Wes Bos

Designer, Developer & Entrepreneur making the web an awesome place.

Category Archives: browsers

photo (1)

If you do any sort of web development locally you have probably run into at least one of the following problems:

  1. I can’t access my local sites/apps on my mobile devices
  2. I can’t access localhost inside of my virtual machines
  3. My teammates can’t access my local site to view it
  4. I need to test IE6 on my Toshiba crapbook

Pushing your site to a server isn’t ideal, especially when you are debugging a problem and have a longer deploy process.

I develop everything locally and have to test my sites/apps on a variety of mobile devices as well as a few different installs of windows which I run on Virtual Box. This is how I run a single development domain that is available to every device on my wireless network as well as on my laptop, regardless of the wifi network I’m on.

Continue reading

androidthumb

Be sure to Follow @wesbos on twitter for more like this :)

Earlier this week Chrome for Android was finally announced and web developers everywhere celebrated. Not only did we have one of the best browsers now on our phones, but we had access to remote debugging, which we have been waiting for and talking about forever.

Remote debugging allows a developer to use the browsers developer tools from a desktop computer while inspecting and manipulating the website on the mobile device – all in real time! This means you no longer have to use alert boxes to debug a problem that only reproduces on the phone.

So, while there have been a few earlier implementations of something similar, Chrome for android brings us the rock solid experience that we have been waiting for. Without further ado, here is a quick tutorial on how to get remote debugging up and running.

Update: I’d like to specifically point out that Opera Mobile has has this functionality for quite some time now and you’re able to do it without USB or a SDK (miketaylr had an awesome presentation on it at jQuer conf). So, develop in whatever browser you prefer and use both these tools when you’re debugging that specific mobile browser.
Continue reading

facedetection

This morning I saw this link on youtube which was a little mashup of some HTML5 technologies. I thought it would be funny if I could do the same, but with goofy pair of glasses. I’ve also been itching to put the CCV JavaScript Face Detection library to use. This library shows a few examples on static images, but after a quick look at the code, it shows that the underlying element to the script is a canvas element. So instead of running it on a single image, I am running it on a feed of frames coming from an HTML5 video element.

I’ll go into the technical details further on in the post, but here is a demo as well as a youtube video showing the effect as it can be a little sluggish on older machines. Currently tested and working in Google Chrome 14 and Firefox 6.0.  Continue reading

sockets

Web sockets and Canvas are two really cool features that are currently being implemented into browsers. This tutorial will give you a short rundown of how they both work as well as create a realtime drawing canvas that is powered by Node.js and web sockets. For simplicity’s sake, I’ll be writing all the code in coffeescript. If you prefer regular ‘ol JavaScript, take a look at the corresponding .js files. I’ve also left out the CSS for the same reason.

Quick Screencast detailing tutorial

Cross Device / Browser compatibility

Server Side

The first thing we need to do is create a web socket server. For this we will be using Node.js and the module Socket.io. Socket.io makes its super easy to get a web socket server up and running. It even provides a flash fallback for browsers that don’t support native web sockets. In this tutorial we will only be working with browsers that support the canvas element.

If you don’t have Socket.io installed yet, make sure you do so by typing npm install socket.io into your terminal.

For now, lets just set up the web socket server. Create your server.coffee file with the following configuration.

io = require('socket.io').listen(4000)
io.sockets.on 'connection', (socket) ->

Compile your coffeescript and hop back into your terminal and type node server.js. You now have a web socket server running on port 4000.

If you go to localhost:4000 you’ll see the following:

Client Side

First, lets quickly get our index.html file up and running. In addition to some bare bones markup, I’m also including jQuery, our Socket.io JS file which is now being served up from our server, a jQuery plugin for drag events, and our own scripts.js file which will hold all the magic.

<!DOCTYPE HTML>
<html>
<head>
	<meta charset="UTF-8">
	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
	<script type="text/javascript" src="js/jquery.event.drag-2.0.js"></script>
	<script src="http://localhost:4000/socket.io/socket.io.js"></script>
	<script type="text/javascript" src="scripts.js"></script>
	<link rel="stylesheet" href="style.css" />

	<title>HTML5 Canvas + Node.JS Socket.io</title>
</head>
<body>
	<article><!-- our canvas will be inserted here--></article>


	<!-- Scripts required -->
	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
	<script type="text/javascript" src="js/jquery.event.drag-2.0.js"></script>
	<script src="http://localhost:4000/socket.io/socket.io.js"></script>
	<script type="text/javascript" src="scripts.js"></script>
</body>

Now that we have our server up and running, we can write some code which will draw to the canvas. Create a new file called scripts.coffee. All of the following code happens within the App.init() method which we will trigger on the jQuery document ready.

Create our Canvas Element

# setup our application with its own namespace 
App = {}

###
	Init 
###
App.init = -> 
	App.canvas = document.createElement 'canvas' #create the canvas element 
	App.canvas.height = 400
	App.canvas.width = 800  #size it up
	document.getElementsByTagName('article')[0].appendChild(App.canvas) #append it into the DOM 

	App.ctx = App.canvas.getContext("2d") # Store the context 

	# set some preferences for our line drawing.
	App.ctx.fillStyle = "solid" 		
	App.ctx.strokeStyle = "#bada55"		
	App.ctx.lineWidth = 5				
	App.ctx.lineCap = "round"

	# Draw Function
	App.draw = (x,y,type) ->
		if type is "dragstart"
			App.ctx.beginPath()
			App.ctx.moveTo(x,y)
		else if type is "drag"
			App.ctx.lineTo(x,y)
			App.ctx.stroke()
		else
			App.ctx.closePath()
	return

Draw to canvas function

Since drawing to canvas involves beginning, moving and closing paths, i’ve create a short little function that hooks into the jQuery dragstart and drag events.

# Draw Function
App.draw = (x,y,type) ->
	if type is "dragstart"
		App.ctx.beginPath()
		App.ctx.moveTo(x,y)
	else if type is "drag"
		App.ctx.lineTo(x,y)
		App.ctx.stroke()
	else
		App.ctx.closePath()
return

Setup our client side web socket

Since we included our file at http://localhost:4000/socket.io/socket.io.js we are able to create an object which we can send our data over. With just a few lines, we create our App.socket object and bind to any incoming web socket events called ‘draw’. We will go over this more soon.

# Sockets!
App.socket = io.connect('http://localhost:4000')

App.socket.on 'draw', (data) ->
	App.draw(data.x,data.y,data.type)

Canvas Drawing Event

This is where things gets exciting. Now we want to bind a few events to our canvas element. The way this works is when someone draws on the canvas, we immediately use our draw() function to draw to the current canvas as well as send the x and y ordinates over the web socket with socket.io’s emit. In just a bit we will take a look at the server side part of this event and see how the server sends out this data to all open windows.

###
	Draw Events
###
$('canvas').live 'drag dragstart dragend', (e) ->
	type = e.handleObj.type
	offset = $(this).offset()
	
	e.offsetX = e.layerX - offset.left
	e.offsetY = e.layerY - offset.top
	x = e.offsetX 
	y = e.offsetY
	App.draw(x,y,type)
	App.socket.emit('drawClick', { x : x, y : y, type : type})
	return

Jump back to server side

Now that we know we are sending the x, y and type of event over the web socket, we need to do something with that on our server. What we want to do, is take that data and send it back out to everyone else that has a browser open.

Our updated server.coffee file now looks like this. We first wait for a connection event, then wait for a ‘drawClick’ event to be sent by a browser. When that happens we take the data and send it out to everyone else with a browser open. THe server side script we wrote earlier will then paint the canvas.

io = require('socket.io').listen(4000)

io.sockets.on 'connection', (socket) ->
	socket.on 'drawClick', (data) ->
		socket.broadcast.emit 'draw',{ x : data.x, y : data.y, type: data.type}
		return
	return

You’ll now need to restart your web socket server as we have made changes to it. Hit control-c to kill it, and node type node server.js to restart it.

Get Drawing!

One you fully understand how this all works, open your index.html file in any web browser that supports web sockets and canvas (at the time of writing Chrome, Firefox, Safari, Opera and IE9). Check http://caniuse.com/#search=canvas for more support info.

Limitations

As this is a very basic demo, there are a few limitations which can easily be solved with a little more code. Currently the canvas only supports one person drawing at a time, if two or more are drawing, the canvas will be painted sporadically. Also, there is definitely a lot of room to add tools such as brushes, colours, erasers and PNG export. If there is interest, I’ll expand this tutorial series to cover them.

If you’re interested in getting this up and running in the real world and off of your localhost, I was able to get mine running on Amazons free micro instance of EC2 although this involves installing Node and NPM all over again. Also note you should run your server on port 80 rather than 4000.

Please feel free to download, hack, complain, fork or contribute to the project on my github account.

Screen shot 2011-05-17 at 12.56.54 PM

Two of my favorite jQuery plugins are Mike Alsup’s Cycle and Ben Alman’s Hashchange. Cycle allows you to create really flexible sliders /slideshows and Hashchange allows you to create an event that triggers on hash change. When you’re using jQuery cycle for a large slideshow, its a good idea to let users link within that slideshow to a specific slide so that they can share and bookmark them.

A great example of this is for a photographer that may have 50 pictures in their portfolio, they often do not let you share the link to that specific picture but rather just the page with the slideshow embedded in it. Additionally, the user can now use the browsers back/forward buttons to navigate through your slideshow Continue reading

Screen shot 2011-05-11 at 3.08.07 PM

Just about an hour ago Rovio and Chrome released Angry Birds for Chrome. As a JavaScript / HTML5 guy, I quickly jumped into the code to see how things worked.

I was quickly able to find a hack that gave me access to all the levels, even the special Chrome levels!  So to  get access to all levels in Chrome Angry Birds, just copy and paste the following line into your browser’s address bar.

Continue reading

paywall

If you haven’t heard, the New York Times has implemented a paywall where you can only view 20 articles a month. After that they throw an overlay on top of the content so you can’t view it.

Since they still want to be indexed by search engines, they don’t bother to hide the content once you have reached your 20 max. Two simple lines of CSS will hide this. I’ve also made it into a Chrome Extension
Continue reading

Screen shot 2011-03-23 at 2.56.08 AM

Yesterday Firefox 4.0 was released and web developers everywhere celebrated a really great browser.  The browser comes packed with a super fast JavaScript engine called JägerMonkey. Now don’t get too excited just yet! We still need to keep that old version of Firefox around for testing; we can’t assume everyone has upgraded to Firefox 4. So, to run both Firefox 3.6 and Firefox 4.0 on the same machine, just follow these simple steps: Continue reading