Tag Archives: javascript

Javascript Singleton Pattern

Here’s a pattern for a javascript singleton that I’ve been using for a while.

window.singletonName = window.singletonName || new (function(argument) {
	console.log("argument: " + argument);
	this.pub = "foo"; // window.singletonName.pub will be "foo" 
	var priv = "bar"; // window.singletonName.priv will be undefined
})("test argument");

No matter how many times you run this code, window.singletonName will still refer to the function you created the first time you ran it.

Rolling my own very simple, MVC patterned Javascript Canvas game without an MVC framework

Recently we (at Primal) were asked to create a game that had to run on iOS and Android, in the browser. We picked the new CreateJS framework by Grant Skinner and Adobe, which is designed to make javascript and canvas work more like Actionscript and Flash. The docs are a little light on examples, but apart from that, I’m extremely happy with the performance and features of CreateJS.

Anyway, this isn’t about CreateJS, this is about MVC in Javascript, without an MVC framework. Here’s a very stripped down version of how it worked. I’m not saying this is the right way to do it, or the best way to do it, but it worked really well for me.

Note that in Javascript, there are no classes, so we fake them with functions. It works pretty much the same way, and you don’t have to learn any standardized constructor/destructor stuff.

The HTML:
In the case of a javascript game, the HTML really only serves to load the JS files, and kick things off when everything is loaded.

<html>
<head>
	
	
	
	
	
	
		
</head>

	
	

</html>

The Controller:
I had just one controller that represented the game’s main logic tree.

function GameController() {
	var self = this;
	this.toString = function() { return "GameController"; }

	this.gameModel;

	this.uiView;
	this.avatarView;
	this.hudView;
	this.scoreView;
	this.etcView;

	this.create = function() {
		self.gameModel = new GameModel();
		
		self.uiView = new UiView();
		self.uiView.create();
		
		self.avatarView = new AvatarView();
		self.avatarView.create();
		
		self.hudView = new HudView();
		self.hudView.create();
		
		// and so on
		
		self.initGame();
	}

	this.initGame = function() {
		// now that we've created all the view elements,
		// and the model, get the game started
	}
}

The Model:
Note that this isn’t a singleton. I had just one controller, so I didn’t run the risk of duplicating the Model, but if I did, I would have made this a singleton.

function GameModel() {
	var self = this;
	this.toString = function() { return "GameModel"; }

	this.something;

	this.getSomething = function() {
		return self.something;
	}
	this.setSomething = function(data) {
		self.something = data;
	}

}

The Views:
Views come and go, so they need to be created and destroyed. In the destroy, make sure you clean up everything.

function UiView() {
	var self = this;
	this.toString = function() { return "UiView"; }

	this.someUiElement;
	this.anotherUiElement;

	this.create = function() {
		// load and display bitmaps, or whatever
		// fetch the URL for a bitmap from the model like this:
		game.gameModel.getSomething();
	}
	this.destroy = function(data) {
		// unload all assets and unset all variables.
	}
}

And that’s about it. Every view and model is a variable in the main GameController, which itself is a global variable (I called it game), so you can find anything through that game variable.

Also note these lines that appear at the top of every class.

var self = this;
this.toString = function() { return "NameOfClass"; }

Defining a var called self as this lets you refer to self anywhere in that class, and not worry about scope. For example, if you used a setTimeout to delay something, this would be redefined to the setTimeout handler function, but self would still refer to the class.
Redefining toString to return the name of the class is optional, but it makes your console clearer if you want to console.log where something is coming from.

Dos and Don’ts of Animating for iPad 1 using CSS or JS/TweenMax

I’m working on a project at Primal right now for a big TV network you’ve heard of who is making an iPad app. They’re bringing the content, and another company is writing the app, but they’ve brought us in to make some funny interstitials/easter eggs. The minimum specs are these:

- iOS 5 (thankyou!)
- iPad 1 (ouch)
- Loaded in a UIWebView, i.e. HTML5, CSS3, JS: Mobile Webkit’s capabilities.
- 100kb limit on prepackaged assets, but we can load more as needed.

So I’m learning what is tough on the hardware (kills the framerate) and what it likes, and I thought I’d share.

Dos:
- Use this trick I’ve mentioned before
- Use 3D transforms, and other webkit native stuff
- Failing that, use absolute positioning of elements, i.e. top and left, not margins

Don’ts:
- Animate background-position. Not sure why, but a box-in-a-box, where the inner box has the background and it moves within the outer box, is more efficient
- Animate padding, margins, or the dimensions of inline elements. These cause the page renderer to worry about whether it needs to rewrap lines, and push other objects around.
- Use huge images. iPad 1 has a 4mb texture buffer, which comes out to 5 1024×768 images. You can use up to 2048×2048, but of course that’s 4 1024s in itself, so just one.
- Use transition-delay to offset one animation from another, if they need to stay in sync. The delayed one will try to start on time, but sometimes it loses sync. Instead, start the animations at the same time, and just have the animation that would be delayed do nothing for a while.

