Archive for the 'Prototype' Category

Django Facebook 2.0 – Integrating Facebook

It’s been a year since Facebook changed the web with the open graph API and their like button. Unfortunately Facebook didn’t have much developer love for the python/django platform. Django Facebook aims to make it easy to build facebook apps and integrate facebook with your website.

Key functionality

One of the strong points of Django Facebook is the ability to register users using Facebook. It ports all of Facebook’s user data to the Django user and profile models. This allows you to have a secure register/connect/login flow using Facebook, greatly reducing the barriers to start using your application. Below an example of me registering for Fashiolista using the Facebook register flow.

Me on Facebook

Me on Fashiolista

In this blog post I will explain how to get started implementing a Facebook connect flow. Django Facebook can however do quite a bit more, as you can see in the feature list below. Development over at the github repo is very active. I strongly appreciate help on improving the functionality so please fork and contribute.

Features

  • Register users using the Facebook open graph API
    • Full profile data birthday, gender, website, about me, username, email and picture
    • Support for mobile authentication
    • Fallback to registration form for entering additional data when required
  • Build Facebook Canvas applications
  • Mobile registration using Facebook
  • Execute Facebook FQL queries
  • Upload pictures to Facebook
  • Find your Facebook friends

Getting Started

Now let’s get started with building a Facebook login/connect/register flow. This post will guide you through it step by step.

Prerequisites

Create a Facebook app

Have django registration installed (other registration systems will require some small code changes)

pip install django_facebook :)

A.) Settings and more

Define these settings in your settings file.
FACEBOOK_API_KEY
FACEBOOK_APP_ID
FACEBOOK_APP_SECRET

add django facebook to your installed apps
‘django_facebook’,
add this line to your url config
(r’^facebook/’, include(‘django_facebook.urls’)),
add this line to your context processors
‘django_facebook.context_processors.facebook’,
add this to your AUTHENTICATION_BACKENDS
‘django_facebook.auth_backends.FacebookBackend’,

B.) Adjust your user Profile model

Secondly we need to be able to store the Facebook data on your user profile.
The easiest way to do this is to add the abstract model in django_facebook/models.py called FacebookProfileModel to your profile model.
After your profile is ready to store Facebook data you should have a working example at /facebook/connect/.
Let me know in the comments if something went wrong up to this point :)

C.) Design and integration

You can style the facebook form and button anyway you see fit. Over at Fashiolista we added a nice facepile for example. The basic markup is located in the example file connect.html.
We use the facebook javascript SDK for a smooth user integration. You can load the facebook JS like this:

<script src="{{ MEDIA_URL }}js/original/facebook.js" type="text/javascript"></script>
<script>
facebookAppId = '{{ FACEBOOK_APP_ID }}';
function facebookJSLoaded(){
FB.init({appId: facebookAppId, status: false, cookie: true, xfbml: true});
}
window.fbAsyncInit = facebookJSLoaded;
F = new facebookClass(facebookAppId);
F.load();
</script>

Subsequently implement a form which calls Facebook via javascript. Note that you can control which page to go to after connect using the next input field.

<form action="{% url facebook_connect %}?facebook_login=1" method="post">
<a href="javascript:void(0);" style="font-size: 20px;" onclick="F.connect(this.parentNode);">Register, login or connect with facebook</a>
<input type="hidden" value="{{ request.path }}" name="next" />
</form>
<div id="fb-root"></div>

That was all, you should now have a working registration flow using Facebook. Let me know in the comments if you encounter any difficulties.
If you want to go one step further and understand the facebook API, you can find the Facebook documentation here.
Django Facebook received tons of improvements from the python community. I’m certainly missing a few authors, but I would like to thank a few specifically:

Many thanks to (amongst many others)

More posts coming up

  • Building a facebook canvas app using Django Facebook
  • Find and invite friends using Django Facebook

We’re hiring!

Do you also see the beauty in clean code? Are you experienced with high scalability web apps? Currently we’re looking for additional talent over at our Amsterdam office. Feel free to drop me a line at my personal email for more information: thierryschellenbach[at]gmail.com

Css & Django & Events & Facebook & Fashiolista & Prototype & Python & Web Development tschellenbach 23 Jun 2011 70 Comments

YTM launch!!

No more beta for YouTellMe.nl
The website which is taking over the Dutch product comparison market is officially going out of beta @ 8 o clock.
Party in Amsterdam, Keizersgracht 182 :) Festivities starting right now!

