Link

Why Mobile Web Apps Are Slow

Why Mobile Web Apps Are Slow

Okay, but how does JS performance compare to native performance exactly?
Custom FBML Dialogs in Facebook Apps

Custom FBML Dialogs in Facebook Apps

There are several examples around on doing custom Facebook dialogs, some which are satisfactory and some which are not. Here is some code that I use to create custom FB dialogs that I can position, color, style at will.

First, let’s look at the FBJS function to invoke a custom dialog. In this case, I have created a dialog that accepts Yes / No answers. By convention, I assume that I will define a dialog somewhere on my page named “question_dialog1”.

// Custom yes / no dialog that we can position
function showYesNoDialog(id, title, content, confirm, cancel) {
document.getElementById(id).setStyle("display", "inline");
if (confirm) {
document.getElementById('yes_button1').removeEventListener('click', confirm, false);
document.getElementById('yes_button1').addEventListener('click', confirm, false);
}
if (cancel) {
document.getElementById('no_button1').removeEventListener('click', cancel, false);
document.getElementById('no_button1').addEventListener('click', cancel, false);
}
document.getElementById("question_title1").setTextValue(title);
document.getElementById("question_content1").setTextValue(content);
}

The first thing I do is display my question dialog, which is initially styled {display: none;}.

Next, I attach a couple of click events – if present – to two buttons, yes and no, for confirmation and cancel (by convention, I use yes_button1 and no_button1, but you can certainly parameterize this or better yet encapsulate in a class).

Finally, I set Title Text and Content Text using the setTextValue method.

A typical call to this dialog might look like the following (I use the built-in FBJS Ajax object):

var yes = function() {
var ajax = new Ajax();
ajax.responseType = Ajax.FBML;
ajax.ondone = function(data) {
document.getElementById("delete_dialog1").setStyle("display", "none");
document.setLocation("http://apps.facebook.com/SomeApp/ThisPage.php");
}
ajax.onerror = function() {document.getElementById("delete_dialog1").setStyle("display", "none");}
newShowDialog("delete_dialog1");
ajax.post('http://apps.facebook.com/SomeApp/performDelete.php?fbid=' + <? echo $user; ?>;
}

showYesNoDialog("question_dialog1", "Delete Record?", "Delete \"" + argRecordDescription + "\"?", yes);

The actual FBML for the question_dialog1 looks something like the code below. You can style this anyway you want; I usually try to get my dialogs to look like the styling of the application to which the dialog belongs, but do whatever floats your boat here.

<div id="question_dialog1" style='display: none; position: absolute; top: 300px; left: 150px;'>
<table>
<tr>

<!-- Transparent border around dialog, like FB built in dialogs-->

<td style="background-image:url('http://app.facebook.com/SomeApp/Images/pop_dialog_border.png');">

<div style='border: 2px solid #8ec73c; background: white; font-size: 18pt; margin: 10px;'>
<div id='question_title1' style='background: white; padding: 2px; color: white; background: #8ec73c; font-weight: bold; font-size: small;'>Title Here...</div>
<div id='question_content1' style='font-weight: bold; font-size: 12pt; padding: 10px 30px 10px 30px; border-bottom: 1px solid #8ec73c;'>Dialog content will go here...</div>

<div style='background: white; text-align: right; padding: 10px; font-size: small; height: 20px;'>

<input id='yes_button1' type='button' value='Yes' onclick='document.getElementById("question_dialog1").setStyle("display", "none");' style='background: #8ec73c; color: white; width: 40px;' />

<input id='no_button1' type='button' value='No' onclick='document.getElementById("question_dialog1").setStyle("display", "none");' style='background: #8ec73c; color: white; width: 30px;' /></diV>
</div>

</td></tr>
</table>
</div>

Finally, a note to code nit-pickers: This example is meant to be illustrative and not a comprehensive way on how best to do Facebook dialogs or write FBJS.

Another FBJS Gem that Caused Me No Little Grief

Another FBJS Gem that Caused Me No Little Grief

While the Facebook Developer Documentation has gotten somewhat better, there are places where it is out and out – well – wrong.

For example, then using the addEventListener function connect events to an object, the Facebook documentation says that the third parameter for capture is not used. WRONG.

How do I know this? Well, because I had need to attach both a blur and a change event to an inline edit control… and when the 3rd parameter was left missing, the blur event never fired. Adding false to the third parameter allowed both events to fire (see code below).

if (document.getElementById('inlineEdit')) {document.getElementById('inlineEdit').addEventListener('blur', blurInlineEdit, false);}

if (document.getElementById('inlineEdit')) {document.getElementById('inlineEdit').addEventListener('change', changeInlineEdit, false);}

One of the big challenges in writing Javascript (er, FBJS) for Facebook Canvas Pages is seeing what gets broken by Facebook’s munging of Javascript. By and large, things hang together pretty well. Events, however, probably cause me more grief in debugging Facebook applications than any other area of development focus.

Positioning a dialog on a Facebook Canvas Page

Positioning a dialog on a Facebook Canvas Page

As promised (or threatened) here is a post on some little Facebook development insight gained through some trial, error, blood, sweat, and yes tears.

A problem I was having was accurately determining the x, y position of a given control for popping up informational dialogs. Sure, it was easy enough to use the getAbsoluteTop and getAbsoluteLeft calls to get the absolute positioning (supposed), but after playing around with these calls it became apparent that “absolute” didn’t mean “absolute” in the sense that most web / windows developers would understand. It really is a relative offset – but to what?

After perusing the FBJS docs, and finding no mention of a viewport (which is really what I was trying to determine the offset from), I took a total flier and thought – “well, if I could jet get the root element of my document, and find ITS x and y, I should be home free.

Bingo. That was the trick. Use document.getRootElement() to get the container element.

The code below demonstrates the technique.

var argCtl = document.getElementById(“myForm”);
var newTop = argCtl.getAbsoluteTop();
var newLeft = argCtl.getAbsoluteLeft();
var scrollW = argCtl.getScrollWidth();
var root = document.getRootElement();
var cTop = root.getAbsoluteTop();
var cLeft = root.getAbsoluteLeft();

document.getElementById(“confirm_dialog1”).setStyle(“top”, (newTop – cTop) + “px”);
document.getElementById(“confirm_dialog1”).setStyle(“left”, (newLeft – cLeft) + “px”);

First, grab a reference to an object on the page that you wish to position relative to (in this case, I am using a form named “myForm”). Get its x and y coordinates.

Next, get the container x and y by getting its reference (document.getRootElement()) and then its x and y values (getAbsoluteTop and getAbsoluteLeft).

Finally, to accurately position a dialog where an element exists, take the difference between the container and the element being positioned:

document.getElementById(“confirm_dialog1”).setStyle(“top”, (newTop – cTop) + “px”);
document.getElementById(“confirm_dialog1”).setStyle(“left”, (newLeft – cLeft) + “px”);

Voila. You’ve just positioned a dialog over an element.

In practice, you would want some arbitrary additional offset from the control so that you don’t hide it when you pop up / display your dialog. I’ll leave that as an exercise for the reader.