It was a tight competition between TweenMax and CSS animation. In the end, CSS had a very slight edge in performance, but writing it all was a huge pain. Keyframes assigned by percent? Thanks W3C. I’d suggest TweenMax to anyone but the biggest CSS geeks, or those wanting every last ounce of performance.

I’ll keep adding to this list as I find more.

Socket.io 0.7 – Sending messages to individual clients

Note that this is just for Socket.io version 0.7, and possibly higher if they don’t change the API again.

I’m writing an iPhone app right now using PhoneGap and jQuery Mobile on the phone, and node.js and socket.io on an Amazon EC2 server, and I hit a wall when I started using Socket.io. The problem is that the documentation is sparse, disorganized, and hard to find. In addition to that, there are dozens of blog posts and community members who’ll teach you how to do things in older versions of socket, but the API has changed, so you just end up with undefined errors.

My exact problem was with sending messages to individual clients.

First, you need the client’s socket ID, so have the user “check in” when they connect, and have the server store their socket ID with whatever identifier we’ll be using to refer to users (in my case, phone number).

// on the server
var users = {};
io.sockets.on('connection', function (socket) {
	socket.emit('who are you');
	socket.on('check in', function (incoming) {
		users[incoming.phonenumber] = socket.id;
	});
});
// on the client
socket.on('who are you', function (incoming) {
	socket.emit('check in', {phonenumber: savedphonenumber});
});

To recap: The server is listening for connections. When a client connects, the server emits the custom message “who are you”. The client hears it and responds with it’s identifier (I’m using their phone number, which I verify and store earlier in the process). The server then stores the client’s socket ID in a users object, with their identifier as the key, and the socket ID as the value.

From then on, it’s a simple case of grabbing the user’s socket ID from the user’s table when you need to send them a message, and sending it like this:

var socketid = users[clientphonenumber];
io.sockets.socket(socketid).emit('for your eyes only');

One thing to consider is what happens to that users object if you have thousands of users. It’ll get pretty bloated, pretty quickly. You need to figure out a strategy for removing users from the users object if they disconnect AND if you don’t hear from them in a while (in case the disconnect event doesn’t fire).

Make your own live, auto-updating data feed with PHP (CodeIgniter) and Javascript (jQuery)

EDIT: I guess you don’t need to store the last entry time in a cookie, storing it in a simple js var works fine. I’ve updated the code to reflect this.
EDIT2: If your server isn’t doing a good job of responding to the queries for the last entry time, and it’s just sending 304 Not Modified every time, then you can add a random GET var on the request, so it always give you a fresh copy. Takes more resources though.

$.ajax({
	url: "latest_report_time.txt?" + Math.floor(Math.random()*10000),
	.......

Original Post:
I’ve been working on a webapp recently which involves users in the field sumbitting reports, and users back at the office seeing those reports as they come in. Eventually I’ll probably set it up right, with true two way communication between the field users and the office users, via an XMPP server, but in the meantime I went with a simpler approach.

Here’s what I came up with.

1) When a field user submits a report, it goes into the database as you would expect, but a new function I wrote just for this purpose also does something else, something very simple, it replaces a text file on the server with the current timestamp. Note that its a simple .txt file and that the single timestamp of the latest report is all it contains. That way there’s no PHP overhead when someone looks at that file, and if they’ve already looked it up once and it hasn’t changed, the server will return a 304 not modified message, and the browser won’t even download the file. Very efficient.
In CodeIgniter, that code looks like this, but it could be done in any framework, or plain old PHP.

$this->load->helper('file');
$timestamp = now();
write_file('latest_report_time.txt', $timestamp);

2) When an office user opens a page in their browser that is meant to be auto-updating, a new javascript is run. All that script does is look up that file we made, latest_report_time.txt, every 5 seconds, and checks to see if the timestamp in it has changed since the last check (which was saved in a cookie on the last check). Note that I’m using jQuery and a very jQuery plugin called jQuery Cookie, but you could do this in any JS framework, or plain old JS.

setInterval(checkForReportUpdates, 5000);

var oldLastReportSeen = 0;
function checkForReportUpdates() {
	$.ajax({
		url: "latest_report_time.txt",
		success: function(data) {
			var newLastReportSeen = data;
				
			if (oldLastReportSeen != newLastReportSeen) {
				console.log("New report found, get it and set new cookie");
				getNewLatestReport();
				oldLastReportSeen = newLastReportSeen;
			} else {
				console.log("No new reports");
				oldLastReportSeen = newLastReportSeen;
			}
		}
	});
};