13342_350348980430_784785430_9966158_5558110_n

Things are going well, looking very forward to international launch.
We’ve changed a lot since the first reviews!

13342_350352790430_784785430_9966172_7726367_n

Beter pictures coming after the event :P

PS. Thanks to Python and Django, for enabling us to beat the competition :)

PSS. Next2News, eduhub, come and join :)

Apache & Business & Css & Django & Dutch & Events & Javascript & PHP & Prototype & Python & Symfony & Web Development & YouTellMe tschellenbach 11 Dec 2009 150 Comments

Javascript optimization – high performance JS apps

The most common use cases of Javascript require no optimization at all. However when you go about building substantial applications in javascript you will hit some walls rather rapidly. Fortunately the code you are currently writing can probably be accelerated substantially.

Step 0: Analyzing performance

Prior to attempting any tweaks, be sure to get firebug and use their console.profile() and console.profileEnd(). Test results will vary substantially during subsequent tests, but they serve their purpose for finding the bottlenecks.

Step 1: Remove Double Dollar $$ and event binding

There are many small performance differences, but several things are likely to really kill performance. One of the most nasty ones is using prototype’s double dollar $$ function (or the similar Element.select). You can often avoid using the double dollar function. For example the use case of attaching events to all ‘report this’ buttons on your site. The simple (and often good enough) approach would be to use the following code:

$$('.report_this').each(function(report_button) {
   var id = report_button.id.split('_')[1];
   report_button.observe('click', this.respondToReportButton.bind(this, id);
});

Four things are slowing this code down: 1. the usage of the $$ function, 2. the usage of each instead of a native looping construct, 3. the retrieving of the id from the id string, 4. the repeated binding of functions.

There are several possible remedies against the above code:

  1. Give all report_this buttons a unique id (say for instance that you have 15 or less in a list)
  2. Pre generate a list of ids using your server side language of choice and pass it to javascript
  3. Manually traverse the DOM; $(‘container’).childNodes can do wonders
  4. Bind once to a common parent element
  5. Find items by name instead of class
  6. Forget about all the initializing and fall back to old school onclick=”classinstance.respondToReportButton()”

This last option sort of goes against many webdevelopment principles, but is often a very pragmatic choice. Joseph Smarr from Plaxo holds a similar opinion on the topic.

A better implementation using technique 1 would be:

this.respondToReportButtonBound = this.respondToReportButton.bind(this);
for(x=1;x<16;x++) {
   button = $('report_button'+x);
   if(!button) break;
   button.observe('click', this.respondToReportButtonBound);
}

In practice I’ve experienced speed improvements of over 40 times using this technique. Firstly the repondTo function is bound only once. Secondly the $$ function is no longer needed. Thirdly the each implementation has been replaced by a blazingly fast for loop. Fourthly the id is no longer extracted. A better practice is to extract it when respondToReportButton is actually executed. This last point actually brings us to the next main item.

Step 2: Be Lazy!

The trick here is to actually put in a bit of effort to make your code lazy. Don’t do anything until it is needed. (With the one, but large exception if doing so would hurt the user experience.) If some items are currently not visible to the user simply don’t bind events to them. If you need to extract id’s don’t do so until someone actually clicks on the item in question. Furthermore also make it lazy in the regular sense of the word. If your code only need to change one item, figure out which one it is and don’t loop about changing all just in case. This point is different for every application, but it can achieve great speed gains for a creative programmer!

Step 3: Stop using prototype functions if you don’t need them

Often you do not really need (as in that it barely saves you development time) some of the functionality of prototype. When comparing the speed of element.innerHTML = ‘hello world’ versus element.update(‘hello world’) the differences are substantial (60 times with large chunks of html). Also the each iterator is often not needed and can be replace by a simple for loop with checks on nodeType and tagName. The same goes for the templating system. These tools barely save you time, but really hurt performance. I am a big fan of the prototype library and for most use cases these nice helpers are great. When you really need speed, be sure to refrain from using them though.

Step 4: Lower level optimizations

When you are done implementing the really important optimizations there are quite some lower level optimizations which will speed up your code.

Two generally great resources on the topic are:

  1. Joseph Smarr (Plaxo)
  2. Opera Dev

The missing performance data

One item affecting the performance of javascript interface elements is the speed by which the browsers redraws the page. Unfortunately I have barely found any documentation on how browsers determine what to redraw and what affects redraw speed. One certainty is the negative influence of transparent images on redraw speed, but other than that little seems to be known. Furthermore most browsers won’t redraw the page until your javascript function returns. This can make your interface elements feel very unresponsive. A solution to this problem is to use the setTimeout functionality.

Message for Dutch Programmers

YouTellMe is an innovative startup located in the center of Rotterdam. Talented programmers are always welcome. Have a look at the job page to get an impression of the job openings (We develop using Python/Django).

Javascript & Prototype & Web Development tschellenbach 18 May 2008 23 Comments

Have a Cookie

Here a nice little cookie wrapper. It’s mainly based on the Quirksmode code with some nice Prototype style.

Have a look:

var cookieJar = Class.create();
cookieJar.prototype = {
initialize: function() {},
write: function(name,value,days) {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else var expires = '';
document.cookie = name + '=' + value + expires + '; path=/';
},
writeJSON: function(name,value,days) {
var JSONvalue = $H(value).toJSON();
this.write(name,JSONvalue,days);
},
read: function(name) {
var nameEQ = name + '=';
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return false;
},
readJSON: function(name) {
var value = this.read(name) || '{}';
value = value.evalJSON();
return value;
},
erase: function (name) {
this.create(name,"",-1);
}
};
cJar = new cookieJar();

Javascript & Prototype & Web Development tschellenbach 07 Feb 2008 14 Comments

Updated cross site ajax plugin for Prototype

The first post on my cross site ajax plugin for Prototype (1.5.0) was received with great enthusiasm. It was very nice to see my own work on the great Ajaxian website and the delicious front page. Since that post the quality of the plug-in has improved quite a bit. Especially cross browser compatibility improved. I made a test page to evaluate this; have a look to test your own browser. Furthermore some 14 screen shots show that the compatibility is good.

Here the new version: Download the cross site ajax plugin.

The syntax remains exactly the same:

new Ajax.Request(url, {
method: 'GET',
crossSite: true,
onLoading: function() {
//things to do at the start
},
onSuccess: function(transport) {
//things to do when everything goes well
},
onFailure: function(transport) {
//things to do when we encounter a failure
}
});

Cross Browser Compatibility

First of all thanks to Kris Kowal and Gary Gurevich for spotting the problems with Safari. Prior to the changes the plugin used three different methods to detect the loading of the script element. For Safari and Konqueror a sequential script technique was used. This technique has now been replaced with the polling technique, like in COWS. So the following three solutions are used.

1.) For IE it used its proprietary onreadystatechange event
2.) For Safari and Konqueror it uses the polling technique
3.) For Firefox and Opera it uses the standard onload event

