prettyPhoto 3.0: Updated beta.
August 26th 2010
Hey I’m not dead. Neither is prettyPhoto. My last update dates back to March 15th, I’ve been quite busy. Part of it is job, the other part has been Final Fantasy 13
But the good news is, I have been working on prettyPhoto during that time. So today I release an updated beta version with several bug fixes that were in the previous version.
Here are the full details:
- Added: Keyboard event bindings as a setting.
- Added: Inline galleries.
- Added: Multiple prettyPhoto with different settings on one page.
- Added: Slideshows!
- Fixed: Double click causing a where prettyPhoto would open without the faded background.
- Fixed: Bug when an image would not resize after opening an iframe.
- Fixed: Image resizing issues when allow_resize is set to false. Images now center properly.
- Fixed: “Image cannot be loaded” message bug. Removed the toLowerCase, a bug I introduced…can’t really say why I did that
- Changed: Vimeo video now uses their new universal player. http://vimeo.com/blog:334
- Changed: Default theme, now facebook.
- Changed: Default speed, now fast, feel snappier.
Download
So you want to test it? You can find the demo page here: http://no-margin-for-errors.com/demos/prettyphoto_3.0/
I suggest you test it on your website, you can find a zip file here: http://no-margin-for-errors.com/demos/prettyphoto_3.0/prettyPhoto_3.0b.zip
Please note that since it’s a beta, you should retest everything on your own to make sure nothing breaks.
Bug reports
Please report any bug in that thread in the forums. I’ll do my best to get them squashed to release that update as quickly as possible.
Thanks!
Deliver real-time information to your users using node.js
July 26th 2010
You must have already heard about node.js, if not, it’s an evented input/output server based on Google V8 engine. That means that as soon as the server receives information it can respond and send relevant information back to your front-end. You can then treat this information the way you want. What is so cool about it is that if you know javascript you can code a node.js server and it really is a lot of fun!
In this article, I’ll cover the basics to be able to build a simple server that will respond to an “admin” user input and then broadcast a message to all users connected on the website. Based on that, you’re then free to apply it to whatever needs you may have.
Please note that some basic server knowledge is required, like installing software with command line and forward requests to specific ports.
The demo
First open the live feed demo page, then open the live feed admin page. Try to resize them so you can see both, then click on the display buttons on the admin page, watch the magic happen on the live feed page!
The basics
How does that real-time thing work? Well it’s actually quite simple. Every time a user connects to my demo page, I open an ajax connection, that ajax connection wait for the server to send data. Once it receives data, it’s processed, the connection is closed and a new one is opened. This can be called Comet, long polling, ajax push, HTTP Streaming and a bunch of other names. You can also do long-polling in PHP but since node.js is a dedicated server it does a better job at handling the load.
The setup
If you’ve never installed node.js on your server, you first need to do it. The documentation is here. Make sure you have g++ installed on your server. Simply run: “sudo apt-get install g++” if you’re on Ubuntu, it’ll either tell you it’s up to date or install it.
Here’s how I proceeded to install node.js, 4 easy steps:
[/sources] > git clone git://github.com/ry/node.git [/sources] > cd node [/sources/node] > ./configure ...wait... [/sources/node] > make ...wait... [/sources/node] > sudo make install ...wait... 'install' finished successfully (0.193s) DONE
So you should now be setup with node.js on your server, let the fun begin.
The server (link to the source)
This demo uses two main javascript file, one for the server and one for the client. Let’s begin by tearing down the server javascript file.
The first thing you need to do is load the modules required for your app, in this case we need the http, sys, url and querystring module.
var http = require("http"),
sys = require("sys"),
url = require("url"),
qs = require("querystring");
I then declared my global variables for this applications, they are as follow:
var ITEMS_BACKLOG = 20;
var urlMap = {
'/real_time_feed' : function (req, res) {
var since = parseInt(qs.parse(url.parse(req.url).query).since, 10);
feed.query(since, function (data) {
res.simpleJSON(200, data);
});
},
'/send_feed_item' : function (req, res, json) {
feed.appendMessage( json );
res.simpleJSON(200, {});
}
}
The ITEMS_BACKLOG is the max number of items the server keeps in memory, this way you can make sur it never runs out of memory, you’ll see where it’s being used later.
I then declare my urlMap, these are the URLs the server listens to and the code to execute upon calling. It’s fairly straight forward, there’s one very important thing you need to know tho, it’s that since node.js runs on a different port than your normal webserver (a webserver usually runs on port 80), you need to forward the calls on those URLs to your node.js server port.
In my case, I use NGINX as my webserver and node.js runs on port 8001. Here’s what my NGINX configuration file looks like:
# Send request to node.js on port 8001
location ~* ^(/real_time_feed|/send_feed_item)$
{
proxy_pass http://localhost:8001;
}
You see that I redirect both URLs in my “urlMap” to the node.js server port. Might not be the most efficient way but since you cannot do cross-domain posting in ajax, it’s the only solution I found for now.
Then comes the meat, the server itself, it’s fairly easy to create, you just need to invoke the “createServer” method and make it listen to a specific port.
http.createServer(function (req, res) {
...
}).listen(8001);
All requests and responses will be processed in here, so you need some code in there right? Here it is:
http.createServer(function (req, res) {
// Get the url and associate the function to the handler
// or
// Trigger the 404
handler = urlMap[url.parse(req.url).pathname] || notFound;
var json = "";
if(req.method === "POST"){
// We need to process the post but we need to wait until the request's body is available to get the field/value pairs.
req.body = '';
req.addListener('data', function (chunk) {
// Build the body from the chunks sent in the post.
req.body = req.body + chunk;
})
.addListener('end', function () {
json = JSON.stringify(qs.parse(req.body));
handler(req, res, json);
});
}else{
handler(req, res);
}
res.simpleJSON = function (code, obj) {
var body = JSON.stringify(obj);
res.writeHead(code, {
"Content-Type": "text/json",
"Content-Length": body.length
});
res.end(body);
};
}).listen(8001);
So the first thing I do is go get the function that need to be invoked in my urlMap and assign it to my handler. Then depending on the type of request, I either get the posted data and send a response or just straight invoke the handler of the URL called and send a response.
Now you’ll see that in my urlMap I call the feed object, this object has 2 methods, one for querying and one for appending content to the feed.
The “query” method, don’t respond until there’s valid content to send, that’s why the ajax call keeps running, it’s just there waiting. The “appendMessage” method…well she append content to my “real_time_items” array.
// Handles the feed push and querying.
var feed = new function () {
var real_time_items = [],
callbacks = [];
this.appendMessage = function (json) {
// Append the new item.
real_time_items.push( json );
// Log it to the console
sys.puts(new Date() + ": " + JSON.parse(json).type + " pushed");
// As soon as something is pushed, call the query callback
while (callbacks.length > 0)
callbacks.shift().callback([JSON.parse(json)]);
// Make sur we don't flood the server
while (real_time_items.length > ITEMS_BACKLOG)
real_time_items.shift();
};
this.query = function (since, callback) {
var matching = [];
for (var i = 0; i < real_time_items.length; i++) {
var real_time_item = real_time_items[i];
if (real_time_item.timestamp > since)
matching.push(real_time_item)
}
if (matching.length != 0) {
callback(matching);
} else {
callbacks.push({ timestamp: new Date(), callback: callback });
}
};
};
That’s basically it for the server!
The client (link to the source)
What you need to do on the client side is very simple, you only need to start an ajax call that restarts when it receive a response:
function longPoll_feed () {
//make another request
$.ajax({
cache: false,
dataType: 'json',
type: "GET",
url: "/real_time_feed",
error: function () {
//don't flood the servers on error, wait 10 seconds before retrying
setTimeout(longPoll_feed, 10*1000);
},
success: function (json) {
display_event(json);
//if everything went well, begin another request immediately
//the server will take a long time to respond
//how long? well, it will wait until there is another message
//and then it will return it to us and close the connection.
//since the connection is closed when we get data, we longPoll again
longPoll_feed();
}
});
}
So that ajax call listens to what is sent on the “real_time_feed” url. Once it receives data, it processes them.
Since it’s JSON that is returned to my views, I can then treat it the way I want. This file need to be included in the HTML file that will receive the live content.
The big merge
Ok so now you have your server javascript file and your client javascript file. The first thing you need to do is create an HTML page in which you’ll include the client.js file, I my case, it’s the index.html file.
Now for the server.js file, you actually need to connect via command line and start the node.js server like so:
[scaron] > node /path/to/server.js Server running at http://127.0.0.1:8001/
And finally, to be able to send content to the server in real time, you need to POST content to the url “/send_feed_item”. If you remember in my URL map, I have setup this url to append content to my feed. So a simple ajax post should do the trick to post content, that’s what I do in my admin page.
$.post(
'http://nodejs.no-margin-for-errors.com/send_feed_item',
json,
function(){
// Done!
}
);
The sources
All the sources are available on github, feel free to fork them and play with it yourself.
The possibilities
Let’s just say you watch a live conference on ustream.tv and the speaker mention some website, with node.js he could be able to send you to this website in real time as long as you are connected to his server or you could be watching live news on a website and they mention traffic, you could then be presented a Google traffic map live as they talk about it on the stream.
The possibilites are endless, this post covers only the basics, I’ll let your mind do the rest
Douglas Crockford — Crockford on JavaScript
July 23rd 2010
It’s friday, time to relax (and learn!). Here’s a really cool link, it’s a tiny bit old but it’s still totally worth it if you’ve never heard of it.
It’s a talk Douglas Crockford gave back in january about javascript, it’s past, present and future. It’s divided in five chapters. This is a very interesting talk, it’s one thing to know the language but it’s another to know where it’s from and where it’s going.
So sit back, crank up the volume and enjoy: Douglas Crockford — Crockford on JavaScript
3D wall effect using only javascript + CSS3
July 13th 2010
I recently wanted to test if I was able to give a 3D aspect to wall as a proof of concept, so I fired up textmate, started coding and ended up with this. I only used JavaScript and CSS(3). I also need to point out that this demo only work in Safari as I used a proprietary attribute “-webkit-perspective”.
First things first
Check out the following video to have an idea how it should look in your Safari browser. Check out the project page to test it out by yourself: http://no-margin-for-errors.com/demos/3d-wall/
You can also check out this other version, featuring more objects: http://no-margin-for-errors.com/demos/3d-wall-products/
The basics
The way I laid down the HTML is fairly simple, I have a container and inside of it, I have an unordered list. The markup looks something like the following (tweaked for readability)
<div class="wall">
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
</div>
The CSS
The CSS is also quite simple. There’s one very important property that needs to be applied to the container in order to be able to have the 3D effect in Safari or else the wall would look flat as it does in the other browsers. That property is the “-webkit-perspective” property. You can read more about it on the official Apple Safari developer documentation. After that, all I need to do is to rotate the unordered list (ul) on the “y” axis depending on the direction the user is sliding. That’s done using the “-webkit-transform” property.
The JavaScript
If you take a look at the JavaScript, you’ll see that it’s fairly simple. The only really important thing you need to do is to calculate the amount of degrees you which to rotate the list depending on the velocity of the drag. All of the angles calculations are done in the “perspective” function.
function perspective(){
clearInterval(wall_interval);
// Set an interval for the anim.
wall_interval = setInterval(function(){
if(wall_direction == 0){ // User stopped dragging
if(wall_angle > 0 || wall_angle < 0 ){ // Bring it to neutral state
wall_angle = wall_angle/1.1;
$('ul').css('-webkit-transform','rotateY('+(wall_angle*-1)+'deg)');
}else{ // Once neutral, cancel the interval
clearInterval(wall_interval);
}
}else{
wall_target_angle = wall_speed * wall_max_angle / wall_max_speed; // Calculate the angle based on velocity
if(wall_direction > 0 && wall_angle > wall_target_angle) { // Give the angle depending on the scroll direction
wall_angle--;
}else if(wall_direction < 0 && wall_angle < wall_target_angle){
wall_angle++;
}
$('ul').css('-webkit-transform','rotateY('+(wall_angle*-1)+'deg)'); // Apply it
}
},20);
}
Bottom line
The proof of concept worked! It can be done today, just not widely supported. I was also quite impressed at how fast I’ve been able to build it, the rough has been done in about 2 hours, the rest of the time was spent tweaking the animations/styling the page. I didn’t document the code (I did comment it tho), feel free to take it and re-use bits of it.
This project sparked an idea?
Feel free to buy me a beer, or a coffee, or candies, or a car!
JavaScript tip of the day: Extending a String Across Multiple Lines
June 17th 2010
I’m working on a project where I need to inject qui a bit of HTML. The examples will feature jQuery but it works with any library as it is simply string handling in javascript.
So the problem we face is that a string of content on a single line is hard to read. Something like that:
$(element).append('<div class="content"><div class="left"></div><div class="right"></div></div>');
It’s really not easy to maintain as you have to figure out where in the HTML structure you want to add new elements.
So here’s the tip
To keep the HTML cleanly formatted simply add a backslash after every line. This way you escape the new line feed and the javascript thinks everything is on a single line. Here’s an example:
$(element).append(' \
<div class="content"> \
<div class="left"> \
</div> \
<div class="right"> \
</div> \
</div> \
');
It’s a very nice way to keep the HTML structured to make sure the code is easily maintainable.
Hope you liked it
prettyLoader 1.0.1
April 23rd 2010
Tiny new version I’ve just released. Basically it consists of 3 things:
- Bind events only when the loader is showed
- Fixed loader position when users scroll
- Added error control on loader path and alerts you in the event the loader image is inaccessible.
It is a suggested update but not critic.
Head over to the project page for more details.
Unvealing prettyLoader, a solution aimed to unify ajax loaders.
April 9th 2010
prettyLoader is a small (less than 4kb uncompressed) jQuery plugin that aim at making your life easier regarding ajax loader display.
You know, when you do an ajax call and you never quite know where to position your loader. prettyLoader takes care of that for you, by default, prettyLoader will “hook” to the jQuery ajax function and display a nice spinning circle next to the mouse cursor and hide it once the ajax call is complete, neat no?
You don’t even have to bother calling any additional javascript, prettyLoader takes care of that for you.
Check out the project page for demos and more details.
Book Review: jQuery 1.4 Reference Guide
April 8th 2010
Here’s my first book review ever, the first of, I hope, many more!
First of all I must say that I’ve been quite late and lazy on getting around all the new feature of jQuery 1.4+. Sure I was all excited to hear about the new stuff, but didn’t really into it deeper than the method names. I must say this book arrived in time for me as it allowed me to get deeper understanding of all the new methods.
What it is
Well…it’s a reference guide. It’s a book containing all the jQuery methods of version 1.4, see it as the paper version of the jQuery documentation. It contains all the methods, I didn’t notice any missing.
It also dissect all of them by explaining their purpose, the parameters they accepts, what they return or what they do. Every method is also completed by a nice working example so you can get an idea of what it look like used in a real project.
What it is not
It is NOT a book for someone who thinks it’ll contain tutorials and example of small working scripts. All it does is describe all the methods, gives you example on how to use them and it ends there.
There’s at the beginning of the book a dissection of a “typical” jQuery script explaining how everything ties together. It’s well explained and well presented but it’s not significant enough for someone to consider the buying the book upon that single chapter. There are other books that do a far better job at dissecting and giving you practical example.
Well who is it for then?
Well, I’d say this book is aimed at intermediate/advanced jQuery developer. It’s a book for someone who wants to know all the possibilities jQuery offers you. As I said before, this book cover all the method, it won’t tell you: “You want to call something upon every ajax calls you make in your application, well here’s how”, instead it’ll explain the .ajaxStart() method and it’ll be your job to figure out how to use it and when to use it.
That’s specifically why I think it’s aimed more toward intermediate/advanced developers, those who need a “paper jQuery API bible” more than a beginner that needs to be taken by hand and explained all the possibilites. It’s your job to figure out the possibilites based on what you’ll find in the book.
Would I recommend it?
Depending on your skill level, I think it’s a nice addition to the jQuery documentation found online. I personally went through it during transit while I had no access to a computer and it allowed me to discover methods I wouldn’t have noticed by browsing the jQuery doc.
Head over here if you’re interested in buying it: https://www.packtpub.com/jquery-1-4-reference-guide/book
prettyPhoto 3.0: Beta
March 15th 2010
Here it is! The beta version of prettyPhoto 3.0. Why beta? Because there are several big changes in this version and before making it official, I really want it to be working properly. I tested the usual stuff myself, but I really want to throw it out to the community so you guys can test it.
Summary of changes
- Ability to initialize multiple prettyPhoto with different settings
- When opening a gallery in prettyPhoto an inline gallery is presented over the photo. See post thumbnail.
- Slideshow! See settings in jquery.prettyPhoto.js
- Changed defaut theme, “facebook” theme is now default.
- Changed the default speed to fast, feels snappier now.
- Code optimization, removed about 70 lines of crap.
Download
So you want to test it? You can find the demo page here: http://no-margin-for-errors.com/demos/prettyphoto_3.0/
I suggest you test it on your website, you can find a zip file here: http://no-margin-for-errors.com/demos/prettyphoto_3.0/prettyPhoto_3.0b.zip
Please note that since it’s a beta, you should retest everything on your own to make sure nothing breaks.
Bug reports
Please report any bug in that thread in the forums. I’ll do m y best to get them squashed to release that update as quickly as possible.
Thanks!
Mobile Web Apps: The End of App Stores?
January 28th 2010
Earlier this week Google released Google Voice as a web application. It’s a toned down version of the application that originally got submitted to the App Store but stirred controversy.
If you never heard of it before, the application got pulled down from the App Store for “unknown” reasons, Google complained to the FCC, then Apple said they were investigating the app. Someone somewhere obviously doesn’t want that app on the iPhone.
What they did this week is a straight hit in Apple’s face,. They modified their original App to be available as a web app, so unless Apple block access to the Google Voice website, there’s really nothing they can do about it and that’s a good thing.
Mobile Browsers are really powerful.
Mobile Safari is part of why Google has been able to release Voice as a web app. This browser really is quite powerful, it supports advanced HTML5, CSS3 and the JavaScript performance is impressive.
This got me thinking about the relevance of developing an App for the App Store. It’s true that the browser can’t access some core features like the camera or the gps, but some apps could actually be quite easily converted to a browser based equivalent. Just think about website specific apps that really are only RSS readers (Engadget,TUAW,CyberPresse), notes apps, even Instapaper could be converted using Safari client-side database.
Visibility
It’s true the App Store can potentially give you a lot of visibility, but the truth is that with over 140 000 apps yours can easily be far down the list. As if you publish it as a web app you can actually promote it not only for the iPhone but for many more platforms as it is browser based.
Open is epic win
Developing a web app aimed at the iPhone makes a lot of sense, you don’t have to go through the approval process when you launch or when you want to update your app. Your market could also be a lot broader as the app could be easily adapted for Android and Pre, much easier than re-coding the equivalent in their native language.
You can even add web pages to your home screen on the iPhone so it feels more like an app from the App store.
Cost $$$
Last time I checked there were not many people in my area developing for the iPhone, while there were plenty of web developer. It would be a lot easier to maintain and to find support in the event you lose one of your programmer. And as with everything, if demand is up, prices will follow so an Objective C programmer ain’t cheap.
Bottom line
If I had to develop and app for the iPhone today, I’d strongly consider the web app avenue unless the app rely on core features that are only available in the iPhone SDK.
What’s your view?