3) Finally, if the timestamp on the server has been updated, do another ajax call to grab the latest report. I leave the rest of this up to you, because the structures of our sites are probably very different, but you’ll probably end up writing some of your own logic to check to make sure the newly fetched report is not one you are already showing, and then use jQuery’s prepend() or append() to insert it into your page.

function getNewLatestReport() {
	$.ajax({
		url: "reports/latest",
		success: function(data){
			if (/*check for duplicates here*/) {
				$("#reports").prepend(data);
			}
		}
	});
}

Load more content as the user reaches the bottom of your page, with jQuery

I recently built a project gallery for Primal Screen’s new website (not live yet). Instead of having the traditional < 1 2 3 4 5 > pagination setup, we decided to take a leap forward into the the world of modern browsers, ajax, and users with very short attention spans. In this on-demand world, we load the content as needed: when the user hits the bottom of page one, page two is loaded and appended, and so on until you run out of content, or the user’s scroll wheel breaks. It’s a never ending page, without a never ending load. You may have seen this functionality in the Firefox plugin, AutoPager, or the Chrome/Safari plugin AutoPagerize.

Anyway, basically it works like this:
1) User loads page with 15 thumbnails on it
2) User scrolls to bottom of page, triggering a jQuery event we set up
3) 15 more thumbnails appear like magic or voodoo or mindreading or something and the page gets longer! Without even clicking!
4) User scrolls some more, hits bottom of page again, jQuery event fires again and
5) 15 more thumbnails appear and the page gets longer, further blowing the user’s mind!
6) ?
7) Profit.

alreadyloading = false;
nextpage = 2;

$(window).scroll(function() {
	if ($('body').height() <= ($(window).height() + $(window).scrollTop())) {
		if (alreadyloading == false) {
			var url = "page"+nextpage+".html";
			alreadyloading = true;
			$.post(url, function(data) {
				$('#galleryThumbsCol').children().last().after(data);
				alreadyloading = false;
				nextpage++;
			});
		}
	}
});

Line 1 is a state variable. We set it to true when we start loading a new page, false when it's loaded and shown, and before we load a new page we check to make sure the variable is set to false to ensure that we don't try to load page three before page two is done loading.
Line 4 Standard jQuery scroll event. This fires several times per second when scrolling in a modern browser, but on old browsers it just fires once when you stop scrolling.
Line 5 Here we check to see if the user is at the bottom of the page.
Line 6 Here we check to make sure we aren;t already loading a page.
Line 7 This is where the magic happens. $.post is a jQuery function that loads the url you give it in it's first parameter, and runs the callback function you give it in it's second parameter (and that function get's the loaded data in it's one and only parameter, did you follow all that?).
Line 8 Now that we have the loaded page, we have to put it in our existing page. Translated to english, this line reads "find the element with the ID: galleryThumbsCol, find it's last child, and put the loaded data in after that child.
Line 9, 10 Then we set our variables so we're ready to load the next page.

Find the Pixel perfect position of an element with jQuery (and keep elements always visible)

If you need to know the exact x and y positioning of any element on your page (relative to the viewport), use jQuery like this.

var x = $("#myElement").offset().left;
var y = $("#myElement").offset().top;

Then you can do stuff like this

$(window).scroll(function() {
	var y = $("#myElement").offset().top;
	var scrollY = $(window).scrollTop();
	if (scrollY > y) {
		var padY = scrollY - y;
		$("#myElement").css("paddingTop", padY);
	}
});

This script would compare your scrollbar’s position and the position of the element, #myElement, every time you scroll (several times per second on good browsers, when you let go of the scrollbar on bad browsers). Then, if the top of the element is above the top edge of the viewport, it adds some padding-top to it to keep it locked there at the top of the screen.

Use jQuery to attach an event to a key press

Keep in mind that some browsers don’t let jQuery know about certain key presses. For example, Chrome doesn’t send the event for keyCode 27 (escape), but Safari does.

$(document).keypress(function(e) {
	if (e.keyCode == 13) {
		alert("You pressed Enter!");
	}
});

And here’s a list of all the available keyCodes for you to use.

UPDATE: jQuery: Get all objects of selector, and then loop through them

In my original post I mentioned how one can use the get() function in jQuery to gather up all the selected DOM elements and put them in an Array, like so:

var stuffArray = $(".stuff").get();

Well here’s another way to do the same thing:

var stuffArray = $.makeArray($(".stuff"));

And then I showed how to loop through that new array and do something with each of the DOM elements like so:

for (x in stuffArray) {
	stuffArray[x].doSomethingHere();
}

Well there’s another way to do that too:

$.each(stuffArray, function(key, value) {
	value.doSomethingHere();
});

The two variables (key and value in the example) in the each callback function can be called whatever you want, but they represent 1) the array key, or if it’s a numerical array, the index of the entry in the array your each function is working on, and 2) the value at that key/index.