Timing problems

In addition to the cross browser compatibility problems I noticed another complication. In Prototype 1.5.0 the onLoading, onSuccess etc., are generally fired by running the onreadystatechange function. However this is not the case for a transport status below 2. Actually the onLoading event is triggered by a delayed function after the open command. I didn’t realize this initially. However if you have a script which loads rather fast it will result in onSuccess executing before onLoading. This issue was fixed by calling respondToReadyState directly.

Points of Improvement

Firstly the current implementation detects browsers, not capabilities. This might create problems with future or buggy versions of browsers.
Secondly the usage of a global variable to indicate transport status makes it impossible to handle simultaneous requests nicely.
Thirdly the script currently does not clean up the script nodes.

If these points turn out to be troublesome, I will use a modified version of COWS for the transport aspects.

Conclusion

The new version of this plug-in is widely cross browser compatible. Currently it is suitable for a large variety of applications. It is however not yet ready to deal with simultaneous requests.

Javascript & Prototype & Web Development tschellenbach 07 Nov 2007 2 Comments

Introducing a cross site ajax plugin for Prototype

Update: there have been some improvements to this plugin. Have a look at this post regarding the update. Thanks for the feedback!

After some days of hard labor, I finished my cross site Ajax plugin for the prototype framework 1.5.0. (Download Plugin Here) While working on a new product of mine I realized I needed cross site Ajax, which is not supported in the Prototype framework.

During cross site Ajax requests the standard XmlHttpRequest approach breaks down. The problem is that XmlHttpRequest is bounded by the same site policy. Fortunately the script tag has the freedom to do as it pleases.

