Unable to reproduce TypeError: ‘undefined’ is not an object

Google Analytics shows that ~12% of our total users are affected by a Javascript bug of:

TypeError: 'undefined' is not an object

90% of the browsers are Safari 7534.48.3, 10% are Mozilla compatible agent. 75% of the errors come from iPhones, 23% from iPads. 1% from Macintosh, the other 2% is from iPod etc. None of the devices run Linux or Windows.

I have tried enabling debug mode in safari on both an iPhone and iPad but not able to reproduce the bug.

Here is a link to a page Google Analytics claims is showing the error. If anyone can consistently reproduce the error here I will be super happy because just a line number would be enough to get me started debugging.

Update: TypeError: ‘undefined’ is not an object (evaluating ‘safari.self.tab.canLoad’)

Managed to get that out of it once when clicking around, mostly on an iphone whilst clicking “Change country..”

Update: Solved this by making sure the element was available in the dom. Turns out the ajax call on success was trying to write to an element that wasn’t available.

Why I’m making a game before my next project

Quick link to the game I made


Primary Technology is a good place to work, the main reason being is that I have a lot of freedom to be creative. The ability to be creative means I get to work with a lot of different platforms and technologies. The next project I have been asked to do is a “web based really real time light-weight open source collaborative sticky note tool” AKA PrimaryWall. o_O

So let’s break that down… Web based, easy.. Really real time, not so easy when using conventions… light-weight, easy-ish.. open source, sort of easy.. collaborative, not so easy…

I could go ahead and make something with AJAX & Apache but it wouldn’t be as really real time as a lot of genuine really-real time so I’m going to be better off using NodeJS and Web Sockets. I did an example using Socket and Node a week or so ago that really got me thinking about how I can/could apply what I had learned to the projects I work on at Primary Technology.

The biggest problem I face is my lack of experience with Javascript. If I went straight into building PrimaryWall I would probably build it in a linear fashion and that would suck for an open source project because it wouldn’t feel appropriately structured.. Sure I “could” structure it all out based on what I know so far but I feel like I should do a test first and that test is to build a game using the same structure and hopefully at the same time build my knowledge of NodeJS, WebSocket + Javascript.

So I have 4 weeks to build a game then 4 weeks to build PrimaryWall (It is due at the end of March). The game will be called either “Tag” or “You’re it” and will be a simple multi-mouse game where moving the mouse is all that is required to play.

Any developers that read this think that I’m wasting my time and should just go for it?

I think this post is mostly me justifying spending the next month building a game that has been ultimately funded by the public sector.. I know this may seem a little strange but NodeJS is relatively new and so is Javascript and I really need to learn before I create as to create something that is worthwhile for other people to contribute towards….

Quick link to the game I made

Real time mouse activity w/ NodeJS & Sockets

Quick link to the NodeJS/websocket game I made — includes source

Thanks to Reddit for helping me test this.

Steps:
Get NodeJS
Get npm
Get SocketIO

Create server.js
Paste in:

// Simple Node & Socket server

var http = require('http')
  , url = require('url')
  , fs = require('fs')
  , io = require('../')
  , sys = require('sys')
  , server;

server = http.createServer(function(req, res){
  var path = url.parse(req.url).pathname;
  switch (path){
    case '/':
      res.writeHead(200, {'Content-Type': 'text/html'});
      res.write('<h1>Welcome. Try the <a href="/chat.html">chat</a> example.</h1>');
      res.end();
      break;
      
    case '/json.js':
    case '/test.html':
      fs.readFile(__dirname + path, function(err, data){
        if (err) return send404(res);
        res.writeHead(200, {'Content-Type': path == 'json.js' ? 'text/javascript' : 'text/html'})
        res.write(data, 'utf8');
        res.end();
      });
      break;
    default: send404(res);
  }
}),

send404 = function(res){
  res.writeHead(404);
  res.write('404');
  res.end();
};
server.listen(8080);

// socket.io, I choose you
var io = io.listen(server)
  , buffer = [];
  
io.on('connection', function(client){
  client.send({ buffer: buffer });
  client.broadcast({ announcement: client.sessionId + ' connected' });
  
  client.on('message', function(message){
    var msg = { message: [client.sessionId, message] };
    buffer.push(msg);
    if (buffer.length > 15) buffer.shift();
    client.broadcast(msg);
//    console.log(msg);
});
  client.on('disconnect', function(){
    client.broadcast({ announcement: client.sessionId + ' disconnected' });
  });
});

Create test.html
Paste in:

<!doctype html>
<html>
  <head>
    <title>Multi Mouse - How many mice can I mouse eater eat?</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script> <!-- jquery -->        
    <script src="/json.js"></script> <!-- for ie -->
    <script src="socket.io/socket.io.js"></script> <!-- sockets -->
  </head>
  <body>
<h1> You can see my mouse!! ZOMG - <a href="http://www.youtube.com/watch?v=aFLcbBvTGns">Video explaining why I'm doign this</a></h1>    

    <script>

// some random color 
function randc(){
colors = new Array('#FF0000','#00FF00','#0000FF','#00FFFF','#FF00FF','#C0C0C0');
var color = colors[Math.floor(Math.random()*colors.length)]
return color;
}

// When a new message arrives..
      function message(obj){
	var data = obj.message[1].split(':');
	var x = data[0];
	var y = data[1];
        var userid = obj.message[0];

  if($('#mouse_'+userid).length == 0 && userid != 'you') {
	var randcolor = randc();
	$('body').append('<div class="dot" style="background-color:'+randcolor+'" id="mouse_'+userid+'"/>'
    );
  }

// stops a dot being drawn for local user
if (userid != 'you'){
   $('#mouse_'+userid).css({
    'left' : x + 'px',
    'top' : y + 'px'
  })
}
        var el = document.createElement('p');
        if ('announcement' in obj) el.innerHTML = '<em>' + esc(obj.announcement) + '</em>';
        else if ('message' in obj) el.innerHTML = '<b>' + esc(obj.message[0]) + ':</b> ' + esc(obj.message[1]);
        document.getElementById('chat').appendChild(el);
        document.getElementById('chat').scrollTop = 1000000;
      }
      
// A function to define how we send data
      function send(){
        var val = document.getElementById('text').value;
        socket.send(val);
        message({ message: ['you', val] });
        document.getElementById('text').value = '';
      }
      
// When a mouse is moved
      window.onmousemove = function(event){
	 message({ message: ['you', event.clientX+':'+event.clientY] });
         socket.send(event.clientX+':'+event.clientY);
      };

// replace <&> w/ &lt&&gt
      function esc(msg){
        return msg.replace(/</g, '&lt;').replace(/>/g, '&gt;');
      };

// establish the socket connection      
      var socket = new io.Socket(null, {port: 8080, rememberTransport: false});
      socket.connect();
      socket.on('message', function(obj){
        if ('buffer' in obj){
          document.getElementById('form').style.display='none';
          document.getElementById('chat').innerHTML = '';
          
          for (var i in obj.buffer) message(obj.buffer[i]);
        } else message(obj);
      });
    </script>
    
    <div id="chat"><p>Connecting...</p></div>
    <form id="form" onsubmit="send(); return false">
      <input type="text" autocomplete="off" id="text"><input type="submit" value="Send">
    </form>
    
    <style>
      .dot { height: 10px; width: 10px; background-color:#000000;position:absolute;left:0;top:0;}
    </style>
    
  </body>
</html>

Run it with

node server.js

Test it by visiting http://whatever:8080

Quick link to the NodeJS/websocket game I made — includes source