Some other libraries such as dojo and jquery do support the script method for doing Ajax. There is even a project on source-forge called COWS, which is dedicated to this purpose. This plugin is an adaptation of the jquery plugin, but modeled to look like an XmlHttpRequest. The credits of the original code go to Ralf S. Engelschall , which amazingly achieved to make it nicely cross browser compatible. This plugin supports FF, IE, Safari, Opera and Konqueror, but has only been properly tested in FF and IE.

Prototype’s structured way of doing Ajax was my main reason to choose the prototype framework. Furthermore it is also included in the great Symfony framework. In Prototype Ajax requests are written like this:

new Ajax.Request('myurl', {
method: 'GET',
crossSite: true,
parameters: Form.serialize(obj),
onLoading: function() {
//things to do at the start
},
onSuccess: function(transport) {
//things to do when everything goes well
},
onFailure: function(transport) {
//things to do when we encounter a failure
}
});

The cross site plugin simply allows you to do Ajax cross site, by specifying crossSite: true (line 3 of the above example). I will now cover some technical aspects of the plugin, but if you just want to start using it simply skip to the plug and play instructions below.

How it works – Technical Aspects

This plugin uses the dynamic script tag technique. This basically means that we insert new <script> tags into the Dom. Since this script tag is not bound to the same site you can send and receive data in the Ajax way. In its most basic form the javascript would be like this:

this.node = document.createElement('SCRIPT');
this.node.type = 'text/javascript';
this.node.src = 'http://www.serversite.com';
var head = document.getElementsByTagName('HEAD')[0];
head.appendChild(this.node);

In order to make it very easy to use with Prototype, or any other library for that matter, I decided to mimic the functions of the XmlHttpRequest. This is easily achieved by implementing the functions open, send and onreadystatechange. Furthermore I needed to specify the variables readyState and status in order to support prototype’s onLoad, onSucces and onFailure.

Detecting the loading of a script element is not that easy. Browsers such as Safari and Konqueror simply give no indication of this at all. One common solution to dealing with this is to use an interval and perform a check. The work at TrainOfThoughts however takes the beautiful approach of inserting a helper script. This exploits the fact that the dynamically added scripts are executed in sequence. This approach makes the plugin nicely cross browser compatible.

Detecting failure is rather cumbersome for the script technique. As far as I know there is no way to read the headers on the incoming file, or to inspect its contents through javascript. This leaves us with the rather blunt approach of setting a global variable using the server output. It works, but it could be prettier.

Plug and Play implementation instructions

Firstly you need to load the plugin javascript file: download cross site ajax plugin for the prototype framework 1.5.0.

Secondly you need to change your regular prototype Ajax request, by ensuring that you instruct it to use the crossSite and GET methods, as such (observe line 2 and 3):

new Ajax.Request(baseurl+'/comment/giveratingjs', {
method: 'GET',
crossSite: true,
parameters: Form.serialize(obj),
onLoading: function() {
//things to do at the start
},
onSuccess: function(transport) {
//things to do when everything goes well
},
onFailure: function(transport) {
//things to do when we encounter a failure
}
});

Thirdly you might need to rewrite some of your javascript code to accommodate the instant execution of the scripts.

Fourthly, if you want to use onFailure for any of your scripts you need to send some javascript instructions back from the server. You need to do this both on success and on failure (since a global variable is used). This is the javascript variable you need to set:

'var _xsajax$transport_status = 200;' Or
'var _xsajax$transport_status = 404;'

Symfony specific tips

Symfony detects if it receives a XmlHttpRequest and automatically turns off your debug bar and layout. Unfortunately it is not so kind to the script technique. So in your action you need to do this manually:

sfConfig::set('sf_web_debug', false);
$this->setLayout(false);

Furthermore your validation files by default only look at POST variables (this one tricked me). To instruct them to look at both, simply mention

methods: [post, get]

at the top of your validation.yml

Since you will probably want to send html to the browser, I would suggest you put this little function (found in the symfony escape helpers) in your toolbox.

public static function esc_js($value) {
return addcslashes($value, "\0..\37\\'\"\177..\377\/");
}

Conclusion

The dynamic script tag technique opens up a wide range of possibilities. Personally I am very glad with the results and would like to thank Ralf S. Engelschall for his superb cbc work. Unfortunately I didn’t include an example this time. You will have to wait for the products’ launch:). Comments and improvements are always appreciated. Enjoy your cross site scripting!

Javascript & PHP & Prototype & Symfony & Web Development tschellenbach 25 Oct 2007 240 Comments